├── .npmrc ├── index.ts ├── .prettierrc ├── src ├── decorators │ ├── index.ts │ └── use-permissions.decorator.ts ├── interfaces │ ├── index.ts │ ├── permission.interface.ts │ └── authz-module-options.interface.ts ├── services │ ├── index.ts │ ├── authz-rbac.service.ts │ ├── authz-api.ts │ ├── authz-management.service.ts │ └── authz.service.ts ├── authz.constants.ts ├── index.ts ├── types.ts ├── authz.module.ts └── authz.guard.ts ├── renovate.json ├── .editorconfig ├── tsconfig.json ├── tslint.json ├── .releaserc.json ├── test ├── use-permissions.decorator.spec.ts └── authz.guard.spec.ts ├── LICENSE ├── .gitignore ├── .github └── workflows │ └── ci.yml ├── package.json ├── jest.config.js ├── README.md └── CHANGELOG.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | export * from './src'; 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './use-permissions.decorator'; 2 | -------------------------------------------------------------------------------- /src/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './authz-module-options.interface'; 2 | export * from './permission.interface'; 3 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "schedule": [ 6 | "every weekend" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './authz-management.service'; 2 | export * from './authz-rbac.service'; 3 | export * from './authz.service'; 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true -------------------------------------------------------------------------------- /src/authz.constants.ts: -------------------------------------------------------------------------------- 1 | export const AUTHZ_MODULE_OPTIONS = 'AUTHZ_MODULE_OPTIONS'; 2 | export const AUTHZ_ENFORCER = 'AUTHZ_ENFORCER'; 3 | export const PERMISSIONS_METADATA = '__PERMISSIONS__'; 4 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './authz.module'; 2 | export * from './authz.constants'; 3 | export * from './authz.guard'; 4 | export * from './services'; 5 | export * from './types'; 6 | export * from './decorators'; 7 | export * from './interfaces'; 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "module": "commonjs", 5 | "declaration": true, 6 | "removeComments": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "noImplicitAny": true, 10 | "noImplicitReturns": true, 11 | "strictNullChecks": true, 12 | "stripInternal": true, 13 | "target": "es6", 14 | "outDir": "./dist", 15 | "baseUrl": "./" 16 | }, 17 | "exclude": ["**/node_modules/**", "test", "**/*spec.ts", "example"] 18 | } 19 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": ["tslint:recommended"], 4 | "jsRules": { 5 | "no-unused-expression": true 6 | }, 7 | "rules": { 8 | "quotemark": [true, "single"], 9 | "member-access": [false], 10 | "ordered-imports": [false], 11 | "max-line-length": [true, 150], 12 | "member-ordering": [false], 13 | "interface-name": [false], 14 | "arrow-parens": false, 15 | "object-literal-sort-keys": false, 16 | "trailing-comma": false 17 | }, 18 | "rulesDirectory": [] 19 | } 20 | -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "plugins": [ 4 | "@semantic-release/commit-analyzer", 5 | "@semantic-release/release-notes-generator", 6 | "@semantic-release/npm", 7 | [ 8 | "@semantic-release/changelog", 9 | { 10 | "changelogFile": "CHANGELOG.md" 11 | } 12 | ], 13 | [ 14 | "@semantic-release/git", 15 | { 16 | "assets": ["package.json", "CHANGELOG.md"], 17 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 18 | } 19 | ], 20 | "@semantic-release/github" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/interfaces/permission.interface.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AuthActionVerb, 3 | AuthPossession, 4 | CustomAuthActionVerb, 5 | AuthResource, 6 | BatchApproval 7 | } from '../types'; 8 | import { ExecutionContext } from '@nestjs/common'; 9 | 10 | export interface Permission { 11 | resource: AuthResource; 12 | action: AuthActionVerb | CustomAuthActionVerb; 13 | possession?: AuthPossession; 14 | isOwn?: (ctx: ExecutionContext) => boolean; 15 | resourceFromContext?: boolean | ResourceFromContextFn; 16 | batchApproval?: BatchApproval; 17 | } 18 | 19 | export type PermissionData = Omit; 20 | export type ResourceFromContextFn = ( 21 | context: ExecutionContext, 22 | permission: PermissionData 23 | ) => AuthResource | AuthResource[]; 24 | -------------------------------------------------------------------------------- /src/interfaces/authz-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ExecutionContext, 3 | Provider, 4 | DynamicModule, 5 | ForwardReference, 6 | Type 7 | } from '@nestjs/common'; 8 | import { AuthUser, BatchApproval } from '../types'; 9 | import { ResourceFromContextFn } from './permission.interface'; 10 | 11 | export interface AuthZModuleOptions { 12 | model?: string; 13 | policy?: string | Promise; 14 | enablePossession?: boolean; 15 | userFromContext: (context: ExecutionContext) => AuthUser; 16 | resourceFromContext?: ResourceFromContextFn; 17 | batchApproval?: BatchApproval; 18 | enforcerProvider?: Provider; 19 | /** 20 | * Optional list of imported modules that export the providers which are 21 | * required in this module. 22 | */ 23 | imports?: Array< 24 | Type | DynamicModule | Promise | ForwardReference 25 | >; 26 | } 27 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | 3 | export enum AuthActionVerb { 4 | CREATE = 'create', 5 | UPDATE = 'update', 6 | DELETE = 'delete', 7 | READ = 'read' 8 | } 9 | 10 | export type CustomAuthActionVerb = string; 11 | 12 | export type AuthResource = string | Record; 13 | 14 | export type AuthUser = string | Record; 15 | 16 | export enum AuthPossession { 17 | ANY = 'any', 18 | OWN = 'own', 19 | OWN_ANY = 'own|any' 20 | } 21 | 22 | export enum AuthAction { 23 | CREATE_ANY = 'create:any', 24 | CREATE_OWN = 'create:own', 25 | 26 | UPDATE_ANY = 'update:any', 27 | UPDATE_OWN = 'update:own', 28 | 29 | DELETE_ANY = 'delete:any', 30 | DELETE_OWN = 'delete:own', 31 | 32 | READ_ANY = 'read:any', 33 | READ_OWN = 'read:own' 34 | } 35 | 36 | export enum BatchApproval { 37 | ANY = 'any', 38 | ALL = 'all' 39 | } 40 | -------------------------------------------------------------------------------- /test/use-permissions.decorator.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | UsePermissions, 3 | PERMISSIONS_METADATA, 4 | Permission, 5 | AuthActionVerb, 6 | AuthPossession 7 | } from '../src'; 8 | 9 | describe('@UsePermissions()', () => { 10 | it('should set metadata correctly', () => { 11 | const permissions: Permission[] = [ 12 | { 13 | resource: 'test', 14 | action: AuthActionVerb.READ, 15 | possession: AuthPossession.ANY 16 | }, 17 | { 18 | resource: {type: 'testType', id: 'testId'}, 19 | action: AuthActionVerb.CREATE, 20 | possession: AuthPossession.OWN, 21 | } 22 | ]; 23 | class TestController { 24 | @UsePermissions(...permissions) 25 | getData(): boolean { 26 | return false; 27 | } 28 | } 29 | const res = Reflect.getMetadata( 30 | PERMISSIONS_METADATA, 31 | TestController.prototype.getData 32 | ); 33 | expect(res).toEqual(permissions); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Mingkai Guo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/decorators/use-permissions.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | import { Permission, PermissionData } from '../interfaces/permission.interface'; 3 | import { PERMISSIONS_METADATA } from '../authz.constants'; 4 | import { ExecutionContext } from '@nestjs/common'; 5 | import { AuthPossession, BatchApproval } from '../types'; 6 | 7 | const defaultIsOwn = (ctx: ExecutionContext): boolean => false; 8 | const defaultResourceFromContext = ( 9 | ctx: ExecutionContext, 10 | perm: PermissionData 11 | ) => perm.resource; 12 | /** 13 | * You can define multiple permissions, but only 14 | * when all of them satisfied, could you access the route. 15 | */ 16 | export const UsePermissions = (...permissions: Permission[]): any => { 17 | const perms = permissions.map(item => { 18 | if (!item.possession) { 19 | item.possession = AuthPossession.ANY; 20 | } 21 | if (!item.isOwn) { 22 | item.isOwn = defaultIsOwn; 23 | } 24 | 25 | if (!item.resourceFromContext) { 26 | item.resourceFromContext = defaultResourceFromContext; 27 | } 28 | 29 | if (!item.batchApproval) { 30 | item.batchApproval = BatchApproval.ALL; 31 | } 32 | 33 | return item; 34 | }); 35 | 36 | return SetMetadata(PERMISSIONS_METADATA, perms); 37 | }; 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | ### VisualStudioCode ### 64 | .vscode/* 65 | !.vscode/settings.json 66 | !.vscode/tasks.json 67 | !.vscode/launch.json 68 | !.vscode/extensions.json 69 | 70 | /dist 71 | 72 | .idea/ 73 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | node-version: [^16, ^18, ^20] 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Use Node.js 18 | uses: actions/setup-node@v2 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | 22 | - run: yarn install 23 | - run: yarn typecheck 24 | - run: yarn lint 25 | - run: yarn style 26 | - run: yarn test 27 | - run: yarn coverage 28 | 29 | - name: Coveralls 30 | uses: coverallsapp/github-action@master 31 | with: 32 | github-token: ${{ secrets.GITHUB_TOKEN }} 33 | flag-name: run-${{ matrix.node-version }} 34 | parallel: true 35 | 36 | report: 37 | needs: test 38 | runs-on: ubuntu-latest 39 | steps: 40 | - name: Coveralls Finished 41 | uses: coverallsapp/github-action@master 42 | with: 43 | github-token: ${{ secrets.github_token }} 44 | parallel-finished: true 45 | 46 | release: 47 | needs: report 48 | runs-on: ubuntu-latest 49 | if: github.repository == 'node-casbin/nest-authz' && github.event_name == 'push' 50 | steps: 51 | - uses: actions/checkout@v2 52 | - name: Use Node.js 53 | uses: actions/setup-node@v2 54 | with: 55 | node-version: ^20 56 | 57 | - run: yarn install 58 | - run: yarn build 59 | - run: npx -p semantic-release -p @semantic-release/git -p @semantic-release/changelog semantic-release 60 | env: 61 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 62 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nest-authz", 3 | "version": "2.17.0", 4 | "description": "Nest.js RBAC & ABAC authorization module based on Node-Casbin", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "engines": { 8 | "node": ">= 10.13.0" 9 | }, 10 | "directories": { 11 | "test": "test" 12 | }, 13 | "scripts": { 14 | "clean": "rimraf dist", 15 | "commit": "git-cz", 16 | "build": "rimraf dist && tsc -p tsconfig.json", 17 | "prepublish": "yarn lint && yarn build", 18 | "style": "prettier --check \"src/**/*.ts\"", 19 | "format": "prettier --write \"src/**/*.ts\"", 20 | "lint": "tslint -p tsconfig.json -c tslint.json", 21 | "release": "standard-version", 22 | "test": "jest", 23 | "coverage": "jest --coverage", 24 | "typecheck": "tsc --noEmit" 25 | }, 26 | "keywords": [], 27 | "author": "dreamdevil00", 28 | "license": "MIT", 29 | "dependencies": { 30 | "casbin": "^5.30.0" 31 | }, 32 | "devDependencies": { 33 | "@nestjs/common": "^9.0.3", 34 | "@nestjs/core": "^9.0.3", 35 | "@types/jest": "24.9.0", 36 | "@types/node": "11.15.50", 37 | "commitizen": "4.2.4", 38 | "cz-conventional-changelog": "3.3.0", 39 | "jest": "24.9.0", 40 | "prettier": "1.19.1", 41 | "reflect-metadata": "^0.1.13 || ^0.2.0", 42 | "rimraf": "3.0.1", 43 | "rxjs": "^6.0.0", 44 | "standard-version": "8.0.2", 45 | "ts-jest": "24.3.0", 46 | "ts-node": "10.0.0", 47 | "tslint": "5.11.0", 48 | "typescript": "^5.0.0" 49 | }, 50 | "peerDependencies": { 51 | "@nestjs/common": "^9.0.3 || ^10.0.0", 52 | "@nestjs/core": "^9.0.3 || ^10.0.0", 53 | "reflect-metadata": "^0.1.13 || ^0.2.0", 54 | "rxjs": "^7.5.6" 55 | }, 56 | "repository": { 57 | "type": "git", 58 | "url": "https://github.com/node-casbin/nest-authz.git" 59 | }, 60 | "files": [ 61 | "dist", 62 | "src", 63 | "LICENSE", 64 | "README.md" 65 | ], 66 | "config": { 67 | "commitizen": { 68 | "path": "./node_modules/cz-conventional-changelog" 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/authz.module.ts: -------------------------------------------------------------------------------- 1 | import { Module, DynamicModule, Global } from '@nestjs/common'; 2 | import * as casbin from 'casbin'; 3 | 4 | import { AuthZModuleOptions } from './interfaces'; 5 | import { AuthZGuard } from './authz.guard'; 6 | import { AUTHZ_MODULE_OPTIONS, AUTHZ_ENFORCER } from './authz.constants'; 7 | import { 8 | AuthZRBACService, 9 | AuthZManagementService, 10 | AuthZService 11 | } from './services'; 12 | 13 | @Global() 14 | @Module({ 15 | providers: [], 16 | exports: [] 17 | }) 18 | export class AuthZModule { 19 | static register(options: AuthZModuleOptions): DynamicModule { 20 | if (options.enablePossession === undefined) { 21 | options.enablePossession = true; 22 | } 23 | 24 | const moduleOptionsProvider = { 25 | provide: AUTHZ_MODULE_OPTIONS, 26 | useValue: options || {} 27 | }; 28 | 29 | let enforcerProvider = options.enforcerProvider; 30 | const importsModule = options.imports || []; 31 | 32 | if (!enforcerProvider) { 33 | if (!options.model || !options.policy) { 34 | throw new Error( 35 | 'must provide either enforcerProvider or both model and policy' 36 | ); 37 | } 38 | 39 | enforcerProvider = { 40 | provide: AUTHZ_ENFORCER, 41 | useFactory: async () => { 42 | const isFile = typeof options.policy === 'string'; 43 | 44 | let policyOption; 45 | 46 | if (isFile) { 47 | policyOption = options.policy as string; 48 | } else { 49 | policyOption = await options.policy; 50 | } 51 | 52 | return casbin.newEnforcer(options.model, policyOption); 53 | } 54 | }; 55 | } 56 | 57 | return { 58 | module: AuthZModule, 59 | providers: [ 60 | moduleOptionsProvider, 61 | enforcerProvider, 62 | AuthZGuard, 63 | AuthZRBACService, 64 | AuthZManagementService, 65 | AuthZService 66 | ], 67 | imports: importsModule, 68 | exports: [ 69 | moduleOptionsProvider, 70 | enforcerProvider, 71 | AuthZGuard, 72 | AuthZRBACService, 73 | AuthZManagementService, 74 | AuthZService 75 | ] 76 | }; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /test/authz.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Permission, 3 | AuthActionVerb, 4 | AuthPossession, 5 | PermissionData, 6 | AuthZGuard, 7 | BatchApproval 8 | } from '../src'; 9 | 10 | describe('@AuthZGuard()', () => { 11 | const policies = [ 12 | ['user1', 'resourceType1', 'id1', AuthActionVerb.READ], 13 | ['user1', 'resourceType1', 'id2', AuthActionVerb.READ], 14 | ['user1', 'resourceType1', 'id3', AuthActionVerb.READ], 15 | ['user2', 'resourceType1', 'id1', AuthActionVerb.READ], 16 | ['user2', 'resourceType1', 'id3', AuthActionVerb.READ], 17 | ]; 18 | 19 | const mockEnforcer: any = { 20 | enforce: (userId: string, resource: any, action: string) => { 21 | return policies.some((p) => p[0] === userId && p[1] === resource.type && p[2] === resource.id && p[3] === action); 22 | }, 23 | batchEnforce: (checks: string[][]) => { 24 | return checks.map((res: any) => { 25 | return policies.some((p) => p[0] === res[0] && p[1] === res[1].type && p[2] === res[1].id && p[3] === res[2]) 26 | }); 27 | }, 28 | }; 29 | 30 | const mockOptions: any = { 31 | userFromContext: (ctx: any) => ctx.user.id, 32 | } 33 | 34 | const getMockContext = (user: string, resources: any): any => ({ 35 | getHandler: () => null, 36 | data: {id: resources}, 37 | user: {id: user} 38 | }); 39 | 40 | const getMockReflector = (permissions: Permission[]): any => ({ 41 | get: (meta: any, handler: any) => permissions, 42 | }); 43 | 44 | it('should enforce specific resource', async () => { 45 | const permission: Permission[] = [ 46 | { 47 | resource: 'resourceType1', 48 | action: AuthActionVerb.READ, 49 | resourceFromContext: (ctx: any, perm: PermissionData) => ({type: perm.resource, id: ctx.data.id}) 50 | }, 51 | ]; 52 | 53 | const guard = new AuthZGuard(getMockReflector(permission), mockEnforcer, mockOptions); 54 | 55 | expect(guard.canActivate(getMockContext('user1', 'id1'))).resolves.toEqual(true); 56 | expect(guard.canActivate(getMockContext('user2', 'id1'))).resolves.toEqual(true); 57 | expect(guard.canActivate(getMockContext('user2', 'id2'))).resolves.toEqual(false); 58 | }); 59 | 60 | it('should batch enforce ALL specific resources', async () => { 61 | const permission2: Permission[] = [ 62 | { 63 | resource: 'resourceType1', 64 | action: AuthActionVerb.READ, 65 | resourceFromContext: (ctx: any, perm: PermissionData) => { 66 | return ctx.data.id.map((id: string) => ({type: perm.resource, id})) 67 | } 68 | }, 69 | ]; 70 | 71 | const guard = new AuthZGuard(getMockReflector(permission2), mockEnforcer, mockOptions); 72 | 73 | expect(guard.canActivate(getMockContext('user1', ['id1', 'id2', 'id3']))).resolves.toEqual(true); 74 | expect(guard.canActivate(getMockContext('user2', ['id1', 'id3']))).resolves.toEqual(true); 75 | expect(guard.canActivate(getMockContext('user2', ['id1', 'id2', 'id3']))).resolves.toEqual(false); 76 | }); 77 | 78 | it('should batch enforce ANY specific resources', async () => { 79 | const permission2: Permission[] = [ 80 | { 81 | resource: 'resourceType1', 82 | action: AuthActionVerb.READ, 83 | resourceFromContext: (ctx: any, perm: PermissionData) => { 84 | return ctx.data.id.map((id: string) => ({type: perm.resource, id})) 85 | }, 86 | batchApproval: BatchApproval.ANY, 87 | }, 88 | ]; 89 | 90 | const guard = new AuthZGuard(getMockReflector(permission2), mockEnforcer, mockOptions); 91 | 92 | expect(guard.canActivate(getMockContext('user2', ['id1', 'id2', 'id3']))).resolves.toEqual(true); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /src/authz.guard.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Injectable, 3 | CanActivate, 4 | ExecutionContext, 5 | Inject 6 | } from '@nestjs/common'; 7 | import { Reflector } from '@nestjs/core'; 8 | import { 9 | AUTHZ_ENFORCER, 10 | PERMISSIONS_METADATA, 11 | AUTHZ_MODULE_OPTIONS 12 | } from './authz.constants'; 13 | import * as casbin from 'casbin'; 14 | import { 15 | Permission, 16 | PermissionData, 17 | ResourceFromContextFn 18 | } from './interfaces/permission.interface'; 19 | import { UnauthorizedException } from '@nestjs/common'; 20 | import { AuthPossession, AuthResource, AuthUser, BatchApproval } from './types'; 21 | import { AuthZModuleOptions } from './interfaces/authz-module-options.interface'; 22 | 23 | @Injectable() 24 | export class AuthZGuard implements CanActivate { 25 | constructor( 26 | protected readonly reflector: Reflector, 27 | @Inject(AUTHZ_ENFORCER) protected enforcer: casbin.Enforcer, 28 | @Inject(AUTHZ_MODULE_OPTIONS) protected options: AuthZModuleOptions 29 | ) {} 30 | 31 | async canActivate(context: ExecutionContext): Promise { 32 | try { 33 | const permissions: Permission[] = this.reflector.get( 34 | PERMISSIONS_METADATA, 35 | context.getHandler() 36 | ); 37 | 38 | if (!permissions) { 39 | return true; 40 | } 41 | 42 | const requestUser = this.options.userFromContext(context); 43 | 44 | if (!requestUser) { 45 | throw new UnauthorizedException(); 46 | } 47 | 48 | const hasPermission = async ( 49 | user: AuthUser, 50 | permission: Permission 51 | ): Promise => { 52 | const { 53 | possession, 54 | resource, 55 | action, 56 | resourceFromContext, 57 | batchApproval 58 | } = permission; 59 | 60 | let contextResource: AuthResource; 61 | if (resourceFromContext === true) { 62 | if (this.options.resourceFromContext) { 63 | // Use default resourceFromContext function if provided. 64 | contextResource = this.options.resourceFromContext(context, { 65 | possession, 66 | resource, 67 | action 68 | }); 69 | } else { 70 | // Default to permission resource if not provided. 71 | contextResource = resource; 72 | } 73 | } else { 74 | // Use custom resourceFromContext function or default. 75 | contextResource = (resourceFromContext as ResourceFromContextFn)( 76 | context, 77 | { possession, resource, action } 78 | ); 79 | } 80 | 81 | const batchApprovalPolicy = batchApproval ?? this.options.batchApproval; 82 | if (!this.options.enablePossession) { 83 | return this.enforce( 84 | user, 85 | contextResource, 86 | action, 87 | batchApprovalPolicy 88 | ); 89 | } 90 | 91 | const poss = []; 92 | 93 | if (possession === AuthPossession.OWN_ANY) { 94 | poss.push(AuthPossession.ANY, AuthPossession.OWN); 95 | } else { 96 | poss.push(possession as AuthPossession); 97 | } 98 | 99 | return AuthZGuard.asyncSome(poss, async p => { 100 | if (p === AuthPossession.OWN) { 101 | return (permission as any).isOwn(context); 102 | } else { 103 | return this.enforce( 104 | user, 105 | contextResource, 106 | `${action}:${p}`, 107 | batchApprovalPolicy 108 | ); 109 | } 110 | }); 111 | }; 112 | 113 | const result = await AuthZGuard.asyncEvery( 114 | permissions, 115 | async permission => hasPermission(requestUser, permission) 116 | ); 117 | 118 | return result; 119 | } catch (e) { 120 | throw e; 121 | } 122 | } 123 | 124 | async enforce( 125 | user: AuthUser, 126 | resource: AuthResource | AuthResource[], 127 | action: string, 128 | batchApprovalPolicy?: BatchApproval 129 | ): Promise { 130 | if (Array.isArray(resource)) { 131 | // Batch enforce according to batchApproval option. 132 | const checks = resource.map(res => [user, res, action]); 133 | const results = await this.enforcer.batchEnforce(checks); 134 | 135 | if (batchApprovalPolicy === BatchApproval.ANY) { 136 | return results.some(result => result); 137 | } 138 | 139 | return results.every(result => result); 140 | } 141 | 142 | return this.enforcer.enforce(user, resource, action); 143 | } 144 | 145 | static async asyncSome( 146 | array: T[], 147 | callback: (value: T, index: number, a: T[]) => Promise 148 | ): Promise { 149 | for (let i = 0; i < array.length; i++) { 150 | const result = await callback(array[i], i, array); 151 | if (result) { 152 | return result; 153 | } 154 | } 155 | 156 | return false; 157 | } 158 | 159 | static async asyncEvery( 160 | array: T[], 161 | callback: (value: T, index: number, a: T[]) => Promise 162 | ): Promise { 163 | for (let i = 0; i < array.length; i++) { 164 | const result = await callback(array[i], i, array); 165 | if (!result) { 166 | return result; 167 | } 168 | } 169 | 170 | return true; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // For a detailed explanation regarding each configuration property, visit: 2 | // https://jestjs.io/docs/en/configuration.html 3 | 4 | module.exports = { 5 | // All imported modules in your tests should be mocked automatically 6 | // automock: false, 7 | 8 | // Stop running tests after the first failure 9 | // bail: false, 10 | 11 | // Respect "browser" field in package.json when resolving modules 12 | // browser: false, 13 | 14 | // The directory where Jest should store its cached dependency information 15 | // cacheDirectory: "/tmp/jest_rs", 16 | 17 | // Automatically clear mock calls and instances between every test 18 | // clearMocks: false, 19 | 20 | // Indicates whether the coverage information should be collected while executing the test 21 | // collectCoverage: false, 22 | 23 | // An array of glob patterns indicating a set of files for which coverage information should be collected 24 | // collectCoverageFrom: null, 25 | 26 | // The directory where Jest should output its coverage files 27 | // coverageDirectory: null, 28 | 29 | // An array of regexp pattern strings used to skip coverage collection 30 | coveragePathIgnorePatterns: ['/node_modules/'], 31 | 32 | // A list of reporter names that Jest uses when writing coverage reports 33 | // coverageReporters: [ 34 | // "json", 35 | // "text", 36 | // "lcov", 37 | // "clover" 38 | // ], 39 | 40 | // An object that configures minimum threshold enforcement for coverage results 41 | // coverageThreshold: null, 42 | 43 | // Make calling deprecated APIs throw helpful error messages 44 | // errorOnDeprecated: false, 45 | 46 | // Force coverage collection from ignored files usin a array of glob patterns 47 | // forceCoverageMatch: [], 48 | 49 | // A path to a module which exports an async function that is triggered once before all test suites 50 | // globalSetup: null, 51 | 52 | // A path to a module which exports an async function that is triggered once after all test suites 53 | // globalTeardown: null, 54 | 55 | // A set of global variables that need to be available in all test environments 56 | globals: { 57 | 'ts-jest': { 58 | tsConfig: 'tsconfig.json' 59 | } 60 | }, 61 | 62 | // An array of directory names to be searched recursively up from the requiring module's location 63 | // moduleDirectories: [ 64 | // "node_modules" 65 | // ], 66 | 67 | // An array of file extensions your modules use 68 | moduleFileExtensions: ['ts', 'tsx', 'js'], 69 | 70 | // A map from regular expressions to module names that allow to stub out resources with a single module 71 | moduleNameMapper: { 72 | 'csv-parse': '/node_modules/csv-parse/dist/cjs/sync.cjs', 73 | }, 74 | 75 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 76 | // modulePathIgnorePatterns: [], 77 | 78 | // Activates notifications for test results 79 | // notify: false, 80 | 81 | // An enum that specifies notification mode. Requires { notify: true } 82 | // notifyMode: "always", 83 | 84 | // A preset that is used as a base for Jest's configuration 85 | // preset: null, 86 | 87 | // Run tests from one or more projects 88 | // projects: null, 89 | 90 | // Use this configuration option to add custom reporters to Jest 91 | // reporters: undefined, 92 | 93 | // Automatically reset mock state between every test 94 | // resetMocks: false, 95 | 96 | // Reset the module registry before running each individual test 97 | // resetModules: false, 98 | 99 | // A path to a custom resolver 100 | // resolver: null, 101 | 102 | // Automatically restore mock state between every test 103 | // restoreMocks: false, 104 | 105 | // The root directory that Jest should scan for tests and modules within 106 | // rootDir: null, 107 | 108 | // A list of paths to directories that Jest should use to search for files in 109 | roots: ['test'], 110 | 111 | // Allows you to use a custom runner instead of Jest's default test runner 112 | // runner: "jest-runner", 113 | 114 | // The paths to modules that run some code to configure or set up the testing environment before each test 115 | // setupFiles: [], 116 | 117 | // The path to a module that runs some code to configure or set up the testing framework before each test 118 | // setupTestFrameworkScriptFile: null, 119 | 120 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 121 | // snapshotSerializers: [], 122 | 123 | // The test environment that will be used for testing 124 | testEnvironment: 'node', 125 | 126 | // Options that will be passed to the testEnvironment 127 | // testEnvironmentOptions: {}, 128 | 129 | // Adds a location field to test results 130 | // testLocationInResults: false, 131 | 132 | // The glob patterns Jest uses to detect test files 133 | testMatch: ['**/test/*.+(ts|tsx)'], 134 | 135 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 136 | testPathIgnorePatterns: ['/node_modules/'], 137 | 138 | // The regexp pattern Jest uses to detect test files 139 | // testRegex: "", 140 | 141 | // This option allows the use of a custom results processor 142 | // testResultsProcessor: null, 143 | 144 | // This option allows use of a custom test runner 145 | // testRunner: "jasmine2", 146 | 147 | // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href 148 | // testURL: "http://localhost", 149 | 150 | // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" 151 | // timers: "real", 152 | 153 | // A map from regular expressions to paths to transformers 154 | transform: { 155 | '^.+\\.(ts|tsx)$': 'ts-jest' 156 | } 157 | 158 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 159 | // transformIgnorePatterns: [ 160 | // "/node_modules/" 161 | // ], 162 | 163 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 164 | // unmockedModulePathPatterns: undefined, 165 | 166 | // Indicates whether each individual test should be reported during the run 167 | // verbose: null, 168 | 169 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 170 | // watchPathIgnorePatterns: [], 171 | 172 | // Whether to use watchman for file crawling 173 | // watchman: true, 174 | }; 175 | -------------------------------------------------------------------------------- /src/services/authz-rbac.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Inject } from '@nestjs/common'; 2 | import { AUTHZ_ENFORCER } from '../authz.constants'; 3 | import * as casbin from 'casbin'; 4 | import * as authzAPI from './authz-api'; 5 | 6 | /** 7 | * A wrapper of casbin RBAC API. 8 | * All methods are transformed to async in terms of possible IO operations 9 | * in the future. 10 | * @deprecated This service will be removed and replace by AuthZService in a later release. 11 | */ 12 | @Injectable() 13 | export class AuthZRBACService { 14 | constructor( 15 | @Inject(AUTHZ_ENFORCER) 16 | public readonly enforcer: casbin.Enforcer 17 | ) {} 18 | 19 | /** 20 | * Gets the roles that a user has. 21 | * 22 | * @param {string} name username 23 | * @param {string} [domain] domain name 24 | * @returns {Promise} roles owned by the user 25 | * @memberof AuthZRBACService 26 | */ 27 | getRolesForUser(name: string, domain?: string): Promise { 28 | return authzAPI.getRolesForUser(this.enforcer, name, domain); 29 | } 30 | 31 | /** 32 | * Gets the users that has a role. 33 | * 34 | * @param {string} name username 35 | * @param {string} [domain] domain name 36 | * @returns {Promise} users that has a role 37 | * @memberof AuthZRBACService 38 | */ 39 | getUsersForRole(name: string, domain?: string): Promise { 40 | return authzAPI.getUsersForRole(this.enforcer, name, domain); 41 | } 42 | 43 | /** 44 | * Determines whether a user has a role. 45 | * 46 | * @param {string} name username 47 | * @param {string} role role name 48 | * @param {string} [domain] domain name 49 | * @returns {Promise} 50 | * @memberof AuthZRBACService 51 | */ 52 | hasRoleForUser( 53 | name: string, 54 | role: string, 55 | domain?: string 56 | ): Promise { 57 | return authzAPI.hasRoleForUser(this.enforcer, name, role, domain); 58 | } 59 | 60 | /** 61 | * Adds a role for a user. 62 | * Returns false if the user already has the role (aka not affected). 63 | * 64 | * @param {string} user username 65 | * @param {string} role role name 66 | * @param {string} [domain] domain name 67 | * @returns {Promise} 68 | * @memberof AuthZRBACService 69 | */ 70 | addRoleForUser( 71 | user: string, 72 | role: string, 73 | domain?: string 74 | ): Promise { 75 | return authzAPI.addRoleForUser(this.enforcer, user, role, domain); 76 | } 77 | 78 | /** 79 | * deletes a role for a user. 80 | * Returns false if the user does not have the role (aka not affected). 81 | * 82 | * @param {string} user username 83 | * @param {string} role role name 84 | * @param {string} [domain] domain name 85 | * @returns {Promise} 86 | * @memberof AuthZRBACService 87 | */ 88 | deleteRoleForUser( 89 | user: string, 90 | role: string, 91 | domain?: string 92 | ): Promise { 93 | return authzAPI.deleteRoleForUser(this.enforcer, user, role, domain); 94 | } 95 | 96 | /** 97 | * Deletes all roles for a user. 98 | * Returns false if the user does not have any roles (aka not affected). 99 | * 100 | * @param {string} user username 101 | * @returns {Promise} 102 | * @memberof AuthZRBACService 103 | */ 104 | deleteRolesForUser(user: string, domain?: string): Promise { 105 | return authzAPI.deleteRolesForUser(this.enforcer, user, domain); 106 | } 107 | 108 | /** 109 | * Deletes a user. 110 | * Returns false if the user does not exist (aka not affected). 111 | * 112 | * @param {string} user username 113 | * @returns {Promise} 114 | * @memberof AuthZRBACService 115 | */ 116 | async deleteUser(user: string): Promise { 117 | return authzAPI.deleteUser(this.enforcer, user); 118 | } 119 | 120 | /** 121 | * Deletes a role 122 | * 123 | * @param {string} role role name 124 | * @returns {Promise} 125 | * @memberof AuthZRBACService 126 | */ 127 | deleteRole(role: string): Promise { 128 | return authzAPI.deleteRole(this.enforcer, role); 129 | } 130 | 131 | /** 132 | * Deletes a permission. 133 | * Returns false if the permission does not exist (aka not affected). 134 | * 135 | * @param {...string[]} permission permission per casbin model definition 136 | * @returns {Promise} 137 | * @memberof AuthZRBACService 138 | */ 139 | deletePermission(...permission: string[]): Promise { 140 | return authzAPI.deletePermission(this.enforcer, ...permission); 141 | } 142 | 143 | /** 144 | * Adds a permission for a user or role. 145 | * Returns false if the user or role already has the permission (aka not affected). 146 | * 147 | * @param {string} userOrRole username or role name 148 | * @param {...string[]} permission permission per casbin model definition 149 | * @returns {Promise} 150 | * @memberof AuthZRBACService 151 | */ 152 | addPermissionForUser( 153 | userOrRole: string, 154 | ...permission: string[] 155 | ): Promise { 156 | return authzAPI.addPermissionForUser( 157 | this.enforcer, 158 | userOrRole, 159 | ...permission 160 | ); 161 | } 162 | 163 | /** 164 | * Deletes a permission for a user or role. 165 | * Returns false if the user or role does not have the permission (aka not affected). 166 | * 167 | * @param {string} userOrRole username or role name 168 | * @param {...string[]} permission permission per casbin model definition 169 | * @returns {Promise} 170 | * @memberof AuthZRBACService 171 | */ 172 | deletePermissionForUser( 173 | userOrRole: string, 174 | ...permission: string[] 175 | ): Promise { 176 | return authzAPI.deletePermissionForUser( 177 | this.enforcer, 178 | userOrRole, 179 | ...permission 180 | ); 181 | } 182 | 183 | /** 184 | * Deletes permissions for a user or role. 185 | * Returns false if the user or role does not have any permissions (aka not affected). 186 | * 187 | * @param {string} userOrRole username or role name 188 | * @returns {Promise} 189 | * @memberof AuthZRBACService 190 | */ 191 | deletePermissionsForUser(userOrRole: string): Promise { 192 | return authzAPI.deletePermissionsForUser(this.enforcer, userOrRole); 193 | } 194 | 195 | /** 196 | * Gets permissions for a user or role. 197 | * 198 | * @param {string} userOrRole username or role name 199 | * @returns {Promise} 200 | * @memberof AuthZRBACService 201 | */ 202 | getPermissionsForUser(userOrRole: string): Promise { 203 | return authzAPI.getPermissionsForUser(this.enforcer, userOrRole); 204 | } 205 | 206 | /** 207 | * Determines whether a user has a permission. 208 | * 209 | * @param {string} user username 210 | * @param {...string[]} permission permission per casbin model definition 211 | * @returns {Promise} 212 | * @memberof AuthZRBACService 213 | */ 214 | hasPermissionForUser( 215 | user: string, 216 | ...permission: string[] 217 | ): Promise { 218 | return authzAPI.hasPermissionForUser(this.enforcer, user, ...permission); 219 | } 220 | 221 | /** 222 | * Gets implicit roles that a user has. 223 | * Compared to getRolesForUser(), this function retrieves indirect roles besides direct roles.\ 224 | * 225 | * For example: 226 | * 227 | * g, alice, role:admin\ 228 | * g, role:admin, role:user 229 | * 230 | * 231 | * getRolesForUser("alice") can only get: ["role:admin"]. 232 | * But getImplicitRolesForUser("alice") will get: ["role:admin", "role:user"]. 233 | * 234 | * @param {string} name username 235 | * @param {...string[]} domain domains 236 | * @returns {Promise} 237 | * @memberof AuthZRBACService 238 | */ 239 | getImplicitRolesForUser( 240 | name: string, 241 | ...domain: string[] 242 | ): Promise { 243 | return authzAPI.getImplicitRolesForUser(this.enforcer, name, ...domain); 244 | } 245 | 246 | /** 247 | * Gets implicit permissions for a user or role. 248 | * Compared to getPermissionsForUser(), this function retrieves permissions for inherited roles.\ 249 | * 250 | * For example: 251 | * p, admin, data1, read 252 | * p, alice, data2, read 253 | * g, alice, admin 254 | * 255 | * getPermissionsForUser("alice") can only get: [["alice", "data2", "read"]].\ 256 | * But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]]. 257 | * 258 | * @param {string} user username 259 | * @returns {Promise} 260 | * @memberof AuthZRBACService 261 | */ 262 | getImplicitPermissionsForUser( 263 | user: string, 264 | ...domain: string[] 265 | ): Promise { 266 | return authzAPI.getImplicitPermissionsForUser( 267 | this.enforcer, 268 | user, 269 | ...domain 270 | ); 271 | } 272 | /** 273 | * getImplicitUsersForPermission gets implicit users for a permission. 274 | * For example: 275 | * p, admin, data1, read 276 | * p, bob, data1, read 277 | * g, alice, admin 278 | * 279 | * getImplicitUsersForPermission("data1", "read") will get: ["alice", "bob"]. 280 | * Note: only users will be returned, roles (2nd arg in "g") will be excluded. 281 | */ 282 | getImplicitUsersForPermission(...permission: string[]): Promise { 283 | return authzAPI.getImplicitUsersForPermission(this.enforcer, ...permission); 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nest-authz 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![NPM download][download-image]][download-url] 5 | [![ci](https://github.com/node-casbin/nest-authz/actions/workflows/ci.yml/badge.svg)](https://github.com/node-casbin/nest-authz/actions/workflows/ci.yml) 6 | [![Coverage Status](https://coveralls.io/repos/github/node-casbin/nest-authz/badge.svg?branch=master)](https://coveralls.io/github/node-casbin/nest-authz?branch=master) 7 | [![Discord](https://img.shields.io/discord/1022748306096537660?logo=discord&label=discord&color=5865F2)](https://discord.gg/S5UjpzGZjN) 8 | 9 | [npm-image]: https://img.shields.io/npm/v/nest-authz.svg?style=flat-square 10 | [npm-url]: https://npmjs.org/package/nest-authz 11 | [download-image]: https://img.shields.io/npm/dm/nest-authz.svg?style=flat-square 12 | [download-url]: https://npmjs.org/package/nest-authz 13 | 14 | A access control library for [NestJS](https://nestjs.com/) which built on [node-casbin](https://github.com/casbin/node-casbin). 15 | 16 | Casbin is a powerful and efficient open-source access control library. It provides support for enforcing authorization based on various access control models like ACL, RBAC, ABAC. For detailed info, check out the [official docs](https://casbin.org/) 17 | 18 | ## How to use 19 | 20 | ### Installation 21 | 22 | ```bat 23 | $ npm install --save nest-authz 24 | ``` 25 | 26 | ### Define Access Control Model 27 | 28 | Firstly, you should create your own casbin access control model. Checkout [related docs](https://github.com/casbin/node-casbin#supported-models) if you have not. 29 | 30 | ### Initialization 31 | 32 | Register nest-authz with options in the AppModule as follows: 33 | 34 | ``` 35 | AuthZModule.register(options) 36 | ``` 37 | 38 | `options` is an object literal containing options. 39 | 40 | - `model` is a path string to the casbin model. 41 | - `policy` is a path string to the casbin policy file or adapter 42 | - `enablePossession` is a boolean that enables the use of possession (`AuthPossession.(ANY|OWN|OWN_ANY)`) for actions. 43 | - `userFromContext` (REQUIRED) is a function that accepts `ExecutionContext`(the param of guard method `canActivate`) as the only parameter and returns the user as either string, object, or null. The `AuthZGuard` uses the returned user to determine their permission internally. 44 | - `resourceFromContext` (OPTIONAL) is a function that accepts `ExecutionContext` and `PermissionData` and returns an `AuthResource`. This allows the `AuthZGuard` to perform access control on specific resources found in a request. When provided, this function is used as the default for all `Permissions` with `resourceFromContext: true`. 45 | - `enforcerProvider` Optional enforcer provider 46 | - `imports` Optional list of imported modules that export the providers which are required in this module. 47 | 48 | There are two ways to configure enforcer, either `enforcerProvider`(optional with `imports`) or `model` with `policy` 49 | 50 | An example configuration which reads user and resource id from the http request. 51 | 52 | ```typescript 53 | import { TypeOrmModule } from '@nestjs/typeorm'; 54 | 55 | @Module({ 56 | imports: [ 57 | AuthZModule.register({ 58 | model: 'model.conf', 59 | policy: TypeORMAdapter.newAdapter({ 60 | type: 'mysql', 61 | host: 'localhost', 62 | port: 3306, 63 | username: 'root', 64 | password: 'password', 65 | database: 'nestdb' 66 | }), 67 | userFromContext: (ctx) => { 68 | const request = ctx.switchToHttp().getRequest(); 69 | return request.user && request.user.username; 70 | }, 71 | resourceFromContext: (ctx, perm) => { 72 | const request = ctx.switchToHttp().getRequest(); 73 | return { type: perm.resource, id: request.id }; 74 | } 75 | }), 76 | ], 77 | controllers: [AppController], 78 | providers: [AppService] 79 | }) 80 | ``` 81 | 82 | or 83 | 84 | ```typescript 85 | import { TypeOrmModule } from '@nestjs/typeorm'; 86 | import { ConfigModule, ConfigService } from './config.module'; 87 | import { AUTHZ_ENFORCER } from 'nest-authz'; 88 | 89 | @Module({ 90 | imports: [ 91 | ConfigModule, 92 | AuthZModule.register({ 93 | imports: [ConfigModule], 94 | enforcerProvider: { 95 | provide: AUTHZ_ENFORCER, 96 | useFactory: async (configSrv: ConfigService) => { 97 | const config = await configSrv.getAuthConfig(); 98 | return casbin.newEnforcer(config.model, config.policy); 99 | }, 100 | inject: [ConfigService], 101 | }, 102 | userFromContext: (ctx) => { 103 | const request = ctx.switchToHttp().getRequest(); 104 | return request.user && { 105 | username: request.user.username, 106 | isAdmin: request.user.isAdmin 107 | }; 108 | } 109 | }), 110 | ], 111 | controllers: [AppController], 112 | providers: [AppService] 113 | ``` 114 | 115 | The latter method of configuring the enforcer is preferred. 116 | 117 | ### Checking Permissions 118 | 119 | #### Using `@UsePermissions` Decorator 120 | 121 | The `@UsePermissions` decorator is the easiest and most common way of checking permissions. Consider the method shown below: 122 | 123 | ```typescript 124 | @Get('users') 125 | @UseGuards(AuthZGuard) 126 | @UsePermissions({ 127 | action: AuthActionVerb.READ, 128 | resource: 'USER', 129 | possession: AuthPossession.ANY 130 | }) 131 | async findAllUsers() {} 132 | 133 | ``` 134 | 135 | The `findAllUsers` method can not be called by a user who is not granted the permission to read any user. 136 | 137 | The value of property `resource` is a magic string just for demonstrating. In the real-world applications you should avoid magic strings. Resources should be kept in the separated file like `resources.ts` 138 | 139 | The param of `UsePermissions` are some objects with required properties `action`, and `resource`, and optionally `possession`, and `isOwn`. 140 | 141 | - `action` is an enum value of `AuthActionVerb`. 142 | - `resource` is a resource string or object the request is accessing. 143 | - `possession` is an enum value of `AuthPossession`. Defaults to `AuthPossession.ANY` if not defined. 144 | - `isOwn` is a function that accepts `ExecutionContext`(the param of guard method `canActivate`) as the only parameter and returns boolean. The `AuthZGuard` uses it to determine whether the user is the owner of the resource. A default `isOwn` function which returns `false` will be used if not defined. 145 | - `resourceFromContext` is either a boolean (which defaults to false) or a function that accepts `ExecutionContext` and `PermissionData` as parameters and returns an `AuthResource`. When set to true, the default `resourceFromContext` function provided during module initialization is used. When set to a function, the provided function will override the default `resourceFromContext` function. When set to false, undefined, or if a default `resourceFromContext` is not provided, the `resource` option will be used as-is for each request. 146 | 147 | In order to support ABAC models which authorize based on arbitrary attributes in lieu of simple strings, you can also provide an object for the resource. For example: 148 | 149 | ```typescript 150 | @UsePermissions({ 151 | action: AuthActionVerb.READ, 152 | resource: {type: 'User', operation: 'single'}, 153 | possession: AuthPossession.ANY 154 | }) 155 | async userById(id: string) {} 156 | 157 | @UsePermissions({ 158 | action: AuthActionVerb.READ, 159 | resource: {type: 'User', operation: 'batch'}, 160 | possession: AuthPossession.ANY 161 | }) 162 | async findAllUsers() {} 163 | ``` 164 | 165 | To provide access control on specific resources, `resourceFromContext` can be used: 166 | 167 | ```typescript 168 | @UsePermissions({ 169 | action: AuthActionVerb.READ, 170 | resource: 'User', 171 | resourceFromContext: (ctx, perm) => { 172 | const req = ctx.switchToHttp().getRequest(); 173 | return { type: perm.resource, id: req.id }; 174 | } 175 | }) 176 | async userById(id: string) {} 177 | ``` 178 | 179 | You can define multiple permissions, but only when all of them satisfied, could you access the route. For example: 180 | 181 | ``` 182 | @UsePermissions({ 183 | action: AuthActionVerb.READ, 184 | resource: 'USER_ADDRESS', 185 | possession: AuthPossession.ANY 186 | }, { 187 | action; AuthActionVerb.READ, 188 | resource: 'USER_ROLES', 189 | possession: AuthPossession.ANY 190 | }) 191 | ``` 192 | 193 | Only when the user is granted both permissions of reading any user address and reading any roles, could he/she access the route. 194 | 195 | #### Using `AuthZService` 196 | 197 | While the `@UsePermissions` decorator is good enough for most cases, there are situations where we may want to check for a permission in a method's body. We can inject and use `AuthZService` which is a wrapper of the Casbin RBAC + Management API for that as shown in the example below: 198 | 199 | ```typescript 200 | import { Controller, Get, UnauthorizedException, Req } from '@nestjs/common'; 201 | import { 202 | AuthZGuard, 203 | AuthZService, 204 | AuthActionVerb, 205 | AuthPossession, 206 | UsePermissions 207 | } from 'nest-authz'; 208 | 209 | @Controller() 210 | export class AppController { 211 | constructor(private readonly authzSrv: AuthZService) {} 212 | 213 | @Get('users') 214 | async findAllUsers(@Req() request: Request) { 215 | let username = request.user['username']; 216 | // If there is a policy `p, root, user, read:any` in policy.csv 217 | // then user `root` can do this operation 218 | 219 | // Using string literals for simplicity. 220 | const isPermitted = await this.authzSrv.hasPermissionForUser(username, "user", "read:any"); 221 | if (!isPermitted) { 222 | throw new UnauthorizedException( 223 | 'You are not authorized to read users list' 224 | ); 225 | } 226 | // A user can not reach this point if he/she is not granted for permission read users 227 | // ... 228 | } 229 | } 230 | ``` 231 | 232 | 233 | #### (Deprecated) Using `AuthZRBACService` or `AuthZManagementService` 234 | 235 | > The functionality provided by `AuthZRBACService` and `AuthZManagementService` has been unified in `AuthZService`, so these services will be removed in a later release. 236 | 237 | We can inject and use `AuthZRBACService` or `AuthZManagementService` which are wrappers of the Casbin RBAC and Management APIs, respectively, as shown in the example below: 238 | 239 | ```typescript 240 | import { Controller, Get, UnauthorizedException, Req } from '@nestjs/common'; 241 | import { 242 | AuthZGuard, 243 | AuthZRBACService, 244 | AuthActionVerb, 245 | AuthPossession, 246 | UsePermissions 247 | } from 'nest-authz'; 248 | 249 | @Controller() 250 | export class AppController { 251 | constructor(private readonly rbacSrv: AuthZRBACService) {} 252 | 253 | @Get('users') 254 | async findAllUsers(@Req() request: Request) { 255 | let username = request.user['username']; 256 | // If there is a policy `p, root, user, read:any` in policy.csv 257 | // then user `root` can do this operation 258 | 259 | // Using string literals for simplicity. 260 | const isPermitted = await this.rbacSrv.hasPermissionForUser(username, "user", "read:any"); 261 | if (!isPermitted) { 262 | throw new UnauthorizedException( 263 | 'You are not authorized to read users list' 264 | ); 265 | } 266 | // A user can not reach this point if he/she is not granted for permission read users 267 | // ... 268 | } 269 | } 270 | ``` 271 | 272 | ## Example 273 | 274 | For more detailed information, checkout the working example in 275 | [nest-authz-example](https://github.com/node-casbin/nest-authz-example) 276 | 277 | ## License 278 | 279 | This project is licensed under the MIT license. 280 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [2.17.0](https://github.com/node-casbin/nest-authz/compare/v2.16.0...v2.17.0) (2025-04-23) 2 | 3 | 4 | ### Features 5 | 6 | * loosen reflect-metadata peerDependency for Nest v10 ([#178](https://github.com/node-casbin/nest-authz/issues/178)) ([7c0e2b8](https://github.com/node-casbin/nest-authz/commit/7c0e2b8e2144f95b6575dccca235ff0fffd8cdac)) 7 | 8 | # [2.16.0](https://github.com/node-casbin/nest-authz/compare/v2.15.0...v2.16.0) (2025-04-23) 9 | 10 | 11 | ### Features 12 | 13 | * remove "cache: 'yarn'" in CI ([51fb110](https://github.com/node-casbin/nest-authz/commit/51fb110ced890478fd440d7ea4c5cdc96d2d78af)) 14 | 15 | # [2.15.0](https://github.com/node-casbin/nest-authz/compare/v2.14.0...v2.15.0) (2025-03-17) 16 | 17 | 18 | ### Features 19 | 20 | * allow AuthZGuard children to access injected dependencies ([#177](https://github.com/node-casbin/nest-authz/issues/177)) ([569d1f8](https://github.com/node-casbin/nest-authz/commit/569d1f836185308c9a4b9186c8b5f023b8fa3728)) 21 | 22 | # [2.14.0](https://github.com/node-casbin/nest-authz/compare/v2.13.0...v2.14.0) (2025-02-12) 23 | 24 | 25 | ### Features 26 | 27 | * fix bug in authz.service.ts: invalid request size: expected 3, got 1, rvals: ([#176](https://github.com/node-casbin/nest-authz/issues/176)) ([ac259c2](https://github.com/node-casbin/nest-authz/commit/ac259c28e8a3e97d55185271f120d30f0c87bc15)) 28 | 29 | # [2.13.0](https://github.com/node-casbin/nest-authz/compare/v2.12.0...v2.13.0) (2025-02-12) 30 | 31 | 32 | ### Features 33 | 34 | * fix "invalid request size: expected 3, got 1" bug in AuthZService.enforce ([#175](https://github.com/node-casbin/nest-authz/issues/175)) ([7b4d406](https://github.com/node-casbin/nest-authz/commit/7b4d4063f142043cfcda493b65bfb3b7eb4bb74a)) 35 | 36 | # [2.12.0](https://github.com/node-casbin/nest-authz/compare/v2.11.0...v2.12.0) (2025-01-09) 37 | 38 | 39 | ### Features 40 | 41 | * Add support for guarding based on request data ([#173](https://github.com/node-casbin/nest-authz/issues/173)) ([7ea8f53](https://github.com/node-casbin/nest-authz/commit/7ea8f53640e2efe2c8ee8b9249d5cb7bff51461d)) 42 | 43 | # [2.11.0](https://github.com/node-casbin/nest-authz/compare/v2.10.0...v2.11.0) (2024-08-06) 44 | 45 | 46 | ### Features 47 | 48 | * Unify RBAC and Management services into single service ([#171](https://github.com/node-casbin/nest-authz/issues/171)) ([2c9fbb3](https://github.com/node-casbin/nest-authz/commit/2c9fbb3a4b2b6f763b7ba938a3ac489c78161a5d)) 49 | 50 | # [2.10.0](https://github.com/node-casbin/nest-authz/compare/v2.9.0...v2.10.0) (2024-07-03) 51 | 52 | 53 | ### Features 54 | 55 | * Update to latest node-casbin version and improve API support ([#169](https://github.com/node-casbin/nest-authz/issues/169)) ([a3ab9d3](https://github.com/node-casbin/nest-authz/commit/a3ab9d3bbd69d21f9a173b2759ff58c1d853f656)) 56 | 57 | # [2.9.0](https://github.com/node-casbin/nest-authz/compare/v2.8.0...v2.9.0) (2024-06-27) 58 | 59 | 60 | ### Features 61 | 62 | * Add ABAC support and make custom actions more flexible ([#168](https://github.com/node-casbin/nest-authz/issues/168)) ([e0bc88f](https://github.com/node-casbin/nest-authz/commit/e0bc88fe5a15eafb1d818603d432c4b41479ea7c)) 63 | 64 | # [2.8.0](https://github.com/node-casbin/nest-authz/compare/v2.7.0...v2.8.0) (2024-03-24) 65 | 66 | 67 | ### Features 68 | 69 | * allows user to access underlying casbin enforcer ([#166](https://github.com/node-casbin/nest-authz/issues/166)) ([26ea61d](https://github.com/node-casbin/nest-authz/commit/26ea61dc68f6885cee1ae7970565c0a2dd048262)) 70 | 71 | # [2.7.0](https://github.com/node-casbin/nest-authz/compare/v2.6.0...v2.7.0) (2024-03-24) 72 | 73 | 74 | ### Features 75 | 76 | * upgrade CI Node.js version to 20 ([4fe3e12](https://github.com/node-casbin/nest-authz/commit/4fe3e12379880e1a0b6b9547d8605f546c456b63)) 77 | 78 | # [2.6.0](https://github.com/node-casbin/nest-authz/compare/v2.5.1...v2.6.0) (2023-09-14) 79 | 80 | 81 | ### Bug Fixes 82 | 83 | * fix broken links ([#162](https://github.com/node-casbin/nest-authz/issues/162)) ([f3a5415](https://github.com/node-casbin/nest-authz/commit/f3a5415cd40bef675884a051e9c3a5482680c570)) 84 | 85 | 86 | ### Features 87 | 88 | * bump version to v2.6.0 ([4cce89b](https://github.com/node-casbin/nest-authz/commit/4cce89b00203945e998db5022542c40b4f61d18f)) 89 | 90 | # [2.4.0](https://github.com/node-casbin/nest-authz/compare/v2.3.0...v2.4.0) (2023-07-18) 91 | 92 | 93 | ### Features 94 | 95 | * upgrade nestjs version to v9 ([#160](https://github.com/node-casbin/nest-authz/issues/160)) ([9a6811f](https://github.com/node-casbin/nest-authz/commit/9a6811fd34a2eefceeb27909a93ab1233b8ff0d4)) 96 | 97 | # [2.3.0](https://github.com/node-casbin/nest-authz/compare/v2.2.1...v2.3.0) (2023-06-22) 98 | 99 | 100 | ### Features 101 | 102 | * fix CI Node.js version ([53965d3](https://github.com/node-casbin/nest-authz/commit/53965d34be6442f6931fa6073126b9998473d7df)) 103 | * update peer dependencies to allow NestJS v10 ([#158](https://github.com/node-casbin/nest-authz/issues/158)) ([924fad4](https://github.com/node-casbin/nest-authz/commit/924fad4a0754db1763c115f0f0d49d9de240c833)) 104 | 105 | ## [2.2.1](https://github.com/node-casbin/nest-authz/compare/v2.2.0...v2.2.1) (2022-07-17) 106 | 107 | 108 | ### Bug Fixes 109 | 110 | * upgrade dependencies ([#156](https://github.com/node-casbin/nest-authz/issues/156)) ([005308b](https://github.com/node-casbin/nest-authz/commit/005308b07cc312ac9716900f00afd8cf546fc495)) 111 | 112 | # [2.2.0](https://github.com/node-casbin/nest-authz/compare/v2.1.0...v2.2.0) (2021-08-13) 113 | 114 | 115 | ### Bug Fixes 116 | 117 | * fix compile error ([a1cf723](https://github.com/node-casbin/nest-authz/commit/a1cf723c34522441bc7f6baf395eb044ac356c09)) 118 | * **deps:** update dependency casbin to v5.6.0 ([fe4c881](https://github.com/node-casbin/nest-authz/commit/fe4c881b1ff8e7fd91d6f935e45f59f14400f949)) 119 | * **deps:** update dependency casbin to v5.8.0 ([59d038f](https://github.com/node-casbin/nest-authz/commit/59d038f9cc477a5115fc623dfc908c6ee5c1bb1a)) 120 | 121 | 122 | ### Features 123 | 124 | * add support for custom action verb ([9d7c7ed](https://github.com/node-casbin/nest-authz/commit/9d7c7edd9f9812b19627db6f957a8cdf2f2e5fe6)) 125 | 126 | # Changelog 127 | 128 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 129 | 130 | ## [2.1.0](https://github.com/node-casbin/nest-authz/compare/v2.0.0...v2.1.0) (2021-03-20) 131 | 132 | 133 | ### Features 134 | 135 | * **authz-management.service:** add more management methods ([6411a44](https://github.com/node-casbin/nest-authz/commit/6411a4467fbe6747f481e541ff42c7af0edb2cfb)) 136 | 137 | 138 | ### Bug Fixes 139 | 140 | * **deps:** update dependency casbin to v5 ([#95](https://github.com/node-casbin/nest-authz/issues/95)) ([d8a83fd](https://github.com/node-casbin/nest-authz/commit/d8a83fd1a1fbaef340a90f82940697d2bdc1a80e)) 141 | 142 | ## [2.0.0](https://github.com/node-casbin/nest-authz/compare/v1.1.0...v2.0.0) (2020-05-17) 143 | 144 | 145 | ### ⚠ BREAKING CHANGES 146 | 147 | * drop support for node v8. Required Nodejs>= 10.13.0 as nestjs v7 148 | upgrade casbin to v4 making apis async. 149 | 150 | ### Features 151 | 152 | * **services:** add casbin apis since v2 ([340a60c](https://github.com/node-casbin/nest-authz/commit/340a60c68e0e4e84888ad9a9f97a88d81ff29709)) 153 | 154 | 155 | ### Bug Fixes 156 | 157 | * **deps:** update dependency @nestjs/swagger to v4.1.12 ([eb27853](https://github.com/node-casbin/nest-authz/commit/eb278538fe99f3b629d8110650f454d4be629917)) 158 | * **deps:** update dependency @nestjs/swagger to v4.1.13 ([866ab7f](https://github.com/node-casbin/nest-authz/commit/866ab7f86df295f4fdbd5fb1f7bc083f052314c2)) 159 | * **deps:** update dependency @nestjs/swagger to v4.1.14 ([a00b4f9](https://github.com/node-casbin/nest-authz/commit/a00b4f99f99b4de9b11e134999240571fb63cc06)) 160 | * **deps:** update dependency @nestjs/swagger to v4.1.14 ([#54](https://github.com/node-casbin/nest-authz/issues/54)) ([a7f164b](https://github.com/node-casbin/nest-authz/commit/a7f164b32ebc9a1a6c65de075f98569f2ac1a09b)) 161 | * **deps:** update dependency @nestjs/swagger to v4.1.15 ([ae38445](https://github.com/node-casbin/nest-authz/commit/ae3844587be7404a5fdf9b4774bf89705d4aaac8)) 162 | * **deps:** update dependency @nestjs/swagger to v4.2.1 ([624a318](https://github.com/node-casbin/nest-authz/commit/624a318d5a989d3e41fc416d73ff1d5cfa8964e1)) 163 | * **deps:** update dependency @nestjs/swagger to v4.2.1 ([#60](https://github.com/node-casbin/nest-authz/issues/60)) ([4a3789e](https://github.com/node-casbin/nest-authz/commit/4a3789e62453270f861a3dae9ee1823fc718aad1)) 164 | * **deps:** update dependency @nestjs/swagger to v4.3.1 ([8926983](https://github.com/node-casbin/nest-authz/commit/892698313493bb6c5ef04a95e755b08862e7333f)) 165 | * **deps:** update dependency swagger-ui-express to v4.1.3 ([08a9bdc](https://github.com/node-casbin/nest-authz/commit/08a9bdc6b7d6a2e937b138e19b56bea1a53d4af0)) 166 | * **deps:** update dependency swagger-ui-express to v4.1.3 ([#55](https://github.com/node-casbin/nest-authz/issues/55)) ([e8529e6](https://github.com/node-casbin/nest-authz/commit/e8529e60b563c1b84154fd3651ffdfe12b3473cf)) 167 | * **deps:** update dependency uuid to v3.4.0 ([f3aeb12](https://github.com/node-casbin/nest-authz/commit/f3aeb124c7dab1ea79325955a97158dcf19796a1)) 168 | 169 | 170 | ### build 171 | 172 | * update dependencies ([1c06e17](https://github.com/node-casbin/nest-authz/commit/1c06e17c0af92270ed1e8e1f11c562185f6a6835)) 173 | 174 | ## [1.1.0](https://github.com/node-casbin/nest-authz/compare/v1.0.0...v1.1.0) (2020-01-03) 175 | 176 | 177 | ### Features 178 | 179 | * add module options to allow dynamic configure enforcer ([#42](https://github.com/node-casbin/nest-authz/issues/42)) ([d03472f](https://github.com/node-casbin/nest-authz/commit/d03472f83a5d223e6b441c4a69c766c454395e73)) 180 | * **options:** add module options ([765df74](https://github.com/node-casbin/nest-authz/commit/765df745646fc25f4984808e513df16b8cf70893)) 181 | 182 | 183 | ### Bug Fixes 184 | 185 | * **deps:** pin dependencies ([07f5668](https://github.com/node-casbin/nest-authz/commit/07f56681555d2c082ab669b89ec611fa841bbc82)) 186 | * **deps:** update dependency @nestjs/passport to v6.1.1 ([e48df14](https://github.com/node-casbin/nest-authz/commit/e48df141a6a8214d0d7509dc23363891ad1384a3)) 187 | * **deps:** update dependency @nestjs/passport to v6.1.1 ([#21](https://github.com/node-casbin/nest-authz/issues/21)) ([df4ee95](https://github.com/node-casbin/nest-authz/commit/df4ee952c2ca418bb9dccc067801bb6ca13e0692)) 188 | * **deps:** update dependency @nestjs/swagger to v4 ([f91ce80](https://github.com/node-casbin/nest-authz/commit/f91ce8063cd786f0054e9f0ff6c11fdf2a4ed866)) 189 | * **deps:** update dependency @nestjs/swagger to v4.1.2 ([05d18aa](https://github.com/node-casbin/nest-authz/commit/05d18aa4786e82adf92a165a269c2ac8ad90c102)) 190 | * **deps:** update dependency @nestjs/swagger to v4.1.2 ([#26](https://github.com/node-casbin/nest-authz/issues/26)) ([b16ab8d](https://github.com/node-casbin/nest-authz/commit/b16ab8d10753f1f0cf871e0f34a52ff2b02bba8d)) 191 | * **deps:** update dependency class-validator to v0.11.0 ([7fe2dac](https://github.com/node-casbin/nest-authz/commit/7fe2dacc43847708403da2733dcb563866ce2cfe)) 192 | * **deps:** update dependency class-validator to v0.11.0 ([#5](https://github.com/node-casbin/nest-authz/issues/5)) ([c91051c](https://github.com/node-casbin/nest-authz/commit/c91051cc324fb426959afcfce82905102ea2b81b)) 193 | * **deps:** update dependency dotenv to v8 ([d0fa313](https://github.com/node-casbin/nest-authz/commit/d0fa3137f8db1cf4ad4af734d91a4c594452789f)) 194 | * **deps:** update dependency dotenv to v8 ([#14](https://github.com/node-casbin/nest-authz/issues/14)) ([8b777b9](https://github.com/node-casbin/nest-authz/commit/8b777b9ca056d538671a922f386e7ce54fe3ea32)) 195 | * **deps:** update dependency passport to v0.4.1 ([fb57896](https://github.com/node-casbin/nest-authz/commit/fb57896338ef430d1dfb0429eeb07438cfb7fb5d)) 196 | * **deps:** update dependency passport to v0.4.1 ([#30](https://github.com/node-casbin/nest-authz/issues/30)) ([6239013](https://github.com/node-casbin/nest-authz/commit/623901321bdb6c65a5dd3d20104c68ce669389f1)) 197 | 198 | # [1.0.0](https://github.com/node-casbin/nest-authz/compare/v0.1.0...v1.0.0) (2019-04-27) 199 | 200 | 201 | ### Code Refactoring 202 | 203 | * refactor `isOwn` to accept ExecutionContext ([e757472](https://github.com/node-casbin/nest-authz/commit/e757472)) 204 | 205 | 206 | ### Features 207 | 208 | * **example:** add example to show usage ([0d573b8](https://github.com/node-casbin/nest-authz/commit/0d573b8)) 209 | * **module options:** add `usernameFromContext` ([48fd26c](https://github.com/node-casbin/nest-authz/commit/48fd26c)) 210 | 211 | 212 | ### BREAKING CHANGES 213 | 214 | * isOwn now accepts ExecutionContext as the only arg 215 | 216 | 217 | 218 | # [1.0.0](https://github.com/node-casbin/nest-authz/compare/v0.1.0...v1.0.0) (2019-04-27) 219 | 220 | 221 | ### Code Refactoring 222 | 223 | * refactor `isOwn` to accept ExecutionContext ([e757472](https://github.com/node-casbin/nest-authz/commit/e757472)) 224 | 225 | 226 | ### Features 227 | 228 | * **example:** add example to show usage ([0d573b8](https://github.com/node-casbin/nest-authz/commit/0d573b8)) 229 | * **module options:** add `usernameFromContext` ([48fd26c](https://github.com/node-casbin/nest-authz/commit/48fd26c)) 230 | 231 | 232 | ### BREAKING CHANGES 233 | 234 | * isOwn now accepts ExecutionContext as the only arg 235 | -------------------------------------------------------------------------------- /src/services/authz-api.ts: -------------------------------------------------------------------------------- 1 | import * as casbin from 'casbin'; 2 | 3 | export function getRolesForUser( 4 | enforcer: casbin.Enforcer, 5 | name: string, 6 | domain?: string 7 | ): Promise { 8 | return enforcer.getRolesForUser(name, domain); 9 | } 10 | 11 | export function getUsersForRole( 12 | enforcer: casbin.Enforcer, 13 | name: string, 14 | domain?: string 15 | ): Promise { 16 | return enforcer.getUsersForRole(name, domain); 17 | } 18 | 19 | export function hasRoleForUser( 20 | enforcer: casbin.Enforcer, 21 | name: string, 22 | role: string, 23 | domain?: string 24 | ): Promise { 25 | return enforcer.hasRoleForUser(name, role, domain); 26 | } 27 | 28 | export function addRoleForUser( 29 | enforcer: casbin.Enforcer, 30 | user: string, 31 | role: string, 32 | domain?: string 33 | ): Promise { 34 | return enforcer.addRoleForUser(user, role, domain); 35 | } 36 | 37 | export function deleteRoleForUser( 38 | enforcer: casbin.Enforcer, 39 | user: string, 40 | role: string, 41 | domain?: string 42 | ): Promise { 43 | return enforcer.deleteRoleForUser(user, role, domain); 44 | } 45 | 46 | export function deleteRolesForUser( 47 | enforcer: casbin.Enforcer, 48 | user: string, 49 | domain?: string 50 | ): Promise { 51 | return enforcer.deleteRolesForUser(user, domain); 52 | } 53 | 54 | export function deleteUser( 55 | enforcer: casbin.Enforcer, 56 | user: string 57 | ): Promise { 58 | return enforcer.deleteUser(user); 59 | } 60 | 61 | export function deleteRole( 62 | enforcer: casbin.Enforcer, 63 | role: string 64 | ): Promise { 65 | return enforcer.deleteRole(role); 66 | } 67 | 68 | export function deletePermission( 69 | enforcer: casbin.Enforcer, 70 | ...permission: string[] 71 | ): Promise { 72 | return enforcer.deletePermission(...permission); 73 | } 74 | 75 | export function addPermissionForUser( 76 | enforcer: casbin.Enforcer, 77 | userOrRole: string, 78 | ...permission: string[] 79 | ): Promise { 80 | return enforcer.addPermissionForUser(userOrRole, ...permission); 81 | } 82 | 83 | export function deletePermissionForUser( 84 | enforcer: casbin.Enforcer, 85 | userOrRole: string, 86 | ...permission: string[] 87 | ): Promise { 88 | return enforcer.deletePermissionForUser(userOrRole, ...permission); 89 | } 90 | 91 | export function deletePermissionsForUser( 92 | enforcer: casbin.Enforcer, 93 | userOrRole: string 94 | ): Promise { 95 | return enforcer.deletePermissionsForUser(userOrRole); 96 | } 97 | 98 | export function getPermissionsForUser( 99 | enforcer: casbin.Enforcer, 100 | userOrRole: string 101 | ): Promise { 102 | return enforcer.getPermissionsForUser(userOrRole); 103 | } 104 | 105 | export function hasPermissionForUser( 106 | enforcer: casbin.Enforcer, 107 | user: string, 108 | ...permission: string[] 109 | ): Promise { 110 | return enforcer.hasPermissionForUser(user, ...permission); 111 | } 112 | 113 | export function getImplicitRolesForUser( 114 | enforcer: casbin.Enforcer, 115 | name: string, 116 | ...domain: string[] 117 | ): Promise { 118 | return enforcer.getImplicitRolesForUser(name, ...domain); 119 | } 120 | 121 | export function getImplicitResourcesForUser( 122 | enforcer: casbin.Enforcer, 123 | name: string, 124 | ...domain: string[] 125 | ): Promise { 126 | return enforcer.getImplicitResourcesForUser(name, ...domain); 127 | } 128 | 129 | export function getImplicitPermissionsForUser( 130 | enforcer: casbin.Enforcer, 131 | user: string, 132 | ...domain: string[] 133 | ): Promise { 134 | return enforcer.getImplicitPermissionsForUser(user, ...domain); 135 | } 136 | 137 | export function getImplicitUsersForPermission( 138 | enforcer: casbin.Enforcer, 139 | ...permission: string[] 140 | ): Promise { 141 | return enforcer.getImplicitUsersForPermission(...permission); 142 | } 143 | 144 | /** 145 | * Management API 146 | */ 147 | 148 | export function enforce( 149 | enforcer: casbin.Enforcer, 150 | ...params: any[] 151 | ): Promise { 152 | return enforcer.enforce(...params); 153 | } 154 | 155 | export function enforceWithMatcher( 156 | enforcer: casbin.Enforcer, 157 | matcher: string, 158 | ...params: any[] 159 | ): Promise { 160 | return enforcer.enforceWithMatcher(matcher, ...params); 161 | } 162 | 163 | export function enforceEx( 164 | enforcer: casbin.Enforcer, 165 | ...params: any[] 166 | ): Promise<[boolean, string[]]> { 167 | return enforcer.enforceEx(...params); 168 | } 169 | 170 | export function enforceExWithMatcher( 171 | enforcer: casbin.Enforcer, 172 | matcher: string, 173 | ...params: any[] 174 | ): Promise<[boolean, string[]]> { 175 | return enforcer.enforceExWithMatcher(matcher, ...params); 176 | } 177 | 178 | export function batchEnforce( 179 | enforcer: casbin.Enforcer, 180 | params: any[][] 181 | ): Promise { 182 | return enforcer.batchEnforce(params); 183 | } 184 | 185 | export function getAllSubjects(enforcer: casbin.Enforcer): Promise { 186 | return enforcer.getAllSubjects(); 187 | } 188 | 189 | export function getAllNamedSubjects( 190 | enforcer: casbin.Enforcer, 191 | ptype: string 192 | ): Promise { 193 | return enforcer.getAllNamedSubjects(ptype); 194 | } 195 | 196 | export function getAllObjects(enforcer: casbin.Enforcer): Promise { 197 | return enforcer.getAllObjects(); 198 | } 199 | 200 | export function getAllNamedObjects( 201 | enforcer: casbin.Enforcer, 202 | ptype: string 203 | ): Promise { 204 | return enforcer.getAllNamedObjects(ptype); 205 | } 206 | 207 | export function getAllActions(enforcer: casbin.Enforcer): Promise { 208 | return enforcer.getAllActions(); 209 | } 210 | 211 | export function getAllNamedActions( 212 | enforcer: casbin.Enforcer, 213 | ptype: string 214 | ): Promise { 215 | return enforcer.getAllNamedActions(ptype); 216 | } 217 | 218 | export function getAllRoles(enforcer: casbin.Enforcer): Promise { 219 | return enforcer.getAllRoles(); 220 | } 221 | 222 | export function getAllNamedRoles( 223 | enforcer: casbin.Enforcer, 224 | ptype: string 225 | ): Promise { 226 | return enforcer.getAllNamedRoles(ptype); 227 | } 228 | 229 | export function getPolicy(enforcer: casbin.Enforcer): Promise { 230 | return enforcer.getPolicy(); 231 | } 232 | 233 | export function getFilteredPolicy( 234 | enforcer: casbin.Enforcer, 235 | fieldIndex: number, 236 | ...fieldValues: string[] 237 | ): Promise { 238 | return enforcer.getFilteredPolicy(fieldIndex, ...fieldValues); 239 | } 240 | 241 | export function getNamedPolicy( 242 | enforcer: casbin.Enforcer, 243 | ptype: string 244 | ): Promise { 245 | return enforcer.getNamedPolicy(ptype); 246 | } 247 | 248 | export function getFilteredNamedPolicy( 249 | enforcer: casbin.Enforcer, 250 | ptype: string, 251 | fieldIndex: number, 252 | ...fieldValues: string[] 253 | ): Promise { 254 | return enforcer.getFilteredNamedPolicy(ptype, fieldIndex, ...fieldValues); 255 | } 256 | 257 | export function getGroupingPolicy( 258 | enforcer: casbin.Enforcer 259 | ): Promise { 260 | return enforcer.getGroupingPolicy(); 261 | } 262 | 263 | export function getFilteredGroupingPolicy( 264 | enforcer: casbin.Enforcer, 265 | fieldIndex: number, 266 | ...fieldValues: string[] 267 | ): Promise { 268 | return enforcer.getFilteredGroupingPolicy(fieldIndex, ...fieldValues); 269 | } 270 | 271 | export function getNamedGroupingPolicy( 272 | enforcer: casbin.Enforcer, 273 | ptype: string 274 | ): Promise { 275 | return enforcer.getNamedGroupingPolicy(ptype); 276 | } 277 | 278 | export function getFilteredNamedGroupingPolicy( 279 | enforcer: casbin.Enforcer, 280 | ptype: string, 281 | fieldIndex: number, 282 | ...fieldValues: string[] 283 | ): Promise { 284 | return enforcer.getFilteredNamedGroupingPolicy( 285 | ptype, 286 | fieldIndex, 287 | ...fieldValues 288 | ); 289 | } 290 | 291 | export function hasPolicy( 292 | enforcer: casbin.Enforcer, 293 | ...params: string[] 294 | ): Promise { 295 | return enforcer.hasPolicy(...params); 296 | } 297 | 298 | export function hasNamedPolicy( 299 | enforcer: casbin.Enforcer, 300 | ptype: string, 301 | ...params: string[] 302 | ): Promise { 303 | return enforcer.hasNamedPolicy(ptype, ...params); 304 | } 305 | 306 | export function addPolicy( 307 | enforcer: casbin.Enforcer, 308 | ...params: string[] 309 | ): Promise { 310 | return enforcer.addPolicy(...params); 311 | } 312 | 313 | export function addPolicies( 314 | enforcer: casbin.Enforcer, 315 | rules: string[][] 316 | ): Promise { 317 | return enforcer.addPolicies(rules); 318 | } 319 | 320 | export function addNamedPolicy( 321 | enforcer: casbin.Enforcer, 322 | ptype: string, 323 | ...params: string[] 324 | ): Promise { 325 | return enforcer.addNamedPolicy(ptype, ...params); 326 | } 327 | 328 | export function addNamedPolicies( 329 | enforcer: casbin.Enforcer, 330 | ptype: string, 331 | rules: string[][] 332 | ): Promise { 333 | return enforcer.addNamedPolicies(ptype, rules); 334 | } 335 | 336 | export function updatePolicy( 337 | enforcer: casbin.Enforcer, 338 | oldRule: string[], 339 | newRule: string[] 340 | ): Promise { 341 | return enforcer.updatePolicy(oldRule, newRule); 342 | } 343 | 344 | export function updateNamedPolicy( 345 | enforcer: casbin.Enforcer, 346 | ptype: string, 347 | oldRule: string[], 348 | newRule: string[] 349 | ): Promise { 350 | return enforcer.updateNamedPolicy(ptype, oldRule, newRule); 351 | } 352 | 353 | export function removePolicy( 354 | enforcer: casbin.Enforcer, 355 | ...params: string[] 356 | ): Promise { 357 | return enforcer.removePolicy(...params); 358 | } 359 | 360 | export function removePolicies( 361 | enforcer: casbin.Enforcer, 362 | rules: string[][] 363 | ): Promise { 364 | return enforcer.removePolicies(rules); 365 | } 366 | 367 | export function removeFilteredPolicy( 368 | enforcer: casbin.Enforcer, 369 | fieldIndex: number, 370 | ...fieldValues: string[] 371 | ): Promise { 372 | return enforcer.removeFilteredPolicy(fieldIndex, ...fieldValues); 373 | } 374 | 375 | export function removeNamedPolicy( 376 | enforcer: casbin.Enforcer, 377 | ptype: string, 378 | ...params: string[] 379 | ): Promise { 380 | return enforcer.removeNamedPolicy(ptype, ...params); 381 | } 382 | 383 | export function removeNamedPolicies( 384 | enforcer: casbin.Enforcer, 385 | ptype: string, 386 | rules: string[][] 387 | ): Promise { 388 | return enforcer.removeNamedPolicies(ptype, rules); 389 | } 390 | 391 | export function removeFilteredNamedPolicy( 392 | enforcer: casbin.Enforcer, 393 | ptype: string, 394 | fieldIndex: number, 395 | ...fieldValues: string[] 396 | ): Promise { 397 | return enforcer.removeFilteredNamedPolicy(ptype, fieldIndex, ...fieldValues); 398 | } 399 | 400 | export function hasGroupingPolicy( 401 | enforcer: casbin.Enforcer, 402 | ...params: string[] 403 | ): Promise { 404 | return enforcer.hasGroupingPolicy(...params); 405 | } 406 | 407 | export function hasNamedGroupingPolicy( 408 | enforcer: casbin.Enforcer, 409 | ptype: string, 410 | ...params: string[] 411 | ): Promise { 412 | return enforcer.hasNamedGroupingPolicy(ptype, ...params); 413 | } 414 | export function addGroupingPolicy( 415 | enforcer: casbin.Enforcer, 416 | ...params: string[] 417 | ): Promise { 418 | return enforcer.addGroupingPolicy(...params); 419 | } 420 | export function addGroupingPolicies( 421 | enforcer: casbin.Enforcer, 422 | rules: string[][] 423 | ): Promise { 424 | return enforcer.addGroupingPolicies(rules); 425 | } 426 | export function addNamedGroupingPolicy( 427 | enforcer: casbin.Enforcer, 428 | ptype: string, 429 | ...params: string[] 430 | ): Promise { 431 | return enforcer.addNamedGroupingPolicy(ptype, ...params); 432 | } 433 | export function addNamedGroupingPolicies( 434 | enforcer: casbin.Enforcer, 435 | ptype: string, 436 | rules: string[][] 437 | ): Promise { 438 | return enforcer.addNamedGroupingPolicies(ptype, rules); 439 | } 440 | export function removeGroupingPolicy( 441 | enforcer: casbin.Enforcer, 442 | ...params: string[] 443 | ): Promise { 444 | return enforcer.removeGroupingPolicy(...params); 445 | } 446 | export function removeGroupingPolicies( 447 | enforcer: casbin.Enforcer, 448 | rules: string[][] 449 | ): Promise { 450 | return enforcer.removeGroupingPolicies(rules); 451 | } 452 | export function removeFilteredGroupingPolicy( 453 | enforcer: casbin.Enforcer, 454 | fieldIndex: number, 455 | ...fieldValues: string[] 456 | ): Promise { 457 | return enforcer.removeFilteredGroupingPolicy(fieldIndex, ...fieldValues); 458 | } 459 | export function removeNamedGroupingPolicy( 460 | enforcer: casbin.Enforcer, 461 | ptype: string, 462 | ...params: string[] 463 | ): Promise { 464 | return enforcer.removeNamedGroupingPolicy(ptype, ...params); 465 | } 466 | export function removeNamedGroupingPolicies( 467 | enforcer: casbin.Enforcer, 468 | ptype: string, 469 | rules: string[][] 470 | ): Promise { 471 | return enforcer.removeNamedGroupingPolicies(ptype, rules); 472 | } 473 | export function removeFilteredNamedGroupingPolicy( 474 | enforcer: casbin.Enforcer, 475 | ptype: string, 476 | fieldIndex: number, 477 | ...fieldValues: string[] 478 | ): Promise { 479 | return enforcer.removeFilteredNamedGroupingPolicy( 480 | ptype, 481 | fieldIndex, 482 | ...fieldValues 483 | ); 484 | } 485 | export function addFunction( 486 | enforcer: casbin.Enforcer, 487 | name: string, 488 | func: any 489 | ): Promise { 490 | return enforcer.addFunction(name, func); 491 | } 492 | 493 | export function loadPolicy(enforcer: casbin.Enforcer): Promise { 494 | return enforcer.loadPolicy(); 495 | } 496 | 497 | export function updateGroupingPolicy( 498 | enforcer: casbin.Enforcer, 499 | oldRule: string[], 500 | newRule: string[] 501 | ): Promise { 502 | return enforcer.updateGroupingPolicy(oldRule, newRule); 503 | } 504 | 505 | export function updateNamedGroupingPolicy( 506 | enforcer: casbin.Enforcer, 507 | ptype: string, 508 | oldRule: string[], 509 | newRule: string[] 510 | ): Promise { 511 | return enforcer.updateNamedGroupingPolicy(ptype, oldRule, newRule); 512 | } 513 | -------------------------------------------------------------------------------- /src/services/authz-management.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Inject } from '@nestjs/common'; 2 | import { AUTHZ_ENFORCER } from '../authz.constants'; 3 | import * as casbin from 'casbin'; 4 | import * as authzAPI from './authz-api'; 5 | 6 | /** 7 | * A wrapper of casbin management API 8 | * @deprecated This service will be removed and replace by AuthZService in a later release. 9 | */ 10 | @Injectable() 11 | export class AuthZManagementService { 12 | constructor( 13 | @Inject(AUTHZ_ENFORCER) 14 | public readonly enforcer: casbin.Enforcer 15 | ) {} 16 | 17 | /** 18 | * enforce decides whether a "subject" can access a "object" with the operation "action" 19 | * 20 | * @param params the request parameters, usually (sub, obj, act) 21 | * 22 | * @return whether or not the request is allowed 23 | */ 24 | enforce(...params: string[]): Promise { 25 | return authzAPI.enforce(this.enforcer, params); 26 | } 27 | 28 | /** 29 | * enforceWithMatcher uses a custom matcher to decides whether a "subject" can access a "object" with the operation "action" 30 | * 31 | * @param matcher the matcher statement to use 32 | * @param params the request parameters, usually (sub, obj, act) 33 | * 34 | * @return whether or not the request is allowed 35 | */ 36 | enforceWithMatcher(matcher: string, ...params: string[]): Promise { 37 | return authzAPI.enforceWithMatcher(this.enforcer, matcher, params); 38 | } 39 | 40 | /** 41 | * enforceEx explains enforcement by returning matched rules. 42 | * 43 | * @param params the request parameters, usually (sub, obj, act) 44 | * 45 | * @return whether or not the request is allowed, and what policy caused that decision 46 | */ 47 | enforceEx(...params: string[]): Promise<[boolean, string[]]> { 48 | return authzAPI.enforceEx(this.enforcer, params); 49 | } 50 | 51 | /** 52 | * enforceExWithMatcher uses a custom matcher and explains enforcement by returning matched rules. 53 | * 54 | * @param matcher the matcher statement to use 55 | * @param params the request parameters, usually (sub, obj, act) 56 | * 57 | * @return whether or not the request is allowed, and what policy caused that decision 58 | */ 59 | enforceExWithMatcher( 60 | matcher: string, 61 | ...params: string[] 62 | ): Promise<[boolean, string[]]> { 63 | return authzAPI.enforceExWithMatcher(this.enforcer, matcher, params); 64 | } 65 | 66 | /** 67 | * batchEnforce enforces each request and returns result in a bool array 68 | * 69 | * @param params the request parameters, usually (sub, obj, act) 70 | * 71 | * @return an array with the enforcement results for each given request 72 | */ 73 | batchEnforce(params: string[][]): Promise { 74 | return authzAPI.batchEnforce(this.enforcer, params); 75 | } 76 | 77 | /** 78 | * getAllSubjects gets the list of subjects that show up in the current policy. 79 | * 80 | * @return all the subjects in "p" policy rules. It actually collects the 81 | * 0-index elements of "p" policy rules. So make sure your subject 82 | * is the 0-index element, like (sub, obj, act). Duplicates are removed. 83 | */ 84 | getAllSubjects(): Promise { 85 | return authzAPI.getAllSubjects(this.enforcer); 86 | } 87 | /** 88 | * getAllNamedSubjects gets the list of subjects that show up in the currentnamed policy. 89 | * 90 | * @param ptype the policy type, can be "p", "p2", "p3", .. 91 | * @return all the subjects in policy rules of the ptype type. It actually 92 | * collects the 0-index elements of the policy rules. So make sure 93 | * your subject is the 0-index element, like (sub, obj, act). 94 | * Duplicates are removed. 95 | */ 96 | getAllNamedSubjects(ptype: string): Promise { 97 | return authzAPI.getAllNamedSubjects(this.enforcer, ptype); 98 | } 99 | /** 100 | * getAllObjects gets the list of objects that show up in the current policy. 101 | * 102 | * @return all the objects in "p" policy rules. It actually collects the 103 | * 1-index elements of "p" policy rules. So make sure your object 104 | * is the 1-index element, like (sub, obj, act). 105 | * Duplicates are removed. 106 | */ 107 | getAllObjects(): Promise { 108 | return authzAPI.getAllObjects(this.enforcer); 109 | } 110 | /** 111 | * getAllNamedObjects gets the list of objects that show up in the current named policy. 112 | * 113 | * @param ptype the policy type, can be "p", "p2", "p3", .. 114 | * @return all the objects in policy rules of the ptype type. It actually 115 | * collects the 1-index elements of the policy rules. So make sure 116 | * your object is the 1-index element, like (sub, obj, act). 117 | * Duplicates are removed. 118 | */ 119 | getAllNamedObjects(ptype: string): Promise { 120 | return authzAPI.getAllNamedObjects(this.enforcer, ptype); 121 | } 122 | /** 123 | * getAllActions gets the list of actions that show up in the current policy. 124 | * 125 | * @return all the actions in "p" policy rules. It actually collects 126 | * the 2-index elements of "p" policy rules. So make sure your action 127 | * is the 2-index element, like (sub, obj, act). 128 | * Duplicates are removed. 129 | */ 130 | getAllActions(): Promise { 131 | return authzAPI.getAllActions(this.enforcer); 132 | } 133 | /** 134 | * GetAllNamedActions gets the list of actions that show up in the current named policy. 135 | * 136 | * @param ptype the policy type, can be "p", "p2", "p3", .. 137 | * @return all the actions in policy rules of the ptype type. It actually 138 | * collects the 2-index elements of the policy rules. So make sure 139 | * your action is the 2-index element, like (sub, obj, act). 140 | * Duplicates are removed. 141 | */ 142 | getAllNamedActions(ptype: string): Promise { 143 | return authzAPI.getAllNamedActions(this.enforcer, ptype); 144 | } 145 | /** 146 | * getAllRoles gets the list of roles that show up in the current policy. 147 | * 148 | * @return all the roles in "g" policy rules. It actually collects 149 | * the 1-index elements of "g" policy rules. So make sure your 150 | * role is the 1-index element, like (sub, role). 151 | * Duplicates are removed. 152 | */ 153 | getAllRoles(): Promise { 154 | return authzAPI.getAllRoles(this.enforcer); 155 | } 156 | /** 157 | * getAllNamedRoles gets the list of roles that show up in the current named policy. 158 | * 159 | * @param ptype the policy type, can be "g", "g2", "g3", .. 160 | * @return all the subjects in policy rules of the ptype type. It actually 161 | * collects the 0-index elements of the policy rules. So make 162 | * sure your subject is the 0-index element, like (sub, obj, act). 163 | * Duplicates are removed. 164 | */ 165 | getAllNamedRoles(ptype: string): Promise { 166 | return authzAPI.getAllNamedRoles(this.enforcer, ptype); 167 | } 168 | /** 169 | * getPolicy gets all the authorization rules in the policy. 170 | * 171 | * @return all the "p" policy rules. 172 | */ 173 | getPolicy(): Promise { 174 | return authzAPI.getPolicy(this.enforcer); 175 | } 176 | /** 177 | * getFilteredPolicy gets all the authorization rules in the policy, field filters can be specified. 178 | * 179 | * @param fieldIndex the policy rule's start index to be matched. 180 | * @param fieldValues the field values to be matched, value "" 181 | * means not to match this field. 182 | * @return the filtered "p" policy rules. 183 | */ 184 | getFilteredPolicy( 185 | fieldIndex: number, 186 | ...fieldValues: string[] 187 | ): Promise { 188 | return authzAPI.getFilteredPolicy( 189 | this.enforcer, 190 | fieldIndex, 191 | ...fieldValues 192 | ); 193 | } 194 | /** 195 | * getNamedPolicy gets all the authorization rules in the named policy. 196 | * 197 | * @param ptype the policy type, can be "p", "p2", "p3", .. 198 | * @return the "p" policy rules of the specified ptype. 199 | */ 200 | getNamedPolicy(ptype: string): Promise { 201 | return authzAPI.getNamedPolicy(this.enforcer, ptype); 202 | } 203 | /** 204 | * getFilteredNamedPolicy gets all the authorization rules in the named policy, field filters can be specified. 205 | * 206 | * @param ptype the policy type, can be "p", "p2", "p3", .. 207 | * @param fieldIndex the policy rule's start index to be matched. 208 | * @param fieldValues the field values to be matched, value "" 209 | * means not to match this field. 210 | * @return the filtered "p" policy rules of the specified ptype. 211 | */ 212 | getFilteredNamedPolicy( 213 | ptype: string, 214 | fieldIndex: number, 215 | ...fieldValues: string[] 216 | ): Promise { 217 | return authzAPI.getFilteredNamedPolicy( 218 | this.enforcer, 219 | ptype, 220 | fieldIndex, 221 | ...fieldValues 222 | ); 223 | } 224 | /** 225 | * getGroupingPolicy gets all the role inheritance rules in the policy. 226 | * 227 | * @return all the "g" policy rules. 228 | */ 229 | getGroupingPolicy(): Promise { 230 | return authzAPI.getGroupingPolicy(this.enforcer); 231 | } 232 | /** 233 | * getFilteredGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified. 234 | * 235 | * @param fieldIndex the policy rule's start index to be matched. 236 | * @param fieldValues the field values to be matched, value "" means not to match this field. 237 | * @return the filtered "g" policy rules. 238 | */ 239 | getFilteredGroupingPolicy( 240 | fieldIndex: number, 241 | ...fieldValues: string[] 242 | ): Promise { 243 | return authzAPI.getFilteredGroupingPolicy( 244 | this.enforcer, 245 | fieldIndex, 246 | ...fieldValues 247 | ); 248 | } 249 | /** 250 | * getNamedGroupingPolicy gets all the role inheritance rules in the policy. 251 | * 252 | * @param ptype the policy type, can be "g", "g2", "g3", .. 253 | * @return the "g" policy rules of the specified ptype. 254 | */ 255 | getNamedGroupingPolicy(ptype: string): Promise { 256 | return authzAPI.getNamedGroupingPolicy(this.enforcer, ptype); 257 | } 258 | /** 259 | * getFilteredNamedGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified. 260 | * 261 | * @param ptype the policy type, can be "g", "g2", "g3", .. 262 | * @param fieldIndex the policy rule's start index to be matched. 263 | * @param fieldValues the field values to be matched, value "" 264 | * means not to match this field. 265 | * @return the filtered "g" policy rules of the specified ptype. 266 | */ 267 | getFilteredNamedGroupingPolicy( 268 | ptype: string, 269 | fieldIndex: number, 270 | ...fieldValues: string[] 271 | ): Promise { 272 | return authzAPI.getFilteredNamedGroupingPolicy( 273 | this.enforcer, 274 | ptype, 275 | fieldIndex, 276 | ...fieldValues 277 | ); 278 | } 279 | /** 280 | * hasPolicy determines whether an authorization rule exists. 281 | * 282 | * @param params the "p" policy rule, ptype "p" is implicitly used. 283 | * @return whether the rule exists. 284 | */ 285 | hasPolicy(...params: string[]): Promise { 286 | return authzAPI.hasPolicy(this.enforcer, ...params); 287 | } 288 | /** 289 | * hasNamedPolicy determines whether a named authorization rule exists. 290 | * 291 | * @param ptype the policy type, can be "p", "p2", "p3", .. 292 | * @param params the "p" policy rule. 293 | * @return whether the rule exists. 294 | */ 295 | hasNamedPolicy(ptype: string, ...params: string[]): Promise { 296 | return authzAPI.hasNamedPolicy(this.enforcer, ptype, ...params); 297 | } 298 | /** 299 | * addPolicy adds an authorization rule to the current policy. 300 | * If the rule already exists, the function returns false and the rule will not be added. 301 | * Otherwise the function returns true by adding the new rule. 302 | * 303 | * @param params the "p" policy rule, ptype "p" is implicitly used. 304 | * @return succeeds or not. 305 | */ 306 | addPolicy(...params: string[]): Promise { 307 | return authzAPI.addPolicy(this.enforcer, ...params); 308 | } 309 | 310 | /** 311 | * addPolicies adds authorization rules to the current policy. 312 | * If the rule already exists, the function returns false and the rules will not be added. 313 | * Otherwise the function returns true by adding the new rules. 314 | * 315 | * @param rules the "p" policy rules, ptype "p" is implicitly used. 316 | * @return succeeds or not. 317 | */ 318 | addPolicies(rules: string[][]): Promise { 319 | return authzAPI.addPolicies(this.enforcer, rules); 320 | } 321 | 322 | /** 323 | * addNamedPolicy adds an authorization rule to the current named policy. 324 | * If the rule already exists, the function returns false and the rule will not be added. 325 | * Otherwise the function returns true by adding the new rule. 326 | * 327 | * @param ptype the policy type, can be "p", "p2", "p3", .. 328 | * @param params the "p" policy rule. 329 | * @return succeeds or not. 330 | */ 331 | addNamedPolicy(ptype: string, ...params: string[]): Promise { 332 | return authzAPI.addNamedPolicy(this.enforcer, ptype, ...params); 333 | } 334 | 335 | /** 336 | * addNamedPolicies adds authorization rules to the current named policy. 337 | * If the rule already exists, the function returns false and the rules will not be added. 338 | * Otherwise the function returns true by adding the new rules. 339 | * 340 | * @param ptype the policy type, can be "p", "p2", "p3", .. 341 | * @param rules the "p" policy rules. 342 | * @return succeeds or not. 343 | */ 344 | addNamedPolicies(ptype: string, rules: string[][]): Promise { 345 | return authzAPI.addNamedPolicies(this.enforcer, ptype, rules); 346 | } 347 | 348 | /** 349 | * updatePolicy updates an authorization rule from the current policy. 350 | * If the rule not exists, the function returns false. 351 | * Otherwise the function returns true by changing it to the new rule. 352 | * 353 | * @return succeeds or not. 354 | * @param oldRule the policy will be remove 355 | * @param newRule the policy will be added 356 | */ 357 | updatePolicy(oldRule: string[], newRule: string[]): Promise { 358 | return authzAPI.updatePolicy(this.enforcer, oldRule, newRule); 359 | } 360 | 361 | /** 362 | * updateNamedPolicy updates an authorization rule from the current named policy. 363 | * If the rule not exists, the function returns false. 364 | * Otherwise the function returns true by changing it to the new rule. 365 | * 366 | * @param ptype the policy type, can be "p", "p2", "p3", .. 367 | * @param oldRule the policy rule will be remove 368 | * @param newRule the policy rule will be added 369 | * @return succeeds or not. 370 | */ 371 | updateNamedPolicy( 372 | ptype: string, 373 | oldRule: string[], 374 | newRule: string[] 375 | ): Promise { 376 | return authzAPI.updateNamedPolicy(this.enforcer, ptype, oldRule, newRule); 377 | } 378 | 379 | /** 380 | * removePolicy removes an authorization rule from the current policy. 381 | * 382 | * @param params the "p" policy rule, ptype "p" is implicitly used. 383 | * @return succeeds or not. 384 | */ 385 | removePolicy(...params: string[]): Promise { 386 | return authzAPI.removePolicy(this.enforcer, ...params); 387 | } 388 | /** 389 | * removePolicies removes an authorization rules from the current policy. 390 | * 391 | * @param rules the "p" policy rules, ptype "p" is implicitly used. 392 | * @return succeeds or not. 393 | */ 394 | removePolicies(rules: string[][]): Promise { 395 | return authzAPI.removePolicies(this.enforcer, rules); 396 | } 397 | /** 398 | * removeFilteredPolicy removes an authorization rule from the current policy, field filters can be specified. 399 | * 400 | * @param fieldIndex the policy rule's start index to be matched. 401 | * @param fieldValues the field values to be matched, value "" 402 | * means not to match this field. 403 | * @return succeeds or not. 404 | */ 405 | removeFilteredPolicy( 406 | fieldIndex: number, 407 | ...fieldValues: string[] 408 | ): Promise { 409 | return authzAPI.removeFilteredPolicy( 410 | this.enforcer, 411 | fieldIndex, 412 | ...fieldValues 413 | ); 414 | } 415 | /** 416 | * removeNamedPolicy removes an authorization rule from the current named policy. 417 | * 418 | * @param ptype the policy type, can be "p", "p2", "p3", .. 419 | * @param params the "p" policy rule. 420 | * @return succeeds or not. 421 | */ 422 | removeNamedPolicy(ptype: string, ...params: string[]): Promise { 423 | return authzAPI.removeNamedPolicy(this.enforcer, ptype, ...params); 424 | } 425 | /** 426 | * removeNamedPolicies removes authorization rules from the current named policy. 427 | * 428 | * @param ptype the policy type, can be "p", "p2", "p3", .. 429 | * @param rules the "p" policy rules. 430 | * @return succeeds or not. 431 | */ 432 | removeNamedPolicies(ptype: string, rules: string[][]): Promise { 433 | return authzAPI.removeNamedPolicies(this.enforcer, ptype, rules); 434 | } 435 | /** 436 | * removeFilteredNamedPolicy removes an authorization rule from the current named policy, field filters can be specified. 437 | * 438 | * @param ptype the policy type, can be "p", "p2", "p3", .. 439 | * @param fieldIndex the policy rule's start index to be matched. 440 | * @param fieldValues the field values to be matched, value "" 441 | * means not to match this field. 442 | * @return succeeds or not. 443 | */ 444 | removeFilteredNamedPolicy( 445 | ptype: string, 446 | fieldIndex: number, 447 | ...fieldValues: string[] 448 | ): Promise { 449 | return authzAPI.removeFilteredNamedPolicy( 450 | this.enforcer, 451 | ptype, 452 | fieldIndex, 453 | ...fieldValues 454 | ); 455 | } 456 | /** 457 | * hasGroupingPolicy determines whether a role inheritance rule exists. 458 | * 459 | * @param params the "g" policy rule, ptype "g" is implicitly used. 460 | * @return whether the rule exists. 461 | */ 462 | hasGroupingPolicy(...params: string[]): Promise { 463 | return authzAPI.hasGroupingPolicy(this.enforcer, ...params); 464 | } 465 | /** 466 | * hasNamedGroupingPolicy determines whether a named role inheritance rule exists. 467 | * 468 | * @param ptype the policy type, can be "g", "g2", "g3", .. 469 | * @param params the "g" policy rule. 470 | * @return whether the rule exists. 471 | */ 472 | hasNamedGroupingPolicy(ptype: string, ...params: string[]): Promise { 473 | return authzAPI.hasNamedGroupingPolicy(this.enforcer, ptype, ...params); 474 | } 475 | /** 476 | * addGroupingPolicy adds a role inheritance rule to the current policy. 477 | * If the rule already exists, the function returns false and the rule will not be added. 478 | * Otherwise the function returns true by adding the new rule. 479 | * 480 | * @param params the "g" policy rule, ptype "g" is implicitly used. 481 | * @return succeeds or not. 482 | */ 483 | addGroupingPolicy(...params: string[]): Promise { 484 | return authzAPI.addGroupingPolicy(this.enforcer, ...params); 485 | } 486 | /** 487 | * addGroupingPolicies adds a role inheritance rules to the current policy. 488 | * If the rule already exists, the function returns false and the rules will not be added. 489 | * Otherwise the function returns true by adding the new rules. 490 | * 491 | * @param rules the "g" policy rules, ptype "g" is implicitly used. 492 | * @return succeeds or not. 493 | */ 494 | addGroupingPolicies(rules: string[][]): Promise { 495 | return authzAPI.addGroupingPolicies(this.enforcer, rules); 496 | } 497 | /** 498 | * addNamedGroupingPolicy adds a named role inheritance rule to the current policy. 499 | * If the rule already exists, the function returns false and the rule will not be added. 500 | * Otherwise the function returns true by adding the new rule. 501 | * 502 | * @param ptype the policy type, can be "g", "g2", "g3", .. 503 | * @param params the "g" policy rule. 504 | * @return succeeds or not. 505 | */ 506 | addNamedGroupingPolicy(ptype: string, ...params: string[]): Promise { 507 | return authzAPI.addNamedGroupingPolicy(this.enforcer, ptype, ...params); 508 | } 509 | /** 510 | * addNamedGroupingPolicies adds named role inheritance rules to the current policy. 511 | * If the rule already exists, the function returns false and the rules will not be added. 512 | * Otherwise the function returns true by adding the new rules. 513 | * 514 | * @param ptype the policy type, can be "g", "g2", "g3", .. 515 | * @param rules the "g" policy rule. 516 | * @return succeeds or not. 517 | */ 518 | addNamedGroupingPolicies(ptype: string, rules: string[][]): Promise { 519 | return authzAPI.addNamedGroupingPolicies(this.enforcer, ptype, rules); 520 | } 521 | /** 522 | * removeGroupingPolicy removes a role inheritance rule from the current policy. 523 | * 524 | * @param params the "g" policy rule, ptype "g" is implicitly used. 525 | * @return succeeds or not. 526 | */ 527 | removeGroupingPolicy(...params: string[]): Promise { 528 | return authzAPI.removeGroupingPolicy(this.enforcer, ...params); 529 | } 530 | /** 531 | * removeGroupingPolicies removes role inheritance rules from the current policy. 532 | * 533 | * @param rules the "g" policy rules, ptype "g" is implicitly used. 534 | * @return succeeds or not. 535 | */ 536 | removeGroupingPolicies(rules: string[][]): Promise { 537 | return authzAPI.removeGroupingPolicies(this.enforcer, rules); 538 | } 539 | /** 540 | * removeFilteredGroupingPolicy removes a role inheritance rule from the current policy, field filters can be specified. 541 | * 542 | * @param fieldIndex the policy rule's start index to be matched. 543 | * @param fieldValues the field values to be matched, value "" 544 | * means not to match this field. 545 | * @return succeeds or not. 546 | */ 547 | removeFilteredGroupingPolicy( 548 | fieldIndex: number, 549 | ...fieldValues: string[] 550 | ): Promise { 551 | return authzAPI.removeFilteredGroupingPolicy( 552 | this.enforcer, 553 | fieldIndex, 554 | ...fieldValues 555 | ); 556 | } 557 | /** 558 | * removeNamedGroupingPolicy removes a role inheritance rule from the current named policy. 559 | * 560 | * @param ptype the policy type, can be "g", "g2", "g3", .. 561 | * @param params the "g" policy rule. 562 | * @return succeeds or not. 563 | */ 564 | removeNamedGroupingPolicy( 565 | ptype: string, 566 | ...params: string[] 567 | ): Promise { 568 | return authzAPI.removeNamedGroupingPolicy(this.enforcer, ptype, ...params); 569 | } 570 | /** 571 | * removeNamedGroupingPolicies removes role inheritance rules from the current named policy. 572 | * 573 | * @param ptype the policy type, can be "g", "g2", "g3", .. 574 | * @param rules the "g" policy rules. 575 | * @return succeeds or not. 576 | */ 577 | removeNamedGroupingPolicies( 578 | ptype: string, 579 | rules: string[][] 580 | ): Promise { 581 | return authzAPI.removeNamedGroupingPolicies(this.enforcer, ptype, rules); 582 | } 583 | /** 584 | * removeFilteredNamedGroupingPolicy removes a role inheritance rule from the current named policy, field filters can be specified. 585 | * 586 | * @param ptype the policy type, can be "g", "g2", "g3", .. 587 | * @param fieldIndex the policy rule's start index to be matched. 588 | * @param fieldValues the field values to be matched, value "" 589 | * means not to match this field. 590 | * @return succeeds or not. 591 | */ 592 | removeFilteredNamedGroupingPolicy( 593 | ptype: string, 594 | fieldIndex: number, 595 | ...fieldValues: string[] 596 | ): Promise { 597 | return authzAPI.removeFilteredNamedGroupingPolicy( 598 | this.enforcer, 599 | ptype, 600 | fieldIndex, 601 | ...fieldValues 602 | ); 603 | } 604 | /** 605 | * addFunction adds a customized function. 606 | * @param name custom function name 607 | * @param func function 608 | */ 609 | addFunction(name: string, func: any): Promise { 610 | return authzAPI.addFunction(this.enforcer, name, func); 611 | } 612 | 613 | /** 614 | * loadPolicy reloads the policy from file/database. 615 | */ 616 | loadPolicy(): Promise { 617 | return authzAPI.loadPolicy(this.enforcer); 618 | } 619 | 620 | /** 621 | * updateGroupingPolicy updates a role inheritance rule from the current policy. 622 | * If the rule not exists, the function returns false. 623 | * Otherwise the function returns true by changing it to the new rule. 624 | * 625 | * @param oldRule the role inheritance rule will be remove 626 | * @param newRule the role inheritance rule will be added 627 | * @return succeeds or not. 628 | */ 629 | updateGroupingPolicy(oldRule: string[], newRule: string[]): Promise { 630 | return authzAPI.updateGroupingPolicy(this.enforcer, oldRule, newRule); 631 | } 632 | 633 | /** 634 | * updateNamedGroupingPolicy updates a named role inheritance rule from the current policy. 635 | * If the rule not exists, the function returns false. 636 | * Otherwise the function returns true by changing it to the new rule. 637 | * 638 | * @param ptype the policy type, can be "g", "g2", "g3", .. 639 | * @param oldRule the role inheritance rule will be remove 640 | * @param newRule the role inheritance rule will be added 641 | * @return succeeds or not. 642 | */ 643 | updateNamedGroupingPolicy( 644 | ptype: string, 645 | oldRule: string[], 646 | newRule: string[] 647 | ): Promise { 648 | return authzAPI.updateNamedGroupingPolicy( 649 | this.enforcer, 650 | ptype, 651 | oldRule, 652 | newRule 653 | ); 654 | } 655 | } 656 | -------------------------------------------------------------------------------- /src/services/authz.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Inject } from '@nestjs/common'; 2 | import { AUTHZ_ENFORCER } from '../authz.constants'; 3 | import * as casbin from 'casbin'; 4 | import * as authzAPI from './authz-api'; 5 | 6 | /** 7 | * A wrapper of casbin RBAC API. 8 | * All methods are transformed to async in terms of possible IO operations 9 | * in the future. 10 | */ 11 | @Injectable() 12 | export class AuthZService { 13 | constructor( 14 | @Inject(AUTHZ_ENFORCER) 15 | public readonly enforcer: casbin.Enforcer 16 | ) {} 17 | 18 | /** 19 | * RBAC API 20 | */ 21 | 22 | /** 23 | * Gets the roles that a user has. 24 | * 25 | * @param {string} name username 26 | * @param {string} [domain] domain name 27 | * @returns {Promise} roles owned by the user 28 | * @memberof AuthZService 29 | */ 30 | getRolesForUser(name: string, domain?: string): Promise { 31 | return authzAPI.getRolesForUser(this.enforcer, name, domain); 32 | } 33 | 34 | /** 35 | * Gets the users that has a role. 36 | * 37 | * @param {string} name username 38 | * @param {string} [domain] domain name 39 | * @returns {Promise} users that has a role 40 | * @memberof AuthZService 41 | */ 42 | getUsersForRole(name: string, domain?: string): Promise { 43 | return authzAPI.getUsersForRole(this.enforcer, name, domain); 44 | } 45 | 46 | /** 47 | * Determines whether a user has a role. 48 | * 49 | * @param {string} name username 50 | * @param {string} role role name 51 | * @param {string} [domain] domain name 52 | * @returns {Promise} 53 | * @memberof AuthZService 54 | */ 55 | hasRoleForUser( 56 | name: string, 57 | role: string, 58 | domain?: string 59 | ): Promise { 60 | return authzAPI.hasRoleForUser(this.enforcer, name, role, domain); 61 | } 62 | 63 | /** 64 | * Adds a role for a user. 65 | * Returns false if the user already has the role (aka not affected). 66 | * 67 | * @param {string} user username 68 | * @param {string} role role name 69 | * @param {string} [domain] domain name 70 | * @returns {Promise} 71 | * @memberof AuthZService 72 | */ 73 | addRoleForUser( 74 | user: string, 75 | role: string, 76 | domain?: string 77 | ): Promise { 78 | return authzAPI.addRoleForUser(this.enforcer, user, role, domain); 79 | } 80 | 81 | /** 82 | * deletes a role for a user. 83 | * Returns false if the user does not have the role (aka not affected). 84 | * 85 | * @param {string} user username 86 | * @param {string} role role name 87 | * @param {string} [domain] domain name 88 | * @returns {Promise} 89 | * @memberof AuthZService 90 | */ 91 | deleteRoleForUser( 92 | user: string, 93 | role: string, 94 | domain?: string 95 | ): Promise { 96 | return authzAPI.deleteRoleForUser(this.enforcer, user, role, domain); 97 | } 98 | 99 | /** 100 | * Deletes all roles for a user. 101 | * Returns false if the user does not have any roles (aka not affected). 102 | * 103 | * @param {string} user username 104 | * @returns {Promise} 105 | * @memberof AuthZService 106 | */ 107 | deleteRolesForUser(user: string, domain?: string): Promise { 108 | return authzAPI.deleteRolesForUser(this.enforcer, user, domain); 109 | } 110 | 111 | /** 112 | * Deletes a user. 113 | * Returns false if the user does not exist (aka not affected). 114 | * 115 | * @param {string} user username 116 | * @returns {Promise} 117 | * @memberof AuthZService 118 | */ 119 | async deleteUser(user: string): Promise { 120 | return authzAPI.deleteUser(this.enforcer, user); 121 | } 122 | 123 | /** 124 | * Deletes a role 125 | * 126 | * @param {string} role role name 127 | * @returns {Promise} 128 | * @memberof AuthZService 129 | */ 130 | deleteRole(role: string): Promise { 131 | return authzAPI.deleteRole(this.enforcer, role); 132 | } 133 | 134 | /** 135 | * Deletes a permission. 136 | * Returns false if the permission does not exist (aka not affected). 137 | * 138 | * @param {...string[]} permission permission per casbin model definition 139 | * @returns {Promise} 140 | * @memberof AuthZService 141 | */ 142 | deletePermission(...permission: string[]): Promise { 143 | return authzAPI.deletePermission(this.enforcer, ...permission); 144 | } 145 | 146 | /** 147 | * Adds a permission for a user or role. 148 | * Returns false if the user or role already has the permission (aka not affected). 149 | * 150 | * @param {string} userOrRole username or role name 151 | * @param {...string[]} permission permission per casbin model definition 152 | * @returns {Promise} 153 | * @memberof AuthZService 154 | */ 155 | addPermissionForUser( 156 | userOrRole: string, 157 | ...permission: string[] 158 | ): Promise { 159 | return authzAPI.addPermissionForUser( 160 | this.enforcer, 161 | userOrRole, 162 | ...permission 163 | ); 164 | } 165 | 166 | /** 167 | * Deletes a permission for a user or role. 168 | * Returns false if the user or role does not have the permission (aka not affected). 169 | * 170 | * @param {string} userOrRole username or role name 171 | * @param {...string[]} permission permission per casbin model definition 172 | * @returns {Promise} 173 | * @memberof AuthZService 174 | */ 175 | deletePermissionForUser( 176 | userOrRole: string, 177 | ...permission: string[] 178 | ): Promise { 179 | return authzAPI.deletePermissionForUser( 180 | this.enforcer, 181 | userOrRole, 182 | ...permission 183 | ); 184 | } 185 | 186 | /** 187 | * Deletes permissions for a user or role. 188 | * Returns false if the user or role does not have any permissions (aka not affected). 189 | * 190 | * @param {string} userOrRole username or role name 191 | * @returns {Promise} 192 | * @memberof AuthZService 193 | */ 194 | deletePermissionsForUser(userOrRole: string): Promise { 195 | return authzAPI.deletePermissionsForUser(this.enforcer, userOrRole); 196 | } 197 | 198 | /** 199 | * Gets permissions for a user or role. 200 | * 201 | * @param {string} userOrRole username or role name 202 | * @returns {Promise} 203 | * @memberof AuthZService 204 | */ 205 | getPermissionsForUser(userOrRole: string): Promise { 206 | return authzAPI.getPermissionsForUser(this.enforcer, userOrRole); 207 | } 208 | 209 | /** 210 | * Determines whether a user has a permission. 211 | * 212 | * @param {string} user username 213 | * @param {...string[]} permission permission per casbin model definition 214 | * @returns {Promise} 215 | * @memberof AuthZService 216 | */ 217 | hasPermissionForUser( 218 | user: string, 219 | ...permission: string[] 220 | ): Promise { 221 | return authzAPI.hasPermissionForUser(this.enforcer, user, ...permission); 222 | } 223 | 224 | /** 225 | * Gets implicit roles that a user has. 226 | * Compared to getRolesForUser(), this function retrieves indirect roles besides direct roles.\ 227 | * 228 | * For example: 229 | * 230 | * g, alice, role:admin\ 231 | * g, role:admin, role:user 232 | * 233 | * 234 | * getRolesForUser("alice") can only get: ["role:admin"]. 235 | * But getImplicitRolesForUser("alice") will get: ["role:admin", "role:user"]. 236 | * 237 | * @param {string} name username 238 | * @param {...string[]} domain domains 239 | * @returns {Promise} 240 | * @memberof AuthZService 241 | */ 242 | getImplicitRolesForUser( 243 | name: string, 244 | ...domain: string[] 245 | ): Promise { 246 | return authzAPI.getImplicitRolesForUser(this.enforcer, name, ...domain); 247 | } 248 | 249 | /** 250 | * Gets implicit resources that a user has access to. 251 | * 252 | * For example: 253 | * 254 | * g, alice, role:admin 255 | * p, alice, resource1, read 256 | * p, role:admin, resource1, write 257 | * 258 | * 259 | * getImplicitResourcesForUser("alice") will return: [["alice", "resource1", "read"], ["role:admin", "resource1", "write"]]. 260 | * 261 | * @param {string} name username 262 | * @param {...string[]} domain domains 263 | * @returns {Promise} 264 | * @memberof AuthZService 265 | */ 266 | getImplicitResourcesForUser( 267 | name: string, 268 | ...domain: string[] 269 | ): Promise { 270 | return authzAPI.getImplicitResourcesForUser(this.enforcer, name, ...domain); 271 | } 272 | 273 | /** 274 | * Gets implicit permissions for a user or role. 275 | * Compared to getPermissionsForUser(), this function retrieves permissions for inherited roles.\ 276 | * 277 | * For example: 278 | * p, admin, data1, read 279 | * p, alice, data2, read 280 | * g, alice, admin 281 | * 282 | * getPermissionsForUser("alice") can only get: [["alice", "data2", "read"]].\ 283 | * But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]]. 284 | * 285 | * @param {string} user username 286 | * @returns {Promise} 287 | * @memberof AuthZService 288 | */ 289 | getImplicitPermissionsForUser( 290 | user: string, 291 | ...domain: string[] 292 | ): Promise { 293 | return authzAPI.getImplicitPermissionsForUser( 294 | this.enforcer, 295 | user, 296 | ...domain 297 | ); 298 | } 299 | /** 300 | * getImplicitUsersForPermission gets implicit users for a permission. 301 | * For example: 302 | * p, admin, data1, read 303 | * p, bob, data1, read 304 | * g, alice, admin 305 | * 306 | * getImplicitUsersForPermission("data1", "read") will get: ["alice", "bob"]. 307 | * Note: only users will be returned, roles (2nd arg in "g") will be excluded. 308 | */ 309 | getImplicitUsersForPermission(...permission: string[]): Promise { 310 | return authzAPI.getImplicitUsersForPermission(this.enforcer, ...permission); 311 | } 312 | 313 | /** 314 | * Management API 315 | */ 316 | 317 | /** 318 | * enforce decides whether a "subject" can access a "object" with the operation "action" 319 | * 320 | * @param params the request parameters, usually (sub, obj, act) 321 | * 322 | * @return whether or not the request is allowed 323 | */ 324 | enforce(...params: any[]): Promise { 325 | return authzAPI.enforce(this.enforcer, ...params); 326 | } 327 | 328 | /** 329 | * enforceWithMatcher uses a custom matcher to decides whether a "subject" can access a "object" with the operation "action" 330 | * 331 | * @param matcher the matcher statement to use 332 | * @param params the request parameters, usually (sub, obj, act) 333 | * 334 | * @return whether or not the request is allowed 335 | */ 336 | enforceWithMatcher(matcher: string, ...params: any[]): Promise { 337 | return authzAPI.enforceWithMatcher(this.enforcer, matcher, ...params); 338 | } 339 | 340 | /** 341 | * enforceEx explains enforcement by returning matched rules. 342 | * 343 | * @param params the request parameters, usually (sub, obj, act) 344 | * 345 | * @return whether or not the request is allowed, and what policy caused that decision 346 | */ 347 | enforceEx(...params: any[]): Promise<[boolean, string[]]> { 348 | return authzAPI.enforceEx(this.enforcer, ...params); 349 | } 350 | 351 | /** 352 | * enforceExWithMatcher uses a custom matcher and explains enforcement by returning matched rules. 353 | * 354 | * @param matcher the matcher statement to use 355 | * @param params the request parameters, usually (sub, obj, act) 356 | * 357 | * @return whether or not the request is allowed, and what policy caused that decision 358 | */ 359 | enforceExWithMatcher( 360 | matcher: string, 361 | ...params: any[] 362 | ): Promise<[boolean, string[]]> { 363 | return authzAPI.enforceExWithMatcher(this.enforcer, matcher, ...params); 364 | } 365 | 366 | /** 367 | * batchEnforce enforces each request and returns result in a bool array 368 | * 369 | * @param params the request parameters, usually (sub, obj, act) 370 | * 371 | * @return an array with the enforcement results for each given request 372 | */ 373 | batchEnforce(params: any[][]): Promise { 374 | return authzAPI.batchEnforce(this.enforcer, params); 375 | } 376 | 377 | /** 378 | * getAllSubjects gets the list of subjects that show up in the current policy. 379 | * 380 | * @return all the subjects in "p" policy rules. It actually collects the 381 | * 0-index elements of "p" policy rules. So make sure your subject 382 | * is the 0-index element, like (sub, obj, act). Duplicates are removed. 383 | */ 384 | getAllSubjects(): Promise { 385 | return authzAPI.getAllSubjects(this.enforcer); 386 | } 387 | /** 388 | * getAllNamedSubjects gets the list of subjects that show up in the currentnamed policy. 389 | * 390 | * @param ptype the policy type, can be "p", "p2", "p3", .. 391 | * @return all the subjects in policy rules of the ptype type. It actually 392 | * collects the 0-index elements of the policy rules. So make sure 393 | * your subject is the 0-index element, like (sub, obj, act). 394 | * Duplicates are removed. 395 | */ 396 | getAllNamedSubjects(ptype: string): Promise { 397 | return authzAPI.getAllNamedSubjects(this.enforcer, ptype); 398 | } 399 | /** 400 | * getAllObjects gets the list of objects that show up in the current policy. 401 | * 402 | * @return all the objects in "p" policy rules. It actually collects the 403 | * 1-index elements of "p" policy rules. So make sure your object 404 | * is the 1-index element, like (sub, obj, act). 405 | * Duplicates are removed. 406 | */ 407 | getAllObjects(): Promise { 408 | return authzAPI.getAllObjects(this.enforcer); 409 | } 410 | /** 411 | * getAllNamedObjects gets the list of objects that show up in the current named policy. 412 | * 413 | * @param ptype the policy type, can be "p", "p2", "p3", .. 414 | * @return all the objects in policy rules of the ptype type. It actually 415 | * collects the 1-index elements of the policy rules. So make sure 416 | * your object is the 1-index element, like (sub, obj, act). 417 | * Duplicates are removed. 418 | */ 419 | getAllNamedObjects(ptype: string): Promise { 420 | return authzAPI.getAllNamedObjects(this.enforcer, ptype); 421 | } 422 | /** 423 | * getAllActions gets the list of actions that show up in the current policy. 424 | * 425 | * @return all the actions in "p" policy rules. It actually collects 426 | * the 2-index elements of "p" policy rules. So make sure your action 427 | * is the 2-index element, like (sub, obj, act). 428 | * Duplicates are removed. 429 | */ 430 | getAllActions(): Promise { 431 | return authzAPI.getAllActions(this.enforcer); 432 | } 433 | /** 434 | * GetAllNamedActions gets the list of actions that show up in the current named policy. 435 | * 436 | * @param ptype the policy type, can be "p", "p2", "p3", .. 437 | * @return all the actions in policy rules of the ptype type. It actually 438 | * collects the 2-index elements of the policy rules. So make sure 439 | * your action is the 2-index element, like (sub, obj, act). 440 | * Duplicates are removed. 441 | */ 442 | getAllNamedActions(ptype: string): Promise { 443 | return authzAPI.getAllNamedActions(this.enforcer, ptype); 444 | } 445 | /** 446 | * getAllRoles gets the list of roles that show up in the current policy. 447 | * 448 | * @return all the roles in "g" policy rules. It actually collects 449 | * the 1-index elements of "g" policy rules. So make sure your 450 | * role is the 1-index element, like (sub, role). 451 | * Duplicates are removed. 452 | */ 453 | getAllRoles(): Promise { 454 | return authzAPI.getAllRoles(this.enforcer); 455 | } 456 | /** 457 | * getAllNamedRoles gets the list of roles that show up in the current named policy. 458 | * 459 | * @param ptype the policy type, can be "g", "g2", "g3", .. 460 | * @return all the subjects in policy rules of the ptype type. It actually 461 | * collects the 0-index elements of the policy rules. So make 462 | * sure your subject is the 0-index element, like (sub, obj, act). 463 | * Duplicates are removed. 464 | */ 465 | getAllNamedRoles(ptype: string): Promise { 466 | return authzAPI.getAllNamedRoles(this.enforcer, ptype); 467 | } 468 | /** 469 | * getPolicy gets all the authorization rules in the policy. 470 | * 471 | * @return all the "p" policy rules. 472 | */ 473 | getPolicy(): Promise { 474 | return authzAPI.getPolicy(this.enforcer); 475 | } 476 | /** 477 | * getFilteredPolicy gets all the authorization rules in the policy, field filters can be specified. 478 | * 479 | * @param fieldIndex the policy rule's start index to be matched. 480 | * @param fieldValues the field values to be matched, value "" 481 | * means not to match this field. 482 | * @return the filtered "p" policy rules. 483 | */ 484 | getFilteredPolicy( 485 | fieldIndex: number, 486 | ...fieldValues: string[] 487 | ): Promise { 488 | return authzAPI.getFilteredPolicy( 489 | this.enforcer, 490 | fieldIndex, 491 | ...fieldValues 492 | ); 493 | } 494 | /** 495 | * getNamedPolicy gets all the authorization rules in the named policy. 496 | * 497 | * @param ptype the policy type, can be "p", "p2", "p3", .. 498 | * @return the "p" policy rules of the specified ptype. 499 | */ 500 | getNamedPolicy(ptype: string): Promise { 501 | return authzAPI.getNamedPolicy(this.enforcer, ptype); 502 | } 503 | /** 504 | * getFilteredNamedPolicy gets all the authorization rules in the named policy, field filters can be specified. 505 | * 506 | * @param ptype the policy type, can be "p", "p2", "p3", .. 507 | * @param fieldIndex the policy rule's start index to be matched. 508 | * @param fieldValues the field values to be matched, value "" 509 | * means not to match this field. 510 | * @return the filtered "p" policy rules of the specified ptype. 511 | */ 512 | getFilteredNamedPolicy( 513 | ptype: string, 514 | fieldIndex: number, 515 | ...fieldValues: string[] 516 | ): Promise { 517 | return authzAPI.getFilteredNamedPolicy( 518 | this.enforcer, 519 | ptype, 520 | fieldIndex, 521 | ...fieldValues 522 | ); 523 | } 524 | /** 525 | * getGroupingPolicy gets all the role inheritance rules in the policy. 526 | * 527 | * @return all the "g" policy rules. 528 | */ 529 | getGroupingPolicy(): Promise { 530 | return authzAPI.getGroupingPolicy(this.enforcer); 531 | } 532 | /** 533 | * getFilteredGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified. 534 | * 535 | * @param fieldIndex the policy rule's start index to be matched. 536 | * @param fieldValues the field values to be matched, value "" means not to match this field. 537 | * @return the filtered "g" policy rules. 538 | */ 539 | getFilteredGroupingPolicy( 540 | fieldIndex: number, 541 | ...fieldValues: string[] 542 | ): Promise { 543 | return authzAPI.getFilteredGroupingPolicy( 544 | this.enforcer, 545 | fieldIndex, 546 | ...fieldValues 547 | ); 548 | } 549 | /** 550 | * getNamedGroupingPolicy gets all the role inheritance rules in the policy. 551 | * 552 | * @param ptype the policy type, can be "g", "g2", "g3", .. 553 | * @return the "g" policy rules of the specified ptype. 554 | */ 555 | getNamedGroupingPolicy(ptype: string): Promise { 556 | return authzAPI.getNamedGroupingPolicy(this.enforcer, ptype); 557 | } 558 | /** 559 | * getFilteredNamedGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified. 560 | * 561 | * @param ptype the policy type, can be "g", "g2", "g3", .. 562 | * @param fieldIndex the policy rule's start index to be matched. 563 | * @param fieldValues the field values to be matched, value "" 564 | * means not to match this field. 565 | * @return the filtered "g" policy rules of the specified ptype. 566 | */ 567 | getFilteredNamedGroupingPolicy( 568 | ptype: string, 569 | fieldIndex: number, 570 | ...fieldValues: string[] 571 | ): Promise { 572 | return authzAPI.getFilteredNamedGroupingPolicy( 573 | this.enforcer, 574 | ptype, 575 | fieldIndex, 576 | ...fieldValues 577 | ); 578 | } 579 | /** 580 | * hasPolicy determines whether an authorization rule exists. 581 | * 582 | * @param params the "p" policy rule, ptype "p" is implicitly used. 583 | * @return whether the rule exists. 584 | */ 585 | hasPolicy(...params: string[]): Promise { 586 | return authzAPI.hasPolicy(this.enforcer, ...params); 587 | } 588 | /** 589 | * hasNamedPolicy determines whether a named authorization rule exists. 590 | * 591 | * @param ptype the policy type, can be "p", "p2", "p3", .. 592 | * @param params the "p" policy rule. 593 | * @return whether the rule exists. 594 | */ 595 | hasNamedPolicy(ptype: string, ...params: string[]): Promise { 596 | return authzAPI.hasNamedPolicy(this.enforcer, ptype, ...params); 597 | } 598 | /** 599 | * addPolicy adds an authorization rule to the current policy. 600 | * If the rule already exists, the function returns false and the rule will not be added. 601 | * Otherwise the function returns true by adding the new rule. 602 | * 603 | * @param params the "p" policy rule, ptype "p" is implicitly used. 604 | * @return succeeds or not. 605 | */ 606 | addPolicy(...params: string[]): Promise { 607 | return authzAPI.addPolicy(this.enforcer, ...params); 608 | } 609 | 610 | /** 611 | * addPolicies adds authorization rules to the current policy. 612 | * If the rule already exists, the function returns false and the rules will not be added. 613 | * Otherwise the function returns true by adding the new rules. 614 | * 615 | * @param rules the "p" policy rules, ptype "p" is implicitly used. 616 | * @return succeeds or not. 617 | */ 618 | addPolicies(rules: string[][]): Promise { 619 | return authzAPI.addPolicies(this.enforcer, rules); 620 | } 621 | 622 | /** 623 | * addNamedPolicy adds an authorization rule to the current named policy. 624 | * If the rule already exists, the function returns false and the rule will not be added. 625 | * Otherwise the function returns true by adding the new rule. 626 | * 627 | * @param ptype the policy type, can be "p", "p2", "p3", .. 628 | * @param params the "p" policy rule. 629 | * @return succeeds or not. 630 | */ 631 | addNamedPolicy(ptype: string, ...params: string[]): Promise { 632 | return authzAPI.addNamedPolicy(this.enforcer, ptype, ...params); 633 | } 634 | 635 | /** 636 | * addNamedPolicies adds authorization rules to the current named policy. 637 | * If the rule already exists, the function returns false and the rules will not be added. 638 | * Otherwise the function returns true by adding the new rules. 639 | * 640 | * @param ptype the policy type, can be "p", "p2", "p3", .. 641 | * @param rules the "p" policy rules. 642 | * @return succeeds or not. 643 | */ 644 | addNamedPolicies(ptype: string, rules: string[][]): Promise { 645 | return authzAPI.addNamedPolicies(this.enforcer, ptype, rules); 646 | } 647 | 648 | /** 649 | * updatePolicy updates an authorization rule from the current policy. 650 | * If the rule not exists, the function returns false. 651 | * Otherwise the function returns true by changing it to the new rule. 652 | * 653 | * @return succeeds or not. 654 | * @param oldRule the policy will be remove 655 | * @param newRule the policy will be added 656 | */ 657 | updatePolicy(oldRule: string[], newRule: string[]): Promise { 658 | return authzAPI.updatePolicy(this.enforcer, oldRule, newRule); 659 | } 660 | 661 | /** 662 | * updateNamedPolicy updates an authorization rule from the current named policy. 663 | * If the rule not exists, the function returns false. 664 | * Otherwise the function returns true by changing it to the new rule. 665 | * 666 | * @param ptype the policy type, can be "p", "p2", "p3", .. 667 | * @param oldRule the policy rule will be remove 668 | * @param newRule the policy rule will be added 669 | * @return succeeds or not. 670 | */ 671 | updateNamedPolicy( 672 | ptype: string, 673 | oldRule: string[], 674 | newRule: string[] 675 | ): Promise { 676 | return authzAPI.updateNamedPolicy(this.enforcer, ptype, oldRule, newRule); 677 | } 678 | 679 | /** 680 | * removePolicy removes an authorization rule from the current policy. 681 | * 682 | * @param params the "p" policy rule, ptype "p" is implicitly used. 683 | * @return succeeds or not. 684 | */ 685 | removePolicy(...params: string[]): Promise { 686 | return authzAPI.removePolicy(this.enforcer, ...params); 687 | } 688 | /** 689 | * removePolicies removes an authorization rules from the current policy. 690 | * 691 | * @param rules the "p" policy rules, ptype "p" is implicitly used. 692 | * @return succeeds or not. 693 | */ 694 | removePolicies(rules: string[][]): Promise { 695 | return authzAPI.removePolicies(this.enforcer, rules); 696 | } 697 | /** 698 | * removeFilteredPolicy removes an authorization rule from the current policy, field filters can be specified. 699 | * 700 | * @param fieldIndex the policy rule's start index to be matched. 701 | * @param fieldValues the field values to be matched, value "" 702 | * means not to match this field. 703 | * @return succeeds or not. 704 | */ 705 | removeFilteredPolicy( 706 | fieldIndex: number, 707 | ...fieldValues: string[] 708 | ): Promise { 709 | return authzAPI.removeFilteredPolicy( 710 | this.enforcer, 711 | fieldIndex, 712 | ...fieldValues 713 | ); 714 | } 715 | /** 716 | * removeNamedPolicy removes an authorization rule from the current named policy. 717 | * 718 | * @param ptype the policy type, can be "p", "p2", "p3", .. 719 | * @param params the "p" policy rule. 720 | * @return succeeds or not. 721 | */ 722 | removeNamedPolicy(ptype: string, ...params: string[]): Promise { 723 | return authzAPI.removeNamedPolicy(this.enforcer, ptype, ...params); 724 | } 725 | /** 726 | * removeNamedPolicies removes authorization rules from the current named policy. 727 | * 728 | * @param ptype the policy type, can be "p", "p2", "p3", .. 729 | * @param rules the "p" policy rules. 730 | * @return succeeds or not. 731 | */ 732 | removeNamedPolicies(ptype: string, rules: string[][]): Promise { 733 | return authzAPI.removeNamedPolicies(this.enforcer, ptype, rules); 734 | } 735 | /** 736 | * removeFilteredNamedPolicy removes an authorization rule from the current named policy, field filters can be specified. 737 | * 738 | * @param ptype the policy type, can be "p", "p2", "p3", .. 739 | * @param fieldIndex the policy rule's start index to be matched. 740 | * @param fieldValues the field values to be matched, value "" 741 | * means not to match this field. 742 | * @return succeeds or not. 743 | */ 744 | removeFilteredNamedPolicy( 745 | ptype: string, 746 | fieldIndex: number, 747 | ...fieldValues: string[] 748 | ): Promise { 749 | return authzAPI.removeFilteredNamedPolicy( 750 | this.enforcer, 751 | ptype, 752 | fieldIndex, 753 | ...fieldValues 754 | ); 755 | } 756 | /** 757 | * hasGroupingPolicy determines whether a role inheritance rule exists. 758 | * 759 | * @param params the "g" policy rule, ptype "g" is implicitly used. 760 | * @return whether the rule exists. 761 | */ 762 | hasGroupingPolicy(...params: string[]): Promise { 763 | return authzAPI.hasGroupingPolicy(this.enforcer, ...params); 764 | } 765 | /** 766 | * hasNamedGroupingPolicy determines whether a named role inheritance rule exists. 767 | * 768 | * @param ptype the policy type, can be "g", "g2", "g3", .. 769 | * @param params the "g" policy rule. 770 | * @return whether the rule exists. 771 | */ 772 | hasNamedGroupingPolicy(ptype: string, ...params: string[]): Promise { 773 | return authzAPI.hasNamedGroupingPolicy(this.enforcer, ptype, ...params); 774 | } 775 | /** 776 | * addGroupingPolicy adds a role inheritance rule to the current policy. 777 | * If the rule already exists, the function returns false and the rule will not be added. 778 | * Otherwise the function returns true by adding the new rule. 779 | * 780 | * @param params the "g" policy rule, ptype "g" is implicitly used. 781 | * @return succeeds or not. 782 | */ 783 | addGroupingPolicy(...params: string[]): Promise { 784 | return authzAPI.addGroupingPolicy(this.enforcer, ...params); 785 | } 786 | /** 787 | * addGroupingPolicies adds a role inheritance rules to the current policy. 788 | * If the rule already exists, the function returns false and the rules will not be added. 789 | * Otherwise the function returns true by adding the new rules. 790 | * 791 | * @param rules the "g" policy rules, ptype "g" is implicitly used. 792 | * @return succeeds or not. 793 | */ 794 | addGroupingPolicies(rules: string[][]): Promise { 795 | return authzAPI.addGroupingPolicies(this.enforcer, rules); 796 | } 797 | /** 798 | * addNamedGroupingPolicy adds a named role inheritance rule to the current policy. 799 | * If the rule already exists, the function returns false and the rule will not be added. 800 | * Otherwise the function returns true by adding the new rule. 801 | * 802 | * @param ptype the policy type, can be "g", "g2", "g3", .. 803 | * @param params the "g" policy rule. 804 | * @return succeeds or not. 805 | */ 806 | addNamedGroupingPolicy(ptype: string, ...params: string[]): Promise { 807 | return authzAPI.addNamedGroupingPolicy(this.enforcer, ptype, ...params); 808 | } 809 | /** 810 | * addNamedGroupingPolicies adds named role inheritance rules to the current policy. 811 | * If the rule already exists, the function returns false and the rules will not be added. 812 | * Otherwise the function returns true by adding the new rules. 813 | * 814 | * @param ptype the policy type, can be "g", "g2", "g3", .. 815 | * @param rules the "g" policy rule. 816 | * @return succeeds or not. 817 | */ 818 | addNamedGroupingPolicies(ptype: string, rules: string[][]): Promise { 819 | return authzAPI.addNamedGroupingPolicies(this.enforcer, ptype, rules); 820 | } 821 | /** 822 | * removeGroupingPolicy removes a role inheritance rule from the current policy. 823 | * 824 | * @param params the "g" policy rule, ptype "g" is implicitly used. 825 | * @return succeeds or not. 826 | */ 827 | removeGroupingPolicy(...params: string[]): Promise { 828 | return authzAPI.removeGroupingPolicy(this.enforcer, ...params); 829 | } 830 | /** 831 | * removeGroupingPolicies removes role inheritance rules from the current policy. 832 | * 833 | * @param rules the "g" policy rules, ptype "g" is implicitly used. 834 | * @return succeeds or not. 835 | */ 836 | removeGroupingPolicies(rules: string[][]): Promise { 837 | return authzAPI.removeGroupingPolicies(this.enforcer, rules); 838 | } 839 | /** 840 | * removeFilteredGroupingPolicy removes a role inheritance rule from the current policy, field filters can be specified. 841 | * 842 | * @param fieldIndex the policy rule's start index to be matched. 843 | * @param fieldValues the field values to be matched, value "" 844 | * means not to match this field. 845 | * @return succeeds or not. 846 | */ 847 | removeFilteredGroupingPolicy( 848 | fieldIndex: number, 849 | ...fieldValues: string[] 850 | ): Promise { 851 | return authzAPI.removeFilteredGroupingPolicy( 852 | this.enforcer, 853 | fieldIndex, 854 | ...fieldValues 855 | ); 856 | } 857 | /** 858 | * removeNamedGroupingPolicy removes a role inheritance rule from the current named policy. 859 | * 860 | * @param ptype the policy type, can be "g", "g2", "g3", .. 861 | * @param params the "g" policy rule. 862 | * @return succeeds or not. 863 | */ 864 | removeNamedGroupingPolicy( 865 | ptype: string, 866 | ...params: string[] 867 | ): Promise { 868 | return authzAPI.removeNamedGroupingPolicy(this.enforcer, ptype, ...params); 869 | } 870 | /** 871 | * removeNamedGroupingPolicies removes role inheritance rules from the current named policy. 872 | * 873 | * @param ptype the policy type, can be "g", "g2", "g3", .. 874 | * @param rules the "g" policy rules. 875 | * @return succeeds or not. 876 | */ 877 | removeNamedGroupingPolicies( 878 | ptype: string, 879 | rules: string[][] 880 | ): Promise { 881 | return authzAPI.removeNamedGroupingPolicies(this.enforcer, ptype, rules); 882 | } 883 | /** 884 | * removeFilteredNamedGroupingPolicy removes a role inheritance rule from the current named policy, field filters can be specified. 885 | * 886 | * @param ptype the policy type, can be "g", "g2", "g3", .. 887 | * @param fieldIndex the policy rule's start index to be matched. 888 | * @param fieldValues the field values to be matched, value "" 889 | * means not to match this field. 890 | * @return succeeds or not. 891 | */ 892 | removeFilteredNamedGroupingPolicy( 893 | ptype: string, 894 | fieldIndex: number, 895 | ...fieldValues: string[] 896 | ): Promise { 897 | return authzAPI.removeFilteredNamedGroupingPolicy( 898 | this.enforcer, 899 | ptype, 900 | fieldIndex, 901 | ...fieldValues 902 | ); 903 | } 904 | /** 905 | * addFunction adds a customized function. 906 | * @param name custom function name 907 | * @param func function 908 | */ 909 | addFunction(name: string, func: any): Promise { 910 | return authzAPI.addFunction(this.enforcer, name, func); 911 | } 912 | 913 | /** 914 | * loadPolicy reloads the policy from file/database. 915 | */ 916 | loadPolicy(): Promise { 917 | return authzAPI.loadPolicy(this.enforcer); 918 | } 919 | 920 | /** 921 | * updateGroupingPolicy updates a role inheritance rule from the current policy. 922 | * If the rule not exists, the function returns false. 923 | * Otherwise the function returns true by changing it to the new rule. 924 | * 925 | * @param oldRule the role inheritance rule will be remove 926 | * @param newRule the role inheritance rule will be added 927 | * @return succeeds or not. 928 | */ 929 | updateGroupingPolicy(oldRule: string[], newRule: string[]): Promise { 930 | return authzAPI.updateGroupingPolicy(this.enforcer, oldRule, newRule); 931 | } 932 | 933 | /** 934 | * updateNamedGroupingPolicy updates a named role inheritance rule from the current policy. 935 | * If the rule not exists, the function returns false. 936 | * Otherwise the function returns true by changing it to the new rule. 937 | * 938 | * @param ptype the policy type, can be "g", "g2", "g3", .. 939 | * @param oldRule the role inheritance rule will be remove 940 | * @param newRule the role inheritance rule will be added 941 | * @return succeeds or not. 942 | */ 943 | updateNamedGroupingPolicy( 944 | ptype: string, 945 | oldRule: string[], 946 | newRule: string[] 947 | ): Promise { 948 | return authzAPI.updateNamedGroupingPolicy( 949 | this.enforcer, 950 | ptype, 951 | oldRule, 952 | newRule 953 | ); 954 | } 955 | } 956 | --------------------------------------------------------------------------------