@piyeycorp/authz
v0.0.1
Published
A small, type-safe authorization engine for TypeScript.
Maintainers
Readme
Authz
A small, type-safe authorization engine for TypeScript applications.
Authz focuses on authorization, not authentication. Your application owns users, sessions, roles, and persistence. This package answers whether a user can perform an action on a resource.
Install
pnpm add @piyeycorp/authzBasic Usage
import {
defineAuthz,
definePermissions,
resource,
type PermissionSet,
} from "@piyeycorp/authz";
const Permissions = definePermissions({
document: ["read", "create", "update"],
blogPost: ["read", "update", "manage"],
} as const satisfies PermissionSet);
type AppUser = {
id: string;
permissionKeys: ReadonlySet<string>;
};
const authz = defineAuthz({
permissions: Permissions,
getUserPermissionKeys: (user: AppUser) => user.permissionKeys,
});
const user: AppUser = {
id: "1",
permissionKeys: new Set(["document:read"]),
};
authz.can(user, "read", "document");
authz.assertCan(user, "read", "document");getUserPermissionKeys can return either a ReadonlySet<string> of keys or a structured Permission[] with { resource, action, allowed } entries. Explicit denied entries in Permission[] win over allowed entries for the same resource/action.
Tagged Resources
Use resource(type, object) when passing plain objects.
const post = resource("blogPost", {
author: "1",
title: "Hello",
});
authz.can(user, "manage", post);Rules
Rules are evaluated before permission keys. Deny rules override allow rules.
const authz = defineAuthz({
permissions: Permissions,
getUserPermissionKeys: (user: AppUser) => user.permissionKeys,
defineRules: (user, allow, deny) => [
allow("manage", "blogPost", { author: user.id }),
deny("update", "blogPost", {
createdAt: { $lt: Date.now() - 24 * 60 * 60 * 1000 },
}),
],
});Resource Normalization
Resource matching is case-sensitive by default. Add normalizeResourceKey if your application stores permission keys in a normalized format.
const authz = defineAuthz({
permissions: Permissions,
normalizeResourceKey: (key) => key.toLowerCase(),
getUserPermissionKeys: (user: AppUser) => user.permissionKeys,
});