chore(docs): consolidate 22 audit files from root into docs/audits/
Root directory had accumulated audit/exploration markdown files cluttering the project root. Moved all audit-related files to docs/audits/ with a README.md index, and updated cross-references in K6_LOAD_TESTING_GUIDE.md and README_FRONTEND_DOCS.md. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
297
docs/audits/ADMIN_AUDIT_QUICK_FILES.md
Normal file
297
docs/audits/ADMIN_AUDIT_QUICK_FILES.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# Quick File Reference for Admin Module Audit Logging
|
||||
|
||||
## MUST READ FIRST (15 min total)
|
||||
|
||||
### 1. Main Controllers (Define what actions need audit)
|
||||
- ✅ `apps/api/src/modules/admin/presentation/controllers/admin.controller.ts` (155 lines)
|
||||
- User management: ban, update status, adjust subscription
|
||||
- All endpoints have @CurrentUser() decorator to capture admin ID
|
||||
|
||||
- ✅ `apps/api/src/modules/admin/presentation/controllers/admin-moderation.controller.ts` (157 lines)
|
||||
- Listing approval/rejection
|
||||
- KYC approval/rejection
|
||||
- Bulk moderation
|
||||
|
||||
### 2. Command Handlers (Where to hook audit logging)
|
||||
Each command publishes a domain event. Audit logging listener should listen to these events.
|
||||
|
||||
**Ban User Flow:**
|
||||
- Input: `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 lines)
|
||||
- Line 62: `this.eventBus.publish(new UserBannedEvent(...))`
|
||||
|
||||
**Approve Listing Flow:**
|
||||
- Input: `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 lines)
|
||||
- Line 42-44: `this.eventBus.publish(new ListingApprovedEvent(...))`
|
||||
|
||||
### 3. Domain Events (What information is published)
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
Each event has:
|
||||
- `eventName` (e.g., 'user.banned')
|
||||
- `occurredAt` (timestamp)
|
||||
- `aggregateId` (userId or listingId)
|
||||
- `adminId` (the admin who performed the action)
|
||||
- Additional context (reason, notes, etc.)
|
||||
|
||||
### 4. Existing Event Listener Pattern (Template)
|
||||
- ✅ `apps/api/src/modules/admin/application/listeners/user-banned.listener.ts` (52 lines)
|
||||
- Shows @OnEvent() decorator
|
||||
- Shows how to access event data
|
||||
- Shows side effects (deactivate listings, send notification)
|
||||
- **THIS IS YOUR TEMPLATE FOR AUDIT LOGGING LISTENER**
|
||||
|
||||
### 5. Logger Service (Where to log)
|
||||
- ✅ `apps/api/src/modules/shared/infrastructure/logger.service.ts` (65 lines)
|
||||
- Pino-based structured logging
|
||||
- Auto PII redaction
|
||||
- Methods: log(), error(), warn(), debug(), verbose()
|
||||
|
||||
### 6. Exception Filter (For error logging)
|
||||
- ✅ `apps/api/src/modules/shared/infrastructure/filters/global-exception.filter.ts` (145 lines)
|
||||
- Catches all exceptions
|
||||
- Logs with correlationId
|
||||
- Could capture failed admin actions
|
||||
|
||||
---
|
||||
|
||||
## ARCHITECTURE REFERENCES
|
||||
|
||||
### Repository Pattern
|
||||
- Domain Interface: `apps/api/src/modules/admin/domain/repositories/admin-query.repository.ts`
|
||||
- Prisma Implementation: `apps/api/src/modules/admin/infrastructure/repositories/prisma-admin-query.repository.ts`
|
||||
- **FOLLOW THIS PATTERN** for AuditLog repository
|
||||
|
||||
### Module Bootstrap
|
||||
- `apps/api/src/modules/admin/admin.module.ts` (64 lines)
|
||||
- Shows how to register repositories via DI
|
||||
- Shows how to register listeners
|
||||
- Shows how to import CQRS module
|
||||
|
||||
### Global App Setup
|
||||
- `apps/api/src/app.module.ts` (100+ lines)
|
||||
- Shows APP_FILTER, APP_GUARD, APP_INTERCEPTOR registration
|
||||
- Shows CqrsModule.forRoot() setup
|
||||
- Shows middleware configuration
|
||||
|
||||
---
|
||||
|
||||
## PRISMA SCHEMA
|
||||
|
||||
### Current Models (What we're auditing)
|
||||
- `prisma/schema.prisma` (602 lines total)
|
||||
|
||||
**User Model** (lines 34-71):
|
||||
- Fields to audit: isActive, kycStatus, role
|
||||
|
||||
**Listing Model** (lines 227-276):
|
||||
- Fields to audit: status, moderationScore, moderationNotes
|
||||
|
||||
**NO AUDIT MODEL YET** - Opportunity to create from scratch
|
||||
|
||||
---
|
||||
|
||||
## EXACT ENDPOINTS TO AUDIT (From Controllers)
|
||||
|
||||
### AdminController Actions:
|
||||
1. `PATCH /admin/users/status` - Update user active status
|
||||
2. `POST /admin/users/ban` - Ban/unban user
|
||||
3. `POST /admin/subscriptions/adjust` - Adjust subscription
|
||||
|
||||
### AdminModerationController Actions:
|
||||
1. `POST /admin/moderation/approve` - Approve listing
|
||||
2. `POST /admin/moderation/reject` - Reject listing
|
||||
3. `POST /admin/moderation/bulk` - Bulk moderate listings
|
||||
4. `POST /admin/kyc/approve` - Approve KYC
|
||||
5. `POST /admin/kyc/reject` - Reject KYC
|
||||
|
||||
Each action:
|
||||
- Already captures admin ID from JWT
|
||||
- Already publishes a domain event
|
||||
- Already has a command handler
|
||||
- Needs: Audit logging listener to capture to database
|
||||
|
||||
---
|
||||
|
||||
## DEPENDENCIES ALREADY IMPORTED
|
||||
|
||||
### In AdminModule:
|
||||
```typescript
|
||||
// Already available:
|
||||
- CqrsModule (from @nestjs/cqrs)
|
||||
- AuthModule (auth guards/decorators)
|
||||
- ListingsModule (for listing operations)
|
||||
- SubscriptionsModule (for subscription operations)
|
||||
|
||||
// In providers:
|
||||
- CommandHandlers (8 total)
|
||||
- QueryHandlers (6 total)
|
||||
- Event Listeners (2 existing + need to add AuditLoggingListener)
|
||||
```
|
||||
|
||||
### From SharedModule:
|
||||
- `PrismaService` (database)
|
||||
- `LoggerService` (logging)
|
||||
- Exception types (NotFoundException, ValidationException, etc.)
|
||||
|
||||
---
|
||||
|
||||
## IMPLEMENTATION CHECKLIST
|
||||
|
||||
### Phase 1: Database & Repository
|
||||
- [ ] Create AuditLog Prisma model in schema.prisma
|
||||
- [ ] Create IAuditLogRepository interface
|
||||
- [ ] Create PrismaAuditLogRepository implementation
|
||||
- [ ] Add to AdminModule providers
|
||||
|
||||
### Phase 2: Events & Listeners
|
||||
- [ ] Create AuditEvent domain event (if needed as wrapper)
|
||||
- [ ] Create AuditLoggingListener to @OnEvent() for all admin events
|
||||
- [ ] Inject AuditLogRepository into listener
|
||||
- [ ] Persist audit records on event
|
||||
|
||||
### Phase 3: Query & API
|
||||
- [ ] Create GetAuditLogsQuery
|
||||
- [ ] Create GetAuditLogsHandler
|
||||
- [ ] Create IAuditLogQueryRepository method
|
||||
- [ ] Add to QueryHandlers in module
|
||||
|
||||
### Phase 4: Controller Endpoint
|
||||
- [ ] Add GET /admin/audit-logs endpoint
|
||||
- [ ] Add filtering DTOs (dateRange, adminId, actionType, resourceId)
|
||||
- [ ] Add pagination support
|
||||
|
||||
### Phase 5: Testing
|
||||
- [ ] Unit tests for AuditLoggingListener
|
||||
- [ ] Integration tests for audit persistence
|
||||
- [ ] E2E tests for audit log retrieval
|
||||
|
||||
---
|
||||
|
||||
## CRITICAL PATTERNS TO FOLLOW
|
||||
|
||||
### 1. Command Pattern (Already Used)
|
||||
```typescript
|
||||
// DTOs validate input
|
||||
// Commands encapsulate business intent
|
||||
// Handlers execute + publish events
|
||||
// Events trigger side effects via listeners
|
||||
```
|
||||
|
||||
### 2. DDD Layer Structure
|
||||
```
|
||||
Presentation (DTO validation)
|
||||
↓
|
||||
Application (Command/Query execution + Event publishing)
|
||||
↓
|
||||
Domain (Event definitions, Repository interfaces)
|
||||
↓
|
||||
Infrastructure (Database implementation)
|
||||
```
|
||||
|
||||
### 3. Dependency Injection
|
||||
```typescript
|
||||
// Always use Symbol for tokens:
|
||||
export const AUDIT_LOG_REPOSITORY = Symbol('AUDIT_LOG_REPOSITORY');
|
||||
|
||||
// Register in module:
|
||||
{ provide: AUDIT_LOG_REPOSITORY, useClass: PrismaAuditLogRepository }
|
||||
|
||||
// Inject in service:
|
||||
constructor(
|
||||
@Inject(AUDIT_LOG_REPOSITORY) private readonly auditRepo: IAuditLogRepository,
|
||||
) {}
|
||||
```
|
||||
|
||||
### 4. Event Listener Pattern
|
||||
```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> {
|
||||
// Extract data from event
|
||||
// Persist to database
|
||||
// Log if successful/failed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## WHERE TO ADD CODE
|
||||
|
||||
```
|
||||
apps/api/src/modules/admin/
|
||||
├── domain/
|
||||
│ ├── events/
|
||||
│ │ └── audit-logged.event.ts (NEW - optional wrapper)
|
||||
│ └── repositories/
|
||||
│ ├── audit-log.repository.ts (NEW - interface)
|
||||
│ └── index.ts (update exports)
|
||||
│
|
||||
├── application/
|
||||
│ ├── queries/
|
||||
│ │ ├── get-audit-logs/ (NEW)
|
||||
│ │ │ ├── get-audit-logs.query.ts
|
||||
│ │ │ └── get-audit-logs.handler.ts
|
||||
│ │ └── index.ts (update exports)
|
||||
│ │
|
||||
│ └── listeners/
|
||||
│ ├── audit-logging.listener.ts (NEW)
|
||||
│ └── index.ts (update if needed)
|
||||
│
|
||||
├── infrastructure/
|
||||
│ └── repositories/
|
||||
│ ├── prisma-audit-log.repository.ts (NEW)
|
||||
│ └── index.ts (update exports)
|
||||
│
|
||||
└── presentation/
|
||||
├── controllers/
|
||||
│ ├── admin.controller.ts (ADD ENDPOINT)
|
||||
│ └── admin-moderation.controller.ts (UPDATE if needed)
|
||||
│
|
||||
└── dto/
|
||||
├── get-audit-logs-query.dto.ts (NEW)
|
||||
└── index.ts (update exports)
|
||||
|
||||
prisma/
|
||||
└── schema.prisma (ADD AuditLog MODEL)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## EVENTS TO LISTEN TO
|
||||
|
||||
1. 'user.banned' - from UserBannedEvent
|
||||
2. 'user.unbanned' - from UserUnbannedEvent
|
||||
3. 'listing.approved' - from ListingApprovedEvent
|
||||
4. 'listing.rejected' - from ListingRejectedEvent
|
||||
5. 'kyc.approved' - from KycApprovedEvent
|
||||
6. 'kyc.rejected' - from KycRejectedEvent
|
||||
7. 'subscription.adjusted' - from SubscriptionAdjustedEvent
|
||||
8. 'user.deactivated' - (if exists in auth module)
|
||||
|
||||
Each gets logged with:
|
||||
- Admin ID (from event)
|
||||
- Resource ID (aggregateId from event)
|
||||
- Resource Type (derived from eventName)
|
||||
- Timestamp (from event.occurredAt)
|
||||
- Additional context (reason, notes, etc.)
|
||||
|
||||
Reference in New Issue
Block a user