add rbac module

This commit is contained in:
liuyi 2025-06-25 17:44:48 +08:00
parent 9d23757f45
commit bbc9c5d6bf
6 changed files with 215 additions and 0 deletions

View File

@ -0,0 +1,66 @@
import { AbilityTuple, MongoQuery, RawRuleFrom } from '@casl/ability';
import { Exclude, Expose } from 'class-transformer';
import { Column, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn, Relation } from 'typeorm';
import { UserEntity } from '@/modules/user/entities';
import { RoleEntity } from './role.entity';
/**
*
*/
@Exclude()
@Entity('rbac_permission')
export class PermissionEntity<
P extends AbilityTuple = AbilityTuple,
T extends MongoQuery = MongoQuery,
> {
/**
* ID
*/
@Expose()
@PrimaryGeneratedColumn('uuid')
id: string;
/**
*
*/
@Expose()
@Column({ comment: '权限名称' })
name: string;
/**
*
*/
@Expose()
@Column({ comment: '权限显示名', nullable: true })
label?: string;
/**
*
*/
@Expose()
@Column({ comment: '权限描述', nullable: true, type: 'text' })
description?: string;
/**
*
*/
@Column({ type: 'simple-json', comment: '权限规则' })
rule: Omit<RawRuleFrom<P, T>, 'conditions'>;
/**
*
*/
@Expose({ groups: ['permission-list', 'permission-detail'] })
@ManyToMany(() => RoleEntity, (role) => role.permissions, { cascade: true })
@JoinTable()
roles: Relation<RoleEntity>[];
/**
*
*/
@ManyToMany(() => UserEntity, (user) => user.permissions)
@JoinTable()
users: Relation<UserEntity>[];
}

View File

@ -0,0 +1,79 @@
import { Exclude, Expose, Type } from 'class-transformer';
import {
BaseEntity,
Column,
DeleteDateColumn,
Entity,
JoinTable,
ManyToMany,
PrimaryGeneratedColumn,
Relation,
} from 'typeorm';
import { UserEntity } from '@/modules/user/entities';
import { PermissionEntity } from './permission.entity';
/**
*
*/
@Exclude()
@Entity('rbac_role')
export class RoleEntity extends BaseEntity {
/**
* ID
*/
@Expose()
@PrimaryGeneratedColumn('uuid')
id: string;
/**
*
*/
@Column({ comment: '角色名称' })
name: string;
/**
*
*/
@Column({ comment: '显示名称', nullable: true })
label?: string;
/**
*
*/
@Column({ comment: '角色描述', nullable: true, type: 'text' })
description?: string;
/**
*
*/
@Column({ comment: '是否为不可更改的系统权限', default: false })
systemed?: boolean;
/**
*
*/
@Expose({ groups: ['role-detail', 'role-list'] })
@Type(() => Date)
@DeleteDateColumn({ comment: '删除时间' })
deletedAt: Date;
/**
*
*/
@Expose({ groups: ['role-detail'] })
@Type(() => PermissionEntity)
@ManyToMany(() => PermissionEntity, (permission) => permission.roles, {
cascade: true,
eager: true,
})
permissions: Relation<PermissionEntity>[];
/**
*
*/
@ManyToMany(() => UserEntity, (user) => user.roles, { deferrable: 'INITIALLY IMMEDIATE' })
@JoinTable()
users: Relation<UserEntity>[];
}

View File

@ -0,0 +1,21 @@
import { AbilityTuple, MongoQuery } from '@casl/ability';
import { SelectQueryBuilder } from 'typeorm';
import { BaseRepository } from '@/modules/database/base/repository';
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
import { PermissionEntity } from '../entities/permission.entity';
@CustomRepository(PermissionEntity)
export class PermissionRepository extends BaseRepository<PermissionEntity> {
protected _qbName: string = 'permission';
buildBaseQB(): SelectQueryBuilder<PermissionEntity<AbilityTuple, MongoQuery>> {
return this.createQueryBuilder(this.qbName).leftJoinAndSelect(
`${this.qbName}.roles`,
'roles',
);
}
}

View File

@ -0,0 +1,19 @@
import { SelectQueryBuilder } from 'typeorm';
import { BaseRepository } from '@/modules/database/base/repository';
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
import { RoleEntity } from '../entities/role.entity';
@CustomRepository(RoleEntity)
export class RoleRepository extends BaseRepository<RoleEntity> {
protected _qbName: string = 'role';
buildBaseQB(): SelectQueryBuilder<RoleEntity> {
return this.createQueryBuilder(this.qbName).leftJoinAndSelect(
`${this.qbName}.permissions`,
'permissions',
);
}
}

View File

@ -0,0 +1,15 @@
import { isNil } from 'lodash';
import { BaseSubscriber } from '@/modules/database/base/subscriber';
import { PermissionEntity } from '../entities/permission.entity';
export class PermissionSubscriber extends BaseSubscriber<PermissionEntity> {
protected entity = PermissionEntity;
async afterLoad(entity: PermissionEntity): Promise<void> {
if (isNil(entity.label)) {
entity.label = entity.name;
}
}
}

View File

@ -0,0 +1,15 @@
import { isNil } from 'lodash';
import { BaseSubscriber } from '@/modules/database/base/subscriber';
import { RoleEntity } from '../entities/role.entity';
export class RoleSubscriber extends BaseSubscriber<RoleEntity> {
protected entity = RoleEntity;
async afterLoad(entity: RoleEntity): Promise<void> {
if (isNil(entity.label)) {
entity.label = entity.name;
}
}
}