feat: add CASL authorization and AI configuration

This commit is contained in:
2026-07-11 14:25:34 +08:00
parent 8f0991a51f
commit 1e1c476bc3
59 changed files with 7733 additions and 120 deletions

View File

@@ -1,36 +1,45 @@
import { Controller, Get, Query, Request, UseGuards } from '@nestjs/common';
import { DashboardService } from './dashboard.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import {
AuthorizationService,
CaslAction,
SubjectName,
} from '../authorization';
import { RequirePermission } from '../auth/decorators/permission.decorator';
interface RequestUser {
id: number;
username: string;
permissions?: string[];
isSuperAdmin?: boolean;
permissions: string[];
isSuperAdmin: boolean;
}
@UseGuards(JwtAuthGuard)
@RequirePermission('dashboard:view')
@Controller('dashboard')
export class DashboardController {
constructor(private service: DashboardService) {}
constructor(
private service: DashboardService,
private readonly authService: AuthorizationService,
) {}
private canManageAllDashboard(user: RequestUser): boolean {
private canManageAllDashboard(req: { user: RequestUser }): boolean {
const ability = this.authService.abilityForRequest(req);
// Legacy: class:edit grants broad dashboard access
return (
user.isSuperAdmin === true ||
user.permissions?.includes('dashboard:manage') === true ||
user.permissions?.includes('class:edit') === true
ability.can(CaslAction.Manage, SubjectName.Dashboard) ||
ability.can(CaslAction.Update, SubjectName.Class)
);
}
private getAccessibleClassIds(user: RequestUser) {
return this.service.getAccessibleClassIds(user.id, this.canManageAllDashboard(user));
private getAccessibleClassIds(req: { user: RequestUser }) {
return this.service.getAccessibleClassIds(req.user.id, this.canManageAllDashboard(req));
}
@Get('stats')
async getStats(@Request() req: { user: RequestUser }) {
return this.service.getStats(await this.getAccessibleClassIds(req.user));
return this.service.getStats(await this.getAccessibleClassIds(req));
}
@Get('gantt')
@@ -60,7 +69,7 @@ export class DashboardController {
@Get('class-attendance-ranking')
async getClassAttendanceRanking(@Request() req: { user: RequestUser }) {
return this.service.getClassAttendanceRanking(await this.getAccessibleClassIds(req.user));
return this.service.getClassAttendanceRanking(await this.getAccessibleClassIds(req));
}
@Get('classroom-occupancy')