diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-27 01:16:20 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-27 01:16:20 +0000 |
| commit | e9897d416b3e7327bbd4d4aef887eee37751ae82 (patch) | |
| tree | bd20ce6eadf9b21755bd7425492d2d31c7700a0e /hooks/use-settings-access.ts | |
| parent | 3bf1952c1dad9d479bb8b22031b06a7434d37c37 (diff) | |
(대표님) 20250627 오전 10시 작업사항
Diffstat (limited to 'hooks/use-settings-access.ts')
| -rw-r--r-- | hooks/use-settings-access.ts | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/hooks/use-settings-access.ts b/hooks/use-settings-access.ts new file mode 100644 index 00000000..cd7938ac --- /dev/null +++ b/hooks/use-settings-access.ts @@ -0,0 +1,118 @@ +// hooks/use-settings-access.ts (개선된 버전) +"use client" + +import * as React from "react" +import { useSession } from "next-auth/react" +import { useRouter } from "next/navigation" + +// 인증 방식 타입 +type AuthMethod = 'otp' | 'email' | 'sgips' | 'saml' + +interface UseSettingsAccessOptions { + // 재인증 유효 시간 (밀리초, 기본값: 5분) + validDuration?: number + // S-Gips 사용자 리다이렉트 경로 + sgipsRedirectPath?: string +} + +type AccessType = 'allowed' | 'reauth_required' | 'blocked_sgips' | 'loading' | 'unauthenticated' + +interface SettingsAccessState { + accessType: AccessType + showReAuthModal: boolean + isAuthenticated: boolean + userEmail: string + userId: string + userDomain: string | null + authMethod: AuthMethod | undefined + handleReAuthSuccess: () => Promise<void> + forceReAuth: () => void +} + +export function useSettingsAccess(options: UseSettingsAccessOptions = {}): SettingsAccessState { + const { + validDuration = 5 * 60 * 1000, + sgipsRedirectPath = "/dashboard" + } = options + + const { data: session, status, update } = useSession() + const router = useRouter() + const [showReAuthModal, setShowReAuthModal] = React.useState(false) + + // 사용자의 접근 타입 결정 (인증 방식 기반) + const accessType: AccessType = React.useMemo(() => { + if (status === "loading") return 'loading' + if (status === "unauthenticated") return 'unauthenticated' + if (!session?.user) return 'unauthenticated' + + const authMethod = session.user.authMethod + + // 인증 방식에 따른 접근 제어 + switch (authMethod) { + case 'sgips': + // S-Gips 사용자는 접근 차단 + return 'blocked_sgips' + + case 'saml': + // SAML 사용자는 바로 접근 허용 + return 'allowed' + + case 'otp': + // OTP 사용자는 바로 접근 허용 (이미 2차 인증 완료) + return 'allowed' + + case 'email': + // 일반 이메일 사용자는 재인증 필요 + const reAuthTime = session.user.reAuthTime + if (!reAuthTime) return 'reauth_required' + + const now = Date.now() + const isReAuthValid = (now - reAuthTime) < validDuration + + return isReAuthValid ? 'allowed' : 'reauth_required' + + default: + // 인증 방식이 불명확한 경우 재인증 요구 + console.warn('Unknown auth method:', authMethod) + return 'reauth_required' + } + }, [session, status, validDuration]) + + // S-Gips 사용자 자동 리다이렉트 + React.useEffect(() => { + if (accessType === 'blocked_sgips') { + router.push(sgipsRedirectPath) + } + }, [accessType, router, sgipsRedirectPath]) + + // 재인증 필요 시 모달 표시 + React.useEffect(() => { + setShowReAuthModal(accessType === 'reauth_required') + }, [accessType]) + + const handleReAuthSuccess = React.useCallback(async () => { + await update({ + reAuthTime: Date.now() + }) + setShowReAuthModal(false) + }, [update]) + + const forceReAuth = React.useCallback(async () => { + await update({ + reAuthTime: null + }) + setShowReAuthModal(true) + }, [update]) + + return { + accessType, + showReAuthModal, + isAuthenticated: accessType === 'allowed', + userEmail: session?.user?.email || "", + userId: session?.user?.id || "", + userDomain: session?.user?.domain || null, + authMethod: session?.user?.authMethod, + handleReAuthSuccess, + forceReAuth, + } +}
\ No newline at end of file |
