Code Monkey home page Code Monkey logo

role-acl's People

Contributors

chrisjagoda avatar dependabot[bot] avatar ivoreis avatar janejeon avatar koladilip avatar monalisorathiya avatar myovchev avatar paragpoddar avatar sbuljac avatar vitorluizc avatar

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

role-acl's Issues

Require cycle problem

Hi, I try to use this library on react-native. And I got warning

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle.
[Wed Jul 01 2020 06:55:03.110]  WARN     Require cycle: node_modules/role-acl/lib/src/conditions/util.js -> node_modules/role-acl/lib/src/conditions/StartsWithCondition.js -> node_modules/role-acl/lib/src/conditions/util.js

How to solve this problem ?

Own condition fn

Hey, your lib looks not bad but we need own condition functions

function checkOwner(context) {
  // ... own specifc logic
  return allowed;
}

ac.grant('user')
  .condition(checkOwner)
  .execute('update')
  .on('posts');

ac.can(user.roles)
  .context({user, post, org})
  .execute('update')
  .on('posts');

In a prefect world, the checkOwner function can be async to allow additional database lookups without the need to bind this logic on the context creation.

"Cannot find module 'role-acl'" - needing to refer to AccessControl class as type

I'm writing type definitions for another developer's library and they're using role-acl. One of the arguments they're using is of the AccessControl class. If I write import { AccessControl } from 'role-acl', role-acl is not recognised as a module (see error message in title). How do I access the AccessControl class in order to use it as a type? Thank you.

Support setting error messages from ACL

Hi, so I've dug thru the source code and found that the only "attributes" of a grant allowed are the role, resource, action, attributes, and condition.

However, I'd like to specify the error message when defining the ACL. I know this isn't possible now, but could you please add this feature? Thank you!

Cannot find module './lib' from 'index.js'

Hey,

I have the following error when i try to use the lib (v3.3.3 - installed via npm):

Cannot find module './lib' from 'index.js'

To fix it I change the file /index.js with:

var AC = require("./lib").AccessControl;

=>

var AC = require("./lib/src").AccessControl;

:)

Condition with json path does not work

Hello,

When I reproduce the example, the condition does not pass. I use the latest version (3.3.0) installed via yarn add role-acl.

Furthermore, is it possible to pass a path to access nested objects?
For example: $.owner.tenant._id

const AccessControl = require('role-acl')

test('Condition', async () => {
  const ac = new AccessControl()
  ac.grant('user').condition({
    Fn: 'EQUALS',
    args: {
      'requester': '$.owner'
    }
  }).execute('edit').on('article')
  const permission = ac.can('user').context({ requester: 'dilip', owner: 'dilip'}).execute('edit').on('article')
  expect(permission.granted).toBeTruthy()
})

Result:
Screenshot 2019-03-19 at 21 11 13

Thx for your great job!

Add option to make methods synchronous

Hi, I maintain a library that depends on role-acl and accesscontrol, and while I've tried to work around the now asynchronous methods, it's ridiculously hard, especially when extendRole is async.

Can you add an option to make the methods synchronous? 99% of us don't need the methods to be async... please and thank you.

Action rule not working

Hi,

Thanks for the great tool. I am evaluating the 4.1.0 version of it. I run into an issue.

My grant list looks like this:

{ role: "terminalDispatcher", resource: "user", action: "read", attributes: ["*"] }, { role: "terminalDispatcher", resource: "user", action: "edit", attributes: ["*"], condition: { Fn: "EQUALS", args: { requester: "$.owner" } } }, { role: "terminalAdmin", resource: "user", action: "read", attributes: ["*"] }, { role: "terminalAdmin", resource: "user", action: "edit", attributes: ["*"], condition: { Fn: "EQUALS", args: { requester: "$.owner" } } }, { role: "terminalAdmin", resource: "user", action: ["edit", "delete"], attributes: ["*"], condition: { Fn: "EQUALS", args: { allowedRole: "terminalDispatcher" } } }
My intentions are:

  • terminalDispatcher and terminalAdmin roles can read all the users.
  • terminalDispatcher and terminalAdmin role can edit their own records.
  • terminalAdmin can edit and delete terminalDispatcher records

Using the above grants I have initialized AccessControl, here is the code snippet:

