From d2d87701ded618872ea96cf1907ab31cb93d459a Mon Sep 17 00:00:00 2001 From: EL <1175065040@qq.com> Date: Fri, 3 Apr 2026 09:41:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=B8=BB=E4=BB=BB/=E7=BB=84?= =?UTF-8?q?=E9=95=BF/=E5=8C=BB=E7=94=9F=E5=88=A0=E9=99=A4=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E5=B9=B6=E6=96=B0=E5=A2=9E=E5=88=A0=E9=99=A4=E8=8C=83?= =?UTF-8?q?=E5=9B=B4=E6=9D=83=E9=99=90=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/devices/b-devices/b-devices.controller.ts | 8 ++- src/devices/devices.service.ts | 70 ++++++++++++++++++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/devices/b-devices/b-devices.controller.ts b/src/devices/b-devices/b-devices.controller.ts index 5a0458f..82321b9 100644 --- a/src/devices/b-devices/b-devices.controller.ts +++ b/src/devices/b-devices/b-devices.controller.ts @@ -160,7 +160,13 @@ export class BDevicesController { * 删除设备。 */ @Delete(':id') - @Roles(Role.SYSTEM_ADMIN, Role.HOSPITAL_ADMIN) + @Roles( + Role.SYSTEM_ADMIN, + Role.HOSPITAL_ADMIN, + Role.DIRECTOR, + Role.LEADER, + Role.DOCTOR, + ) @ApiOperation({ summary: '删除设备' }) @ApiParam({ name: 'id', description: '设备 ID' }) remove( diff --git a/src/devices/devices.service.ts b/src/devices/devices.service.ts index 581215b..feb01f1 100644 --- a/src/devices/devices.service.ts +++ b/src/devices/devices.service.ts @@ -177,7 +177,7 @@ export class DevicesService { * 删除设备:若设备已被任务明细引用,则返回 409。 */ async remove(actor: ActorContext, id: number) { - const current = await this.findOne(actor, id); + const current = await this.findRemovableDevice(actor, id); try { return await this.prisma.device.delete({ @@ -538,6 +538,74 @@ export class DevicesService { /** * 管理员角色校验:仅系统管理员与院管可操作患者植入实例。 */ + private async findRemovableDevice(actor: ActorContext, id: number) { + const deviceId = this.toInt(id, 'id'); + const device = await this.prisma.device.findUnique({ + where: { id: deviceId }, + select: { + id: true, + patient: { + select: { + hospitalId: true, + doctorId: true, + doctor: { + select: { + departmentId: true, + groupId: true, + }, + }, + }, + }, + }, + }); + + if (!device) { + throw new NotFoundException(MESSAGES.DEVICE.NOT_FOUND); + } + + this.assertDeviceRemovableScope(actor, device.patient); + return device; + } + + private assertDeviceRemovableScope( + actor: ActorContext, + patient: { + hospitalId: number; + doctorId: number; + doctor: { departmentId: number | null; groupId: number | null }; + }, + ) { + switch (actor.role) { + case Role.SYSTEM_ADMIN: + return; + case Role.HOSPITAL_ADMIN: + if (patient.hospitalId !== this.requireActorHospitalId(actor)) { + throw new ForbiddenException(MESSAGES.DEFAULT_FORBIDDEN); + } + return; + case Role.DIRECTOR: + if ( + !actor.departmentId || + patient.doctor.departmentId !== actor.departmentId + ) { + throw new ForbiddenException(MESSAGES.DEFAULT_FORBIDDEN); + } + return; + case Role.LEADER: + if (!actor.groupId || patient.doctor.groupId !== actor.groupId) { + throw new ForbiddenException(MESSAGES.DEFAULT_FORBIDDEN); + } + return; + case Role.DOCTOR: + if (patient.doctorId !== actor.id) { + throw new ForbiddenException(MESSAGES.DEFAULT_FORBIDDEN); + } + return; + default: + throw new ForbiddenException(MESSAGES.DEFAULT_FORBIDDEN); + } + } + private assertAdmin(actor: ActorContext) { if ( actor.role !== Role.SYSTEM_ADMIN &&