@openneuro/server 4.20.4 → 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,28 +1,28 @@
|
|
|
1
1
|
// dependencies ------------------------------------
|
|
2
2
|
|
|
3
|
-
import express from
|
|
4
|
-
import * as users from
|
|
5
|
-
import * as datalad from
|
|
6
|
-
import * as comments from
|
|
7
|
-
import { clientConfig } from
|
|
8
|
-
import * as subscriptions from
|
|
9
|
-
import verifyUser from
|
|
10
|
-
import * as google from
|
|
11
|
-
import * as orcid from
|
|
12
|
-
import * as jwt from
|
|
13
|
-
import * as auth from
|
|
14
|
-
import * as doi from
|
|
15
|
-
import { sitemapHandler } from
|
|
16
|
-
import { reviewerHandler } from
|
|
3
|
+
import express from "express"
|
|
4
|
+
import * as users from "./handlers/users"
|
|
5
|
+
import * as datalad from "./handlers/datalad"
|
|
6
|
+
import * as comments from "./handlers/comments"
|
|
7
|
+
import { clientConfig } from "./handlers/config"
|
|
8
|
+
import * as subscriptions from "./handlers/subscriptions"
|
|
9
|
+
import verifyUser from "./libs/authentication/verifyUser"
|
|
10
|
+
import * as google from "./libs/authentication/google"
|
|
11
|
+
import * as orcid from "./libs/authentication/orcid"
|
|
12
|
+
import * as jwt from "./libs/authentication/jwt"
|
|
13
|
+
import * as auth from "./libs/authentication/states"
|
|
14
|
+
import * as doi from "./handlers/doi"
|
|
15
|
+
import { sitemapHandler } from "./handlers/sitemap"
|
|
16
|
+
import { reviewerHandler } from "./handlers/reviewer"
|
|
17
17
|
|
|
18
18
|
const noCache = (req, res, next) => {
|
|
19
|
-
res.setHeader(
|
|
19
|
+
res.setHeader("Surrogate-Control", "no-store")
|
|
20
20
|
res.setHeader(
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
"Cache-Control",
|
|
22
|
+
"no-store, no-cache, must-revalidate, proxy-revalidate",
|
|
23
23
|
)
|
|
24
|
-
res.setHeader(
|
|
25
|
-
res.setHeader(
|
|
24
|
+
res.setHeader("Pragma", "no-cache")
|
|
25
|
+
res.setHeader("Expires", "0")
|
|
26
26
|
|
|
27
27
|
next()
|
|
28
28
|
}
|
|
@@ -30,22 +30,22 @@ const noCache = (req, res, next) => {
|
|
|
30
30
|
const routes = [
|
|
31
31
|
// Health check --------------------------------
|
|
32
32
|
{
|
|
33
|
-
method:
|
|
34
|
-
url:
|
|
33
|
+
method: "get",
|
|
34
|
+
url: "/",
|
|
35
35
|
handler: (req, res) => {
|
|
36
36
|
res.sendStatus(200)
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
// React config --------------------------------
|
|
40
40
|
{
|
|
41
|
-
method:
|
|
42
|
-
url:
|
|
41
|
+
method: "get",
|
|
42
|
+
url: "/config.js",
|
|
43
43
|
handler: clientConfig,
|
|
44
44
|
},
|
|
45
45
|
// users ---------------------------------------
|
|
46
46
|
{
|
|
47
|
-
method:
|
|
48
|
-
url:
|
|
47
|
+
method: "get",
|
|
48
|
+
url: "/users/self",
|
|
49
49
|
middleware: [noCache, jwt.authenticate, auth.authenticated],
|
|
50
50
|
handler: verifyUser,
|
|
51
51
|
},
|
|
@@ -53,78 +53,78 @@ const routes = [
|
|
|
53
53
|
// comments --------------------------------------
|
|
54
54
|
|
|
55
55
|
{
|
|
56
|
-
method:
|
|
57
|
-
url:
|
|
56
|
+
method: "post",
|
|
57
|
+
url: "/comments/reply/:commentId/:userId",
|
|
58
58
|
handler: comments.reply,
|
|
59
59
|
},
|
|
60
60
|
|
|
61
61
|
// subscriptions ----------------------------------------
|
|
62
62
|
|
|
63
63
|
{
|
|
64
|
-
method:
|
|
65
|
-
url:
|
|
64
|
+
method: "get",
|
|
65
|
+
url: "/subscriptions/:datasetId",
|
|
66
66
|
handler: subscriptions.getSubscriptions,
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
|
-
method:
|
|
70
|
-
url:
|
|
69
|
+
method: "get",
|
|
70
|
+
url: "/subscriptions/:datasetId/:userId",
|
|
71
71
|
middleware: [noCache],
|
|
72
72
|
handler: subscriptions.checkUserSubscription,
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
|
-
method:
|
|
76
|
-
url:
|
|
75
|
+
method: "post",
|
|
76
|
+
url: "/subscriptions/:datasetId",
|
|
77
77
|
middleware: [jwt.authenticate, auth.authenticated],
|
|
78
78
|
handler: subscriptions.create,
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
|
-
method:
|
|
82
|
-
url:
|
|
81
|
+
method: "delete",
|
|
82
|
+
url: "/subscriptions/:datasetId/:userId",
|
|
83
83
|
middleware: [jwt.authenticate, auth.authenticated],
|
|
84
84
|
handler: subscriptions.deleteSubscription,
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
|
-
method:
|
|
88
|
-
url:
|
|
87
|
+
method: "delete",
|
|
88
|
+
url: "/subscriptions/:datasetId",
|
|
89
89
|
middleware: [jwt.authenticate, auth.authenticated],
|
|
90
90
|
handler: subscriptions.deleteAll,
|
|
91
91
|
},
|
|
92
92
|
|
|
93
93
|
// dataset doi ----------------------------------------
|
|
94
94
|
{
|
|
95
|
-
method:
|
|
96
|
-
url:
|
|
95
|
+
method: "post",
|
|
96
|
+
url: "/doi/:datasetId/:snapshotId",
|
|
97
97
|
middleware: [jwt.authenticate, auth.authenticated],
|
|
98
98
|
handler: doi.createSnapshotDoi,
|
|
99
99
|
},
|
|
100
100
|
{
|
|
101
|
-
method:
|
|
102
|
-
url:
|
|
101
|
+
method: "get",
|
|
102
|
+
url: "/doi/:datasetId/:snapshotId",
|
|
103
103
|
handler: doi.getDoi,
|
|
104
104
|
},
|
|
105
105
|
|
|
106
106
|
// generate CLI API keys ------------------------------
|
|
107
107
|
{
|
|
108
|
-
method:
|
|
109
|
-
url:
|
|
108
|
+
method: "post",
|
|
109
|
+
url: "/keygen",
|
|
110
110
|
middleware: [noCache, jwt.authenticate, auth.authenticated],
|
|
111
111
|
handler: users.createAPIKey,
|
|
112
112
|
},
|
|
113
113
|
|
|
114
114
|
// file routes
|
|
115
115
|
{
|
|
116
|
-
method:
|
|
117
|
-
url:
|
|
116
|
+
method: "get",
|
|
117
|
+
url: "/datasets/:datasetId/files/:filename",
|
|
118
118
|
handler: datalad.getFile,
|
|
119
119
|
},
|
|
120
120
|
{
|
|
121
|
-
method:
|
|
122
|
-
url:
|
|
121
|
+
method: "get",
|
|
122
|
+
url: "/datasets/:datasetId/snapshots/:snapshotId/files/:filename",
|
|
123
123
|
handler: datalad.getFile,
|
|
124
124
|
},
|
|
125
125
|
{
|
|
126
|
-
method:
|
|
127
|
-
url:
|
|
126
|
+
method: "get",
|
|
127
|
+
url: "/datasets/:datasetId/objects/:key",
|
|
128
128
|
handler: datalad.getObject,
|
|
129
129
|
},
|
|
130
130
|
|
|
@@ -132,42 +132,42 @@ const routes = [
|
|
|
132
132
|
|
|
133
133
|
// google
|
|
134
134
|
{
|
|
135
|
-
method:
|
|
136
|
-
url:
|
|
135
|
+
method: "get",
|
|
136
|
+
url: "/auth/google",
|
|
137
137
|
middleware: [noCache],
|
|
138
138
|
handler: google.requestAuth,
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
|
-
method:
|
|
142
|
-
url:
|
|
141
|
+
method: "get",
|
|
142
|
+
url: "/auth/google/callback",
|
|
143
143
|
middleware: [noCache, google.authCallback],
|
|
144
144
|
handler: jwt.authSuccessHandler,
|
|
145
145
|
},
|
|
146
146
|
|
|
147
147
|
// orcid
|
|
148
148
|
{
|
|
149
|
-
method:
|
|
150
|
-
url:
|
|
149
|
+
method: "get",
|
|
150
|
+
url: "/auth/orcid",
|
|
151
151
|
middleware: [noCache],
|
|
152
152
|
handler: orcid.requestAuth,
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
|
-
method:
|
|
156
|
-
url:
|
|
155
|
+
method: "get",
|
|
156
|
+
url: "/auth/orcid/callback",
|
|
157
157
|
middleware: [noCache, orcid.authCallback],
|
|
158
158
|
handler: jwt.authSuccessHandler,
|
|
159
159
|
},
|
|
160
160
|
// Anonymous reviewer access
|
|
161
161
|
{
|
|
162
|
-
method:
|
|
163
|
-
url:
|
|
162
|
+
method: "get",
|
|
163
|
+
url: "/reviewer/:token",
|
|
164
164
|
middleware: [noCache],
|
|
165
165
|
handler: reviewerHandler,
|
|
166
166
|
},
|
|
167
167
|
// sitemap
|
|
168
168
|
{
|
|
169
|
-
method:
|
|
170
|
-
url:
|
|
169
|
+
method: "get",
|
|
170
|
+
url: "/sitemap",
|
|
171
171
|
handler: sitemapHandler,
|
|
172
172
|
},
|
|
173
173
|
]
|
|
@@ -177,7 +177,7 @@ const routes = [
|
|
|
177
177
|
const router = express.Router()
|
|
178
178
|
|
|
179
179
|
for (const route of routes) {
|
|
180
|
-
const arr = route.hasOwnProperty(
|
|
180
|
+
const arr = route.hasOwnProperty("middleware") ? route.middleware : []
|
|
181
181
|
arr.unshift(route.url)
|
|
182
182
|
arr.push(route.handler)
|
|
183
183
|
router[route.method](...arr)
|
package/src/server.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/** Needs to run before the other imports in Node */
|
|
2
|
-
import apm from
|
|
2
|
+
import apm from "elastic-apm-node"
|
|
3
3
|
apm.start({
|
|
4
|
-
serviceName:
|
|
5
|
-
cloudProvider:
|
|
4
|
+
serviceName: "openneuro-server",
|
|
5
|
+
cloudProvider: "none",
|
|
6
6
|
})
|
|
7
7
|
|
|
8
|
-
import { createServer } from
|
|
9
|
-
import mongoose from
|
|
10
|
-
import { connect as redisConnect } from
|
|
11
|
-
import config from
|
|
12
|
-
import { expressApolloSetup } from
|
|
8
|
+
import { createServer } from "http"
|
|
9
|
+
import mongoose from "mongoose"
|
|
10
|
+
import { connect as redisConnect } from "./libs/redis"
|
|
11
|
+
import config from "./config"
|
|
12
|
+
import { expressApolloSetup } from "./app"
|
|
13
13
|
|
|
14
14
|
const redisConnectionSetup = async () => {
|
|
15
15
|
try {
|
|
@@ -31,7 +31,7 @@ void redisConnectionSetup().then(async () => {
|
|
|
31
31
|
const server = createServer(app)
|
|
32
32
|
server.listen(config.port, () => {
|
|
33
33
|
// eslint-disable-next-line no-console
|
|
34
|
-
console.log(
|
|
34
|
+
console.log("Server is listening on port " + config.port)
|
|
35
35
|
// Setup GraphQL subscription transport
|
|
36
36
|
//subscriptionServerFactory(server)
|
|
37
37
|
})
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import { vi } from
|
|
1
|
+
import { vi } from "vitest"
|
|
2
2
|
import {
|
|
3
3
|
datasetOrSnapshot,
|
|
4
4
|
getDatasetFromSnapshotId,
|
|
5
|
-
} from
|
|
5
|
+
} from "../datasetOrSnapshot"
|
|
6
6
|
|
|
7
|
-
vi.mock(
|
|
7
|
+
vi.mock("ioredis")
|
|
8
8
|
|
|
9
|
-
describe(
|
|
10
|
-
it(
|
|
9
|
+
describe("datasetOrSnapshot()", () => {
|
|
10
|
+
it("resolves a dataset object correctly", () => {
|
|
11
11
|
const dataset = {
|
|
12
|
-
id:
|
|
13
|
-
revision:
|
|
12
|
+
id: "ds000001",
|
|
13
|
+
revision: "abcfdeg",
|
|
14
14
|
modified: new Date(),
|
|
15
15
|
draft: {
|
|
16
|
-
id:
|
|
16
|
+
id: "abcfdeg",
|
|
17
17
|
},
|
|
18
18
|
}
|
|
19
19
|
expect(datasetOrSnapshot(dataset)).toEqual({
|
|
20
|
-
datasetId:
|
|
21
|
-
revision:
|
|
20
|
+
datasetId: "ds000001",
|
|
21
|
+
revision: "abcfdeg",
|
|
22
22
|
})
|
|
23
23
|
})
|
|
24
|
-
it(
|
|
24
|
+
it("resolves snapshot objects correctly", () => {
|
|
25
25
|
const snapshot = {
|
|
26
|
-
id:
|
|
27
|
-
tag:
|
|
28
|
-
hexsha:
|
|
26
|
+
id: "ds000001:1.0.0",
|
|
27
|
+
tag: "1.0.0",
|
|
28
|
+
hexsha: "abcfdeg",
|
|
29
29
|
modified: new Date(),
|
|
30
|
-
files: [{ id:
|
|
30
|
+
files: [{ id: "1234", filename: "dataset_description.json" }],
|
|
31
31
|
}
|
|
32
32
|
expect(datasetOrSnapshot(snapshot)).toEqual({
|
|
33
|
-
datasetId:
|
|
34
|
-
revision:
|
|
33
|
+
datasetId: "ds000001",
|
|
34
|
+
revision: "abcfdeg",
|
|
35
35
|
})
|
|
36
36
|
})
|
|
37
|
-
it(
|
|
37
|
+
it("resolves the snapshot tag only corner case", () => {
|
|
38
38
|
const snapshot = {
|
|
39
|
-
id:
|
|
40
|
-
tag:
|
|
39
|
+
id: "ds000002:1.0.1",
|
|
40
|
+
tag: "1.0.1",
|
|
41
41
|
modified: new Date(),
|
|
42
42
|
}
|
|
43
43
|
expect(datasetOrSnapshot(snapshot)).toEqual({
|
|
44
|
-
datasetId:
|
|
45
|
-
revision:
|
|
44
|
+
datasetId: "ds000002",
|
|
45
|
+
revision: "1.0.1",
|
|
46
46
|
})
|
|
47
47
|
})
|
|
48
|
-
describe(
|
|
49
|
-
it(
|
|
50
|
-
expect(getDatasetFromSnapshotId(
|
|
48
|
+
describe("getDatasetFromSnapshotId", () => {
|
|
49
|
+
it("extracts the datasetId correctly", () => {
|
|
50
|
+
expect(getDatasetFromSnapshotId("ds000001:1.0.0")).toBe("ds000001")
|
|
51
51
|
})
|
|
52
52
|
})
|
|
53
53
|
})
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { vi } from
|
|
2
|
-
import { validateUrl } from
|
|
1
|
+
import { vi } from "vitest"
|
|
2
|
+
import { validateUrl } from "../validateUrl"
|
|
3
3
|
|
|
4
|
-
vi.mock(
|
|
4
|
+
vi.mock("ioredis")
|
|
5
5
|
|
|
6
|
-
describe(
|
|
7
|
-
it(
|
|
8
|
-
expect(validateUrl(
|
|
6
|
+
describe("validateUrl", () => {
|
|
7
|
+
it("returns true for a regular HTTPS url", () => {
|
|
8
|
+
expect(validateUrl("https://openneuro.org")).toBe(true)
|
|
9
9
|
})
|
|
10
|
-
it(
|
|
11
|
-
expect(validateUrl(
|
|
10
|
+
it("returns false for a regular HTTP url", () => {
|
|
11
|
+
expect(validateUrl("http://openneuro.org")).toBe(false)
|
|
12
12
|
})
|
|
13
|
-
it(
|
|
14
|
-
expect(validateUrl(
|
|
13
|
+
it("returns false for something that is not really a URL", () => {
|
|
14
|
+
expect(validateUrl("openneuro.org/robots.txt")).toBe(false)
|
|
15
15
|
})
|
|
16
16
|
})
|
|
@@ -23,7 +23,7 @@ export type DatasetOrSnapshot = HasId | HasSnapshotId
|
|
|
23
23
|
export function datasetOrSnapshot(
|
|
24
24
|
obj: DatasetOrSnapshot,
|
|
25
25
|
): DatasetRevisionReference {
|
|
26
|
-
if (
|
|
26
|
+
if ("tag" in obj) {
|
|
27
27
|
return {
|
|
28
28
|
datasetId: getDatasetFromSnapshotId(obj.id),
|
|
29
29
|
revision: obj.hexsha || obj.tag,
|
|
@@ -38,5 +38,5 @@ export function datasetOrSnapshot(
|
|
|
38
38
|
* @returns {string} Dataset id portion 'ds000001'
|
|
39
39
|
*/
|
|
40
40
|
export function getDatasetFromSnapshotId(snapshotId: string): string {
|
|
41
|
-
return snapshotId.split(
|
|
41
|
+
return snapshotId.split(":")[0]
|
|
42
42
|
}
|
package/src/utils/validateUrl.ts
CHANGED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import * as changelog from '../changelog.js'
|
|
2
|
-
|
|
3
|
-
vi.mock('ioredis')
|
|
4
|
-
vi.mock('../../config.js')
|
|
5
|
-
|
|
6
|
-
describe('changelog editing tools', () => {
|
|
7
|
-
describe('findVersion()', () => {
|
|
8
|
-
it('finds the version bounds for a single entry', () => {
|
|
9
|
-
const newChanges = ['1.0.0 2019-01-01', ' - Initial version']
|
|
10
|
-
expect(changelog.findVersion(newChanges, '1.0.0')).toEqual([0, 2])
|
|
11
|
-
})
|
|
12
|
-
it('returns an empty array when no matching version is found', () => {
|
|
13
|
-
const newChanges = ['1.0.0 2019-01-01', ' - Initial version']
|
|
14
|
-
expect(changelog.findVersion(newChanges, '1.0.1')).toEqual([])
|
|
15
|
-
})
|
|
16
|
-
it('returns the correct offset for a change in the middle of others', () => {
|
|
17
|
-
const newChanges = [
|
|
18
|
-
'2.0.0 2019-02-02',
|
|
19
|
-
' - New derivatives',
|
|
20
|
-
'1.1.0 2019-02-01',
|
|
21
|
-
' - Added subjects',
|
|
22
|
-
' - Fixed metadata',
|
|
23
|
-
'1.0.0 2019-01-01',
|
|
24
|
-
' - Initial version',
|
|
25
|
-
]
|
|
26
|
-
expect(changelog.findVersion(newChanges, '1.1.0')).toEqual([2, 3])
|
|
27
|
-
})
|
|
28
|
-
it('works with fuzzy data', () => {
|
|
29
|
-
const newChanges = ['I', 'am', 'a', 'banana']
|
|
30
|
-
expect(changelog.findVersion(newChanges, '1.0.0')).toEqual([])
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
describe('spliceChangelog()', () => {
|
|
34
|
-
it('splices in changes to an existing changelog', () => {
|
|
35
|
-
const original = '1.0.0 2019-01-01\n - Initial version\n'
|
|
36
|
-
const changes = ['Some new change', 'Another new change']
|
|
37
|
-
const tag = '1.0.0'
|
|
38
|
-
expect(
|
|
39
|
-
changelog.spliceChangelog(original, tag, '2019-02-01', changes),
|
|
40
|
-
).toEqual(
|
|
41
|
-
'1.0.0 2019-02-01\n - Some new change\n - Another new change\n',
|
|
42
|
-
)
|
|
43
|
-
})
|
|
44
|
-
it('splices correctly when no matching version is found', () => {
|
|
45
|
-
const original = '1.0.0 2019-01-01\n - Initial version\n'
|
|
46
|
-
const changes = ['Some new change']
|
|
47
|
-
const tag = '1.0.1'
|
|
48
|
-
expect(
|
|
49
|
-
changelog.spliceChangelog(original, tag, '2019-02-01', changes),
|
|
50
|
-
).toEqual(
|
|
51
|
-
'1.0.1 2019-02-01\n - Some new change\n1.0.0 2019-01-01\n - Initial version\n',
|
|
52
|
-
)
|
|
53
|
-
})
|
|
54
|
-
it('handles fuzzy data', () => {
|
|
55
|
-
const original = 'abc 123 not a changelog\nnope'
|
|
56
|
-
const changes = ['Fixed up data']
|
|
57
|
-
const tag = '1.0.0'
|
|
58
|
-
expect(
|
|
59
|
-
changelog.spliceChangelog(original, tag, '2019-02-01', changes),
|
|
60
|
-
).toEqual(
|
|
61
|
-
'1.0.0 2019-02-01\n - Fixed up data\nabc 123 not a changelog\nnope\n',
|
|
62
|
-
)
|
|
63
|
-
})
|
|
64
|
-
it('works with legacy versions', () => {
|
|
65
|
-
const original = '00001 1999-12-31\n - Partying'
|
|
66
|
-
const changes = ['Bringing dataset into the present day']
|
|
67
|
-
const tag = '1.0.0'
|
|
68
|
-
expect(
|
|
69
|
-
changelog.spliceChangelog(original, tag, '2019-02-01', changes),
|
|
70
|
-
).toEqual(
|
|
71
|
-
'1.0.0 2019-02-01\n - Bringing dataset into the present day\n00001 1999-12-31\n - Partying\n',
|
|
72
|
-
)
|
|
73
|
-
})
|
|
74
|
-
it('works if no CHANGES are provided', () => {
|
|
75
|
-
expect(
|
|
76
|
-
changelog.spliceChangelog('', '1.0.0', '2019-03-04', [
|
|
77
|
-
'Initial snapshot',
|
|
78
|
-
]),
|
|
79
|
-
).toEqual('1.0.0 2019-03-04\n - Initial snapshot\n')
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
})
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { vi } from 'vitest'
|
|
2
|
-
import request from 'superagent'
|
|
3
|
-
import { createDataset, datasetsFilter, testBlacklist } from '../dataset.js'
|
|
4
|
-
import { getDatasetWorker } from '../../libs/datalad-service'
|
|
5
|
-
import { connect } from 'mongoose'
|
|
6
|
-
|
|
7
|
-
// Mock requests to Datalad service
|
|
8
|
-
vi.mock('superagent')
|
|
9
|
-
vi.mock('ioredis')
|
|
10
|
-
vi.mock('../../libs/redis.js')
|
|
11
|
-
vi.mock('../../config.js')
|
|
12
|
-
vi.mock('../../libs/notifications.js')
|
|
13
|
-
|
|
14
|
-
describe('dataset model operations', () => {
|
|
15
|
-
describe('createDataset()', () => {
|
|
16
|
-
beforeAll(() => {
|
|
17
|
-
// Setup MongoDB with mongodb-memory-server
|
|
18
|
-
connect(globalThis.__MONGO_URI__)
|
|
19
|
-
})
|
|
20
|
-
it('resolves to dataset id string', async () => {
|
|
21
|
-
const user = { id: '1234' }
|
|
22
|
-
const { id: dsId } = await createDataset(user.id, user, {
|
|
23
|
-
affirmedDefaced: true,
|
|
24
|
-
affirmedConsent: true,
|
|
25
|
-
})
|
|
26
|
-
expect(dsId).toHaveLength(8)
|
|
27
|
-
expect(dsId.slice(0, 2)).toBe('ds')
|
|
28
|
-
})
|
|
29
|
-
it('posts to the DataLad /datasets/{dsId} endpoint', async () => {
|
|
30
|
-
const user = { id: '1234' }
|
|
31
|
-
// Reset call count for request.post
|
|
32
|
-
request.post.mockClear()
|
|
33
|
-
const { id: dsId } = await createDataset(user.id, user, {
|
|
34
|
-
affirmedDefaced: true,
|
|
35
|
-
affirmedConsent: true,
|
|
36
|
-
})
|
|
37
|
-
expect(request.post).toHaveBeenCalledTimes(1)
|
|
38
|
-
expect(request.post).toHaveBeenCalledWith(
|
|
39
|
-
expect.stringContaining(`${getDatasetWorker(dsId)}/datasets/`),
|
|
40
|
-
)
|
|
41
|
-
})
|
|
42
|
-
})
|
|
43
|
-
describe('datasetsFilter()', () => {
|
|
44
|
-
describe('filterBy: {all: true} ', () => {
|
|
45
|
-
it('returns the specified match for regular users', () => {
|
|
46
|
-
const testMatch = { test: 'match' }
|
|
47
|
-
expect(
|
|
48
|
-
datasetsFilter({
|
|
49
|
-
userId: '1234',
|
|
50
|
-
admin: false,
|
|
51
|
-
filterBy: { all: true },
|
|
52
|
-
})(testMatch)[0].$match,
|
|
53
|
-
).toBe(testMatch)
|
|
54
|
-
})
|
|
55
|
-
it('excludes match argument for admins', () => {
|
|
56
|
-
const testMatch = { test: 'match' }
|
|
57
|
-
expect(
|
|
58
|
-
datasetsFilter({
|
|
59
|
-
userId: '5678',
|
|
60
|
-
admin: true,
|
|
61
|
-
filterBy: { all: true },
|
|
62
|
-
})(testMatch),
|
|
63
|
-
).not.toBe(testMatch)
|
|
64
|
-
})
|
|
65
|
-
})
|
|
66
|
-
describe('filterBy: {invalid: true}', () => {
|
|
67
|
-
it('returns the correct number of stages', () => {
|
|
68
|
-
expect(
|
|
69
|
-
datasetsFilter({ filterBy: { invalid: true } })({}),
|
|
70
|
-
).toHaveLength(4)
|
|
71
|
-
})
|
|
72
|
-
})
|
|
73
|
-
describe('filterBy: {invalid: true, public: true}', () => {
|
|
74
|
-
it('returns the same number of stages as invalid: true', () => {
|
|
75
|
-
expect(
|
|
76
|
-
datasetsFilter({ filterBy: { invalid: true, public: true } })({}),
|
|
77
|
-
).toHaveLength(4)
|
|
78
|
-
})
|
|
79
|
-
it('returns one less stage for admins with all', () => {
|
|
80
|
-
expect(
|
|
81
|
-
datasetsFilter({
|
|
82
|
-
admin: true,
|
|
83
|
-
filterBy: { invalid: true, public: true, all: true },
|
|
84
|
-
})({}),
|
|
85
|
-
).toHaveLength(3)
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
describe('testBlacklist', () => {
|
|
89
|
-
it('returns false for .bidsignore', () => {
|
|
90
|
-
expect(testBlacklist('', '.bidsignore')).toBe(false)
|
|
91
|
-
})
|
|
92
|
-
it('returns true for .git paths', () => {
|
|
93
|
-
expect(testBlacklist('.git', 'HEAD')).toBe(true)
|
|
94
|
-
})
|
|
95
|
-
it('returns true for root level .DS_Store files', () => {
|
|
96
|
-
expect(testBlacklist('', '.DS_Store')).toBe(true)
|
|
97
|
-
})
|
|
98
|
-
it('returns true for nested .DS_Store files', () => {
|
|
99
|
-
expect(testBlacklist('sub-01/anat/', '.DS_Store')).toBe(true)
|
|
100
|
-
})
|
|
101
|
-
// https://github.com/OpenNeuroOrg/openneuro/issues/2519
|
|
102
|
-
it('skips ._ prefixed files created by macOS', () => {
|
|
103
|
-
expect(testBlacklist('', '._.DS_Store')).toBe(true)
|
|
104
|
-
expect(testBlacklist('stimuli/', '._1002.png')).toBe(true)
|
|
105
|
-
expect(testBlacklist('stimuli/', 'test._1002.png')).toBe(false)
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
})
|
|
109
|
-
})
|