기존에 비자동승인 도메인(gmail.com 등) Google 로그인 시 403 에러를 던져 등록 실패처럼 보이던 문제를 수정. PENDING 사용자에 대해 에러 대신 200 응답으로 pending 상태를 반환하고, 프론트엔드에서 청록색 안내 메시지로 표시하도록 변경. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81 lines
2.4 KiB
TypeScript
81 lines
2.4 KiB
TypeScript
import { create } from 'zustand'
|
|
import { loginApi, googleLoginApi, logoutApi, fetchMe, PendingApprovalError } from '../services/authApi'
|
|
import type { AuthUser } from '../services/authApi'
|
|
|
|
interface AuthState {
|
|
user: AuthUser | null
|
|
isAuthenticated: boolean
|
|
isLoading: boolean
|
|
error: string | null
|
|
pendingMessage: string | null
|
|
login: (account: string, password: string) => Promise<void>
|
|
googleLogin: (credential: string) => Promise<void>
|
|
logout: () => Promise<void>
|
|
checkSession: () => Promise<void>
|
|
hasPermission: (resource: string) => boolean
|
|
clearError: () => void
|
|
}
|
|
|
|
export const useAuthStore = create<AuthState>((set, get) => ({
|
|
user: null,
|
|
isAuthenticated: false,
|
|
isLoading: true,
|
|
error: null,
|
|
pendingMessage: null,
|
|
|
|
login: async (account: string, password: string) => {
|
|
set({ isLoading: true, error: null })
|
|
try {
|
|
const user = await loginApi(account, password)
|
|
set({ user, isAuthenticated: true, isLoading: false })
|
|
} catch (err) {
|
|
const message = (err as { message?: string })?.message || '로그인에 실패했습니다.'
|
|
set({ isLoading: false, error: message })
|
|
throw err
|
|
}
|
|
},
|
|
|
|
googleLogin: async (credential: string) => {
|
|
set({ isLoading: true, error: null, pendingMessage: null })
|
|
try {
|
|
const user = await googleLoginApi(credential)
|
|
set({ user, isAuthenticated: true, isLoading: false })
|
|
} catch (err) {
|
|
if (err instanceof PendingApprovalError) {
|
|
set({ isLoading: false, pendingMessage: err.message })
|
|
return
|
|
}
|
|
const message = (err as { message?: string })?.message || 'Google 로그인에 실패했습니다.'
|
|
set({ isLoading: false, error: message })
|
|
throw err
|
|
}
|
|
},
|
|
|
|
logout: async () => {
|
|
try {
|
|
await logoutApi()
|
|
} catch {
|
|
// 로그아웃 실패해도 클라이언트 상태는 초기화
|
|
}
|
|
set({ user: null, isAuthenticated: false, isLoading: false, error: null })
|
|
},
|
|
|
|
checkSession: async () => {
|
|
set({ isLoading: true })
|
|
try {
|
|
const user = await fetchMe()
|
|
set({ user, isAuthenticated: true, isLoading: false })
|
|
} catch {
|
|
set({ user: null, isAuthenticated: false, isLoading: false })
|
|
}
|
|
},
|
|
|
|
hasPermission: (resource: string) => {
|
|
const { user } = get()
|
|
if (!user) return false
|
|
return user.permissions.includes(resource)
|
|
},
|
|
|
|
clearError: () => set({ error: null, pendingMessage: null }),
|
|
}))
|