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
48 changes: 29 additions & 19 deletions lib/acl.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ ACL.prototype.can = function (user, mode, resource, callback, options) {
})
}

ACL.prototype.findAgentClass = function (graph, user, mode, resource, acl, callback) {
ACL.prototype.findAgentClass = function (graph, user, mode, resource, acl,
callback) {
var self = this

// Agent class statement
Expand All @@ -131,7 +132,8 @@ ACL.prototype.findAgentClass = function (graph, user, mode, resource, acl, callb
}, callback)
}

ACL.prototype.findRule = function (graph, user, mode, resource, accessType, acl, callback, options) {
ACL.prototype.findRule = function (graph, user, mode, resource, accessType, acl,
callback, options) {
var self = this

// TODO check if this is necessary
Expand All @@ -155,7 +157,8 @@ ACL.prototype.findRule = function (graph, user, mode, resource, accessType, acl,
var statementSubject = statement.subject.uri

// Check for origin
var matchOrigin = self.matchOrigin(graph, statementSubject, options.origin, options.host)
var matchOrigin = self.matchOrigin(graph, statementSubject,
options.origin, options.host)
if (!matchOrigin) {
debug('The request does not match the origin')
return done(false)
Expand All @@ -164,7 +167,8 @@ ACL.prototype.findRule = function (graph, user, mode, resource, accessType, acl,
// Check for accessTo/defaultForNew
if (!self.isAcl(resource) || accessType === 'defaultForNew') {
debug('Checking for accessType:' + accessType)
var accesses = self.matchAccessType(graph, statementSubject, accessType, resource)
var accesses = self.matchAccessType(graph, statementSubject, accessType,
resource)
if (!accesses) {
debug('Cannot find accessType ' + accessType)
return done(false)
Expand All @@ -189,7 +193,8 @@ ACL.prototype.findRule = function (graph, user, mode, resource, accessType, acl,

debug('Inspect agentClass')
// Check for AgentClass
return self.findAgentClass(graph, user, mode, resource, statementSubject, done)
return self.findAgentClass(graph, user, mode, resource, statementSubject,
done)
},
function (found) {
if (!found) {
Expand All @@ -209,7 +214,8 @@ ACL.prototype.getMode = function getMode (graph, mode) {
'http://www.w3.org/ns/auth/acl#' + mode)
}

ACL.prototype.matchAccessType = function matchAccessType (graph, rule, accessType, uri) {
ACL.prototype.matchAccessType = function matchAccessType (graph, rule,
accessType, uri) {
var self = this
var matches = self.match(
graph,
Expand Down Expand Up @@ -250,7 +256,8 @@ function possibleACLs (uri, suffix) {
var first = S(uri).endsWith(suffix) ? uri : uri + suffix
var urls = [first]
var parsedUri = url.parse(uri)
var baseUrl = (parsedUri.protocol ? parsedUri.protocol + '//' : '') + (parsedUri.host || '')
var baseUrl = (parsedUri.protocol ? parsedUri.protocol + '//' : '') +
(parsedUri.host || '')
if (baseUrl + '/' === uri) {
return urls
}
Expand Down Expand Up @@ -301,18 +308,19 @@ function getUserId (req, callback) {
}

var delegator = rdfVocab.debrack(onBehalfOf)
verifyDelegator(req.hostname, delegator, req.session.userId, function (err, res) {
if (err) {
err.status = 500
return callback(err)
}
verifyDelegator(req.hostname, delegator, req.session.userId,
function (err, res) {
if (err) {
err.status = 500
return callback(err)
}

if (res) {
debug('Request User ID (delegation) :' + delegator)
return callback(null, delegator)
}
return callback(null, req.session.userId)
})
if (res) {
debug('Request User ID (delegation) :' + delegator)
return callback(null, delegator)
}
return callback(null, req.session.userId)
})
}

function verifyDelegator (host, ldp, baseUri, delegator, delegatee, callback) {
Expand Down Expand Up @@ -365,7 +373,9 @@ function allow (mode) {
getUserId(req, function (err, userId) {
if (err) return next(err)

var reqPath = res && res.locals && res.locals.path ? res.locals.path : req.path
var reqPath = res && res.locals && res.locals.path
? res.locals.path
: req.path
ldp.exists(req.hostname, reqPath, function (err, stat) {
if (reqPath[reqPath.length - 1] !== '/' &&
!err &&
Expand Down
66 changes: 36 additions & 30 deletions lib/identity-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ IdentityProvider.prototype.create = function (options, cert, callback) {
graphs.push(self.putGraph(options.preferences, createPreferences(options)))
}
if (options.inbox) {
graphs.push(self.putGraph(options.inbox + self.suffixAcl, createInboxAcl(options)))
graphs.push(self.putGraph(options.inbox + self.suffixAcl,
createInboxAcl(options)))
}
if (options.defaultContainers && options.defaultContainers.length > 0) {
throw new Error('default containers is not supported yet')
Expand Down Expand Up @@ -382,10 +383,12 @@ IdentityProvider.prototype.get = function (req, res, next) {
if (err && err.status === 404) {
// TODO maybe a personalized page
// or a redirect
debug('Account on ' + req.hostname + ' is available from ' + req.originalUrl)
debug('Account on ' + req.hostname + ' is available from ' +
req.originalUrl)
return res.sendStatus(404)
} else {
debug('Account on ' + req.hostname + ' is not available ' + req.originalUrl)
debug('Account on ' + req.hostname + ' is not available ' +
req.originalUrl)
return next()
}
})
Expand All @@ -410,7 +413,8 @@ IdentityProvider.prototype.newCert = function (req, res, next) {
debug('Requesting new cert for ' + options.webid)

if (req.session.userId !== options.webid) {
debug('user is not logged in: ' + req.session.userId + ' is not ' + options.webid)
debug('user is not logged in: ' + req.session.userId + ' is not ' +
options.webid)
var error = new Error('You are not logged in, so you can\'t create a certificate')
error.status = 401
return next(error)
Expand All @@ -423,7 +427,8 @@ IdentityProvider.prototype.newCert = function (req, res, next) {
// Get a new cert
webid('tls').generate({
spkac: spkac,
commonName: options.name + ' [on ' + options.host + ' created at ' + options.date.toDateString() + ']',
commonName: options.name + ' [on ' + options.host + ' created at ' +
options.date.toDateString() + ']',
issuer: { commonName: options.host },
duration: 10,
agent: options.webid
Expand Down Expand Up @@ -465,32 +470,33 @@ IdentityProvider.prototype.getGraph = function (uri, callback) {
var hostname = parsed.hostname
var reqPath = parsed.path

self.store.get(hostname, reqPath, null, true, 'text/turtle', function (err, stream) {
if (err) {
debug('Cannot find WebID card')
var notexists = new Error('Cannot find WebID card')
notexists.status = 500
return callback(notexists)
}
var data = ''
stream
.on('data', function (chunk) {
data += chunk
})
.on('end', function () {
// TODO make sure that uri is correct
parse(data, uri, 'text/turtle', function (err, card) {
if (err) {
debug('WebId can\'t be parsed: ' + err.message)
var invalid = new Error('You have an invalid WebID card')
invalid.status = 500
return callback(invalid)
}

return callback(null, card)
self.store.get(hostname, reqPath, null, true, 'text/turtle',
function (err, stream) {
if (err) {
debug('Cannot find WebID card')
var notexists = new Error('Cannot find WebID card')
notexists.status = 500
return callback(notexists)
}
var data = ''
stream
.on('data', function (chunk) {
data += chunk
})
})
})
.on('end', function () {
// TODO make sure that uri is correct
parse(data, uri, 'text/turtle', function (err, card) {
if (err) {
debug('WebId can\'t be parsed: ' + err.message)
var invalid = new Error('You have an invalid WebID card')
invalid.status = 500
return callback(invalid)
}

return callback(null, card)
})
})
})
}

// Handle POST requests on account creation
Expand Down
167 changes: 167 additions & 0 deletions lib/ldp-container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
module.exports.addContainerStats = addContainerStats
module.exports.addFile = addFile
module.exports.addStats = addStats
module.exports.getMetadataGraph = getMetadataGraph
module.exports.readdir = readdir

var $rdf = require('rdflib')
var debug = require('./debug')
var error = require('./http-error')
var fs = require('fs')
var ns = require('./vocab/ns').ns
var S = require('string')
var turtleExtension = '.ttl'

function addContainerStats (ldp, filename, resourceGraph, next) {
ldp.stat(filename, function (err, containerStats) {
if (!err) {
addStats(resourceGraph, '', containerStats)
resourceGraph.add(
resourceGraph.sym(''),
ns.rdf('type'),
ns.ldp('BasicContainer'))

resourceGraph.add(
resourceGraph.sym(''),
ns.rdf('type'),
ns.ldp('Container'))
}
next()
})
}

function addFile (ldp, resourceGraph, baseUri, uri, container, file, callback) {
// Skip .meta and .acl
if (S(file).endsWith(ldp.suffixMeta) || S(file).endsWith(ldp.suffixAcl)) {
return callback(null)
}

// Get file stats
ldp.stat(container + file, function (err, stats) {
if (err) {
// File does not exist, skip
return callback(null)
}

var fileSubject = file + (stats.isDirectory() ? '/' : '')
// var fileBaseUri = utils.filenameToBaseUri(fileSubject, uri, root)

// Add fileStats to resource Graph
addStats(resourceGraph, fileSubject, stats)

// Add to `contains` list
resourceGraph.add(
resourceGraph.sym(''),
ns.ldp('contains'),
resourceGraph.sym(fileSubject))

// Set up a metaFile path
var metaFile = container + file +
(stats.isDirectory() ? '/' : '') +
(S(file).endsWith(turtleExtension) ? '' : ldp.suffixMeta)

getMetadataGraph(ldp, metaFile, baseUri, function (err, metadataGraph) {
if (err) {
metadataGraph = $rdf.graph()
}

// Add Container or BasicContainer types
if (stats.isDirectory()) {
resourceGraph.add(
metadataGraph.sym(fileSubject),
ns.rdf('type'),
ns.ldp('BasicContainer'))

resourceGraph.add(
metadataGraph.sym(fileSubject),
ns.rdf('type'),
ns.ldp('Container'))
}
// Add generic LDP type
resourceGraph.add(
metadataGraph.sym(fileSubject),
ns.rdf('type'),
ns.ldp('Resource'))

// Add type from metadataGraph
metadataGraph
.statementsMatching(
metadataGraph.sym(baseUri),
ns.rdf('type'),
undefined)
.forEach(function (typeStatement) {
// If the current is a file and its type is BasicContainer,
// This is not possible, so do not infer its type!
if (
(
typeStatement.object.uri !== ns.ldp('BasicContainer').uri &&
typeStatement.object.uri !== ns.ldp('Container').uri
) ||
!stats.isFile()
) {
resourceGraph.add(
resourceGraph.sym(fileSubject),
typeStatement.predicate,
typeStatement.object)
}
})

return callback(null)
})
})
}

function addStats (resourceGraph, baseUri, stats) {
resourceGraph.add(
resourceGraph.sym(baseUri),
ns.stat('mtime'),
stats.mtime.getTime() / 1000)

resourceGraph.add(
resourceGraph.sym(baseUri),
ns.stat('size'),
stats.size)
}

function readdir (filename, callback) {
debug.handlers('GET -- Reading directory')
fs.readdir(filename, function (err, files) {
if (err) {
debug.handlers('GET -- Error reading files: ' + err)
return callback(error(err, 'Can\'t read container'))
}

debug.handlers('Files in directory: ' + files)
return callback(null, files)
})
}

function getMetadataGraph (ldp, metaFile, fileBaseUri, callback) {
ldp.stat(metaFile, function (err, metaStats) {
if (err) {
return callback(err)
}

if (metaStats && metaStats.isFile()) {
ldp.readFile(metaFile, function (err, rawMetadata) {
if (err) {
return callback(err)
}

var metadataGraph = $rdf.graph()
try {
$rdf.parse(
rawMetadata,
metadataGraph,
fileBaseUri,
'text/turtle')
} catch (dirErr) {
return callback(error(err, 'Can\'t parse container metadata'))
}
return callback(null, metadataGraph)
})
} else {
return callback(null, $rdf.graph())
}
})
}
Loading