Permix allows you to define granular permissions using a PermissionsDefinition. You can associate actions with specific TypeScript types and use closures (functions) to implement relationship-based access control (ReBAC). This allows you to check permissions against specific object instances (e.g., checking if a user is the author of a comment).
import { createPermix } from 'permix'
interface User { id: string; role: 'editor' | 'user' }
interface Post { id: string; title: string; authorId: string; published: boolean }
interface Comment { id: string; content: string; authorId: string }
type PermissionsDefinition = {
post: [
{ name: 'create', type: Post },
{ name: 'read', type: Post },
{ name: 'update', type: Post },
{ name: 'delete', type: Post },
]
comment: [
{ name: 'create', type: Comment },
{ name: 'read', type: Comment },
{ name: 'update', type: Comment },
]
}
const permix = createPermix<PermissionsDefinition>()
// Using templates to create reusable permission sets
const userPermissions = permix.template(({ id: userId }: User) => ({
post: {
create: false,
read: true,
update: false,
delete: false,
},
comment: {
create: true,
read: true,
// Relationship-based rule using a closure
update: (comment: Comment) => comment?.authorId === userId,
},
}))
// Applying the template via setup
const user: User = { id: '1', role: 'user' }
permix.setup(userPermissions(user))
// Checking permission against an instance
const comment: Comment = { id: '1', content: 'Hello', authorId: '1' }
const canUpdate = permix.check('comment.update', comment) // true