Skip to content

Commit 111e63b

Browse files
Restrict URL/file knowledge to ResourceMapper (#1213)
Restrict knowledge of the URL/file mapping again to ResourceMapper
2 parents 7b670c6 + 14d02cf commit 111e63b

File tree

11 files changed

+128
-142
lines changed

11 files changed

+128
-142
lines changed

lib/create-app.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,7 @@ function createApp (argv = {}) {
4848
rootUrl: argv.serverUri,
4949
rootPath: path.resolve(argv.root || process.cwd()),
5050
includeHost: argv.multiuser,
51-
defaultContentType: argv.defaultContentType,
52-
fileSuffixes: [
53-
argv.suffixAcl || '.acl',
54-
argv.suffixMeta || '.meta'
55-
]
51+
defaultContentType: argv.defaultContentType
5652
})
5753

5854
const configPath = config.initConfigDir(argv)

lib/handlers/allow.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,15 @@ function allow (mode, checkPermissionsForDirectory) {
5656
if (mode === 'Read' && (resourcePath === '' || resourcePath === '/')) {
5757
// This is a hack to make NSS check the ACL for representation that is served for root (if any)
5858
// See https://github.com/solid/node-solid-server/issues/1063 for more info
59-
const representationUrl = await ldp.resourceMapper.getRepresentationUrlForResource(resourceUrl)
60-
if (representationUrl.endsWith('index.html')) {
61-
// We ONLY want to do this when the representation we return is a HTML file
59+
const representationUrl = `${rootUrl}/index.html`
60+
let representationPath
61+
try {
62+
representationPath = await ldp.resourceMapper.mapUrlToFile({ url: representationUrl })
63+
} catch (err) {
64+
}
65+
66+
// We ONLY want to do this when the HTML representation exists
67+
if (representationPath) {
6268
req.acl = ACL.createFromLDPAndRequest(representationUrl, ldp, req)
6369
const representationIsAllowed = await req.acl.can(userId, mode)
6470
if (representationIsAllowed) {

lib/handlers/get.js

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -132,19 +132,26 @@ async function handler (req, res, next) {
132132
}
133133

134134
async function globHandler (req, res, next) {
135-
const ldp = req.app.locals.ldp
136-
// TODO: This is a hack, that does not check if the target file exists, as this is quite complex with globbing.
137-
// TODO: Proper support for this is not implemented, as globbing support might be removed in the future.
138-
const filename = ldp.resourceMapper.getFullPath(req)
139-
const requestUri = (await ldp.resourceMapper.mapFileToUrl({ path: filename, hostname: req.hostname })).url
135+
const { ldp } = req.app.locals
136+
137+
// Ensure this is a glob for all files in a single folder
138+
// https://github.com/solid/solid-spec/pull/148
139+
const requestUrl = await ldp.resourceMapper.getRequestUrl(req)
140+
if (!/^[^*]+\/\*$/.test(requestUrl)) {
141+
return next(error(404, 'Unsupported glob pattern'))
142+
}
143+
144+
// Extract the folder on the file system from the URL glob
145+
const folderUrl = requestUrl.substr(0, requestUrl.length - 1)
146+
const folderPath = (await ldp.resourceMapper.mapUrlToFile({ url: folderUrl, searchIndex: false })).path
140147

141148
const globOptions = {
142149
noext: true,
143150
nobrace: true,
144151
nodir: true
145152
}
146153

147-
glob(filename, globOptions, function (err, matches) {
154+
glob(`${folderPath}*`, globOptions, async (err, matches) => {
148155
if (err || matches.length === 0) {
149156
debugGlob('No files matching the pattern')
150157
return next(error(404, 'No files matching glob pattern'))
@@ -154,7 +161,7 @@ async function globHandler (req, res, next) {
154161
const globGraph = $rdf.graph()
155162

156163
debugGlob('found matches ' + matches)
157-
Promise.all(matches.map(match => new Promise(async (resolve, reject) => {
164+
await Promise.all(matches.map(match => new Promise(async (resolve, reject) => {
158165
const urlData = await ldp.resourceMapper.mapFileToUrl({ path: match, hostname: req.hostname })
159166
fs.readFile(match, {encoding: 'utf8'}, function (err, fileData) {
160167
if (err) {
@@ -178,15 +185,14 @@ async function globHandler (req, res, next) {
178185
})
179186
})
180187
})))
181-
.then(() => {
182-
const data = $rdf.serialize(undefined, globGraph, requestUri, 'text/turtle')
183-
// TODO this should be added as a middleware in the routes
184-
res.setHeader('Content-Type', 'text/turtle')
185-
debugGlob('returning turtle')
186-
187-
res.send(data)
188-
return next()
189-
})
188+
189+
const data = $rdf.serialize(undefined, globGraph, requestUrl, 'text/turtle')
190+
// TODO this should be added as a middleware in the routes
191+
res.setHeader('Content-Type', 'text/turtle')
192+
debugGlob('returning turtle')
193+
194+
res.send(data)
195+
next()
190196
})
191197
}
192198

@@ -198,7 +204,7 @@ function hasReadPermissions (file, req, res, callback) {
198204
return callback(true)
199205
}
200206

201-
const root = ldp.resourceMapper.getBasePath(req.hostname)
207+
const root = ldp.resourceMapper.resolveFilePath(req.hostname)
202208
const relativePath = '/' + _path.relative(root, file)
203209
res.locals.path = relativePath
204210
allow('Read')(req, res, err => callback(!err))

lib/handlers/patch.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ async function patchHandler (req, res, next) {
6767
const result = await withLock(path, { mustExist: false }, async () => {
6868
const graph = await readGraph(resource)
6969
await applyPatch(patchObject, graph, url)
70-
return writeGraph(graph, resource, ldp.resourceMapper.rootPath, ldp.serverUri)
70+
return writeGraph(graph, resource, ldp.resourceMapper.resolveFilePath(req.hostname), ldp.serverUri)
7171
})
7272

7373
// Send the result to the client

lib/handlers/put.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ async function putStream (req, res, next, stream = req) {
3333
}
3434
}
3535

36-
async function putAcl (req, res, next) {
36+
function putAcl (req, res, next) {
3737
const ldp = req.app.locals.ldp
3838
const contentType = req.get('content-type')
39-
const path = ldp.resourceMapper.getFullPath(req)
40-
const requestUri = await ldp.resourceMapper.resolveUrl(req.hostname, path)
39+
const requestUri = ldp.resourceMapper.getRequestUrl(req)
40+
4141
if (ldp.isValidRdf(req.body, requestUri, contentType)) {
4242
const stream = stringToStream(req.body)
4343
return putStream(req, res, next, stream)

lib/ldp.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const ldpContainer = require('./ldp-container')
1717
const parse = require('./utils').parse
1818
const fetch = require('node-fetch')
1919
const { promisify } = require('util')
20+
const URL = require('url')
2021
const URI = require('urijs')
2122
const withLock = require('./lock')
2223

@@ -153,8 +154,7 @@ class LDP {
153154
originalPath += '/'
154155
}
155156
}
156-
const { url: putUrl, contentType } = await this.resourceMapper.mapFileToUrl(
157-
{ path: this.resourceMapper.rootPath + resourcePath, hostname: host })
157+
const { url: putUrl, contentType } = await this.resourceMapper.mapFileToUrl({ path: resourcePath, hostname: host })
158158

159159
// HACK: the middleware in webid-oidc.js uses body-parser, thus ending the stream of data
160160
// for JSON bodies. So, the stream needs to be reset
@@ -218,7 +218,8 @@ class LDP {
218218
// First check if we are above quota
219219
let isOverQuota
220220
try {
221-
isOverQuota = await overQuota(this.resourceMapper.rootPath, this.serverUri)
221+
const { hostname } = URL.parse(url.url || url)
222+
isOverQuota = await overQuota(this.resourceMapper.resolveFilePath(hostname), this.serverUri)
222223
} catch (err) {
223224
throw error(500, 'Error finding user quota')
224225
}
@@ -323,9 +324,7 @@ class LDP {
323324
async get (options, searchIndex = true) {
324325
let path, contentType, stats
325326
try {
326-
({ path, contentType } = await this.resourceMapper.mapUrlToFile({
327-
url: options, contentType: options.contentType, searchIndex
328-
}))
327+
({ path, contentType } = await this.resourceMapper.mapUrlToFile({ url: options, searchIndex }))
329328
stats = await this.stat(path)
330329
} catch (err) {
331330
throw error(404, 'Can\'t find file requested: ' + options)

lib/models/account-manager.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ class AccountManager {
130130
* @return {string}
131131
*/
132132
accountDirFor (accountName) {
133-
return this.store.resourceMapper.getBasePath(url.parse(this.accountUriFor(accountName)).hostname)
133+
const { hostname } = url.parse(this.accountUriFor(accountName))
134+
return this.store.resourceMapper.resolveFilePath(hostname)
134135
}
135136

136137
/**

0 commit comments

Comments
 (0)