'use server'; import { isRedirectError } from 'next/dist/client/components/redirect'; import { revalidatePath } from 'next/cache'; import { serverFetch } from '@/lib/api/fetch-wrapper'; import type { Role, RoleStats, PermissionMatrix, MenuTreeItem, ApiResponse, PaginatedResponse } from './types'; const API_URL = process.env.NEXT_PUBLIC_API_URL; // ========== Role CRUD ========== /** * 역할 목록 조회 */ export async function fetchRoles(params?: { page?: number; size?: number; q?: string; is_hidden?: boolean; }): Promise>> { try { const searchParams = new URLSearchParams(); if (params?.page) searchParams.set('page', params.page.toString()); if (params?.size) searchParams.set('per_page', params.size.toString()); if (params?.q) searchParams.set('q', params.q); if (params?.is_hidden !== undefined) searchParams.set('is_hidden', params.is_hidden.toString()); const url = `${API_URL}/api/v1/roles?${searchParams.toString()}`; const { response, error } = await serverFetch(url, { method: 'GET' }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '역할 목록 조회에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '역할 목록 조회 실패' }; } return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to fetch roles:', error); return { success: false, error: error instanceof Error ? error.message : '역할 목록 조회 실패' }; } } /** * 역할 상세 조회 */ export async function fetchRole(id: number): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/${id}`, { method: 'GET' }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '역할 조회에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '역할 조회 실패' }; } return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to fetch role:', error); return { success: false, error: error instanceof Error ? error.message : '역할 조회 실패' }; } } /** * 역할 생성 */ export async function createRole(data: { name: string; description?: string; is_hidden?: boolean; }): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles`, { method: 'POST', body: JSON.stringify(data), }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '역할 생성에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '역할 생성 실패' }; } revalidatePath('/settings/permissions'); return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to create role:', error); return { success: false, error: error instanceof Error ? error.message : '역할 생성 실패' }; } } /** * 역할 수정 */ export async function updateRole( id: number, data: { name?: string; description?: string; is_hidden?: boolean; } ): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/${id}`, { method: 'PATCH', body: JSON.stringify(data), }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '역할 수정에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '역할 수정 실패' }; } revalidatePath('/settings/permissions'); revalidatePath(`/settings/permissions/${id}`); return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to update role:', error); return { success: false, error: error instanceof Error ? error.message : '역할 수정 실패' }; } } /** * 역할 삭제 */ export async function deleteRole(id: number): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/${id}`, { method: 'DELETE', }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '역할 삭제에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '역할 삭제 실패' }; } revalidatePath('/settings/permissions'); return { success: true }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to delete role:', error); return { success: false, error: error instanceof Error ? error.message : '역할 삭제 실패' }; } } /** * 역할 통계 조회 */ export async function fetchRoleStats(): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/stats`, { method: 'GET' }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '역할 통계 조회에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '역할 통계 조회 실패' }; } return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to fetch role stats:', error); return { success: false, error: error instanceof Error ? error.message : '역할 통계 조회 실패' }; } } /** * 활성 역할 목록 (드롭다운용) */ export async function fetchActiveRoles(): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/active`, { method: 'GET' }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '활성 역할 목록 조회에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '활성 역할 목록 조회 실패' }; } return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to fetch active roles:', error); return { success: false, error: error instanceof Error ? error.message : '활성 역할 목록 조회 실패' }; } } // ========== Permission Matrix ========== /** * 권한 매트릭스용 메뉴 트리 조회 */ export async function fetchPermissionMenus(): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/role-permissions/menus`, { method: 'GET' }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '메뉴 트리 조회에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '메뉴 트리 조회 실패' }; } return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to fetch permission menus:', error); return { success: false, error: error instanceof Error ? error.message : '메뉴 트리 조회 실패' }; } } /** * 역할의 권한 매트릭스 조회 */ export async function fetchPermissionMatrix(roleId: number): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/${roleId}/permissions/matrix`, { method: 'GET' }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '권한 매트릭스 조회에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '권한 매트릭스 조회 실패' }; } return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to fetch permission matrix:', error); return { success: false, error: error instanceof Error ? error.message : '권한 매트릭스 조회 실패' }; } } /** * 특정 메뉴의 특정 권한 토글 */ export async function togglePermission( roleId: number, menuId: number, permissionType: string ): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/${roleId}/permissions/toggle`, { method: 'POST', body: JSON.stringify({ menu_id: menuId, permission_type: permissionType, }), }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '권한 토글에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '권한 토글 실패' }; } revalidatePath(`/settings/permissions/${roleId}`); return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to toggle permission:', error); return { success: false, error: error instanceof Error ? error.message : '권한 토글 실패' }; } } /** * 모든 권한 허용 */ export async function allowAllPermissions(roleId: number): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/${roleId}/permissions/allow-all`, { method: 'POST', }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '전체 허용에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '전체 허용 실패' }; } revalidatePath(`/settings/permissions/${roleId}`); return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to allow all permissions:', error); return { success: false, error: error instanceof Error ? error.message : '전체 허용 실패' }; } } /** * 모든 권한 거부 */ export async function denyAllPermissions(roleId: number): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/${roleId}/permissions/deny-all`, { method: 'POST', }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '전체 거부에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '전체 거부 실패' }; } revalidatePath(`/settings/permissions/${roleId}`); return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to deny all permissions:', error); return { success: false, error: error instanceof Error ? error.message : '전체 거부 실패' }; } } /** * 기본 권한으로 초기화 (view만 허용) */ export async function resetPermissions(roleId: number): Promise> { try { const { response, error } = await serverFetch(`${API_URL}/api/v1/roles/${roleId}/permissions/reset`, { method: 'POST', }); if (error) { return { success: false, error: error.message }; } if (!response) { return { success: false, error: '권한 초기화에 실패했습니다.' }; } const result = await response.json(); if (!response.ok || !result.success) { return { success: false, error: result.message || '권한 초기화 실패' }; } revalidatePath(`/settings/permissions/${roleId}`); return { success: true, data: result.data }; } catch (error) { if (isRedirectError(error)) throw error; console.error('Failed to reset permissions:', error); return { success: false, error: error instanceof Error ? error.message : '권한 초기화 실패' }; } }