- Upgrade TypeScript 5.3.3 → 5.9.3 - Upgrade @types/node to 25.0.3 (all workspaces) - Upgrade Prisma 5.22.0 → 7.2.0 (BREAKING) - Upgrade @prisma/client 5.9.1 → 7.2.0 (BREAKING) BREAKING CHANGES: - Prisma 7 requires prisma.config.ts instead of url in datasource - Migrated to Neon adapter with @neondatabase/serverless - Added @prisma/adapter-neon for Prisma 7 compatibility - Removed url property from schema.prisma datasource blocks - Created prisma.config.ts for iam-service and _template All services tested and typecheck passes
673 lines
18 KiB
Plaintext
673 lines
18 KiB
Plaintext
// EN: Enterprise IAM Service Prisma Schema
|
|
// VI: Schema Prisma cho Enterprise IAM Service
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
binaryTargets = ["native", "linux-musl-openssl-3.0.x", "linux-musl-arm64-openssl-3.0.x"]
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
}
|
|
|
|
|
|
// EN: User model - Core user entity
|
|
// VI: Model User - Entity người dùng cốt lõi
|
|
model User {
|
|
id String @id @default(cuid())
|
|
email String @unique
|
|
username String? @unique
|
|
passwordHash String? // Nullable for social-only users
|
|
isActive Boolean @default(true)
|
|
emailVerified Boolean @default(false)
|
|
mfaEnabled Boolean @default(false)
|
|
mfaSecret String? // Encrypted TOTP secret
|
|
mfaBackupCodes String? @db.Text // Encrypted JSON array of backup codes
|
|
lastLoginAt DateTime?
|
|
loginCount Int @default(0)
|
|
failedLoginAttempts Int @default(0) // Track failed login attempts for lockout
|
|
lockedUntil DateTime? // Account lockout timestamp
|
|
organizationId String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// Existing Relations
|
|
userRoles UserRole[]
|
|
userPermissions UserPermission[]
|
|
sessions Session[]
|
|
refreshTokens RefreshToken[]
|
|
socialAccounts SocialAccount[]
|
|
mfaDevices MFADevice[]
|
|
authEvents AuthEvent[]
|
|
|
|
// New IAM Relations
|
|
organization Organization? @relation(fields: [organizationId], references: [id])
|
|
profile UserProfile?
|
|
verifications IdentityVerification[]
|
|
accessRequests AccessRequest[]
|
|
riskScores RiskScore[]
|
|
groupMembers GroupMember[]
|
|
|
|
@@index([email])
|
|
@@index([username])
|
|
@@index([createdAt])
|
|
@@index([organizationId])
|
|
@@map("users")
|
|
}
|
|
|
|
// EN: Role model - RBAC roles
|
|
// VI: Model Role - Vai trò RBAC
|
|
model Role {
|
|
id String @id @default(cuid())
|
|
name String @unique // ADMIN, MANAGER, USER, etc.
|
|
displayName String
|
|
description String?
|
|
isSystem Boolean @default(false) // Cannot be deleted
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// Relations
|
|
permissions RolePermission[]
|
|
userRoles UserRole[]
|
|
|
|
@@map("roles")
|
|
}
|
|
|
|
// EN: Permission model - Granular permissions
|
|
// VI: Model Permission - Quyền chi tiết
|
|
model Permission {
|
|
id String @id @default(cuid())
|
|
resource String // users, products, orders, etc.
|
|
action String // create, read, update, delete, etc.
|
|
scope String? // own, team, all
|
|
description String?
|
|
createdAt DateTime @default(now())
|
|
|
|
// Relations
|
|
roles RolePermission[]
|
|
users UserPermission[]
|
|
groups GroupPermission[]
|
|
|
|
@@unique([resource, action, scope])
|
|
@@index([resource])
|
|
@@index([resource, action])
|
|
@@map("permissions")
|
|
}
|
|
|
|
// EN: UserRole - Many-to-many relationship with expiration
|
|
// VI: UserRole - Quan hệ nhiều-nhiều với thời hạn
|
|
model UserRole {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
roleId String
|
|
grantedBy String? // ID of user who granted this role
|
|
expiresAt DateTime? // Temporary role assignment
|
|
createdAt DateTime @default(now())
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([userId, roleId])
|
|
@@index([userId])
|
|
@@index([roleId])
|
|
@@index([expiresAt])
|
|
@@map("user_roles")
|
|
}
|
|
|
|
// EN: RolePermission - Many-to-many relationship
|
|
// VI: RolePermission - Quan hệ nhiều-nhiều
|
|
model RolePermission {
|
|
id String @id @default(cuid())
|
|
roleId String
|
|
permissionId String
|
|
createdAt DateTime @default(now())
|
|
|
|
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([roleId, permissionId])
|
|
@@index([roleId])
|
|
@@map("role_permissions")
|
|
}
|
|
|
|
// EN: UserPermission - Direct user permissions (override roles)
|
|
// VI: UserPermission - Quyền trực tiếp của người dùng (ghi đè roles)
|
|
model UserPermission {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
permissionId String
|
|
granted Boolean @default(true) // false = deny permission
|
|
grantedBy String?
|
|
expiresAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([userId, permissionId])
|
|
@@index([userId])
|
|
@@index([expiresAt])
|
|
@@map("user_permissions")
|
|
}
|
|
|
|
// EN: Session model - Active user sessions
|
|
// VI: Model Session - Phiên người dùng đang hoạt động
|
|
model Session {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
deviceId String
|
|
deviceName String?
|
|
ipAddress String
|
|
userAgent String?
|
|
fingerprint String? // Device fingerprint
|
|
isActive Boolean @default(true)
|
|
expiresAt DateTime
|
|
createdAt DateTime @default(now())
|
|
lastActivityAt DateTime @default(now())
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@index([deviceId])
|
|
@@index([expiresAt])
|
|
@@index([isActive])
|
|
@@map("sessions")
|
|
}
|
|
|
|
// EN: RefreshToken model - Long-lived refresh tokens
|
|
// VI: Model RefreshToken - Refresh token sống lâu
|
|
model RefreshToken {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
token String @unique
|
|
family String? // Token family for rotation
|
|
deviceId String?
|
|
ipAddress String?
|
|
userAgent String?
|
|
expiresAt DateTime
|
|
revokedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@index([token])
|
|
@@index([family])
|
|
@@index([expiresAt])
|
|
@@map("refresh_tokens")
|
|
}
|
|
|
|
// EN: SocialAccount model - Social login accounts
|
|
// VI: Model SocialAccount - Tài khoản đăng nhập mạng xã hội
|
|
model SocialAccount {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
provider Provider // GOOGLE, FACEBOOK, GITHUB, APPLE
|
|
providerId String // ID from provider
|
|
email String?
|
|
name String?
|
|
avatar String?
|
|
accessToken String? @db.Text // Encrypted access token
|
|
refreshToken String? @db.Text // Encrypted refresh token
|
|
expiresAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([provider, providerId])
|
|
@@index([userId])
|
|
@@index([provider])
|
|
@@map("social_accounts")
|
|
}
|
|
|
|
enum Provider {
|
|
GOOGLE
|
|
FACEBOOK
|
|
GITHUB
|
|
APPLE
|
|
MICROSOFT
|
|
}
|
|
|
|
// EN: MFADevice model - Multi-factor authentication devices
|
|
// VI: Model MFADevice - Thiết bị xác thực đa yếu tố
|
|
model MFADevice {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
type MFAType // TOTP, WEBAUTHN
|
|
name String // Device name
|
|
secret String? // Encrypted TOTP secret
|
|
credentialId String? // For WebAuthn
|
|
publicKey String? @db.Text // For WebAuthn
|
|
counter Int? // For WebAuthn
|
|
isActive Boolean @default(true)
|
|
lastUsedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@index([credentialId])
|
|
@@map("mfa_devices")
|
|
}
|
|
|
|
enum MFAType {
|
|
TOTP
|
|
WEBAUTHN
|
|
}
|
|
|
|
// EN: AuthEvent model - Event sourcing for audit logs
|
|
// VI: Model AuthEvent - Event sourcing cho audit logs
|
|
model AuthEvent {
|
|
id String @id @default(cuid())
|
|
userId String?
|
|
eventType String // LOGIN, LOGOUT, MFA_ENABLED, PERMISSION_CHANGED, etc.
|
|
eventData Json
|
|
ipAddress String?
|
|
userAgent String?
|
|
success Boolean @default(true)
|
|
errorMessage String? @db.Text
|
|
timestamp DateTime @default(now())
|
|
|
|
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([userId, timestamp])
|
|
@@index([eventType, timestamp])
|
|
@@index([timestamp])
|
|
@@map("auth_events")
|
|
}
|
|
|
|
// EN: Feature model - Feature flags and toggles
|
|
// VI: Model Feature - Feature flags và toggles
|
|
model Feature {
|
|
id String @id @default(cuid())
|
|
name String @unique // Feature identifier
|
|
title String? // Human-readable title
|
|
description String? @db.Text // Feature description
|
|
config Json? // Feature configuration
|
|
enabled Boolean @default(true) // Feature toggle
|
|
version String @default("1.0.0") // Feature version
|
|
tags Json? // Feature tags for categorization
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([name])
|
|
@@index([enabled])
|
|
@@map("features")
|
|
}
|
|
|
|
// EN: Policy model - ABAC policies
|
|
// VI: Model Policy - Chính sách ABAC
|
|
model Policy {
|
|
id String @id @default(cuid())
|
|
name String @unique
|
|
description String?
|
|
resource String // Resource this policy applies to
|
|
condition Json // Policy condition (JSON logic)
|
|
effect String // ALLOW, DENY
|
|
priority Int @default(0) // Higher priority evaluated first
|
|
isActive Boolean @default(true)
|
|
organizationId String?
|
|
organization Organization? @relation(fields: [organizationId], references: [id])
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([resource])
|
|
@@index([isActive, priority])
|
|
@@index([organizationId])
|
|
@@map("policies")
|
|
}
|
|
|
|
// =============================================================================
|
|
// EN: Identity Management Models
|
|
// VI: Models Quản Lý Danh Tính
|
|
// =============================================================================
|
|
|
|
// EN: Organization model - Multi-tenant organization support
|
|
// VI: Model Organization - Hỗ trợ tổ chức multi-tenant
|
|
model Organization {
|
|
id String @id @default(cuid())
|
|
name String
|
|
domain String? @unique
|
|
parentId String?
|
|
settings Json?
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
users User[]
|
|
groups Group[]
|
|
policies Policy[]
|
|
parent Organization? @relation("OrganizationHierarchy", fields: [parentId], references: [id])
|
|
children Organization[] @relation("OrganizationHierarchy")
|
|
|
|
@@index([domain])
|
|
@@map("organizations")
|
|
}
|
|
|
|
// EN: Group model - Groups within organizations
|
|
// VI: Model Group - Nhóm trong tổ chức
|
|
model Group {
|
|
id String @id @default(cuid())
|
|
name String
|
|
organizationId String?
|
|
description String?
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
organization Organization? @relation(fields: [organizationId], references: [id])
|
|
members GroupMember[]
|
|
permissions GroupPermission[]
|
|
|
|
@@unique([organizationId, name])
|
|
@@index([organizationId])
|
|
@@map("groups")
|
|
}
|
|
|
|
// EN: GroupMember model - Members of a group
|
|
// VI: Model GroupMember - Thành viên của nhóm
|
|
model GroupMember {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
groupId String
|
|
role String @default("member") // member, admin
|
|
joinedAt DateTime @default(now())
|
|
expiresAt DateTime?
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([userId, groupId])
|
|
@@index([userId])
|
|
@@index([groupId])
|
|
@@map("group_members")
|
|
}
|
|
|
|
// EN: GroupPermission model - Permissions assigned to groups
|
|
// VI: Model GroupPermission - Quyền được gán cho nhóm
|
|
model GroupPermission {
|
|
id String @id @default(cuid())
|
|
groupId String
|
|
permissionId String
|
|
createdAt DateTime @default(now())
|
|
|
|
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
|
|
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([groupId, permissionId])
|
|
@@index([groupId])
|
|
@@map("group_permissions")
|
|
}
|
|
|
|
// EN: UserProfile model - Extended user profile information
|
|
// VI: Model UserProfile - Thông tin profile mở rộng của user
|
|
model UserProfile {
|
|
id String @id @default(cuid())
|
|
userId String @unique
|
|
firstName String?
|
|
lastName String?
|
|
phone String?
|
|
phoneVerified Boolean @default(false)
|
|
avatarUrl String?
|
|
customFields Json? // Extended attributes
|
|
preferences Json? // User preferences
|
|
metadata Json? // Additional metadata
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([phone])
|
|
@@map("user_profiles")
|
|
}
|
|
|
|
// EN: IdentityVerification model - Identity verification records
|
|
// VI: Model IdentityVerification - Hồ sơ xác thực danh tính
|
|
model IdentityVerification {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
type VerificationType
|
|
status VerificationStatus @default(PENDING)
|
|
method String?
|
|
token String? @unique // OTP token, verification code
|
|
verifiedAt DateTime?
|
|
expiresAt DateTime?
|
|
metadata Json? // Verification details
|
|
createdAt DateTime @default(now())
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId, type])
|
|
@@index([token])
|
|
@@index([status])
|
|
@@map("identity_verifications")
|
|
}
|
|
|
|
enum VerificationType {
|
|
EMAIL
|
|
PHONE
|
|
DOCUMENT
|
|
BIOMETRIC
|
|
}
|
|
|
|
enum VerificationStatus {
|
|
PENDING
|
|
VERIFIED
|
|
REJECTED
|
|
EXPIRED
|
|
}
|
|
|
|
// =============================================================================
|
|
// EN: Access Management Models
|
|
// VI: Models Quản Lý Truy Cập
|
|
// =============================================================================
|
|
|
|
// EN: AccessRequest model - Access requests and approvals
|
|
// VI: Model AccessRequest - Yêu cầu và phê duyệt truy cập
|
|
model AccessRequest {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
resource String
|
|
action String
|
|
reason String?
|
|
status RequestStatus @default(PENDING)
|
|
requestedAt DateTime @default(now())
|
|
reviewedAt DateTime?
|
|
reviewedBy String?
|
|
expiresAt DateTime?
|
|
metadata Json?
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
approvers AccessRequestApprover[]
|
|
|
|
@@index([userId])
|
|
@@index([status])
|
|
@@index([resource])
|
|
@@map("access_requests")
|
|
}
|
|
|
|
enum RequestStatus {
|
|
PENDING
|
|
APPROVED
|
|
REJECTED
|
|
EXPIRED
|
|
CANCELLED
|
|
}
|
|
|
|
// EN: AccessRequestApprover model - Approvers for access requests
|
|
// VI: Model AccessRequestApprover - Người phê duyệt yêu cầu truy cập
|
|
model AccessRequestApprover {
|
|
id String @id @default(cuid())
|
|
requestId String
|
|
approverId String
|
|
status ApprovalStatus @default(PENDING)
|
|
comments String?
|
|
reviewedAt DateTime?
|
|
|
|
request AccessRequest @relation(fields: [requestId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([requestId, approverId])
|
|
@@index([approverId])
|
|
@@map("access_request_approvers")
|
|
}
|
|
|
|
enum ApprovalStatus {
|
|
PENDING
|
|
APPROVED
|
|
REJECTED
|
|
}
|
|
|
|
// EN: AccessReview model - Periodic access reviews
|
|
// VI: Model AccessReview - Đánh giá truy cập định kỳ
|
|
model AccessReview {
|
|
id String @id @default(cuid())
|
|
name String
|
|
description String?
|
|
type ReviewType
|
|
status ReviewStatus @default(DRAFT)
|
|
startDate DateTime
|
|
endDate DateTime
|
|
createdBy String
|
|
createdAt DateTime @default(now())
|
|
completedAt DateTime?
|
|
|
|
items AccessReviewItem[]
|
|
|
|
@@index([status])
|
|
@@index([type])
|
|
@@map("access_reviews")
|
|
}
|
|
|
|
enum ReviewType {
|
|
PERIODIC
|
|
ADHOC
|
|
CERTIFICATION
|
|
}
|
|
|
|
enum ReviewStatus {
|
|
DRAFT
|
|
ACTIVE
|
|
COMPLETED
|
|
CANCELLED
|
|
}
|
|
|
|
// EN: AccessReviewItem model - Individual items in an access review
|
|
// VI: Model AccessReviewItem - Item riêng lẻ trong đánh giá truy cập
|
|
model AccessReviewItem {
|
|
id String @id @default(cuid())
|
|
reviewId String
|
|
userId String
|
|
resource String
|
|
access Json // Current access details
|
|
status ReviewItemStatus @default(PENDING)
|
|
reviewedBy String?
|
|
reviewedAt DateTime?
|
|
comments String?
|
|
|
|
review AccessReview @relation(fields: [reviewId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([reviewId])
|
|
@@index([userId])
|
|
@@index([status])
|
|
@@map("access_review_items")
|
|
}
|
|
|
|
enum ReviewItemStatus {
|
|
PENDING
|
|
APPROVED
|
|
REVOKED
|
|
NO_CHANGE
|
|
}
|
|
|
|
// =============================================================================
|
|
// EN: Governance Models
|
|
// VI: Models Quản Trị
|
|
// =============================================================================
|
|
|
|
// EN: ComplianceReport model - Compliance reporting
|
|
// VI: Model ComplianceReport - Báo cáo tuân thủ
|
|
model ComplianceReport {
|
|
id String @id @default(cuid())
|
|
type ComplianceType
|
|
name String
|
|
periodStart DateTime
|
|
periodEnd DateTime
|
|
status ReportStatus @default(DRAFT)
|
|
data Json?
|
|
generatedAt DateTime?
|
|
generatedBy String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([type])
|
|
@@index([status])
|
|
@@map("compliance_reports")
|
|
}
|
|
|
|
enum ComplianceType {
|
|
GDPR
|
|
SOC2
|
|
ISO27001
|
|
HIPAA
|
|
CUSTOM
|
|
}
|
|
|
|
enum ReportStatus {
|
|
DRAFT
|
|
GENERATED
|
|
PUBLISHED
|
|
ARCHIVED
|
|
}
|
|
|
|
// EN: PolicyTemplate model - Policy templates for governance
|
|
// VI: Model PolicyTemplate - Template cho policies trong quản trị
|
|
model PolicyTemplate {
|
|
id String @id @default(cuid())
|
|
name String
|
|
category PolicyCategory
|
|
description String?
|
|
content Json // Policy template structure
|
|
version String @default("1.0.0")
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([category])
|
|
@@index([isActive])
|
|
@@map("policy_templates")
|
|
}
|
|
|
|
enum PolicyCategory {
|
|
SECURITY
|
|
ACCESS
|
|
COMPLIANCE
|
|
DATA
|
|
PRIVACY
|
|
}
|
|
|
|
// EN: RiskScore model - User risk scoring
|
|
// VI: Model RiskScore - Điểm rủi ro của user
|
|
model RiskScore {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
score Int // 0-100
|
|
level RiskLevel
|
|
factors Json // Risk factors
|
|
calculatedAt DateTime @default(now())
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@index([score])
|
|
@@index([level])
|
|
@@map("risk_scores")
|
|
}
|
|
|
|
enum RiskLevel {
|
|
LOW
|
|
MEDIUM
|
|
HIGH
|
|
CRITICAL
|
|
}
|