pwix:permissions
What is it ?
A Meteor package which provides the thinnest Javascript permissions manager.
Rationale
An application, or at least the applications I use to write, typically use the alanning:roles
roles, which I find practical to extend in pwix:roles
package.
But a bunch of permissions are actually involved into applications which would be a minimal itself involved in security management: permission to run such or sunch method on such or such object, permission to subscribe to a publication with such and sunch arguments, and so on.
This may be rather complex, and, even if you are using roles in your application, you may not always want use these roles to manages which can be called technical permissions.
This package tries to provide an extensible interface to let:
-
other packages provide suggested permissions
-
application centralyze all code to compute the permissions.
Basically, all permissions managed here are defined by a single string which is expected to identify the to-be-run task, a user on behalf the task will be executed, and, maybe some additional arguments.
The question is rather simple: this user is he/she allowed to do this task (with these arguments) ? And the answer is given by our allow function.
Installation
As simple as:
meteor add pwix:permissions
Usage
When this package is added to your application, it provides a Permissions.isAllowed()
function which defaults to always return true
.
Your application, or your calling packages, should define for each task the computing function by calling Permissions.set()
function.
Example:
1 Permissions.set( 'my_task', ( userId ) => async { 2 return userId !== null; 3 });
or:
1 Permissions.set({ 2 async my_first_task( userId ){ 3 return userId !== null; 4 }, 5 async my_second_task( userId, arg ){ 6 return userId !== null && await isSuitable( arg ); 7 } 8 });
Then the compatible callers just have to do:
1 const allowed = await Permissions.isAllowed( 'my_task', this.userId );
What does it provide ?
Permissions
The globally exported object.
Functions
Permissions.configure( o<Object> )
See below
Permissions.isAllowed( task, userId, ... )
An async function which returns true
if the userId
is allowed to execute the given task
.
When not provided, the userId
defaults to current logged-in user on the client side. No default is provided on the server side.
All arguments are transmitted to the final function.
Hint: pass your additional arguments as a single object.
Permissions.set( task, async fn<Function> )
Permissions.set( o<Object> )
Feeds the task referentiel with a task and its allow function, or with a list of tasks and their allowed functions.
The prototype of allow functions is:
1 async allowFunction( userId<String|Object>, ... ): <Boolean>
All calls to Permissions.set()
are cumulative.
Task naming and tasks namespace
At the application level, all tasks share the same single namespace.
You - as a code writer - should name your tasks so that you do not risk a name collision between your packages and your application.
As a writing facility, this package considers that dot.named tasks are organized as hierachical objects, so that allow functions for the my.task.first
and my.task.second
tasks can be set as:
1 Permissions.set({ 2 my: { 3 task: { 4 async first( userId ){ 5 return userId !== null; 6 }, 7 async second( userId, arg ){ 8 return userId !== null && await isSuitable( arg ); 9 } 10 } 11 } 12 });
as well as:
1 Permissions.set({ 2 async 'my.task.first'( userId ){ 3 return userId !== null; 4 }, 5 async 'my.task.second'( userId ){ 6 return userId !== null && await isSuitable( arg ); 7 } 8 });
Configuration
The package's behavior can be configured through a call to the Permissions.configure()
method, with just a single javascript object argument, which itself should only contains the options you want override.
Known configuration options are:
-
allowedIfTaskNotFound
How to answer to an allowed request if the task is not found in our referentiel, defaulting to
true
. -
verbosity
The verbosity level as:
Permissions.C.Verbose.NONE
or an OR-ed value of integer constants:
-
Permissions.C.Verbose.CONFIGURE
Trace configuration operations
-
Permissions.C.Verbose.ALLOWED
Trace allowed results
-
Permissions.C.Verbose.NOT_ALLOWED
Trace not allowed results
Defaults to
Permissions.C.Verbose.CONFIGURE
. -
warnIfTaskNotFound
Whether to emit a console warning if the task is not found in our referentiel, defaulting to
true
.
Remind too that Meteor packages are instanciated at application level. They are so only configurable once, or, in other words, only one instance has to be or can be configured. Addtionnal calls to Permissions.configure()
will just override the previous one. You have been warned: only the application should configure a package.
NPM peer dependencies
Starting with v 1.0.0, and in accordance with advices from the Meteor Guide, we no more hardcode NPM dependencies in the Npm.depends
clause of the package.js
.
Instead we check npm versions of installed packages at runtime, on server startup, in development environment.
Dependencies as of v 1.0.0:
'lodash': '^4.17.0'
Each of these dependencies should be installed at application level:
meteor npm install <package> --save
Translations
None at the moment.
Cookies and comparable technologies
None at the moment.
P. Wieser
- Last updated on 2024, Oct. 4th