0.0.2 • Published 9 months ago

roba v0.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

roba

Flexible Role-Based Access Control

Roba is a lightweight access control library that lets you quickly define and verify rules for controlling access to resources.

What Does "Roba" Mean?

Roba just uncreatively means Role-Based Access. Clever, right?

Installation

npm install roba

or

yarn add roba

or

pnpm add roba

Concepts

Entities

Entities are the actors performing actions, such as users. There are two types of entities: Actors and Collectives. An Actor is a single entity designated by a unique name. Likewise, a Collective is a group of several actors under a certain name (such as a role).

Entity Scopes

Scopes are used to group things together.

Actions

Actions are the actions that can be performed. There are only four types of actions: Create, Read, Update, Delete.

Resources

Resources are the things we entities perform actions on. For example, posts. Like Entities, resources are identified by some unique name. Resources can either be collections or instances. Collections refer to the resource as a whole. Meanwhile, Instances are specific objects within a resource collection, identified by an id and owner identifier.

Scoped Resources

Like entities, resources can also have a scope.

Usage

Creating an Entity

To begin, you define an actor or a collective containing its own set of permissions.

import { Actor, Collective, Permission } from 'roba';

// basic definition of a collective
const users = new Collective('users', [Permissions.Protected('accounts'), ...]);

// with a custom scope for a collective.
const users = new Collective('users', [Permission.Protected('accounts'), ...], 'my-scope');

// creating an actor from a collective.
const user = Actor.DerivedFrom(users, 'bob');

// creating an Actor manually
const user = new Actor('users', 'user-id', [Permission.Protected('accounts'), ...], 'my-scope');

An Actor is a single entity capable of performing an action. A Collective is a collection of Actors under a shared name, scope, and permissions. It is highly recommended that you create a Collective first, and then derive Actors from it using the Actor.DeriveFrom() method. This ensures actors have a consistent set of permissions and scopes.

Creating Resounces

Once you have created an entity, you must next create a Resource. A Resource is something that is owned by an entity. A Resource can either be a Collection or an Instance. a Resource Collection refers to all instances of that resource. Meanwhile, a Resource Instance refers to a single instance of that resource with a unique identifier.

import { Resource } from 'roba';

const accounts = Resource.Collection('accounts', 'my-scope');
const account = Resource.InstanceOf(accounts, 'account-id', user, 'my-scope');

We define Resources with either the Resource.Collection() method or the Resource.InstanceOf() method.

Note: Resource names should be single words in lowercase plural form if possible. For example, "accounts" and "users", If more than one word is needed, use underscores (_) to separate them. For example, "user_accounts".

Verifying Permissions

Finally, we can check whether or not an actor or collection can perform an action as follows.

import { users } from './entities';
import { accounts } from './resources';

users.can.update(accounts); // false
const bob = Actor.DeriveFrom(users, 'bob');
const bobAccount = Resource.InstanceOf(accounts, 'account-id', bob);
bob.can.update(bobAccount); // true

Notice how the first call to the can() method returns false while the second returns true. When we pass a Resource Collection to the can.*() functions, we are testing permissions for the collection as a whole. When we pass a Resource Instance to the can.*() methods, we are testing permissions for that specific resource instance.

Custom Conditions

There are situations where it is necessary to meet certain conditions, in addition to having the right permissions. For this reason, it is possible to declare custom conditions that must be met in order to grant permission.

import { Actions } from 'roba';
import { users } from './entities';
import { accounts } from './resources';

users.can.update(accounts); // false
const bob = Actor.DeriveFrom(users, 'bob');
const bobAccount = Resource.InstanceOf(accounts, 'account-id', bob);
bob.can.update(bobAccount, (entity, action, resource) => bobIsActive); // true

We have added an additional parater to the can.*() methods, which returns a boolean (bobIsActive) that indicates whether or not we can update the bobAccount resource.

Verifying the Lack of Permissions

If you need to check if an entity does not have permission to perform an action, Roba provides convenient cannot.*() methods that return the inverse of their can.*() counterparts.

import { users } from './entities';
import { accounts } from './resources';

users.cannot.update(accounts); // true
const bob = Actor.DeriveFrom(users, 'bob');
const bobAccount = Resource.InstanceOf(accounts, 'account-id', bob);
bob.cannot.update(bobAccount); // false

Inheritance

We can inherit from existing collectives using the Collective.Inheritfrom() method. Inheriting from a Collective lets the derived collective adopt the permissions and scope of the collective it is inheriting. You can even customize permissions by redefining them in the permissions array, in which case they will override any existing permissions inside the parent collective.

import { Actions, Collective } from 'roba';
import { users } from './entities';
import { accounts } from './resources';

const admins = Collective.InheritFrom(users, 'admins', [Permission.All('accounts')]);
users.can(Actions.Destroy, accounts) // false
admins.can(Action.Destroy, accounts) // true

Utilities

Roba provides a few utility functions to assist with miscellaneous tasks.

Parsing Permissions Lists

There are situations where it is necessary to extract permissions from an entity. By default, Roba entities (Actors amd Collectives) expose a permissionsList property which returns a string array consisting of the entity's permissions.

import { Actor, Collective, Permission } from 'roba';

// basic definition of a collective
const users = new Collective('users', [Permissions.Protected('accounts'), ...]);
collectionPermissions = users.permissionsList);

// creating an actor from a collective.
const user = Actor.DerivedFrom(users, 'bob');
const userPermissions = user.permissionsList);

To reconstruct permission objects from permissions lists, Roba exports the parsePermissionsList() function.

import { parsePermissionsList } from 'roba';
const permissions = parsePermissionsList(str);

The parsePewrmissionsList() function returns a Permission array which can be used when recreating entities.

LICENSE

Roba is provided under the MIT license.

Reporting Issues

If you encounter any issues, you can open an issue here.

0.0.2

9 months ago

0.0.1

9 months ago