Skip to content

Commit d26b658

Browse files
authored
Merge branch 'master' into PeterHindes-patch-1
2 parents 889944d + 66ae108 commit d26b658

File tree

102 files changed

+31910
-5962
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+31910
-5962
lines changed

.github/workflows/test.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Package image
1919
run: |
2020
docker save synbiohub/synbiohub:snapshot-standalone | gzip > sbh.tar.gz
21-
- uses: actions/upload-artifact@v2
21+
- uses: actions/upload-artifact@v4
2222
name: Upload Docker image
2323
with:
2424
name: sbh-image
@@ -30,7 +30,7 @@ jobs:
3030
steps:
3131
- uses: actions/checkout@v2
3232
name: Checkout source tree
33-
- uses: actions/download-artifact@v2
33+
- uses: actions/download-artifact@v4
3434
name: Download Docker image
3535
with:
3636
name: sbh-image
@@ -57,7 +57,7 @@ jobs:
5757
steps:
5858
- uses: actions/checkout@v2
5959
name: Checkout source tree
60-
- uses: actions/download-artifact@v2
60+
- uses: actions/download-artifact@v4
6161
name: Download Docker image
6262
with:
6363
name: sbh-image
@@ -80,7 +80,7 @@ jobs:
8080
runs-on: ubuntu-latest
8181
if: endsWith(github.ref, 'master')
8282
steps:
83-
- uses: actions/download-artifact@v2
83+
- uses: actions/download-artifact@v4
8484
name: Download Docker iamge
8585
with:
8686
name: sbh-image

