feat: 新增首页和图片资源
This commit is contained in:
143
src/store/auth/auth-store.ts
Normal file
143
src/store/auth/auth-store.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { create } from 'zustand'
|
||||
import { createJSONStorage, persist } from 'zustand/middleware'
|
||||
|
||||
import { AUTH_STORAGE_KEY } from '@/constants'
|
||||
|
||||
export type AuthStatus = 'anonymous' | 'authenticated' | 'restoring'
|
||||
|
||||
export interface AuthUser {
|
||||
email?: string
|
||||
id: string
|
||||
name?: string
|
||||
roles?: string[]
|
||||
}
|
||||
|
||||
export interface AuthSessionInput {
|
||||
accessToken: string
|
||||
currentUser?: AuthUser | null
|
||||
refreshToken?: string | null
|
||||
}
|
||||
|
||||
interface PersistedAuthState {
|
||||
accessToken: string | null
|
||||
currentUser: AuthUser | null
|
||||
refreshToken: string | null
|
||||
}
|
||||
|
||||
interface AuthState extends PersistedAuthState {
|
||||
clearAccessToken: () => void
|
||||
clearSession: () => void
|
||||
finishHydration: () => void
|
||||
isHydrated: boolean
|
||||
lastUnauthorizedAt: string | null
|
||||
markUnauthorized: () => void
|
||||
setAccessToken: (token: string) => void
|
||||
setCurrentUser: (user: AuthUser | null) => void
|
||||
startSession: (session: AuthSessionInput) => void
|
||||
status: AuthStatus
|
||||
updateTokens: (tokens: {
|
||||
accessToken: string
|
||||
refreshToken?: string | null
|
||||
}) => void
|
||||
}
|
||||
|
||||
function resolveAuthStatus(accessToken: string | null): AuthStatus {
|
||||
return accessToken ? 'authenticated' : 'anonymous'
|
||||
}
|
||||
|
||||
const initialPersistedState: PersistedAuthState = {
|
||||
accessToken: null,
|
||||
refreshToken: null,
|
||||
currentUser: null,
|
||||
}
|
||||
|
||||
export const useAuthStore = create<AuthState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
...initialPersistedState,
|
||||
status: 'restoring',
|
||||
isHydrated: false,
|
||||
lastUnauthorizedAt: null,
|
||||
setAccessToken: (token) => {
|
||||
set({
|
||||
accessToken: token,
|
||||
status: 'authenticated',
|
||||
isHydrated: true,
|
||||
})
|
||||
},
|
||||
setCurrentUser: (currentUser) => {
|
||||
set((state) => ({
|
||||
currentUser,
|
||||
status: resolveAuthStatus(state.accessToken),
|
||||
}))
|
||||
},
|
||||
startSession: ({
|
||||
accessToken,
|
||||
currentUser = null,
|
||||
refreshToken = null,
|
||||
}) => {
|
||||
set({
|
||||
accessToken,
|
||||
currentUser,
|
||||
refreshToken,
|
||||
status: 'authenticated',
|
||||
isHydrated: true,
|
||||
})
|
||||
},
|
||||
updateTokens: ({ accessToken, refreshToken }) => {
|
||||
set((state) => ({
|
||||
accessToken,
|
||||
refreshToken: refreshToken ?? state.refreshToken,
|
||||
status: 'authenticated',
|
||||
isHydrated: true,
|
||||
}))
|
||||
},
|
||||
finishHydration: () => {
|
||||
set((state) => ({
|
||||
isHydrated: true,
|
||||
status: resolveAuthStatus(state.accessToken),
|
||||
}))
|
||||
},
|
||||
clearAccessToken: () => {
|
||||
set({
|
||||
accessToken: null,
|
||||
status: 'anonymous',
|
||||
isHydrated: true,
|
||||
})
|
||||
},
|
||||
clearSession: () => {
|
||||
set({
|
||||
...initialPersistedState,
|
||||
status: 'anonymous',
|
||||
isHydrated: true,
|
||||
})
|
||||
},
|
||||
markUnauthorized: () => {
|
||||
set({
|
||||
...initialPersistedState,
|
||||
status: 'anonymous',
|
||||
isHydrated: true,
|
||||
lastUnauthorizedAt: new Date().toISOString(),
|
||||
})
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: AUTH_STORAGE_KEY,
|
||||
storage: createJSONStorage(() => sessionStorage),
|
||||
partialize: (state) => ({
|
||||
accessToken: state.accessToken,
|
||||
currentUser: state.currentUser,
|
||||
refreshToken: state.refreshToken,
|
||||
}),
|
||||
onRehydrateStorage: () => (state, error) => {
|
||||
if (error) {
|
||||
state?.clearSession()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
state?.finishHydration()
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
Reference in New Issue
Block a user