fix(server): 路由 id 使用 ParseIntPipe,限制分页与批量数组上限
This commit is contained in:
@@ -131,8 +131,8 @@ export class AttendanceQueryService {
|
||||
},
|
||||
accessibleClassIds?: number[],
|
||||
) {
|
||||
const page = query.page || 1;
|
||||
const pageSize = query.pageSize || 20;
|
||||
const page = Math.max(1, Math.floor(Number(query.page) || 1));
|
||||
const pageSize = Math.min(200, Math.max(1, Math.floor(Number(query.pageSize) || 20)));
|
||||
|
||||
const qb = this.attendanceRepo.createQueryBuilder('ar');
|
||||
|
||||
@@ -233,8 +233,8 @@ export class AttendanceQueryService {
|
||||
|
||||
// ── DingAttendance raw records ──
|
||||
async getDingRaw(query: QueryDingRawDto, accessibleClassIds?: number[]) {
|
||||
const page = query.page || 1;
|
||||
const pageSize = query.pageSize || 20;
|
||||
const page = Math.max(1, Math.floor(Number(query.page) || 1));
|
||||
const pageSize = Math.min(200, Math.max(1, Math.floor(Number(query.pageSize) || 20)));
|
||||
const qb = this.dingRawRepo.createQueryBuilder('ar');
|
||||
|
||||
qb.leftJoinAndSelect('ar.matchedStudent', 'matchedStudent');
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Query,
|
||||
UseGuards,
|
||||
UsePipes,
|
||||
@@ -85,7 +86,7 @@ export class ClassesController {
|
||||
|
||||
@Get(':id')
|
||||
@RequirePermission('class:view')
|
||||
async findOne(@Param('id') id: string, @Request() req: AuthenticatedRequest) {
|
||||
async findOne(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
|
||||
await this.assertReadAccess(req, +id);
|
||||
return this.service.findOne(+id);
|
||||
}
|
||||
@@ -93,7 +94,7 @@ export class ClassesController {
|
||||
@Get(':id/schedule')
|
||||
@RequirePermission('class:view')
|
||||
async getSchedule(
|
||||
@Param('id') id: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Query() query: QueryClassScheduleDto,
|
||||
@Request() req: AuthenticatedRequest,
|
||||
) {
|
||||
@@ -104,7 +105,7 @@ export class ClassesController {
|
||||
@Get(':id/attendance-summary')
|
||||
@RequirePermission('class:view')
|
||||
async getAttendanceSummary(
|
||||
@Param('id') id: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Query() query: QueryClassAttendanceSummaryDto,
|
||||
@Request() req: AuthenticatedRequest,
|
||||
) {
|
||||
@@ -125,27 +126,27 @@ export class ClassesController {
|
||||
/** 批量导入学生到班级(通过钉钉用户ID) */
|
||||
@Post(':id/students/import')
|
||||
@RequirePermission('class:edit')
|
||||
async batchImportStudents(@Param('id') id: string, @Body() dto: BatchImportStudentsDto) {
|
||||
async batchImportStudents(@Param('id', ParseIntPipe) id: number, @Body() dto: BatchImportStudentsDto) {
|
||||
return this.service.batchImportStudents(+id, dto.users);
|
||||
}
|
||||
|
||||
/** 归档班级 */
|
||||
@Put(':id/archive')
|
||||
@RequirePermission('class:edit')
|
||||
async archive(@Param('id') id: string) {
|
||||
async archive(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.service.archive(+id);
|
||||
}
|
||||
|
||||
/** 取消归档 */
|
||||
@Put(':id/restore')
|
||||
@RequirePermission('class:edit')
|
||||
async restore(@Param('id') id: string) {
|
||||
async restore(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.service.restore(+id);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
@RequirePermission('class:edit')
|
||||
async update(@Param('id') id: string, @Body() dto: UpdateClassDto, @Request() req: any) {
|
||||
async update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateClassDto, @Request() req: any) {
|
||||
const result = await this.service.update(+id, dto);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '班级管理', action: '编辑班级', targetId: +id, targetType: 'class', detail: JSON.stringify(dto),
|
||||
@@ -155,7 +156,7 @@ export class ClassesController {
|
||||
|
||||
@Delete(':id')
|
||||
@RequirePermission('class:delete')
|
||||
async remove(@Param('id') id: string, @Request() req: any) {
|
||||
async remove(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const result = await this.service.remove(+id);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '班级管理', action: '归档班级', targetId: +id, targetType: 'class',
|
||||
@@ -165,7 +166,7 @@ export class ClassesController {
|
||||
|
||||
@Delete(':id/permanent')
|
||||
@RequirePermission('class:purge')
|
||||
async purge(@Param('id') id: string, @Request() req: any) {
|
||||
async purge(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const result = await this.service.purge(+id);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '班级管理', action: '永久删除班级', targetId: +id, targetType: 'class', detail: '物理删除,不可恢复',
|
||||
@@ -176,7 +177,7 @@ export class ClassesController {
|
||||
@Get(':id/roster/export')
|
||||
@RequirePermission('class:view')
|
||||
async exportRoster(
|
||||
@Param('id') id: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Res() res: Response,
|
||||
@Request() req: AuthenticatedRequest,
|
||||
) {
|
||||
@@ -218,14 +219,14 @@ export class ClassesController {
|
||||
|
||||
@Get(':id/students')
|
||||
@RequirePermission('class:view')
|
||||
async getStudents(@Param('id') id: string, @Request() req: AuthenticatedRequest) {
|
||||
async getStudents(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
|
||||
await this.assertReadAccess(req, +id);
|
||||
return this.service.getStudents(+id);
|
||||
}
|
||||
|
||||
@Post(':id/students')
|
||||
@RequirePermission('class:edit')
|
||||
async addStudents(@Param('id') id: string, @Body() dto: AddStudentsDto, @Request() req: any) {
|
||||
async addStudents(@Param('id', ParseIntPipe) id: number, @Body() dto: AddStudentsDto, @Request() req: any) {
|
||||
const result = await this.service.addStudents(+id, dto.studentIds);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '班级管理', action: '添加学生', targetId: +id, targetType: 'class', detail: `新增${result.added}名学生`,
|
||||
@@ -249,8 +250,8 @@ export class ClassesController {
|
||||
@Delete(':id/students/:studentId')
|
||||
@RequirePermission('class:edit')
|
||||
async removeStudent(
|
||||
@Param('id') id: string,
|
||||
@Param('studentId') studentId: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Param('studentId', ParseIntPipe) studentId: number,
|
||||
@Request() req: any,
|
||||
) {
|
||||
const result = await this.service.removeStudent(+id, +studentId);
|
||||
@@ -262,14 +263,14 @@ export class ClassesController {
|
||||
|
||||
@Get(':id/teachers')
|
||||
@RequirePermission('class:view')
|
||||
async getTeachers(@Param('id') id: string, @Request() req: AuthenticatedRequest) {
|
||||
async getTeachers(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
|
||||
await this.assertReadAccess(req, +id);
|
||||
return this.service.getTeachers(+id);
|
||||
}
|
||||
|
||||
@Post(':id/teachers')
|
||||
@RequirePermission('class:edit')
|
||||
async addTeacher(@Param('id') id: string, @Body() dto: AddTeacherDto, @Request() req: any) {
|
||||
async addTeacher(@Param('id', ParseIntPipe) id: number, @Body() dto: AddTeacherDto, @Request() req: any) {
|
||||
const result = await this.service.addTeacher(+id, dto);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '班级管理', action: '添加教师', targetId: +id, targetType: 'class', detail: `教师${dto.userId} 角色${dto.roleType}`,
|
||||
@@ -290,8 +291,8 @@ export class ClassesController {
|
||||
@Delete(':id/teacher-assignments/:assignmentId')
|
||||
@RequirePermission('class:edit')
|
||||
async removeTeacherAssignment(
|
||||
@Param('id') id: string,
|
||||
@Param('assignmentId') assignmentId: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Param('assignmentId', ParseIntPipe) assignmentId: number,
|
||||
@Request() req: any,
|
||||
) {
|
||||
const result = await this.service.removeTeacherAssignment(+id, +assignmentId);
|
||||
@@ -304,8 +305,8 @@ export class ClassesController {
|
||||
@Delete(':id/teachers/:userId')
|
||||
@RequirePermission('class:edit')
|
||||
async removeTeacher(
|
||||
@Param('id') id: string,
|
||||
@Param('userId') userId: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Param('userId', ParseIntPipe) userId: number,
|
||||
@Request() req: any,
|
||||
) {
|
||||
const result = await this.service.removeTeacher(+id, +userId);
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Query,
|
||||
UseGuards,
|
||||
Request,
|
||||
@@ -95,7 +96,7 @@ export class ClassroomRentalsController {
|
||||
|
||||
@Get(':id')
|
||||
@RequirePermission('rental:view')
|
||||
findOne(@Param('id') id: string) {
|
||||
findOne(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.service.findOne(+id);
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ export class ClassroomRentalsController {
|
||||
|
||||
@Put(':id')
|
||||
@RequirePermission('rental:edit')
|
||||
async update(@Param('id') id: string, @Body() dto: UpdateRentalDto, @Request() req: any) {
|
||||
async update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateRentalDto, @Request() req: any) {
|
||||
const result = await this.service.update(+id, dto);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '教室租赁', action: '编辑租赁', targetId: +id, targetType: 'classroom-rental', detail: JSON.stringify(dto),
|
||||
@@ -121,7 +122,7 @@ export class ClassroomRentalsController {
|
||||
|
||||
@Put(':id/cancel')
|
||||
@RequirePermission('rental:edit')
|
||||
async cancel(@Param('id') id: string, @Request() req: any) {
|
||||
async cancel(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const result = await this.service.cancel(+id);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '教室租赁', action: '取消租赁', targetId: +id, targetType: 'classroom-rental',
|
||||
@@ -131,7 +132,7 @@ export class ClassroomRentalsController {
|
||||
|
||||
@Put(':id/end')
|
||||
@RequirePermission('rental:edit')
|
||||
async end(@Param('id') id: string, @Request() req: any) {
|
||||
async end(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const result = await this.service.end(+id);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '教室租赁', action: '结束租赁', targetId: +id, targetType: 'classroom-rental',
|
||||
@@ -141,7 +142,7 @@ export class ClassroomRentalsController {
|
||||
|
||||
@Delete(':id')
|
||||
@RequirePermission('rental:delete')
|
||||
async remove(@Param('id') id: string, @Request() req: any) {
|
||||
async remove(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const result = await this.service.remove(+id);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '教室租赁', action: '归档租赁', targetId: +id, targetType: 'classroom-rental',
|
||||
@@ -151,7 +152,7 @@ export class ClassroomRentalsController {
|
||||
|
||||
@Delete(':id/permanent')
|
||||
@RequirePermission('rental:purge')
|
||||
async purge(@Param('id') id: string, @Request() req: any) {
|
||||
async purge(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const result = await this.service.purge(+id);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '教室租赁', action: '永久删除租赁订单', targetId: +id, targetType: 'classroom-rental', detail: '物理删除,不可恢复',
|
||||
@@ -174,7 +175,7 @@ export class ClassroomRentalsController {
|
||||
}),
|
||||
)
|
||||
async uploadContract(
|
||||
@Param('id') id: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Request() req: any,
|
||||
) {
|
||||
@@ -188,7 +189,7 @@ export class ClassroomRentalsController {
|
||||
|
||||
@Get(':id/contract')
|
||||
@RequirePermission('rental:view')
|
||||
async downloadContract(@Param('id') id: string, @Res() res: Response) {
|
||||
async downloadContract(@Param('id', ParseIntPipe) id: number, @Res() res: Response) {
|
||||
const { fullPath, originalName } = await this.service.getContractPath(+id);
|
||||
res.setHeader('Content-Type', 'application/pdf');
|
||||
res.setHeader(
|
||||
@@ -201,7 +202,7 @@ export class ClassroomRentalsController {
|
||||
|
||||
@Delete(':id/contract')
|
||||
@RequirePermission('rental:edit')
|
||||
async deleteContract(@Param('id') id: string, @Request() req: any) {
|
||||
async deleteContract(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const result = await this.service.removeContract(+id);
|
||||
await logAudit(this.logService, req, {
|
||||
module: '教室租赁', action: '移除合同', targetId: +id, targetType: 'classroom-rental',
|
||||
|
||||
@@ -17,4 +17,11 @@ describe('BatchIdsDto', () => {
|
||||
const dto = Object.assign(new BatchIdsDto(), { ids: [1, 1, 2] });
|
||||
await expect(validate(dto)).resolves.toHaveLength(0);
|
||||
});
|
||||
|
||||
it('rejects batches with more than 500 ids', async () => {
|
||||
const dto = Object.assign(new BatchIdsDto(), {
|
||||
ids: Array.from({ length: 501 }, (_, i) => i + 1),
|
||||
});
|
||||
await expect(validate(dto)).resolves.not.toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { ArrayNotEmpty, IsArray, IsInt, Min } from 'class-validator';
|
||||
import { ArrayMaxSize, ArrayNotEmpty, IsArray, IsInt, Min } from 'class-validator';
|
||||
|
||||
export class BatchIdsDto {
|
||||
@IsArray()
|
||||
@ArrayNotEmpty()
|
||||
@ArrayMaxSize(500)
|
||||
@IsInt({ each: true })
|
||||
@Min(1, { each: true })
|
||||
ids: number[];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Controller, Get, Post, Put, Delete, Body, Param, UseGuards, Request } from '@nestjs/common';
|
||||
import { Controller, Get, Post, Put, Delete, Body, Param, ParseIntPipe, UseGuards, Request } from '@nestjs/common';
|
||||
import { ExpenseTypesService } from './expense-types.service';
|
||||
import { CreateExpenseTypeDto, UpdateExpenseTypeDto } from './dto/expense-type.dto';
|
||||
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
||||
@@ -47,7 +47,7 @@ export class ExpenseTypesController {
|
||||
|
||||
@Put(':id')
|
||||
@RequirePermission('expense:edit')
|
||||
async update(@Param('id') id: string, @Body() dto: UpdateExpenseTypeDto, @Request() req: any) {
|
||||
async update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateExpenseTypeDto, @Request() req: any) {
|
||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
||||
const result = await this.service.update(+id, dto);
|
||||
await this.logService.log({
|
||||
@@ -66,7 +66,7 @@ export class ExpenseTypesController {
|
||||
|
||||
@Delete(':id')
|
||||
@RequirePermission('expense:delete')
|
||||
async remove(@Param('id') id: string, @Request() req: any) {
|
||||
async remove(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
||||
await this.service.remove(+id);
|
||||
await this.logService.log({
|
||||
|
||||
@@ -28,4 +28,17 @@ describe('BatchRoomExpenseDto boundaries', () => {
|
||||
});
|
||||
await expect(validate(dto)).resolves.toHaveLength(0);
|
||||
});
|
||||
|
||||
it('rejects a batch with more than 500 items', async () => {
|
||||
const dto = plainToInstance(BatchRoomExpenseDto, {
|
||||
periodStart: '2026-07-01',
|
||||
periodEnd: '2026-07-31',
|
||||
expenses: Array.from({ length: 501 }, () => ({
|
||||
roomId: 1,
|
||||
expenseType: 'water',
|
||||
amount: 10,
|
||||
})),
|
||||
});
|
||||
await expect(validate(dto)).resolves.not.toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ArrayNotEmpty, IsArray, IsDateString, IsIn, IsInt, IsISO8601, IsString, IsNumber, IsOptional, Matches, Min, ValidateNested } from 'class-validator';
|
||||
import { ArrayMaxSize, ArrayNotEmpty, IsArray, IsDateString, IsIn, IsInt, IsISO8601, IsString, IsNumber, IsOptional, Matches, Min, ValidateNested } from 'class-validator';
|
||||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
@@ -117,6 +117,7 @@ export class BatchRoomExpenseDto {
|
||||
|
||||
@IsArray()
|
||||
@ArrayNotEmpty()
|
||||
@ArrayMaxSize(500)
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => BatchRoomExpenseItemDto)
|
||||
expenses: BatchRoomExpenseItemDto[];
|
||||
|
||||
@@ -32,4 +32,13 @@ describe('notification DTO boundaries', () => {
|
||||
expect(await validate(dto)).not.toEqual([]);
|
||||
}
|
||||
});
|
||||
|
||||
it('rejects more than 500 recipients', async () => {
|
||||
const dto = plainToInstance(CreateNotificationDto, {
|
||||
recipientIds: Array.from({ length: 501 }, (_, i) => i + 1),
|
||||
type: 'test',
|
||||
title: '标题',
|
||||
});
|
||||
await expect(validate(dto)).resolves.not.toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
ArrayNotEmpty,
|
||||
ArrayMaxSize,
|
||||
IsString,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
@@ -13,6 +14,7 @@ import { Type } from 'class-transformer';
|
||||
export class CreateNotificationDto {
|
||||
@IsArray()
|
||||
@ArrayNotEmpty()
|
||||
@ArrayMaxSize(500)
|
||||
@IsInt({ each: true })
|
||||
recipientIds: number[];
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Get,
|
||||
Put,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Query,
|
||||
Req,
|
||||
Sse,
|
||||
@@ -74,7 +75,7 @@ export class NotificationsController {
|
||||
|
||||
@Put(':id/read')
|
||||
async markRead(
|
||||
@Param('id') id: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Req() req: AuthenticatedRequest,
|
||||
) {
|
||||
await this.service.markRead(+id, req.user.id);
|
||||
|
||||
@@ -53,8 +53,8 @@ export class OperationLogsService {
|
||||
if (query?.endDate)
|
||||
qb.andWhere('log.createdAt <= :endDate', { endDate: query.endDate + ' 23:59:59' });
|
||||
|
||||
const page = query?.page || 1;
|
||||
const pageSize = query?.pageSize || 50;
|
||||
const page = Math.max(1, Math.floor(Number(query?.page) || 1));
|
||||
const pageSize = Math.min(200, Math.max(1, Math.floor(Number(query?.pageSize) || 50)));
|
||||
const [data, total] = await qb
|
||||
.skip((page - 1) * pageSize)
|
||||
.take(pageSize)
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Query,
|
||||
UseGuards,
|
||||
Request,
|
||||
@@ -42,7 +43,7 @@ export class OrganizationsController {
|
||||
|
||||
@Get(':id')
|
||||
@RequirePermission('organization:view')
|
||||
findOne(@Param('id') id: string) {
|
||||
findOne(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.service.findOne(+id);
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ export class OrganizationsController {
|
||||
|
||||
@Put(':id')
|
||||
@RequirePermission('organization:edit')
|
||||
async update(@Param('id') id: string, @Body() dto: UpdateOrganizationDto, @Request() req: any) {
|
||||
async update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateOrganizationDto, @Request() req: any) {
|
||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
||||
const result = await this.service.update(+id, dto);
|
||||
await this.logService.log({
|
||||
@@ -86,7 +87,7 @@ export class OrganizationsController {
|
||||
|
||||
@Delete(':id')
|
||||
@RequirePermission('organization:delete')
|
||||
async remove(@Param('id') id: string, @Request() req: any) {
|
||||
async remove(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
||||
const result = await this.service.remove(+id);
|
||||
await this.logService.log({
|
||||
@@ -104,7 +105,7 @@ export class OrganizationsController {
|
||||
|
||||
@Delete(':id/permanent')
|
||||
@RequirePermission('organization:purge')
|
||||
async purge(@Param('id') id: string, @Request() req: any) {
|
||||
async purge(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
||||
const result = await this.service.purge(+id);
|
||||
await this.logService.log({
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
UseGuards,
|
||||
Request,
|
||||
BadRequestException,
|
||||
ParseIntPipe,
|
||||
} from '@nestjs/common';
|
||||
import { RbacService } from './rbac.service';
|
||||
import {
|
||||
@@ -41,7 +42,7 @@ export class RbacController {
|
||||
|
||||
@Get('roles/:id')
|
||||
@RequirePermission('role:view')
|
||||
findRoleById(@Param('id') id: string) {
|
||||
findRoleById(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.rbacService.findRoleById(+id);
|
||||
}
|
||||
|
||||
@@ -57,7 +58,7 @@ export class RbacController {
|
||||
|
||||
@Put('roles/:id')
|
||||
@RequirePermission('role:edit')
|
||||
async updateRole(@Param('id') id: string, @Body() dto: UpdateRoleDto, @Request() req: any) {
|
||||
async updateRole(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateRoleDto, @Request() req: any) {
|
||||
try {
|
||||
const result = await this.rbacService.updateRole(+id, dto);
|
||||
await logAudit(this.logService, req, {
|
||||
@@ -71,7 +72,7 @@ export class RbacController {
|
||||
|
||||
@Delete('roles/:id')
|
||||
@RequirePermission('role:delete')
|
||||
async deleteRole(@Param('id') id: string, @Request() req: any) {
|
||||
async deleteRole(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
try {
|
||||
const result = await this.rbacService.deleteRole(+id);
|
||||
await logAudit(this.logService, req, {
|
||||
@@ -118,7 +119,7 @@ export class RbacController {
|
||||
|
||||
@Put('users/:id')
|
||||
@RequirePermission('user:edit')
|
||||
async updateUser(@Param('id') id: string, @Body() dto: UpdateUserDto, @Request() req: any) {
|
||||
async updateUser(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateUserDto, @Request() req: any) {
|
||||
try {
|
||||
const result = await this.rbacService.updateUser(+id, dto);
|
||||
await logAudit(this.logService, req, {
|
||||
@@ -132,7 +133,7 @@ export class RbacController {
|
||||
|
||||
@Put('users/:id/password')
|
||||
@RequirePermission('user:reset-password')
|
||||
async resetPassword(@Param('id') id: string, @Body() dto: ResetPasswordDto, @Request() req: any) {
|
||||
async resetPassword(@Param('id', ParseIntPipe) id: number, @Body() dto: ResetPasswordDto, @Request() req: any) {
|
||||
try {
|
||||
const result = await this.rbacService.resetPassword(+id, dto.password);
|
||||
await logAudit(this.logService, req, {
|
||||
@@ -146,7 +147,7 @@ export class RbacController {
|
||||
|
||||
@Put('users/:id/archive')
|
||||
@RequirePermission('user:edit')
|
||||
async archiveUser(@Param('id') id: string) {
|
||||
async archiveUser(@Param('id', ParseIntPipe) id: number) {
|
||||
try {
|
||||
return await this.rbacService.archiveUser(+id);
|
||||
} catch (e: unknown) {
|
||||
@@ -157,7 +158,7 @@ export class RbacController {
|
||||
|
||||
@Put('users/:id/restore')
|
||||
@RequirePermission('user:edit')
|
||||
async restoreUser(@Param('id') id: string) {
|
||||
async restoreUser(@Param('id', ParseIntPipe) id: number) {
|
||||
try {
|
||||
return await this.rbacService.restoreUser(+id);
|
||||
} catch (e: unknown) {
|
||||
@@ -168,7 +169,7 @@ export class RbacController {
|
||||
|
||||
@Delete('users/:id/permanent')
|
||||
@RequirePermission('user:purge')
|
||||
async purgeUser(@Param('id') id: string, @Request() req: any) {
|
||||
async purgeUser(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
|
||||
try {
|
||||
const result = await this.rbacService.purgeUser(+id, req.user?.id);
|
||||
await logAudit(this.logService, req, {
|
||||
@@ -183,7 +184,7 @@ export class RbacController {
|
||||
|
||||
@Put('users/:id/mark-staff')
|
||||
@RequirePermission('user:edit')
|
||||
async markAsStaff(@Param('id') id: string) {
|
||||
async markAsStaff(@Param('id', ParseIntPipe) id: number) {
|
||||
try {
|
||||
return await this.rbacService.markAsStaff(+id);
|
||||
} catch (e: unknown) {
|
||||
@@ -194,7 +195,7 @@ export class RbacController {
|
||||
|
||||
@Put('users/:id/mark-student')
|
||||
@RequirePermission('user:edit')
|
||||
async markAsStudent(@Param('id') id: string) {
|
||||
async markAsStudent(@Param('id', ParseIntPipe) id: number) {
|
||||
try {
|
||||
return await this.rbacService.markAsStudent(+id);
|
||||
} catch (e: unknown) {
|
||||
@@ -205,14 +206,14 @@ export class RbacController {
|
||||
|
||||
@Get('users/:id/profile')
|
||||
@RequirePermission('user:view')
|
||||
getUserProfile(@Param('id') id: string) {
|
||||
getUserProfile(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.rbacService.getUserProfile(+id);
|
||||
}
|
||||
|
||||
@Put('users/:id/profile')
|
||||
@RequirePermission('user:edit')
|
||||
async updateUserProfile(
|
||||
@Param('id') id: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body() dto: UpdateProfileDto,
|
||||
@Request() req: any,
|
||||
) {
|
||||
@@ -250,7 +251,7 @@ export class RbacController {
|
||||
@Put('teachers/:id/profile')
|
||||
@RequirePermission('teacher:edit')
|
||||
async updateTeacherProfile(
|
||||
@Param('id') id: string,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body() profile: UpdateProfileDto,
|
||||
@Request() req: { user?: { id: number; username: string } },
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user