Giter Site home page Giter Site logo

casbin / node-casbin Goto Github PK

View Code? Open in Web Editor NEW
2.5K 20.0 210.0 2.96 MB

An authorization library that supports access control models like ACL, RBAC, ABAC in Node.js and Browser

Home Page: https://casbin.org

License: Apache License 2.0

TypeScript 99.91% JavaScript 0.09%
casbin nodejs node js javascript access-control authorization rbac abac acl

node-casbin's Introduction

Node-Casbin

NPM version NPM download install size codebeat badge GitHub Actions Coverage Status Release Discord

Sponsored by

Build auth with fraud prevention, faster.
Try Stytch for API-first authentication, user & org management, multi-tenant SSO, MFA, device fingerprinting, and more.

💖 Looking for an open-source identity and access management solution like Okta, Auth0, Keycloak ? Learn more about: Casdoor

casdoor

News: still worry about how to write the correct node-casbin policy? Casbin online editor is coming to help!

casbin Logo

node-casbin is a powerful and efficient open-source access control library for Node.JS projects. It provides support for enforcing authorization based on various access control models.

All the languages supported by Casbin:

golang java nodejs php
Casbin jCasbin node-Casbin PHP-Casbin
production-ready production-ready production-ready production-ready
python dotnet c++ rust
PyCasbin Casbin.NET Casbin-CPP Casbin-RS
production-ready production-ready beta-test production-ready

Documentation

https://casbin.org/docs/overview

Installation

# NPM
npm install casbin --save

# Yarn
yarn add casbin

Get started

New a node-casbin enforcer with a model file and a policy file, see Model section for details:

// For Node.js:
const { newEnforcer } = require('casbin');
// For browser:
// import { newEnforcer } from 'casbin';

const enforcer = await newEnforcer('basic_model.conf', 'basic_policy.csv');

Note: you can also initialize an enforcer with policy in DB instead of file, see Persistence section for details.

Add an enforcement hook into your code right before the access happens:

const sub = 'alice'; // the user that wants to access a resource.
const obj = 'data1'; // the resource that is going to be accessed.
const act = 'read'; // the operation that the user performs on the resource.

// Async:
const res = await enforcer.enforce(sub, obj, act);
// Sync:
// const res = enforcer.enforceSync(sub, obj, act);

if (res) {
  // permit alice to read data1
} else {
  // deny the request, show an error
}

Besides the static policy file, node-casbin also provides API for permission management at run-time. For example, You can get all the roles assigned to a user as below:

const roles = await enforcer.getRolesForUser('alice');

See Policy management APIs for more usage.

Policy management

Casbin provides two sets of APIs to manage permissions:

  • Management API: the primitive API that provides full support for Casbin policy management.
  • RBAC API: a more friendly API for RBAC. This API is a subset of Management API. The RBAC users could use this API to simplify the code.

Official Model

https://casbin.org/docs/supported-models

Policy persistence

https://casbin.org/docs/adapters

Policy consistence between multiple nodes

https://casbin.org/docs/watchers

Role manager

https://casbin.org/docs/role-managers

Contributors

This project exists thanks to all the people who contribute.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

This project is licensed under the Apache 2.0 license.

Contact

If you have any issues or feature requests, please contact us. PR is welcomed.

node-casbin's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-casbin's Issues

Throws ERROR Unexpected token import

Hi,
I am trying the example given in node-casbin readme and facing following error.

error: uncaughtException: Unexpected token import
/server/services/casbin.service.js:1
(function (exports, require, module, __filename, __dirname) { import * as casbin from 'casbin';
                                                              ^^^^^^

SyntaxError: Unexpected token import
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:607:28)
    at Object.Module._extensions..js (module.js:654:10)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)
    at Module.require (module.js:587:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/server/routers/casbin.routes.js:3:21)
    at Module._compile (module.js:643:30)
    at Object.Module._extensions..js (module.js:654:10)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)
    at Module.require (module.js:587:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/server/routers/app.routes.js:95:24)
    at Module._compile (module.js:643:30)
    at Object.Module._extensions..js (module.js:654:10)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)