let targetEditTerminalDispatcher = { allowedRole: 'terminalDispatcher' }; let targetEditTerminalAdmin = { allowedRole: 'terminalAdmin' }; let grantList = getUserRoleACL(); const ac = new AccessControl(grantList); const readPermission = await ac.can('terminalAdmin').execute('read').on('user'); const editSelfPermission = await ac.can('terminalAdmin').context({requester: 5, owner: 5}).execute('edit').on('user'); const editNotSelfPermission = await ac.can('terminalAdmin').context({requester: 5, owner: 6}).execute('edit').on('user'); const editTerminalDispatcher = await ac.can('terminalAdmin').execute('edit').with(targetEditTerminalDispatcher).on('user'); const editTerminalAdmin = await ac.can('terminalDispatcher').execute('edit').with(targetEditTerminalAdmin).on('user'); const editTerminalAdminRANDOM = await ac.can('terminalDispatcher').execute('edit').with('ABC').on('user');

All grant results good except for editTerminalAdmin and editTerminalAdminRANDOM.
I was not expecting them to be granted = true, but they are.

Am I missing something or do I need specifically deny permission?

Retrieve condition for a resource/action

Hello,

First of all, I want to give you a big thanks for this great library.
In some case, I have to use the condition feature which requires some check in the database for certain role. Admin users can do anything on the resource, but basic users can only maintain the resources in the room they belong to.
For example, basic user 1 can edit the resources A, B and C, and basic user 2 can edit resources C and D.

In order to minimize performance impact, I would like to retrieve the grant associated to the resource / action and then provide the context (LIST_CONTAINS retrieved from database) only if required.
One option is to first check on my side if the role requires to pass the context, but this means that I must have the permission knowledge in my business module. Additionally, it increases the maintenance of my application in case of any change in the authorization.

Another option is to use the custom condition, but it's not compatible with the grant object definition. I found that custom condition are removed when the json object is cloned in the normalizeGrantsObject method.

Does it makes sense for you ?

Thanks

Db storage

Hey,
I really love the api of this library but It's a shame it's only saved in memory.
it this possible to think about extending with db, redis... ?

Condition when args EQUALS null returns false, expected true.

I'm testing whether an argument equals null in a condition with the expectation that it should return true.

Instead, it returns false

Permission {
  _: {
    role: 'user',
    resource: 'abc',
    context: {
      AssignedId: 'f1346471-6adf-431e-9602-656fa46c78b1',
      CompletedAt: null,
      userId: 'f1346471-6adf-431e-9602-656fa46c78b1',
    },
    attributes: []
  }
}
       {
            resource: 'abc',
            action: ['update'],
            attributes: ["CompletedAt"],
            condition: {
                Fn: 'AND',
                args: [
                    { 'Fn': 'EQUALS', 'args': { 'userId': '$.AssignedId' } },
                    { 'Fn': 'EQUALS', 'args': { 'CompletedAt': null } }
                ]
            }
        }

I've also tried without the Fn: 'AND' condition and see the same.

Need suggestion on how to support async functions for conditions

This is a great library that I was using in my project, thanks! I especially love how I can express my permissions business logic using

ac.grant('user').execute('action').where(context => SOME LOGIC).on('resource')

However I came upon a wall. I would like to use an asynchronous function in the where clause. But the library does not support that. Any idea how I can go about this?

E.g. I would like to pass a resource_id as the context, and the function would perform an asynchronous database call to ensure that the user has been associated with that resource.

Update documentation to reflect async functions in 4.0

Honestly 90% of the examples in the README are synchronous and I literally can't tell whether a method is async or not (e.g. I was surprised when extendRole was failing, and turns out it was async for some reason) because of it.

It would be nice to just say "hey all these functions are synchronous on <4.0" at the top of the documentation and update the examples of async methods to reflect that. It's just confusing because some are async, some are not, and I can't tell by reading the README!

P.S. to make it easier for people to migrate between versions, please maintain a changelog by using something like https://github.com/sindresorhus/np for every version you release.

3.0.7 gives module not found error

Hi,

First I'd like to mention that I like using this module, the conditionals make it very powerful to deal with fine grained access control.

After updating to v3.0.7 I get the following error
{"column":32,"file":"module.js","function":"Module.load","line":573,"method":"load","native":false}],"stack":["Error: Cannot find module './lib'"," at Function.Module._resolveFilename (module.js:555:15)"," at Function.Module._load (module.js:482:25)"," at Module.require (module.js:604:17)"," at require (internal/module.js:11:18)"," at Object.<anonymous> (/api/node_modules/role-acl/index.js:1:10)"," at Module._compile (module.js:660:30)"," at Object.Module._extensions..js (module.js:671:10)"," at Module.load (module.js:573:32)"," at tryModuleLoad (module.js:513:12)"," at Function.Module._load (module.js:505:3)"," at Module.require (module.js:604:17)"," at require (internal/module.js:11:18)"," at Object.<anonymous> (/api/something.js:6:23)"," at Module._compile (module.js:660:30)"," at Object.Module._extensions..js (module.js:671:10)"," at Module.load (module.js:573:32)"],"level":"error","message":"uncaughtException: Cannot find module './lib'"}

