Authorization with Pundit
Pundit is a simple and powerful authorization library that allows you to define policies for your application.
Table of Contents
Install Pundit
Github repo: https://github.com/fatihky/pundit-ts
npm install pundit-ts
Create models
models.ts
export class User {
constructor(
// the type for Data can also come from an ORM
readonly data: { id: number; role: "admin" | "editor" | "user" }) {}
}
export class Post {
constructor(readonly data: { id: number; 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);
}
async authorize(user: User, post: Post, action: PostActions) {
switch (action) {
case "create":
return (
user.data.role === "admin" ||
user.data.role === "editor" ||
user.data.role === "user"
);
case "update":
return (
user.data.role === "admin" ||
post.data.authorId === user.data.id ||
user.data.role === "editor"
);
case "delete":
return (
user.data.role === "admin" || post.data.authorId === user.data.id
);
default:
return false;
}
}
async 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({ id: 1, role: 'admin' });
const editorUser = new User({ id: 2, role: 'editor' });
const authorUser = new User({ id: 3, role: 'user' });
const otherUser = new User({ id: 4, role: 'user' });
const post = new Post({ id: 1, authorId: 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 author id matches the author id
console.log(await pundit.authorize(otherUser, post, 'delete'));
// Other user delete: false