@openneuro/server 4.47.5 → 4.47.7
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openneuro/server",
|
|
3
|
-
"version": "4.47.
|
|
3
|
+
"version": "4.47.7",
|
|
4
4
|
"description": "Core service for the OpenNeuro platform.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "src/server.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@elastic/elasticsearch": "8.13.1",
|
|
22
22
|
"@graphql-tools/schema": "^10.0.0",
|
|
23
23
|
"@keyv/redis": "^4.5.0",
|
|
24
|
-
"@openneuro/search": "^4.47.
|
|
24
|
+
"@openneuro/search": "^4.47.7",
|
|
25
25
|
"@sentry/node": "^10.37.0",
|
|
26
26
|
"@sentry/profiling-node": "^10.37.0",
|
|
27
27
|
"base64url": "^3.0.0",
|
|
@@ -89,5 +89,5 @@
|
|
|
89
89
|
"publishConfig": {
|
|
90
90
|
"access": "public"
|
|
91
91
|
},
|
|
92
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "af17c267fa700dff5b13d1b31aaf4f89c0853165"
|
|
93
93
|
}
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
import { MongoMemoryServer } from "mongodb-memory-server"
|
|
11
11
|
import mongoose, { Types } from "mongoose"
|
|
12
12
|
import User from "../../../models/user"
|
|
13
|
-
import
|
|
13
|
+
import DatasetEvent from "../../../models/datasetEvents"
|
|
14
|
+
import { notifications, user, users } from "../user.js"
|
|
14
15
|
import type { GraphQLContext } from "../user.js"
|
|
15
16
|
|
|
16
17
|
vi.mock("ioredis")
|
|
@@ -132,6 +133,27 @@ describe("user resolvers", () => {
|
|
|
132
133
|
await User.insertMany(testUsersSeedData)
|
|
133
134
|
})
|
|
134
135
|
|
|
136
|
+
describe("user()", () => {
|
|
137
|
+
it("does not crash when userInfo is undefined (anonymous request)", async () => {
|
|
138
|
+
const result = await user(null, { id: "u1" }, {})
|
|
139
|
+
expect(result).not.toBeNull()
|
|
140
|
+
expect(result!.id).toBe("u1")
|
|
141
|
+
// Email should be hidden for anonymous users
|
|
142
|
+
expect(result!.email).toBeUndefined()
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it("does not crash when context is completely missing", async () => {
|
|
146
|
+
const result = await user(null, { id: "u1" }, undefined)
|
|
147
|
+
expect(result).not.toBeNull()
|
|
148
|
+
expect(result!.id).toBe("u1")
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
it("returns null for non-existent user", async () => {
|
|
152
|
+
const result = await user(null, { id: "nonexistent" }, {})
|
|
153
|
+
expect(result).toBeNull()
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
135
157
|
describe("users()", () => {
|
|
136
158
|
it("returns sanitized data for non-admin context", async () => {
|
|
137
159
|
const result = await users(null, {}, nonAdminContext)
|
|
@@ -364,4 +386,57 @@ describe("user resolvers", () => {
|
|
|
364
386
|
expect(result.totalCount).toBe(3) // u1, u4, u6 are admins
|
|
365
387
|
})
|
|
366
388
|
})
|
|
389
|
+
|
|
390
|
+
describe("notifications()", () => {
|
|
391
|
+
it("returns empty array for reviewer users", async () => {
|
|
392
|
+
const result = await notifications(
|
|
393
|
+
{ id: "reviewer" },
|
|
394
|
+
null,
|
|
395
|
+
{ userInfo: { reviewer: true, admin: false, blocked: false } },
|
|
396
|
+
)
|
|
397
|
+
expect(result).toEqual([])
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
it("does not crash when userInfo is undefined", async () => {
|
|
401
|
+
await expect(
|
|
402
|
+
notifications({ id: "u1" }, null, { userInfo: undefined }),
|
|
403
|
+
).rejects.toThrow("Not authorized to view these notifications.")
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
it("returns notifications for a user viewing their own", async () => {
|
|
407
|
+
await DatasetEvent.create({
|
|
408
|
+
id: "event-1",
|
|
409
|
+
datasetId: "ds000001",
|
|
410
|
+
userId: "u1",
|
|
411
|
+
timestamp: new Date(),
|
|
412
|
+
event: {
|
|
413
|
+
type: "contributorCitation",
|
|
414
|
+
datasetId: "ds000001",
|
|
415
|
+
addedBy: "u2",
|
|
416
|
+
targetUserId: "u1",
|
|
417
|
+
contributorData: { name: "Test User" },
|
|
418
|
+
},
|
|
419
|
+
success: true,
|
|
420
|
+
note: "Added as contributor",
|
|
421
|
+
})
|
|
422
|
+
const result = await notifications(
|
|
423
|
+
{ id: "u1" },
|
|
424
|
+
null,
|
|
425
|
+
{ userInfo: { id: "u1", admin: false, userId: "u1" } },
|
|
426
|
+
)
|
|
427
|
+
expect(result.length).toBe(1)
|
|
428
|
+
expect(result[0].id).toBe("event-1")
|
|
429
|
+
expect(result[0].notificationStatus.status).toBe("UNREAD")
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
it("throws authorization error for regular user viewing another user's notifications", async () => {
|
|
433
|
+
await expect(
|
|
434
|
+
notifications(
|
|
435
|
+
{ id: "u1" },
|
|
436
|
+
null,
|
|
437
|
+
{ userInfo: { id: "u2", admin: false, userId: "u2" } },
|
|
438
|
+
),
|
|
439
|
+
).rejects.toThrow("Not authorized to view these notifications.")
|
|
440
|
+
})
|
|
441
|
+
})
|
|
367
442
|
})
|
|
@@ -34,7 +34,7 @@ export async function user(
|
|
|
34
34
|
{ id },
|
|
35
35
|
{ userInfo }: { userInfo?: Record<string, unknown> } = {},
|
|
36
36
|
): Promise<Partial<GraphQLUserType> | null> {
|
|
37
|
-
if (userInfo
|
|
37
|
+
if (userInfo?.reviewer) {
|
|
38
38
|
const oneWeekAgo = new Date()
|
|
39
39
|
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7)
|
|
40
40
|
return {
|
|
@@ -279,7 +279,7 @@ export async function notifications(obj, _, { userInfo }) {
|
|
|
279
279
|
const userId = obj.id
|
|
280
280
|
|
|
281
281
|
// Reviewers never have notifications
|
|
282
|
-
if (userInfo
|
|
282
|
+
if (userInfo?.reviewer) {
|
|
283
283
|
return []
|
|
284
284
|
}
|
|
285
285
|
|