Files
pos-system/services/iam-service/prisma/schema.prisma
Ho Ngoc Hai 935c253c7e feat: upgrade Phase 1 dependencies to latest versions
- 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
2026-01-07 17:20:34 +07:00

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
}