When looking at the node_modules/role_acl directory the 'lib' directory is missing. It seems that the package is incomplete. Going back to v3.0.6 resolves the error.

Support dynamic context values in the conditions using function.

For example: if the value of expression contain "fun:getUserDepartment", it should call "getUserDepartment" function to return the current user's department info.

Maybe need register this custom function to ac with its context.
ac.registerConditionFunc('getUserDepartment', getUserDepartment, userContext)

Nested JSON path does not work.

I've been trying to use grant conditions on a context which has a nested Object similar to below.

Context object:

{
    "val": "abc",
    "item": {
        "itemValue": "abc"
    }
}

condition:

    condition: {
        Fn: 'EQUALS',
        args: {
             'val': $item.itemValue
        }
    }

The docs suggest that an JSON path similar to $item.itemValue would work but the context test never works.

Are nested objects in the context supported? Could you provide examples in the tests if they are?

Loading conflicting grants from same level.

Two grants are loaded from database.

const role1 = {
    role: 'role1',
     resource: 'person',
     action: ['create', 'view', 'treat'],
     attributes: ['*']
}

and

const role2 = {
    role: 'role2',
    resource: 'person',
    action: ['update', 'greet', '!create'],
    attributes: ['*'],
}

With following test code.

const grantsToLoad = [role1, role2]
ac.setGrants(grantsToLoad)

const roles = ac.getRoles()
const permission = await ac.can(roles).execute('create').on('person')
expect(permission.granted).toEqual(false)

I expect create to be denied as it being explicitly mentioned in action of role2. But the desired result is the permission to create is granted. Thus explicit denial is not taken into consideration.

The code behind this behavior is in filter of getUnionAttrsOfRolesSync where role2 is being filtered out in favor of positive action.

public static getUnionAttrsOfRolesSync(grants: any, query: IQueryInfo): string[] {
const matchingGrants = (this.getUnionGrantsOfRolesSync(grants, query))
.filter((grant) => {
return this.anyMatch(query.resource, grant.resource)
&& this.anyMatch(query.action, grant.action);
});
return (this.filterGrantsAllowingSync(matchingGrants, query))
.map((grant) => {
return ArrayUtil.toStringArray(grant.attributes);
}).reduce(Notation.Glob.union, []);
}

Comparing values inside context to each other

I feel it would be very useful to write conditions that can compare values passed into the context against each other, instead of just being able to compare against static values. This would be particularly helpful for checking to see if a user is the owner of a resource.

Something like this could be done outside the RBAC check, but this would help encapsulate all RBAC logic.

For example,

AccessControl.can(roles)
            .with({ requester, target })
            .execute("update")
            .on("user");

...

condition: {
    Fn: 'EQUALS',
    args: {
        requester: '$target'
    }
}

When is next version is published?

there is this note in the readme:

NOTE: getValueByPath is available in versions >= 4.5.5

but on NPM you only have version 4.5.4 published. Is there a reason why this isn't published yet?
I'm trying to use the getValueByPath method.

Copyright notice and License

This is a fork of AccessControl with MIT license.

You cannot remove the copyright notice.
Please include it in both the README and license.

Also remove this and any other false notice in the code please. You can only mark the portions of the code that you actually develop.

You should respect OSS developers. Open-Source is not "free" code for you to label.

AND condition does not await async custom conditions passed as args

Hi- your library is really enjoyable and intuitive to use! I ran into an issue with the AND condition; if you pass it any async custom conditions as args, it does not await those conditions.

Example- given the following grant definition:

