mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 07:05:41 +00:00 
			
		
		
		
	refactor(frontend): Do not request token in frontend (#9217)
* remove calls that reference tokens * remove call to token endpoint * ensure CSRFToken is always send * bump axios * lower axios * reset axios change * bump reslution down
This commit is contained in:
		@@ -2,7 +2,6 @@ import { QueryClient } from '@tanstack/react-query';
 | 
				
			|||||||
import axios from 'axios';
 | 
					import axios from 'axios';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useLocalState } from './states/LocalState';
 | 
					import { useLocalState } from './states/LocalState';
 | 
				
			||||||
import { useUserState } from './states/UserState';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Global API instance
 | 
					// Global API instance
 | 
				
			||||||
export const api = axios.create({});
 | 
					export const api = axios.create({});
 | 
				
			||||||
@@ -12,7 +11,6 @@ export const api = axios.create({});
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export function setApiDefaults() {
 | 
					export function setApiDefaults() {
 | 
				
			||||||
  const { host } = useLocalState.getState();
 | 
					  const { host } = useLocalState.getState();
 | 
				
			||||||
  const { token } = useUserState.getState();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  api.defaults.baseURL = host;
 | 
					  api.defaults.baseURL = host;
 | 
				
			||||||
  api.defaults.timeout = 5000;
 | 
					  api.defaults.timeout = 5000;
 | 
				
			||||||
@@ -22,11 +20,10 @@ export function setApiDefaults() {
 | 
				
			|||||||
  api.defaults.xsrfCookieName = 'csrftoken';
 | 
					  api.defaults.xsrfCookieName = 'csrftoken';
 | 
				
			||||||
  api.defaults.xsrfHeaderName = 'X-CSRFToken';
 | 
					  api.defaults.xsrfHeaderName = 'X-CSRFToken';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (token) {
 | 
					  axios.defaults.withCredentials = true;
 | 
				
			||||||
    api.defaults.headers.Authorization = `Token ${token}`;
 | 
					  axios.defaults.withXSRFToken = true;
 | 
				
			||||||
  } else {
 | 
					  axios.defaults.xsrfHeaderName = 'X-CSRFToken';
 | 
				
			||||||
    delete api.defaults.headers['Authorization'];
 | 
					  axios.defaults.xsrfCookieName = 'csrftoken';
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const queryClient = new QueryClient({
 | 
					export const queryClient = new QueryClient({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,7 +66,8 @@ export const doBasicLogin = async (
 | 
				
			|||||||
  navigate: NavigateFunction
 | 
					  navigate: NavigateFunction
 | 
				
			||||||
) => {
 | 
					) => {
 | 
				
			||||||
  const { host } = useLocalState.getState();
 | 
					  const { host } = useLocalState.getState();
 | 
				
			||||||
  const { clearUserState, setToken, fetchUserState } = useUserState.getState();
 | 
					  const { clearUserState, setAuthenticated, fetchUserState } =
 | 
				
			||||||
 | 
					    useUserState.getState();
 | 
				
			||||||
  const { setAuthContext } = useServerApiState.getState();
 | 
					  const { setAuthContext } = useServerApiState.getState();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (username.length == 0 || password.length == 0) {
 | 
					  if (username.length == 0 || password.length == 0) {
 | 
				
			||||||
@@ -94,7 +95,7 @@ export const doBasicLogin = async (
 | 
				
			|||||||
    .then((response) => {
 | 
					    .then((response) => {
 | 
				
			||||||
      setAuthContext(response.data?.data);
 | 
					      setAuthContext(response.data?.data);
 | 
				
			||||||
      if (response.status == 200 && response.data?.meta?.is_authenticated) {
 | 
					      if (response.status == 200 && response.data?.meta?.is_authenticated) {
 | 
				
			||||||
        setToken(response.data.meta.access_token);
 | 
					        setAuthenticated(true);
 | 
				
			||||||
        loginDone = true;
 | 
					        loginDone = true;
 | 
				
			||||||
        success = true;
 | 
					        success = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -217,7 +218,7 @@ function observeProfile() {
 | 
				
			|||||||
export async function ensureCsrf() {
 | 
					export async function ensureCsrf() {
 | 
				
			||||||
  const cookie = getCsrfCookie();
 | 
					  const cookie = getCsrfCookie();
 | 
				
			||||||
  if (cookie == undefined) {
 | 
					  if (cookie == undefined) {
 | 
				
			||||||
    await api.get(apiUrl(ApiEndpoints.user_token)).catch(() => {});
 | 
					    await api.get(apiUrl(ApiEndpoints.auth_session)).catch(() => {});
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -251,7 +252,7 @@ export function handleMfaLogin(
 | 
				
			|||||||
  values: { code: string },
 | 
					  values: { code: string },
 | 
				
			||||||
  setError: (message: string | undefined) => void
 | 
					  setError: (message: string | undefined) => void
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
  const { setToken, fetchUserState } = useUserState.getState();
 | 
					  const { setAuthenticated, fetchUserState } = useUserState.getState();
 | 
				
			||||||
  const { setAuthContext } = useServerApiState.getState();
 | 
					  const { setAuthContext } = useServerApiState.getState();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  authApi(apiUrl(ApiEndpoints.auth_login_2fa), undefined, 'post', {
 | 
					  authApi(apiUrl(ApiEndpoints.auth_login_2fa), undefined, 'post', {
 | 
				
			||||||
@@ -260,7 +261,7 @@ export function handleMfaLogin(
 | 
				
			|||||||
    .then((response) => {
 | 
					    .then((response) => {
 | 
				
			||||||
      setError(undefined);
 | 
					      setError(undefined);
 | 
				
			||||||
      setAuthContext(response.data?.data);
 | 
					      setAuthContext(response.data?.data);
 | 
				
			||||||
      setToken(response.data.meta.access_token);
 | 
					      setAuthenticated();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      fetchUserState().finally(() => {
 | 
					      fetchUserState().finally(() => {
 | 
				
			||||||
        observeProfile();
 | 
					        observeProfile();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,14 +10,13 @@ import type { UserProps } from './states';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export interface UserStateProps {
 | 
					export interface UserStateProps {
 | 
				
			||||||
  user: UserProps | undefined;
 | 
					  user: UserProps | undefined;
 | 
				
			||||||
  token: string | undefined;
 | 
					  is_authed: boolean;
 | 
				
			||||||
  userId: () => number | undefined;
 | 
					  userId: () => number | undefined;
 | 
				
			||||||
  username: () => string;
 | 
					  username: () => string;
 | 
				
			||||||
 | 
					  setAuthenticated: (authed?: boolean) => void;
 | 
				
			||||||
 | 
					  fetchUserToken: () => Promise<void>;
 | 
				
			||||||
  setUser: (newUser: UserProps | undefined) => void;
 | 
					  setUser: (newUser: UserProps | undefined) => void;
 | 
				
			||||||
  getUser: () => UserProps | undefined;
 | 
					  getUser: () => UserProps | undefined;
 | 
				
			||||||
  setToken: (newToken: string | undefined) => void;
 | 
					 | 
				
			||||||
  clearToken: () => void;
 | 
					 | 
				
			||||||
  fetchUserToken: () => void;
 | 
					 | 
				
			||||||
  fetchUserState: () => Promise<void>;
 | 
					  fetchUserState: () => Promise<void>;
 | 
				
			||||||
  clearUserState: () => void;
 | 
					  clearUserState: () => void;
 | 
				
			||||||
  checkUserRole: (role: UserRoles, permission: UserPermissions) => boolean;
 | 
					  checkUserRole: (role: UserRoles, permission: UserPermissions) => boolean;
 | 
				
			||||||
@@ -33,6 +32,7 @@ export interface UserStateProps {
 | 
				
			|||||||
  hasChangePermission: (model: ModelType) => boolean;
 | 
					  hasChangePermission: (model: ModelType) => boolean;
 | 
				
			||||||
  hasAddPermission: (model: ModelType) => boolean;
 | 
					  hasAddPermission: (model: ModelType) => boolean;
 | 
				
			||||||
  hasViewPermission: (model: ModelType) => boolean;
 | 
					  hasViewPermission: (model: ModelType) => boolean;
 | 
				
			||||||
 | 
					  isAuthed: () => boolean;
 | 
				
			||||||
  isLoggedIn: () => boolean;
 | 
					  isLoggedIn: () => boolean;
 | 
				
			||||||
  isStaff: () => boolean;
 | 
					  isStaff: () => boolean;
 | 
				
			||||||
  isSuperuser: () => boolean;
 | 
					  isSuperuser: () => boolean;
 | 
				
			||||||
@@ -43,13 +43,9 @@ export interface UserStateProps {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export const useUserState = create<UserStateProps>((set, get) => ({
 | 
					export const useUserState = create<UserStateProps>((set, get) => ({
 | 
				
			||||||
  user: undefined,
 | 
					  user: undefined,
 | 
				
			||||||
  token: undefined,
 | 
					  is_authed: false,
 | 
				
			||||||
  setToken: (newToken: string | undefined) => {
 | 
					  setAuthenticated: (authed = true) => {
 | 
				
			||||||
    set({ token: newToken });
 | 
					    set({ is_authed: authed });
 | 
				
			||||||
    setApiDefaults();
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  clearToken: () => {
 | 
					 | 
				
			||||||
    get().setToken(undefined);
 | 
					 | 
				
			||||||
    setApiDefaults();
 | 
					    setApiDefaults();
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  userId: () => {
 | 
					  userId: () => {
 | 
				
			||||||
@@ -68,8 +64,7 @@ export const useUserState = create<UserStateProps>((set, get) => ({
 | 
				
			|||||||
  setUser: (newUser: UserProps | undefined) => set({ user: newUser }),
 | 
					  setUser: (newUser: UserProps | undefined) => set({ user: newUser }),
 | 
				
			||||||
  getUser: () => get().user,
 | 
					  getUser: () => get().user,
 | 
				
			||||||
  clearUserState: () => {
 | 
					  clearUserState: () => {
 | 
				
			||||||
    get().setUser(undefined);
 | 
					    set({ user: undefined, is_authed: false });
 | 
				
			||||||
    get().setToken(undefined);
 | 
					 | 
				
			||||||
    clearCsrfCookie();
 | 
					    clearCsrfCookie();
 | 
				
			||||||
    setApiDefaults();
 | 
					    setApiDefaults();
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
@@ -79,30 +74,30 @@ export const useUserState = create<UserStateProps>((set, get) => ({
 | 
				
			|||||||
      !document.cookie.includes('csrftoken') &&
 | 
					      !document.cookie.includes('csrftoken') &&
 | 
				
			||||||
      !document.cookie.includes('sessionid')
 | 
					      !document.cookie.includes('sessionid')
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
      get().clearToken();
 | 
					      get().setAuthenticated(false);
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await api
 | 
					    await api
 | 
				
			||||||
      .get(apiUrl(ApiEndpoints.user_token))
 | 
					      .get(apiUrl(ApiEndpoints.auth_session))
 | 
				
			||||||
      .then((response) => {
 | 
					      .then((response) => {
 | 
				
			||||||
        if (response.status == 200 && response.data.token) {
 | 
					        if (response.status == 200 && response.data.meta.is_authenticated) {
 | 
				
			||||||
          get().setToken(response.data.token);
 | 
					          get().setAuthenticated(true);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          get().clearToken();
 | 
					          get().setAuthenticated(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      .catch(() => {
 | 
					      .catch(() => {
 | 
				
			||||||
        get().clearToken();
 | 
					        get().setAuthenticated(false);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  fetchUserState: async () => {
 | 
					  fetchUserState: async () => {
 | 
				
			||||||
    if (!get().token) {
 | 
					    if (!get().isAuthed()) {
 | 
				
			||||||
      await get().fetchUserToken();
 | 
					      await get().fetchUserToken();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If we still don't have a token, clear the user state and return
 | 
					    // If we still don't have a token, clear the user state and return
 | 
				
			||||||
    if (!get().token) {
 | 
					    if (!get().isAuthed()) {
 | 
				
			||||||
      get().clearUserState();
 | 
					      get().clearUserState();
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -161,8 +156,11 @@ export const useUserState = create<UserStateProps>((set, get) => ({
 | 
				
			|||||||
        get().clearUserState();
 | 
					        get().clearUserState();
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  isAuthed: () => {
 | 
				
			||||||
 | 
					    return get().is_authed;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  isLoggedIn: () => {
 | 
					  isLoggedIn: () => {
 | 
				
			||||||
    if (!get().token) {
 | 
					    if (!get().isAuthed()) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const user: UserProps = get().user as UserProps;
 | 
					    const user: UserProps = get().user as UserProps;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user