fix: audit remediation — SSE user scoping, FK transactional safety, UI error handling

- H4: scoped SSE import progress to exact userId match; non-HTTP events excluded from all subscribers
- H2: moved PRAGMA foreign_key_check inside SQLite transaction before COMMIT; violations rollback preserving old tables
- M1: removed dead axios-style error branch from extractErrorMessage (interceptor already unwraps)
- M2: split handleSave try/catch — save errors vs reload errors shown distinctly
- M3: added provider field validation before AI config test request
- Added SSE scoping regression tests (import service + controller)
- Added FK check failure rollback test (database-migrations.spec)
- Updated controller spec expectations for userId parameter

Co-authored-by: Code Review <branch-review>
This commit is contained in:
2026-07-12 22:59:03 +08:00
parent b6fca99390
commit cc4f4dae4e
69 changed files with 6262 additions and 1980 deletions

View File

@@ -126,7 +126,7 @@ export class RbacController {
// ==================== 用户管理 ====================
@Get('users')
@RequirePermission('user:view')
@RequirePermission('user:view', 'teacher:view')
getUsers(@Query('isArchived') isArchived?: string) {
const archived = isArchived === 'true';
return this.rbacService.findAllUsers(archived);
@@ -301,7 +301,7 @@ export class RbacController {
// ---- 教师工作台 ----
@Get('teacher-workspace')
@RequirePermission('class:view')
@RequirePermission('teacher-workspace:view')
async getTeacherWorkspace(@Request() req: any) {
return this.rbacService.getTeacherWorkspace(req.user?.id);
}
@@ -309,7 +309,7 @@ export class RbacController {
// ---- 教师管理 ----
@Get('teachers')
@RequirePermission('user:view')
@RequirePermission('teacher:view')
async getTeachers(
@Query('search') search?: string,
@Query('page') page?: string,
@@ -323,7 +323,7 @@ export class RbacController {
}
@Put('teachers/:id/profile')
@RequirePermission('user:edit')
@RequirePermission('teacher:edit')
async updateTeacherProfile(
@Param('id') id: string,
@Body() profile: UpdateProfileDto,