feat(rbac): implement full admin management, dynamic roles, permissions matrix, and workspace access control
- Add Workspace, Role, Permission, RolePermission, AdminRoleAssignment, and AdminWorkspaceAssignment models to Prisma schema\n- Create database migration and RBAC seed script\n- Implement PermissionsGuard, @RequirePermission decorator, and real-time permission resolution in JwtAdminStrategy\n- Implement AdminManagementModule with endpoints for managers CRUD, roles matrix, permissions catalog, and workspaces\n- Secure all sensitive admin controllers with granular permission requirements\n- Add useAuthStore helpers (can, canAny, fetchMe) and v-permission directive\n- Implement Desktop views: AdminListView, AdminFormDrawer (RTL right-side), RoleMatrixView, WorkspaceListView, and ForbiddenView\n- Implement Mobile views: MAdminListView, MAdminFormView (stepped mobile form), MRoleMatrixView, MWorkspaceListView, and MForbiddenView\n- Fix sticky header behavior across desktop and mobile shells\n- Update route guards and device detection logic for mobile prefixing
This commit is contained in:
@@ -21,6 +21,11 @@ enum AdminRole {
|
||||
SUPPORT
|
||||
}
|
||||
|
||||
enum AccessScopeType {
|
||||
ALL
|
||||
CUSTOM_CAMPAIGNS
|
||||
}
|
||||
|
||||
enum UserStatus {
|
||||
ACTIVE
|
||||
BLOCKED
|
||||
@@ -111,11 +116,15 @@ model Admin {
|
||||
passwordHash String @map("password_hash")
|
||||
role AdminRole @default(OPERATOR)
|
||||
status AdminStatus @default(ACTIVE)
|
||||
isSuperAdmin Boolean @default(false) @map("is_super_admin")
|
||||
lastLoginAt DateTime? @map("last_login_at")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
auditLogs AdminLog[]
|
||||
chanceTxns ChanceTransaction[] @relation("AdminCreatedTxn")
|
||||
auditLogs AdminLog[]
|
||||
chanceTxns ChanceTransaction[] @relation("AdminCreatedTxn")
|
||||
roles AdminRoleAssignment[]
|
||||
workspaceAssignments AdminWorkspaceAssignment[]
|
||||
|
||||
@@map("admins")
|
||||
}
|
||||
@@ -171,6 +180,8 @@ model Campaign {
|
||||
ctaText String? @map("cta_text")
|
||||
wheelDesign WheelDesign @default(CLASSIC_CASINO) @map("wheel_design")
|
||||
settings Json? // primaryColor, secondaryColor, headerText, buttonText, headerImage, celebrationEffect...
|
||||
workspaceId String? @map("workspace_id")
|
||||
workspace Workspace? @relation(fields: [workspaceId], references: [id])
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@ -181,6 +192,7 @@ model Campaign {
|
||||
userPrizes UserPrize[]
|
||||
|
||||
@@index([status, startAt, endAt])
|
||||
@@index([workspaceId])
|
||||
@@map("campaigns")
|
||||
}
|
||||
|
||||
@@ -317,3 +329,84 @@ model AdminLog {
|
||||
@@index([entityType, entityId])
|
||||
@@map("admin_logs")
|
||||
}
|
||||
|
||||
// ==================== WORKSPACE & RBAC MODELS ====================
|
||||
|
||||
model Workspace {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
description String?
|
||||
status String @default("ACTIVE")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
campaigns Campaign[]
|
||||
adminAssignments AdminWorkspaceAssignment[]
|
||||
|
||||
@@map("workspaces")
|
||||
}
|
||||
|
||||
model Role {
|
||||
id String @id @default(uuid())
|
||||
code String @unique // e.g. "SUPER_ADMIN", "OPERATOR", "SUPPORT"
|
||||
name String // نام فارسی
|
||||
description String?
|
||||
isSystem Boolean @default(false) @map("is_system")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
permissions RolePermission[]
|
||||
admins AdminRoleAssignment[]
|
||||
|
||||
@@map("roles")
|
||||
}
|
||||
|
||||
model Permission {
|
||||
id String @id @default(uuid())
|
||||
code String @unique // e.g. "campaigns:read", "campaigns:create"
|
||||
module String // e.g. "campaigns", "users", "prizes", "reports", "admins"
|
||||
name String // نام فارسی
|
||||
description String?
|
||||
|
||||
roles RolePermission[]
|
||||
|
||||
@@index([module])
|
||||
@@map("permissions")
|
||||
}
|
||||
|
||||
model RolePermission {
|
||||
roleId String @map("role_id")
|
||||
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
||||
permissionId String @map("permission_id")
|
||||
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([roleId, permissionId])
|
||||
@@map("role_permissions")
|
||||
}
|
||||
|
||||
model AdminRoleAssignment {
|
||||
id String @id @default(uuid())
|
||||
adminId String @map("admin_id")
|
||||
admin Admin @relation(fields: [adminId], references: [id], onDelete: Cascade)
|
||||
roleId String @map("role_id")
|
||||
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
||||
assignedAt DateTime @default(now()) @map("assigned_at")
|
||||
|
||||
@@unique([adminId, roleId])
|
||||
@@map("admin_role_assignments")
|
||||
}
|
||||
|
||||
model AdminWorkspaceAssignment {
|
||||
id String @id @default(uuid())
|
||||
adminId String @map("admin_id")
|
||||
admin Admin @relation(fields: [adminId], references: [id], onDelete: Cascade)
|
||||
workspaceId String @map("workspace_id")
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
scopeType AccessScopeType @default(ALL) @map("scope_type")
|
||||
specificCampaignIds Json? @map("specific_campaign_ids")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@unique([adminId, workspaceId])
|
||||
@@map("admin_workspace_assignments")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user