1 | const util = require('util')
|
2 | const get = require('lodash.get')
|
3 |
|
4 | const UnauthorizedError = require('./error')
|
5 | const PermissionError = new UnauthorizedError(
|
6 | 'permission_denied', { message: 'Permission denied' }
|
7 | )
|
8 |
|
9 | const Guard = function (options) {
|
10 | const defaults = {
|
11 | requestProperty: 'user',
|
12 | permissionsProperty: 'permissions'
|
13 | }
|
14 |
|
15 | this._options = Object.assign({}, defaults, options)
|
16 | }
|
17 |
|
18 | function isString (value) {
|
19 | return typeof value === 'string'
|
20 | }
|
21 |
|
22 | function isArray (value) {
|
23 | return value instanceof Array
|
24 | }
|
25 |
|
26 | Guard.prototype = {
|
27 |
|
28 | check: function (required) {
|
29 | if (isString(required)) {
|
30 | required = [[required]]
|
31 | } else if (isArray(required) && required.every(isString)) {
|
32 | required = [required]
|
33 | }
|
34 |
|
35 | const _middleware = function _middleware (req, res, next) {
|
36 | const self = this
|
37 | const options = self._options
|
38 |
|
39 | if (!options.requestProperty) {
|
40 | return next(new UnauthorizedError('request_property_undefined', {
|
41 | message: 'requestProperty hasn\'t been defined. Check your configuration.'
|
42 | }))
|
43 | }
|
44 |
|
45 | const user = get(req, options.requestProperty, undefined)
|
46 | if (!user) {
|
47 | return next(new UnauthorizedError('user_object_not_found', {
|
48 | message: util.format('user object "%s" was not found. Check your configuration.', options.requestProperty)
|
49 | }))
|
50 | }
|
51 |
|
52 | let permissions = get(user, options.permissionsProperty, undefined)
|
53 | if (!permissions) {
|
54 | return next(new UnauthorizedError('permissions_not_found', {
|
55 | message: 'Could not find permissions for user. Bad configuration?'
|
56 | }))
|
57 | }
|
58 |
|
59 | if (typeof permissions === 'string') {
|
60 | permissions = permissions.split(' ')
|
61 | }
|
62 |
|
63 | if (!Array.isArray(permissions)) {
|
64 | return next(new UnauthorizedError('permissions_invalid', {
|
65 | message: 'Permissions should be an Array or String. Bad format?'
|
66 | }))
|
67 | }
|
68 |
|
69 | const sufficient = required.some(function (required) {
|
70 | return required.every(function (permission) {
|
71 | return permissions.indexOf(permission) !== -1
|
72 | })
|
73 | })
|
74 |
|
75 | next(!sufficient ? PermissionError : null)
|
76 | }.bind(this)
|
77 |
|
78 | _middleware.unless = require('express-unless')
|
79 |
|
80 | return _middleware
|
81 | }
|
82 | }
|
83 |
|
84 | module.exports = function (options) {
|
85 | return new Guard(options)
|
86 | }
|