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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@moeed/nest-casl

v1.1.0

Published

NestJS CASL integration

Readme

@moeed/nest-casl

A NestJS module for integrating CASL (Capability-based Authorization System Library) to manage permissions and authorization in your NestJS applications.

Introduction

@moeed/nest-casl simplifies authorization in NestJS by leveraging CASL, a powerful capability-based authorization library. With this package, you can define fine-grained permissions (abilities) based on user roles or other criteria and protect your HTTP routes, GraphQL resolvers, or other endpoints seamlessly. It provides guards, decorators, and utilities to integrate CASL into the NestJS ecosystem with minimal boilerplate.

Key features include:

  • Define abilities using CASL's fluent API.
  • Protect routes or resolvers with the AclGuard.
  • Use decorators to specify permissions and inject context data.
  • Support for custom subject hooks to fetch entities dynamically.
  • Compatible with HTTP, GraphQL, WebSocket, and RPC contexts.

Installation

Install the package via npm:

npm install @moeed/nest-casl

Peer Dependencies: Ensure you have @nestjs/common, @nestjs/core, @casl/ability, and optionally @nestjs/graphql (for GraphQL support) installed in your project.

Configuration

To use @moeed/nest-casl, you need to set up an ability factory and register the AclModule in your application.

Step 1: Create an Ability Factory

Extend the AbilityFactory abstract class to define your authorization rules and extract authentication data from the request context.

