diff options
Diffstat (limited to 'lib/nonsap/action-utils.ts')
| -rw-r--r-- | lib/nonsap/action-utils.ts | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/lib/nonsap/action-utils.ts b/lib/nonsap/action-utils.ts new file mode 100644 index 00000000..731df1f5 --- /dev/null +++ b/lib/nonsap/action-utils.ts @@ -0,0 +1,85 @@ +import { getServerSession } from "next-auth/next"; +import { authOptions } from "@/app/api/auth/[...nextauth]/route"; +import { verifyNonsapPermission, AuthAction } from "./auth-service"; +import 'server-only'; // 클라이언트 번들에 포함되는 걸 방지하기 위함 + +export type ActionResponse<T> = { + success: boolean; + data?: T; + error?: string; + message?: string; +}; + +/** + * 권한 체크와 세션 확인을 수행하는 고차 함수 (Action Factory) + * + * 이 유틸리티는 Server Action을 감싸서 다음 기능을 자동으로 수행합니다: + * 1. 사용자 세션 확인 (로그인 여부) + * 2. NONSAP 권한 검증 (verifyNonsapPermission 사용) + * 3. 에러 핸들링 (try-catch) + * + * @param requiredActions - 해당 액션을 수행하기 위해 필요한 권한 목록 (예: ['ADD'], ['SEARCH', 'DOWN']) + * @param action - 실제 비즈니스 로직을 수행하는 함수. + * 첫 번째 인자로 input을, 두 번째 인자로 검증된 userId를 받습니다. + * @param options - (Optional) 추가 옵션 + * @param options.url - 권한 체크를 위한 명시적 URL (생략 시 x-pathname 헤더 자동 감지). + * 특정 화면의 권한을 강제로 적용하고 싶을 때 사용합니다. + * @param options.logic - 여러 권한이 필요할 때의 논리 연산 ('AND' | 'OR'). 기본값은 'AND'. + * @returns 권한 검증 로직이 포함된 새로운 비동기 함수 + */ +export function withNonsapAuth<TInput, TOutput>( + requiredActions: AuthAction[], + action: (input: TInput, userId: number) => Promise<ActionResponse<TOutput>>, + options?: { + url?: string; + logic?: 'AND' | 'OR'; + } +) { + return async (input: TInput): Promise<ActionResponse<TOutput>> => { + try { + // 1. 세션 확인 + const session = await getServerSession(authOptions); + const userId = Number(session?.user?.id); + + if (!userId || isNaN(userId)) { + return { + success: false, + error: "로그인이 필요하거나 세션이 만료되었습니다." + }; + } + + // 2. 권한 검증 + // options.url이 있으면 그것을 사용하고, 없으면 headers()를 통해 자동 감지 + const authResult = await verifyNonsapPermission( + userId, + requiredActions, + options?.url, + { logic: options?.logic } + ); + + if (!authResult.authorized) { + // 환경변수 체크: CHECK_NONSAP_AUTH_HOC가 'true'일 때만 권한 체크를 강제함 + // 그 외의 경우(설정되지 않았거나 false 등)에는 경고만 남기고 실행 허용 + if (process.env.CHECK_NONSAP_AUTH_HOC === 'true') { + return { + success: false, + error: authResult.message || "이 작업을 수행할 권한이 없습니다." + }; + } else { + console.warn(`[withNonsapAuth] 권한 체크 실패했으나 실행 허용됨 (CHECK_NONSAP_AUTH_HOC != true). User: ${userId}, Actions: ${requiredActions.join(',')}`); + } + } + + // 3. 실제 액션 실행 + // userId를 주입하여 액션 내부에서 다시 세션을 조회할 필요가 없도록 합니다. + return await action(input, userId); + + } catch (error) { + console.error("[withNonsapAuth] Server Action Error:", error); + return { + success: false, + error: "서버 내부 오류가 발생했습니다." + }; + } + }; +} |
