@openneuro/server 4.20.5 → 4.20.6-alpha.2
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,8 +1,7 @@
|
|
|
1
|
-
import User, { UserDocument } from
|
|
2
|
-
import Permission, { PermissionDocument } from
|
|
3
|
-
import { checkDatasetAdmin } from
|
|
4
|
-
import { user } from
|
|
5
|
-
import pubsub from '../pubsub.js'
|
|
1
|
+
import User, { UserDocument } from "../../models/user"
|
|
2
|
+
import Permission, { PermissionDocument } from "../../models/permission"
|
|
3
|
+
import { checkDatasetAdmin } from "../permissions"
|
|
4
|
+
import { user } from "./user"
|
|
6
5
|
|
|
7
6
|
interface DatasetPermission {
|
|
8
7
|
id: string
|
|
@@ -14,16 +13,15 @@ export async function permissions(ds): Promise<DatasetPermission> {
|
|
|
14
13
|
return {
|
|
15
14
|
id: ds.id,
|
|
16
15
|
userPermissions: permissions.map(
|
|
17
|
-
userPermission =>
|
|
18
|
-
(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} as PermissionDocument & { user: Promise<UserDocument> }),
|
|
16
|
+
(userPermission) => ({
|
|
17
|
+
...userPermission.toJSON(),
|
|
18
|
+
user: user(ds, { id: userPermission.userId }),
|
|
19
|
+
} as PermissionDocument & { user: Promise<UserDocument> }),
|
|
22
20
|
),
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
const publishPermissions = async datasetId => {
|
|
24
|
+
const publishPermissions = async (datasetId) => {
|
|
27
25
|
// Create permissionsUpdated object with DatasetPermissions in Dataset
|
|
28
26
|
// and resolve all promises before publishing
|
|
29
27
|
const ds = { id: datasetId }
|
|
@@ -33,17 +31,13 @@ const publishPermissions = async datasetId => {
|
|
|
33
31
|
permissions: {
|
|
34
32
|
id,
|
|
35
33
|
userPermissions: await Promise.all(
|
|
36
|
-
userPermissions.map(async userPermission => ({
|
|
34
|
+
userPermissions.map(async (userPermission) => ({
|
|
37
35
|
...userPermission,
|
|
38
36
|
user: await user(ds, { id: userPermission.userId }),
|
|
39
37
|
})),
|
|
40
38
|
),
|
|
41
39
|
},
|
|
42
40
|
}
|
|
43
|
-
pubsub.publish('permissionsUpdated', {
|
|
44
|
-
datasetId,
|
|
45
|
-
permissionsUpdated,
|
|
46
|
-
})
|
|
47
41
|
}
|
|
48
42
|
|
|
49
43
|
/**
|
|
@@ -53,14 +47,14 @@ export const updatePermissions = async (obj, args, { user, userInfo }) => {
|
|
|
53
47
|
await checkDatasetAdmin(args.datasetId, user, userInfo)
|
|
54
48
|
// get all users the the email specified by permissions arg
|
|
55
49
|
const users = await User.find({ email: args.userEmail })
|
|
56
|
-
.collation({ locale:
|
|
50
|
+
.collation({ locale: "en", strength: 2 })
|
|
57
51
|
.exec()
|
|
58
52
|
|
|
59
53
|
if (!users.length) {
|
|
60
|
-
throw new Error(
|
|
54
|
+
throw new Error("A user with that email address does not exist")
|
|
61
55
|
}
|
|
62
56
|
|
|
63
|
-
const userPromises = users.map(user => {
|
|
57
|
+
const userPromises = users.map((user) => {
|
|
64
58
|
return new Promise<void>((resolve, reject) => {
|
|
65
59
|
Permission.updateOne(
|
|
66
60
|
{
|
|
@@ -76,11 +70,11 @@ export const updatePermissions = async (obj, args, { user, userInfo }) => {
|
|
|
76
70
|
)
|
|
77
71
|
.exec()
|
|
78
72
|
.then(() => resolve())
|
|
79
|
-
.catch(err => reject(err))
|
|
73
|
+
.catch((err) => reject(err))
|
|
80
74
|
})
|
|
81
75
|
})
|
|
82
76
|
return Promise.all(userPromises).then(() =>
|
|
83
|
-
publishPermissions(args.datasetId)
|
|
77
|
+
publishPermissions(args.datasetId)
|
|
84
78
|
)
|
|
85
79
|
}
|
|
86
80
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import config from "../../config"
|
|
2
|
+
import request from "superagent"
|
|
3
|
+
import { updatePublic } from "../../datalad/dataset"
|
|
4
|
+
import { checkDatasetWrite } from "../permissions.js"
|
|
5
|
+
import { generateDataladCookie } from "../../libs/authentication/jwt"
|
|
6
|
+
import { getDatasetWorker } from "../../libs/datalad-service"
|
|
7
|
+
|
|
8
|
+
export const publishDataset = (obj, { datasetId }, { user, userInfo }) => {
|
|
9
|
+
return checkDatasetWrite(datasetId, user, userInfo).then(async () => {
|
|
10
|
+
await updatePublic(datasetId, true)
|
|
11
|
+
const uri = `${getDatasetWorker(datasetId)}/datasets/${datasetId}/publish`
|
|
12
|
+
return await request
|
|
13
|
+
.post(uri)
|
|
14
|
+
.set("Cookie", generateDataladCookie(config)(userInfo))
|
|
15
|
+
.then(() => true)
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top level query
|
|
3
|
+
*/
|
|
4
|
+
import { dataset, datasets } from "./dataset.js"
|
|
5
|
+
import { participantCount, snapshot } from "./snapshots.js"
|
|
6
|
+
import { user, users } from "./user.js"
|
|
7
|
+
import { flaggedFiles } from "./flaggedFiles"
|
|
8
|
+
import { publicMetadata } from "./metadata"
|
|
9
|
+
|
|
10
|
+
const Query = {
|
|
11
|
+
dataset,
|
|
12
|
+
datasets,
|
|
13
|
+
user,
|
|
14
|
+
users,
|
|
15
|
+
snapshot,
|
|
16
|
+
participantCount,
|
|
17
|
+
flaggedFiles,
|
|
18
|
+
publicMetadata,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default Query
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Resolver implementation for README files
|
|
3
3
|
* This stub is here in case draft.readme or snapshot.readme needs future extension
|
|
4
4
|
*/
|
|
5
|
-
import { setReadme } from
|
|
6
|
-
import { checkDatasetWrite } from
|
|
7
|
-
export { readme } from
|
|
5
|
+
import { setReadme } from "../../datalad/readme"
|
|
6
|
+
import { checkDatasetWrite } from "../permissions"
|
|
7
|
+
export { readme } from "../../datalad/readme"
|
|
8
8
|
|
|
9
9
|
export const updateReadme = (obj, { datasetId, value }, { user, userInfo }) => {
|
|
10
10
|
return checkDatasetWrite(datasetId, user, userInfo).then(() => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolver for rerunning remote exports.
|
|
3
3
|
*/
|
|
4
|
-
import { checkAdmin } from
|
|
5
|
-
import { runReexporter } from
|
|
4
|
+
import { checkAdmin } from "../permissions"
|
|
5
|
+
import { runReexporter } from "../../datalad/reexporter"
|
|
6
6
|
|
|
7
7
|
export const reexportRemotes = async (
|
|
8
8
|
obj,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import Dataset from
|
|
2
|
-
import { checkDatasetAdmin } from
|
|
3
|
-
import { DOIPattern } from
|
|
1
|
+
import Dataset from "../../models/dataset"
|
|
2
|
+
import { checkDatasetAdmin } from "../permissions"
|
|
3
|
+
import { DOIPattern } from "../../libs/doi/normalize"
|
|
4
4
|
|
|
5
5
|
export const createRelation = async (
|
|
6
6
|
obj,
|
|
@@ -9,9 +9,9 @@ export const createRelation = async (
|
|
|
9
9
|
) => {
|
|
10
10
|
await checkDatasetAdmin(datasetId, user, userInfo)
|
|
11
11
|
// Validate the right DOI format
|
|
12
|
-
if (!doi.startsWith(
|
|
12
|
+
if (!doi.startsWith("doi:") || !doi.slice(4).match(DOIPattern)) {
|
|
13
13
|
throw new Error(
|
|
14
|
-
|
|
14
|
+
"DOI format must follow BIDS recommended format (see https://bids-specification.readthedocs.io/en/stable/02-common-principles.html#uniform-resource-indicator)",
|
|
15
15
|
)
|
|
16
16
|
}
|
|
17
17
|
const dataset = await Dataset.findOneAndUpdate(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { checkDatasetWrite } from
|
|
2
|
-
import { resetDraft as resetDraftTask } from
|
|
1
|
+
import { checkDatasetWrite } from "../permissions"
|
|
2
|
+
import { resetDraft as resetDraftTask } from "../../datalad/draft"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Mutation to move the draft HEAD reference forward or backward
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import config from
|
|
2
|
-
import Reviewer from
|
|
3
|
-
import { checkDatasetAdmin } from
|
|
4
|
-
import { generateReviewerToken } from
|
|
1
|
+
import config from "../../config"
|
|
2
|
+
import Reviewer from "../../models/reviewer"
|
|
3
|
+
import { checkDatasetAdmin } from "../permissions.js"
|
|
4
|
+
import { generateReviewerToken } from "../../libs/authentication/jwt"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Create an anonymous read-only access key
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import * as datalad from
|
|
2
|
-
import {
|
|
3
|
-
import { onBrainlife } from
|
|
4
|
-
import { checkDatasetRead, checkDatasetWrite } from
|
|
5
|
-
import { readme } from
|
|
6
|
-
import { description } from
|
|
7
|
-
import { summary } from
|
|
8
|
-
import { snapshotIssues } from
|
|
9
|
-
import { getFiles } from
|
|
10
|
-
import Summary from
|
|
11
|
-
import DatasetModel from
|
|
12
|
-
import { filterRemovedAnnexObjects } from
|
|
13
|
-
import DeprecatedSnapshot from
|
|
14
|
-
import { redis } from
|
|
15
|
-
import CacheItem, { CacheType } from
|
|
16
|
-
import { normalizeDOI } from
|
|
17
|
-
import { getDraftHead } from
|
|
18
|
-
import { downloadFiles } from
|
|
1
|
+
import * as datalad from "../../datalad/snapshots"
|
|
2
|
+
import { analytics, dataset, snapshotCreationComparison } from "./dataset.js"
|
|
3
|
+
import { onBrainlife } from "./brainlife"
|
|
4
|
+
import { checkDatasetRead, checkDatasetWrite } from "../permissions"
|
|
5
|
+
import { readme } from "./readme.js"
|
|
6
|
+
import { description } from "./description.js"
|
|
7
|
+
import { summary } from "./summary"
|
|
8
|
+
import { snapshotIssues } from "./issues.js"
|
|
9
|
+
import { getFiles } from "../../datalad/files"
|
|
10
|
+
import Summary from "../../models/summary"
|
|
11
|
+
import DatasetModel from "../../models/dataset"
|
|
12
|
+
import { filterRemovedAnnexObjects } from "../utils/file"
|
|
13
|
+
import DeprecatedSnapshot from "../../models/deprecatedSnapshot"
|
|
14
|
+
import { redis } from "../../libs/redis"
|
|
15
|
+
import CacheItem, { CacheType } from "../../cache/item"
|
|
16
|
+
import { normalizeDOI } from "../../libs/doi/normalize"
|
|
17
|
+
import { getDraftHead } from "../../datalad/dataset"
|
|
18
|
+
import { downloadFiles } from "../../datalad/snapshots"
|
|
19
19
|
|
|
20
|
-
export const snapshots = obj => {
|
|
20
|
+
export const snapshots = (obj) => {
|
|
21
21
|
return datalad.getSnapshots(obj.id)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export const snapshot = (obj, { datasetId, tag }, context) => {
|
|
25
25
|
return checkDatasetRead(datasetId, context.user, context.userInfo).then(
|
|
26
26
|
() => {
|
|
27
|
-
return datalad.getSnapshot(datasetId, tag).then(snapshot => ({
|
|
27
|
+
return datalad.getSnapshot(datasetId, tag).then((snapshot) => ({
|
|
28
28
|
...snapshot,
|
|
29
29
|
dataset: () => dataset(snapshot, { id: datasetId }, context),
|
|
30
30
|
description: () => description(snapshot),
|
|
@@ -37,7 +37,7 @@ export const snapshot = (obj, { datasetId, tag }, context) => {
|
|
|
37
37
|
size: () =>
|
|
38
38
|
Summary.findOne({ datasetId: datasetId, id: snapshot.hexsha })
|
|
39
39
|
.exec()
|
|
40
|
-
.then(res => res?.toObject()?.size),
|
|
40
|
+
.then((res) => res?.toObject()?.size),
|
|
41
41
|
deprecated: () => deprecated({ datasetId, tag }),
|
|
42
42
|
related: () => related(datasetId),
|
|
43
43
|
onBrainlife: () => onBrainlife(snapshot),
|
|
@@ -56,23 +56,23 @@ export const deprecated = ({ datasetId, tag }) => {
|
|
|
56
56
|
* Search dataset metadeta for related objects and return an array
|
|
57
57
|
* @param {string} datasetId
|
|
58
58
|
*/
|
|
59
|
-
export const related = async datasetId => {
|
|
59
|
+
export const related = async (datasetId) => {
|
|
60
60
|
const dataset = await DatasetModel.findOne({ id: datasetId }).lean().exec()
|
|
61
61
|
return dataset.related
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
export const matchKnownObjects = desc => {
|
|
64
|
+
export const matchKnownObjects = (desc) => {
|
|
65
65
|
if (desc?.ReferencesAndLinks) {
|
|
66
66
|
const objects = []
|
|
67
67
|
for (const item of desc.ReferencesAndLinks) {
|
|
68
68
|
try {
|
|
69
69
|
const rawDOI = normalizeDOI(item)
|
|
70
70
|
// NIMH Data Archive (NDA) 10.15154
|
|
71
|
-
if (rawDOI.startsWith(
|
|
71
|
+
if (rawDOI.startsWith("10.15154")) {
|
|
72
72
|
objects.push({
|
|
73
73
|
id: rawDOI,
|
|
74
|
-
source:
|
|
75
|
-
type:
|
|
74
|
+
source: "NDA",
|
|
75
|
+
type: "dataset",
|
|
76
76
|
})
|
|
77
77
|
} else {
|
|
78
78
|
objects.push({ id: rawDOI })
|
|
@@ -138,24 +138,24 @@ export const participantCount = (obj, { modality }) => {
|
|
|
138
138
|
const cache = new CacheItem(
|
|
139
139
|
redis,
|
|
140
140
|
CacheType.participantCount,
|
|
141
|
-
[modality ||
|
|
141
|
+
[modality || "all"],
|
|
142
142
|
3600,
|
|
143
143
|
)
|
|
144
144
|
return cache.get(async () => {
|
|
145
145
|
const queryHasSubjects = {
|
|
146
|
-
|
|
146
|
+
"summary.subjects": {
|
|
147
147
|
$exists: true,
|
|
148
148
|
},
|
|
149
149
|
}
|
|
150
150
|
const matchQuery = modality
|
|
151
151
|
? {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
152
|
+
$and: [
|
|
153
|
+
queryHasSubjects,
|
|
154
|
+
{
|
|
155
|
+
"summary.modalities.0": modality,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
}
|
|
159
159
|
: queryHasSubjects
|
|
160
160
|
const aggregateResult = await DatasetModel.aggregate([
|
|
161
161
|
{
|
|
@@ -165,24 +165,24 @@ export const participantCount = (obj, { modality }) => {
|
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
$lookup: {
|
|
168
|
-
from:
|
|
169
|
-
localField:
|
|
170
|
-
foreignField:
|
|
171
|
-
as:
|
|
168
|
+
from: "snapshots",
|
|
169
|
+
localField: "id",
|
|
170
|
+
foreignField: "datasetId",
|
|
171
|
+
as: "snapshots",
|
|
172
172
|
},
|
|
173
173
|
},
|
|
174
174
|
{
|
|
175
175
|
$project: {
|
|
176
|
-
id:
|
|
177
|
-
hexsha: { $arrayElemAt: [
|
|
176
|
+
id: "$id",
|
|
177
|
+
hexsha: { $arrayElemAt: ["$snapshots.hexsha", -1] },
|
|
178
178
|
},
|
|
179
179
|
},
|
|
180
180
|
{
|
|
181
181
|
$lookup: {
|
|
182
|
-
from:
|
|
183
|
-
localField:
|
|
184
|
-
foreignField:
|
|
185
|
-
as:
|
|
182
|
+
from: "summaries",
|
|
183
|
+
localField: "hexsha",
|
|
184
|
+
foreignField: "id",
|
|
185
|
+
as: "summary",
|
|
186
186
|
},
|
|
187
187
|
},
|
|
188
188
|
{
|
|
@@ -192,7 +192,7 @@ export const participantCount = (obj, { modality }) => {
|
|
|
192
192
|
$group: {
|
|
193
193
|
_id: null,
|
|
194
194
|
participantCount: {
|
|
195
|
-
$sum: { $size: { $arrayElemAt: [
|
|
195
|
+
$sum: { $size: { $arrayElemAt: ["$summary.subjects", 0] } },
|
|
196
196
|
},
|
|
197
197
|
},
|
|
198
198
|
},
|
|
@@ -206,7 +206,7 @@ export const participantCount = (obj, { modality }) => {
|
|
|
206
206
|
* Select the most recent snapshot from an array of snapshots
|
|
207
207
|
* @param {*} snapshots Array of snapshot objects from datalad.getSnapshots
|
|
208
208
|
*/
|
|
209
|
-
export const filterLatestSnapshot = snapshots => {
|
|
209
|
+
export const filterLatestSnapshot = (snapshots) => {
|
|
210
210
|
if (snapshots.length) {
|
|
211
211
|
const sortedSnapshots = Array.prototype.sort.call(
|
|
212
212
|
snapshots,
|
|
@@ -256,8 +256,8 @@ export const deleteSnapshot = (obj, { datasetId, tag }, { user, userInfo }) => {
|
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
const Snapshot = {
|
|
259
|
-
analytics: snapshot => analytics(snapshot),
|
|
260
|
-
issues: snapshot => snapshotIssues(snapshot),
|
|
259
|
+
analytics: (snapshot) => analytics(snapshot),
|
|
260
|
+
issues: (snapshot) => snapshotIssues(snapshot),
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
export default Snapshot
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import Summary, { SummaryDocument } from
|
|
2
|
-
import { datasetType } from
|
|
1
|
+
import Summary, { SummaryDocument } from "../../models/summary"
|
|
2
|
+
import { datasetType } from "./datasetType"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Summary resolver
|
|
@@ -11,7 +11,7 @@ export async function summary(dataset): Promise<Partial<SummaryDocument>> {
|
|
|
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
|
}).exec()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import Upload from
|
|
2
|
-
import { checkDatasetWrite } from
|
|
3
|
-
import { generateUploadToken } from
|
|
4
|
-
import { finishUploadRequest } from
|
|
5
|
-
import { getDatasetEndpoint } from
|
|
1
|
+
import Upload from "../../models/upload"
|
|
2
|
+
import { checkDatasetWrite } from "../permissions.js"
|
|
3
|
+
import { generateUploadToken } from "../../libs/authentication/jwt"
|
|
4
|
+
import { finishUploadRequest } from "../../datalad/upload.js"
|
|
5
|
+
import { getDatasetEndpoint } from "../../libs/datalad-service.js"
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Track initial state for a new upload
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* User resolvers
|
|
3
|
-
*
|
|
4
|
-
* These are passthroughs to SciTran until we have authentication working internally
|
|
5
3
|
*/
|
|
6
|
-
import User from
|
|
4
|
+
import User from "../../models/user"
|
|
7
5
|
|
|
8
6
|
export const user = (obj, { id }) => {
|
|
9
7
|
return User.findOne({ id }).exec()
|
|
@@ -14,7 +12,7 @@ export const users = (obj, args, { userInfo }) => {
|
|
|
14
12
|
return User.find().exec()
|
|
15
13
|
} else {
|
|
16
14
|
return Promise.reject(
|
|
17
|
-
new Error(
|
|
15
|
+
new Error("You must be a site admin to retrieve users"),
|
|
18
16
|
)
|
|
19
17
|
}
|
|
20
18
|
}
|
|
@@ -23,7 +21,7 @@ export const removeUser = (obj, { id }, { userInfo }) => {
|
|
|
23
21
|
if (userInfo.admin) {
|
|
24
22
|
return User.findByIdAndRemove(id).exec()
|
|
25
23
|
} else {
|
|
26
|
-
return Promise.reject(new Error(
|
|
24
|
+
return Promise.reject(new Error("You must be a site admin to remove users"))
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
27
|
|
|
@@ -32,7 +30,7 @@ export const setAdmin = (obj, { id, admin }, { userInfo }) => {
|
|
|
32
30
|
return User.findOneAndUpdate({ id }, { admin }).exec()
|
|
33
31
|
} else {
|
|
34
32
|
return Promise.reject(
|
|
35
|
-
new Error(
|
|
33
|
+
new Error("You must be a site admin to modify this value"),
|
|
36
34
|
)
|
|
37
35
|
}
|
|
38
36
|
}
|
|
@@ -41,22 +39,22 @@ export const setBlocked = (obj, { id, blocked }, { userInfo }) => {
|
|
|
41
39
|
if (userInfo.admin) {
|
|
42
40
|
return User.findOneAndUpdate({ id }, { blocked }).exec()
|
|
43
41
|
} else {
|
|
44
|
-
return Promise.reject(new Error(
|
|
42
|
+
return Promise.reject(new Error("You must be a site admin to block a user"))
|
|
45
43
|
}
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
const UserResolvers = {
|
|
49
|
-
id: obj => obj.id,
|
|
50
|
-
provider: obj => obj.provider,
|
|
51
|
-
avatar: obj => obj.avatar,
|
|
52
|
-
orcid: obj => obj.orcid,
|
|
53
|
-
created: obj => obj.created,
|
|
54
|
-
modified: obj => obj.modified,
|
|
55
|
-
lastSeen: obj => obj.lastSeen,
|
|
56
|
-
email: obj => obj.email,
|
|
57
|
-
name: obj => obj.name,
|
|
58
|
-
admin: obj => obj.admin,
|
|
59
|
-
blocked: obj => obj.blocked,
|
|
47
|
+
id: (obj) => obj.id,
|
|
48
|
+
provider: (obj) => obj.provider,
|
|
49
|
+
avatar: (obj) => obj.avatar,
|
|
50
|
+
orcid: (obj) => obj.orcid,
|
|
51
|
+
created: (obj) => obj.created,
|
|
52
|
+
modified: (obj) => obj.modified,
|
|
53
|
+
lastSeen: (obj) => obj.lastSeen,
|
|
54
|
+
email: (obj) => obj.email,
|
|
55
|
+
name: (obj) => obj.name,
|
|
56
|
+
admin: (obj) => obj.admin,
|
|
57
|
+
blocked: (obj) => obj.blocked,
|
|
60
58
|
}
|
|
61
59
|
|
|
62
60
|
export default UserResolvers
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import config from
|
|
2
|
-
import { generateDataladCookie } from
|
|
3
|
-
import { getDatasetWorker } from
|
|
4
|
-
import Issue from
|
|
5
|
-
import
|
|
6
|
-
import { redlock } from '../../libs/redis.js'
|
|
1
|
+
import config from "../../config"
|
|
2
|
+
import { generateDataladCookie } from "../../libs/authentication/jwt"
|
|
3
|
+
import { getDatasetWorker } from "../../libs/datalad-service"
|
|
4
|
+
import Issue from "../../models/issue"
|
|
5
|
+
import { redlock } from "../../libs/redis"
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Save issues data returned by the datalad service
|
|
@@ -23,16 +22,15 @@ export const updateValidation = (obj, args) => {
|
|
|
23
22
|
},
|
|
24
23
|
)
|
|
25
24
|
.exec()
|
|
26
|
-
.then(() =>
|
|
27
|
-
publishDraftUpdate(args.validation.datasetId, args.validation.id)
|
|
28
|
-
return true
|
|
29
|
-
})
|
|
25
|
+
.then(() => true)
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
export const validationUrl = (datasetId, ref) => {
|
|
33
|
-
return `http://${
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
return `http://${
|
|
30
|
+
getDatasetWorker(
|
|
31
|
+
datasetId,
|
|
32
|
+
)
|
|
33
|
+
}/datasets/${datasetId}/validate/${ref}`
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
/**
|
|
@@ -47,7 +45,7 @@ export const revalidate = async (obj, { datasetId, ref }, { userInfo }) => {
|
|
|
47
45
|
// Lock for five minutes to avoid stacking up multiple validation requests
|
|
48
46
|
await redlock.lock(`openneuro:revalidate-lock:${datasetId}:${ref}`, 300000)
|
|
49
47
|
const response = await fetch(validationUrl(datasetId, ref), {
|
|
50
|
-
method:
|
|
48
|
+
method: "POST",
|
|
51
49
|
body: JSON.stringify({}),
|
|
52
50
|
headers: {
|
|
53
51
|
cookie: generateDataladCookie(config)(userInfo),
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import { schemaComposer } from
|
|
3
|
-
import resolvers from
|
|
4
|
-
import Subscription from './resolvers/subscriptions.js'
|
|
2
|
+
import { schemaComposer } from "graphql-compose"
|
|
3
|
+
import resolvers from "./resolvers"
|
|
5
4
|
import {
|
|
6
|
-
datasetSearch,
|
|
7
5
|
advancedDatasetSearch,
|
|
8
|
-
|
|
6
|
+
datasetSearch,
|
|
7
|
+
} from "./resolvers/dataset-search"
|
|
9
8
|
|
|
10
9
|
export const typeDefs = `
|
|
11
10
|
scalar Date
|
|
@@ -818,7 +817,6 @@ export const typeDefs = `
|
|
|
818
817
|
|
|
819
818
|
schemaComposer.addTypeDefs(typeDefs)
|
|
820
819
|
schemaComposer.addResolveMethods(resolvers)
|
|
821
|
-
schemaComposer.Subscription.addFields(Subscription)
|
|
822
820
|
schemaComposer.Query.addFields(datasetSearch)
|
|
823
821
|
schemaComposer.Query.addFields(advancedDatasetSearch)
|
|
824
822
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import BadAnnexObject from
|
|
1
|
+
import BadAnnexObject from "../../models/badAnnexObject"
|
|
2
2
|
|
|
3
3
|
export const filterRemovedAnnexObjects =
|
|
4
|
-
(datasetId, userInfo) => async files => {
|
|
4
|
+
(datasetId, userInfo) => async (files) => {
|
|
5
5
|
const removedAnnexObjectKeys = (
|
|
6
6
|
await BadAnnexObject.find({ datasetId }).exec()
|
|
7
7
|
).map(({ annexKey }) => annexKey)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import notifications from
|
|
3
|
-
import { format } from
|
|
4
|
-
import User from
|
|
5
|
-
import Comment from
|
|
6
|
-
import MailgunIdentifier from
|
|
7
|
-
import { ContentState, convertFromHTML, convertToRaw } from
|
|
8
|
-
import mongoose from
|
|
2
|
+
import notifications from "../libs/notifications.js"
|
|
3
|
+
import { format } from "date-fns/format"
|
|
4
|
+
import User from "../models/user"
|
|
5
|
+
import Comment from "../models/comment"
|
|
6
|
+
import MailgunIdentifier from "../models/mailgunIdentifier"
|
|
7
|
+
import { ContentState, convertFromHTML, convertToRaw } from "draft-js"
|
|
8
|
+
import mongoose from "mongoose"
|
|
9
9
|
const ObjectID = mongoose.Schema.Types.ObjectId
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -15,7 +15,7 @@ const ObjectID = mongoose.Schema.Types.ObjectId
|
|
|
15
15
|
* item that can be stored as if it came from
|
|
16
16
|
* a client-side draft.js editor
|
|
17
17
|
*/
|
|
18
|
-
const textToDraft = text => {
|
|
18
|
+
const textToDraft = (text) => {
|
|
19
19
|
return JSON.stringify(
|
|
20
20
|
convertToRaw(ContentState.createFromBlockArray(convertFromHTML(text))),
|
|
21
21
|
)
|
|
@@ -36,10 +36,10 @@ export async function reply(req, res, next) {
|
|
|
36
36
|
const userId = req.params.userId
|
|
37
37
|
? decodeURIComponent(req.params.userId)
|
|
38
38
|
: null
|
|
39
|
-
const text = textToDraft(req.body[
|
|
40
|
-
const inReplyToRaw = req.body[
|
|
39
|
+
const text = textToDraft(req.body["stripped-text"])
|
|
40
|
+
const inReplyToRaw = req.body["In-Reply-To"]
|
|
41
41
|
const inReplyTo = inReplyToRaw
|
|
42
|
-
? inReplyToRaw.replace(
|
|
42
|
+
? inReplyToRaw.replace("<", "").replace(">", "")
|
|
43
43
|
: null
|
|
44
44
|
const messageId = inReplyTo
|
|
45
45
|
? await MailgunIdentifier.findOne({ messageId: inReplyTo }).exec()
|
|
@@ -22,5 +22,5 @@ const config = {
|
|
|
22
22
|
// Provide some environment variables to the client
|
|
23
23
|
export const clientConfig = (req, res) => {
|
|
24
24
|
const configScript = `window.OpenNeuroConfig = ${JSON.stringify(config)}`
|
|
25
|
-
res.type(
|
|
25
|
+
res.type("text/javascript").send(configScript)
|
|
26
26
|
}
|