NestJS+TypeORM(MariaDB)配置groups表固定不可删角色
NestJS + TypeORM(MariaDB) 实现不可删除的ADMIN/DEFAULT角色
1. 确认Group实体定义
先确保你的Group实体字段配置正确,尤其是deleteable字段默认设为true(普通角色默认可删),后续给ADMIN和DEFAULT角色单独设置为false:
// src/group/group.entity.ts import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity('groups') export class Group { @PrimaryGeneratedColumn() id: number; @Column({ unique: true }) // 保证角色名唯一,避免重复创建 name: string; @Column('simple-array') // 假设权限是字符串数组,比如['create', 'read'],也可改用json类型 permissions: string[]; @Column({ default: true }) // 默认允许删除 deleteable: boolean; }
2. 自动初始化ADMIN和DEFAULT角色
在项目启动时自动创建这两个角色(如果不存在),避免手动插入。在Group服务类中实现OnModuleInit接口:
// src/group/group.service.ts import { Injectable, OnModuleInit } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Group } from './group.entity'; @Injectable() export class GroupService implements OnModuleInit { constructor( @InjectRepository(Group) private groupRepository: Repository<Group>, ) {} async onModuleInit() { // 检查并创建ADMIN角色 const adminExists = await this.groupRepository.findOne({ where: { name: 'ADMIN' } }); if (!adminExists) { await this.groupRepository.save({ name: 'ADMIN', permissions: ['*'], // 全权限,根据业务需求调整 deleteable: false, // 标记为不可删除 }); } // 检查并创建DEFAULT角色 const defaultExists = await this.groupRepository.findOne({ where: { name: 'DEFAULT' } }); if (!defaultExists) { await this.groupRepository.save({ name: 'DEFAULT', permissions: ['read'], // 默认权限,按需调整 deleteable: false, // 标记为不可删除 }); } } // 其他业务方法... }
项目启动时会自动执行这段逻辑,重复启动也不会因为唯一约束报错。
3. 服务层控制删除逻辑
在删除角色的方法中,先判断该角色是否允许删除,若deleteable为false则拒绝操作:
// src/group/group.service.ts 新增删除方法 async deleteGroup(id: number) { const group = await this.groupRepository.findOne({ where: { id } }); if (!group) { throw new Error('角色不存在'); } if (!group.deleteable) { throw new Error('该角色不允许删除'); } await this.groupRepository.delete(id); }
然后在控制器中调用该方法,处理错误并返回响应:
// src/group/group.controller.ts import { Controller, Delete, Param, HttpException, HttpStatus } from '@nestjs/common'; import { GroupService } from './group.service'; @Controller('groups') export class GroupController { constructor(private readonly groupService: GroupService) {} @Delete(':id') async delete(@Param('id') id: string) { try { await this.groupService.deleteGroup(parseInt(id)); return { message: '删除成功' }; } catch (error) { throw new HttpException(error.message, HttpStatus.FORBIDDEN); } } }
进阶:数据库层面防删除(可选)
如果担心服务层逻辑被绕过,可以在MariaDB中创建触发器,删除前检查角色名,阻止删除ADMIN和DEFAULT:
-- 执行以下SQL创建触发器 DELIMITER // CREATE TRIGGER prevent_delete_protected_groups BEFORE DELETE ON groups FOR EACH ROW BEGIN IF OLD.name IN ('ADMIN', 'DEFAULT') THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '该角色不允许删除'; END IF; END // DELIMITER ;
这个触发器会在执行DELETE操作前触发,若目标是受保护的角色则抛出错误,阻止删除。
内容的提问来源于stack exchange,提问作者luka
相关产品推荐
相关产品推荐