All policies getting deleted from the database

Issue:
All the policies in the casbin_rules DB are getting cleared when we try adding a new policy to the DB.

Description:
The casbin library is being used in an authorizer function that's being executed in a lambda function on AWS. After a certain number of policies in the DB, when we try adding a new policy, it looks like the node-casbin library is truncating the table and then adds the new policy.
I am using a mysql db with the typeorm adapter.

The code

Any help would be greatly appreciated.

Watcher does not wait for updating the policy

When I'm providing the enforcer with watcher to reload policy on changes, it actually does not wait for it. It leads to the problem, when policy is inconsistent for a some time.

Here is how I am injecting the watcher:

const adapter = await Adapter.newAdapter(uri);
const watcher = new Watcher();
const enforcer = await Enforcer.newEnforcer(model, adapter, false);
enforcer.setWatcher(watcher);

Surely, watcher has implemented required interface, but, when CoreEnforcer calls an update method in watcher, it actually does not wait for it. update method in watcher calls loadPolicy, which is async function.

Proposed fix - add await here - https://github.com/casbin/node-casbin/blob/master/src/coreEnforcer.ts#L216

Is there any options to cache model and policy files

I added a new line

loadPolicyFile(model, handler) {

        return __awaiter(this, void 0, void 0, function* () {
            const bodyBuf = yield util_1.readFile(this.filePath);
            console.log('loadPolicyFile:',Date.now());
            const lines = bodyBuf.toString().split('\n');
            lines.forEach((n, index) => {
                const line = n.trim();
                if (!line) {
                    return;
                }
                handler(n, model);
            });
        });
    }

and there is a console log show for every request
should we have an option to cache the files

How I have to start casbin with nodejs

Hi sir
Iam new to Nodejs casbin how can I proceed with this
Simply
I have 3 defrent roles
1.admin
2. interviewer
3.candidate
Each and every person has his individual permissions to acces his data how can do this using Nodejs casbin
Please suggest me... With examples
Thanks in advance

Request definition doesn't work without subject.

In this first example, the subject is included in the request.

[request_definition]
r = sub, obj, act

[policy_definition]
p = obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.obj == p.obj && r.act == p.act
p, Resource, Read
await e.enforce('p', 'Resource', 'Read') // returns true

But, if I remove the subject from the request definition, the CSV, and the enforce argument signature, I would expect the result to be the same. However, the coreEnforcer.ts returns an Indeterminate result.

[request_definition]
r = obj, act

[policy_definition]
p = obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.obj == p.obj && r.act == p.act
Resource, Read
await e.enforce('Resource', 'Read') // returns false

The justification for removing the subject entirely is based on my particular use case. In my case, the policy comes in the form of a merged policy document specific to that user.

Is this a bug or a feature of casbin?

TypeError: rvals[j].trim is not a function

Get that error trying to use both of ABAC and RBAC models.

I have the following model:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = (g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act) || r.sub.id == r.obj.owner

Also some records in 'policy.csv' which look like:

p, admin, post, delete

Here is my code:

enforcer.enforce('admin', 'post', 'delete') // works fine.
enforcer.enforce({ id: 1 }, { name: 'post', owner: 1 }, act) // is failing with the error:
(node:77674) UnhandledPromiseRejectionWarning: TypeError: rvals[j].trim is not a function
    at model.model.get.get.tokens.forEach (/Users/ahushh/Projects/casbin/node_modules/casbin/lib/coreEnforcer.js:291:54)
    at Array.forEach (<anonymous>)
    at Enforcer.enforce (/Users/ahushh/Projects/casbin/node_modules/casbin/lib/coreEnforcer.js:290:59)
    at Object.<anonymous> (/Users/ahushh/Projects/casbin/index.ts:13:14)
    at step (/Users/ahushh/Projects/casbin/index.ts:32:23)
    at Object.next (/Users/ahushh/Projects/casbin/index.ts:13:53)
    at fulfilled (/Users/ahushh/Projects/casbin/index.ts:4:58)
