Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions lib/acl-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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#')
Expand Down Expand Up @@ -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
Expand Down
44 changes: 1 addition & 43 deletions lib/handlers/allow.js
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down Expand Up @@ -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
Expand All @@ -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
}
}
8 changes: 8 additions & 0 deletions lib/ldp.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down