
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
universal-permissions
Advanced tools
Super easy to use javascript `can`-style permission management library. Not relying on prototypes — share same permissions across client and server.
Super easy to use javascript can-style permission management library. Not relying on prototypes — share same permissions across client and server.
/* permissions.js */
import Permissions from 'universal-permissons'
import * as definitions from './definitions'
export const { can, set, remove } = new Permissions(definitions);
Definitions can be passed inside an object to Permissions constructor, or/and can be set/removed dynamically.
For example, you can use a separate module with multiple exports, and then import it as shown above:
/* definitions.js */
export const post = {
edit: (viewer, post) => (
viewer.id === post.authorId
),
see: true
};
export const comment = {
edit: (viewer, comment) => (
viewer.id === comment.authorId && !comment.blocked
),
delete: comment.edit,
create: (viewer) => viewer.id
};
Here exported objects correspond to permission type, keys such as 'edit', 'delete', etc. correspond to permission action, and properties correspond to permission definition.
As you can see, definition can be of any type, but if it's a function, it will recieve viewer, and entity objects as params.
Make sure to always return something from functional definition, otherwise action will be always unpermitted.
For some reason, you may want to set/delete/replace definitions during runtime:
import { set, remove } from './permissions'
set('comment', 'like', (viewer) => viewer.id );
set('post', ['edit', 'delete'], (viewer, post) => (
viewer.id === post.authorId && !post.protected
)); // 'edit' replaced
remove('comment', 'create');
canThen anywhere you want, you can find out whether you can perform an action on given object calling can:
import { can } from './permissions'
const viewer = { id: 1 };
const comment = { authorId: 1, text: 'Hello' };
can(viewer, 'edit', { comment }) // true
can({ id: 2 }, 'edit', { comment }) // false
can(null, 'create', 'comment') // false
can(viewer, 'create', 'comment') // true
Last argument can be an object of shape { type: entity } or a string, representing type. It is your responsibility to pass proper entity to functional definitions. For example, this will, of course, return false for definitions defined above:
const viewer = { id: 1 };
const post = { authorId: 1 };
can(viewer, 'edit', 'post') // false
can(viewer, 'edit', post) // will throw because of
// unknown type 'authorId'
can exampleNot the best style of doing things, but you can get the idea:
import { can } from './permissions'
import store from './store'
const { viewer } = store;
fetch('/api/comment/2')
.then(res => res.json())
.then(comment => {
comment.editable = can(viewer, 'edit', { comment })
comment.deletable = can(viewer, 'delete', { comment })
})
can exampleOne can imagine such Express setup:
import express from 'express';
import Comment from './models/User'
import { can } from './permissions'
let app = express();
/* Here should be used some auth middleware,
* providing req.user, ex. passport */
const getComment = ({ params: id }, res, next) => {
Comment.findById(id)
.then(comment => {
req.comment = comment;
next();
})
.catch(error => next(error));
};
const ifCan = (action, type) => {
return (req, res, next) => {
if (can(req.user, action, { type: req[type] })) {
return next();
}
res.status(403).end('Forbidden');
}
}
/* We update only if we CAN, otherwise we see an error */
app.get('/api/comment/:id/edit',
getComment,
ifCan('edit', 'post'),
({ body }, res, next) => {
Post
.update(body)
.then(post => res.json(post))
.catch(error => next(error))
;
});
Coming soon.
MIT license, you are welcome.
FAQs
Super easy to use javascript `can`-style permission management library. Not relying on prototypes — share same permissions across client and server.
We found that universal-permissions demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.