java/src/main/java/org/synbiohub/ConvertToGenBankJob.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ public void execute() throws Exception
2121
{
2222
ByteArrayOutputStream logOutputStream = new ByteArrayOutputStream();
2323
ByteArrayOutputStream errorOutputStream = new ByteArrayOutputStream();
24-
25-
System.err.println("GFF3="+gff3Out);
26-
24+
2725
SBOLDocument doc = SBOLValidate.validate(
2826
new PrintStream(logOutputStream),
2927
new PrintStream(errorOutputStream),
@@ -45,9 +43,11 @@ public void execute() throws Exception
4543
false,
4644
false,
4745
gff3Out,
46+
false,
4847
"",
4948
false,
5049
false,
50+
false,
5151
false);
5252

5353
String log = new String(logOutputStream.toByteArray(), StandardCharsets.UTF_8);

java/src/main/java/org/synbiohub/PrepareSubmissionJob.java

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public class PrepareSubmissionJob extends Job {
8787
public String tempDirPath;
8888
public boolean useSBOLExplorer;
8989
public String SBOLExplorerEndpoint;
90+
public String user;
9091

9192
private boolean readCOMBINEArchive(String initialFilename, Map<String, String> attachments) {
9293
CombineArchive combine = null;
@@ -481,6 +482,7 @@ public void visit(Identified identified, TopLevel topLevel) {
481482
// Check if the object is already in the collection
482483
for (String registry : webOfRegistries.keySet()) {
483484
SynBioHubFrontend sbh = new SynBioHubFrontend(webOfRegistries.get(registry), registry);
485+
sbh.setUser(user);
484486
if (topLevel.getIdentity().toString().startsWith(registry)) {
485487

486488
// Fetch the object from SynBioHub

lib/actions/addOwnedBy.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,20 @@ const config = require('../config')
44
const getOwnedBy = require('../query/ownedBy')
55
const retrieveUris = require('../retrieveUris')
66
const getUrisFromReq = require('../getUrisFromReq')
7+
const db = require('../db')
78

8-
module.exports = function (req, res) {
9+
module.exports = async function (req, res) {
910
const userUri = req.body.user
1011

12+
var userId = ''
13+
if (req.body.user.lastIndexOf('/') >= 0) {
14+
userId = req.body.user.substring(req.body.user.lastIndexOf('/') + 1)
15+
}
16+
17+
const user = await db.model.User.findOne({
18+
where: db.sequelize.or({ email: userId }, { username: userId })
19+
})
20+
1121
const { graphUri, uri } = getUrisFromReq(req, res)
1222

1323
const sharedAdditionQuery = loadTemplate('./sparql/AddToSharedCollection.sparql', {
@@ -23,6 +33,12 @@ module.exports = function (req, res) {
2333
})
2434
}
2535

36+
if (!user) {
37+
return new Promise(function (resolve, reject) {
38+
reject(new Error('user ' + userId + ' not recognized'))
39+
})
40+
}
41+
2642
return sparql.updateQuery(sharedAdditionQuery, userUri).then(() => {
2743
return retrieveUris(uri, graphUri)
2844
}).then((uris) => {

lib/actions/makePublic.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ var fs = require('mz/fs')
2626

2727
const prepareSubmission = require('../prepare-submission')
2828

29+
const apiTokens = require('../apiTokens')
30+
2931
module.exports = function (req, res) {
3032
req.setTimeout(0) // no timeout
3133

@@ -225,10 +227,11 @@ module.exports = function (req, res) {
225227
rootCollectionIdentity: config.get('databasePrefix') + 'public/' + collectionId + '/' + collectionId + '_collection' + '/' + version,
226228
newRootCollectionDisplayId: collectionId + '_collection',
227229
newRootCollectionVersion: version,
228-
ownedByURI: config.get('databasePrefix') + 'user/' + req.user.username,
230+
ownedByURI: config.get('databasePrefix') + 'user/' + req.params.userId,
229231
creatorName: '',
230232
citationPubmedIDs: citations,
231-
overwrite_merge: overwriteMerge
233+
overwrite_merge: overwriteMerge,
234+
user: apiTokens.createToken(req.user)
232235

233236
})
234237
}).then((result) => {

lib/actions/removeOwnedBy.js

+30-20
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,19 @@ const loadTemplate = require('../loadTemplate')
66
const getOwnedBy = require('../query/ownedBy')
77

88
module.exports = function (req, res) {
9-
const { graphUri, uri, share } = getUrisFromReq(req, res)
9+
const { graphUri, uri, url } = getUrisFromReq(req, res)
1010

1111
return getOwnedBy(uri, graphUri).then((ownedBy) => {
1212
if (ownedBy.indexOf(config.get('databasePrefix') + 'user/' + req.user.username) === -1) {
13-
res.status(401).send('not authorized to remove an owner')
13+
return res.status(401).send('Not authorized to remove an owner')
1414
}
1515

16-
return retrieveUris(uri, graphUri).then(uris => {
16+
return retrieveUris(uri, graphUri).then((uris) => {
1717
let chunks = []
1818
let offset = config.get('resolveBatch')
1919

2020
for (let i = 0; i < uris.length; i += offset) {
2121
let end = i + offset < uris.length ? i + offset : uris.length
22-
2322
chunks.push(uris.slice(i, end))
2423
}
2524

@@ -30,22 +29,33 @@ module.exports = function (req, res) {
3029

3130
console.log(sharedRemovalQuery)
3231

33-
return sparql.updateQuery(sharedRemovalQuery, req.body.userUri).then(result => {
34-
return Promise.all(chunks.map(chunk => {
35-
let uris = chunk.map(uri => {
36-
return '<' + uri + '> sbh:ownedBy <' + req.body.userUri + '>'
37-
}).join(' . \n')
38-
39-
const updateQuery = loadTemplate('./sparql/RemoveOwnedBy.sparql', {
40-
uris: uris
41-
})
42-
console.log(updateQuery)
43-
44-
return sparql.updateQuery(updateQuery, graphUri).then(() => {
45-
res.redirect(share)
46-
})
47-
}))
48-
})
32+
return sparql.updateQuery(sharedRemovalQuery, req.body.userUri)
33+
.then(() => {
34+
return Promise.all(
35+
chunks.map((chunk) => {
36+
let uris = chunk
37+
.map((uri) => `<${uri}> sbh:ownedBy <${req.body.userUri}>`)
38+
.join(' . \n')
39+
40+
const updateQuery = loadTemplate('./sparql/RemoveOwnedBy.sparql', { uris })
41+
console.log(updateQuery)
42+
43+
return sparql.updateQuery(updateQuery, graphUri)
44+
})
45+
)
46+
})
47+
.then(() => {
48+
// Redirect only once after all promises resolve
49+
if (!req.accepts('text/html')) {
50+
res.status(200).send('Success')
51+
} else {
52+
res.redirect(url)
53+
}
54+
})
55+
.catch((err) => {
56+
console.error('Error:', err)
57+
res.status(500).send(`Error removing ownership: ${err.message}`)
58+
})
4959
})
5060
})
5161
}

lib/actions/upload.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ module.exports = function (req, res) {
3131
return res.status(401).send('not authorized to edit this submission')
3232
}
3333

34+
let formFields = {} // Object to store parsed form fields
35+
36+
form.on('field', (name, value) => {
37+
// Capture the form fields, such as `id`
38+
formFields[name] = value
39+
})
40+
3441
form.on('part', (partStream) => {
3542
if (partStream.filename) {
3643
uploads.createUpload(partStream).then((uploadInfo) => {
@@ -41,7 +48,7 @@ module.exports = function (req, res) {
4148

4249
return attachments.addAttachmentToTopLevel(
4350
graphUri, baseUri, uri, partStream.filename, hash, size,
44-
mime, req.user.username)
51+
mime, req.user.username, formFields.id)
4552
}).then(() => {
4653
var templateParams = {
4754
uri: uri

lib/api/attachUrl.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,18 @@ async function serve (req, res) {
1111
let typeString = req.body.type
1212
let name = req.body.name || uuid()
1313

14-
let displayId = name
14+
// Replace non-alphanumeric characters and spaces with underscores
15+
let displayId = name.replace(/[^a-zA-Z0-9]/g, '_')
16+
// Ensure it does not start with a number by prefixing an underscore if needed
17+
if (/^\d/.test(displayId)) {
18+
displayId = '_' + displayId
19+
}
20+
1521
let version = '1'
1622
let attachmentUri = `${baseUri}/${displayId}/${version}`
1723
let persistentIdentity = `${baseUri}/${displayId}`
1824
let ownedBy = await getOwnedBy(uri, graphUri)
25+
const collectionUri = baseUri + baseUri.slice(baseUri.lastIndexOf('/')) + '_collection/' + version
1926

2027
if (ownedBy.indexOf(config.get('databasePrefix') + 'user/' + req.user.username) === -1) {
2128
if (!req.accepts('text/html')) {
@@ -52,7 +59,8 @@ async function serve (req, res) {
5259
ownedBy: ownedBy,
5360
uri: attachmentUri,
5461
source: source,
55-
type: typeString
62+
type: typeString,
63+
collectionUri: collectionUri
5664
})
5765

5866
console.log('attachUrl: ' + graphUri)

lib/api/datatables.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,16 @@ function collectionMembersDatatable (req, res) {
5656
]).then((result) => {
5757
const [count, filterCount, members] = result
5858

59+
const uniqueMembers = members.filter(
60+
(item, index, self) =>
61+
index === self.findIndex((t) => t.uri === item.uri)
62+
)
63+
5964
res.header('content-type', 'application/json').send(JSON.stringify({
6065
draw: parseInt(req.query.draw),
6166
recordsTotal: count,
6267
recordsFiltered: filterCount,
63-
data: members.map((member) => {
68+
data: uniqueMembers.map((member) => {
6469
var memberUrl = uriToUrl(member.uri)
6570
if (member.uri.toString().startsWith(config.get('databasePrefix') + 'user/')) {
6671
if (req.headers.referer.toString().endsWith('/share')) {

lib/api/shareLink.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
var getUrisFromReq = require('../getUrisFromReq')
3+
4+
function shareLink (req, res) {
5+
const { graphUri, uri, share } = getUrisFromReq(req, res)
6+
7+
if (share && uri.startsWith(graphUri)) {
8+
res.status(200).type('text/plain')
9+
res.header('content-type', 'text/plain').send(share)
10+
} else {
11+
res.status(404).send(uri + ' not found')
12+
}
13+
}
14+
15+
module.exports = shareLink

lib/api/sparql.js

+14-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const SparqlGenerator = require('sparqljs').Generator
66

77
const checkQuery = require('../checkSparqlQuery')
88

9+
const getUrisFromReq = require('../getUrisFromReq')
10+
911
module.exports = function (req, res) {
1012
if (req.method === 'POST') {
1113
query(req, res, req.body.query, req.body['default-graph-uri'])
@@ -15,8 +17,6 @@ module.exports = function (req, res) {
1517
}
1618

1719
function query (req, res, rawQuery, graphUri) {
18-
graphUri = graphUri || null
19-
2020
const parser = new SparqlParser()
2121
const generator = new SparqlGenerator()
2222

@@ -33,8 +33,19 @@ function query (req, res, rawQuery, graphUri) {
3333

3434
queryString = generator.stringify(query)
3535

36+
var baseUri
37+
38+
if (req.url.toString().indexOf('?') >= 0 &&
39+
req.url.toString().substring(0, req.url.toString().indexOf('?')).endsWith('/share/sparql')) {
40+
({ graphUri,
41+
baseUri
42+
} = getUrisFromReq(req, res))
43+
} else {
44+
graphUri = graphUri || null
45+
}
46+
3647
try {
37-
checkQuery(query, req.user)
48+
checkQuery(query, req.user, baseUri)
3849
} catch (e) {
3950
res.status(400).send(e.stack.split('\n')[0])
4051
return

0 commit comments

Comments
 (0)