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

@cjr-unb/autho

v1.1.1

Published

Module for authorization in NestJS built with CASL and integrated with Prisma

Downloads

43

Readme

@cjr-unb/autho

Módulo para autorização em NestJS construído com CASL e integrado com o Prisma.

Instalação

É necessário ter Nest e o Prisma instalados com pelo menos uma migração executada. Em seguida, execute o comando:

npm install @cjr-unb/autho

Como usar

Definindo Regras

Defina as regras de autorização da sua aplicação numa função de callback do tipo Rules. Essa função recebe o tipo do usuário armazenado no token JWT e um objeto com as propriedades can, cannot e user.

import { Rules } from "@cjr-unb/autho";
import { JwtPayload } from "./auth/dtos/jwt-payload.dto";

export const rules: Rules<JwtPayload> = ({ can, cannot, user }) => {
  // Defina aqui as regras de autorização da sua aplicação. Exemplo:

  if (user.roles.includes("admin")) can("manage", "all");

  can("update", "post", { authorId: user.id });
};

Os nomes das possíveis actions são: manage, create, read, update e delete. Os nomes dos possíveis resources são: all e o nome das entidades do seu banco de dados. Você pode definir actions e resources customizados. Veja a seção Definindo Actions e Resources Customizados.

A definição das regras é feita como descrito na documentação do CASL.

AuthoModule

Adicione o AuthoModule utilizando o método forRoot em um dos módulos da sua aplicação. Os argumentos que o método recebe são:

  • <JwtPayload>: Tipo do usuário armazenado no token JWT.
  • Options:
    • PrismaModule: Módulo do prisma que deve exportar o PrismaService
    • rules: Função de callback que contém as regras de autenticação. Recebe um objeto com as propriedades can, cannot e user.
    • userProperty?: Nome da propriedade que contém o usuário autenticado no objeto request. Default: user.
    • exceptionIfNotFound?: Tipo de exceção que deve ser lançada caso o recurso não seja encontrado no banco de dados. Os possíveis valores são: 404, 403 e prisma. Default: not found.
    • forbiddenMessage?: Função que recebe o nome da action e do resource que o usuário não tem permissão para acessar e retorna a mensagem que deve ser exibida na exceção. Caso não seja definida, a mensagem "Forbidden resource" será exibida. Default: undefined.
    • numberIdName?: Nome da propriedade que contém o id do recurso no Prisma. Deve ser utilizado quando o id do recurso é um número. Você deve escolher entre numberIdName e stringIdName. Default: id.
    • stringIdName?: Nome da propriedade que contém o id do recurso no Prisma. Deve ser utilizado quando o id do recurso é uma string. Você deve escolher entre numberIdName e stringIdName. Default: undefined.
import { AuthoModule } from "@cjr-unb/autho";
import { JwtPayload } from "./auth/dtos/jwt-payload.dto";
import { Module } from "@nestjs/common";
import { PrismaModule } from "./prisma/prisma.module";
import { rules } from "./auth/auth.rules";

@Module({
  imports: [
    AuthoModule.forRoot<JwtPayload>({
      PrismaModule,
      rules,
    }),
  ],
})
export class AppModule {}

Decorator Ability

Agora você pode utilizar o decorator @Ability em qualquer rota da sua aplicação. O decorator recebe a ação que o usuário está tentando executa, o nome do recurso que ele está tentando acessar e opções adicionais.

import { Ability } from "@cjr-unb/autho";
import { Controller, Get, UseGuards } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";

@Controller("post")
export class PostsController {
  @Ability("read", "post")
  @UseGuards(AuthGuard("jwt")) // O guard de autenticação deve ser executado antes do guard de autorização
  @Get()
  findAll() {
    // ...
  }
}

Caso seja necessário consultar o banco de dados para verificar se o usuário tem permissão para acessar o recurso, você pode utilizar a opção useDb. O recurso será buscado através do id passado no parâmetro da rota.

O nome da propriedade que contém o id do recurso no é definido nas opções numberIdName ou stringIdName.

Se na sua rota, o nome da propriedade que contém o id do recurso no for diferente do definido na opção numberIdName ou stringIdName, você pode passar o nome correto na opção param.

Caso o recurso não seja encontrado, o Autho lançará uma exceção do tipo definido na opção exceptionIfNotFound.

import { Ability } from "@cjr-unb/autho";
import { Controller, Get, UseGuards } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";

@Controller("post")
export class PostsController {
  @Ability("read", "post", { useDb: true, param: "postId" })
  @UseGuards(AuthGuard("jwt"))
  @Get(":postId")
  findOne() {
    // ...
  }
}

Agora quando um usuário que não tem permissão tentar acessar a rota, uma exceção do tipo ForbiddenException será lançada.

Definindo Actions e Resources Customizados

É possível definir seus próprios actions e resources customizados criando um tipo que contém as propriedades action e resource e passando esse tipo como parâmetro para a função rules, para o AuthoModule, para o decorator Ability e para a função forbiddenMessage caso ela seja definida.

Você pode extender as Actions e Resources padrões através dos tipos DefaultActions e DefaultResources.

import { DefaultActions, DefaultResources } from "@cjr-unb/autho";

export type CustomOptions = {
  actions: "operate" | DefaultActions;
  resources: "calculator" | DefaultResources;
};

Na função rules:

import { Rules } from "@cjr-unb/autho";
import { JwtPayload } from "./auth/dtos/jwt-payload.dto";
import { CustomOptions } from "./custom-options";

export const rules: Rules<JwtPayload, CustomOptions> = ({
  can,
  cannot,
  user,
}) => {
  if (user.roles.includes("admin")) can("operate", "calculator");
};

No AuthoModule:

import { AuthoModule } from "@cjr-unb/autho";
import { JwtPayload } from "./auth/dtos/jwt-payload.dto";
import { Module } from "@nestjs/common";
import { PrismaModule } from "./prisma/prisma.module";
import { rules } from "./auth/auth.rules";
import { CustomOptions } from "./custom-options";

@Module({
  imports: [
    AuthoModule.forRoot<JwtPayload, CustomOptions>({
      PrismaModule,
      rules,
    }),
  ],
})
export class AppModule {}

No decorator Ability:

import { Ability } from "@cjr-unb/autho";
import { Controller, Get, UseGuards } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { CustomOptions } from "./custom-options";

@Controller("calculator")
export class CalculatorController {
  @Ability<CustomOptions>("operate", "calculator")
  @UseGuards(AuthGuard("jwt"))
  @Get()
  operate() {
    // ...
  }
}

Limitações

Atualmente, para o funcionamento correto do Autho, é necessário que em todas as models do Prisma o nome da coluna que contém a PK sejam iguais.

Além disso, o Autho não tem suporte para definição de aliases para as actions.