项目作者: jjohnson1994

项目描述 :
Role base permissions, write rules and permissions based on user roles.
高级语言: HTML
项目地址: git://github.com/jjohnson1994/rbr.git
创建时间: 2018-07-26T07:26:03Z
项目社区:https://github.com/jjohnson1994/rbr

开源协议:

下载


RBR

Role • Based • Rules

Quickly write rules and permissions based on user roles.

Basic Usage

Import RBR into your app

  1. import RBR from 'rbr';

Define your rules

  1. const rules = {
  2. posts: {
  3. canEdit: {
  4. guest: false,
  5. member: (memberId, postAuthorId) => memberId === postAuthorId,
  6. admin: true,
  7. },
  8. },
  9. };
  10. RBR.setRules(rules);

Query the rules later on

  1. import RBR from 'rbr';
  2. RBR.canEditPost('guest')(1, 1); // false
  3. RBR.canEditPost('member')(1, 1); // true
  4. RBR.canEditPost('admin')(1, 1); // true
  5. /* or */
  6. RBR.setRole('member');
  7. RBR.canEditPost('member')(1, 1); // true
  8. RBR.canEditPost('member')(1, 2); // false

Terminolodgy

  • Table. A table is an object the user can perform actions on. e.g. users, posts.
  • Permission. A permission is an action that the user would like to perform.
  • User Role. A user role defined the level of access the user has. This should be saved against the user somewhere in your database. e.g. guest, admin.
  • Rule. A rule is the requirements that must be met for a user role to be able to perform an action on a table.

Defining Rules

The Rules Object

Rules are defined within a rules object. The rules object contains three levels: tables, permissions and roles. Each role is then given a rule.

  1. const rules = {
  2. tableA: {
  3. permissionA: {
  4. userRoleA: rule,
  5. userRoleB: rule,
  6. },
  7. permissionB: {
  8. userRoleA: rule,
  9. userRoleB: rule,
  10. },
  11. },
  12. tableB: {
  13. permissionC: {
  14. userRoleA: (a, b) => a !== b,
  15. userRoleB: (a, b) => a > b,
  16. },
  17. permissionD: {
  18. userRoleA: true,
  19. userRoleB: (a, b, c) => a > b && c < a,
  20. },
  21. },
  22. }

Naming Permissions

Permissions should be named after the action they perform e.g. canEdit, canUpdate. The name of each permission will be prepended to the table they belong to (final permission name = permission name + table name).

  1. const rules = {
  2. dog: {
  3. canFeed: {
  4. ...
  5. }
  6. canClean: {
  7. ...
  8. },
  9. },
  10. }

The rules object above will yield two permissions canFeedDog and canCleanDog.

Writing rules

Rules are defined on each user role, they can either be a boolean or a function. You might want to use a boolean value for some user roles, and a function for others.

  1. const rules = {
  2. post: {
  3. canRead: {
  4. guest: post => post.visibility = 'public',
  5. member: post => post.visibility = 'public',
  6. },
  7. canEdit: {
  8. guest: false,
  9. member: (userId, postAuthorId) => userId === postAuthorId,
  10. },
  11. },
  12. }

Or simplified to

  1. const isPostPublic = post => post.visibility = 'public';
  2. const rules = {
  3. post: {
  4. canRead: {
  5. guest: isPostPublic,
  6. member: isPostPublic,
  7. },
  8. canEdit: {
  9. guest: false,
  10. member: (userId, postAuthorId) => userId === postAuthorId,
  11. },
  12. },
  13. }

The examples above are quite simple and a lot more can be done within a rules function. For example, you could make calls to your API.

If a boolean is used as a rules value, it will be wrapped in a function that returns its value. This way you can treat all rules as functions when checking permissions later on.

Checking Permissions

RBR using a singleton pattern, so anywhere you import RBR, you will have access to your rules.

You can specity the user role to check either when calling a rule or on the RBR class. Setting it on the RBR class is recommended because it only has to be set once.

When a rule is called (e.g. canEditPost()) it will return a second function, this function takes any parameters that might be used in a rule.

If parameters are given to a rule that doesn’t require them, they will be ignored and the rule will return it’s value like normal.

  1. const rules = {
  2. user: {
  3. canCreated: {
  4. user: false,
  5. admin: true,
  6. },
  7. canEdit: {
  8. user: (currentUserId, editUserid) => currentUserId === editUserId,
  9. admin: true,
  10. }
  11. }
  12. }
  1. import RBR from 'rbr';
  2. RBR.canCreatedUser('user')(); // false
  3. RBR.canCreatedUser('admin')(); // true
  4. /* or */
  5. RBR.setRole('user');
  6. RBR.canEditUser()(1, 1); // true
  7. RBR.canEditUser()(1, 2); // false