// app/actions/permission-group-actions.ts "use server"; import db from "@/db/db"; import { eq, and, inArray, sql } from "drizzle-orm"; import { permissionGroups, permissionGroupMembers, permissions, rolePermissions, userPermissions, roles, users } from "@/db/schema"; import { checkUserPermission } from "./service"; import { getServerSession } from "next-auth/next" import { authOptions } from "@/app/api/auth/[...nextauth]/route" // 권한 그룹 목록 조회 export async function getPermissionGroups() { const groups = await db .select({ id: permissionGroups.id, groupKey: permissionGroups.groupKey, name: permissionGroups.name, description: permissionGroups.description, domain: permissionGroups.domain, isActive: permissionGroups.isActive, createdAt: permissionGroups.createdAt, updatedAt: permissionGroups.updatedAt, permissionCount: sql`count(distinct ${permissionGroupMembers.permissionId})`.mapWith(Number), }) .from(permissionGroups) .leftJoin(permissionGroupMembers, eq(permissionGroupMembers.groupId, permissionGroups.id)) .groupBy(permissionGroups.id) .orderBy(permissionGroups.name); // 각 그룹의 역할 및 사용자 수 계산 const groupsWithCounts = await Promise.all( groups.map(async (group) => { const roleCount = await db .selectDistinct({ roleId: rolePermissions.roleId }) .from(rolePermissions) .where(eq(rolePermissions.permissionGroupId, group.id)); const userCount = await db .selectDistinct({ userId: userPermissions.userId }) .from(userPermissions) .where(eq(userPermissions.permissionGroupId, group.id)); return { ...group, roleCount: roleCount.length, userCount: userCount.length, }; }) ); return groupsWithCounts; } // 권한 그룹 생성 export async function createPermissionGroup(data: { groupKey: string; name: string; description?: string; domain?: string; isActive: boolean; }) { const session = await getServerSession(authOptions) if (!session?.user?.id) { throw new Error("인증이 필요합니다.") } const currentUserId = Number(session.user.id) if (!await checkUserPermission(currentUserId, "admin.permissions.manage")) { throw new Error("권한 관리 권한이 없습니다."); } // 중복 체크 const existing = await db.select() .from(permissionGroups) .where(eq(permissionGroups.groupKey, data.groupKey)) .limit(1); if (existing.length > 0) { throw new Error("이미 존재하는 그룹 키입니다."); } const [created] = await db.insert(permissionGroups).values(data).returning(); return created; } // 권한 그룹 수정 export async function updatePermissionGroup(id: number, data: any) { const session = await getServerSession(authOptions) if (!session?.user?.id) { throw new Error("인증이 필요합니다.") } const currentUserId = Number(session.user.id) if (!await checkUserPermission(currentUserId, "admin.permissions.manage")) { throw new Error("권한 관리 권한이 없습니다."); } const [updated] = await db.update(permissionGroups) .set({ ...data, updatedAt: new Date(), }) .where(eq(permissionGroups.id, id)) .returning(); return updated; } // 권한 그룹 삭제 export async function deletePermissionGroup(id: number) { const session = await getServerSession(authOptions) if (!session?.user?.id) { throw new Error("인증이 필요합니다.") } const currentUserId = Number(session.user.id) if (!await checkUserPermission(currentUserId, "admin.permissions.manage")) { throw new Error("권한 관리 권한이 없습니다."); } await db.transaction(async (tx) => { // 그룹 멤버 삭제 await tx.delete(permissionGroupMembers) .where(eq(permissionGroupMembers.groupId, id)); // 그룹 삭제 await tx.delete(permissionGroups) .where(eq(permissionGroups.id, id)); }); } // 그룹의 권한 조회 export async function getGroupPermissions(groupId: number) { const groupPermissions = await db .select({ id: permissions.id, permissionKey: permissions.permissionKey, name: permissions.name, description: permissions.description, resource: permissions.resource, action: permissions.action, permissionType: permissions.permissionType, scope: permissions.scope, }) .from(permissionGroupMembers) .innerJoin(permissions, eq(permissions.id, permissionGroupMembers.permissionId)) .where(eq(permissionGroupMembers.groupId, groupId)); const allPermissions = await db.select().from(permissions) .where(eq(permissions.isActive, true)); return { permissions: groupPermissions, availablePermissions: allPermissions, }; } // 그룹 권한 업데이트 export async function updateGroupPermissions(groupId: number, permissionIds: number[]) { const session = await getServerSession(authOptions) if (!session?.user?.id) { throw new Error("인증이 필요합니다.") } const currentUserId = Number(session.user.id) if (!await checkUserPermission(currentUserId, "admin.permissions.manage")) { throw new Error("권한 관리 권한이 없습니다."); } await db.transaction(async (tx) => { // 기존 권한 삭제 await tx.delete(permissionGroupMembers) .where(eq(permissionGroupMembers.groupId, groupId)); // 새 권한 추가 if (permissionIds.length > 0) { await tx.insert(permissionGroupMembers).values( permissionIds.map(permissionId => ({ groupId, permissionId, })) ); } }); } // 권한 그룹 복제 export async function clonePermissionGroup(groupId: number) { const session = await getServerSession(authOptions) if (!session?.user?.id) { throw new Error("인증이 필요합니다.") } const currentUserId = Number(session.user.id) if (!await checkUserPermission(currentUserId, "admin.permissions.manage")) { throw new Error("권한 관리 권한이 없습니다."); } // 원본 그룹 조회 const [originalGroup] = await db.select() .from(permissionGroups) .where(eq(permissionGroups.id, groupId)); if (!originalGroup) { throw new Error("그룹을 찾을 수 없습니다."); } // 원본 그룹의 권한 조회 const originalPermissions = await db.select() .from(permissionGroupMembers) .where(eq(permissionGroupMembers.groupId, groupId)); // 새 그룹 생성 const timestamp = Date.now(); const [newGroup] = await db.insert(permissionGroups).values({ groupKey: `${originalGroup.groupKey}_copy_${timestamp}`, name: `${originalGroup.name} (복사본)`, description: originalGroup.description, domain: originalGroup.domain, isActive: originalGroup.isActive, }).returning(); // 권한 복사 if (originalPermissions.length > 0) { await db.insert(permissionGroupMembers).values( originalPermissions.map(p => ({ groupId: newGroup.id, permissionId: p.permissionId, })) ); } return newGroup; } // 그룹 할당 정보 조회 export async function getGroupAssignments(groupId: number) { const assignedRoles = await db .select({ id: roles.id, name: roles.name, domain: roles.domain, }) .from(rolePermissions) .innerJoin(roles, eq(roles.id, rolePermissions.roleId)) .where(eq(rolePermissions.permissionGroupId, groupId)); const assignedUsers = await db .select({ id: users.id, name: users.name, email: users.email, imageUrl: users.imageUrl, domain: users.domain, }) .from(userPermissions) .innerJoin(users, eq(users.id, userPermissions.userId)) .where(eq(userPermissions.permissionGroupId, groupId)); return { roles: assignedRoles, users: assignedUsers, }; }