Provides rbac for nestcloud.
$ npm i --save @nestcloud/rbac
import { Injectable, Module } from '@nestjs/common';
import { NEST_BOOT, NEST_CONSUL } from '@nestcloud/common';
import { BootModule } from '@nestcloud/boot';
import { ConsulModule } from '@nestcloud/consul';
import { RbacModule, UseValidators, ConsulValidator } from '@nestcloud/rbac';
import { HeroController } from './hero.controller';
@Injectable()
@UseValidators(ConsulValidator)
export class ValidatorRegister {
}
@Module({
imports: [
BootModule.register(__dirname, `config.yaml`),
ConsulModule.register({ dependencies: [NEST_BOOT] }),
RbacModule.register({
dependencies: [NEST_CONSUL, NEST_BOOT],
})
],
controllers: [HeroController],
providers: [ValidatorRegister],
})
export class AppModule {
}
consul:
host: localhost
port: 8500
rbac:
parameters:
name: service-rbac
The Rbac configuration has three kinds: Account, Role, RoleBinding and use '---' split these.
Please set the rbac configuration into consul kv named service-rbac.
kind: Account
name: test
---
kind: Role
name: admin
rules:
- resources: ["user"]
verbs: ["get", "list"]
---
kind: RoleBinding
role: admin
accounts:
- test
Put a user object into request instance. The RbacGuard need it for permission validation.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { IRbacAccount } from '@nestcloud/rbac';
@Injectable()
export class AccountGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
request.user = { name: request.query.user } as IRbacAccount;
return true;
}
}
Your custom AccountGuard must be set before RbacGuard.
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { AccountGuard } from './account.guard';
import { RbacGuard, Resource, Verb, Verbs } from '@nestcloud/rbac';
@Controller('/users')
@Resource('user')
@UseGuards(AccountGuard, RbacGuard)
export class HeroController {
@Get('/:userId')
@Verb(Verbs.GET)
async get(@Param('heroId') heroId: number): Promise<any> {
return { user: 'Shadow hunter' };
}
@Get('/')
@Verb(Verbs.LIST)
async list(): Promise<any> {
return { users: ['Shadow hunter', 'BladeMaster'] };
}
}
The rbac component use ConsulValidator as default validator, if you don't want to use consul as storage backend, you can write a custom validator.
import { IRbacValidator } from "./interfaces/rbac-validator.interface";
import { IRbacAccount } from "./interfaces/rbac-account.interface";
import { IRbacRole } from "./interfaces/rbac-role.interface";
import { IRbacRoleBinding } from "./interfaces/rbac-role-binding.interface";
import { Store } from "./store";
import { IRbacOptions } from "./interfaces/rbac-options.interface";
export class CustomValidator implements IRbacValidator {
private readonly store: Store = new Store();
/**
*
* @param options
* @param client
* If set config.backend to Backend.CONSUl, the client will be consul instance;
* if set config.backend to Backend.LOADBALANCE, the client will be loadbalance instance;
* if set config.backend to Backend.CUSTOM or not set, the client will be null.
*/
public async init(options: IRbacOptions, client?: any) {
const roles: IRbacRole[] = [];
const accounts: IRbacAccount[] = [];
const roleBindings: IRbacRoleBinding[] = [];
this.store.init(accounts, roles, roleBindings);
}
public validate(resource: string, verb: string, account: IRbacAccount): boolean {
return this.store.validate(account.name, resource, verb);
}
}
- Author - NestCloud
NestCloud is MIT licensed.