{
  role: 'manager',
  resource: 'customers',
  action: 'PUT',
  attributes: ['*'],
  condition: {
    Fn: 'AND',
    args: [
      { Fn: 'custom:sameCustomer }, //sync
      { Fn: 'custom:userCanAccessResource' }, // async
    ],
  },
},

custom:userCanAccessResource is not awaited before permission is evaluated- permission.granted evaluates to "true" as long as all other conditions are met.

Even if you remove custom:sameOwner, you get the same result, so it doesn't seem to be an issue with combining sync with async conditions.

Looks like && Promise.resolve(elm) == elm in the containsPromises method is the culprit; if you comment out that condition, async custom functions passed to AND get awaited properly.

It would seem that removing this logic is the fix, but is there a reason that it's there & should not be removed?

Extend Role in Array

Is it possible to extend a role via the Array Syntax when loading from a DB? I am not able to find anything in the docs if this is possible and seems quite useful.

For example ('admin' extends 'user'):

let grantList = [
    { role: 'user', resource: 'video', action: 'create', attributes: ['*'] },
    { role: 'user', resource: 'video', action: 'read', attributes: ['*'] },
    { role: 'user', resource: 'video', action: 'update', attributes: ['*'] },

    { role: 'admin', extend: 'user' },
    { role: 'admin', resource: 'video', action: 'delete', attributes: ['*'] },
];

4.5.3 introduces type errors

Can only replicate in 4.5.3 (4.5.2 seems to be fine). Using a standard import { AccessControl } from 'role-acl'; results in the following errors at build time.

node_modules/role-acl/lib/src/AccessControl.d.ts:320:16 - error TS1086: An accessor cannot be declared in an ambient context.

320     static get Error(): any;
                   ~~~~~

node_modules/role-acl/lib/src/core/Permission.d.ts:62:9 - error TS1086: An accessor cannot be declared in an ambient context.

62     get roles(): string[];
           ~~~~~

node_modules/role-acl/lib/src/core/Permission.d.ts:70:9 - error TS1086: An accessor cannot be declared in an ambient context.      

70     get resource(): string;
           ~~~~~~~~

node_modules/role-acl/lib/src/core/Permission.d.ts:83:9 - error TS1086: An accessor cannot be declared in an ambient context.      

83     get attributes(): string[];
           ~~~~~~~~~~

node_modules/role-acl/lib/src/core/Permission.d.ts:92:9 - error TS1086: An accessor cannot be declared in an ambient context.      

92     get granted(): boolean;

Versioning & Changelog

Hi there,

The library looks very promising and I really like the ability to define conditions for the permissions ๐Ÿ‘
Wanna give it a try in my current project.

The only concern I have at the moment is the lack of a changelog and tagged versions so that I can easily switch between different versions.

Could you please tag versions and document changes between versions

Error CoreMongooseArray

Hi,
I wrote my grantobject and took it to acl like this, but i had error
const ac = new AccessControl();
ac.setGrants(grantsObject);

Class constructor CoreMongooseArray cannot be invoked without 'new'
(node:11861) UnhandledPromiseRejectionWarning: TypeError: Class constructor CoreMongooseArray cannot be invoked without 'new'
at initCloneArray.........

Role inheritance does not work

Bug Report

Extending roles does not work as expected.
Code sample is taken from documentation.

script.js:

const roleAcl = require("role-acl");
const ac = new roleAcl();

ac.grant('user')
    .execute('read').on('video')
  .grant('admin')
    .extend('user')
    .execute('create').on('video')
    .execute('update').on('video')
    .execute('delete').on('video');
/path/to/script.js:8
  .execute('create')
   ^

TypeError: ac.grant(...).execute(...).on(...).grant(...).extend(...).execute is not a function
    at Object.<anonymous> (/path/to/script.js:8:6)

Environment

  • node version: 12.15.0
  • role-acl version: 4.3.2
  • os: Ubuntu 18.04

Custom declarative condition Fns

I'm exploring the possibility to implement the role-acl lib in a project. I'm injecting it in my own ACL abstraction and everything looks good so far.

However, what I'm missing is an option to declare and register a custom condition Fn as a string and map it to a function. This way I'd be able to wrap more complex business logic and still to serialize and store the grant object.

I see there is custom functions support, which is an option to pre-process the definition and replace a custom condition string with JS function so that library process it, but a native library support would be much better. Not to mention it would open contribution possibilities (I can imagine a MONGODB_QUERY condition...)

Here is sample API of what I have on my mind:

Signature

interface CustomConditionFns {
  [name: string]: (ctx?: Record<string, unknown>, args?: unknown) => boolean;
}

condition.gte.ts

import { get } from 'lodash';

export type ARGS = { field: string; value: number };

export const conditionGte = (ctx: Record<string, any>, args: ARGS) => {
  return +get(ctx, args.field) > args.value;
};

acl.ts

import { AccessControl } from 'role-acl';
import { conditionLte } from 'condition.lte'

const grantObj = fetchOrImportGrant();
const customFns = { 'GTE': conditionGte };

// We'd need to register custom conditions together with grant 
// or before the grant to allow a type checking (unknown condition Fn)

// Register them together with the grant
const acl = new AccessControl(grantObj, customFns);
// OR first conditions, then the grant
const acl = new AccessControl();
acl.useConditions(customFns);
acl.setGrants(grantObj);

Usage (grant definition)

import { ARGS } from 'condition.lte'
const condition: { Fn: 'GTE'; args: ARGS } = {
  Fn: 'GTE',
  args: {
    field: 'user.visits',
    value: 1,
  },
};

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.