Authorization with Pundit

Pundit is a simple and powerful authorization library that allows you to define policies for your application.

Install Pundit

Github repo: https://github.com/fatihky/pundit-ts

npm install pundit-ts

Create models

models.ts

export class User {
  constructor(public id: number, public role: "admin" | "editor" | "user") {}
}

export class Post {
  constructor(public authorId: number) {}
}

Define actions

actions.ts

export type PostActions = "create" | "delete" | "update";

Define policies

policies.ts

import { PunditPolicy } from "pundit-ts";
import { PostActions } from "./actions";
import { Post, User } from "./models";

export class PostPolicy extends PunditPolicy<User, Post, PostActions> {
  constructor() {
    super(Post);
  }

  authorize(user: User, post: Post, action: PostActions): boolean {
    switch (action) {
      case "create":
        return (
          user.role === "admin" ||
          user.role === "editor" ||
          user.role === "user"
        );
      case "update":
        return (
          user.role === "admin" ||
          post.authorId === user.id ||
          user.role === "editor"
        );
      case "delete":
        return user.role === "admin" || post.authorId === user.id;
      default:
        return false;
    }
  }

  filter(ctx) {
    // Placeholder for filtering logic if needed
  }
}

Create pundit instance

pundit.ts

import { Pundit } from "pundit-ts";
import { User } from "./models";
import { PostPolicy } from "./policies";

export const pundit = new Pundit<User>().register(new PostPolicy())
// use .register() to register multiple policies

Validate authorization

import { Post, User } from './models';
import { pundit } from './pundit';

const adminUser = new User(1, 'admin');
const editorUser = new User(2, 'editor');
const authorUser = new User(3, 'user');
const otherUser = new User(4, 'user');

const post = new Post(3);

console.log(await pundit.authorize(adminUser, post, 'update'));
// Admin update: true

console.log(await pundit.authorize(editorUser, post, 'delete'));
// Editor delete: false

console.log(await pundit.authorize(authorUser, post, 'update'));
// Author update: true
// True because the post id matches the author id

console.log(await pundit.authorize(otherUser, post, 'delete'));
// Other user delete: false