(node:77674) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:77674) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I've tried to fix that by removing trim call when rvals[j] is not a string and it works. But this is my first use of Casbin and I'm not sure if I use Casbin correctly at all.

Versions:

  "dependencies": {
    "@types/node": "^10.12.3",
    "casbin": "^1.1.5",
    "ts-node": "^7.0.1",
    "typescript": "^3.1.6"
  }

Documentation has two broken links @ "See here for examples."

Heads up!

On this page: https://github.com/casbin/node-casbin#policy-management, under the Policy Management header, the links to your examples for 1) Management API, and 2) RBAC API are returning 404.

Specifically, the links have the word here linked in the sentence "See here for examples."
The two urls set on the word here are, respectively:

  1. https://github.com/casbin/node-casbin/blob/master/src/test/java/org/casbin/node-casbin/main/ManagementAPIUnitTest.java
  2. https://github.com/casbin/node-casbin/blob/master/src/test/java/org/casbin/node-casbin/main/RbacAPIUnitTest.java
    ...which point to .java files instead of {.js|.jsx|.ts} files?

Thanks for your time.

-Dan

[Feature Request] separating packages

It is recommended that separating packages to implement core functions and configuration/policy reads to facilitate multi-environment (e.g. web front-end) usage.

where can I find web-ui?

In the guide, it mentioned there is a web-based UI for model management and policy management..
where can I find it?? how can I use this web-ui in my own node-casbin application??
should I develop the web part by myself ?? any guide there???

RoleManager interface return type

I see that the return type of function signature in interface RoleManager are not async value.
In fact, all functions related to IO operation in JavaScript should be async, for example:

getRoles(name: string, ...domain: string[]): string[];
Perhaps it will query database
So it should be

getRoles(name: string, ...domain: string[]): Promise<string[]>

for compatibility, maybe it can be
getRoles(name: string, ...domain: string[]): Promise<string[]> | string[]

thoughts?

@nodece @hsluoyz

Enforce auth problem

hi every one

i have a new problem when i try the simple example

i write a simple function named casbin_test() , and "keymatch_model.conf" , "keymatch_policy.csv"
is the example files.

but the

enforcer.enforce(sub, obj, act)

is always return "false"

async function casbin_test() {
    const enforcer = await casbin.newEnforcer('./keymatch_model.conf', './keymatch_policy.csv');
    const sub = 'alice'; // the user that wants to access a resource.
    const obj = '/alice_data/'; // the resource that is going to be accessed.
    const act = 'GET'; // the operation that the user performs on the resource.

    if (enforcer.enforce(sub, obj, act) == true) {
        console.log('permit alice to read data1');
    } else {
        console.log('deny the request, show an error');
    }
}

and when i want check the roles that a user has

    async function casbin_test() {
    const enforcer = await casbin.newEnforcer('./keymatch_model.conf', './keymatch_policy.csv');
    console.log(enforcer.getRolesForUser('alice'));
}

it will display

0|CIA  | 2019-01-30 10:07 +08:00: TypeError: Cannot read property 'get' of undefined
0|CIA  | 2019-01-30 10:07 +08:00:     at Enforcer.getRolesForUser (/home/node_modules/casbin/lib/enforcer.js:84:45)
0|CIA  | 2019-01-30 10:07 +08:00:     at casbin_test (/home/app.js:93:26)

Can not add role for a user in case g = _, _, _

I have the following role definition:

[role_definition]
g = _, _, _

But, when I am trying to add a role for a user, the function addRoleForUser accepts only two parameters (it is hardcoded), so I can not provide the domain.

Here is the test-case I wrote to check that:

    it('Should properly add new role to user and remove it from the enforcer', async () => {
        const enforcer = await getEnforcer();

        assert.deepEqual(await enforcer.getGroupingPolicy(), []);
        // here I am trying to add role, but signature for the method accepts only user and role
        assert.isTrue(await enforcer.addRoleForUser('subject', 'role', 'domain'));
    });

So, as a result, I am getting the following error:

