fastify-casbin-rest
Advanced tools
Comparing version 1.1.1 to 1.2.0
{ | ||
"name": "fastify-casbin-rest", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "Plugin for fastify to add support for Casbin REST model", | ||
@@ -41,12 +41,12 @@ "main": "plugin.js", | ||
"devDependencies": { | ||
"@types/node": "^14.14.6", | ||
"fastify": "^3.7.0", | ||
"@types/node": "^14.14.21", | ||
"fastify": "^3.10.1", | ||
"pre-commit": "^1.2.2", | ||
"sinon": "^9.2.1", | ||
"sinon": "^9.2.3", | ||
"snazzy": "^9.0.0", | ||
"standard": "^16.0.1", | ||
"tap": "^14.10.8", | ||
"tsd": "^0.13.1", | ||
"typescript": "^4.0.5" | ||
"standard": "^16.0.3", | ||
"tap": "^14.11.0", | ||
"tsd": "^0.14.0", | ||
"typescript": "^4.1.3" | ||
} | ||
} |
/// <reference types="node" /> | ||
import { FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify' | ||
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify' | ||
@@ -9,5 +9,5 @@ declare module 'fastify' { | ||
rest?: boolean | { | ||
getSub?: (request: FastifyRequest) => string, | ||
getObj?: (request: FastifyRequest) => string, | ||
getAct?: (request: FastifyRequest) => string | ||
getSub?: ((request: FastifyRequest) => string) | string, | ||
getObj?: ((request: FastifyRequest) => string) | string, | ||
getAct?: ((request: FastifyRequest) => string) | string | ||
} | ||
@@ -29,2 +29,3 @@ } | ||
onDeny?(reply: FastifyReply, sub: string, obj: string, act: string): void | ||
log?(fastify: FastifyInstance, request: FastifyRequest, sub: string, obj: string, act: string): void | ||
hook?: Hook | ||
@@ -31,0 +32,0 @@ } |
@@ -13,2 +13,3 @@ 'use strict' | ||
}, | ||
log: (fastify, request, sub, obj, act) => { fastify.log.info({ sub, obj, act }, 'Invoking casbin enforce') }, | ||
hook: 'preHandler' | ||
@@ -19,2 +20,3 @@ } | ||
options = { ...defaultOptions, ...options } | ||
const { log } = options | ||
@@ -35,5 +37,5 @@ fastify.addHook('onRoute', routeOptions => { | ||
const getSub = routeOptions.casbin.rest.getSub || options.getSub | ||
const getObj = routeOptions.casbin.rest.getObj || options.getObj | ||
const getAct = routeOptions.casbin.rest.getAct || options.getAct | ||
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) | ||
@@ -45,4 +47,3 @@ routeOptions[hook].push(async (request, reply) => { | ||
fastify.log.info({ sub, obj, act }, 'Invoking casbin enforce') | ||
log(fastify, request, sub, obj, act) | ||
if (!(await fastify.casbin.enforce(sub, obj, act))) { | ||
@@ -56,2 +57,16 @@ await options.onDeny(reply, sub, 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, { | ||
@@ -58,0 +73,0 @@ name: 'fastify-casbin-rest', |
@@ -47,7 +47,7 @@ # fastify-casbin-rest | ||
| Option | Type | Description | Default | | ||
| -------- | ------------------- | -------------------------------- | --------------------------- | | ||
| `getSub` | `Request => string` | Extracts `sub` from the request | Value from plugin options | | ||
| `getObj` | `Request => string` | Extracts `obj` from the request | Value from plugin options | | ||
| `getAct` | `Request => string` | Extracts `act` from the request | Value from plugin options | | ||
| Option | Type | Description | Default | | ||
| -------- | ------------------------------- | -------------------------------------------- | --------------------------- | | ||
| `getSub` | `Request => string` or `string` | Extracts `sub` from the request or constant | Value from plugin options | | ||
| `getObj` | `Request => string` or `string` | Extracts `obj` from the request or constant | Value from plugin options | | ||
| `getAct` | `Request => string` or `string` | Extracts `act` from the request or constant | Value from plugin options | | ||
@@ -64,2 +64,3 @@ ### Plugin options | ||
| `onDeny` | `(Reply, sub, obj, act) => any` | Invoked when Casbin's `enforce` resolves to false | Returns a `403 Forbidden` error | | ||
| `log` | `(Fastify, Request, sub, obj, act => void` | Invoked before invoking Casbin's `enforce` | Logs using fastify.log.info | | ||
| `hook` | `'onRequest', 'preParsing', 'preValidation', 'preHandler'` | Which lifecycle to use for performing the check | `'preHandler'` | | ||
@@ -117,3 +118,4 @@ | ||
rest: { | ||
getObj: request => request.userId | ||
getSub: request => request.userId, | ||
getAct: 'read' | ||
}, | ||
@@ -120,0 +122,0 @@ } |
@@ -35,3 +35,3 @@ 'use strict' | ||
fastify.ready(err => { | ||
t.is(err.message, "The decorator 'casbin' is not present in Fastify") | ||
t.is(err.message, "The decorator 'casbin' required by 'fastify-casbin-rest' is not present in Fastify") | ||
@@ -209,2 +209,33 @@ fastify.close() | ||
test('supports specifying custom logger', t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
fastify.register(makeStubCasbin()) | ||
fastify.register(plugin, { | ||
log: (fastify, request, sub, obj, act) => { | ||
t.equal(sub, 'a') | ||
t.equal(obj, 'b') | ||
t.equal(act, 'c') | ||
}, | ||
getSub: _request => 'a', | ||
getObj: _request => 'b', | ||
getAct: _request => 'c' | ||
}) | ||
fastify.get('/', { | ||
casbin: { rest: true } | ||
}, () => 'ok') | ||
fastify.ready(async err => { | ||
t.error(err) | ||
fastify.casbin.enforce.resolves(true) | ||
t.equal((await fastify.inject('/')).statusCode, 200) | ||
fastify.close() | ||
}) | ||
}) | ||
test('supports overriding plugin rules on route level', t => { | ||
@@ -247,1 +278,39 @@ t.plan(4) | ||
}) | ||
test('supports passing constants as extractor params', t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
fastify.register(makeStubCasbin()) | ||
fastify.register(plugin, { | ||
hook: 'onRequest', | ||
getSub: request => request.user, | ||
getObj: request => request.url, | ||
getAct: request => request.method | ||
}) | ||
fastify.get('/', { | ||
casbin: { | ||
rest: { | ||
getSub: 'a', | ||
getObj: 'b', | ||
getAct: 'c' | ||
} | ||
} | ||
}, () => 'ok') | ||
fastify.ready(async err => { | ||
t.error(err) | ||
fastify.casbin.enforce.callsFake((sub, obj, act) => { | ||
t.equal(sub, 'a') | ||
t.equal(obj, 'b') | ||
t.equal(act, 'c') | ||
return Promise.resolve(false) | ||
}) | ||
await fastify.inject('/') | ||
fastify.close() | ||
}) | ||
}) |
@@ -10,2 +10,3 @@ import fastify, { FastifyReply, FastifyRequest } from 'fastify' | ||
server.register(casbinRest, { | ||
log: (fastify, request, sub, obj, act) => { fastify.log.info({ sub, obj, act }, 'Invoking casbin enforce') }, | ||
onDeny: (reply, sub, obj, act) => { | ||
@@ -40,1 +41,11 @@ expectType<FastifyReply>(reply) | ||
}, () => Promise.resolve('ok')) | ||
server.get('/entity', { | ||
casbin: { | ||
rest: { | ||
getSub: '1', | ||
getObj: 'entity', | ||
getAct: 'read' | ||
} | ||
} | ||
}, () => Promise.resolve('ok')) |
18695
364
128