import { Injectable } from '@nestjs/common';
import { AbilityFactory, AbilityFactoryBuilder, AclActions } from '@moeed/nest-casl';
import { ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';

interface AuthPayload {
  user?: { id: string };
}
 class Post {
  id: string;
  authorId: string;
}
type Subjects = InferSubjects<typeof Post>;
@Injectable()
export class MyAbilityFactory extends AbilityFactory<AclActions, Post, AuthPayload> {
  async defineRules(builder: AbilityFactoryBuilder<Post, AclActions>, auth?: AuthPayload) {
    const { can } = builder;

    if (auth?.user?.id) {
      can(AclActions.read, 'all'); // Allow authenticated users to read everything
      can(AclActions.manage, 'Post', { authorId: auth.user.id }); // Manage own posts
    } else {
      can(AclActions.read, 'all'); // Allow guests to read everything
    }
  }

  async getAuthFromContext(context: ExecutionContext): Promise<AuthPayload | undefined> {
    const type = context.getType();
    if (type === 'http') {
      const request = context.switchToHttp().getRequest();
      return request.user; // Assumes user is set by an auth middleware
    } else if (type === 'graphql') {
      const ctx = GqlExecutionContext.create(context).getContext();
      return ctx.req?.user || ctx.user;
    }
    return undefined; // Extend for 'ws' or 'rpc' if needed
  }
}
  • defineRules: Use the CASL AbilityBuilder to specify what actions (e.g., read, manage) are allowed on which subjects (e.g., 'Post') under what conditions.
  • getAuthFromContext: Extract authentication data (e.g., user info) from the context, supporting various NestJS context types.

Step 2: Register AclModule

Import AclModule in your root module (AppModule) and provide your ability factory and any subject hooks.

import { Module } from '@nestjs/common';
import { AclModule } from '@moeed/nest-casl';
import { MyAbilityFactory } from './my-ability.factory';
import { PostHook } from './post.hook';

@Module({
  imports: [
    AclModule.forRoot({
      abilityFactory: MyAbilityFactory,
      hookProviders: [PostHook], // Optional: Add subject hooks
    }),
  ],
})
export class AppModule {}
  • hookProviders: Array of classes implementing SubjectHook for dynamic entity fetching (see "Advanced Features").
  • abilityFactory: Your custom AbilityFactory implementation.

Usage

Protect your routes or resolvers using the @ACL decorator and AclGuard. The package attaches auth and ability data to the request/context, making them accessible throughout the lifecycle.

Protecting Routes

Use @ACL to specify required permissions and AclGuard to enforce them.

import { Controller, Get, UseGuards } from '@nestjs/common';
import { ACL, AclGuard } from '@moeed/nest-casl';
import { Post } from './post.entity';
import { PostHook } from './post.hook';

@Controller('posts')
@UseGuards(AclGuard)
export class PostsController {
  @Get()
  @ACL('read', Post) // Can user read 'Post'?
  findAll() {
    return { message: 'List of posts' };
  }

  @Get(':id')
  @ACL('read', Post, PostHook) // Can user read this specific Post?
  findOne() {
    return { message: 'Single post' };
  }
}
  • @ACL(action, subject, hook?):

    • action: Permission to check (e.g., 'read', 'update').
    • subject: Subject type (string like 'Post' or class like Post).
    • hook: Optional SubjectHook to fetch the entity (e.g., PostHook).
  • If a hook is provided, the guard fetches the entity and checks the permission against it. Otherwise, it checks against the subject type.

Accessing Context Data

Use @Subject and @AuthData decorators to inject the subject entity or auth data into your handlers.

import { Controller, Get, Param } from '@nestjs/common';
import { ACL, AclGuard, Subject, AuthData } from '@moeed/nest-casl';
import { Post } from './post.entity';
import { PostHook } from './post.hook';

interface AuthPayload {
  user?: { id: string };
}

@Controller('posts')
@UseGuards(AclGuard)
export class PostsController {
  @Get(':id')
  @ACL('read', Post, PostHook)
  findOne(@Subject(Post) post: Post, @AuthData() auth: AuthPayload) {
    console.log(auth.user?.id); // Logged-in user's ID
    return post; // The fetched Post entity
  }
}
  • @Subject(subject): Injects the entity fetched by the hook (e.g., post).
  • @AuthData(): Injects the auth payload (e.g., { user: { id: '123' } }).

Advanced Features

Custom Subject Hooks

Implement SubjectHook to fetch entities dynamically based on request parameters.

import { Injectable } from '@nestjs/common';
import { SubjectHook } from '@moeed/nest-casl';
import { Post } from './post.entity';
import { PostService } from './post.service';

interface AuthPayload {
  user?: { id: string };
}

@Injectable()
export class PostHook implements SubjectHook<Post, { id: string }, AuthPayload> {
  constructor(private postService: PostService) {}

  async run(params: { id: string }, auth?: AuthPayload): Promise<Post | undefined> {
    return this.postService.findOne(params.id); // Fetch post by ID
  }
}
  • Register PostHook in AclModule.forRoot({ hookProviders: [PostHook] }).
  • Use it in @ACL('read', Post, PostHook) to check permissions against the fetched entity.

GraphQL Support

The package works seamlessly with GraphQL resolvers.

import { Resolver, Query, Args } from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';
import { ACL, AclGuard, Subject } from '@moeed/nest-casl';
import { Post } from './post.entity';
import { PostHook } from './post.hook';

@Resolver(() => Post)
@UseGuards(AclGuard)
export class PostsResolver {
  @Query(() => [Post])
  @ACL('read', 'Post')
  async posts() {
    return [{ id: '1', title: 'Example' }];
  }

  @Query(() => Post)
  @ACL('read', Post, PostHook)
  async post(@Args('id') id: string, @Subject(Post) post: Post) {
    return post;
  }
}
  • Ensure @nestjs/graphql is installed and configured.
  • The AbilityFactory handles GraphQL context automatically.

Predefined Actions

The package provides an AclActions enum for common actions:

export enum AclActions {
  create = 'create',
  read = 'read',
  update = 'update',
  delete = 'delete',
  manage = 'manage',
}

Use these in your defineRules or @ACL decorator, or define custom actions as strings.

API Reference

Core Components

  • AbilityFactory<TAction, TSubject, TAuth>

    • Abstract class to define abilities and extract auth.
    • Methods: defineRules, getAuthFromContext.
  • AclModule

    • Static forRoot(options: AclModuleOptions): Registers the module globally.
    • Options: { abilityFactory: Type<AbilityFactory>, hookProviders: Type<SubjectHook>[] }.
  • AclGuard

    • Guard that enforces permissions based on @ACL metadata.

Decorators

  • @ACL(action: string, subject: Type | string, hook?: Type<SubjectHook>)

    • Defines permission requirements for a handler.
  • @Subject(subject: Type | string)

    • Injects the fetched subject entity.
  • @AuthData()

    • Injects the auth payload.

Interfaces

  • SubjectHook<TSubject, TArgs, TAuth>
    • Method: run(params: TArgs, auth?: TAuth): Promise<TSubject | undefined>.

Examples

For complete examples, visit the example directory in the repository (update this link after publishing).

Contributing

Contributions are welcome! Please:

  1. Fork the repository.
  2. Create a feature branch.
  3. Submit a pull request with a clear description.

Report issues or suggest features on the GitHub Issues page.

License

This package is licensed under the MIT License.


Notes

  • Context Support: The package handles HTTP, GraphQL, WebSocket, and RPC contexts out of the box. Extend getAuthFromContext and getAttachTarget in AbilityFactory for custom behavior.
  • CASL Integration: Familiarity with CASL's can, cannot, and conditions (e.g., { authorId: user.id }) is recommended. See CASL docs.

This README should provide a solid foundation for users to adopt @moeed/nest-casl in their NestJS projects. Update repository links and version details before publishing to npm!