Error: grouping policy elements do not meet role definition
      at Assertion.buildRoleLinks (node_modules/casbin/lib/model/assertion.js:40:23)
      at astMap.forEach.value (node_modules/casbin/lib/model/model.js:123:19)
      at Map.forEach (<anonymous>)
      at Model.buildRoleLinks (node_modules/casbin/lib/model/model.js:122:16)
      at Enforcer.buildRoleLinks (node_modules/casbin/lib/coreEnforcer.js:246:20)
      at Enforcer.<anonymous> (node_modules/casbin/lib/managementEnforcer.js:339:22)
      at Generator.next (<anonymous>)
      at fulfilled (node_modules/casbin/lib/managementEnforcer.js:17:58)

Pure permission groups assignable for specific domains/groups/tenants

Hi there,

I'm looking for a way to create groups with non specific permissions. e.g. Admin -> * -> write and the ability to assign these groups to specific domains.

How would I go about this?

https://github.com/casbin/node-casbin/blob/master/examples/rbac_with_domains_policy.csv
This example is creating a group for every domain, I would like to each group only once and control the domain access when the group assigned to users.
e.g.

p, group_admin, subject_blog, permission_read
g, user_a, group_admin, domain_7

Is this possible?

GitHub release for 3.04

Hi there,

I notice that 3.0.4 has been released to NPM but not to GitHub. Is it possible to make a release for it?

Thanks!

Node.js API Documentation?

Hi, great project here, currently trying to do some tests with it.
But is there a proper API documentation in javascript? Currently, when not using TS, it seems very hard to get into. I've been trying to translate some methods from the website's examples in Go, cross-referenced with the TS sources, but there's little feedback why something does/doesn't work.

Example:

const model = new casbin.Model(modelText); //basic acl model
const policyAdapter = new casbin.FileAdapter('/tmp/policy');
const e = new casbin.Enforcer();
e.setModel(model);
e.setAdapter(policyAdapter);
e.enableAutoSave(false);
let added = await e.addPolicy('p', 'alice', 'data1', 'read');
//added is false, without any indication as to why
expect(e.enforce('humbug','data1','write')).to.equal(false);
//fails, enforce always returns true

Are there plans to improve this weak documentation and debugging?
I'd offer to help, but I'm not using TS.

escape of '.' or just using '.' in regexMatch fails

[request_definition]
r = sub, obj, role, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = permitted(r.sub, r.obj, r.role, r.act) && (created(r.sub, r.obj) || owned(r.sub, r.obj) || (isGlobal(r.obj) && regexMatch(r.act, '.*get$') && !regexMatch(r.act, '.user.')))

regexMatch(r.act, '.user.') translate to .user_ which is passed to:

function regexMatch(key1, key2) {
    return new RegExp(key2).test(key1);
}

as key2

Trying to use one of:

regexMatch(r.act, '\.user') 
regexMatch(r.act, '\\.user') 
regexMatch(r.act, '\\\.user') 
regexMatch(r.act, '\\\\.user') 

Leads to an TypeError.

const expString = this.model.model.get('m').get('m').value
TypeError: Cannot read property 'get' of undefined
    at Enforcer.<anonymous> (node_modules\casbin\lib\coreEnforcer.js:254:56)
    at Generator.next (<anonymous>)
    at node_modules\casbin\lib\coreEnforcer.js:20:71
    at new Promise (<anonymous>)
    at __awaiter (node_modules\casbin\lib\coreEnforcer.js:16:12)
    at Enforcer.enforce (s:\workspace\vsts\boge-connect\server\node_modules\casbin\lib\coreEnforcer.js:239:16)

Any suggestions?

RBAC filtering roles based on domain

Hi,

I have set up "Role definition with domains tenants" model and it works well when I use enforce() to check user permission per domain. But is there an option to filter role listing per domain? getAllRoles() return all roles for all domains and I didn't find any other way that can return me filtered roles.

[Feature Request] Support string policy

Problem

This library would be much easier to support and implement against if the expected policy document was a string instead of a file or database connection.

