Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
297 lines
10 KiB
Markdown
297 lines
10 KiB
Markdown
# Tài liệu Tham chiếu Nhanh cho Ghi nhật ký Kiểm toán Module Admin
|
|
|
|
## ĐỌC TRƯỚC (tổng cộng 15 phút)
|
|
|
|
### 1. Các Controller Chính (Xác định những hành động cần kiểm toán)
|
|
- ✅ `apps/api/src/modules/admin/presentation/controllers/admin.controller.ts` (155 dòng)
|
|
- Quản lý người dùng: cấm, cập nhật trạng thái, điều chỉnh gói đăng ký
|
|
- Tất cả các endpoint đều có decorator @CurrentUser() để ghi lại ID admin
|
|
|
|
- ✅ `apps/api/src/modules/admin/presentation/controllers/admin-moderation.controller.ts` (157 dòng)
|
|
- Duyệt/từ chối tin đăng
|
|
- Duyệt/từ chối KYC
|
|
- Kiểm duyệt hàng loạt
|
|
|
|
### 2. Các Command Handler (Nơi để gắn ghi nhật ký kiểm toán)
|
|
Mỗi command phát ra một sự kiện domain. Listener ghi nhật ký kiểm toán nên lắng nghe các sự kiện này.
|
|
|
|
**Luồng Cấm Người Dùng:**
|
|
- Đầu vào: `apps/api/src/modules/admin/presentation/dto/ban-user.dto.ts`
|
|
- Command: `apps/api/src/modules/admin/application/commands/ban-user/ban-user.command.ts`
|
|
- Handler: `apps/api/src/modules/admin/application/commands/ban-user/ban-user.handler.ts` (70 dòng)
|
|
- Dòng 62: `this.eventBus.publish(new UserBannedEvent(...))`
|
|
|
|
**Luồng Duyệt Tin Đăng:**
|
|
- Đầu vào: `apps/api/src/modules/admin/presentation/dto/approve-listing.dto.ts`
|
|
- Command: `apps/api/src/modules/admin/application/commands/approve-listing/approve-listing.command.ts`
|
|
- Handler: `apps/api/src/modules/admin/application/commands/approve-listing/approve-listing.handler.ts` (52 dòng)
|
|
- Dòng 42-44: `this.eventBus.publish(new ListingApprovedEvent(...))`
|
|
|
|
### 3. Các Sự kiện Domain (Thông tin được phát ra)
|
|
```
|
|
apps/api/src/modules/admin/domain/events/
|
|
├── user-banned.event.ts
|
|
├── user-unbanned.event.ts
|
|
├── listing-approved.event.ts
|
|
├── listing-rejected.event.ts
|
|
├── subscription-adjusted.event.ts
|
|
├── kyc-approved.event.ts
|
|
└── kyc-rejected.event.ts
|
|
```
|
|
|
|
Mỗi sự kiện có:
|
|
- `eventName` (ví dụ: 'user.banned')
|
|
- `occurredAt` (dấu thời gian)
|
|
- `aggregateId` (userId hoặc listingId)
|
|
- `adminId` (admin đã thực hiện hành động)
|
|
- Ngữ cảnh bổ sung (lý do, ghi chú, v.v.)
|
|
|
|
### 4. Mẫu Event Listener Hiện có (Template)
|
|
- ✅ `apps/api/src/modules/admin/application/listeners/user-banned.listener.ts` (52 dòng)
|
|
- Minh hoạ decorator @OnEvent()
|
|
- Minh hoạ cách truy cập dữ liệu sự kiện
|
|
- Minh hoạ các hiệu ứng phụ (vô hiệu hoá tin đăng, gửi thông báo)
|
|
- **ĐÂY LÀ TEMPLATE CHO AUDIT LOGGING LISTENER CỦA BẠN**
|
|
|
|
### 5. Logger Service (Nơi ghi log)
|
|
- ✅ `apps/api/src/modules/shared/infrastructure/logger.service.ts` (65 dòng)
|
|
- Ghi log có cấu trúc dựa trên Pino
|
|
- Tự động che giấu thông tin PII
|
|
- Các phương thức: log(), error(), warn(), debug(), verbose()
|
|
|
|
### 6. Exception Filter (Để ghi log lỗi)
|
|
- ✅ `apps/api/src/modules/shared/infrastructure/filters/global-exception.filter.ts` (145 dòng)
|
|
- Bắt tất cả các ngoại lệ
|
|
- Ghi log kèm correlationId
|
|
- Có thể ghi lại các hành động admin thất bại
|
|
|
|
---
|
|
|
|
## THAM CHIẾU KIẾN TRÚC
|
|
|
|
### Mẫu Repository
|
|
- Giao diện Domain: `apps/api/src/modules/admin/domain/repositories/admin-query.repository.ts`
|
|
- Triển khai Prisma: `apps/api/src/modules/admin/infrastructure/repositories/prisma-admin-query.repository.ts`
|
|
- **TUÂN THEO MẪU NÀY** cho AuditLog repository
|
|
|
|
### Khởi tạo Module
|
|
- `apps/api/src/modules/admin/admin.module.ts` (64 dòng)
|
|
- Minh hoạ cách đăng ký repository qua DI
|
|
- Minh hoạ cách đăng ký listener
|
|
- Minh hoạ cách import CQRS module
|
|
|
|
### Cấu hình App Toàn cục
|
|
- `apps/api/src/app.module.ts` (100+ dòng)
|
|
- Minh hoạ đăng ký APP_FILTER, APP_GUARD, APP_INTERCEPTOR
|
|
- Minh hoạ cấu hình CqrsModule.forRoot()
|
|
- Minh hoạ cấu hình middleware
|
|
|
|
---
|
|
|
|
## PRISMA SCHEMA
|
|
|
|
### Các Model Hiện tại (Những gì chúng ta đang kiểm toán)
|
|
- `prisma/schema.prisma` (602 dòng tổng cộng)
|
|
|
|
**User Model** (dòng 34-71):
|
|
- Các trường cần kiểm toán: isActive, kycStatus, role
|
|
|
|
**Listing Model** (dòng 227-276):
|
|
- Các trường cần kiểm toán: status, moderationScore, moderationNotes
|
|
|
|
**CHƯA CÓ AUDIT MODEL** - Cơ hội để tạo từ đầu
|
|
|
|
---
|
|
|
|
## CÁC ENDPOINT CẦN KIỂM TOÁN (Từ Controllers)
|
|
|
|
### Hành động của AdminController:
|
|
1. `PATCH /admin/users/status` - Cập nhật trạng thái hoạt động của người dùng
|
|
2. `POST /admin/users/ban` - Cấm/bỏ cấm người dùng
|
|
3. `POST /admin/subscriptions/adjust` - Điều chỉnh gói đăng ký
|
|
|
|
### Hành động của AdminModerationController:
|
|
1. `POST /admin/moderation/approve` - Duyệt tin đăng
|
|
2. `POST /admin/moderation/reject` - Từ chối tin đăng
|
|
3. `POST /admin/moderation/bulk` - Kiểm duyệt hàng loạt tin đăng
|
|
4. `POST /admin/kyc/approve` - Duyệt KYC
|
|
5. `POST /admin/kyc/reject` - Từ chối KYC
|
|
|
|
Mỗi hành động:
|
|
- Đã ghi lại ID admin từ JWT
|
|
- Đã phát ra sự kiện domain
|
|
- Đã có command handler
|
|
- Cần: Audit logging listener để lưu vào cơ sở dữ liệu
|
|
|
|
---
|
|
|
|
## CÁC PHỤ THUỘC ĐÃ ĐƯỢC IMPORT
|
|
|
|
### Trong AdminModule:
|
|
```typescript
|
|
// Đã sẵn sàng:
|
|
- CqrsModule (from @nestjs/cqrs)
|
|
- AuthModule (auth guards/decorators)
|
|
- ListingsModule (for listing operations)
|
|
- SubscriptionsModule (for subscription operations)
|
|
|
|
// Trong providers:
|
|
- CommandHandlers (8 tổng cộng)
|
|
- QueryHandlers (6 tổng cộng)
|
|
- Event Listeners (2 hiện có + cần thêm AuditLoggingListener)
|
|
```
|
|
|
|
### Từ SharedModule:
|
|
- `PrismaService` (cơ sở dữ liệu)
|
|
- `LoggerService` (ghi log)
|
|
- Các loại ngoại lệ (NotFoundException, ValidationException, v.v.)
|
|
|
|
---
|
|
|
|
## DANH SÁCH KIỂM TRA TRIỂN KHAI
|
|
|
|
### Giai đoạn 1: Cơ sở dữ liệu & Repository
|
|
- [ ] Tạo AuditLog Prisma model trong schema.prisma
|
|
- [ ] Tạo interface IAuditLogRepository
|
|
- [ ] Tạo triển khai PrismaAuditLogRepository
|
|
- [ ] Thêm vào providers của AdminModule
|
|
|
|
### Giai đoạn 2: Events & Listeners
|
|
- [ ] Tạo AuditEvent domain event (nếu cần làm wrapper)
|
|
- [ ] Tạo AuditLoggingListener để @OnEvent() cho tất cả các sự kiện admin
|
|
- [ ] Inject AuditLogRepository vào listener
|
|
- [ ] Lưu bản ghi kiểm toán khi có sự kiện
|
|
|
|
### Giai đoạn 3: Query & API
|
|
- [ ] Tạo GetAuditLogsQuery
|
|
- [ ] Tạo GetAuditLogsHandler
|
|
- [ ] Tạo phương thức IAuditLogQueryRepository
|
|
- [ ] Thêm vào QueryHandlers trong module
|
|
|
|
### Giai đoạn 4: Endpoint Controller
|
|
- [ ] Thêm endpoint GET /admin/audit-logs
|
|
- [ ] Thêm các DTO lọc (dateRange, adminId, actionType, resourceId)
|
|
- [ ] Thêm hỗ trợ phân trang
|
|
|
|
### Giai đoạn 5: Kiểm thử
|
|
- [ ] Unit tests cho AuditLoggingListener
|
|
- [ ] Integration tests cho việc lưu kiểm toán
|
|
- [ ] E2E tests cho việc truy xuất nhật ký kiểm toán
|
|
|
|
---
|
|
|
|
## CÁC MẪU QUAN TRỌNG CẦN TUÂN THEO
|
|
|
|
### 1. Command Pattern (Đã được sử dụng)
|
|
```typescript
|
|
// DTO xác thực đầu vào
|
|
// Command đóng gói ý định nghiệp vụ
|
|
// Handler thực thi + phát sự kiện
|
|
// Event kích hoạt hiệu ứng phụ qua listener
|
|
```
|
|
|
|
### 2. Cấu trúc Tầng DDD
|
|
```
|
|
Presentation (xác thực DTO)
|
|
↓
|
|
Application (thực thi Command/Query + phát Event)
|
|
↓
|
|
Domain (định nghĩa Event, giao diện Repository)
|
|
↓
|
|
Infrastructure (triển khai cơ sở dữ liệu)
|
|
```
|
|
|
|
### 3. Dependency Injection
|
|
```typescript
|
|
// Luôn dùng Symbol cho token:
|
|
export const AUDIT_LOG_REPOSITORY = Symbol('AUDIT_LOG_REPOSITORY');
|
|
|
|
// Đăng ký trong module:
|
|
{ provide: AUDIT_LOG_REPOSITORY, useClass: PrismaAuditLogRepository }
|
|
|
|
// Inject vào service:
|
|
constructor(
|
|
@Inject(AUDIT_LOG_REPOSITORY) private readonly auditRepo: IAuditLogRepository,
|
|
) {}
|
|
```
|
|
|
|
### 4. Mẫu Event Listener
|
|
```typescript
|
|
@Injectable()
|
|
export class AuditLoggingListener {
|
|
constructor(
|
|
@Inject(AUDIT_LOG_REPOSITORY) private readonly auditRepo: IAuditLogRepository,
|
|
private readonly logger: LoggerService,
|
|
) {}
|
|
|
|
@OnEvent('user.banned', { async: true })
|
|
async handleUserBanned(event: UserBannedEvent): Promise<void> {
|
|
// Trích xuất dữ liệu từ sự kiện
|
|
// Lưu vào cơ sở dữ liệu
|
|
// Ghi log nếu thành công/thất bại
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## NƠI THÊM CODE
|
|
|
|
```
|
|
apps/api/src/modules/admin/
|
|
├── domain/
|
|
│ ├── events/
|
|
│ │ └── audit-logged.event.ts (MỚI - wrapper tuỳ chọn)
|
|
│ └── repositories/
|
|
│ ├── audit-log.repository.ts (MỚI - interface)
|
|
│ └── index.ts (cập nhật exports)
|
|
│
|
|
├── application/
|
|
│ ├── queries/
|
|
│ │ ├── get-audit-logs/ (MỚI)
|
|
│ │ │ ├── get-audit-logs.query.ts
|
|
│ │ │ └── get-audit-logs.handler.ts
|
|
│ │ └── index.ts (cập nhật exports)
|
|
│ │
|
|
│ └── listeners/
|
|
│ ├── audit-logging.listener.ts (MỚI)
|
|
│ └── index.ts (cập nhật nếu cần)
|
|
│
|
|
├── infrastructure/
|
|
│ └── repositories/
|
|
│ ├── prisma-audit-log.repository.ts (MỚI)
|
|
│ └── index.ts (cập nhật exports)
|
|
│
|
|
└── presentation/
|
|
├── controllers/
|
|
│ ├── admin.controller.ts (THÊM ENDPOINT)
|
|
│ └── admin-moderation.controller.ts (CẬP NHẬT nếu cần)
|
|
│
|
|
└── dto/
|
|
├── get-audit-logs-query.dto.ts (MỚI)
|
|
└── index.ts (cập nhật exports)
|
|
|
|
prisma/
|
|
└── schema.prisma (THÊM AuditLog MODEL)
|
|
```
|
|
|
|
---
|
|
|
|
## CÁC SỰ KIỆN CẦN LẮNG NGHE
|
|
|
|
1. 'user.banned' - từ UserBannedEvent
|
|
2. 'user.unbanned' - từ UserUnbannedEvent
|
|
3. 'listing.approved' - từ ListingApprovedEvent
|
|
4. 'listing.rejected' - từ ListingRejectedEvent
|
|
5. 'kyc.approved' - từ KycApprovedEvent
|
|
6. 'kyc.rejected' - từ KycRejectedEvent
|
|
7. 'subscription.adjusted' - từ SubscriptionAdjustedEvent
|
|
8. 'user.deactivated' - (nếu tồn tại trong auth module)
|
|
|
|
Mỗi sự kiện được ghi lại kèm:
|
|
- ID Admin (từ sự kiện)
|
|
- ID Tài nguyên (aggregateId từ sự kiện)
|
|
- Loại Tài nguyên (suy ra từ eventName)
|
|
- Dấu thời gian (từ event.occurredAt)
|
|
- Ngữ cảnh bổ sung (lý do, ghi chú, v.v.)
|