add parent pages
This commit is contained in:
@@ -14,9 +14,16 @@ export type { AuthUser }
|
||||
type AuthState = {
|
||||
token: string | null
|
||||
user: AuthUser | null
|
||||
selectedRole: string | null
|
||||
}
|
||||
|
||||
const STORAGE_USER = 'alrahma_api_user'
|
||||
const STORAGE_ROLE = 'alrahma_selected_role'
|
||||
|
||||
function enabledRoles(user: AuthUser | null): string[] {
|
||||
if (!user?.roles) return []
|
||||
return Object.keys(user.roles).filter((k) => user.roles[k])
|
||||
}
|
||||
|
||||
function readUser(): AuthUser | null {
|
||||
try {
|
||||
@@ -33,11 +40,30 @@ function writeUser(user: AuthUser | null): void {
|
||||
else localStorage.removeItem(STORAGE_USER)
|
||||
}
|
||||
|
||||
function readSelectedRole(): string | null {
|
||||
const role = localStorage.getItem(STORAGE_ROLE)
|
||||
return role && role.trim() ? role : null
|
||||
}
|
||||
|
||||
function writeSelectedRole(role: string | null): void {
|
||||
if (role) localStorage.setItem(STORAGE_ROLE, role)
|
||||
else localStorage.removeItem(STORAGE_ROLE)
|
||||
}
|
||||
|
||||
function validSelectedRole(user: AuthUser | null, role: string | null): string | null {
|
||||
if (!role) return null
|
||||
const roles = enabledRoles(user)
|
||||
return roles.includes(role) ? role : null
|
||||
}
|
||||
|
||||
let memory: AuthState = {
|
||||
token: getStoredToken(),
|
||||
user: readUser(),
|
||||
selectedRole: null,
|
||||
}
|
||||
|
||||
memory.selectedRole = validSelectedRole(memory.user, readSelectedRole())
|
||||
|
||||
const listeners = new Set<() => void>()
|
||||
|
||||
function emit(): void {
|
||||
@@ -59,9 +85,11 @@ function getSnapshot(): AuthState {
|
||||
}
|
||||
|
||||
export function hydrateAuthFromStorage(): void {
|
||||
const user = readUser()
|
||||
memory = {
|
||||
token: getStoredToken(),
|
||||
user: readUser(),
|
||||
user,
|
||||
selectedRole: validSelectedRole(user, readSelectedRole()),
|
||||
}
|
||||
emit()
|
||||
}
|
||||
@@ -77,22 +105,42 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
message: result.message ?? 'Login failed.',
|
||||
}
|
||||
}
|
||||
|
||||
const roles = enabledRoles(result.user)
|
||||
const nextRole = roles.length === 1 ? roles[0] : null
|
||||
setStoredToken(result.token)
|
||||
writeUser(result.user)
|
||||
setAuth({ token: result.token, user: result.user })
|
||||
return { ok: true as const }
|
||||
writeSelectedRole(nextRole)
|
||||
setAuth({ token: result.token, user: result.user, selectedRole: nextRole })
|
||||
return {
|
||||
ok: true as const,
|
||||
requiresRoleSelection: roles.length > 1,
|
||||
roles,
|
||||
selectedRole: nextRole,
|
||||
}
|
||||
}, [])
|
||||
|
||||
const logout = useCallback(() => {
|
||||
setStoredToken(null)
|
||||
writeUser(null)
|
||||
setAuth({ token: null, user: null })
|
||||
writeSelectedRole(null)
|
||||
setAuth({ token: null, user: null, selectedRole: null })
|
||||
}, [])
|
||||
|
||||
const setSession = useCallback((token: string, user: AuthUser) => {
|
||||
const roles = enabledRoles(user)
|
||||
const nextRole = roles.length === 1 ? roles[0] : null
|
||||
setStoredToken(token)
|
||||
writeUser(user)
|
||||
setAuth({ token, user })
|
||||
writeSelectedRole(nextRole)
|
||||
setAuth({ token, user, selectedRole: nextRole })
|
||||
}, [])
|
||||
|
||||
const setSelectedRole = useCallback((role: string | null) => {
|
||||
const roles = enabledRoles(memory.user)
|
||||
const nextRole = role && roles.includes(role) ? role : null
|
||||
writeSelectedRole(nextRole)
|
||||
setAuth({ ...memory, selectedRole: nextRole })
|
||||
}, [])
|
||||
|
||||
const value = useMemo(
|
||||
@@ -100,11 +148,14 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
login,
|
||||
logout,
|
||||
setSession,
|
||||
setSelectedRole,
|
||||
token: state.token,
|
||||
user: state.user,
|
||||
selectedRole: state.selectedRole,
|
||||
roles: enabledRoles(state.user),
|
||||
isAuthenticated: Boolean(state.token && state.user),
|
||||
}),
|
||||
[state.token, state.user, login, logout, setSession],
|
||||
[state.token, state.user, state.selectedRole, login, logout, setSession, setSelectedRole],
|
||||
)
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
||||
@@ -114,11 +165,16 @@ type AuthContextValue = {
|
||||
login: (
|
||||
email: string,
|
||||
password: string,
|
||||
) => Promise<{ ok: true } | { ok: false; message: string }>
|
||||
) => Promise<
|
||||
{ ok: true; requiresRoleSelection: boolean; roles: string[]; selectedRole: string | null } | { ok: false; message: string }
|
||||
>
|
||||
logout: () => void
|
||||
setSession: (token: string, user: AuthUser) => void
|
||||
setSelectedRole: (role: string | null) => void
|
||||
token: string | null
|
||||
user: AuthUser | null
|
||||
selectedRole: string | null
|
||||
roles: string[]
|
||||
isAuthenticated: boolean
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user