{"_id":"@actinode/express-permission","_rev":"5-40e3aacdf02880b8d19822e1bb175f34","name":"@actinode/express-permission","dist-tags":{"latest":"0.1.4"},"versions":{"0.1.0":{"name":"@actinode/express-permission","version":"0.1.0","keywords":["express","middleware","permissions","roles","rbac","authorization"],"license":"MIT","_id":"@actinode/express-permission@0.1.0","maintainers":[{"name":"actinode","email":"actinodesolutions@gmail.com"}],"dist":{"shasum":"ea1e70820f62c6acfb9a85e04dc428decec52e82","tarball":"https://registry.npmjs.org/@actinode/express-permission/-/express-permission-0.1.0.tgz","fileCount":8,"integrity":"sha512-7J9Ud1c5xgcSplKF/kgPUXB64ACk9jyYZYv5AfA1XXwIkjgFR8AzEtaa6nA+aohejwaU+S3N/7jvbyZe8+51ug==","signatures":[{"sig":"MEYCIQCcfigem240+YrNcyURTGBBjpke9VcCtpe4Alll0tb6bAIhAJC1GYCavyz5lUsJ6gkBkGL5IN49AcCD4whS78xPol0w","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":127074},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"ad83ed29e241c85f9bf6274720740ad41204533d","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"actinode","email":"actinodesolutions@gmail.com"},"_npmVersion":"10.9.3","description":"Express middleware for role-based permissions — roles, direct permissions, and permission groups","directories":{},"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.0","express":"^5.1.0","typescript":"^5.9.3","@types/node":"^25.5.0","@types/express":"^5.0.3"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/express-permission_0.1.0_1774479183757_0.0012530934783734349","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@actinode/express-permission","version":"0.1.1","keywords":["express","middleware","permissions","roles","rbac","authorization"],"license":"MIT","_id":"@actinode/express-permission@0.1.1","maintainers":[{"name":"actinode","email":"actinodesolutions@gmail.com"}],"dist":{"shasum":"20bacfb0a87f07b561ad2db8c0349593d3d39536","tarball":"https://registry.npmjs.org/@actinode/express-permission/-/express-permission-0.1.1.tgz","fileCount":8,"integrity":"sha512-YAvjneXxqmKPHyqQijenmjPkawleEFQZ5vuJVWl45bqPlaUolaOv/auZfwkimZF4HIvDiEMb3kKth6yUK/X8DQ==","signatures":[{"sig":"MEYCIQCJzU/fQTfp3qbE5NRKUtRDKx8NDlgAaLWMipBFOZauCAIhAPLqiRMgydZr1rl6cW+c0TyCiYsBEk+ZczYK8tefezoK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":126987},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"ad83ed29e241c85f9bf6274720740ad41204533d","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"actinode","email":"actinodesolutions@gmail.com"},"_npmVersion":"10.9.3","description":"Express middleware for role-based permissions — roles, direct permissions, and permission groups","directories":{},"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.0","express":"^5.1.0","typescript":"^5.9.3","@types/node":"^25.5.0","@types/express":"^5.0.3"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/express-permission_0.1.1_1774479253387_0.2942496619407331","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@actinode/express-permission","version":"0.1.2","keywords":["express","middleware","permissions","roles","rbac","authorization"],"license":"MIT","_id":"@actinode/express-permission@0.1.2","maintainers":[{"name":"actinode","email":"actinodesolutions@gmail.com"}],"dist":{"shasum":"d81eda88ed3b57b103ec9fbf503065735aed501f","tarball":"https://registry.npmjs.org/@actinode/express-permission/-/express-permission-0.1.2.tgz","fileCount":8,"integrity":"sha512-hyT6PSjEE891t3yu9dgXBS6eg0LUVnayWzcsv1FfcZC/akjopAWHsuZkdFM8MSSICha5p8tJrPBDlMaRJnVNiA==","signatures":[{"sig":"MEUCIQC5vBwhAJreKputqecss70UbkJjxPnHJzzL5clmgXuuyAIgcKB49tvPKIe54iC13Lfr/yucklIoIToONt4ppqQGDCs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":128238},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"3407619148484c51b364a0c6e773e4db5a454119","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"actinode","email":"actinodesolutions@gmail.com"},"_npmVersion":"10.9.3","description":"Express middleware for role-based permissions — roles, direct permissions, and permission groups","directories":{},"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.0","express":"^5.1.0","typescript":"^5.9.3","@types/node":"^25.5.0","@types/express":"^5.0.3"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/express-permission_0.1.2_1774562939784_0.3462379657369312","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@actinode/express-permission","version":"0.1.3","keywords":["express","middleware","permissions","roles","rbac","authorization"],"license":"MIT","_id":"@actinode/express-permission@0.1.3","maintainers":[{"name":"actinode","email":"actinodesolutions@gmail.com"}],"dist":{"shasum":"4292aa5164d5c4ce65f9417506d2de18206f0ec9","tarball":"https://registry.npmjs.org/@actinode/express-permission/-/express-permission-0.1.3.tgz","fileCount":8,"integrity":"sha512-PzYgxB+1PI+U8A9g4JxsDOv8cRKDOzYteOblY9HAdYmDvCu8MQaBWTgdToC4YFm89EXmBvu2bmWVyCCBh5B3EQ==","signatures":[{"sig":"MEYCIQCyh7Ycj754IaEUaGPdKAM+2xaM/jAYnMaKL8e3y9szvgIhAKmKFAU/h6mWjQd9TKqq8OqWCXNPndrhTXaP5iEg22lI","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":128870},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"7fb46e95cf68bc30a5c526d48735d0f0daadf2f4","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"actinode","email":"actinodesolutions@gmail.com"},"_npmVersion":"10.9.3","description":"Express middleware for role-based permissions — roles, direct permissions, and permission groups","directories":{},"_nodeVersion":"22.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.0","express":"^5.1.0","typescript":"^5.9.3","@types/node":"^25.5.0","@types/express":"^5.0.3"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/express-permission_0.1.3_1774564685196_0.49671744553613784","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@actinode/express-permission","version":"0.1.4","description":"Express middleware for role-based permissions — roles, direct permissions, and permission groups","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit"},"homepage":"https://docs.actinode.com/express/permission/","repository":{"type":"git","url":"git+https://github.com/actinode/community.git"},"bugs":{"url":"https://github.com/actinode/community/issues/new?template=bug_report.md"},"keywords":["actinode","express","permission","roles","authorization","middleware","nodejs","typescript","prisma","mongoose"],"license":"MIT","peerDependencies":{"express":"^4.0.0 || ^5.0.0"},"devDependencies":{"@types/express":"^5.0.3","@types/node":"^25.5.0","express":"^5.1.0","tsup":"^8.5.1","typescript":"^5.9.3","vitest":"^4.1.0"},"publishConfig":{"access":"public"},"_id":"@actinode/express-permission@0.1.4","gitHead":"190d302f63d061373695b9247a0774dcb70bda72","_nodeVersion":"22.19.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-ZH7Q/3BrEzGHBVxxe5OTLQvQX4cMI9eqpTBw5CQvB3G8G709yZ5xuthrAuyjExJkzr39i2gKxDtXx0IXrx+FXA==","shasum":"080a00e35fdff3e6ffc73e54c043d7a54ca73566","tarball":"https://registry.npmjs.org/@actinode/express-permission/-/express-permission-0.1.4.tgz","fileCount":8,"unpackedSize":129193,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGJ1yiJopaYkAwZ+WoqUzt4WAvvpcAC+cOVNsm7M7LSIAiAj/8Vcl1ymCXF899hAOKtROT2SG9XMONNOCvRsmH1C1g=="}]},"_npmUser":{"name":"actinode","email":"actinodesolutions@gmail.com"},"directories":{},"maintainers":[{"name":"actinode","email":"actinodesolutions@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/express-permission_0.1.4_1774565092799_0.05118575287209981"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-25T22:53:03.632Z","modified":"2026-03-26T22:44:53.097Z","0.1.0":"2026-03-25T22:53:03.916Z","0.1.1":"2026-03-25T22:54:13.541Z","0.1.2":"2026-03-26T22:08:59.928Z","0.1.3":"2026-03-26T22:38:05.358Z","0.1.4":"2026-03-26T22:44:52.982Z"},"license":"MIT","keywords":["actinode","express","permission","roles","authorization","middleware","nodejs","typescript","prisma","mongoose"],"description":"Express middleware for role-based permissions — roles, direct permissions, and permission groups","maintainers":[{"name":"actinode","email":"actinodesolutions@gmail.com"}],"readme":"# @actinode/express-permission\n\n[![Documentation](https://img.shields.io/badge/docs-actinode.com-blue)](https://docs.actinode.com)\n[![npm](https://img.shields.io/npm/v/@actinode/express-permission)](https://www.npmjs.com/package/@actinode/express-permission)\n[![license](https://img.shields.io/npm/l/@actinode/express-permission)](LICENSE)\n\nRole-based permissions for Express — roles, direct permissions, and permission groups.\n\n📚 **Full documentation at [docs.actinode.com](https://docs.actinode.com)**\n\n## Installation\n\n```bash\nnpm install @actinode/express-permission\n# or\npnpm add @actinode/express-permission\n```\n\n> For detailed installation guide visit [docs.actinode.com](https://docs.actinode.com/express/permission/)\n\n---\n\n## Setup with Prisma\n\nAdd the following models to your `schema.prisma`:\n\n```prisma\nmodel Role {\n  id          String   @id @default(cuid())\n  name        String   @unique\n  permissions Permission[]\n  users       UserRole[]\n  createdAt   DateTime @default(now())\n}\n\nmodel Permission {\n  id    String  @id @default(cuid())\n  name  String  @unique\n  roles Role[]\n  users UserPermission[]\n}\n\nmodel PermissionGroup {\n  id          String   @id @default(cuid())\n  name        String   @unique\n  permissions String[]\n  createdAt   DateTime @default(now())\n}\n\nmodel UserRole {\n  userId    String\n  roleId    String\n  role      Role   @relation(fields: [roleId], references: [id])\n  @@id([userId, roleId])\n}\n\nmodel UserPermission {\n  userId       String\n  permissionId String\n  permission   Permission @relation(fields: [permissionId], references: [id])\n  @@id([userId, permissionId])\n}\n\nmodel UserGroup {\n  userId  String\n  group   String\n  @@id([userId, group])\n}\n```\n\nThen set up the instance:\n\n```ts\nimport { createPermission, prismaAdapter } from '@actinode/express-permission'\nimport { PrismaClient } from '@prisma/client'\n\nconst prisma = new PrismaClient()\n\nconst permission = createPermission({\n  adapter: prismaAdapter(prisma),\n  getUserId: (req) => req.user?.id,\n})\n```\n\n---\n\n## Setup with Mongoose\n\nDefine your models and pass them to the adapter:\n\n```ts\nimport mongoose from 'mongoose'\nimport { createPermission, mongooseAdapter } from '@actinode/express-permission'\nimport type { MongooseModels } from '@actinode/express-permission'\n\nconst RoleSchema = new mongoose.Schema({\n  name:        { type: String, required: true, unique: true },\n  permissions: [{ type: String }],\n  createdAt:   { type: Date, default: Date.now },\n})\n\nconst PermissionSchema = new mongoose.Schema({\n  name: { type: String, required: true, unique: true },\n})\n\nconst PermissionGroupSchema = new mongoose.Schema({\n  name:        { type: String, required: true, unique: true },\n  permissions: [{ type: String }],\n  createdAt:   { type: Date, default: Date.now },\n})\n\nconst UserRoleSchema = new mongoose.Schema({ userId: String, roleName: String })\nUserRoleSchema.index({ userId: 1, roleName: 1 }, { unique: true })\n\nconst UserPermissionSchema = new mongoose.Schema({ userId: String, permissionName: String })\nUserPermissionSchema.index({ userId: 1, permissionName: 1 }, { unique: true })\n\nconst UserGroupSchema = new mongoose.Schema({ userId: String, group: String })\nUserGroupSchema.index({ userId: 1, group: 1 }, { unique: true })\n\nconst models: MongooseModels = {\n  Role:            mongoose.model('Role',            RoleSchema),\n  Permission:      mongoose.model('Permission',      PermissionSchema),\n  PermissionGroup: mongoose.model('PermissionGroup', PermissionGroupSchema),\n  UserRole:        mongoose.model('UserRole',        UserRoleSchema),\n  UserPermission:  mongoose.model('UserPermission',  UserPermissionSchema),\n  UserGroup:       mongoose.model('UserGroup',       UserGroupSchema),\n}\n\nconst permission = createPermission({\n  adapter: mongooseAdapter(models),\n  getUserId: (req) => req.user?.id,\n})\n```\n\n---\n\n## Middleware Usage\n\nProtect routes by attaching middleware:\n\n```ts\n// Require a single permission\napp.get('/posts', permission.can('view-posts'), handler)\n\n// Require a role\napp.delete('/posts/:id', permission.hasRole('admin'), handler)\n\n// Require any one of multiple permissions\napp.put('/posts/:id', permission.canAny(['edit-posts', 'manage-posts']), handler)\n\n// Require all permissions\napp.put('/posts/:id', permission.canAll(['edit-posts', 'publish-posts']), handler)\n```\n\nUnauthorized (no userId): `401 { error: 'Unauthorized', message: 'User not authenticated' }`\n\nForbidden (lacks permission): `403 { error: 'Forbidden', message: '...' }`\n\n> For full API reference and more examples visit [docs.actinode.com](https://docs.actinode.com/express/permission/api)\n\n---\n\n## Helper Functions\n\n### assign\n\n```ts\nawait permission.assign.role(userId, 'admin')\nawait permission.assign.permission(userId, 'edit-posts')\nawait permission.assign.group(userId, 'content-managers')\n```\n\n### revoke\n\n```ts\nawait permission.revoke.role(userId, 'admin')\nawait permission.revoke.permission(userId, 'edit-posts')\n```\n\n### check\n\n```ts\nawait permission.check.can(userId, 'edit-posts')           // boolean\nawait permission.check.hasRole(userId, 'admin')            // boolean\nawait permission.check.canAny(userId, ['edit', 'manage'])  // boolean\nawait permission.check.canAll(userId, ['edit', 'publish']) // boolean\n```\n\n### get\n\n```ts\nawait permission.get.roles(userId)        // string[]\nawait permission.get.permissions(userId)  // string[]\nawait permission.get.groups(userId)       // string[]\n```\n\n---\n\n## Permission Groups\n\nGroup multiple permissions under a single name for easy bulk assignment:\n\n```ts\n// Create a group\nawait permission.groups.create('content-managers', [\n  'view-posts',\n  'edit-posts',\n  'publish-posts',\n])\n\n// Assign a group to a user\nawait permission.groups.assign(userId, 'content-managers')\n```\n\n`permission.check.can()` and all middleware automatically check group membership.\n\n---\n\n## Custom getUserId\n\nBy default the middleware reads `req.user?.id`. Override it to match your auth setup:\n\n```ts\nconst permission = createPermission({\n  adapter: prismaAdapter(prisma),\n  getUserId: (req) => req.auth?.sub,  // e.g. JWT payload\n})\n```\n\n---\n\n## Error Handling\n\nErrors thrown by helper functions are instances of `PermissionError`:\n\n```ts\nimport { PermissionError } from '@actinode/express-permission'\n\ntry {\n  await permission.revoke.role(userId, 'ghost-role')\n} catch (err) {\n  if (err instanceof PermissionError) {\n    console.log(err.code)    // 'NOT_FOUND' | 'UNAUTHORIZED' | 'UNAUTHENTICATED'\n    console.log(err.message) // human-readable description\n  }\n}\n```\n\n---\n\n## Full API Reference\n\n| Method | Description |\n|---|---|\n| `permission.can(perm)` | Middleware: require a permission |\n| `permission.hasRole(role)` | Middleware: require a role |\n| `permission.canAny(perms[])` | Middleware: require any permission |\n| `permission.canAll(perms[])` | Middleware: require all permissions |\n| `permission.assign.role(uid, role)` | Assign a role to a user |\n| `permission.assign.permission(uid, perm)` | Assign a direct permission to a user |\n| `permission.assign.group(uid, group)` | Assign a permission group to a user |\n| `permission.revoke.role(uid, role)` | Remove a role from a user |\n| `permission.revoke.permission(uid, perm)` | Remove a direct permission from a user |\n| `permission.check.can(uid, perm)` | Check permission (direct + role + group) |\n| `permission.check.hasRole(uid, role)` | Check role membership |\n| `permission.check.canAny(uid, perms[])` | Check any permission |\n| `permission.check.canAll(uid, perms[])` | Check all permissions |\n| `permission.get.roles(uid)` | List all roles for user |\n| `permission.get.permissions(uid)` | List all direct permissions for user |\n| `permission.get.groups(uid)` | List all groups for user |\n| `permission.groups.create(name, perms[])` | Create a permission group |\n| `permission.groups.assign(uid, group)` | Assign a group to a user |\n\n---\n\n## Issues & Support\n\n- 🐛 Found a bug? [Open a bug report](https://github.com/actinode/community/issues/new?template=bug_report.md)\n- 🚀 Have a feature idea? [Open a feature request](https://github.com/actinode/community/issues/new?template=feature_request.md)\n- 📦 Want a new package? [Open a package request](https://github.com/actinode/community/issues/new?template=package_request.md)\n- 💬 Questions and discussions? [Join the community](https://github.com/actinode/community/discussions)\n- 📚 Full documentation: [docs.actinode.com](https://docs.actinode.com/express/permission/)\n\n## Documentation\n\nFull documentation, guides and API reference is available at **[docs.actinode.com](https://docs.actinode.com)**\n\n- [Getting Started](https://docs.actinode.com/express/permission/)\n- [Roles](https://docs.actinode.com/express/permission/roles)\n- [Permissions](https://docs.actinode.com/express/permission/permissions)\n- [Groups](https://docs.actinode.com/express/permission/groups)\n- [API Reference](https://docs.actinode.com/express/permission/api)\n\n## Contributing\n\nContributions are welcome! Please visit our [GitHub repository](https://github.com/actinode/libs) to get started.\n\n## License\n\nMIT © [actinode](https://actinode.com)\n","readmeFilename":"README.md","homepage":"https://docs.actinode.com/express/permission/","repository":{"type":"git","url":"git+https://github.com/actinode/community.git"},"bugs":{"url":"https://github.com/actinode/community/issues/new?template=bug_report.md"}}