diff --git a/src/contexts/auth/index.tsx b/src/contexts/auth/index.tsx index d4dca3b..581bbab 100644 --- a/src/contexts/auth/index.tsx +++ b/src/contexts/auth/index.tsx @@ -1,180 +1,147 @@ import Loader from "@/components/loader"; -import React, { createContext, useEffect, useReducer } from "react"; -import { auth, getUserInfo } from "@/service/api/user.ts"; -import { getAuthToken, setAuthToken } from "@/hooks/useAuth.ts"; -import { getRoleByUsername } from "@/contexts/auth/role.ts"; +import React, {createContext, useEffect, useReducer} from "react"; +import {auth, getUserInfo} from "@/service/api/user.ts"; +import {getAuthToken, setAuthToken} from "@/hooks/useAuth.ts"; +import {getRoleByUsername} from "@/contexts/auth/role.ts"; const AuthContext = createContext(null) const initialState: AuthProps = { - isLoggedIn: false, - isInitialized: false, - user: null + isLoggedIn: false, + isInitialized: false, + user: null }; const authReducer = (state: AuthProps, action: { action?: string, payload: Partial }) => { - return { - ...state, - ...action.payload, - } - // switch (action.action) { - // case 'LOGIN': - // return { - // ...state, - // ...action.payload, - // isLoggedIn: true - // }; - // case 'LOGOUT': - // return { - // ...state, - // ...action.payload, - // isLoggedIn: false - // }; - // case 'INITIALIZE': - // return { - // ...state, - // ...action.payload, - // isInitialized: true - // }; - // default: - // return state; - // } + return { + ...state, + ...action.payload, + } } const UserRoleStorageKey = 'user-current-role'; + function getCurrentRole(username: string) { - return (localStorage.getItem(UserRoleStorageKey) || getRoleByUsername(username)) as UserRole + return (localStorage.getItem(UserRoleStorageKey) || getRoleByUsername(username)) as UserRole } export function setCurrentRole(role: UserRole) { - localStorage.setItem(UserRoleStorageKey, role) + localStorage.setItem(UserRoleStorageKey, role) } + function removeRoleStorage() { - localStorage.removeItem(UserRoleStorageKey) + localStorage.removeItem(UserRoleStorageKey) } -export const AuthProvider = ({ children }: { children: React.ReactNode }) => { - const [state, dispatch] = useReducer(authReducer, initialState); +function getInitUserData(user: UserProfile) { + const {roles} = user; + const role = !roles || roles.length === 0 ? 'staff' : ( + roles.includes('root') ? 'root' : ( + roles.includes('fo') ? 'fo' : 'ro' + ) + ) as UserRole - // MOCK INIT DATA - const init = async () => { - const token = getAuthToken(); - if (!token) { - dispatch({ - payload: { - isInitialized: true, - } - }) - return 'initialized' - } - getUserInfo().then(user => { - dispatch({ - action: 'init', - payload: { - isInitialized: true, - isLoggedIn: !!user, - user: { - ...user, - origin_role: getRoleByUsername(user.username), - role: getCurrentRole(user.username) - } - } - }) - }).finally(() => { - dispatch({ - payload: { - isInitialized: true, - } - }) - }) - return 'initialized' - } - // 登录 - const login = async (code: string, state: string) => { - const user = await auth(code, state) - // 保存token - setAuthToken(user.token, user.expiration_time ? (new Date(user.expiration_time)).getTime() : -1); + return { + ...user, + origin_role: role, + role: role == 'root' ? (getCurrentRole(user.username) || role) : role + } +} - // - dispatch({ - action: 'login', - payload: { - isLoggedIn: true, - user: { - ...user, - origin_role: getRoleByUsername(user.username), - role: getCurrentRole(user.username) - } - } - }) - } - // 登出 - const logout = async () => { - setTimeout(()=>{ - const a = document.createElement('a') - a.setAttribute('href','https://portal.chuhai.edu.hk/signout') - a.setAttribute('target','_blank') - a.click() - },0) - setAuthToken(null) - removeRoleStorage() - dispatch({ - action: 'logout', - payload: { - isLoggedIn: false, - user: null - } - }) - } - const mockLogin = async () => { - setAuthToken('test-123123', Date.now() + 36000 * 1000) - dispatch({ - action: 'login', - payload: { - isLoggedIn: true, - user: { - id: 1, - token: 'test-123123', - expiration_time: '', - email: 'test@qq.com', - department: '', - role: 'staff', - exp: 1, - iat: 1, - iss: "Hong Kong Chu Hai College", - nbf: 1, - type: "id_token", - username: 'test-123123', - } - } - }) - } +export const AuthProvider = ({children}: { children: React.ReactNode }) => { + const [state, dispatch] = useReducer(authReducer, initialState); - const updateUser = async (user: Partial) => { - dispatch({ - action: 'updateUser', - payload: { - user: { - ...state.user, - ...user - } as never, + // MOCK INIT DATA + const init = async () => { + const token = getAuthToken(); + if (!token) { + dispatch({ + payload: { + isInitialized: true, + } + }) + return 'initialized' + } + getUserInfo().then(user => { + dispatch({ + action: 'init', + payload: { + isInitialized: true, + isLoggedIn: !!user, + user: getInitUserData(user) + } + }) + }).finally(() => { + dispatch({ + payload: { + isInitialized: true, + } + }) + }) + return 'initialized' + } + // 登录 + const login = async (code: string, state: string) => { + const user = await auth(code, state) + // 保存token + setAuthToken(user.token, user.expiration_time ? (new Date(user.expiration_time)).getTime() : -1); - } - }) - }; + // + dispatch({ + action: 'login', + payload: { + isLoggedIn: true, + user: getInitUserData(user) + } + }) + } + // 登出 + const logout = async () => { + setTimeout(() => { + const a = document.createElement('a') + a.setAttribute('href', 'https://portal.chuhai.edu.hk/signout') + a.setAttribute('target', '_blank') + a.click() + }, 0) + setAuthToken(null) + removeRoleStorage() + dispatch({ + action: 'logout', + payload: { + isLoggedIn: false, + user: null + } + }) + } + const mockLogin = async () => { + console.log('mock login') + } - useEffect(() => { - init().then(console.log) - }, []) + const updateUser = async (user: Partial) => { + dispatch({ + action: 'updateUser', + payload: { + user: { + ...state.user, + ...user + } as never, - // 判断是否已经初始化 - if (state.isInitialized !== undefined && !state.isInitialized) { - return ; - } - return ({children}) + } + }) + }; + + useEffect(() => { + init().then(console.log) + }, []) + + // 判断是否已经初始化 + if (state.isInitialized !== undefined && !state.isInitialized) { + return ; + } + return ({children}) } export default AuthContext \ No newline at end of file diff --git a/src/types/auth.d.ts b/src/types/auth.d.ts index 9d298eb..60b9b03 100644 --- a/src/types/auth.d.ts +++ b/src/types/auth.d.ts @@ -12,6 +12,7 @@ declare type UserProfile = { iss: string; nbf: number; type: string; + roles: UserRole[]; role: UserRole; origin_role?: UserRole; }