From bef021d0b029b82e03be0f8b940e33658dad6a69 Mon Sep 17 00:00:00 2001 From: tpluscode Date: Sun, 20 Jun 2021 21:45:27 +0200 Subject: [PATCH] fix(hydra-box): missing req param --- .changeset/sharp-eggs-invent.md | 5 +++++ .../hydra-box-web-access-control/index.ts | 18 ++++++++++++++--- .../test/index.test.ts | 4 ++-- readme.md | 20 ++++++++++++++++++- 4 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 .changeset/sharp-eggs-invent.md diff --git a/.changeset/sharp-eggs-invent.md b/.changeset/sharp-eggs-invent.md new file mode 100644 index 0000000..6d27fba --- /dev/null +++ b/.changeset/sharp-eggs-invent.md @@ -0,0 +1,5 @@ +--- +"hydra-box-web-access-control": patch +------------------------------------- + +Add express `Request` as second parameter to custom patterns diff --git a/packages/hydra-box-web-access-control/index.ts b/packages/hydra-box-web-access-control/index.ts index fd1c3d5..587bbee 100644 --- a/packages/hydra-box-web-access-control/index.ts +++ b/packages/hydra-box-web-access-control/index.ts @@ -3,10 +3,22 @@ import error from 'http-errors' import type { StreamClient } from 'sparql-http-client/StreamClient' import type * as express from 'express' import { acl } from '@tpluscode/rdf-ns-builders' -import { check, Check } from 'rdf-web-access-control' +import { check, AdditionalPatterns } from 'rdf-web-access-control' +import { Variable } from '@rdfjs/types' +import type { SparqlTemplateResult } from '@tpluscode/sparql-builder' -interface Option extends Pick { +export interface AclPatterns { + (acl:Variable, req: express.Request): SparqlTemplateResult | string +} + +interface Option { client: StreamClient + additionalPatterns?: AclPatterns | AclPatterns[] +} + +function wrapPatterns(patterns: Option['additionalPatterns'] = [], req: express.Request): AdditionalPatterns[] { + const arr = Array.isArray(patterns) ? patterns : [patterns] + return arr.map(func => acl => func(acl, req)) } export default ({ client, additionalPatterns }: Option): express.RequestHandler => asyncMiddleware(async (req, res, next) => { @@ -41,7 +53,7 @@ export default ({ client, additionalPatterns }: Option): express.RequestHandler accessMode, client, agent: req.agent, - additionalPatterns, + additionalPatterns: wrapPatterns(additionalPatterns, req), }) if (!result) { diff --git a/packages/hydra-box-web-access-control/test/index.test.ts b/packages/hydra-box-web-access-control/test/index.test.ts index b481ce5..e2b307e 100644 --- a/packages/hydra-box-web-access-control/test/index.test.ts +++ b/packages/hydra-box-web-access-control/test/index.test.ts @@ -36,7 +36,7 @@ describe('hydra-box-web-access-control', () => { it('passes right parameters to check', async () => { // given - const additionalPatterns = () => '' + const additionalPatterns = sinon.stub() const agent = clownface({ dataset: $rdf.dataset() }).namedNode('') app.use((req, res, next) => { req.agent = agent @@ -55,7 +55,7 @@ describe('hydra-box-web-access-control', () => { client, agent, term, - additionalPatterns, + additionalPatterns: sinon.match.array, })) }) diff --git a/readme.md b/readme.md index c596aea..10a5104 100644 --- a/readme.md +++ b/readme.md @@ -89,6 +89,24 @@ app.use(hydraBox.middleware(api, { })) ``` +### Per-request authorization restrictions + +A function of array of functions can be optionally passed to the middleware. They take an RDF/JS variable, and the current request object as parameters and should return additional SPARQL patterns to filter out ACL authorization resources as desired. + +```typescript +import accessControl from 'hydra-box-web-access-control' +import { Variable } from '@rdfjs/types' +import { Request } from 'express' + +const middleware = accessControl({ + client, + additionalPatterns(acl: Variable, req: Request) { + // ... + } + }) +``` + +See [below](#additional-authorization-restrictions) for a complete example. The only difference is that the `hydra-box-web-access-control` adds the second parameter while the other accepts only one. ## rdf-web-access-control @@ -164,7 +182,7 @@ All queries will implicitly add `rdfs:Resource` to the queries types. Given a st It is possible to restrict considered instances of `acl:Authorization`, for example to select only ACLs valid for given timeframe or by a custom property. -To do that, pass a function to the `check` call, which will return partial SPARQL patterns. It takes an RDF/JS Variable object as input which will match the ACL resources in the query, +To do that, pass a function to the `check` call, which will return partial SPARQL patterns. It takes an RDF/JS Variable object as input which will match the ACL resources in the query. ```typescript import { Variable } from '@rdfjs/types'