mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
User roles state (#5685)
* Update for useApiState - Rename to useUserState - Include role information * Adds state method for checking user roles
This commit is contained in:
parent
89faf8e59d
commit
149e5c3696
@ -11,12 +11,12 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import { doClassicLogout } from '../../functions/auth';
|
||||
import { InvenTreeStyle } from '../../globalStyle';
|
||||
import { useApiState } from '../../states/ApiState';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import { PlaceholderPill } from '../items/Placeholder';
|
||||
|
||||
export function MainMenu() {
|
||||
const { classes, theme } = InvenTreeStyle();
|
||||
const [username] = useApiState((state) => [state.user?.name]);
|
||||
const [username] = useUserState((state) => [state.user?.name]);
|
||||
return (
|
||||
<Menu width={260} position="bottom-end">
|
||||
<Menu.Target>
|
||||
|
@ -4,14 +4,10 @@ import { IconCheck } from '@tabler/icons-react';
|
||||
import axios from 'axios';
|
||||
|
||||
import { api } from '../App';
|
||||
import {
|
||||
ApiPaths,
|
||||
url,
|
||||
useApiState,
|
||||
useServerApiState
|
||||
} from '../states/ApiState';
|
||||
import { ApiPaths, url, useServerApiState } from '../states/ApiState';
|
||||
import { useLocalState } from '../states/LocalState';
|
||||
import { useSessionState } from '../states/SessionState';
|
||||
import { useUserState } from '../states/UserState';
|
||||
|
||||
export const doClassicLogin = async (username: string, password: string) => {
|
||||
const { host } = useLocalState.getState();
|
||||
@ -62,11 +58,11 @@ export const doSimpleLogin = async (email: string) => {
|
||||
|
||||
export const doTokenLogin = (token: string) => {
|
||||
const { setToken } = useSessionState.getState();
|
||||
const { fetchApiState } = useApiState.getState();
|
||||
const { fetchUserState } = useUserState.getState();
|
||||
const { fetchServerApiState } = useServerApiState.getState();
|
||||
|
||||
setToken(token);
|
||||
fetchApiState();
|
||||
fetchUserState();
|
||||
fetchServerApiState();
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
WidgetLayout
|
||||
} from '../../components/widgets/WidgetLayout';
|
||||
import { LoadingItem } from '../../functions/loading';
|
||||
import { useApiState } from '../../states/ApiState';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
|
||||
const vals: LayoutItemType[] = [
|
||||
{
|
||||
@ -51,7 +51,7 @@ const vals: LayoutItemType[] = [
|
||||
];
|
||||
|
||||
export default function Home() {
|
||||
const [username] = useApiState((state) => [state.user?.name]);
|
||||
const [username] = useUserState((state) => [state.user?.name]);
|
||||
return (
|
||||
<>
|
||||
<Title order={1}>
|
||||
|
@ -4,13 +4,16 @@ import { api } from '../App';
|
||||
import { emptyServerAPI } from '../defaults/defaults';
|
||||
import { ServerAPIProps, UserProps } from './states';
|
||||
|
||||
interface ApiStateProps {
|
||||
interface UserStateProps {
|
||||
user: UserProps | undefined;
|
||||
setUser: (newUser: UserProps) => void;
|
||||
fetchApiState: () => void;
|
||||
}
|
||||
|
||||
export const useApiState = create<ApiStateProps>((set, get) => ({
|
||||
/**
|
||||
* Global user information state, using Zustand manager
|
||||
*/
|
||||
export const useApiState = create<UserStateProps>((set, get) => ({
|
||||
user: undefined,
|
||||
setUser: (newUser: UserProps) => set({ user: newUser }),
|
||||
fetchApiState: async () => {
|
||||
@ -45,6 +48,7 @@ export const useServerApiState = create<ServerApiStateProps>((set, get) => ({
|
||||
|
||||
export enum ApiPaths {
|
||||
user_me = 'api-user-me',
|
||||
user_roles = 'api-user-roles',
|
||||
user_token = 'api-user-token',
|
||||
user_simple_login = 'api-user-simple-login',
|
||||
user_reset = 'api-user-reset',
|
||||
@ -64,6 +68,8 @@ export function url(path: ApiPaths, pk?: any): string {
|
||||
switch (path) {
|
||||
case ApiPaths.user_me:
|
||||
return 'user/me/';
|
||||
case ApiPaths.user_roles:
|
||||
return 'user/roles/';
|
||||
case ApiPaths.user_token:
|
||||
return 'user/token/';
|
||||
case ApiPaths.user_simple_login:
|
||||
|
59
src/frontend/src/states/UserState.tsx
Normal file
59
src/frontend/src/states/UserState.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
import { api } from '../App';
|
||||
import { ApiPaths, url } from './ApiState';
|
||||
import { UserProps } from './states';
|
||||
|
||||
interface UserStateProps {
|
||||
user: UserProps | undefined;
|
||||
setUser: (newUser: UserProps) => void;
|
||||
fetchUserState: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Global user information state, using Zustand manager
|
||||
*/
|
||||
export const useUserState = create<UserStateProps>((set, get) => ({
|
||||
user: undefined,
|
||||
setUser: (newUser: UserProps) => set({ user: newUser }),
|
||||
fetchUserState: async () => {
|
||||
// Fetch user data
|
||||
await api
|
||||
.get(url(ApiPaths.user_me))
|
||||
.then((response) => {
|
||||
const user: UserProps = {
|
||||
name: `${response.data.first_name} ${response.data.last_name}`,
|
||||
email: response.data.email,
|
||||
username: response.data.username
|
||||
};
|
||||
set({ user: user });
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error fetching user data:', error);
|
||||
});
|
||||
|
||||
// Fetch role data
|
||||
await api
|
||||
.get(url(ApiPaths.user_roles))
|
||||
.then((response) => {
|
||||
const user: UserProps = get().user as UserProps;
|
||||
user.roles = response.data.roles;
|
||||
user.is_staff = response.data.is_staff ?? false;
|
||||
user.is_superuser = response.data.is_superuser ?? false;
|
||||
set({ user: user });
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error fetching user roles:', error);
|
||||
});
|
||||
},
|
||||
checkUserRole: (role: string, permission: string) => {
|
||||
// Check if the user has the specified permission for the specified role
|
||||
const user: UserProps = get().user as UserProps;
|
||||
|
||||
if (user.is_superuser) return true;
|
||||
if (user.roles === undefined) return false;
|
||||
if (user.roles[role] === undefined) return false;
|
||||
|
||||
return user.roles[role].includes(permission);
|
||||
}
|
||||
}));
|
@ -7,12 +7,17 @@ export interface HostList {
|
||||
[key: string]: Host;
|
||||
}
|
||||
|
||||
// Type interface fully defining the current user
|
||||
export interface UserProps {
|
||||
name: string;
|
||||
email: string;
|
||||
username: string;
|
||||
is_staff?: boolean;
|
||||
is_superuser?: boolean;
|
||||
roles?: Record<string, string[]>;
|
||||
}
|
||||
|
||||
// Type interface fully defining the current server
|
||||
export interface ServerAPIProps {
|
||||
server: null | string;
|
||||
version: null | string;
|
||||
|
@ -7,13 +7,13 @@ import { BaseContext } from '../contexts/BaseContext';
|
||||
import { defaultHostList } from '../defaults/defaultHostList';
|
||||
import { url_base } from '../main';
|
||||
import { routes } from '../router';
|
||||
import { useApiState } from '../states/ApiState';
|
||||
import { useLocalState } from '../states/LocalState';
|
||||
import { useSessionState } from '../states/SessionState';
|
||||
import { useUserState } from '../states/UserState';
|
||||
|
||||
export default function DesktopAppView() {
|
||||
const [hostList] = useLocalState((state) => [state.hostList]);
|
||||
const [fetchApiState] = useApiState((state) => [state.fetchApiState]);
|
||||
const [fetchUserState] = useUserState((state) => [state.fetchUserState]);
|
||||
|
||||
// Local state initialization
|
||||
if (Object.keys(hostList).length === 0) {
|
||||
@ -29,7 +29,7 @@ export default function DesktopAppView() {
|
||||
useEffect(() => {
|
||||
if (token && !fetchedServerSession) {
|
||||
setFetchedServerSession(true);
|
||||
fetchApiState();
|
||||
fetchUserState();
|
||||
}
|
||||
}, [token, fetchedServerSession]);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user