@samislam/permissions
v2.1.0
Published
permissions is a small and simple nodejs utility for controlling user actions permissions based on a predefined set of rules
Downloads
8
Maintainers
Readme
permissions is a small and simple Nodejs and Express utility for controlling user actions permissions based on a predefined set of rules.
Examples:
Example #1:
You can use it as an Express middleware:
app.get(
'/users/:id',
permissionsMw((req) => req.params.id === req.$loggedInUser.id, { denyMsg: 'You can only read your own data' }),
(req, res, next) => {
// ... rest of the code
}
)
Example #2:
or you can use it as a regular JavaScript function
app.get('/users/:id', async (req, res, next) => {
await permissions(() => req.params.id === req.$loggedInUser.id, { denyMsg: 'You can only read your own data' })
})
API:
The API is pretty simple and straightforward.
permissionsMw(permission: boolean | function, options: object | function)
: Express middleware
parameters:
- permission: boolean or function.
- If true was provided, it indicates grant permission, which calls
next()
. - If false was provided, it indicates permission denied , which marks the operation as access denied.
- If undefined or nothing was provided, the
defaultBehaviour
option determines what, (which is by default to deny access). - If a function was provided, it will be called with the
req
object as the first argument. Your function can return true, false or undefined, and the same behavior happens.
- If true was provided, it indicates grant permission, which calls
- options: object | function, options to configure how
permissionsMw()
works.- denyMsg: any, the message to include in the error in case the access denied happen, (default: 'You don't have the permission to perform this action').
- denyStatusCode: number, the status code to include in the error in case the access denied happen, (default 401).
- handlePermissionErr: boolean, by default, if access denied happen, permissionsMw sends the response to the client with a meaningful error, in case you wanted to handle that error yourself, change this option to false, and it will call
next()
with the error (default true). - defaultBehaviour: 'deny' | 'access', default behavior if not true or false were the resolved value of the
permission
argument (ex,permissionsMw(undefined)
) (default 'deny').
permissions(permission: boolean | function, options: object)
: Promise
parameters:
- permission: boolean or function.
- If true was provided, it indicates grant permission, which calls
next()
. - If false was provided, it indicates permission denied , which marks the operation as access denied.
- If undefined or nothing was provided, the
defaultBehaviour
option determines what, (which is by default to deny access). - If a function was provided, it will be called with the
req
object as the first argument. Your function can return true, false or undefined, and the same behavior happens.
- If true was provided, it indicates grant permission, which calls
- options: object, options to configure how
permissionsMw()
works.- denyMsg: any, the message to include in the error in case the access denied happen, (default: 'You don't have the permission to perform this action').
- denyStatusCode: number, the status code to include in the error in case the access denied happen, (default 401).
- defaultBehaviour: 'deny' | 'access', default behavior if not true or false were the resolved value of the
permission
argument (ex,permissionsMw(undefined)
) (default 'deny').
PermissionsMw
and Permissions
classes
These are the constructor classes for permissions() and permissionsMw() methods, you can use these classes to generate a set of methods with pre-defined options, and the best way to describe this process is by showing you an example:
const expressAsyncHandler = require('express-async-handler')
const { Permissions, PermissionsMw } = require('permissions')
const customPermissions = new Permissions({
notFoundMsg: 'Ľutujeme, ale požadovaný záznam sa nenašiel!',
}).method
const customPermissionsMw = new PermissionsMw({
notFoundMsg: 'Entschuldigung, aber der angeforderte Datensatz wurde nicht gefunden!',
}).method
app.get('/users', customPermissionsMw(false))
app.patch(
'/users',
expressAsyncHandler(async (req, res, next) => {
await customPermissions(false)
})
)
- All the constructors accept only one argument as an object, the options parameter.
- You can find the available options for each class in the API section above.
Error handling:
The only error that permissions trigger is the permissionsDenyError, this error includes the following properties:
name
: 'permissionsDenyError',statusCode
: the status code chosen when the deny access thing happen, (default 401)message
: (default: "You don't have the permission to perform this action")stack
: the error call stack.
To handle the error when it gets thrown, you can wrap the permissions calls with something like try/catch blocks, or use await-to, or you may do other logic, However you're must likely not going to handle the error through these ways, most likely you'll be having an express Middleware wrapper such as express-async-handler which calls next()
in case any error was thrown in the code it wraps, ex:
app.get(
expressAsyncHandler(async (req, res, next) => {
await permissions(() => {
/* some code */
if (true) return false
})
// the rest of your code
})
)
To handle the error which gets called by next, you should have an express error handling middleware which handles that, ex:
app.get(
'/users/:id',
permissionsMw((req) => false)
)
app.use((err, req, res, next) => {
if (err.name === 'permissionsDenyError') {
res.status(err.statusCode).json({
status: 'fail',
message: err.message,
})
}
})
FAQ:
Q: Can I make the access deny message an object or an array instead of a string?
- Yes you can, if you still need more flexibility, check out the handlePermissionErr option.