add rbac module

This commit is contained in:
liuyi 2025-06-29 20:07:05 +08:00
parent 5de299c0c1
commit 23c8eba867
11 changed files with 758 additions and 587 deletions

View File

@ -40,6 +40,7 @@
"dayjs": "^1.11.13",
"deepmerge": "^4.3.1",
"dotenv": "^16.5.0",
"fastify": "^5.4.0",
"find-up": "^7.0.0",
"fs-extra": "^11.3.0",
"jsonwebtoken": "^9.0.2",

File diff suppressed because it is too large Load Diff

View File

@ -6,3 +6,12 @@ export enum SystemRoles {
export const SYSTEM_PERMISSION = 'system-manage';
export const PERMISSION_CHECKERS = 'permission_checkers';
export enum PermissionAction {
CREATE = 'create',
READ = 'read',
UPDATE = 'update',
DELETE = 'delete',
MANAGE = 'manage',
OWNER = 'onwer',
}

View File

@ -0,0 +1,2 @@
export * from './permission.entity';
export * from './role.entity';

View File

@ -0,0 +1,52 @@
import { DynamicModule, forwardRef, Module } from '@nestjs/common';
import { getDataSourceToken } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { DatabaseModule } from '@/modules/database/database.module';
import { RbacGuard } from '@/modules/rbac/guards/rbac.guard';
import { RbacResolver } from '@/modules/rbac/rbac.resolver';
import { Configure } from '../config/configure';
import { addEntities, addSubscribers } from '../database/utils';
import { UserModule } from '../user/user.module';
import * as entities from './entities';
import * as repositories from './repositories';
import * as services from './services';
import * as subscribers from './subscribers';
@Module({})
export class RbacModule {
static async forRoot(configure: Configure): Promise<DynamicModule> {
return {
module: RbacModule,
imports: [
forwardRef(() => UserModule),
await addEntities(configure, Object.values(entities)),
DatabaseModule.forRepository(Object.values(repositories)),
],
providers: [
...Object.values(services),
...(await addSubscribers(configure, Object.values(subscribers))),
RbacGuard,
{
provide: RbacResolver,
useFactory: async (dataSource: DataSource) => {
const resolver = new RbacResolver(dataSource, configure);
resolver.setOptions({});
return resolver;
},
inject: [getDataSourceToken()],
},
],
exports: [
RbacResolver,
...Object.values(services),
DatabaseModule.forRepository(Object.values(repositories)),
],
};
}
}

View File

@ -68,6 +68,7 @@ export class RbacResolver<P extends AbilityTuple = AbilityTuple, T extends Mongo
if (!this.setuped) {
this.options = options;
this.setuped = true;
console.log(this.options);
}
return this;
}

View File

@ -0,0 +1,2 @@
export * from './permission.repository';
export * from './role.repository';

View File

@ -0,0 +1,2 @@
export * from './permission.service';
export * from './role.service';

View File

@ -0,0 +1,2 @@
export * from './permission.subscriber';
export * from './role.subscriber';

19
src/modules/rbac/utils.ts Normal file
View File

@ -0,0 +1,19 @@
import { MongoAbility } from '@casl/ability';
import { FastifyRekquest as Request } from 'fastify';
import { ObjectLiteral } from 'typeorm';
import { PermissionAction } from './constants';
export async function checkOwnerPermission<T extends ObjectLiteral>(
ability: MongoAbility,
options: {
request: Request;
key?: string;
getData: (items: string[]) => Promise<T[]>;
permission?: string;
},
) {
const { request, key, getData, permission } = options;
const models = await getData(getRequestData(request, key));
return models.every((model) => ability.can(permission ?? PermissionAction.OWNER, model));
}

View File

@ -7,7 +7,6 @@ import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify
import { existsSync } from 'fs-extra';
import { isNil } from 'lodash';
import { JwtAuthGuard } from '@/modules/user/guards';
import { UserModule } from '@/modules/user/user.module';
import * as configs from './config';
@ -16,6 +15,7 @@ import { CreateOptions } from './modules/core/types';
import * as dbCommands from './modules/database/commands';
import { DatabaseModule } from './modules/database/database.module';
import { MeiliModule } from './modules/meilisearch/meili.module';
import { RbacGuard } from './modules/rbac/guards/rbac.guard';
import { Restful } from './modules/restful/restful';
import { RestfulModule } from './modules/restful/restful.module';
import { ApiConfig } from './modules/restful/types';
@ -30,7 +30,7 @@ export const createOptions: CreateOptions = {
await ContentModule.forRoot(configure),
await UserModule.forRoot(configure),
],
globals: { guard: JwtAuthGuard },
globals: { guard: RbacGuard },
builder: async ({ configure, BootModule }) => {
const container = await NestFactory.create<NestFastifyApplication>(
BootModule,