feat: M4-09 — compliance & safety module (policies, agreements, filings, data requests)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 42s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 42s
- Add PrivacyPolicy, UserAgreement, FilingRecord, DataExportRequest Prisma models - ComplianceController: privacy policies, user agreements, filings, deletion/export requests - AAPI: /admin-api/compliance/* (6 resource groups) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
cefc4d51c9
commit
c4089129c0
@ -1468,3 +1468,53 @@ model ReleaseChecklist {
|
|||||||
|
|
||||||
@@index([version])
|
@@index([version])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model PrivacyPolicy {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
version String @db.VarChar(50)
|
||||||
|
title String @db.VarChar(255)
|
||||||
|
content String @db.Text
|
||||||
|
effectiveAt DateTime
|
||||||
|
published Boolean @default(false)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
@@index([version])
|
||||||
|
}
|
||||||
|
|
||||||
|
model UserAgreement {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
version String @db.VarChar(50)
|
||||||
|
title String @db.VarChar(255)
|
||||||
|
content String @db.Text
|
||||||
|
effectiveAt DateTime
|
||||||
|
published Boolean @default(false)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
@@index([version])
|
||||||
|
}
|
||||||
|
|
||||||
|
model FilingRecord {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
type String @db.VarChar(64)
|
||||||
|
title String @db.VarChar(255)
|
||||||
|
filePath String? @db.VarChar(500)
|
||||||
|
status String @default("pending") @db.VarChar(16)
|
||||||
|
notes String? @db.Text
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
model DataExportRequest {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
userId String
|
||||||
|
status String @default("pending") @db.VarChar(16)
|
||||||
|
filePath String? @db.VarChar(500)
|
||||||
|
completedAt DateTime?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
@@index([userId])
|
||||||
|
@@index([status])
|
||||||
|
}
|
||||||
|
|||||||
@ -57,6 +57,7 @@ import { ReportingModule } from './modules/reporting/reporting.module';
|
|||||||
import { ProjectCenterModule } from './modules/project-center/project-center.module';
|
import { ProjectCenterModule } from './modules/project-center/project-center.module';
|
||||||
import { HermesAgentModule } from './modules/hermes-agent/hermes-agent.module';
|
import { HermesAgentModule } from './modules/hermes-agent/hermes-agent.module';
|
||||||
import { ReleaseModule } from './modules/release/release.module';
|
import { ReleaseModule } from './modules/release/release.module';
|
||||||
|
import { ComplianceModule } from './modules/compliance/compliance.module';
|
||||||
|
|
||||||
import { JwtAuthGuard } from './common/guards/jwt-auth.guard';
|
import { JwtAuthGuard } from './common/guards/jwt-auth.guard';
|
||||||
import { RolesGuard } from './common/guards/roles.guard';
|
import { RolesGuard } from './common/guards/roles.guard';
|
||||||
@ -159,6 +160,7 @@ import appleConfig from './config/apple.config';
|
|||||||
ProjectCenterModule,
|
ProjectCenterModule,
|
||||||
HermesAgentModule,
|
HermesAgentModule,
|
||||||
ReleaseModule,
|
ReleaseModule,
|
||||||
|
ComplianceModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: APP_GUARD, useClass: RateLimitGuard },
|
{ provide: APP_GUARD, useClass: RateLimitGuard },
|
||||||
|
|||||||
91
src/modules/compliance/compliance.controller.ts
Normal file
91
src/modules/compliance/compliance.controller.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import { Controller, Get, Post, Patch, Param, Body, UseGuards } from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
|
||||||
|
import { PrismaService } from '../../infrastructure/database/prisma.service';
|
||||||
|
import { AdminAuthGuard } from '../../common/guards/admin-auth.guard';
|
||||||
|
import { AdminRolesGuard } from '../../common/guards/admin-roles.guard';
|
||||||
|
|
||||||
|
@ApiTags('admin-compliance')
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@Controller('admin-api/compliance')
|
||||||
|
@UseGuards(AdminAuthGuard, AdminRolesGuard)
|
||||||
|
export class ComplianceController {
|
||||||
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
|
// ═══ Privacy Policy ═══
|
||||||
|
|
||||||
|
@Get('privacy-policies')
|
||||||
|
@ApiOperation({ summary: '隐私政策列表' })
|
||||||
|
async listPrivacyPolicies() {
|
||||||
|
return this.prisma.privacyPolicy.findMany({ orderBy: { createdAt: 'desc' } });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('privacy-policies')
|
||||||
|
@ApiOperation({ summary: '创建隐私政策版本' })
|
||||||
|
async createPrivacyPolicy(@Body() dto: { version: string; title: string; content: string; effectiveAt: string }) {
|
||||||
|
return this.prisma.privacyPolicy.create({ data: { ...dto, effectiveAt: new Date(dto.effectiveAt) } });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch('privacy-policies/:id')
|
||||||
|
@ApiOperation({ summary: '更新隐私政策' })
|
||||||
|
async updatePrivacyPolicy(@Param('id') id: string, @Body() dto: Record<string, any>) {
|
||||||
|
return this.prisma.privacyPolicy.update({ where: { id }, data: dto });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ User Agreement ═══
|
||||||
|
|
||||||
|
@Get('user-agreements')
|
||||||
|
@ApiOperation({ summary: '用户协议列表' })
|
||||||
|
async listUserAgreements() {
|
||||||
|
return this.prisma.userAgreement.findMany({ orderBy: { createdAt: 'desc' } });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('user-agreements')
|
||||||
|
@ApiOperation({ summary: '创建用户协议版本' })
|
||||||
|
async createUserAgreement(@Body() dto: { version: string; title: string; content: string; effectiveAt: string }) {
|
||||||
|
return this.prisma.userAgreement.create({ data: { ...dto, effectiveAt: new Date(dto.effectiveAt) } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Filing Records ═══
|
||||||
|
|
||||||
|
@Get('filings')
|
||||||
|
@ApiOperation({ summary: '备案台账列表' })
|
||||||
|
async listFilings() {
|
||||||
|
return this.prisma.filingRecord.findMany({ orderBy: { createdAt: 'desc' } });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('filings')
|
||||||
|
@ApiOperation({ summary: '创建备案记录' })
|
||||||
|
async createFiling(@Body() dto: { type: string; title: string; notes?: string }) {
|
||||||
|
return this.prisma.filingRecord.create({ data: dto });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Data Deletion Requests ═══
|
||||||
|
|
||||||
|
@Get('deletion-requests')
|
||||||
|
@ApiOperation({ summary: '用户数据删除请求' })
|
||||||
|
async listDeletionRequests() {
|
||||||
|
return this.prisma.accountDeletionRequest.findMany({ orderBy: { createdAt: 'desc' }, take: 100 });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('deletion-requests/:id/approve')
|
||||||
|
@ApiOperation({ summary: '批准删除请求' })
|
||||||
|
async approveDeletion(@Param('id') id: string) {
|
||||||
|
return this.prisma.accountDeletionRequest.update({ where: { id }, data: { status: 'APPROVED', reviewedAt: new Date() } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Data Export Requests ═══
|
||||||
|
|
||||||
|
@Get('export-requests')
|
||||||
|
@ApiOperation({ summary: '用户数据导出请求' })
|
||||||
|
async listExportRequests() {
|
||||||
|
return this.prisma.dataExportRequest.findMany({ orderBy: { createdAt: 'desc' }, take: 100 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Security Events ═══
|
||||||
|
|
||||||
|
@Get('security-events')
|
||||||
|
@ApiOperation({ summary: '安全事件列表' })
|
||||||
|
async listSecurityEvents() {
|
||||||
|
return this.prisma.securityEvent.findMany({ orderBy: { createdAt: 'desc' }, take: 100 });
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/modules/compliance/compliance.module.ts
Normal file
7
src/modules/compliance/compliance.module.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { ComplianceController } from './compliance.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [ComplianceController],
|
||||||
|
})
|
||||||
|
export class ComplianceModule {}
|
||||||
Loading…
x
Reference in New Issue
Block a user