@rebasepro/server-core 0.0.1-canary.4d4fb3e → 0.0.1-canary.ca2cb6e
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/dist/common/src/collections/CollectionRegistry.d.ts +8 -0
- package/dist/common/src/util/entities.d.ts +22 -0
- package/dist/common/src/util/relations.d.ts +14 -4
- package/dist/common/src/util/resolutions.d.ts +1 -1
- package/dist/index-DXVBFp5V.js +37 -0
- package/dist/index-DXVBFp5V.js.map +1 -0
- package/dist/index.es.js +49931 -55
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +28475 -34569
- package/dist/index.umd.js.map +1 -1
- package/dist/server-core/src/api/openapi-generator.d.ts +15 -1
- package/dist/server-core/src/api/types.d.ts +1 -1
- package/dist/server-core/src/auth/admin-routes.d.ts +10 -1
- package/dist/server-core/src/auth/apple-oauth.d.ts +30 -0
- package/dist/server-core/src/auth/bitbucket-oauth.d.ts +11 -0
- package/dist/server-core/src/auth/discord-oauth.d.ts +14 -0
- package/dist/server-core/src/auth/facebook-oauth.d.ts +14 -0
- package/dist/server-core/src/auth/github-oauth.d.ts +15 -0
- package/dist/server-core/src/auth/gitlab-oauth.d.ts +13 -0
- package/dist/server-core/src/auth/google-oauth.d.ts +5 -11
- package/dist/server-core/src/auth/index.d.ts +13 -2
- package/dist/server-core/src/auth/interfaces.d.ts +45 -6
- package/dist/server-core/src/auth/jwt.d.ts +1 -0
- package/dist/server-core/src/auth/linkedin-oauth.d.ts +18 -0
- package/dist/server-core/src/auth/microsoft-oauth.d.ts +16 -0
- package/dist/server-core/src/auth/middleware.d.ts +36 -11
- package/dist/server-core/src/auth/rate-limiter.d.ts +2 -2
- package/dist/server-core/src/auth/routes.d.ts +13 -3
- package/dist/server-core/src/auth/slack-oauth.d.ts +12 -0
- package/dist/server-core/src/auth/spotify-oauth.d.ts +12 -0
- package/dist/server-core/src/auth/twitter-oauth.d.ts +18 -0
- package/dist/server-core/src/cron/cron-loader.d.ts +17 -0
- package/dist/server-core/src/cron/cron-routes.d.ts +14 -0
- package/dist/server-core/src/cron/cron-scheduler.d.ts +61 -0
- package/dist/server-core/src/cron/cron-store.d.ts +32 -0
- package/dist/server-core/src/cron/index.d.ts +6 -0
- package/dist/server-core/src/email/index.d.ts +2 -2
- package/dist/server-core/src/email/templates.d.ts +9 -0
- package/dist/server-core/src/email/types.d.ts +20 -23
- package/dist/server-core/src/history/history-routes.d.ts +2 -2
- package/dist/server-core/src/index.d.ts +5 -0
- package/dist/server-core/src/init.d.ts +112 -2
- package/dist/server-core/src/singleton.d.ts +35 -0
- package/dist/server-core/src/storage/LocalStorageController.d.ts +9 -9
- package/dist/server-core/src/storage/S3StorageController.d.ts +8 -8
- package/dist/server-core/src/storage/index.d.ts +18 -11
- package/dist/server-core/src/storage/routes.d.ts +3 -3
- package/dist/server-core/src/storage/types.d.ts +28 -16
- package/dist/server-core/src/utils/dev-port.d.ts +35 -0
- package/dist/server-core/src/utils/logger.d.ts +31 -0
- package/dist/server-core/src/utils/request-logger.d.ts +19 -0
- package/dist/types/src/controllers/auth.d.ts +2 -0
- package/dist/types/src/controllers/client.d.ts +119 -7
- package/dist/types/src/controllers/collection_registry.d.ts +4 -3
- package/dist/types/src/controllers/customization_controller.d.ts +7 -1
- package/dist/types/src/controllers/data.d.ts +34 -7
- package/dist/types/src/controllers/data_driver.d.ts +20 -28
- package/dist/types/src/controllers/database_admin.d.ts +2 -2
- package/dist/types/src/controllers/email.d.ts +34 -0
- package/dist/types/src/controllers/index.d.ts +1 -0
- package/dist/types/src/controllers/local_config_persistence.d.ts +4 -4
- package/dist/types/src/controllers/navigation.d.ts +5 -5
- package/dist/types/src/controllers/registry.d.ts +6 -3
- package/dist/types/src/controllers/side_entity_controller.d.ts +7 -6
- package/dist/types/src/controllers/storage.d.ts +24 -26
- package/dist/types/src/rebase_context.d.ts +8 -4
- package/dist/types/src/types/backend.d.ts +4 -1
- package/dist/types/src/types/builders.d.ts +5 -4
- package/dist/types/src/types/chips.d.ts +1 -1
- package/dist/types/src/types/collections.d.ts +169 -125
- package/dist/types/src/types/cron.d.ts +102 -0
- package/dist/types/src/types/data_source.d.ts +1 -1
- package/dist/types/src/types/entity_actions.d.ts +8 -8
- package/dist/types/src/types/entity_callbacks.d.ts +15 -15
- package/dist/types/src/types/entity_link_builder.d.ts +1 -1
- package/dist/types/src/types/entity_overrides.d.ts +2 -1
- package/dist/types/src/types/entity_views.d.ts +8 -8
- package/dist/types/src/types/export_import.d.ts +3 -3
- package/dist/types/src/types/index.d.ts +1 -0
- package/dist/types/src/types/plugins.d.ts +72 -18
- package/dist/types/src/types/properties.d.ts +118 -33
- package/dist/types/src/types/relations.d.ts +1 -1
- package/dist/types/src/types/slots.d.ts +30 -6
- package/dist/types/src/types/translations.d.ts +44 -0
- package/dist/types/src/types/user_management_delegate.d.ts +1 -0
- package/package.json +84 -84
- package/scratch.ts +6 -5
- package/src/api/ast-schema-editor.ts +11 -11
- package/src/api/collections_for_test/callbacks_test_collection.ts +5 -2
- package/src/api/errors.ts +38 -14
- package/src/api/graphql/graphql-schema-generator.ts +5 -3
- package/src/api/openapi-generator.ts +613 -58
- package/src/api/rest/api-generator.ts +17 -11
- package/src/api/rest/query-parser.ts +1 -1
- package/src/api/schema-editor-routes.ts +2 -0
- package/src/api/server.ts +8 -5
- package/src/api/types.ts +1 -1
- package/src/auth/admin-routes.ts +58 -17
- package/src/auth/apple-oauth.ts +130 -0
- package/src/auth/bitbucket-oauth.ts +82 -0
- package/src/auth/discord-oauth.ts +83 -0
- package/src/auth/facebook-oauth.ts +72 -0
- package/src/auth/github-oauth.ts +110 -0
- package/src/auth/gitlab-oauth.ts +70 -0
- package/src/auth/google-oauth.ts +34 -46
- package/src/auth/index.ts +15 -2
- package/src/auth/interfaces.ts +54 -7
- package/src/auth/jwt.ts +22 -5
- package/src/auth/linkedin-oauth.ts +81 -0
- package/src/auth/microsoft-oauth.ts +88 -0
- package/src/auth/middleware.ts +194 -45
- package/src/auth/password.ts +3 -1
- package/src/auth/rate-limiter.ts +4 -4
- package/src/auth/routes.ts +197 -139
- package/src/auth/slack-oauth.ts +71 -0
- package/src/auth/spotify-oauth.ts +67 -0
- package/src/auth/twitter-oauth.ts +120 -0
- package/src/collections/loader.ts +6 -6
- package/src/cron/cron-loader.ts +89 -0
- package/src/cron/cron-routes.test.ts +265 -0
- package/src/cron/cron-routes.ts +85 -0
- package/src/cron/cron-scheduler.test.ts +421 -0
- package/src/cron/cron-scheduler.ts +413 -0
- package/src/cron/cron-store.ts +163 -0
- package/src/cron/index.ts +6 -0
- package/src/db/interfaces.ts +2 -2
- package/src/email/index.ts +3 -2
- package/src/email/smtp-email-service.ts +5 -2
- package/src/email/templates.ts +93 -6
- package/src/email/types.ts +17 -24
- package/src/functions/function-loader.ts +34 -6
- package/src/functions/function-routes.ts +2 -2
- package/src/history/history-routes.ts +4 -3
- package/src/index.ts +10 -0
- package/src/init.ts +475 -57
- package/src/services/driver-registry.ts +1 -1
- package/src/singleton.test.ts +28 -0
- package/src/singleton.ts +70 -0
- package/src/storage/LocalStorageController.ts +50 -53
- package/src/storage/S3StorageController.ts +49 -46
- package/src/storage/index.ts +27 -16
- package/src/storage/routes.ts +76 -59
- package/src/storage/storage-registry.ts +5 -5
- package/src/storage/types.ts +44 -32
- package/src/types/index.ts +4 -4
- package/src/utils/dev-port.ts +176 -0
- package/src/utils/logger.ts +143 -0
- package/src/utils/logging.ts +5 -2
- package/src/utils/request-logger.ts +66 -0
- package/test/admin-routes.test.ts +114 -65
- package/test/api-generator.test.ts +73 -30
- package/test/ast-schema-editor.test.ts +5 -3
- package/test/auth-middleware-hono.test.ts +268 -33
- package/test/auth-routes.test.ts +325 -146
- package/test/driver-registry.test.ts +4 -2
- package/test/error-propagation.test.ts +226 -0
- package/test/errors.test.ts +12 -7
- package/test/jwt-security.test.ts +18 -9
- package/test/jwt.test.ts +26 -13
- package/test/middleware.test.ts +13 -8
- package/test/query-parser.test.ts +13 -8
- package/test/rate-limiter.test.ts +7 -7
- package/test/safe-compare.test.ts +66 -0
- package/test/singleton.test.ts +59 -0
- package/test/storage-local.test.ts +36 -43
- package/test/storage-registry.test.ts +38 -36
- package/test/storage-routes.test.ts +9 -5
- package/test/storage-s3.test.ts +51 -48
- package/test.ts +6 -0
- package/tsconfig.json +1 -1
- package/vite.config.ts +7 -5
- package/dist/index-BeMqpmfQ.js +0 -239
- package/dist/index-BeMqpmfQ.js.map +0 -1
- package/dist/index-bl4J3lNb.js +0 -55823
- package/dist/index-bl4J3lNb.js.map +0 -1
- package/vite.config.ts.timestamp-1775065397568-8a853255edf6e.mjs +0 -46
|
@@ -30,18 +30,21 @@ function mockUser(overrides: Partial<{ id: string; email: string; displayName: s
|
|
|
30
30
|
passwordHash: "salt:hash",
|
|
31
31
|
displayName: overrides.displayName ?? "Test User",
|
|
32
32
|
photoUrl: overrides.photoUrl ?? null,
|
|
33
|
-
provider: overrides.provider ?? "email",
|
|
34
|
-
googleId: null,
|
|
35
33
|
emailVerified: false,
|
|
36
34
|
emailVerificationToken: null,
|
|
37
35
|
emailVerificationSentAt: null,
|
|
38
36
|
createdAt: new Date("2024-01-01"),
|
|
39
|
-
updatedAt: new Date("2024-01-01")
|
|
37
|
+
updatedAt: new Date("2024-01-01")
|
|
40
38
|
};
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
function mockRole(id: string, isAdmin = false) {
|
|
44
|
-
return { id,
|
|
42
|
+
return { id,
|
|
43
|
+
name: id.charAt(0).toUpperCase() + id.slice(1),
|
|
44
|
+
isAdmin,
|
|
45
|
+
defaultPermissions: null,
|
|
46
|
+
collectionPermissions: null,
|
|
47
|
+
config: null };
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
|
|
@@ -50,10 +53,14 @@ let mockAuthRepo: jest.Mocked<any>;
|
|
|
50
53
|
function createApp(opts: { defaultRole?: string } = {}) {
|
|
51
54
|
mockAuthRepo = {
|
|
52
55
|
getUserByEmail: jest.fn().mockResolvedValue(null),
|
|
53
|
-
|
|
56
|
+
getUserByIdentity: jest.fn().mockResolvedValue(null),
|
|
57
|
+
linkUserIdentity: jest.fn().mockResolvedValue(undefined),
|
|
58
|
+
getUserIdentities: jest.fn().mockResolvedValue([]),
|
|
54
59
|
getUserById: jest.fn().mockResolvedValue(null),
|
|
55
60
|
createUser: jest.fn().mockImplementation((data) =>
|
|
56
|
-
Promise.resolve(mockUser({ email: data.email,
|
|
61
|
+
Promise.resolve(mockUser({ email: data.email,
|
|
62
|
+
displayName: data.displayName,
|
|
63
|
+
passwordHash: data.passwordHash }))
|
|
57
64
|
),
|
|
58
65
|
listUsers: jest.fn().mockResolvedValue([]),
|
|
59
66
|
getUserRoles: jest.fn().mockResolvedValue([mockRole("editor")]),
|
|
@@ -61,7 +68,8 @@ function createApp(opts: { defaultRole?: string } = {}) {
|
|
|
61
68
|
assignDefaultRole: jest.fn().mockResolvedValue(undefined),
|
|
62
69
|
setUserRoles: jest.fn().mockResolvedValue(undefined),
|
|
63
70
|
updateUser: jest.fn().mockImplementation((id, data) =>
|
|
64
|
-
Promise.resolve(mockUser({ id,
|
|
71
|
+
Promise.resolve(mockUser({ id,
|
|
72
|
+
...data }))
|
|
65
73
|
),
|
|
66
74
|
deleteUser: jest.fn().mockResolvedValue(undefined),
|
|
67
75
|
updatePassword: jest.fn().mockResolvedValue(undefined),
|
|
@@ -70,7 +78,8 @@ function createApp(opts: { defaultRole?: string } = {}) {
|
|
|
70
78
|
getUserByVerificationToken: jest.fn().mockResolvedValue(null),
|
|
71
79
|
getUserWithRoles: jest.fn().mockImplementation(async (userId) => {
|
|
72
80
|
const user = mockUser({ id: userId });
|
|
73
|
-
return { user,
|
|
81
|
+
return { user,
|
|
82
|
+
roles: [mockRole("editor")] };
|
|
74
83
|
}),
|
|
75
84
|
createRefreshToken: jest.fn().mockResolvedValue(undefined),
|
|
76
85
|
findRefreshTokenByHash: jest.fn().mockResolvedValue(null),
|
|
@@ -84,19 +93,30 @@ function createApp(opts: { defaultRole?: string } = {}) {
|
|
|
84
93
|
deleteExpiredPasswordResetTokens: jest.fn().mockResolvedValue(undefined),
|
|
85
94
|
listRoles: jest.fn().mockResolvedValue([]),
|
|
86
95
|
getRoleById: jest.fn().mockResolvedValue(null),
|
|
87
|
-
createRole: jest.fn().mockImplementation(r => Promise.resolve({ id: r.id,
|
|
88
|
-
|
|
96
|
+
createRole: jest.fn().mockImplementation(r => Promise.resolve({ id: r.id,
|
|
97
|
+
name: r.name,
|
|
98
|
+
isAdmin: r.isAdmin || false,
|
|
99
|
+
defaultPermissions: null,
|
|
100
|
+
collectionPermissions: null,
|
|
101
|
+
config: null })),
|
|
102
|
+
updateRole: jest.fn().mockImplementation((id, r) => Promise.resolve({ id,
|
|
103
|
+
name: r.name,
|
|
104
|
+
isAdmin: r.isAdmin || false,
|
|
105
|
+
defaultPermissions: null,
|
|
106
|
+
collectionPermissions: null,
|
|
107
|
+
config: null })),
|
|
89
108
|
deleteRole: jest.fn().mockResolvedValue(undefined)
|
|
90
109
|
} as unknown as jest.Mocked<AuthRepository>;
|
|
91
|
-
|
|
110
|
+
|
|
92
111
|
|
|
93
112
|
// Password mocks
|
|
94
|
-
(validatePasswordStrength as jest.Mock).mockReturnValue({ valid: true,
|
|
113
|
+
(validatePasswordStrength as jest.Mock).mockReturnValue({ valid: true,
|
|
114
|
+
errors: [] });
|
|
95
115
|
(hashPassword as jest.Mock).mockResolvedValue("hashed-pw");
|
|
96
116
|
|
|
97
117
|
const config: AuthModuleConfig = {
|
|
98
118
|
authRepo: mockAuthRepo,
|
|
99
|
-
defaultRole: opts.defaultRole
|
|
119
|
+
defaultRole: opts.defaultRole
|
|
100
120
|
};
|
|
101
121
|
|
|
102
122
|
const app = new Hono<HonoEnv>();
|
|
@@ -117,7 +137,7 @@ function json(body: Record<string, unknown>) {
|
|
|
117
137
|
return {
|
|
118
138
|
method: "POST" as const,
|
|
119
139
|
headers: { "Content-Type": "application/json" },
|
|
120
|
-
body: JSON.stringify(body)
|
|
140
|
+
body: JSON.stringify(body)
|
|
121
141
|
};
|
|
122
142
|
}
|
|
123
143
|
|
|
@@ -127,7 +147,8 @@ function json(body: Record<string, unknown>) {
|
|
|
127
147
|
|
|
128
148
|
describe("Admin Routes (Integration)", () => {
|
|
129
149
|
beforeAll(() => {
|
|
130
|
-
configureJwt({ secret: TEST_SECRET,
|
|
150
|
+
configureJwt({ secret: TEST_SECRET,
|
|
151
|
+
accessExpiresIn: "1h" });
|
|
131
152
|
});
|
|
132
153
|
|
|
133
154
|
beforeEach(() => {
|
|
@@ -145,7 +166,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
145
166
|
it("returns 403 for non-admin users on admin-only endpoints", async () => {
|
|
146
167
|
const app = createApp();
|
|
147
168
|
const res = await app.request("/admin/users", {
|
|
148
|
-
headers: { ...editorAuth() }
|
|
169
|
+
headers: { ...editorAuth() }
|
|
149
170
|
});
|
|
150
171
|
expect(res.status).toBe(403);
|
|
151
172
|
});
|
|
@@ -153,7 +174,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
153
174
|
it("allows admin users through", async () => {
|
|
154
175
|
const app = createApp();
|
|
155
176
|
const res = await app.request("/admin/users", {
|
|
156
|
-
headers: { ...adminAuth() }
|
|
177
|
+
headers: { ...adminAuth() }
|
|
157
178
|
});
|
|
158
179
|
expect(res.status).toBe(200);
|
|
159
180
|
});
|
|
@@ -161,7 +182,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
161
182
|
it("allows schema-admin users through", async () => {
|
|
162
183
|
const app = createApp();
|
|
163
184
|
const res = await app.request("/admin/users", {
|
|
164
|
-
headers: { Authorization: `Bearer ${generateAccessToken("sa-1", ["schema-admin"])}` }
|
|
185
|
+
headers: { Authorization: `Bearer ${generateAccessToken("sa-1", ["schema-admin"])}` }
|
|
165
186
|
});
|
|
166
187
|
expect(res.status).toBe(200);
|
|
167
188
|
});
|
|
@@ -176,7 +197,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
176
197
|
|
|
177
198
|
const res = await app.request("/admin/bootstrap", {
|
|
178
199
|
method: "POST",
|
|
179
|
-
headers: { ...adminAuth("user-1") }
|
|
200
|
+
headers: { ...adminAuth("user-1") }
|
|
180
201
|
});
|
|
181
202
|
expect(res.status).toBe(200);
|
|
182
203
|
const body = await res.json() as any;
|
|
@@ -192,7 +213,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
192
213
|
|
|
193
214
|
const res = await app.request("/admin/bootstrap", {
|
|
194
215
|
method: "POST",
|
|
195
|
-
headers: { ...adminAuth("user-1") }
|
|
216
|
+
headers: { ...adminAuth("user-1") }
|
|
196
217
|
});
|
|
197
218
|
expect(res.status).toBe(403);
|
|
198
219
|
const body = await res.json() as any;
|
|
@@ -206,8 +227,10 @@ describe("Admin Routes (Integration)", () => {
|
|
|
206
227
|
it("returns list of users with roles", async () => {
|
|
207
228
|
const app = createApp();
|
|
208
229
|
mockAuthRepo.listUsers.mockResolvedValueOnce([
|
|
209
|
-
mockUser({ id: "u1",
|
|
210
|
-
|
|
230
|
+
mockUser({ id: "u1",
|
|
231
|
+
email: "a@test.com" }),
|
|
232
|
+
mockUser({ id: "u2",
|
|
233
|
+
email: "b@test.com" })
|
|
211
234
|
]);
|
|
212
235
|
mockAuthRepo.getUserRoleIds
|
|
213
236
|
.mockResolvedValueOnce(["admin"])
|
|
@@ -227,7 +250,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
227
250
|
const app = createApp();
|
|
228
251
|
mockAuthRepo.getUserWithRoles.mockResolvedValueOnce({
|
|
229
252
|
user: mockUser({ id: "u1" }),
|
|
230
|
-
roles: [mockRole("editor"), mockRole("viewer")]
|
|
253
|
+
roles: [mockRole("editor"), mockRole("viewer")]
|
|
231
254
|
});
|
|
232
255
|
|
|
233
256
|
const res = await app.request("/admin/users/u1", { headers: { ...adminAuth() } });
|
|
@@ -251,14 +274,18 @@ describe("Admin Routes (Integration)", () => {
|
|
|
251
274
|
const app = createApp();
|
|
252
275
|
|
|
253
276
|
const res = await app.request("/admin/users", {
|
|
254
|
-
...json({ email: "new@test.com",
|
|
255
|
-
|
|
277
|
+
...json({ email: "new@test.com",
|
|
278
|
+
displayName: "New",
|
|
279
|
+
password: "StrongPass1",
|
|
280
|
+
roles: ["editor"] }),
|
|
281
|
+
headers: { ...json({}).headers,
|
|
282
|
+
...adminAuth() }
|
|
256
283
|
});
|
|
257
284
|
expect(res.status).toBe(201);
|
|
258
285
|
const body = await res.json() as any;
|
|
259
286
|
expect(body.user.email).toBe("new@test.com");
|
|
260
287
|
expect(mockAuthRepo.createUser).toHaveBeenCalledWith(expect.objectContaining({
|
|
261
|
-
email: "new@test.com"
|
|
288
|
+
email: "new@test.com"
|
|
262
289
|
}));
|
|
263
290
|
});
|
|
264
291
|
|
|
@@ -266,8 +293,10 @@ describe("Admin Routes (Integration)", () => {
|
|
|
266
293
|
const app = createApp();
|
|
267
294
|
|
|
268
295
|
await app.request("/admin/users", {
|
|
269
|
-
...json({ email: "pw@test.com",
|
|
270
|
-
|
|
296
|
+
...json({ email: "pw@test.com",
|
|
297
|
+
password: "StrongPass1" }),
|
|
298
|
+
headers: { ...json({}).headers,
|
|
299
|
+
...adminAuth() }
|
|
271
300
|
});
|
|
272
301
|
expect(hashPassword).toHaveBeenCalledWith("StrongPass1");
|
|
273
302
|
});
|
|
@@ -277,7 +306,8 @@ describe("Admin Routes (Integration)", () => {
|
|
|
277
306
|
|
|
278
307
|
const res = await app.request("/admin/users", {
|
|
279
308
|
...json({ displayName: "No Email" }),
|
|
280
|
-
headers: { ...json({}).headers,
|
|
309
|
+
headers: { ...json({}).headers,
|
|
310
|
+
...adminAuth() }
|
|
281
311
|
});
|
|
282
312
|
expect(res.status).toBe(400);
|
|
283
313
|
});
|
|
@@ -288,7 +318,8 @@ describe("Admin Routes (Integration)", () => {
|
|
|
288
318
|
|
|
289
319
|
const res = await app.request("/admin/users", {
|
|
290
320
|
...json({ email: "existing@test.com" }),
|
|
291
|
-
headers: { ...json({}).headers,
|
|
321
|
+
headers: { ...json({}).headers,
|
|
322
|
+
...adminAuth() }
|
|
292
323
|
});
|
|
293
324
|
expect(res.status).toBe(409);
|
|
294
325
|
const body = await res.json() as any;
|
|
@@ -297,11 +328,14 @@ describe("Admin Routes (Integration)", () => {
|
|
|
297
328
|
|
|
298
329
|
it("returns 400 for weak password", async () => {
|
|
299
330
|
const app = createApp();
|
|
300
|
-
(validatePasswordStrength as jest.Mock).mockReturnValueOnce({ valid: false,
|
|
331
|
+
(validatePasswordStrength as jest.Mock).mockReturnValueOnce({ valid: false,
|
|
332
|
+
errors: ["Too short"] });
|
|
301
333
|
|
|
302
334
|
const res = await app.request("/admin/users", {
|
|
303
|
-
...json({ email: "weak@test.com",
|
|
304
|
-
|
|
335
|
+
...json({ email: "weak@test.com",
|
|
336
|
+
password: "weak" }),
|
|
337
|
+
headers: { ...json({}).headers,
|
|
338
|
+
...adminAuth() }
|
|
305
339
|
});
|
|
306
340
|
expect(res.status).toBe(400);
|
|
307
341
|
const body = await res.json() as any;
|
|
@@ -313,7 +347,8 @@ describe("Admin Routes (Integration)", () => {
|
|
|
313
347
|
|
|
314
348
|
await app.request("/admin/users", {
|
|
315
349
|
...json({ email: "norole@test.com" }),
|
|
316
|
-
headers: { ...json({}).headers,
|
|
350
|
+
headers: { ...json({}).headers,
|
|
351
|
+
...adminAuth() }
|
|
317
352
|
});
|
|
318
353
|
expect(mockAuthRepo.assignDefaultRole).toHaveBeenCalledWith(expect.any(String), "editor");
|
|
319
354
|
});
|
|
@@ -323,7 +358,8 @@ describe("Admin Routes (Integration)", () => {
|
|
|
323
358
|
|
|
324
359
|
await app.request("/admin/users", {
|
|
325
360
|
...json({ email: "nodefault@test.com" }),
|
|
326
|
-
headers: { ...json({}).headers,
|
|
361
|
+
headers: { ...json({}).headers,
|
|
362
|
+
...adminAuth() }
|
|
327
363
|
});
|
|
328
364
|
expect(mockAuthRepo.assignDefaultRole).not.toHaveBeenCalled();
|
|
329
365
|
});
|
|
@@ -332,8 +368,10 @@ describe("Admin Routes (Integration)", () => {
|
|
|
332
368
|
const app = createApp();
|
|
333
369
|
|
|
334
370
|
await app.request("/admin/users", {
|
|
335
|
-
...json({ email: "withroles@test.com",
|
|
336
|
-
|
|
371
|
+
...json({ email: "withroles@test.com",
|
|
372
|
+
roles: ["admin", "editor"] }),
|
|
373
|
+
headers: { ...json({}).headers,
|
|
374
|
+
...adminAuth() }
|
|
337
375
|
});
|
|
338
376
|
expect(mockAuthRepo.setUserRoles).toHaveBeenCalledWith(expect.any(String), ["admin", "editor"]);
|
|
339
377
|
});
|
|
@@ -344,14 +382,16 @@ describe("Admin Routes (Integration)", () => {
|
|
|
344
382
|
const app = createApp();
|
|
345
383
|
mockAuthRepo.getUserById.mockResolvedValueOnce(mockUser({ id: "u1" }));
|
|
346
384
|
mockAuthRepo.getUserWithRoles.mockResolvedValueOnce({
|
|
347
|
-
user: mockUser({ id: "u1",
|
|
348
|
-
|
|
385
|
+
user: mockUser({ id: "u1",
|
|
386
|
+
displayName: "Updated" }),
|
|
387
|
+
roles: [mockRole("editor")]
|
|
349
388
|
});
|
|
350
389
|
|
|
351
390
|
const res = await app.request("/admin/users/u1", {
|
|
352
391
|
method: "PUT",
|
|
353
|
-
headers: { "Content-Type": "application/json",
|
|
354
|
-
|
|
392
|
+
headers: { "Content-Type": "application/json",
|
|
393
|
+
...adminAuth() },
|
|
394
|
+
body: JSON.stringify({ displayName: "Updated" })
|
|
355
395
|
});
|
|
356
396
|
expect(res.status).toBe(200);
|
|
357
397
|
const body = await res.json() as any;
|
|
@@ -363,13 +403,14 @@ describe("Admin Routes (Integration)", () => {
|
|
|
363
403
|
mockAuthRepo.getUserById.mockResolvedValueOnce(mockUser({ id: "u1" }));
|
|
364
404
|
mockAuthRepo.getUserWithRoles.mockResolvedValueOnce({
|
|
365
405
|
user: mockUser({ id: "u1" }),
|
|
366
|
-
roles: [mockRole("admin")]
|
|
406
|
+
roles: [mockRole("admin")]
|
|
367
407
|
});
|
|
368
408
|
|
|
369
409
|
await app.request("/admin/users/u1", {
|
|
370
410
|
method: "PUT",
|
|
371
|
-
headers: { "Content-Type": "application/json",
|
|
372
|
-
|
|
411
|
+
headers: { "Content-Type": "application/json",
|
|
412
|
+
...adminAuth() },
|
|
413
|
+
body: JSON.stringify({ roles: ["admin"] })
|
|
373
414
|
});
|
|
374
415
|
expect(mockAuthRepo.setUserRoles).toHaveBeenCalledWith("u1", ["admin"]);
|
|
375
416
|
});
|
|
@@ -380,8 +421,9 @@ describe("Admin Routes (Integration)", () => {
|
|
|
380
421
|
|
|
381
422
|
const res = await app.request("/admin/users/missing", {
|
|
382
423
|
method: "PUT",
|
|
383
|
-
headers: { "Content-Type": "application/json",
|
|
384
|
-
|
|
424
|
+
headers: { "Content-Type": "application/json",
|
|
425
|
+
...adminAuth() },
|
|
426
|
+
body: JSON.stringify({ displayName: "Updated" })
|
|
385
427
|
});
|
|
386
428
|
expect(res.status).toBe(404);
|
|
387
429
|
});
|
|
@@ -394,7 +436,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
394
436
|
|
|
395
437
|
const res = await app.request("/admin/users/u1", {
|
|
396
438
|
method: "DELETE",
|
|
397
|
-
headers: { ...adminAuth("admin-1") }
|
|
439
|
+
headers: { ...adminAuth("admin-1") }
|
|
398
440
|
});
|
|
399
441
|
expect(res.status).toBe(200);
|
|
400
442
|
expect(mockAuthRepo.deleteUser).toHaveBeenCalledWith("u1");
|
|
@@ -405,7 +447,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
405
447
|
|
|
406
448
|
const res = await app.request("/admin/users/admin-1", {
|
|
407
449
|
method: "DELETE",
|
|
408
|
-
headers: { ...adminAuth("admin-1") }
|
|
450
|
+
headers: { ...adminAuth("admin-1") }
|
|
409
451
|
});
|
|
410
452
|
expect(res.status).toBe(400);
|
|
411
453
|
const body = await res.json() as any;
|
|
@@ -418,7 +460,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
418
460
|
|
|
419
461
|
const res = await app.request("/admin/users/missing", {
|
|
420
462
|
method: "DELETE",
|
|
421
|
-
headers: { ...adminAuth() }
|
|
463
|
+
headers: { ...adminAuth() }
|
|
422
464
|
});
|
|
423
465
|
expect(res.status).toBe(404);
|
|
424
466
|
});
|
|
@@ -433,7 +475,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
433
475
|
mockAuthRepo.listRoles.mockResolvedValueOnce([
|
|
434
476
|
mockRole("admin", true),
|
|
435
477
|
mockRole("editor"),
|
|
436
|
-
mockRole("viewer")
|
|
478
|
+
mockRole("viewer")
|
|
437
479
|
]);
|
|
438
480
|
|
|
439
481
|
const res = await app.request("/admin/roles", { headers: { ...adminAuth() } });
|
|
@@ -470,8 +512,10 @@ describe("Admin Routes (Integration)", () => {
|
|
|
470
512
|
const app = createApp();
|
|
471
513
|
|
|
472
514
|
const res = await app.request("/admin/roles", {
|
|
473
|
-
...json({ id: "custom",
|
|
474
|
-
|
|
515
|
+
...json({ id: "custom",
|
|
516
|
+
name: "Custom Role" }),
|
|
517
|
+
headers: { ...json({}).headers,
|
|
518
|
+
...adminAuth() }
|
|
475
519
|
});
|
|
476
520
|
expect(res.status).toBe(201);
|
|
477
521
|
const body = await res.json() as any;
|
|
@@ -483,7 +527,8 @@ describe("Admin Routes (Integration)", () => {
|
|
|
483
527
|
|
|
484
528
|
const res = await app.request("/admin/roles", {
|
|
485
529
|
...json({ id: "nope" }),
|
|
486
|
-
headers: { ...json({}).headers,
|
|
530
|
+
headers: { ...json({}).headers,
|
|
531
|
+
...adminAuth() }
|
|
487
532
|
});
|
|
488
533
|
expect(res.status).toBe(400);
|
|
489
534
|
});
|
|
@@ -493,8 +538,10 @@ describe("Admin Routes (Integration)", () => {
|
|
|
493
538
|
mockAuthRepo.getRoleById.mockResolvedValueOnce(mockRole("custom"));
|
|
494
539
|
|
|
495
540
|
const res = await app.request("/admin/roles", {
|
|
496
|
-
...json({ id: "custom",
|
|
497
|
-
|
|
541
|
+
...json({ id: "custom",
|
|
542
|
+
name: "Dup" }),
|
|
543
|
+
headers: { ...json({}).headers,
|
|
544
|
+
...adminAuth() }
|
|
498
545
|
});
|
|
499
546
|
expect(res.status).toBe(409);
|
|
500
547
|
const body = await res.json() as any;
|
|
@@ -509,12 +556,13 @@ describe("Admin Routes (Integration)", () => {
|
|
|
509
556
|
|
|
510
557
|
const res = await app.request("/admin/roles/editor", {
|
|
511
558
|
method: "PUT",
|
|
512
|
-
headers: { "Content-Type": "application/json",
|
|
513
|
-
|
|
559
|
+
headers: { "Content-Type": "application/json",
|
|
560
|
+
...adminAuth() },
|
|
561
|
+
body: JSON.stringify({ name: "Super Editor" })
|
|
514
562
|
});
|
|
515
563
|
expect(res.status).toBe(200);
|
|
516
564
|
expect(mockAuthRepo.updateRole).toHaveBeenCalledWith("editor", expect.objectContaining({
|
|
517
|
-
name: "Super Editor"
|
|
565
|
+
name: "Super Editor"
|
|
518
566
|
}));
|
|
519
567
|
});
|
|
520
568
|
|
|
@@ -524,8 +572,9 @@ describe("Admin Routes (Integration)", () => {
|
|
|
524
572
|
|
|
525
573
|
const res = await app.request("/admin/roles/missing", {
|
|
526
574
|
method: "PUT",
|
|
527
|
-
headers: { "Content-Type": "application/json",
|
|
528
|
-
|
|
575
|
+
headers: { "Content-Type": "application/json",
|
|
576
|
+
...adminAuth() },
|
|
577
|
+
body: JSON.stringify({ name: "Nope" })
|
|
529
578
|
});
|
|
530
579
|
expect(res.status).toBe(404);
|
|
531
580
|
});
|
|
@@ -538,7 +587,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
538
587
|
|
|
539
588
|
const res = await app.request("/admin/roles/custom", {
|
|
540
589
|
method: "DELETE",
|
|
541
|
-
headers: { ...adminAuth() }
|
|
590
|
+
headers: { ...adminAuth() }
|
|
542
591
|
});
|
|
543
592
|
expect(res.status).toBe(200);
|
|
544
593
|
expect(mockAuthRepo.deleteRole).toHaveBeenCalledWith("custom");
|
|
@@ -549,7 +598,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
549
598
|
|
|
550
599
|
const res = await app.request("/admin/roles/admin", {
|
|
551
600
|
method: "DELETE",
|
|
552
|
-
headers: { ...adminAuth() }
|
|
601
|
+
headers: { ...adminAuth() }
|
|
553
602
|
});
|
|
554
603
|
expect(res.status).toBe(400);
|
|
555
604
|
const body = await res.json() as any;
|
|
@@ -561,7 +610,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
561
610
|
|
|
562
611
|
const res = await app.request("/admin/roles/editor", {
|
|
563
612
|
method: "DELETE",
|
|
564
|
-
headers: { ...adminAuth() }
|
|
613
|
+
headers: { ...adminAuth() }
|
|
565
614
|
});
|
|
566
615
|
expect(res.status).toBe(400);
|
|
567
616
|
});
|
|
@@ -571,7 +620,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
571
620
|
|
|
572
621
|
const res = await app.request("/admin/roles/viewer", {
|
|
573
622
|
method: "DELETE",
|
|
574
|
-
headers: { ...adminAuth() }
|
|
623
|
+
headers: { ...adminAuth() }
|
|
575
624
|
});
|
|
576
625
|
expect(res.status).toBe(400);
|
|
577
626
|
});
|
|
@@ -582,7 +631,7 @@ describe("Admin Routes (Integration)", () => {
|
|
|
582
631
|
|
|
583
632
|
const res = await app.request("/admin/roles/ghost", {
|
|
584
633
|
method: "DELETE",
|
|
585
|
-
headers: { ...adminAuth() }
|
|
634
|
+
headers: { ...adminAuth() }
|
|
586
635
|
});
|
|
587
636
|
expect(res.status).toBe(404);
|
|
588
637
|
});
|