Skip to content

Quản lý Người dùng v1.0.0

Mã nguồn: src/services/user.service.ts

Mô hình dữ liệu

Cách dùng PolicyDefinition

Mục đíchvariantsubjectTypetargetType
Gán role cho usergroupUserRole
Map user với organizergroupUserOrganizer
Map user với merchantgroupUserMerchant
Cấp permission cho rolepolicyRolePermission
Cấp permission cho userpolicyUserPermission

PolicyDefinition thay thế các bảng cũ UserRoleUserMapping bằng một mô hình liên kết duy nhất theo phong cách Casbin.

Phụ thuộc của UserService

Phụ thuộcMục đích
JWKSIssuerTokenServiceCác thao tác với JWT token
UserConfigurationServiceCấu hình mặc định sau khi tạo
UserRepositoryCRUD và transaction cho User
UserCredentialRepositoryLưu trữ mật khẩu
UserIdentifierRepositoryKiểm tra trùng lặp identifier + CRUD
UserProfileRepositoryCRUD cho profile
PolicyDefinitionRepositoryGán role/organizer/merchant

Luồng tạo User

Xác thực Identifier khi tạo

SchemeverifiedCó thể đăng nhập ngay
USERNAMEtrue
EMAILfalseKhông — cần xác thực
PHONE_NUMBERfalseKhông — cần xác thực

Xử lý Credential

  • Nếu có credential → được hash bằng Bun.password.hash() (Argon2id), lưu với scheme BASIC
  • Nếu credential không được cung cấp → bỏ qua bước này hoàn toàn (ví dụ: khách hàng không cần đăng nhập)

Luồng cập nhật User

Cập nhật được thực hiện theo transaction với các thao tác con chạy song song:

Logic cập nhật Identifier

Hành độngChi tiết
ThêmIdentifier mới chưa có trong DB → tạo mới với verified: false
XóaIdentifier có trong DB nhưng không có trong request → soft-delete
UsernameKhông cập nhật được qua phương thức này

Logic cập nhật Role

So sánh diff với các bản ghi PolicyDefinition:

  1. Lấy các policy GROUP (USER→ROLE) hiện tại
  2. Thêm: roleIds có trong request nhưng không có trong DB → tạo policy mới
  3. Xóa: policy có trong DB nhưng roleId không có trong request → soft-delete

Quản lý Employee

Mã nguồn: src/services/employee.service.ts

Tạo Employee

Kiểm traNội dungLỗi
Quyền truy cập organizerCurrentUser có PolicyDef map tới organizerId403
Quyền sở hữu merchantTất cả merchantIds thuộc về organizer403

Cập nhật Employee

  • Ủy quyền các trường thuộc user cho UserService.updateById()
  • Mapping merchant: chiến lược xóa hết rồi tạo lại thông qua PolicyDefinitionRepository

Schema Request

CreateEmployeeRequest = CreateUserRequest + { organizerId, merchantIds[] }

UpdateByIdEmployeeRequest = UpdateByIdUserRequest + { merchantIds[]? } (tất cả đều partial)

Phân quyền tại Employee Controller

Tất cả thao tác được giới hạn phạm vi qua UserRepository.findIdsByPoliciesForCurrentUser():

MethodPhạm vi
find / count / findOneLọc theo employee IDs đã giới hạn theo policy + tham số organizerId/merchantIds tùy chọn
findById / deleteByIdKiểm tra ID có nằm trong tập đã giới hạn theo policy
createXác thực quyền sở hữu organizer trong EmployeeService
updateByIdXác thực quyền sở hữu organizer trong EmployeeService

User Controller

RouteMethodMô tả
/usersGETDanh sách users (phân trang)
/users/:idGETLấy theo ID
/usersPOSTTạo → UserService.create()
/users/:idPATCHCập nhật → UserService.updateById()
/users/:idDELETESoft-delete
/users/countGETĐếm số lượng
/users/profileGETProfile của user hiện tại
/users/profilePATCHCập nhật profile của user hiện tại

Schema Request

CreateUserRequest

TrườngKiểuBắt buộcValidation
usernamestringKhông4–80 ký tự
credentialstringKhông4–80 ký tự, PASSWORD_PATTERN
emailsstring[]tối thiểu 1, email hợp lệ
phonesstring[]tối thiểu 1, định dạng E.164
statusenumACTIVATED · DEACTIVATED · BLOCKED · UNKNOWN · ARCHIVED
profileobjectfirstName, lastName, birthday?, locale?
roleIdsstring[]tối thiểu 1

UpdateByIdUserRequest (tất cả các trường đều .partial())

TrườngKiểuValidation
emailsstring[]tối thiểu 1 nếu cung cấp
phonesstring[]tối thiểu 1 nếu cung cấp
statusenumtùy chọn
profileobjectcập nhật một phần
roleIdsstring[]tối thiểu 1 nếu cung cấp

UpdateUserProfileRequest (cho PATCH /profile)

TrườngKiểu
emailsstring[]?
phonesstring[]?
statusenum?
profile{ firstName?, lastName?, birthday?, locale?, metadata? }

UserConfiguration Service

Mã nguồn: src/services/user-configuration.service.ts

Được gọi trong _postCreate() sau khi tạo user:

UserConfiguration Controller

MethodPathMô tả
CRUD/user-configurationsCác thao tác chuẩn
POST/user-configurations/viewsTạo config từ template (kiểm tra trùng code/name theo từng user)

Repositories

UserRepository

typescript
findIdsByPoliciesForCurrentUser(opts: {
  currentUserId: string;
  organizerId?: string;
  merchantIds?: string[];
  roleIdentifiers?: string[];
  transaction?: ITransaction;
}): Promise<string[]>

Logic SQL: PolicyDefinition (currentUser → Organizer) → JOIN PolicyDefinition (các user khác → cùng Organizer), tùy chọn lọc theo merchant/role → trả về danh sách User IDs distinct.

UserIdentifierRepository

typescript
validateIdentifierUniqueness(opts: {
  identifiers: string[];
  scheme?: string;
  userId?: string;  // exclude own identifiers during update
  transaction?: ITransaction;
}): Promise<void>  // throws if duplicates found

Trang liên quan

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.