@openneuro/server 4.20.5 → 4.20.6-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -6
- package/src/__mocks__/{config.js → config.ts} +5 -5
- package/src/app.ts +32 -31
- package/src/cache/item.ts +6 -7
- package/src/cache/types.ts +8 -8
- package/src/{config.js → config.ts} +6 -6
- package/src/datalad/__tests__/changelog.spec.ts +83 -0
- package/src/datalad/__tests__/dataset.spec.ts +109 -0
- package/src/datalad/__tests__/description.spec.ts +141 -0
- package/src/datalad/__tests__/files.spec.ts +77 -0
- package/src/datalad/__tests__/pagination.spec.ts +136 -0
- package/src/datalad/__tests__/{snapshots.spec.js → snapshots.spec.ts} +17 -17
- package/src/datalad/{analytics.js → analytics.ts} +4 -4
- package/src/datalad/{changelog.js → changelog.ts} +17 -14
- package/src/datalad/{dataset.js → dataset.ts} +95 -93
- package/src/datalad/{description.js → description.ts} +37 -37
- package/src/datalad/draft.ts +38 -0
- package/src/datalad/files.ts +26 -20
- package/src/datalad/{pagination.js → pagination.ts} +47 -47
- package/src/datalad/{readme.js → readme.ts} +13 -11
- package/src/datalad/{reexporter.js → reexporter.ts} +4 -4
- package/src/datalad/{snapshots.js → snapshots.ts} +56 -62
- package/src/datalad/{upload.js → upload.ts} +7 -5
- package/src/elasticsearch/elastic-client.ts +11 -0
- package/src/elasticsearch/reindex-dataset.ts +7 -7
- package/src/graphql/__tests__/__snapshots__/permissions.spec.ts.snap +5 -0
- package/src/graphql/__tests__/{comment.spec.js → comment.spec.ts} +17 -17
- package/src/graphql/__tests__/permissions.spec.ts +113 -0
- package/src/graphql/{permissions.js → permissions.ts} +14 -14
- package/src/graphql/resolvers/__tests__/brainlife.spec.ts +11 -11
- package/src/graphql/resolvers/__tests__/{dataset-search.spec.js → dataset-search.spec.ts} +25 -23
- package/src/graphql/resolvers/__tests__/dataset.spec.ts +175 -0
- package/src/graphql/resolvers/__tests__/derivatives.spec.ts +19 -19
- package/src/graphql/resolvers/__tests__/importRemoteDataset.spec.ts +20 -20
- package/src/graphql/resolvers/__tests__/permssions.spec.ts +35 -0
- package/src/graphql/resolvers/__tests__/snapshots.spec.ts +59 -0
- package/src/graphql/resolvers/__tests__/user.spec.ts +18 -0
- package/src/graphql/resolvers/brainlife.ts +4 -4
- package/src/graphql/resolvers/cache.ts +4 -4
- package/src/graphql/resolvers/{comment.js → comment.ts} +16 -16
- package/src/graphql/resolvers/{dataset-search.js → dataset-search.ts} +45 -43
- package/src/graphql/resolvers/{dataset.js → dataset.ts} +38 -52
- package/src/graphql/resolvers/datasetType.ts +3 -3
- package/src/graphql/resolvers/derivatives.ts +11 -11
- package/src/graphql/resolvers/description.ts +18 -0
- package/src/graphql/resolvers/{draft.js → draft.ts} +13 -13
- package/src/graphql/resolvers/{flaggedFiles.js → flaggedFiles.ts} +4 -4
- package/src/graphql/resolvers/{follow.js → follow.ts} +1 -1
- package/src/graphql/resolvers/git.ts +3 -3
- package/src/graphql/resolvers/history.ts +13 -0
- package/src/graphql/resolvers/importRemoteDataset.ts +12 -11
- package/src/graphql/resolvers/index.ts +25 -0
- package/src/graphql/resolvers/{issues.js → issues.ts} +9 -9
- package/src/graphql/resolvers/metadata.ts +8 -8
- package/src/graphql/resolvers/{mutation.js → mutation.ts} +26 -26
- package/src/graphql/resolvers/{newsletter.js → newsletter.ts} +2 -2
- package/src/graphql/resolvers/permissions.ts +15 -21
- package/src/graphql/resolvers/publish.ts +17 -0
- package/src/graphql/resolvers/query.ts +21 -0
- package/src/graphql/resolvers/{readme.js → readme.ts} +3 -3
- package/src/graphql/resolvers/{reexporter.js → reexporter.ts} +2 -2
- package/src/graphql/resolvers/relation.ts +5 -5
- package/src/graphql/resolvers/{reset.js → reset.ts} +2 -2
- package/src/graphql/resolvers/reviewer.ts +4 -4
- package/src/graphql/resolvers/{snapshots.js → snapshots.ts} +49 -49
- package/src/graphql/resolvers/{stars.js → stars.ts} +1 -1
- package/src/graphql/resolvers/summary.ts +3 -3
- package/src/graphql/resolvers/{upload.js → upload.ts} +5 -5
- package/src/graphql/resolvers/{user.js → user.ts} +16 -18
- package/src/graphql/resolvers/{validation.js → validation.ts} +12 -14
- package/src/graphql/{schema.js → schema.ts} +4 -6
- package/src/graphql/utils/{file.js → file.ts} +2 -2
- package/src/handlers/{comments.js → comments.ts} +11 -11
- package/src/handlers/{config.js → config.ts} +1 -1
- package/src/handlers/{datalad.js → datalad.ts} +22 -22
- package/src/handlers/{doi.js → doi.ts} +6 -6
- package/src/handlers/reviewer.ts +6 -6
- package/src/handlers/{sitemap.js → sitemap.ts} +19 -19
- package/src/handlers/stars.ts +11 -10
- package/src/handlers/{subscriptions.js → subscriptions.ts} +17 -16
- package/src/handlers/{users.js → users.ts} +3 -3
- package/src/libs/__tests__/apikey.spec.ts +25 -0
- package/src/libs/__tests__/datalad-service.spec.ts +27 -0
- package/src/libs/__tests__/{dataset.spec.js → dataset.spec.ts} +9 -9
- package/src/libs/{apikey.js → apikey.ts} +5 -5
- package/src/libs/authentication/__tests__/jwt.spec.ts +59 -0
- package/src/libs/authentication/{crypto.js → crypto.ts} +16 -16
- package/src/libs/authentication/google.ts +18 -0
- package/src/libs/authentication/jwt.ts +40 -33
- package/src/libs/authentication/{orcid.js → orcid.ts} +11 -11
- package/src/libs/authentication/{passport.js → passport.ts} +45 -30
- package/src/libs/authentication/{states.js → states.ts} +17 -20
- package/src/libs/{counter.js → counter.ts} +1 -1
- package/src/libs/{datalad-service.js → datalad-service.ts} +4 -4
- package/src/libs/dataset.ts +9 -0
- package/src/libs/doi/__tests__/__snapshots__/doi.spec.ts.snap +17 -0
- package/src/libs/doi/__tests__/doi.spec.ts +25 -0
- package/src/libs/doi/__tests__/normalize.spec.ts +19 -19
- package/src/libs/doi/{index.js → index.ts} +27 -21
- package/src/libs/doi/normalize.ts +2 -2
- package/src/libs/email/__tests__/index.spec.ts +14 -14
- package/src/libs/email/index.ts +4 -4
- package/src/libs/email/templates/__tests__/comment-created.spec.ts +12 -12
- package/src/libs/email/templates/__tests__/dataset-deleted.spec.ts +6 -6
- package/src/libs/email/templates/__tests__/owner-unsubscribed.spec.ts +6 -6
- package/src/libs/email/templates/__tests__/snapshot-created.spec.ts +9 -9
- package/src/libs/email/templates/__tests__/snapshot-reminder.spec.ts +7 -7
- package/src/libs/email/templates/comment-created.ts +2 -1
- package/src/libs/email/templates/dataset-deleted.ts +2 -1
- package/src/libs/email/templates/dataset-import-failed.ts +2 -1
- package/src/libs/email/templates/dataset-imported.ts +2 -1
- package/src/libs/email/templates/owner-unsubscribed.ts +2 -1
- package/src/libs/email/templates/snapshot-created.ts +2 -1
- package/src/libs/email/templates/snapshot-reminder.ts +2 -1
- package/src/libs/{notifications.js → notifications.ts} +100 -113
- package/src/libs/{orcid.js → orcid.ts} +20 -20
- package/src/libs/{redis.js → redis.ts} +6 -6
- package/src/models/__tests__/ingestDataset.spec.ts +15 -15
- package/src/models/analytics.ts +2 -2
- package/src/models/badAnnexObject.ts +6 -6
- package/src/models/comment.ts +10 -10
- package/src/models/counter.ts +2 -2
- package/src/models/dataset.ts +16 -16
- package/src/models/deletion.ts +3 -3
- package/src/models/deprecatedSnapshot.ts +2 -2
- package/src/models/doi.ts +2 -2
- package/src/models/file.ts +2 -2
- package/src/models/ingestDataset.ts +4 -4
- package/src/models/issue.ts +2 -2
- package/src/models/key.ts +2 -2
- package/src/models/mailgunIdentifier.ts +2 -2
- package/src/models/metadata.ts +3 -3
- package/src/models/newsletter.ts +3 -3
- package/src/models/notification.ts +2 -2
- package/src/models/permission.ts +4 -4
- package/src/models/reviewer.ts +7 -7
- package/src/models/snapshot.ts +2 -2
- package/src/models/stars.ts +6 -6
- package/src/models/subscription.ts +2 -2
- package/src/models/summary.ts +2 -2
- package/src/models/upload.ts +3 -3
- package/src/models/user.ts +4 -4
- package/src/{routes.js → routes.ts} +62 -62
- package/src/server.ts +9 -9
- package/src/utils/__tests__/datasetOrSnapshot.spec.ts +25 -25
- package/src/utils/__tests__/validateUrl.spec.ts +10 -10
- package/src/utils/datasetOrSnapshot.ts +2 -2
- package/src/utils/validateUrl.ts +1 -1
- package/src/datalad/__tests__/changelog.spec.js +0 -82
- package/src/datalad/__tests__/dataset.spec.js +0 -109
- package/src/datalad/__tests__/description.spec.js +0 -137
- package/src/datalad/__tests__/files.spec.js +0 -75
- package/src/datalad/__tests__/pagination.spec.js +0 -136
- package/src/datalad/draft.js +0 -37
- package/src/elasticsearch/elastic-client.js +0 -11
- package/src/graphql/__tests__/permissions.spec.js +0 -107
- package/src/graphql/pubsub.js +0 -5
- package/src/graphql/resolvers/__tests__/dataset.spec.js +0 -175
- package/src/graphql/resolvers/__tests__/permssions.spec.js +0 -34
- package/src/graphql/resolvers/__tests__/snapshots.spec.js +0 -58
- package/src/graphql/resolvers/__tests__/user.spec.js +0 -17
- package/src/graphql/resolvers/description.js +0 -29
- package/src/graphql/resolvers/history.js +0 -11
- package/src/graphql/resolvers/index.js +0 -25
- package/src/graphql/resolvers/publish.js +0 -17
- package/src/graphql/resolvers/query.js +0 -21
- package/src/graphql/resolvers/subscriptions.js +0 -81
- package/src/graphql/utils/publish-draft-update.js +0 -13
- package/src/libs/__tests__/apikey.spec.js +0 -24
- package/src/libs/__tests__/datalad-service.spec.js +0 -26
- package/src/libs/authentication/__tests__/jwt.spec.js +0 -23
- package/src/libs/authentication/globus.js +0 -11
- package/src/libs/authentication/google.js +0 -19
- package/src/libs/bidsId.js +0 -68
- package/src/libs/dataset.js +0 -9
- package/src/libs/doi/__tests__/doi.spec.js +0 -24
- package/src/libs/redis-pubsub.js +0 -5
- package/src/libs/request.js +0 -155
- package/src/libs/scitran.js +0 -25
- package/src/libs/subscription-server.js +0 -20
- package/src/libs/testing-utils.js +0 -17
- package/src/persistent/datasets/.gitignore +0 -3
- package/src/persistent/temp/.gitignore +0 -3
- /package/src/libs/__mocks__/{notifications.js → notifications.ts} +0 -0
- /package/src/libs/authentication/{verifyUser.js → verifyUser.ts} +0 -0
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
import * as datalad from
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { description } from './description.js'
|
|
1
|
+
import * as datalad from "../../datalad/dataset"
|
|
2
|
+
import { removeDatasetSearchDocument } from "./dataset-search"
|
|
3
|
+
import { latestSnapshot, snapshots } from "./snapshots"
|
|
4
|
+
import { description } from "./description"
|
|
6
5
|
import {
|
|
6
|
+
checkDatasetAdmin,
|
|
7
7
|
checkDatasetRead,
|
|
8
8
|
checkDatasetWrite,
|
|
9
|
-
|
|
10
|
-
} from
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import
|
|
24
|
-
import { derivatives } from './derivatives'
|
|
25
|
-
import semver from 'semver'
|
|
9
|
+
} from "../permissions"
|
|
10
|
+
import { user } from "./user"
|
|
11
|
+
import { permissions } from "./permissions"
|
|
12
|
+
import { datasetComments } from "./comment"
|
|
13
|
+
import { metadata } from "./metadata"
|
|
14
|
+
import { history } from "./history"
|
|
15
|
+
import * as dataladAnalytics from "../../datalad/analytics"
|
|
16
|
+
import DatasetModel from "../../models/dataset"
|
|
17
|
+
import Deletion from "../../models/deletion"
|
|
18
|
+
import { reviewers } from "./reviewer"
|
|
19
|
+
import { getDatasetWorker } from "../../libs/datalad-service"
|
|
20
|
+
import { getFileName } from "../../datalad/files"
|
|
21
|
+
import { onBrainlife } from "./brainlife"
|
|
22
|
+
import { derivatives } from "./derivatives"
|
|
23
|
+
import semver from "semver"
|
|
26
24
|
|
|
27
25
|
export const dataset = async (obj, { id }, { user, userInfo }) => {
|
|
28
26
|
await checkDatasetRead(id, user, userInfo)
|
|
@@ -56,21 +54,21 @@ export const snapshotCreationComparison = (
|
|
|
56
54
|
* Find the canonical name for a dataset from snapshots and drafts
|
|
57
55
|
* @param {object} obj Dataset object (at least {id: "datasetId"})
|
|
58
56
|
*/
|
|
59
|
-
export const datasetName = obj => {
|
|
60
|
-
return snapshots(obj).then(results => {
|
|
57
|
+
export const datasetName = (obj) => {
|
|
58
|
+
return snapshots(obj).then((results) => {
|
|
61
59
|
if (results && results.length) {
|
|
62
60
|
// Return the latest snapshot name
|
|
63
61
|
const sortedSnapshots = results.sort(snapshotCreationComparison)
|
|
64
62
|
return description({
|
|
65
63
|
id: obj.id,
|
|
66
64
|
revision: sortedSnapshots[0].hexsha,
|
|
67
|
-
}).then(desc => desc.Name)
|
|
65
|
+
}).then((desc) => desc.Name)
|
|
68
66
|
} else if (obj.revision) {
|
|
69
67
|
// Return the draft name or null
|
|
70
68
|
return description({
|
|
71
69
|
id: obj.id,
|
|
72
70
|
revision: obj.revision,
|
|
73
|
-
}).then(desc => desc.Name)
|
|
71
|
+
}).then((desc) => desc.Name)
|
|
74
72
|
} else {
|
|
75
73
|
return null
|
|
76
74
|
}
|
|
@@ -81,9 +79,9 @@ export const datasetName = obj => {
|
|
|
81
79
|
* Resolve the best dataset name and cache in mongodb
|
|
82
80
|
* @param {string} datasetId
|
|
83
81
|
*/
|
|
84
|
-
export const updateDatasetName = datasetId =>
|
|
85
|
-
datasetName({ id: datasetId }).then(name =>
|
|
86
|
-
DatasetModel.updateOne({ id: datasetId }, { $set: { name } }).exec()
|
|
82
|
+
export const updateDatasetName = (datasetId) =>
|
|
83
|
+
datasetName({ id: datasetId }).then((name) =>
|
|
84
|
+
DatasetModel.updateOne({ id: datasetId }, { $set: { name } }).exec()
|
|
87
85
|
)
|
|
88
86
|
|
|
89
87
|
/**
|
|
@@ -103,11 +101,11 @@ export const createDataset = (
|
|
|
103
101
|
})
|
|
104
102
|
} else {
|
|
105
103
|
throw new Error(
|
|
106
|
-
|
|
104
|
+
"New dataset must be defaced or have participant consent.",
|
|
107
105
|
)
|
|
108
106
|
}
|
|
109
107
|
} else {
|
|
110
|
-
throw new Error(
|
|
108
|
+
throw new Error("You must be logged in to create a dataset.")
|
|
111
109
|
}
|
|
112
110
|
}
|
|
113
111
|
|
|
@@ -134,10 +132,6 @@ export const deleteDataset = async (
|
|
|
134
132
|
redirect,
|
|
135
133
|
user: { _id: user },
|
|
136
134
|
}).save()
|
|
137
|
-
await pubsub.publish('datasetDeleted', {
|
|
138
|
-
datasetId: id,
|
|
139
|
-
datasetDeleted: id,
|
|
140
|
-
})
|
|
141
135
|
return deleted
|
|
142
136
|
}
|
|
143
137
|
|
|
@@ -152,14 +146,6 @@ export const deleteFiles = async (
|
|
|
152
146
|
try {
|
|
153
147
|
await checkDatasetWrite(datasetId, user, userInfo)
|
|
154
148
|
const deletedFiles = await datalad.deleteFiles(datasetId, files, userInfo)
|
|
155
|
-
pubsub.publish('filesUpdated', {
|
|
156
|
-
datasetId,
|
|
157
|
-
filesUpdated: {
|
|
158
|
-
action: 'DELETE',
|
|
159
|
-
payload: deletedFiles,
|
|
160
|
-
},
|
|
161
|
-
})
|
|
162
|
-
|
|
163
149
|
return true
|
|
164
150
|
} catch (err) {
|
|
165
151
|
return false
|
|
@@ -223,7 +209,7 @@ export const updatePublic = (
|
|
|
223
209
|
/**
|
|
224
210
|
* Get analytics for a dataset or snapshot
|
|
225
211
|
*/
|
|
226
|
-
export const analytics = async obj => {
|
|
212
|
+
export const analytics = async (obj) => {
|
|
227
213
|
// if the dataset field exists, the request is from a snapshot, and
|
|
228
214
|
// we resolve the datasetId from the dataset snapshot field of context.
|
|
229
215
|
// otherwise, just use the id field because the object is a dataset
|
|
@@ -249,7 +235,7 @@ export const trackAnalytics = (obj, { datasetId, tag, type }) => {
|
|
|
249
235
|
/**
|
|
250
236
|
* Get the star count for the dataset
|
|
251
237
|
*/
|
|
252
|
-
export const stars = async obj => {
|
|
238
|
+
export const stars = async (obj) => {
|
|
253
239
|
const datasetId = obj && obj.dataset ? (await obj.dataset()).id : obj.id
|
|
254
240
|
return datalad.getStars(datasetId)
|
|
255
241
|
}
|
|
@@ -257,7 +243,7 @@ export const stars = async obj => {
|
|
|
257
243
|
/**
|
|
258
244
|
* Get the follower count for the dataset
|
|
259
245
|
*/
|
|
260
|
-
export const followers = async obj => {
|
|
246
|
+
export const followers = async (obj) => {
|
|
261
247
|
const datasetId = obj && obj.dataset ? (await obj.dataset()).id : obj.id
|
|
262
248
|
return datalad.getFollowers(datasetId)
|
|
263
249
|
}
|
|
@@ -269,7 +255,7 @@ export const followers = async obj => {
|
|
|
269
255
|
*/
|
|
270
256
|
export const following = (obj, _, { user }) =>
|
|
271
257
|
user
|
|
272
|
-
? datalad.getUserFollowed(obj.id, user).then(res => (res ? true : false))
|
|
258
|
+
? datalad.getUserFollowed(obj.id, user).then((res) => (res ? true : false))
|
|
273
259
|
: null
|
|
274
260
|
|
|
275
261
|
/**
|
|
@@ -279,19 +265,19 @@ export const following = (obj, _, { user }) =>
|
|
|
279
265
|
*/
|
|
280
266
|
export const starred = (obj, _, { user }) =>
|
|
281
267
|
user
|
|
282
|
-
? datalad.getUserStarred(obj.id, user).then(res => (res ? true : false))
|
|
268
|
+
? datalad.getUserStarred(obj.id, user).then((res) => (res ? true : false))
|
|
283
269
|
: null
|
|
284
270
|
|
|
285
|
-
const worker = obj => getDatasetWorker(obj.id)
|
|
271
|
+
const worker = (obj) => getDatasetWorker(obj.id)
|
|
286
272
|
|
|
287
273
|
/**
|
|
288
274
|
* Dataset object
|
|
289
275
|
*/
|
|
290
276
|
const Dataset = {
|
|
291
|
-
uploader: ds => user(ds, { id: ds.uploader }),
|
|
292
|
-
draft: async obj => ({
|
|
277
|
+
uploader: (ds) => user(ds, { id: ds.uploader }),
|
|
278
|
+
draft: async (obj) => ({
|
|
293
279
|
id: obj.id,
|
|
294
|
-
revision: await getDraftHead(obj.id),
|
|
280
|
+
revision: await datalad.getDraftHead(obj.id),
|
|
295
281
|
modified: obj.modified,
|
|
296
282
|
}),
|
|
297
283
|
snapshots,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { description } from
|
|
1
|
+
import { description } from "./description.js"
|
|
2
2
|
|
|
3
|
-
export async function datasetType(dsOrSnapshot): Promise<
|
|
3
|
+
export async function datasetType(dsOrSnapshot): Promise<"schema" | "legacy"> {
|
|
4
4
|
const dsDescription = await description(dsOrSnapshot)
|
|
5
|
-
return dsDescription.DatasetType ===
|
|
5
|
+
return dsDescription.DatasetType === "derivative" ? "schema" : "legacy"
|
|
6
6
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DatasetOrSnapshot,
|
|
3
3
|
getDatasetFromSnapshotId,
|
|
4
|
-
} from
|
|
5
|
-
import config from
|
|
4
|
+
} from "../../utils/datasetOrSnapshot"
|
|
5
|
+
import config from "../../config"
|
|
6
6
|
|
|
7
|
-
const S3_BUCKET =
|
|
8
|
-
const GITHUB_ORGANIZATION =
|
|
7
|
+
const S3_BUCKET = "openneuro-derivatives"
|
|
8
|
+
const GITHUB_ORGANIZATION = "OpenNeuroDerivatives"
|
|
9
9
|
|
|
10
10
|
// Available derivatives at this time
|
|
11
|
-
type GitHubDerivative =
|
|
11
|
+
type GitHubDerivative = "mriqc" | "fmriprep"
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Test for a derivative on GitHub via API
|
|
@@ -49,7 +49,7 @@ export const githubDerivative = async (
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
interface DatasetDerivatives {
|
|
52
|
+
export interface DatasetDerivatives {
|
|
53
53
|
name: string
|
|
54
54
|
local: boolean
|
|
55
55
|
s3Url: URL
|
|
@@ -80,17 +80,17 @@ export const derivatives = async (
|
|
|
80
80
|
dataset: DatasetOrSnapshot,
|
|
81
81
|
): Promise<Array<DatasetDerivatives>> => {
|
|
82
82
|
let datasetId
|
|
83
|
-
if (
|
|
83
|
+
if ("tag" in dataset) {
|
|
84
84
|
datasetId = getDatasetFromSnapshotId(dataset.id)
|
|
85
85
|
} else {
|
|
86
86
|
datasetId = dataset.id
|
|
87
87
|
}
|
|
88
88
|
const available: Array<DatasetDerivatives> = []
|
|
89
|
-
if (await githubDerivative(datasetId,
|
|
90
|
-
available.push(derivativeObject(datasetId,
|
|
89
|
+
if (await githubDerivative(datasetId, "mriqc")) {
|
|
90
|
+
available.push(derivativeObject(datasetId, "mriqc"))
|
|
91
91
|
}
|
|
92
|
-
if (await githubDerivative(datasetId,
|
|
93
|
-
available.push(derivativeObject(datasetId,
|
|
92
|
+
if (await githubDerivative(datasetId, "fmriprep")) {
|
|
93
|
+
available.push(derivativeObject(datasetId, "fmriprep"))
|
|
94
94
|
}
|
|
95
95
|
return available
|
|
96
96
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolver implementation for dataset_description.json
|
|
3
|
+
*/
|
|
4
|
+
import { setDescription } from "../../datalad/description"
|
|
5
|
+
import { checkDatasetWrite } from "../permissions"
|
|
6
|
+
export { description } from "../../datalad/description"
|
|
7
|
+
|
|
8
|
+
export const updateDescription = (
|
|
9
|
+
obj,
|
|
10
|
+
{ datasetId, field, value },
|
|
11
|
+
{ user, userInfo },
|
|
12
|
+
) => {
|
|
13
|
+
return checkDatasetWrite(datasetId, user, userInfo)
|
|
14
|
+
.then(() => setDescription(datasetId, userInfo, { [field]: value }))
|
|
15
|
+
.then((description) => description)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const updateDescriptionList = updateDescription
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import Summary from
|
|
2
|
-
import { summary } from
|
|
3
|
-
import { issues } from
|
|
4
|
-
import { description } from
|
|
5
|
-
import { readme } from
|
|
6
|
-
import { getDraftRevision, updateDatasetRevision } from
|
|
7
|
-
import { checkDatasetWrite } from
|
|
8
|
-
import { getFiles } from
|
|
9
|
-
import { filterRemovedAnnexObjects } from
|
|
1
|
+
import Summary from "../../models/summary"
|
|
2
|
+
import { summary } from "./summary"
|
|
3
|
+
import { issues } from "./issues.js"
|
|
4
|
+
import { description } from "./description.js"
|
|
5
|
+
import { readme } from "./readme.js"
|
|
6
|
+
import { getDraftRevision, updateDatasetRevision } from "../../datalad/draft.js"
|
|
7
|
+
import { checkDatasetWrite } from "../permissions.js"
|
|
8
|
+
import { getFiles } from "../../datalad/files"
|
|
9
|
+
import { filterRemovedAnnexObjects } from "../utils/file.js"
|
|
10
10
|
|
|
11
11
|
// A draft must have a dataset parent
|
|
12
12
|
const draftFiles = async (dataset, args, { userInfo }) => {
|
|
@@ -19,7 +19,7 @@ const draftSize = async (dataset, args, { userInfo }) => {
|
|
|
19
19
|
const hexsha = await getDraftRevision(dataset.id)
|
|
20
20
|
return Summary.findOne({ datasetId: dataset.id, id: hexsha })
|
|
21
21
|
.exec()
|
|
22
|
-
.then(res => res?.toObject()?.size)
|
|
22
|
+
.then((res) => res?.toObject()?.size)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -44,15 +44,15 @@ export const revalidate = async (obj, { datasetId }, { user, userInfo }) => {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const draft = {
|
|
47
|
-
id: obj => obj.id,
|
|
47
|
+
id: (obj) => obj.id,
|
|
48
48
|
files: draftFiles,
|
|
49
49
|
size: draftSize,
|
|
50
50
|
summary,
|
|
51
51
|
issues,
|
|
52
|
-
modified: obj => obj.modified,
|
|
52
|
+
modified: (obj) => obj.modified,
|
|
53
53
|
description,
|
|
54
54
|
readme,
|
|
55
|
-
head: obj => obj.revision,
|
|
55
|
+
head: (obj) => obj.revision,
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export default draft
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import BadAnnexObject from
|
|
2
|
-
import { checkAdmin } from
|
|
1
|
+
import BadAnnexObject from "../../models/badAnnexObject"
|
|
2
|
+
import { checkAdmin } from "../permissions"
|
|
3
3
|
|
|
4
4
|
export const flaggedFiles = async (
|
|
5
5
|
obj,
|
|
@@ -8,6 +8,6 @@ export const flaggedFiles = async (
|
|
|
8
8
|
) => {
|
|
9
9
|
await checkAdmin(user, userInfo)
|
|
10
10
|
return BadAnnexObject.find({ flagged, removed: deleted })
|
|
11
|
-
.populate(
|
|
12
|
-
.populate(
|
|
11
|
+
.populate("flagger")
|
|
12
|
+
.populate("remover")
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { checkDatasetWrite } from
|
|
2
|
-
import { generateRepoToken } from
|
|
3
|
-
import { getDatasetEndpoint } from
|
|
1
|
+
import { checkDatasetWrite } from "../permissions.js"
|
|
2
|
+
import { generateRepoToken } from "../../libs/authentication/jwt"
|
|
3
|
+
import { getDatasetEndpoint } from "../../libs/datalad-service.js"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Generate a short lived token for git operations
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getDatasetWorker } from "../../libs/datalad-service"
|
|
2
|
+
|
|
3
|
+
export const history = async (obj) => {
|
|
4
|
+
const datasetId = obj.id
|
|
5
|
+
const historyUrl = `http://${
|
|
6
|
+
getDatasetWorker(
|
|
7
|
+
datasetId,
|
|
8
|
+
)
|
|
9
|
+
}/datasets/${datasetId}/history`
|
|
10
|
+
const resp = await fetch(historyUrl)
|
|
11
|
+
const { log } = await resp.json()
|
|
12
|
+
return log
|
|
13
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import IngestDataset from
|
|
2
|
-
import { checkDatasetWrite } from
|
|
3
|
-
import { getDatasetWorker } from
|
|
4
|
-
import { generateDataladCookie } from
|
|
5
|
-
import notifications from
|
|
6
|
-
import config from
|
|
1
|
+
import IngestDataset from "../../models/ingestDataset"
|
|
2
|
+
import { checkDatasetWrite } from "../permissions.js"
|
|
3
|
+
import { getDatasetWorker } from "../../libs/datalad-service"
|
|
4
|
+
import { generateDataladCookie } from "../../libs/authentication/jwt"
|
|
5
|
+
import notifications from "../../libs/notifications"
|
|
6
|
+
import config from "../../config"
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Test if a URL is allowed to be imported
|
|
@@ -17,10 +17,10 @@ export function allowedImportUrl(raw: string): boolean {
|
|
|
17
17
|
} catch (_) {
|
|
18
18
|
return false
|
|
19
19
|
}
|
|
20
|
-
if (url.hostname ===
|
|
20
|
+
if (url.hostname === "brainlife.io") {
|
|
21
21
|
return true
|
|
22
22
|
} else if (
|
|
23
|
-
url.hostname ===
|
|
23
|
+
url.hostname === "openneuro-test-import-bucket.s3.us-west-2.amazonaws.com"
|
|
24
24
|
) {
|
|
25
25
|
return true
|
|
26
26
|
} else {
|
|
@@ -46,11 +46,12 @@ export async function importRemoteDataset(
|
|
|
46
46
|
await ingest.save()
|
|
47
47
|
const importId = ingest._id.toString()
|
|
48
48
|
const worker = getDatasetWorker(datasetId)
|
|
49
|
-
const importUrl =
|
|
49
|
+
const importUrl =
|
|
50
|
+
`http://${worker}/datasets/${datasetId}/import/${importId}`
|
|
50
51
|
await fetch(importUrl, {
|
|
51
|
-
method:
|
|
52
|
+
method: "POST",
|
|
52
53
|
headers: {
|
|
53
|
-
|
|
54
|
+
"Content-Type": "application/json",
|
|
54
55
|
Cookie: generateDataladCookie(config)(userInfo),
|
|
55
56
|
},
|
|
56
57
|
body: JSON.stringify({ url }),
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { GraphQLDate, GraphQLDateTime, GraphQLTime } from "graphql-iso-date"
|
|
2
|
+
import GraphQLBigInt from "graphql-bigint"
|
|
3
|
+
import Query from "./query.js"
|
|
4
|
+
import Mutation from "./mutation.js"
|
|
5
|
+
import Dataset from "./dataset.js"
|
|
6
|
+
import Draft from "./draft.js"
|
|
7
|
+
import Snapshot from "./snapshots.js"
|
|
8
|
+
import User from "./user.js"
|
|
9
|
+
import Comment from "./comment.js"
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
// Scalars
|
|
13
|
+
Date: GraphQLDate,
|
|
14
|
+
Time: GraphQLTime,
|
|
15
|
+
DateTime: GraphQLDateTime,
|
|
16
|
+
BigInt: GraphQLBigInt,
|
|
17
|
+
// Complex types
|
|
18
|
+
Query,
|
|
19
|
+
Mutation,
|
|
20
|
+
User,
|
|
21
|
+
Dataset,
|
|
22
|
+
Draft,
|
|
23
|
+
Snapshot,
|
|
24
|
+
Comment,
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import Issue from
|
|
2
|
-
import { datasetType } from
|
|
3
|
-
import { revalidate } from
|
|
1
|
+
import Issue from "../../models/issue"
|
|
2
|
+
import { datasetType } from "./datasetType"
|
|
3
|
+
import { revalidate } from "./validation.js"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Issues resolver
|
|
@@ -11,12 +11,12 @@ export const issues = async (dataset, _, { userInfo }) => {
|
|
|
11
11
|
datasetId: dataset.id,
|
|
12
12
|
// Match if we have no validatorMetadata or the correct 'legacy' / 'schema' value if we do
|
|
13
13
|
$or: [
|
|
14
|
-
{
|
|
14
|
+
{ "validatorMetadata.validator": await datasetType(dataset) },
|
|
15
15
|
{ validatorMetadata: { $exists: false } },
|
|
16
16
|
],
|
|
17
17
|
})
|
|
18
18
|
.exec()
|
|
19
|
-
.then(data => {
|
|
19
|
+
.then((data) => {
|
|
20
20
|
if (!data && userInfo) {
|
|
21
21
|
// If no results were found, acquire a lock and run validation
|
|
22
22
|
revalidate(
|
|
@@ -32,17 +32,17 @@ export const issues = async (dataset, _, { userInfo }) => {
|
|
|
32
32
|
/**
|
|
33
33
|
* Snapshot issues resolver
|
|
34
34
|
*/
|
|
35
|
-
export const snapshotIssues = async snapshot => {
|
|
36
|
-
const datasetId = snapshot.id.split(
|
|
35
|
+
export const snapshotIssues = async (snapshot) => {
|
|
36
|
+
const datasetId = snapshot.id.split(":")[0]
|
|
37
37
|
return Issue.findOne({
|
|
38
38
|
id: snapshot.hexsha,
|
|
39
39
|
datasetId,
|
|
40
40
|
// Match if we have no validatorMetadata or the correct 'legacy' / 'schema' value if we do
|
|
41
41
|
$or: [
|
|
42
|
-
{
|
|
42
|
+
{ "validatorMetadata.validator": await datasetType(snapshot) },
|
|
43
43
|
{ validatorMetadata: { $exists: false } },
|
|
44
44
|
],
|
|
45
45
|
})
|
|
46
46
|
.exec()
|
|
47
|
-
.then(data => (data ? data.issues : null))
|
|
47
|
+
.then((data) => (data ? data.issues : null))
|
|
48
48
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import Snapshot from
|
|
2
|
-
import { LeanDocument } from
|
|
3
|
-
import DatasetModel from
|
|
4
|
-
import MetadataModel, { MetadataDocument } from
|
|
5
|
-
import { latestSnapshot } from
|
|
6
|
-
import { permissions } from
|
|
1
|
+
import Snapshot from "../../models/snapshot"
|
|
2
|
+
import { LeanDocument } from "mongoose"
|
|
3
|
+
import DatasetModel from "../../models/dataset"
|
|
4
|
+
import MetadataModel, { MetadataDocument } from "../../models/metadata"
|
|
5
|
+
import { latestSnapshot } from "./snapshots"
|
|
6
|
+
import { permissions } from "./permissions"
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Summary resolver
|
|
@@ -28,7 +28,7 @@ export const metadata = async (
|
|
|
28
28
|
const adminUsers = []
|
|
29
29
|
const { userPermissions } = await permissions(dataset)
|
|
30
30
|
for (const user of userPermissions) {
|
|
31
|
-
if (user.level ===
|
|
31
|
+
if (user.level === "admin") {
|
|
32
32
|
const userObj = await user.user
|
|
33
33
|
adminUsers.push(userObj.name)
|
|
34
34
|
}
|
|
@@ -50,7 +50,7 @@ export const metadata = async (
|
|
|
50
50
|
adminUsers,
|
|
51
51
|
firstSnapshotCreatedAt,
|
|
52
52
|
latestSnapshotCreatedAt: snapshot.created,
|
|
53
|
-
ages: summary?.subjectMetadata?.map(s => s.age as number),
|
|
53
|
+
ages: summary?.subjectMetadata?.map((s) => s.age as number),
|
|
54
54
|
modalities: summary?.modalities || [],
|
|
55
55
|
dataProcessed: summary?.dataProcessed || null,
|
|
56
56
|
}
|
|
@@ -5,41 +5,41 @@ import {
|
|
|
5
5
|
createDataset,
|
|
6
6
|
deleteDataset,
|
|
7
7
|
deleteFiles,
|
|
8
|
-
removeAnnexObject,
|
|
9
8
|
flagAnnexObject,
|
|
10
|
-
|
|
9
|
+
removeAnnexObject,
|
|
11
10
|
trackAnalytics,
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
updatePublic,
|
|
12
|
+
} from "./dataset.js"
|
|
13
|
+
import { updateRef } from "./draft.js"
|
|
14
14
|
import {
|
|
15
15
|
createSnapshot,
|
|
16
16
|
deleteSnapshot,
|
|
17
17
|
deprecateSnapshot,
|
|
18
18
|
undoDeprecateSnapshot,
|
|
19
|
-
} from
|
|
20
|
-
import { removeUser, setAdmin, setBlocked } from
|
|
21
|
-
import { updateSummary } from
|
|
22
|
-
import { revalidate, updateValidation } from
|
|
23
|
-
import {
|
|
24
|
-
import { followDataset } from
|
|
25
|
-
import { starDataset } from
|
|
26
|
-
import { publishDataset } from
|
|
27
|
-
import { updateDescription, updateDescriptionList } from
|
|
28
|
-
import { updateReadme } from
|
|
29
|
-
import { addComment,
|
|
30
|
-
import { subscribeToNewsletter } from
|
|
31
|
-
import { addMetadata } from
|
|
32
|
-
import {
|
|
33
|
-
import { prepareRepoAccess } from
|
|
34
|
-
import { cacheClear } from
|
|
35
|
-
import { reexportRemotes } from
|
|
36
|
-
import { resetDraft } from
|
|
37
|
-
import { createReviewer, deleteReviewer } from
|
|
38
|
-
import { createRelation, deleteRelation } from
|
|
19
|
+
} from "./snapshots.js"
|
|
20
|
+
import { removeUser, setAdmin, setBlocked } from "./user.js"
|
|
21
|
+
import { updateSummary } from "./summary"
|
|
22
|
+
import { revalidate, updateValidation } from "./validation.js"
|
|
23
|
+
import { removePermissions, updatePermissions } from "./permissions"
|
|
24
|
+
import { followDataset } from "./follow.js"
|
|
25
|
+
import { starDataset } from "./stars.js"
|
|
26
|
+
import { publishDataset } from "./publish.js"
|
|
27
|
+
import { updateDescription, updateDescriptionList } from "./description.js"
|
|
28
|
+
import { updateReadme } from "./readme.js"
|
|
29
|
+
import { addComment, deleteComment, editComment } from "./comment.js"
|
|
30
|
+
import { subscribeToNewsletter } from "./newsletter"
|
|
31
|
+
import { addMetadata } from "./metadata"
|
|
32
|
+
import { finishUpload, prepareUpload } from "./upload.js"
|
|
33
|
+
import { prepareRepoAccess } from "./git"
|
|
34
|
+
import { cacheClear } from "./cache"
|
|
35
|
+
import { reexportRemotes } from "./reexporter"
|
|
36
|
+
import { resetDraft } from "./reset"
|
|
37
|
+
import { createReviewer, deleteReviewer } from "./reviewer"
|
|
38
|
+
import { createRelation, deleteRelation } from "./relation"
|
|
39
39
|
import {
|
|
40
|
-
importRemoteDataset,
|
|
41
40
|
finishImportRemoteDataset,
|
|
42
|
-
|
|
41
|
+
importRemoteDataset,
|
|
42
|
+
} from "./importRemoteDataset"
|
|
43
43
|
|
|
44
44
|
const Mutation = {
|
|
45
45
|
createDataset,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Adds emails to newsletter mailing list.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import Newsletter from
|
|
7
|
+
import Newsletter from "../../models/newsletter"
|
|
8
8
|
|
|
9
9
|
// finds or adds email to newsletter collection
|
|
10
10
|
// returns true if email exists or is successfully created
|
|
@@ -13,7 +13,7 @@ export const subscribeToNewsletter = (obj, { email }) => {
|
|
|
13
13
|
// check if email is not empty
|
|
14
14
|
if (!email) return false
|
|
15
15
|
return Newsletter.create({ email })
|
|
16
|
-
.then(subscriber => Boolean(subscriber))
|
|
16
|
+
.then((subscriber) => Boolean(subscriber))
|
|
17
17
|
.catch(() => false)
|
|
18
18
|
}
|
|
19
19
|
|