diff --git a/lib/actions/upload.js b/lib/actions/upload.js index 6ee983552..9a0c170aa 100644 --- a/lib/actions/upload.js +++ b/lib/actions/upload.js @@ -31,6 +31,13 @@ module.exports = function (req, res) { return res.status(401).send('not authorized to edit this submission') } + let formFields = {} // Object to store parsed form fields + + form.on('field', (name, value) => { + // Capture the form fields, such as `id` + formFields[name] = value + }) + form.on('part', (partStream) => { if (partStream.filename) { uploads.createUpload(partStream).then((uploadInfo) => { @@ -41,7 +48,7 @@ module.exports = function (req, res) { return attachments.addAttachmentToTopLevel( graphUri, baseUri, uri, partStream.filename, hash, size, - mime, req.user.username) + mime, req.user.username, formFields.id) }).then(() => { var templateParams = { uri: uri diff --git a/lib/api/attachUrl.js b/lib/api/attachUrl.js index a9acebde2..a4744c076 100644 --- a/lib/api/attachUrl.js +++ b/lib/api/attachUrl.js @@ -11,11 +11,18 @@ async function serve (req, res) { let typeString = req.body.type let name = req.body.name || uuid() - let displayId = name + // Replace non-alphanumeric characters and spaces with underscores + let displayId = name.replace(/[^a-zA-Z0-9]/g, '_') + // Ensure it does not start with a number by prefixing an underscore if needed + if (/^\d/.test(displayId)) { + displayId = '_' + displayId + } + let version = '1' let attachmentUri = `${baseUri}/${displayId}/${version}` let persistentIdentity = `${baseUri}/${displayId}` let ownedBy = await getOwnedBy(uri, graphUri) + const collectionUri = baseUri + baseUri.slice(baseUri.lastIndexOf('/')) + '_collection/' + version if (ownedBy.indexOf(config.get('databasePrefix') + 'user/' + req.user.username) === -1) { if (!req.accepts('text/html')) { @@ -52,7 +59,8 @@ async function serve (req, res) { ownedBy: ownedBy, uri: attachmentUri, source: source, - type: typeString + type: typeString, + collectionUri: collectionUri }) console.log('attachUrl: ' + graphUri) diff --git a/lib/attachments.js b/lib/attachments.js index ffaa5c84b..b689a9732 100644 --- a/lib/attachments.js +++ b/lib/attachments.js @@ -8,9 +8,20 @@ const sha1 = require('sha1') const uuid = require('uuid/v4') const { fetchSBOLObjectRecursive } = require('./fetch/fetch-sbol-object-recursive') -function addAttachmentToTopLevel (graphUri, baseUri, topLevelUri, name, uploadHash, size, attachmentType, owner) { -// console.log('Adding:'+name+' to:'+topLevelUri) - const displayId = 'attachment_' + uuid().replace(/-/g, '') +function addAttachmentToTopLevel (graphUri, baseUri, topLevelUri, name, uploadHash, size, attachmentType, owner, id) { + // console.log('Adding:'+name+' to:'+topLevelUri) + + // Replace non-alphanumeric characters and spaces with underscores + var cleanId = id + if (cleanId) { + cleanId = id.replace(/[^a-zA-Z0-9]/g, '_') + // Ensure it does not start with a number by prefixing an underscore if needed + if (/^\d/.test(cleanId)) { + cleanId = '_' + cleanId + } + } + + const displayId = cleanId || 'attachment_' + uuid().replace(/-/g, '') const persistentIdentity = baseUri + '/' + displayId // TODO: should get version from topLevelUri const version = '1' @@ -130,6 +141,7 @@ function getAttachmentsFromTopLevel (sbol, topLevel, share) { type: attachmentType, image: attachmentIsImage, url: url, + source: attachment.source.toString(), size: attachment.size, sizeString: attachment.size === -1 ? null : filesize(attachment.size) }) @@ -143,6 +155,7 @@ function getAttachmentsFromTopLevel (sbol, topLevel, share) { name: metaData.name, type: 'unknown', url: url, + source: 'unknown', size: -1, sizeString: 'unknown' }) @@ -194,6 +207,7 @@ function getAttachmentsFromList (graphUri, attachmentList, share) { name: attachment.name, type: format || 'Other', url: url, + source: attachment.source.toString(), size: size, sizeString: size === -1 ? null : filesize(size) }) @@ -204,6 +218,7 @@ function getAttachmentsFromList (graphUri, attachmentList, share) { name: 'Attachment is missing', type: 'Other', url: uri, + source: 'unknown', size: 0, sizeString: null }) diff --git a/lib/views/addToCollection.js b/lib/views/addToCollection.js index 7ddb89edf..ddf0a602a 100644 --- a/lib/views/addToCollection.js +++ b/lib/views/addToCollection.js @@ -3,6 +3,7 @@ const pug = require('pug') const config = require('../config') const sparql = require('../sparql/sparql') const getOwnedBy = require('../query/ownedBy') +const getUrisFromReq = require('../getUrisFromReq') module.exports = function (req, res) { req.setTimeout(0) // no timeout @@ -18,11 +19,16 @@ module.exports = function (req, res) { } } + const { uri } = getUrisFromReq(req, res) + return sparql.queryJson(collectionQuery, req.user.graphUri).then((collections) => { - collections.map((result) => { + collections = collections.filter((result) => { + return result.subject !== uri + }).map((result) => { result.uri = result.subject result.name = result.name ? result.name : result.uri.toString() delete result.subject + return result }) collections.sort(sortByNames) @@ -64,6 +70,20 @@ module.exports = function (req, res) { memberUri = memberUri.replace('/user/', config.get('databasePrefix') + 'user/') } + if (memberUri === uri) { + if (!req.accepts('text/html')) { + return res.status(400).type('text/plain').send('Cannot make a collection a member of itself') + } else { + const locals = { + config: config.get(), + section: 'errors', + user: req.user, + errors: [ 'Cannot make a collection a member of itself' ] + } + return res.status(400).send(pug.renderFile('templates/views/errors/errors.jade', locals)) + } + } + var templateParams = { uri: uri, memberUri: memberUri diff --git a/lib/views/submit.js b/lib/views/submit.js index c171b009c..808f0e7e9 100644 --- a/lib/views/submit.js +++ b/lib/views/submit.js @@ -467,8 +467,8 @@ async function handleSubmission (req, res, submission) { await sparql.uploadFile(submissionData.createdBy.graphUri, resultFilename, 'application/rdf+xml') - let baseURI = config.get('databasePrefix') + 'user/' + encodeURIComponent(submissionData.createdBy.username) + '/' + submissionData.collectionId - let collectionURI = baseURI + '/' + submissionData.collectionId + '_collection/' + submissionData.version + let baseURI = config.get('databasePrefix') + 'user/' + encodeURIComponent(submissionData.createdBy.username) + '/' + submissionData.collectionId.replace('_collection', '') + let collectionURI = baseURI + '/' + submissionData.collectionId + '/' + submissionData.version let sourceQuery = loadTemplate('sparql/GetAttachmentSourceFromTopLevel.sparql', { uri: collectionURI }) @@ -504,7 +504,6 @@ async function handleSubmission (req, res, submission) { return } - let attachmentUri = await attachments.addAttachmentToTopLevel( submissionData.createdBy.graphUri, baseURI, @@ -513,7 +512,7 @@ async function handleSubmission (req, res, submission) { hash, size, attachmentFiles[originalFilename] || mime, - submissionData.createdBy.username) + submissionData.createdBy.username, null) console.log(attachmentUri) diff --git a/sparql/AttachUrl.sparql b/sparql/AttachUrl.sparql index 477fa6aef..5288f1f1e 100644 --- a/sparql/AttachUrl.sparql +++ b/sparql/AttachUrl.sparql @@ -5,6 +5,8 @@ PREFIX sbol: INSERT { <$topLevel> sbol:attachment <$uri> . + <$collectionUri> sbol:member <$uri> . + <$uri> a sbol:Attachment ; dcterms:title "$name" ; sbol:displayId "$displayId" ; diff --git a/templates/mixins/attachments.jade b/templates/mixins/attachments.jade index 5db430c02..37f421fb0 100644 --- a/templates/mixins/attachments.jade +++ b/templates/mixins/attachments.jade @@ -20,7 +20,7 @@ mixin attachments(url, attachments, canEdit) if attachment.sizeString | #{attachment.sizeString} td - a(href=attachment.url + '/download') + a(href=attachment.source) button.btn.btn-primary span.fa.fa-download | Download @@ -38,6 +38,9 @@ mixin attachments(url, attachments, canEdit) span.btn.btn-primary | Select file(s)… input(type="file",name="file",style="display: none;",multiple,form="sbh-attachment-upload") + div.row(style="margin-top: 10px") + div.col-md-6 + input.form-control(type="text", name="id", placeholder="Name", form="sbh-attachment-upload") td(colspan=2) button.btn.btn-success(type='submit',style='width:100%;',form="sbh-attachment-upload") Attach div.row diff --git a/tests/previousresults/getrequest_user-:userId-:collectionId-:displayId_docker.html b/tests/previousresults/getrequest_user-:userId-:collectionId-:displayId_docker.html index 5e2487d32..0cbbbcffd 100644 --- a/tests/previousresults/getrequest_user-:userId-:collectionId-:displayId_docker.html +++ b/tests/previousresults/getrequest_user-:userId-:collectionId-:displayId_docker.html @@ -526,6 +526,11 @@

+
+
+ +
+