The Problem

Backend services built with NestJS often need fine‑grained permission checks (role‑based and attribute‑based) while keeping the codebase readable. Implementing that logic manually leads to duplicated guard code, hard‑to‑track permission matrices, and runtime errors that surface only in production.

What This Does

nest-access-control wraps the accesscontrol library and exposes a Nest‑style guard, decorators, and a RolesBuilder helper. Core files live under src/ (TypeScript source) and are compiled to the lib/ folder for distribution:

src/roles-builder.class.ts – extends AccessControl and provides the fluent API used to declare grants. src/access-control.guard.ts – implements CanActivate and checks the current request against the built grants. src/decorators/.ts – @UseRoles, @InjectRolesBuilder, and @UserRoles let you declare required permissions directly on route handlers.

The compiled equivalents (lib/roles-builder.class.js, lib/access-control.guard.js, etc.) are what downstream projects import (import { AccessControlModule } from 'nest-access-control').

How To Use It

Install – the repo’s package.json lists accesscontrol as a dependency, so the published package can be added with either npm or yarn:

npm i nest-access-control # or yarn add nest-access-control Define grants – create a RolesBuilder instance and chain grant definitions. The example in example/src/app.roles.ts shows the pattern:

// app.roles.ts import { RolesBuilder } from 'nest-access-control'; export enum AppRoles { USER = 'USER', ADMIN = 'ADMIN', } export const roles = new RolesBuilder();

roles .grant(AppRoles.USER) .createOwn('video') .readAny('video') .grant(AppRoles.ADMIN) .extend(AppRoles.USER) .updateAny('video') .deleteAny('video'); Register the module – import the builder in your root module (example/src/app.module.ts demonstrates this):

import { AccessControlModule } from 'nest-access-control'; import { roles } from './app.roles';

@Module({ imports: [AccessControlModule.forRoles(roles)], controllers: [AppController], providers: [AppService], }) export class AppModule {} Protect routes – use the provided decorators (@UseRoles, @UserRoles) on controller methods. See example/src/app.controller.ts for a concrete usage. Run the demo – the example application’s entry point is example/src/main.ts. From the example folder:

cd example yarn install # installs dev deps and nest CLI yarn start # runs nest start

The server starts on port 3000 (default) and exposes the sample video endpoints.

Real‑World Use

A media platform could load role definitions from a database at startup, instantiate a single RolesBuilder, and plug AccessControlModule.forRoles(builder) into the main Nest module. Controllers then annotate endpoints:

@UseRoles('updateAny', 'video') @Patch('videos/:id') async update(@Param('id') id: string, @Body() dto: UpdateDto) { … }

The guard automatically extracts the user’s role (via a custom AuthGuard that sets request.user.role) and filters response payloads according to the granted attribute list.

Code Health & Issues

Low – Missing runtime tests for guard edge cases – src/grants.controller.spec.ts covers the controller but there is no test for AccessControlGuard handling missing roles. Low – CI limited to Travis – .travis.yml exists, but no badge or status link in README; modern projects often use GitHub Actions. Low – No explicit license file in root – a LICENSE is present, but the SPDX identifier is not referenced in package.json. Low – Type definitions duplicated – both src/.ts and compiled lib/.d.ts are committed; this can cause drift if the source is updated without rebuilding. Low – No environment‑variable configuration – the guard expects request.user.role; the repo does not document a standard payload shape, leaving integration to the consumer.

Overall the project compiles cleanly, has a working example, and includes basic unit tests. No obvious security‑critical code paths are missing validation.

The Bottom Line

nest-access-control provides a thin, Nest‑idiomatic wrapper around the mature accesscontrol library, delivering role‑and‑attribute based permissions with minimal boilerplate. It is ready for integration in NestJS services that need declarative ACLs, though teams should add their own guard tests and consider moving CI to a more current platform. Suitable for medium‑scale Nest applications where centralized permission management is required.