Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible future of cancan #28

Closed
8 tasks
stalniy opened this issue Jul 7, 2017 · 7 comments
Closed
8 tasks

Possible future of cancan #28

stalniy opened this issue Jul 7, 2017 · 7 comments

Comments

@stalniy
Copy link

stalniy commented Jul 7, 2017

I'd like to suggest possible future of cancan:

  • make API a bit simpler (ability.can('read', Post) instead of can(user, 'read', Post))
  • improve performance of checks via special datastructure (this will prevent event loop blocking in case of big amount of rules)
  • provide more sophisticated rule checks based on Mongo QL (can be added with help of sift.js)
  • create a mongoose middleware which converts specified rules into Mongo Query and allows fetch records like Post.accessibleBy(ability), where ability is a configured instance of Ability class which in this library is just called CanCan
  • separate RuleBuilder and Ability this will allow to build context dependent DSL
const { RuleBuilder, Ability } = require('cancan')

function defineRulesFor(user) {
  const { can, cannot } = new RuleBuilder()

  can(['read', 'update'], 'Post');
  can('delete', 'Post', { createdBy: user.id });
  cannot('update', 'Post', { readonly: true });
  can('read', 'Comment');
  can('delete', 'Comment', { createdAt: { $gt: Date.now() - 3600 * 1000 } })

  return can.rules;
}

const ability = new Ability(defineRulesFor(currentUser))

ability.can('read', Post)
  • more tests (also I'd like to use something like mocha or jest for testing)
  • provide browser version of the library
  • add better documentation (similar to what Ruby cancan has, provide examples for Express.js integration, for Angular2/Aurelia/Ionic2/React/Vue integration)

Some of these I did in past, so instead of creating one more cancan project suggest to merge some of my ideas into yours :)
So, @vadimdemedes what do you think?

@vadimdemedes
Copy link
Owner

make API a bit simpler (ability.can('read', Post) instead of can(user, 'read', Post))

Could you provide a full example? From here it's not clear how is it simpler.

improve performance of checks via special datastructure (this will prevent event loop blocking in case of big amount of rules)

This is interesting. Do you have any examples?

provide more sophisticated rule checks based on Mongo QL (can be added with help of sift.js)

This is probably too much. The whole point of the package is to give yes/no answers and have a simple API. I'm afraid this will make it complex. Do you have a real use case, where cancan failed?

create a mongoose middleware which converts specified rules into Mongo Query and allows fetch records like Post.accessibleBy(ability), where ability is a configured instance of Ability class which in this library is just called CanCan

Same as above. Since cancan is abstract, I don't see the point of making a middleware for a specific project. Feel free to release it as an individual module though.

separate RuleBuilder and Ability this will allow to build context dependent DSL

Would also like to see real use cases, where this is useful.

more tests

Always welcome.

(also I'd like to use something like mocha or jest for testing)

Why?

provide browser version of the library

It doesn't use any Node.js-specific libraries, what makes it not usable in a browser?

add better documentation

Again, always happy to accept documentation improvements.

(similar to what Ruby cancan has, provide examples for Express.js integration, for Angular2/Aurelia/Ionic2/React/Vue integration)

I think all of them will share the same "cancan code" and will just be demos on how to set up Express or other frameworks.

Some of these I did in past, so instead of creating one more cancan project suggest to merge some of my ideas into yours :)
So, @vadimdemedes what do you think?

Good thinking! Let's elaborate more on these points and see what can be done.

@stalniy
Copy link
Author

stalniy commented Jul 9, 2017

I'd suggest you to look at https://github.com/CanCanCommunity/cancancan#getting-started you will find detailed description of all points. I'd like to create a package which will have the same functionality but in JavaScript, the starting point is MongoDB adapter.

I know that you want to keep code short and simple but I want to make it featured, as ACL framework, the same as it is in Ruby world.

Answers for each question:

  1. can(user, 'read', Post) requires developer to store 2 references (1 for configured can method and another one to user). ability.can('read', Post) requires you to store only 1 reference (reference to ability instance). Everything should be around abilities, not around user. For example, I worked on software for embeded systems. In such software a lot of abilities depends not only on ACL but also on physical capabilities of hardware. In such cases it's very handy to define permissions and hardware capabilities via abilities/rules
  2. in setRules method of Ability I create a structure [action_subject]: <array of rules>. This structure allows quickly get rules for specific action and specific subject and reduce them into integer.
  3. Very often you may want to retrieve all records which satisfies defined permissions. For example, how would you retrieve all Posts which user can update? I suggest to make it EXTREMELY simple Post.accessibleBy(ability), this will construct database specific query and retrieve all posts which satisfies defined rules (inspite of their complexity)
  4. The package should contain middlewares for the most popular frameworks, so users can start use it straightway. I think we can start from putting examples of how to do this for Express and Hapi and then will wait for feedback from community.
  5. This will allow to abstract rule definition and pass all of them as configuration object:
const { can } = new RuleBuilder()
const Ability = require('cancan')

can('read', Post)
const ability = new Ability(can.rules)

// or
const rules = await Permission.find()
const ability = new Ability(rules)

// or 
const response = await http.get('http://some.api.com/session')
const ability = new Ability(response.data.rules)

Basically you can work with rule sources (datasources) much easier.
6. Cool!
7. I'd like to use mocha or jest because people are more familiar with this tools, it will atract to make contributions into the project. Also I believe BDD style is easier for understanding and supporting
8. Currently you are right but when we add more features it will consist more than from 1 file
9. Cool, I already did some in past and will reconstruct something similar to https://github.com/CanCanCommunity/cancancan#getting-started
10. Yes all these are just demos and examples

Hope that all clear and let me know if you have other questions!

Looking forward to successful collaboration :)

@stalniy
Copy link
Author

stalniy commented Jul 10, 2017

About browser build:
As far as I see you started to rewrote code into ES6. Not all browsers supports ES6, that's why package will need to provide ES5 compatible version for browsers

@vadimdemedes
Copy link
Owner

I don't think I want to do any of these (except documentation and test improvements), because they would make this module a monster and I like how tiny and focused it is now. If a project requires such a complex ACL, there's a good chance it needs a custom solution.

@stalniy
Copy link
Author

stalniy commented Jul 10, 2017

I see. Thanks for your time.

The project won't be monster you will see this a bit later ;)

@stalniy stalniy closed this as completed Jul 10, 2017
@vadimdemedes
Copy link
Owner

Thanks for putting all these suggestions too. Too bad that it's not a good fit, in my opinion. Good luck with your project!

@stalniy
Copy link
Author

stalniy commented Aug 3, 2017

Please check https://github.com/stalniy/casl in case if you are interested to see what I came up with

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants