-
Notifications
You must be signed in to change notification settings - Fork 3
/
plugin.js
81 lines (69 loc) · 2.51 KB
/
plugin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
'use strict'
const fp = require('fastify-plugin')
const { Forbidden } = require('http-errors')
const defaultOptions = {
getSub: request => request.user,
getObj: request => request.url,
getAct: request => request.method,
onDeny: (reply, { sub, obj, act, dom }) => {
throw new Forbidden(`${sub} not allowed to ${act} ${dom ? dom + ' ' : ''}${obj}`)
},
log: (fastify, request, permission) => { request.log.info(permission, 'Invoking casbin enforce') },
hook: 'preHandler'
}
async function fastifyCasbinRest (fastify, options) {
options = { ...defaultOptions, ...options }
const { log } = options
fastify.addHook('onRoute', routeOptions => {
// add option to turn it on for all routes
// rest value will depend on the value of that option
// fastify-swagger for an example
// i.e. enforceForAllRoutes
if (routeOptions.casbin && routeOptions.casbin.rest) {
const { hook } = options
if (!routeOptions[hook]) {
routeOptions[hook] = []
}
if (!Array.isArray(routeOptions[hook])) {
routeOptions[hook] = [routeOptions[hook]]
}
const getSub = resolveParameterExtractor(routeOptions.casbin.rest.getSub, options.getSub)
const getObj = resolveParameterExtractor(routeOptions.casbin.rest.getObj, options.getObj)
const getAct = resolveParameterExtractor(routeOptions.casbin.rest.getAct, options.getAct)
const getDom = resolveParameterExtractor(routeOptions.casbin.rest.getDom, options.getDom)
routeOptions[hook].push(async (request, reply) => {
const sub = getSub(request)
const obj = getObj(request)
const act = getAct(request)
const dom = getDom ? getDom(request) : undefined
log(fastify, request, { sub, dom, obj, act })
const isAuthorized = getDom ? await fastify.casbin.enforce(sub, dom, obj, act) : await fastify.casbin.enforce(sub, obj, act)
if (!isAuthorized) {
return await options.onDeny(reply, { sub, dom, obj, act })
}
if (options.onAllow) {
await options.onAllow(reply, { sub, dom, obj, act })
}
})
}
})
}
function isString (value) {
return typeof value === 'string'
}
function resolveParameterExtractor (routeOption, pluginOption) {
if (routeOption) {
if (isString(routeOption)) {
return () => routeOption
}
return routeOption
}
return pluginOption
}
module.exports = fp(fastifyCasbinRest, {
name: 'fastify-casbin-rest',
decorators: {
fastify: ['casbin']
},
dependencies: ['fastify-casbin']
})