GithubHelp home page GithubHelp logo

juicycleff / nestjs-rbac Goto Github PK

View Code? Open in Web Editor NEW

This project forked from sergey-telpuk/nestjs-rbac

0.0 2.0 0.0 195 KB

Awesome RBAC for NestJs

License: Other

Dockerfile 0.32% TypeScript 99.02% JavaScript 0.67%

nestjs-rbac's Introduction

Build Status Greenkeeper badge Scrutinizer Code Quality codecov npm

Description

The rbac module for Nest.

Installation

npm i --save nestjs-rbac

Quick Start

For using RBAC there is need to implement IStorageRbac

export interface IStorageRbac {
  roles: string[];
  permissions: object;
  grants: object;
  filters: { [key: string]: any | IFilterPermission };
}

For instance:

export const RBACstorage: IStorageRbac = {
  roles: ['admin', 'user'],
  permissions: {
    permission1: ['create', 'update', 'delete'],
    permission2: ['create', 'update', 'delete'],
    permission3: ['filter1', 'filter2', RBAC_REQUEST_FILTER],
    permission4: ['create', 'update', 'delete'],
  },
  grants: {
    admin: [
      '&user',
      'permission1',
      'permission3',
    ],
    user: ['permission2', 'permission1@create', 'permission3@filter1'],
  },
  filters: {
    filter1: TestFilterOne,
    filter2: TestFilterTwo,
    [RBAC_REQUEST_FILTER]: RequestFilter,
  },
};

Storage consists of the following keys:

roles: array of roles

permissions: objects of permissions which content actions

grants: objects of assigned permission to roles

filters: objects of customized behavior

Grant symbols

&: extends grant by another grant, for instance admin extends user (only support one level inheritance)

@: a particular action from permission, for instance permission1@update

Using RBAC like an unchangeable storage

import { Module } from '@nestjs/common';
import { RBAcModule } from 'nestjs-rbac';

@Module({
  imports: [
    RBAcModule.forRoot(IStorageRbac),
  ],
  controllers: []
})
export class AppModule {}

Using RBAC like a dynamic storage

There is enough to implement IDynamicStorageRbac interface.

import { Module } from '@nestjs/common';
import { RBAcModule } from 'nestjs-rbac';

@Module({
  imports: [
    RBAcModule.forDynamic(DynamicStorageService),
  ],
  controllers: []
})
export class AppModule {}
// implement dynamic storage
import { IDynamicStorageRbac, IStorageRbac } from 'nestjs-rbac';
@Injectable()
export class  DynamicStorageService implements IDynamicStorageRbac {
  constructor(
    private readonly repository: AnyRepository
  ) {
    
  }
  async getRbac(): Promise<IStorageRbac> {
//use any persistence storage for getting `RBAC`
      return  await this.repository.getRbac();
  }
}

Using for routers

import { RBAcPermissions, RBAcGuard } from 'nestjs-rbac';

@Controller()
export class RbacTestController {

  @RBAcPermissions('permission', 'permission@create')
  @UseGuards(
// Any Guard for getting & adding user to request which implements `IRole` interface from `nestjs-rbac`:  
//*NOTE: 
//  const request = context.switchToHttp().getRequest();
//  const user: IRole = request.user;
    GuardIsForAddingUserToRequestGuard, 
    RBAcGuard,
  )
  @Get('/')
  async test1(): Promise<boolean> {
    return true;
  }
}

Using like service

import { RbacService } from 'nestjs-rbac';

@Controller()
export class RbacTestController {

  constructor(
    private readonly rbac: RbacService
  ){}
    
  @Get('/')
  async test1(): Promise<boolean> {
    await this.rbac.getRole(role).can('permission', 'permission@create');
    return true;
  }
}

Using the custom filters

filter is a great opportunity of customising behaviour RBAC. For creating filter, there is need to implement IFilterPermission interface, which requires for implementing can method, and bind a key filter with filter implementation, like below:

export const RBAC: IStorageRbac = {
  roles: ['role'],
  permissions: {
    permission1: ['filter1'],
  },
  grants: {
    role: [
      `permission1@filter1`
    ],
  },
  filters: {
    filter1: TestFilter,
  },
};  
//===================== implementing filter
import { IFilterPermission } from 'nestjs-rbac';

export class TestFilter implements IFilterPermission {

  can(params?: any[]): boolean {
    return params[0];
  }

}

ParamsFilter services for passing arguments into particular filter:

const filter = new ParamsFilter();
filter.setParam('filter1', some payload);

const res = await rbacService.getRole('admin', filter).can(
  'permission1@filter1',
);

Also RBAC has a default filter RBAC_REQUEST_FILTER which has request object as argument:

Example:
//===================== filter
export class RequestFilter implements IFilterPermission {

  can(params?: any[]): boolean {
    return params[0].headers['test-header'] === 'test';
  }
}
//===================== storage
export const RBAC: IStorageRbac = {
  roles: ['role'],
  permissions: {
    permission1: ['filter1', 'filter2', RBAC_REQUEST_FILTER],
  },
  grants: {
    role: [
      `permission1@${RBAC_REQUEST_FILTER}`
    ],
  },
  filters: {
    [RBAC_REQUEST_FILTER]: RequestFilter,
  },
};  
//===================== using for routes
  @RBAcPermissions(`permission1@${RBAC_REQUEST_FILTER}`)
  @UseGuards(
    AuthGuard,
    RBAcGuard,
  )
  @Get('/')
  async test4(): Promise<boolean> {
    return true;
  }

Performance

By default, RBAC storage always parses grants for each request, in some cases, it can be a very expensive operation. The bigger RBAC storage, the more taking time for parsing. For saving performance RBAC has built-in a cache, based on node-cache

Using cache

import { RbacCache } from 'nestjs-rbac';

@Module({
  imports: [
    RBAcModule.useCache(RbacCache, {KEY: 'RBAC', TTL: 400}).forDynamic(AsyncService),
  ],
})

if you need to change a cache storage, there is enough to implement ICacheRBAC

ICacheRBAC

export interface ICacheRBAC {
  KEY: string;
  TTL: number;

  get(): object | null;

  /**
   *
   * @param value
   */
  set(value: object): void;

  del(): void;
}

Inject ICacheRBAC

import { ICacheRBAC } from 'nestjs-rbac';
...
@Inject('ICacheRBAC') cache: ICacheRBAC

nestjs-rbac's People

Contributors

tsergey-itrex avatar sergey-telpuk avatar greenkeeper[bot] avatar juicycleff avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.