npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@nextnm/nestjs-next-guard

v2.2.5

Published

NestJS RBAC Guard that also checks models ownership

Downloads

34

Readme

Introduction

This is simple guard which can protect your routes by Role (RBAC) and also has the ability to check the ownership chain of the requested entity.

Example

As an example consider that you are a user belonging to an organization which has some books associated. Now, if you request a book by id this guard will check if the book that you are trying to fetch belongs to the organization that you are associated and so on. You only need to pass the models chain as well as the property chain.

Installation

npm i @nextnm/nestjs-next-guard

Usage

Caveats

  1. We only support applications using mongodb.
  2. You must be sure that in every request that the guard is used there is a user property in the request with an array of roles.
  3. It will only contemplates situations where you a have an id as request param (GET ("/:id")) or in the body (PUT updating object {_id:"...", "property1":....})

Interface Decorator

export interface ICheckOwnerShip {
  requestParam: string; // name of param that has the id mentioned in caveat 3
  modelChain: string[]; // the chain of ownership between models
  propertyChain: string[]; // array of the properties that link the models
  godRole?: string; // the role that will overcome the verification
}

Importing module

import * as mongoose from 'mongoose';
import { NextGuardModule } from '@nextnm/nestjs-next-guard';

...
@Module({
  imports: [
    DbModule,
    NextGuardModule.forRoot(),
  ],
  controllers: [],
  providers: [],
  exports: [NestjsNextGuardModule],
})
export class YOURModule {}

Importing module (Redis integration)

We support Redis cache to improve performance when we have multiple chain nodes to verify ownership

import * as mongoose from 'mongoose';
import { NextGuardModule } from '@nextnm/nestjs-next-guard';

...
@Module({
  imports: [
    DbModule,
    NextGuardModule.forRoot(
      {
        redisConfiguration: {
          url: 'redis://localhost:6379'
          retry_strategy: () => 1000,
          mongooseInstance: mongoose,
        },
      }
    ),
  ],
  controllers: [],
  providers: [],
  exports: [NestjsNextGuardModule],
})
export class YOURModule {}

Using decorators

Be aware that both decorators (Roles and CheckOwnerShip) are optional so use them as you want.

1. Use Case

User:
{
  _id:ObjectId
}

Site:
{
  _id:ObjectId,
  user:ObjectId
}

Page:
{
  _id:ObjectId,
  site:ObjectId
}
Description (A user belongs to an Site)
  1. The guard will take a look if you have role based permission to use this route
  2. The guard will look for an "Page" (modelChain[0]) by id equals to the request param;
  3. From the found Page it will try to grab the property 'site' (propertyChain[0]) and find a Site (modelChain[1]) by id equal to that property (propertyChain[0]).
  4. From the Site found it will check if the property "user" matches the id of the user making the request.
  import { CheckOwnerShip, Roles } from '@nextnm/nestjs-next-guard';

  ...

  @CheckOwnerShip({
    requestParam: 'modelId',
    propertyChain: ['site', 'user'], // The last property will be compared with the Id of the user making the request
    modelChain: ['Page','Site'],
    godRole: ExistingRoles.SYS_ADMIN, // If the user has this role not check will be done by the guard
  })
  @Roles(ExistingRoles.USER, ExistingRoles.ADMIN) // Provide the roles that you allow to execute this method,example: 'USER', 'ADMIN'
  @UseGuards(NextGuard)
  @Get(':modelId')
  async findPageById(@Param('id') id: string) {
    //...
  }

2. Use case

User:
{
_id:ObjectId,
organization:ObjectId
}


Organization:
{
  _id:ObjectId
}
Description (A user belongs to an organization)
  1. The guard will take a look if you have role based permission to use this route
  2. The guard will look for an Organization (modelChain[0]) by id equals to the request param;
  3. From the found Organization it will try to grab the property '_id' (propertyChain[0]) and find a User (modelChain[1]) by id equal to the that property (propertyChain[0]).
  4. Since there isn't any, it will try to find a User with a property "organization" (propertyChain[1]) equals to the organization "_id" property(propertyChain[0])
  5. From the User found it will check if the property "_id" matches the id of the user making the request.
  import { CheckOwnerShip, Roles } from '@nextnm/nestjs-next-guard';

    ...

    @CheckOwnerShip({
    requestParam: 'id',
    propertyChain: ['_id','organization','_id'], // The last property will be compared with the Id of the user making the request
    modelChain: ['Organization','User'],
    godRole: ExistingRoles.SYS_ADMIN, // If the user has this role not check will be done by the guard
  })
  @Roles(ExistingRoles.USER, ExistingRoles.ADMIN) // Provide the roles that you allow to execute this method,example: 'USER', 'ADMIN'
  @UseGuards(AuthGuard('jwt'),NextGuard)
  @Get('/:id')
  findOrganizationById(@Param() params): Promise<ReadOrganizationDto> {
    //...
  }

Contributing

Contributions are welcome! See Contributing.

Next steps

  1. Improve documentation
  2. Add some tests using Jest and supertest
  3. Add full support do many to many relationships between models (it doesn't alow having array of ids as relationships)
  4. Build Policy Based Guard

Author

Nuno Carvalhão (nextnm/nextNC) Site

License

Licensed under the MIT License - see the LICENSE file for details.