From b0596c97f54129a3a317f6253a0946bf00de628d Mon Sep 17 00:00:00 2001 From: Arne Hassel Date: Tue, 29 Jan 2019 16:10:58 +0100 Subject: [PATCH] Moving the creation of ACLChechker into a factory method This is a solution that is used in both https://github.com/solid/node-solid-server/tree/feature/quota-ui and https://github.com/solid/node-solid-server/tree/bug/root-index-special-handling --- lib/acl-checker.js | 45 +++++++++++++++++++++++++++++++++++++++++++ lib/handlers/allow.js | 44 +----------------------------------------- lib/ldp.js | 8 ++++++++ 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/lib/acl-checker.js b/lib/acl-checker.js index ece53a64d..6e15a0d00 100644 --- a/lib/acl-checker.js +++ b/lib/acl-checker.js @@ -5,6 +5,8 @@ const debug = require('./debug').ACL const HTTPError = require('./http-error') const aclCheck = require('@solid/acl-check') const { URL } = require('url') +const { promisify } = require('util') +const fs = require('fs') const DEFAULT_ACL_SUFFIX = '.acl' const ACL = rdf.Namespace('http://www.w3.org/ns/auth/acl#') @@ -144,6 +146,49 @@ class ACLChecker { isAcl (resource) { return resource.endsWith(this.suffix) } + + static createFromLDPAndRequest (resource, ldp, req) { + const trustedOrigins = ldp.getTrustedOrigins(req) + return new ACLChecker(resource, { + agentOrigin: req.get('origin'), + // host: req.get('host'), + fetch: fetchFromLdp(ldp.resourceMapper), + fetchGraph: (uri, options) => { + // first try loading from local fs + return ldp.getGraph(uri, options.contentType) + // failing that, fetch remote graph + .catch(() => ldp.fetchGraph(uri, options)) + }, + suffix: ldp.suffixAcl, + strictOrigin: ldp.strictOrigin, + trustedOrigins + }) + } +} + +/** + * Returns a fetch document handler used by the ACLChecker to fetch .acl + * resources up the inheritance chain. + * The `fetch(uri, callback)` results in the callback, with either: + * - `callback(err, graph)` if any error is encountered, or + * - `callback(null, graph)` with the parsed RDF graph of the fetched resource + * @return {Function} Returns a `fetch(uri, callback)` handler + */ +function fetchFromLdp (mapper) { + return async function fetch (url, graph = rdf.graph()) { + // Convert the URL into a filename + let path, contentType + try { + ({ path, contentType } = await mapper.mapUrlToFile({ url })) + } catch (err) { + throw new HTTPError(404, err) + } + // Read the file from disk + const body = await promisify(fs.readFile)(path, { 'encoding': 'utf8' }) + // Parse the file as Turtle + rdf.parse(body, graph, url, contentType) + return graph + } } // Returns the index of the last slash before the given position diff --git a/lib/handlers/allow.js b/lib/handlers/allow.js index 756f48554..b18c2e0a7 100644 --- a/lib/handlers/allow.js +++ b/lib/handlers/allow.js @@ -1,12 +1,8 @@ module.exports = allow -const $rdf = require('rdflib') const path = require('path') const ACL = require('../acl-checker') const debug = require('../debug.js').ACL -const fs = require('fs') -const { promisify } = require('util') -const HTTPError = require('../http-error') function allow (mode, checkPermissionsForDirectory) { return async function allowHandler (req, res, next) { @@ -48,20 +44,7 @@ function allow (mode, checkPermissionsForDirectory) { trustedOrigins.push(ldp.serverUri) } // Obtain and store the ACL of the requested resource - req.acl = new ACL(rootUrl + resourcePath, { - agentOrigin: req.get('origin'), - // host: req.get('host'), - fetch: fetchFromLdp(ldp.resourceMapper), - fetchGraph: (uri, options) => { - // first try loading from local fs - return ldp.getGraph(uri, options.contentType) - // failing that, fetch remote graph - .catch(() => ldp.fetchGraph(uri, options)) - }, - suffix: ldp.suffixAcl, - strictOrigin: ldp.strictOrigin, - trustedOrigins: trustedOrigins - }) + req.acl = ACL.createFromLDPAndRequest(rootUrl + resourcePath, ldp, req) // Ensure the user has the required permission const userId = req.session.userId @@ -74,28 +57,3 @@ function allow (mode, checkPermissionsForDirectory) { next(error) } } - -/** - * Returns a fetch document handler used by the ACLChecker to fetch .acl - * resources up the inheritance chain. - * The `fetch(uri, callback)` results in the callback, with either: - * - `callback(err, graph)` if any error is encountered, or - * - `callback(null, graph)` with the parsed RDF graph of the fetched resource - * @return {Function} Returns a `fetch(uri, callback)` handler - */ -function fetchFromLdp (mapper) { - return async function fetch (url, graph = $rdf.graph()) { - // Convert the URL into a filename - let path, contentType - try { - ({ path, contentType } = await mapper.mapUrlToFile({ url })) - } catch (err) { - throw new HTTPError(404, err) - } - // Read the file from disk - const body = await promisify(fs.readFile)(path, {'encoding': 'utf8'}) - // Parse the file as Turtle - $rdf.parse(body, graph, url, contentType) - return graph - } -} diff --git a/lib/ldp.js b/lib/ldp.js index 85ba7bdad..db7c6d38e 100644 --- a/lib/ldp.js +++ b/lib/ldp.js @@ -464,6 +464,14 @@ class LDP { return ensureNotExists(this, URI.joinPaths(containerURI, filename).toString()) } + getTrustedOrigins (req) { + let trustedOrigins = [this.resourceMapper.resolveUrl(req.hostname)].concat(this.trustedOrigins) + if (this.multiuser) { + trustedOrigins.push(this.serverUri) + } + return trustedOrigins + } + static mimeTypeIsRdf (mimeType) { return RDF_MIME_TYPES.has(mimeType) }