forked from wangziqi/gongxue-base
feat: add CASL authorization and AI configuration
This commit is contained in:
93
apps/server/src/ai-config/ai-config.controller.ts
Normal file
93
apps/server/src/ai-config/ai-config.controller.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Put,
|
||||
Post,
|
||||
Body,
|
||||
UseGuards,
|
||||
Req,
|
||||
} from '@nestjs/common';
|
||||
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
||||
import { RequirePermission } from '../auth/decorators/permission.decorator';
|
||||
import { OperationLogsService } from '../operation-logs/operation-logs.service';
|
||||
import { extractRequestInfo } from '../common/request-utils';
|
||||
import { AiConfigService } from './ai-config.service';
|
||||
import { SaveAiConfigDto, TestAiConfigDto } from './dto/ai-config.dto';
|
||||
|
||||
interface AuthenticatedRequest {
|
||||
user?: { id: number; username: string };
|
||||
headers: Record<string, string | string[] | undefined>;
|
||||
connection?: { remoteAddress?: string };
|
||||
}
|
||||
|
||||
@Controller('ai/config')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
export class AiConfigController {
|
||||
constructor(
|
||||
private readonly service: AiConfigService,
|
||||
private readonly opLog: OperationLogsService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@RequirePermission('ai:config:read')
|
||||
async getConfig() {
|
||||
const data = await this.service.getConfig();
|
||||
return { success: true, data };
|
||||
}
|
||||
|
||||
@Put()
|
||||
@RequirePermission('ai:config:write')
|
||||
async saveConfig(@Body() body: SaveAiConfigDto, @Req() req: AuthenticatedRequest) {
|
||||
const config = await this.service.saveConfig(body);
|
||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
||||
await this.opLog.log({
|
||||
userId: req.user?.id,
|
||||
username: req.user?.username,
|
||||
module: 'ai-config',
|
||||
action: 'save',
|
||||
targetId: config.id,
|
||||
targetType: 'AiConfig',
|
||||
detail: `provider=${body.provider} host=${new URL(config.baseUrl).hostname} model=${body.defaultModel ? 'configured' : 'not-set'} enabled=${body.enabled ?? config.enabled}`,
|
||||
ipAddress,
|
||||
userAgent,
|
||||
});
|
||||
return { success: true, message: '配置已保存' };
|
||||
}
|
||||
|
||||
@Post('test')
|
||||
@RequirePermission('ai:config:test')
|
||||
async testConnection(@Body() body: TestAiConfigDto, @Req() req: AuthenticatedRequest) {
|
||||
const result = await this.service.testConnection(body);
|
||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
||||
await this.opLog.log({
|
||||
userId: req.user?.id,
|
||||
username: req.user?.username,
|
||||
module: 'ai-config',
|
||||
action: 'test',
|
||||
targetType: 'AiConfig',
|
||||
detail: `provider=${body.provider ?? '-'} success=${result.success} latency=${result.latencyMs ?? '-'}`,
|
||||
ipAddress,
|
||||
userAgent,
|
||||
status: result.success ? 'success' : 'failure',
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Post('clear-key')
|
||||
@RequirePermission('ai:config:write')
|
||||
async clearKey(@Req() req: AuthenticatedRequest) {
|
||||
const data = await this.service.clearKey();
|
||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
||||
await this.opLog.log({
|
||||
userId: req.user?.id,
|
||||
username: req.user?.username,
|
||||
module: 'ai-config',
|
||||
action: 'clear-key',
|
||||
targetType: 'AiConfig',
|
||||
detail: `keySource=${data.keySource}`,
|
||||
ipAddress,
|
||||
userAgent,
|
||||
});
|
||||
return { success: true, message: '密钥已清除', data };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user