diff --git a/prisma/migrations/20251009053500_rbac_permissions/migration.sql b/prisma/migrations/20251009053500_rbac_permissions/migration.sql
new file mode 100644
index 0000000..c5b4e96
--- /dev/null
+++ b/prisma/migrations/20251009053500_rbac_permissions/migration.sql
@@ -0,0 +1,16 @@
+-- CreateTable
+CREATE TABLE "role_permissions" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "roleId" TEXT NOT NULL,
+ "resource" TEXT NOT NULL,
+ "action" TEXT NOT NULL,
+ "allowed" BOOLEAN NOT NULL DEFAULT true,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ CONSTRAINT "role_permissions_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "roles" ("roleId") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateIndex
+CREATE INDEX "role_permissions_resource_action_idx" ON "role_permissions"("resource", "action");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "role_permissions_roleId_resource_action_key" ON "role_permissions"("roleId", "resource", "action");
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 2061e96..11e8060 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -81,6 +81,24 @@ enum TargetType {
SYSTEM
}
+// RBAC 리소스/액션 정의
+enum Resource {
+ BOARD
+ POST
+ COMMENT
+ USER
+ ADMIN
+}
+
+enum Action {
+ READ
+ CREATE
+ UPDATE
+ DELETE
+ MODERATE
+ ADMINISTER
+}
+
// ==== Models ====
// 게시판 정의(관리자 생성/정렬)
@@ -214,13 +232,30 @@ model Role {
name String @unique
description String?
- userRoles UserRole[]
+ userRoles UserRole[]
+ permissions RolePermission[]
createdAt DateTime @default(now())
@@map("roles")
}
+// 역할별 권한 매핑 (리소스×액션)
+model RolePermission {
+ id String @id @default(cuid())
+ roleId String
+ resource Resource
+ action Action
+ allowed Boolean @default(true)
+ createdAt DateTime @default(now())
+
+ role Role @relation(fields: [roleId], references: [roleId], onDelete: Cascade)
+
+ @@unique([roleId, resource, action])
+ @@index([resource, action])
+ @@map("role_permissions")
+}
+
// 사용자-역할 매핑 (다대다)
model UserRole {
id String @id @default(cuid())
diff --git a/prisma/seed.js b/prisma/seed.js
index d4e05eb..66ffeef 100644
--- a/prisma/seed.js
+++ b/prisma/seed.js
@@ -15,6 +15,47 @@ async function upsertRoles() {
create: r,
});
}
+ // 기본 권한 매핑
+ const roleMap = {
+ admin: [
+ ["ADMIN", "ADMINISTER"],
+ ["BOARD", "MODERATE"],
+ ["POST", "CREATE"],
+ ["POST", "UPDATE"],
+ ["POST", "DELETE"],
+ ["COMMENT", "DELETE"],
+ ["USER", "UPDATE"],
+ ],
+ editor: [
+ ["BOARD", "MODERATE"],
+ ["POST", "UPDATE"],
+ ["POST", "DELETE"],
+ ["COMMENT", "DELETE"],
+ ],
+ user: [
+ ["POST", "CREATE"],
+ ["COMMENT", "CREATE"],
+ ["POST", "READ"],
+ ["COMMENT", "READ"],
+ ],
+ };
+ for (const [roleName, perms] of Object.entries(roleMap)) {
+ const role = await prisma.role.findUnique({ where: { name: roleName } });
+ if (!role) continue;
+ for (const [resource, action] of perms) {
+ await prisma.rolePermission.upsert({
+ where: {
+ roleId_resource_action: {
+ roleId: role.roleId,
+ resource,
+ action,
+ },
+ },
+ update: { allowed: true },
+ create: { roleId: role.roleId, resource, action, allowed: true },
+ });
+ }
+ }
}
async function upsertAdmin() {
diff --git a/public/erd.svg b/public/erd.svg
index 30f01db..8541e7b 100644
--- a/public/erd.svg
+++ b/public/erd.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file