A simple RBAC implementation that is datasource agnostic. I've designed it to be easy to integrate into existing projects, while being flexible and very simple to use. It may not be the most powerful permission system ever devised, but it is one of the easiest to get up and running with in very little time.
Simply install with npm
:
$ npm add trivialperms
or yarn
:
$ yarn add trivialperms
TrivialPermissions is built on the concept of 'role based access control'. In essence, a user
is a member of a
group
. That group has specific permissions
. A user may also have specific permissions
granted. A user is allowed
access if either they, or one of their groups they have the permission
being tested.
In TrivialPermissions, a permission
is any string (other than *
or */*
):
'PermissionDescriptor'
TrivialPermissions supports whatever roles you want to use. It supports any arbitrary string. Previous versions were
built around a Object/Permission
styles, and those still work, but in the spirit of simplification and flexibility,
we've dropped the concept of 'object level' permissions, since those were never really implemented in a useful way.
TrivialPermissions has special support for *
and */*
. These strings, when used as a permission name, are
considered wildcards. All permission checks will pass if a user or group has *
or */*
as a permission.
Groups are small objects with a name and a list of permissions. TrivialPermissions requires you to define (or load) these groups before you attempt to use them. This is generally considered part of the initial setup for TrivialPermissions. While TrivialPermissions allows you to use your own objects for users, it requires you to preload your groups.
defineGroup({ name: '...', permissions: [...] })
- Returns the created group object.
Defining an individual group is very simple:
import tp from 'trivialperms'
// Create an 'Admins' group
const admGroup = tp.defineGroup({ name: 'Admins', permissions: ['*/*'] });
loadGroups(list)
- Returns a list of all loaded groups.
More usefully, you will want to load multiple groups at once. TrivialPermissions supports loading a list of groups.
Note: Previous versions allowed for you to pass in a promise or a function, and it would resolve it, but in the
world of async
/await
, there's no reason to support this anymore.
import tp from 'trivialperms';
// Load from a list
tp.loadGroups([
{
name: "Administrators",
permissions: [
"*/*"
]
},
{
name: "Authors",
permissions: [
"canViewPosts",
"canAddPosts",
"canEditPosts"
]
},
{
name: "Users",
permissions: [
"canViewPosts"
]
}
]);
This should make it very easy to integrate with a database library, for example.
You are expected to be providing your own user objects. Generally, this would come from either an authentication system, or a database of some kind. Because of this, we did not want to force you to preload all your users; rather, you provide TrivialPermissions with the object when you want to check permissions. TrivialPermissions requires an object that looks like this:
export interface TPUser {
permissions ?: string[];
groups ?: string[];
}
While both permissions
and groups
are optional, the user will have no permissions if one of the two isn't set.
hasPerm(user, perm)
- Returnstrue
if the user has that permission on that object, otherwise false.
This is the heart of the system: checking permissions. It's very simply; you pass the user object, and the permission descriptor (string). Here are a few examples:
import tp from 'trivialperms';
// Setup
tp.loadGroups([
{
name: "Administrators",
permissions: [
"*/*"
]
},
{
name: "Authors",
permissions: [
"canViewPosts",
"canAddPosts",
"canEditPosts"
]
},
{
name: "Users",
permissions: [
"canViewPosts"
]
}
]);
// Define Users
const batman = {
name: 'batman',
groups: ['Administrators']
};
const stark = {
name: 'tstark',
permissions: ['*'],
groups: ['Users']
};
const leo = {
name: 'lblume',
groups: ['Users']
};
// Batman can edit posts
console.log(tp.hasPerm(batman, 'canEditPosts')); // true
// Tony Start can do anything
console.log(tp.hasPerm(stark, 'canEditPosts')); // true
console.log(tp.hasPerm(stark, 'canGetAwayWithMurder')); // true
// Leo can read posts
console.log(tp.hasPerm(leo, 'canViewPosts')); // true
// Leo can not edit posts
console.log(tp.hasPerm(leo, 'canEditPosts')); // false
hasGroup(user, groupName)
- Returns true if the user is a member of the group and the group has been defined, otherwise false.
Checking for group membership is also a very simple thing to do in TrivialPermissions. However, we add one additional
check about simply seeing if groupName
is in the list of groups on the user: hasGroup()
returns false for groups
that have not been defined, regardless of is the user has that group name in their list of groups.
import tp from 'trivialperms';
// Setup
tp.loadGroups([
{
name: "Administrators",
permissions: [
"*/*"
]
},
{
name: "Authors",
permissions: [
"canViewPosts",
"canAddPosts",
"canEditPosts"
]
},
{
name: "Users",
permissions: [
"canViewPosts"
]
}
]);
// Define Users
const batman = {
name: 'batman',
groups: ['Administrators']
};
const stark = {
name: 'tstark',
permissions: ['*'],
groups: ['Users']
};
const leo = {
name: 'lblume',
groups: ['Users']
};
// Batman is an admin
console.log(tp.hasGroup(batman, 'Administrators')); // true
// Tony Start is not an admin
console.log(tp.hasGroup(stark, 'Administrators')); // false
// Leo is a user
console.log(tp.hasGroup(leo, 'Users')); // true