Question

Is there a way for us to pass the policy document as a string? If so, could you provide an example?

Context

Using GraphQL, we pass a policy CSV in the context of a request and check authorization against the policy document multiple times. Therefore, it's far better to have the policy in-memory before asserting against it. Moreover, this policy document originates from the database for security reasons as we don't want to expose a user's given role-based policy document.

If we were to pass in a database connection, we would have to do a DB call for every node of the GraphQL request, which means N+1 database calls.

Otherwise, I would have to write a file to the /tmp directory of our server, read file for every node, then garbage collect on it. This is a potential security vulnerability as we don't want a user's RBAC policies exposed in our file system.

Implementation

const { newEnforcer } = require('casbin')
const isAuthorized = (sub, obj, act) => {
  return rule()(
    async function (parent, args, ctx, info) {
      try {
        const enforcer = await newEnforcer(`${__dirname}/model.conf`, ctx.policy)
        enforcer.enforce(sub, obj, act)
        return enforcer.enforce(sub, obj, act)
      } catch (err) {
        console.error(err)
        return false
      }
    }
  )
}

Policies consistency

I'm having some issues of inconsistency when updating my table rules directly from the database. If I change some data in my database it only reflects on casbin after restarting the application.

I'm using the Sequelizer adapter at the moment.

What is the optimal way to solve this?

building ABAC policies via custom UI interface

I'm trying to create an app where end users can create ABAC policies for resources in my app via a custom UI. In a nutshell, all attributes would be predefined by me for use in the app and the user would go to the custom UI and select attributes based on the subject, action, resource, and time.
Can Casbin support such a system? I've been digging into Casbin trying to fully grasp how to use it with ABAC and I feel like the static models would hinder such an endeavor since (from my understanding) the static model contains the actual logic and seem to be using dot notation to access the attributes on the argument objects.

throw error if does not have access to attributes

Hi,

Thanks for the nice access control package.

I have a use case where we wanted to tell the client side that they don't have access to the following attribute when they try to access it. But right now the AC only check the roles and allow to filter the attribute, in other words, "gracious" style.

Is there a function for me to inform the roles that their access is denied because they requested the attributes that they don't have access.

Right now I think I can compare the attributes pre and post filter if it's not equal, I can throw an error but this will require me to do the same checking like the filter if I want to know which attributes that they don't have access.

@rained23 , you can try Casbin to implement it.

Using enforce on view to show/hide different elements

I'm doing something along the lines of:
res.locals.enforcer = enforcer;

