@openneuro/server 4.2.5-alpha.0 → 4.3.0-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/Dockerfile +2 -1
- package/package.json +2 -3
- package/src/__mocks__/mongoose.js +0 -1
- package/src/graphql/resolvers/__tests__/user.spec.js +2 -13
- package/src/graphql/resolvers/mutation.js +2 -0
- package/src/graphql/resolvers/snapshots.js +39 -23
- package/src/graphql/resolvers/user.js +8 -4
- package/src/graphql/schema.js +5 -3
- package/src/models/deprecatedSnapshot.ts +2 -3
- package/src/__mocks__/mongodb.js +0 -5
package/Dockerfile
CHANGED
|
@@ -11,7 +11,8 @@ WORKDIR /srv
|
|
|
11
11
|
COPY --from=build /srv/packages/openneuro-server/package.json /srv/package.json
|
|
12
12
|
COPY --from=build /srv/.yarnrc.yml /srv/.yarnrc.yml
|
|
13
13
|
COPY --from=build /srv/.yarn /srv/.yarn
|
|
14
|
-
COPY --from=build /srv/.pnp.
|
|
14
|
+
COPY --from=build /srv/.pnp.cjs /srv/.pnp.cjs
|
|
15
|
+
COPY --from=build /srv/.pnp.loader.mjs /srv/.pnp.loader.mjs
|
|
15
16
|
COPY --from=build /srv/packages/openneuro-server/dist /srv/packages/openneuro-server/dist
|
|
16
17
|
|
|
17
18
|
HEALTHCHECK --interval=10s --retries=10 CMD curl -f 'http://localhost:8111' || exit 1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openneuro/server",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0-alpha.3",
|
|
4
4
|
"description": "Core service for the OpenNeuro platform.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "src/server.js",
|
|
@@ -89,7 +89,6 @@
|
|
|
89
89
|
"ioredis-mock": "^3.8.1",
|
|
90
90
|
"jest": "^26.6.3",
|
|
91
91
|
"mockingoose": "2.11.0",
|
|
92
|
-
"mongo-mock": "3.7.1",
|
|
93
92
|
"nodemon": "^2.0.7",
|
|
94
93
|
"supertest": "^3.0.0",
|
|
95
94
|
"ts-node-dev": "1.1.6",
|
|
@@ -104,5 +103,5 @@
|
|
|
104
103
|
"publishConfig": {
|
|
105
104
|
"access": "public"
|
|
106
105
|
},
|
|
107
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "28a399f30997634ecd417539006c188f4249c9a6"
|
|
108
107
|
}
|
|
@@ -3,24 +3,13 @@ import { users } from '../user.js'
|
|
|
3
3
|
describe('user resolvers', () => {
|
|
4
4
|
describe('users()', () => {
|
|
5
5
|
it('throws an error for non-admins', () => {
|
|
6
|
-
expect(
|
|
6
|
+
expect(
|
|
7
7
|
users(
|
|
8
8
|
null,
|
|
9
9
|
{ id: '3311cfe8-9764-434d-b80e-1b1ee72c686d' },
|
|
10
10
|
{ userInfo: {} },
|
|
11
11
|
),
|
|
12
|
-
).
|
|
13
|
-
})
|
|
14
|
-
it('admins should be able to override restrictions', () => {
|
|
15
|
-
expect(() =>
|
|
16
|
-
users(
|
|
17
|
-
null,
|
|
18
|
-
{ id: '3311cfe8-9764-434d-b80e-1b1ee72c686d' },
|
|
19
|
-
{
|
|
20
|
-
userInfo: { admin: true },
|
|
21
|
-
},
|
|
22
|
-
),
|
|
23
|
-
).not.toThrowError()
|
|
12
|
+
).rejects.toEqual(new Error('You must be a site admin to retrieve users'))
|
|
24
13
|
})
|
|
25
14
|
})
|
|
26
15
|
})
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
createSnapshot,
|
|
16
16
|
deleteSnapshot,
|
|
17
17
|
deprecateSnapshot,
|
|
18
|
+
undoDeprecateSnapshot,
|
|
18
19
|
} from './snapshots.js'
|
|
19
20
|
import { removeUser, setAdmin, setBlocked } from './user.js'
|
|
20
21
|
import { updateSummary } from './summary.js'
|
|
@@ -44,6 +45,7 @@ const Mutation = {
|
|
|
44
45
|
flagAnnexObject,
|
|
45
46
|
createSnapshot,
|
|
46
47
|
deprecateSnapshot,
|
|
48
|
+
undoDeprecateSnapshot,
|
|
47
49
|
deleteSnapshot,
|
|
48
50
|
updateSummary,
|
|
49
51
|
updateValidation,
|
|
@@ -9,10 +9,6 @@ import { getFiles, filterFiles } from '../../datalad/files.js'
|
|
|
9
9
|
import DatasetModel from '../../models/dataset'
|
|
10
10
|
import { filterRemovedAnnexObjects } from '../utils/file.js'
|
|
11
11
|
import DeprecatedSnapshot from '../../models/deprecatedSnapshot'
|
|
12
|
-
import { checkDatasetAdmin } from '../permissions.js'
|
|
13
|
-
import SnapshotModel from '../../models/snapshot'
|
|
14
|
-
import User from '../../models/user'
|
|
15
|
-
import * as Sentry from '@sentry/node'
|
|
16
12
|
import { redis } from '../../libs/redis'
|
|
17
13
|
import CacheItem, { CacheType } from '../../cache/item'
|
|
18
14
|
import { normalizeDOI } from '../../libs/doi/normalize'
|
|
@@ -34,15 +30,16 @@ export const snapshot = (obj, { datasetId, tag }, context) => {
|
|
|
34
30
|
getFiles(datasetId, snapshot.hexsha)
|
|
35
31
|
.then(filterFiles(prefix))
|
|
36
32
|
.then(filterRemovedAnnexObjects(datasetId, context.userInfo)),
|
|
37
|
-
deprecated: () => deprecated(
|
|
33
|
+
deprecated: () => deprecated({ datasetId, tag }),
|
|
38
34
|
related: () => related(datasetId),
|
|
39
35
|
}))
|
|
40
36
|
},
|
|
41
37
|
)
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
export const deprecated =
|
|
45
|
-
|
|
40
|
+
export const deprecated = ({ datasetId, tag }) => {
|
|
41
|
+
const id = `${datasetId}:${tag}`
|
|
42
|
+
return DeprecatedSnapshot.findOne({ id }).lean().exec()
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
/**
|
|
@@ -89,22 +86,41 @@ export const deprecateSnapshot = async (
|
|
|
89
86
|
{ datasetId, tag, reason },
|
|
90
87
|
{ user, userInfo },
|
|
91
88
|
) => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
89
|
+
const id = `${datasetId}:${tag}`
|
|
90
|
+
await checkDatasetWrite(datasetId, user, userInfo)
|
|
91
|
+
const timestamp = new Date()
|
|
92
|
+
await DeprecatedSnapshot.updateOne(
|
|
93
|
+
{ id },
|
|
94
|
+
{
|
|
95
|
+
id,
|
|
96
|
+
user,
|
|
97
|
+
reason,
|
|
98
|
+
timestamp,
|
|
99
|
+
},
|
|
100
|
+
{ upsert: true },
|
|
101
|
+
)
|
|
102
|
+
return {
|
|
103
|
+
id,
|
|
104
|
+
deprecated: {
|
|
105
|
+
id,
|
|
106
|
+
user,
|
|
107
|
+
reason,
|
|
108
|
+
timestamp,
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export const undoDeprecateSnapshot = async (
|
|
114
|
+
obj,
|
|
115
|
+
{ datasetId, tag },
|
|
116
|
+
{ user, userInfo },
|
|
117
|
+
) => {
|
|
118
|
+
const id = `${datasetId}:${tag}`
|
|
119
|
+
await checkDatasetWrite(datasetId, user, userInfo)
|
|
120
|
+
await DeprecatedSnapshot.findOneAndDelete({ id })
|
|
121
|
+
return {
|
|
122
|
+
id,
|
|
123
|
+
deprecated: null,
|
|
108
124
|
}
|
|
109
125
|
}
|
|
110
126
|
|
|
@@ -13,7 +13,9 @@ export const users = (obj, args, { userInfo }) => {
|
|
|
13
13
|
if (userInfo.admin) {
|
|
14
14
|
return User.find().exec()
|
|
15
15
|
} else {
|
|
16
|
-
|
|
16
|
+
return Promise.reject(
|
|
17
|
+
new Error('You must be a site admin to retrieve users'),
|
|
18
|
+
)
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
|
|
@@ -21,7 +23,7 @@ export const removeUser = (obj, { id }, { userInfo }) => {
|
|
|
21
23
|
if (userInfo.admin) {
|
|
22
24
|
return User.findByIdAndRemove(id).exec()
|
|
23
25
|
} else {
|
|
24
|
-
|
|
26
|
+
return Promise.reject(new Error('You must be a site admin to remove users'))
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -29,7 +31,9 @@ export const setAdmin = (obj, { id, admin }, { userInfo }) => {
|
|
|
29
31
|
if (userInfo.admin) {
|
|
30
32
|
return User.findOneAndUpdate({ id }, { admin }).exec()
|
|
31
33
|
} else {
|
|
32
|
-
|
|
34
|
+
return Promise.reject(
|
|
35
|
+
new Error('You must be a site admin to modify this value'),
|
|
36
|
+
)
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
|
|
@@ -37,7 +41,7 @@ export const setBlocked = (obj, { id, blocked }, { userInfo }) => {
|
|
|
37
41
|
if (userInfo.admin) {
|
|
38
42
|
return User.findOneAndUpdate({ id }, { blocked }).exec()
|
|
39
43
|
} else {
|
|
40
|
-
|
|
44
|
+
return Promise.reject(new Error('You must be a site admin to block a user'))
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
47
|
|
package/src/graphql/schema.js
CHANGED
|
@@ -176,7 +176,9 @@ export const typeDefs = `
|
|
|
176
176
|
# Reset draft commit
|
|
177
177
|
resetDraft(datasetId: ID!, ref: String!): Boolean
|
|
178
178
|
# Flag snapshot as deprecated
|
|
179
|
-
deprecateSnapshot(datasetId: ID!, tag: String!, reason: String!):
|
|
179
|
+
deprecateSnapshot(datasetId: ID!, tag: String!, reason: String!): Snapshot
|
|
180
|
+
# Unflag snapshot as deprecated
|
|
181
|
+
undoDeprecateSnapshot(datasetId: ID!, tag: String!): Snapshot
|
|
180
182
|
# Create anonymous read only reviewer
|
|
181
183
|
createReviewer(datasetId: ID!): DatasetReviewer
|
|
182
184
|
# Remove reviewer
|
|
@@ -485,9 +487,9 @@ export const typeDefs = `
|
|
|
485
487
|
# hexsha of deprecated snapshots
|
|
486
488
|
id: ID!
|
|
487
489
|
# ID of user who flagged snapshot as deprecated
|
|
488
|
-
user:
|
|
490
|
+
user: String
|
|
489
491
|
# Reason for deprecating snaphot
|
|
490
|
-
|
|
492
|
+
reason: String
|
|
491
493
|
# Timestamp of snapshot deprecation
|
|
492
494
|
timestamp: Date
|
|
493
495
|
}
|
|
@@ -4,7 +4,7 @@ const { Schema, model } = mongoose
|
|
|
4
4
|
export interface DeprecatedSnapshotDocument extends Document {
|
|
5
5
|
id: string // snapshot hexsha
|
|
6
6
|
user: string
|
|
7
|
-
|
|
7
|
+
reason: string
|
|
8
8
|
timestamp: Date
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -13,9 +13,8 @@ const deprecatedSnapshotSchema = new Schema({
|
|
|
13
13
|
user: {
|
|
14
14
|
type: String,
|
|
15
15
|
required: true,
|
|
16
|
-
ref: 'User',
|
|
17
16
|
},
|
|
18
|
-
|
|
17
|
+
reason: {
|
|
19
18
|
type: String,
|
|
20
19
|
required: true,
|
|
21
20
|
},
|