Using ejs for my templating I do something like:
`<% if (enforcer.enforce(sub, obj, act) == true) { } %>

The problem is ejs render the template synchronously and the method enforce is async and returns a promise.. so this doesn't work.

Apparently theres a frontend implementation which returns synchronously and if I used this instead of the node-casbin to create my enforcer it works:
https://github.com/casbin/casbin-website/blob/master/website/static/js/casbin.js

But I'm not sure if this is the correct way to show/hide different elements based on their permissions. Is there anyway to use enforce synchronous from this package?

Using "keyMatch" in the "g" function

I was wondering if it's possible to use the keyMatch function within the g function?

I am attempting to use the domain/tenant as an account and a user could have a role per account or a role for all accounts.

My Model:

[request_definition]
r = subject, resource, action, account

[policy_definition]
p = subject, resource, action, eft

[role_definition]
g = _, _, _

[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))

[matchers]
m = g(r.subject, p.subject, r.account) && keyMatch(r.action, p.action) && (r.resource == p.resource)

My Policies:

p, role:tester, resource, read:*, allow
g, user:1, role:tester, account:*
g, user:2, role:tester, account:21

User 1 has access to the role tester for all accounts. User 2 has access to the role tester for only account 21.

I have tried doing something along to the lines of this but it doesn't seem to work.

m = g(r.subject, p.subject, keyMatch(r.account, p.account) && keyMatch(r.action, p.action) && (r.resource == p.resource)

Facing issue while starting

Hi,

While I execute the below command
npm run-script build

I am getting this error

(node:56412) UnhandledPromiseRejectionWarning: Error: Could not resolve entry (/home/saranya/node-casbin-master/lib/es6/casbin.js)
    at error (/home/saranya/node-casbin-master/node_modules/rollup/dist/rollup.js:3356:15)
    at /home/saranya/node-casbin-master/node_modules/rollup/dist/rollup.js:20724:17 

How to do RBAC with account, organization, user, membership, role structure?

I'm implementing a new model for accounts and users in our application. We're now extending it so that users have roles in organizations ("teams)". So I might be an admin on one team and a user on another. I also see the use for having roles that are a step above all teams, where they are admins over all teams (might be called "Superadmin").

@maxpaj, Node-Casbin supports the RBAC with domains model, see here: https://github.com/casbin/node-casbin#examples. In this model, domain can also be called tenant, or organization as you said. The roles are assigned within a domain context.

Basically what we want is a model that is modular enough so that we can cover a lot of cases.

You can mix the RBAC model with other models like ACL, ABAC, RESTful. it's more flexible than other available auth libraries.

getAllNamedRoles returning null

I have implemented these two methods:

    async getAllUserRoles(){
        let roles = this.enforcer.getAllNamedRoles('g');
        return roles;
    }

    async getAllResourceRoles(){
        let roles = this.enforcer.getAllNamedRoles('g2');
        return roles;
    }

And some of my policies are:

g, test_role, admin
g, sub_role_test1, test_role
g, sub_role_test2, test_role
g, sub_role_test2, test_role
g, test_role_2, admin
g, user_test, just_test_role
g2, glosas, plataforma
g2, credentials, plataforma

In both methods the result is null. Is this a bug?

Synchronizing issues when several instances

Does casbin support working in several application instances or does it provide an interface to implement such?

Problem

Let us say we have 2 instances of API: API 1 and API 2.
Each of these instances have casbin enforcer inside the application.
So, we have casbin 1 in API 1 and casbin 2 in API 2.

Each of them are looking in the same collection in database.
But, considering the implementation of casbin, it stores permissions/roles in memory.

It leads to the problem that can be reproduced by the following scenario:

  • Developer grants a role to a user via API call to API 1.
  • API 1 does make changes in casbin 1 instance and adapter stores the changes in database
  • Though, API 2 and casbin 2 know nothing about recent change and use an out-of-date information from casbin 2 memory.

Any assumptions how it can be resolved?

Same calls with different results

node: v10.16.0, casbin: v3.0.3
Policies are stored in mysql, first call console.log(await enforcer.getUsersForRole('consumer')), return [ 'YFKJ187244601', 'test' ], second call console.log(await enforcer.getUsersForRole('consumer')), return [ 'YFKJ187244601', 'test', '7792707', 'bjdxt' ], .....It's different every time.
I am also try to store policies in redis, the test result are same.
The policies about 40 items.
call
return
policy1
policy2

Can not remove grouping policy

Hi. I can not removeGroupingPolicy from enforcer.

Here is the test case to reproduce:

    it('Should properly add new grouping policy and remove it from the enforcer', async () => {
        const enforcer = await getEnforcer();

        // add grouping policy
        assert.isFalse(await enforcer.hasGroupingPolicy('subject', 'role', 'scope'));
        assert.isTrue(await enforcer.addGroupingPolicy('subject', 'role', 'scope'));
        assert.isTrue(await enforcer.hasGroupingPolicy('subject', 'role', 'scope'));

        // remove grouping policy
        // policy is not removed as a result
        assert.isTrue(await enforcer.removeGroupingPolicy('subject', 'role', 'scope'));
        assert.isFalse(await enforcer.hasGroupingPolicy('subject', 'role', 'scope'));
    });

Multiline matchers support

Golang's casbin supports multiline matchers, but this does not seem to work in the node version (I'm getting a Error: Unexpected "\" at ...).

It would be great to support this use case.

Error retrieving JSON attribute (rvals[j].trim)

I'm trying to use an ABAC policy model, but I'm having some problems to retrieve the attributes from my JSON variable. Here is a simplified example:

My policy file:

p, alice, data1, read

Model file:

[request_definition]
r = user, resource, action

[policy_definition]
p = user, resource, action

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.user == p.user && r.resource.name == p.resource && r.action == p.action

JS call

// req.body.resource = { name: 'data1' }
// req.body.action = read
enforcer.enforce("alice", req.body.resource, req.body.action)

This returns:

UnhandledPromiseRejectionWarning: TypeError: rvals[j].trim is not a function

It works fine when I set 'data1' as enforcer's second argument and remove the ".name" from the matcher.

I have already read TypeError: rvals[j].trim is not a function, but don't found a solution.

keyMatch() matches unwanted policies

Hi,

Suppose I have a model and policies defined as:

p, obj
r, obj
e, some(where (p.eft == allow))
m, keyMatch(r.obj. p.obj)
p, alice:*:* 
p, alice:*:A
p, alice:*:B

Is it correct for me to expect keyMatch() to behave as a glob matching, so that for the request r, alice:*:A, only policies p, alice:*:* and p, alice:*:A would be matched?

Test case

test('matcherWithGlob', async () => {
  let count: number;
  const cb = (...args: string[]): boolean => {
    console.log(args);
    count += 1;
    return true;
  };
  const m = newModel();
  m.addDef('r', 'r', 'obj');
  m.addDef('p', 'p', 'obj');
  m.addDef('e', 'e', 'some(where (p.eft == allow))');
  m.addDef('m', 'm', 'keyMatch(r.obj, p.obj) && cb(r.obj, p.obj)');
  const e = await newEnforcer(m);
  await e.addPolicy('alice:*:*');
  await e.addPolicy('alice:*:A');
  await e.addPolicy('alice:*:B');
  e.addFunction('cb', cb);

  count = 0;
  await e.enforce('alice:resource1:A'); // cb() should be called twice because of short-circuit evaluation
  expect(count).toEqual(2); 
});

Output

  console.log test/enforcer.test.ts:24
    [ 'alice:resource1:A', 'alice:*:*' ]

  console.log test/enforcer.test.ts:24
    [ 'alice:resource1:A', 'alice:*:A' ]

  console.log test/enforcer.test.ts:24
    [ 'alice:resource1:A', 'alice:*:B' ]


Error: expect(received).toEqual(expected)

Expected: 2
Received: 3
Expected :2
Actual   :3
 <Click to see difference>


      39 |   count = 0;
      40 |   await e.enforce('alice:resource1:A');
    > 41 |   expect(count).toEqual(2);
         |                 ^
      42 | });
      43 | 
      44 | function testGetPolicy(e: Enforcer, res: string[][]) {

      at Object.<anonymous> (test/enforcer.test.ts:41:17)
      at fulfilled (test/enforcer.test.ts:17:58)

[question] enforcer api

public async deleteRole(role: string): Promise<void>
Why not return Promise<boolean> ?

public async deleteRolesForUser(user: string): Promise<boolean>
Why not add domain param

Mongoose adapter for casbin

As promised, we have published our mongoose adapter for casbin that we are using in production at the moment.

Feel free to review it and if everything is ok, hoping to add it as official recommended adapter in README for node-casbin.

https://github.com/elasticio/casbin-mongoose-adapter

P.S. I made it thanks to your MongoDB adapter written in Go, so basically, this one is just a port from Go to NodeJS.

Performance issues with ~20k policies

Was wondering if anyone else is experiencing a slow down even with a relatively low number of policies.

For our ~20k policies we notice it takes around 5 seconds to evaluate them.

Here is our conf.

[request_definition]
r = type, resourceId, userId, action

[policy_definition]
p = type, resourceId, userId, action

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.type == p.type && r.resourceId == p.resourceId && r.userId == p.userId && r.action == p.action

We have seemed to narrowed it down to this line in coreEnforcer.ts

Switching from compileAsync to compile and removing the await brought us down to around 40ms with the same amount of policies.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.