@byline/db-postgres 0.9.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/LICENSE +373 -0
- package/README.md +18 -0
- package/dist/database/schema/auth.d.ts +857 -0
- package/dist/database/schema/auth.d.ts.map +1 -0
- package/dist/database/schema/auth.js +176 -0
- package/dist/database/schema/auth.js.map +1 -0
- package/dist/database/schema/index.d.ts +2955 -0
- package/dist/database/schema/index.d.ts.map +1 -0
- package/dist/database/schema/index.js +500 -0
- package/dist/database/schema/index.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/test-helper.d.ts +17 -0
- package/dist/lib/test-helper.d.ts.map +1 -0
- package/dist/lib/test-helper.js +47 -0
- package/dist/lib/test-helper.js.map +1 -0
- package/dist/modules/admin/admin-permissions-repository.d.ts +17 -0
- package/dist/modules/admin/admin-permissions-repository.d.ts.map +1 -0
- package/dist/modules/admin/admin-permissions-repository.js +76 -0
- package/dist/modules/admin/admin-permissions-repository.js.map +1 -0
- package/dist/modules/admin/admin-roles-repository.d.ts +12 -0
- package/dist/modules/admin/admin-roles-repository.d.ts.map +1 -0
- package/dist/modules/admin/admin-roles-repository.js +168 -0
- package/dist/modules/admin/admin-roles-repository.js.map +1 -0
- package/dist/modules/admin/admin-store.d.ts +20 -0
- package/dist/modules/admin/admin-store.d.ts.map +1 -0
- package/dist/modules/admin/admin-store.js +28 -0
- package/dist/modules/admin/admin-store.js.map +1 -0
- package/dist/modules/admin/admin-users-repository.d.ts +12 -0
- package/dist/modules/admin/admin-users-repository.d.ts.map +1 -0
- package/dist/modules/admin/admin-users-repository.js +208 -0
- package/dist/modules/admin/admin-users-repository.js.map +1 -0
- package/dist/modules/admin/index.d.ts +27 -0
- package/dist/modules/admin/index.d.ts.map +1 -0
- package/dist/modules/admin/index.js +27 -0
- package/dist/modules/admin/index.js.map +1 -0
- package/dist/modules/admin/refresh-tokens-repository.d.ts +16 -0
- package/dist/modules/admin/refresh-tokens-repository.d.ts.map +1 -0
- package/dist/modules/admin/refresh-tokens-repository.js +132 -0
- package/dist/modules/admin/refresh-tokens-repository.js.map +1 -0
- package/dist/modules/admin/tests/auth-integration.test.d.ts +9 -0
- package/dist/modules/admin/tests/auth-integration.test.d.ts.map +1 -0
- package/dist/modules/admin/tests/auth-integration.test.js +392 -0
- package/dist/modules/admin/tests/auth-integration.test.js.map +1 -0
- package/dist/modules/admin/tests/session-provider.test.d.ts +9 -0
- package/dist/modules/admin/tests/session-provider.test.d.ts.map +1 -0
- package/dist/modules/admin/tests/session-provider.test.js +370 -0
- package/dist/modules/admin/tests/session-provider.test.js.map +1 -0
- package/dist/modules/storage/@types.d.ts +116 -0
- package/dist/modules/storage/@types.d.ts.map +1 -0
- package/dist/modules/storage/@types.js +9 -0
- package/dist/modules/storage/@types.js.map +1 -0
- package/dist/modules/storage/storage-commands.d.ts +136 -0
- package/dist/modules/storage/storage-commands.d.ts.map +1 -0
- package/dist/modules/storage/storage-commands.js +272 -0
- package/dist/modules/storage/storage-commands.js.map +1 -0
- package/dist/modules/storage/storage-flatten.d.ts +19 -0
- package/dist/modules/storage/storage-flatten.d.ts.map +1 -0
- package/dist/modules/storage/storage-flatten.js +261 -0
- package/dist/modules/storage/storage-flatten.js.map +1 -0
- package/dist/modules/storage/storage-insert.d.ts +22 -0
- package/dist/modules/storage/storage-insert.d.ts.map +1 -0
- package/dist/modules/storage/storage-insert.js +115 -0
- package/dist/modules/storage/storage-insert.js.map +1 -0
- package/dist/modules/storage/storage-queries.d.ts +377 -0
- package/dist/modules/storage/storage-queries.d.ts.map +1 -0
- package/dist/modules/storage/storage-queries.js +976 -0
- package/dist/modules/storage/storage-queries.js.map +1 -0
- package/dist/modules/storage/storage-restore.d.ts +19 -0
- package/dist/modules/storage/storage-restore.d.ts.map +1 -0
- package/dist/modules/storage/storage-restore.js +350 -0
- package/dist/modules/storage/storage-restore.js.map +1 -0
- package/dist/modules/storage/storage-store-manifest.d.ts +71 -0
- package/dist/modules/storage/storage-store-manifest.d.ts.map +1 -0
- package/dist/modules/storage/storage-store-manifest.js +294 -0
- package/dist/modules/storage/storage-store-manifest.js.map +1 -0
- package/dist/modules/storage/storage-utils.d.ts +23 -0
- package/dist/modules/storage/storage-utils.d.ts.map +1 -0
- package/dist/modules/storage/storage-utils.js +72 -0
- package/dist/modules/storage/storage-utils.js.map +1 -0
- package/dist/modules/storage/tests/storage-field-types.test.d.ts +9 -0
- package/dist/modules/storage/tests/storage-field-types.test.d.ts.map +1 -0
- package/dist/modules/storage/tests/storage-field-types.test.js +146 -0
- package/dist/modules/storage/tests/storage-field-types.test.js.map +1 -0
- package/dist/modules/storage/tests/storage-flatten-reconstruct.test.d.ts +9 -0
- package/dist/modules/storage/tests/storage-flatten-reconstruct.test.d.ts.map +1 -0
- package/dist/modules/storage/tests/storage-flatten-reconstruct.test.js +327 -0
- package/dist/modules/storage/tests/storage-flatten-reconstruct.test.js.map +1 -0
- package/dist/modules/storage/tests/storage-store-manifest.test.d.ts +9 -0
- package/dist/modules/storage/tests/storage-store-manifest.test.d.ts.map +1 -0
- package/dist/modules/storage/tests/storage-store-manifest.test.js +141 -0
- package/dist/modules/storage/tests/storage-store-manifest.test.js.map +1 -0
- package/dist/modules/storage/tests/storage-versioning.test.d.ts +9 -0
- package/dist/modules/storage/tests/storage-versioning.test.d.ts.map +1 -0
- package/dist/modules/storage/tests/storage-versioning.test.js +336 -0
- package/dist/modules/storage/tests/storage-versioning.test.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-users-repository.js","sourceRoot":"","sources":["../../../src/modules/admin/admin-users-repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* `@byline/db-postgres/admin` — Postgres implementations of the admin
|
|
10
|
+
* repository contracts declared in `@byline/admin`.
|
|
11
|
+
*
|
|
12
|
+
* Most callers want `createAdminStore(db)` — it bundles all four
|
|
13
|
+
* repositories into the `AdminStore` shape that `@byline/admin` consumers
|
|
14
|
+
* (the built-in `JwtSessionProvider`, `seedSuperAdmin`, admin-user and
|
|
15
|
+
* admin-role commands) expect. Individual factories remain exported for
|
|
16
|
+
* unusual cases (custom wiring, partial testing).
|
|
17
|
+
*
|
|
18
|
+
* No session-provider code lives here — `JwtSessionProvider` moved to
|
|
19
|
+
* `@byline/admin/auth`. This package only supplies the adapter-shaped
|
|
20
|
+
* pieces it implements.
|
|
21
|
+
*/
|
|
22
|
+
export { createAdminPermissionsRepository } from './admin-permissions-repository.js';
|
|
23
|
+
export { createAdminRolesRepository } from './admin-roles-repository.js';
|
|
24
|
+
export { createAdminStore } from './admin-store.js';
|
|
25
|
+
export { createAdminUsersRepository } from './admin-users-repository.js';
|
|
26
|
+
export { createRefreshTokensRepository } from './refresh-tokens-repository.js';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,gCAAgC,EAAE,MAAM,mCAAmC,CAAA;AACpF,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* `@byline/db-postgres/admin` — Postgres implementations of the admin
|
|
10
|
+
* repository contracts declared in `@byline/admin`.
|
|
11
|
+
*
|
|
12
|
+
* Most callers want `createAdminStore(db)` — it bundles all four
|
|
13
|
+
* repositories into the `AdminStore` shape that `@byline/admin` consumers
|
|
14
|
+
* (the built-in `JwtSessionProvider`, `seedSuperAdmin`, admin-user and
|
|
15
|
+
* admin-role commands) expect. Individual factories remain exported for
|
|
16
|
+
* unusual cases (custom wiring, partial testing).
|
|
17
|
+
*
|
|
18
|
+
* No session-provider code lives here — `JwtSessionProvider` moved to
|
|
19
|
+
* `@byline/admin/auth`. This package only supplies the adapter-shaped
|
|
20
|
+
* pieces it implements.
|
|
21
|
+
*/
|
|
22
|
+
export { createAdminPermissionsRepository } from './admin-permissions-repository.js';
|
|
23
|
+
export { createAdminRolesRepository } from './admin-roles-repository.js';
|
|
24
|
+
export { createAdminStore } from './admin-store.js';
|
|
25
|
+
export { createAdminUsersRepository } from './admin-users-repository.js';
|
|
26
|
+
export { createRefreshTokensRepository } from './refresh-tokens-repository.js';
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,gCAAgC,EAAE,MAAM,mCAAmC,CAAA;AACpF,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import type { RefreshTokensRepository } from '@byline/admin/auth';
|
|
9
|
+
import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
10
|
+
import type * as schema from '../../database/schema/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Postgres implementation of `RefreshTokensRepository`, backing the
|
|
13
|
+
* built-in `JwtSessionProvider`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createRefreshTokensRepository(db: NodePgDatabase<typeof schema>): RefreshTokensRepository;
|
|
16
|
+
//# sourceMappingURL=refresh-tokens-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-tokens-repository.d.ts","sourceRoot":"","sources":["../../../src/modules/admin/refresh-tokens-repository.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAmB,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AAElF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAG/D,OAAO,KAAK,KAAK,MAAM,MAAM,gCAAgC,CAAA;AAE7D;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,cAAc,CAAC,OAAO,MAAM,CAAC,GAChC,uBAAuB,CAyIzB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import { and, eq, isNull, lt } from 'drizzle-orm';
|
|
9
|
+
import { adminRefreshTokens } from '../../database/schema/auth.js';
|
|
10
|
+
/**
|
|
11
|
+
* Postgres implementation of `RefreshTokensRepository`, backing the
|
|
12
|
+
* built-in `JwtSessionProvider`.
|
|
13
|
+
*/
|
|
14
|
+
export function createRefreshTokensRepository(db) {
|
|
15
|
+
return {
|
|
16
|
+
async issue(input) {
|
|
17
|
+
const [row] = await db
|
|
18
|
+
.insert(adminRefreshTokens)
|
|
19
|
+
.values({
|
|
20
|
+
id: input.id,
|
|
21
|
+
admin_user_id: input.admin_user_id,
|
|
22
|
+
token_hash: input.token_hash,
|
|
23
|
+
expires_at: input.expires_at,
|
|
24
|
+
user_agent: input.user_agent ?? null,
|
|
25
|
+
ip: input.ip ?? null,
|
|
26
|
+
})
|
|
27
|
+
.returning();
|
|
28
|
+
if (!row)
|
|
29
|
+
throw new Error('issueRefreshToken: insert returned no row');
|
|
30
|
+
return row;
|
|
31
|
+
},
|
|
32
|
+
async findByHash(tokenHash) {
|
|
33
|
+
const [row] = await db
|
|
34
|
+
.select()
|
|
35
|
+
.from(adminRefreshTokens)
|
|
36
|
+
.where(eq(adminRefreshTokens.token_hash, tokenHash));
|
|
37
|
+
return row ?? null;
|
|
38
|
+
},
|
|
39
|
+
async findById(id) {
|
|
40
|
+
const [row] = await db.select().from(adminRefreshTokens).where(eq(adminRefreshTokens.id, id));
|
|
41
|
+
return row ?? null;
|
|
42
|
+
},
|
|
43
|
+
async touch(id, at = new Date()) {
|
|
44
|
+
await db
|
|
45
|
+
.update(adminRefreshTokens)
|
|
46
|
+
.set({ last_used_at: at, updated_at: new Date() })
|
|
47
|
+
.where(eq(adminRefreshTokens.id, id));
|
|
48
|
+
},
|
|
49
|
+
async markRotated(oldId, newId, at = new Date()) {
|
|
50
|
+
await db
|
|
51
|
+
.update(adminRefreshTokens)
|
|
52
|
+
.set({ revoked_at: at, rotated_to_id: newId, updated_at: new Date() })
|
|
53
|
+
.where(eq(adminRefreshTokens.id, oldId));
|
|
54
|
+
},
|
|
55
|
+
async revoke(id, at = new Date()) {
|
|
56
|
+
await db
|
|
57
|
+
.update(adminRefreshTokens)
|
|
58
|
+
.set({ revoked_at: at, updated_at: new Date() })
|
|
59
|
+
.where(and(eq(adminRefreshTokens.id, id), isNull(adminRefreshTokens.revoked_at)));
|
|
60
|
+
},
|
|
61
|
+
async revokeChain(startId, at = new Date()) {
|
|
62
|
+
let cursor = startId;
|
|
63
|
+
let touched = 0;
|
|
64
|
+
// Bounded walk — chains in practice are short; 1000 is a safety ceiling.
|
|
65
|
+
for (let step = 0; cursor != null && step < 1000; step++) {
|
|
66
|
+
const [row] = await db
|
|
67
|
+
.select({
|
|
68
|
+
id: adminRefreshTokens.id,
|
|
69
|
+
rotated_to_id: adminRefreshTokens.rotated_to_id,
|
|
70
|
+
revoked_at: adminRefreshTokens.revoked_at,
|
|
71
|
+
})
|
|
72
|
+
.from(adminRefreshTokens)
|
|
73
|
+
.where(eq(adminRefreshTokens.id, cursor));
|
|
74
|
+
if (!row)
|
|
75
|
+
break;
|
|
76
|
+
if (row.revoked_at == null) {
|
|
77
|
+
await db
|
|
78
|
+
.update(adminRefreshTokens)
|
|
79
|
+
.set({ revoked_at: at, updated_at: new Date() })
|
|
80
|
+
.where(eq(adminRefreshTokens.id, row.id));
|
|
81
|
+
touched++;
|
|
82
|
+
}
|
|
83
|
+
cursor = row.rotated_to_id;
|
|
84
|
+
}
|
|
85
|
+
return touched;
|
|
86
|
+
},
|
|
87
|
+
async revokeAllForUser(adminUserId, at = new Date()) {
|
|
88
|
+
const result = await db
|
|
89
|
+
.update(adminRefreshTokens)
|
|
90
|
+
.set({ revoked_at: at, updated_at: new Date() })
|
|
91
|
+
.where(and(eq(adminRefreshTokens.admin_user_id, adminUserId), isNull(adminRefreshTokens.revoked_at)))
|
|
92
|
+
.returning({ id: adminRefreshTokens.id });
|
|
93
|
+
return result.length;
|
|
94
|
+
},
|
|
95
|
+
async purgeExpired(now = new Date()) {
|
|
96
|
+
const result = await db
|
|
97
|
+
.delete(adminRefreshTokens)
|
|
98
|
+
.where(lt(adminRefreshTokens.expires_at, now))
|
|
99
|
+
.returning({ id: adminRefreshTokens.id });
|
|
100
|
+
return result.length;
|
|
101
|
+
},
|
|
102
|
+
async listActiveForUser(adminUserId) {
|
|
103
|
+
return db
|
|
104
|
+
.select()
|
|
105
|
+
.from(adminRefreshTokens)
|
|
106
|
+
.where(and(eq(adminRefreshTokens.admin_user_id, adminUserId), isNull(adminRefreshTokens.revoked_at)));
|
|
107
|
+
},
|
|
108
|
+
async listAllForUser(adminUserId) {
|
|
109
|
+
return db
|
|
110
|
+
.select()
|
|
111
|
+
.from(adminRefreshTokens)
|
|
112
|
+
.where(eq(adminRefreshTokens.admin_user_id, adminUserId))
|
|
113
|
+
.orderBy(adminRefreshTokens.issued_at);
|
|
114
|
+
},
|
|
115
|
+
async listRotationChain(startId) {
|
|
116
|
+
const chain = [];
|
|
117
|
+
let cursor = startId;
|
|
118
|
+
for (let step = 0; cursor != null && step < 1000; step++) {
|
|
119
|
+
const [row] = await db
|
|
120
|
+
.select()
|
|
121
|
+
.from(adminRefreshTokens)
|
|
122
|
+
.where(eq(adminRefreshTokens.id, cursor));
|
|
123
|
+
if (!row)
|
|
124
|
+
break;
|
|
125
|
+
chain.push(row);
|
|
126
|
+
cursor = row.rotated_to_id;
|
|
127
|
+
}
|
|
128
|
+
return chain;
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=refresh-tokens-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-tokens-repository.js","sourceRoot":"","sources":["../../../src/modules/admin/refresh-tokens-repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=auth-integration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-integration.test.d.ts","sourceRoot":"","sources":["../../../../src/modules/admin/tests/auth-integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import assert from 'node:assert';
|
|
9
|
+
import { after, afterEach, before, describe, it } from 'node:test';
|
|
10
|
+
import { seedSuperAdmin } from '@byline/admin/admin-users';
|
|
11
|
+
import { hashPassword, resolveActor, verifyPassword } from '@byline/admin/auth';
|
|
12
|
+
import { AdminAuth } from '@byline/auth';
|
|
13
|
+
import { eq, inArray } from 'drizzle-orm';
|
|
14
|
+
import { adminPermissions, adminRoleAdminUser, adminRoles, adminUsers, } from '../../../database/schema/auth.js';
|
|
15
|
+
import { setupTestDB, teardownTestDB } from '../../../lib/test-helper.js';
|
|
16
|
+
import { createAdminStore } from '../admin-store.js';
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Track-and-clean fixtures
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
//
|
|
21
|
+
// Integration tests share the dev database with the running webapp, so
|
|
22
|
+
// blanket `DELETE FROM admin_users` wipes would take out whichever
|
|
23
|
+
// super-admin the developer signed in with. Instead, every admin-user
|
|
24
|
+
// and admin-role row a test creates flows through `createUser` or
|
|
25
|
+
// `createRole` helpers that push the new id into a per-suite tracking
|
|
26
|
+
// set. `afterEach` deletes only those ids; `ON DELETE CASCADE` on
|
|
27
|
+
// `adminPermissions`, `adminRoleAdminUser`, and `adminRefreshTokens`
|
|
28
|
+
// handles the dependent rows automatically.
|
|
29
|
+
//
|
|
30
|
+
// To guard against a crashed prior run leaving a stale row with a test
|
|
31
|
+
// email, the helpers pre-delete any existing row with the same email or
|
|
32
|
+
// machine_name before inserting. Keeps the suite re-runnable without
|
|
33
|
+
// manual cleanup.
|
|
34
|
+
let db;
|
|
35
|
+
let store;
|
|
36
|
+
const trackedUserIds = new Set();
|
|
37
|
+
const trackedRoleIds = new Set();
|
|
38
|
+
function trackUser(id) {
|
|
39
|
+
trackedUserIds.add(id);
|
|
40
|
+
}
|
|
41
|
+
function trackRole(id) {
|
|
42
|
+
trackedRoleIds.add(id);
|
|
43
|
+
}
|
|
44
|
+
async function createUser(input) {
|
|
45
|
+
const email = input.email.toLowerCase();
|
|
46
|
+
// Clear any stale row left by a crashed prior run.
|
|
47
|
+
await db.delete(adminUsers).where(eq(adminUsers.email, email));
|
|
48
|
+
const password_hash = await hashPassword(input.password);
|
|
49
|
+
const row = await store.adminUsers.create({
|
|
50
|
+
email: input.email,
|
|
51
|
+
password_hash,
|
|
52
|
+
given_name: input.given_name,
|
|
53
|
+
is_enabled: input.is_enabled,
|
|
54
|
+
is_super_admin: input.is_super_admin,
|
|
55
|
+
});
|
|
56
|
+
trackUser(row.id);
|
|
57
|
+
return row;
|
|
58
|
+
}
|
|
59
|
+
async function createRole(input) {
|
|
60
|
+
await db.delete(adminRoles).where(eq(adminRoles.machine_name, input.machine_name));
|
|
61
|
+
const row = await store.adminRoles.create(input);
|
|
62
|
+
trackRole(row.id);
|
|
63
|
+
return row;
|
|
64
|
+
}
|
|
65
|
+
async function cleanupTrackedRows() {
|
|
66
|
+
if (trackedUserIds.size > 0) {
|
|
67
|
+
await db.delete(adminUsers).where(inArray(adminUsers.id, [...trackedUserIds]));
|
|
68
|
+
}
|
|
69
|
+
if (trackedRoleIds.size > 0) {
|
|
70
|
+
await db.delete(adminRoles).where(inArray(adminRoles.id, [...trackedRoleIds]));
|
|
71
|
+
}
|
|
72
|
+
trackedUserIds.clear();
|
|
73
|
+
trackedRoleIds.clear();
|
|
74
|
+
}
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
describe('auth integration', () => {
|
|
77
|
+
before(() => {
|
|
78
|
+
const testDB = setupTestDB([]);
|
|
79
|
+
db = testDB.db;
|
|
80
|
+
store = createAdminStore(db);
|
|
81
|
+
});
|
|
82
|
+
afterEach(async () => {
|
|
83
|
+
await cleanupTrackedRows();
|
|
84
|
+
});
|
|
85
|
+
after(async () => {
|
|
86
|
+
await cleanupTrackedRows();
|
|
87
|
+
await teardownTestDB();
|
|
88
|
+
});
|
|
89
|
+
// -------------------------------------------------------------------------
|
|
90
|
+
// Admin users
|
|
91
|
+
// -------------------------------------------------------------------------
|
|
92
|
+
describe('admin users repository', () => {
|
|
93
|
+
it('creates, reads, and hides the password hash from public rows', async () => {
|
|
94
|
+
const created = await createUser({
|
|
95
|
+
email: 'alice@example.com',
|
|
96
|
+
password: 'alice-password',
|
|
97
|
+
given_name: 'Alice',
|
|
98
|
+
});
|
|
99
|
+
assert.ok(created.id);
|
|
100
|
+
assert.strictEqual(created.email, 'alice@example.com');
|
|
101
|
+
assert.strictEqual(created.given_name, 'Alice');
|
|
102
|
+
assert.strictEqual(created.is_enabled, false); // default false
|
|
103
|
+
assert.strictEqual(created.is_super_admin, false);
|
|
104
|
+
// Public columns: password_hash is never returned
|
|
105
|
+
assert.strictEqual(created.password_hash, undefined);
|
|
106
|
+
const fetched = await store.adminUsers.getById(created.id);
|
|
107
|
+
assert.strictEqual(fetched?.email, 'alice@example.com');
|
|
108
|
+
});
|
|
109
|
+
it('lowercases the email on insert and on lookup', async () => {
|
|
110
|
+
await createUser({ email: 'Alice@Example.COM', password: 'pw' });
|
|
111
|
+
const byMixed = await store.adminUsers.getByEmail('ALICE@example.com');
|
|
112
|
+
assert.ok(byMixed);
|
|
113
|
+
assert.strictEqual(byMixed.email, 'alice@example.com');
|
|
114
|
+
});
|
|
115
|
+
it('returns the password hash only via getByEmailForSignIn', async () => {
|
|
116
|
+
await createUser({ email: 'b@example.com', password: 'pw-value' });
|
|
117
|
+
const plain = await store.adminUsers.getByEmail('b@example.com');
|
|
118
|
+
assert.strictEqual(plain?.password_hash, undefined);
|
|
119
|
+
const withPw = await store.adminUsers.getByEmailForSignIn('b@example.com');
|
|
120
|
+
assert.ok(withPw);
|
|
121
|
+
assert.ok(await verifyPassword('pw-value', withPw.password_hash));
|
|
122
|
+
});
|
|
123
|
+
it('update applies partial patches and bumps vid', async () => {
|
|
124
|
+
const created = await createUser({ email: 'c@example.com', password: 'pw' });
|
|
125
|
+
assert.strictEqual(created.vid, 1);
|
|
126
|
+
const updated = await store.adminUsers.update(created.id, created.vid, {
|
|
127
|
+
given_name: 'Charlie',
|
|
128
|
+
is_enabled: true,
|
|
129
|
+
});
|
|
130
|
+
assert.strictEqual(updated.given_name, 'Charlie');
|
|
131
|
+
assert.strictEqual(updated.is_enabled, true);
|
|
132
|
+
// Unchanged fields remain
|
|
133
|
+
assert.strictEqual(updated.email, 'c@example.com');
|
|
134
|
+
assert.strictEqual(updated.vid, created.vid + 1);
|
|
135
|
+
});
|
|
136
|
+
it('update throws VERSION_CONFLICT on a stale vid', async () => {
|
|
137
|
+
const created = await createUser({ email: 'c2@example.com', password: 'pw' });
|
|
138
|
+
// First update succeeds and bumps vid.
|
|
139
|
+
await store.adminUsers.update(created.id, created.vid, { given_name: 'First' });
|
|
140
|
+
// Replaying the same vid must conflict.
|
|
141
|
+
await assert.rejects(() => store.adminUsers.update(created.id, created.vid, { given_name: 'Second' }), (err) => err.code === 'admin.users.versionConflict');
|
|
142
|
+
});
|
|
143
|
+
it('setPasswordHash rehashes, bumps vid, and returns the fresh row', async () => {
|
|
144
|
+
const created = await createUser({ email: 'd@example.com', password: 'old' });
|
|
145
|
+
const updated = await store.adminUsers.setPasswordHash(created.id, created.vid, await hashPassword('new-password'));
|
|
146
|
+
assert.strictEqual(updated.id, created.id);
|
|
147
|
+
assert.strictEqual(updated.vid, created.vid + 1);
|
|
148
|
+
const signIn = await store.adminUsers.getByEmailForSignIn('d@example.com');
|
|
149
|
+
assert.ok(signIn);
|
|
150
|
+
assert.ok(await verifyPassword('new-password', signIn.password_hash));
|
|
151
|
+
assert.strictEqual(await verifyPassword('old', signIn.password_hash), false);
|
|
152
|
+
assert.strictEqual(signIn.vid, created.vid + 1);
|
|
153
|
+
});
|
|
154
|
+
it('setPasswordHash throws VERSION_CONFLICT on a stale vid', async () => {
|
|
155
|
+
const created = await createUser({ email: 'd2@example.com', password: 'pw' });
|
|
156
|
+
await store.adminUsers.update(created.id, created.vid, { given_name: 'D' });
|
|
157
|
+
await assert.rejects(() => store.adminUsers.setPasswordHash(created.id, created.vid, '$argon2id$stale-hash'), (err) => err.code === 'admin.users.versionConflict');
|
|
158
|
+
});
|
|
159
|
+
it('recordLoginSuccess resets failed_login_attempts and stamps last_login', async () => {
|
|
160
|
+
const created = await createUser({ email: 'e@example.com', password: 'pw' });
|
|
161
|
+
await store.adminUsers.recordLoginFailure(created.id);
|
|
162
|
+
await store.adminUsers.recordLoginFailure(created.id);
|
|
163
|
+
let row = await store.adminUsers.getById(created.id);
|
|
164
|
+
assert.strictEqual(row?.failed_login_attempts, 2);
|
|
165
|
+
await store.adminUsers.recordLoginSuccess(created.id, '10.0.0.1');
|
|
166
|
+
row = await store.adminUsers.getById(created.id);
|
|
167
|
+
assert.strictEqual(row?.failed_login_attempts, 0);
|
|
168
|
+
assert.strictEqual(row?.last_login_ip, '10.0.0.1');
|
|
169
|
+
assert.ok(row?.last_login);
|
|
170
|
+
});
|
|
171
|
+
it('delete removes the row when vid matches', async () => {
|
|
172
|
+
const created = await createUser({ email: 'f@example.com', password: 'pw' });
|
|
173
|
+
await store.adminUsers.delete(created.id, created.vid);
|
|
174
|
+
const fetched = await store.adminUsers.getById(created.id);
|
|
175
|
+
assert.strictEqual(fetched, null);
|
|
176
|
+
});
|
|
177
|
+
it('delete throws VERSION_CONFLICT on a stale vid', async () => {
|
|
178
|
+
const created = await createUser({ email: 'f2@example.com', password: 'pw' });
|
|
179
|
+
await store.adminUsers.update(created.id, created.vid, { given_name: 'F' });
|
|
180
|
+
await assert.rejects(() => store.adminUsers.delete(created.id, created.vid), (err) => err.code === 'admin.users.versionConflict');
|
|
181
|
+
// Row should still be present.
|
|
182
|
+
assert.ok(await store.adminUsers.getById(created.id));
|
|
183
|
+
});
|
|
184
|
+
it('list applies pagination, order, and query filter', async () => {
|
|
185
|
+
await createUser({ email: 'list1@example.com', password: 'pw', given_name: 'Aaron' });
|
|
186
|
+
await createUser({ email: 'list2@example.com', password: 'pw', given_name: 'Bea' });
|
|
187
|
+
await createUser({ email: 'list3@example.com', password: 'pw', given_name: 'Casey' });
|
|
188
|
+
// Query filters against a stable, unique-to-this-test needle so
|
|
189
|
+
// other test or dev rows don't skew the totals.
|
|
190
|
+
const filtered = await store.adminUsers.list({
|
|
191
|
+
page: 1,
|
|
192
|
+
pageSize: 10,
|
|
193
|
+
query: 'list',
|
|
194
|
+
order: 'email',
|
|
195
|
+
desc: false,
|
|
196
|
+
});
|
|
197
|
+
assert.strictEqual(filtered.length, 3);
|
|
198
|
+
const named = await store.adminUsers.list({
|
|
199
|
+
page: 1,
|
|
200
|
+
pageSize: 10,
|
|
201
|
+
query: 'Bea',
|
|
202
|
+
order: 'email',
|
|
203
|
+
desc: false,
|
|
204
|
+
});
|
|
205
|
+
assert.strictEqual(named.length, 1);
|
|
206
|
+
assert.strictEqual(named[0]?.given_name, 'Bea');
|
|
207
|
+
const total = await store.adminUsers.count({ query: 'list' });
|
|
208
|
+
assert.strictEqual(total, 3);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
// -------------------------------------------------------------------------
|
|
212
|
+
// Admin roles + assignments
|
|
213
|
+
// -------------------------------------------------------------------------
|
|
214
|
+
describe('admin roles repository', () => {
|
|
215
|
+
it('creates and reads a role', async () => {
|
|
216
|
+
const role = await createRole({
|
|
217
|
+
name: 'Editor',
|
|
218
|
+
machine_name: 'test-editor',
|
|
219
|
+
description: 'Can edit content',
|
|
220
|
+
});
|
|
221
|
+
assert.strictEqual(role.machine_name, 'test-editor');
|
|
222
|
+
const byMachine = await store.adminRoles.getByMachineName('test-editor');
|
|
223
|
+
assert.strictEqual(byMachine?.id, role.id);
|
|
224
|
+
});
|
|
225
|
+
it('assignToUser is idempotent and listRolesForUser returns the role', async () => {
|
|
226
|
+
const user = await createUser({ email: 'g@example.com', password: 'pw' });
|
|
227
|
+
const role = await createRole({ name: 'test-r', machine_name: 'test-r' });
|
|
228
|
+
await store.adminRoles.assignToUser(role.id, user.id);
|
|
229
|
+
await store.adminRoles.assignToUser(role.id, user.id); // idempotent
|
|
230
|
+
const userRoles = await store.adminRoles.listRolesForUser(user.id);
|
|
231
|
+
assert.strictEqual(userRoles.length, 1);
|
|
232
|
+
assert.strictEqual(userRoles[0]?.machine_name, 'test-r');
|
|
233
|
+
const usersForRole = await store.adminRoles.listUsersForRole(role.id);
|
|
234
|
+
assert.deepStrictEqual(usersForRole, [user.id]);
|
|
235
|
+
});
|
|
236
|
+
it('unassignFromUser removes the assignment', async () => {
|
|
237
|
+
const user = await createUser({ email: 'h@example.com', password: 'pw' });
|
|
238
|
+
const role = await createRole({ name: 'test-r', machine_name: 'test-r' });
|
|
239
|
+
await store.adminRoles.assignToUser(role.id, user.id);
|
|
240
|
+
await store.adminRoles.unassignFromUser(role.id, user.id);
|
|
241
|
+
assert.strictEqual((await store.adminRoles.listRolesForUser(user.id)).length, 0);
|
|
242
|
+
});
|
|
243
|
+
it('delete cascades to permissions and role-user assignments', async () => {
|
|
244
|
+
const user = await createUser({ email: 'i@example.com', password: 'pw' });
|
|
245
|
+
const role = await createRole({ name: 'test-r', machine_name: 'test-r' });
|
|
246
|
+
await store.adminPermissions.grantAbility(role.id, 'a.one');
|
|
247
|
+
await store.adminRoles.assignToUser(role.id, user.id);
|
|
248
|
+
await store.adminRoles.delete(role.id, role.vid);
|
|
249
|
+
// The role is gone…
|
|
250
|
+
assert.strictEqual(await store.adminRoles.getById(role.id), null);
|
|
251
|
+
// …and its grants are gone…
|
|
252
|
+
const grantsForRole = await db
|
|
253
|
+
.select()
|
|
254
|
+
.from(adminPermissions)
|
|
255
|
+
.where(eq(adminPermissions.admin_role_id, role.id));
|
|
256
|
+
assert.strictEqual(grantsForRole.length, 0);
|
|
257
|
+
// …and no assignment for the role remains.
|
|
258
|
+
const assignsForRole = await db
|
|
259
|
+
.select()
|
|
260
|
+
.from(adminRoleAdminUser)
|
|
261
|
+
.where(eq(adminRoleAdminUser.admin_role_id, role.id));
|
|
262
|
+
assert.strictEqual(assignsForRole.length, 0);
|
|
263
|
+
// The user still exists.
|
|
264
|
+
assert.ok(await store.adminUsers.getById(user.id));
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
// -------------------------------------------------------------------------
|
|
268
|
+
// Admin permissions
|
|
269
|
+
// -------------------------------------------------------------------------
|
|
270
|
+
describe('admin permissions repository', () => {
|
|
271
|
+
it('grantAbility is idempotent', async () => {
|
|
272
|
+
const role = await createRole({ name: 'test-r', machine_name: 'test-r' });
|
|
273
|
+
await store.adminPermissions.grantAbility(role.id, 'collections.pages.publish');
|
|
274
|
+
await store.adminPermissions.grantAbility(role.id, 'collections.pages.publish');
|
|
275
|
+
const abilities = await store.adminPermissions.listAbilities(role.id);
|
|
276
|
+
assert.deepStrictEqual(abilities, ['collections.pages.publish']);
|
|
277
|
+
});
|
|
278
|
+
it('revokeAbility removes the grant', async () => {
|
|
279
|
+
const role = await createRole({ name: 'test-r', machine_name: 'test-r' });
|
|
280
|
+
await store.adminPermissions.grantAbility(role.id, 'a.one');
|
|
281
|
+
await store.adminPermissions.grantAbility(role.id, 'a.two');
|
|
282
|
+
await store.adminPermissions.revokeAbility(role.id, 'a.one');
|
|
283
|
+
const abilities = await store.adminPermissions.listAbilities(role.id);
|
|
284
|
+
assert.deepStrictEqual(abilities.sort(), ['a.two']);
|
|
285
|
+
});
|
|
286
|
+
it('setAbilities replaces the ability set wholesale', async () => {
|
|
287
|
+
const role = await createRole({ name: 'test-r', machine_name: 'test-r' });
|
|
288
|
+
await store.adminPermissions.grantAbility(role.id, 'a.one');
|
|
289
|
+
await store.adminPermissions.grantAbility(role.id, 'a.two');
|
|
290
|
+
await store.adminPermissions.setAbilities(role.id, ['a.three', 'a.four']);
|
|
291
|
+
const abilities = await store.adminPermissions.listAbilities(role.id);
|
|
292
|
+
assert.deepStrictEqual(abilities.sort(), ['a.four', 'a.three']);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
// -------------------------------------------------------------------------
|
|
296
|
+
// resolveActor
|
|
297
|
+
// -------------------------------------------------------------------------
|
|
298
|
+
describe('resolveActor', () => {
|
|
299
|
+
it('returns null for unknown user ids', async () => {
|
|
300
|
+
const actor = await resolveActor(store, '00000000-0000-7000-8000-000000000000');
|
|
301
|
+
assert.strictEqual(actor, null);
|
|
302
|
+
});
|
|
303
|
+
it('returns null for disabled users', async () => {
|
|
304
|
+
const user = await createUser({ email: 'j@example.com', password: 'pw' });
|
|
305
|
+
// Created with is_enabled: false by default
|
|
306
|
+
const actor = await resolveActor(store, user.id);
|
|
307
|
+
assert.strictEqual(actor, null);
|
|
308
|
+
});
|
|
309
|
+
it('builds an AdminAuth with the union of abilities across roles', async () => {
|
|
310
|
+
const user = await createUser({
|
|
311
|
+
email: 'k@example.com',
|
|
312
|
+
password: 'pw',
|
|
313
|
+
is_enabled: true,
|
|
314
|
+
});
|
|
315
|
+
const roleA = await createRole({ name: 'A', machine_name: 'test-a' });
|
|
316
|
+
const roleB = await createRole({ name: 'B', machine_name: 'test-b' });
|
|
317
|
+
await store.adminPermissions.grantAbility(roleA.id, 'collections.pages.read');
|
|
318
|
+
await store.adminPermissions.grantAbility(roleA.id, 'collections.pages.update');
|
|
319
|
+
// Duplicate across roles — should collapse.
|
|
320
|
+
await store.adminPermissions.grantAbility(roleB.id, 'collections.pages.update');
|
|
321
|
+
await store.adminPermissions.grantAbility(roleB.id, 'collections.pages.publish');
|
|
322
|
+
await store.adminRoles.assignToUser(roleA.id, user.id);
|
|
323
|
+
await store.adminRoles.assignToUser(roleB.id, user.id);
|
|
324
|
+
const actor = await resolveActor(store, user.id);
|
|
325
|
+
assert.ok(actor instanceof AdminAuth);
|
|
326
|
+
assert.strictEqual(actor.id, user.id);
|
|
327
|
+
assert.strictEqual(actor.isSuperAdmin, false);
|
|
328
|
+
assert.strictEqual(actor.hasAbility('collections.pages.read'), true);
|
|
329
|
+
assert.strictEqual(actor.hasAbility('collections.pages.update'), true);
|
|
330
|
+
assert.strictEqual(actor.hasAbility('collections.pages.publish'), true);
|
|
331
|
+
assert.strictEqual(actor.hasAbility('collections.pages.delete'), false);
|
|
332
|
+
// Distinct — duplicates across roles collapse
|
|
333
|
+
assert.strictEqual(actor.abilities.size, 3);
|
|
334
|
+
});
|
|
335
|
+
it('honours the is_super_admin flag', async () => {
|
|
336
|
+
const user = await createUser({
|
|
337
|
+
email: 'test-root@example.com',
|
|
338
|
+
password: 'pw',
|
|
339
|
+
is_super_admin: true,
|
|
340
|
+
is_enabled: true,
|
|
341
|
+
});
|
|
342
|
+
const actor = await resolveActor(store, user.id);
|
|
343
|
+
assert.ok(actor);
|
|
344
|
+
assert.strictEqual(actor.isSuperAdmin, true);
|
|
345
|
+
// Even without granting any abilities, super-admins pass every check
|
|
346
|
+
assert.strictEqual(actor.hasAbility('anything.at.all'), true);
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
// -------------------------------------------------------------------------
|
|
350
|
+
// seedSuperAdmin
|
|
351
|
+
//
|
|
352
|
+
// These tests use a test-specific role machine_name and email so the
|
|
353
|
+
// idempotency assertions are not affected by (and do not affect) a
|
|
354
|
+
// real dev-environment super-admin seed.
|
|
355
|
+
// -------------------------------------------------------------------------
|
|
356
|
+
describe('seedSuperAdmin', () => {
|
|
357
|
+
const seedInput = {
|
|
358
|
+
email: 'test-seed-super@example.com',
|
|
359
|
+
password: 'initial-password',
|
|
360
|
+
roleMachineName: 'test-seed-super-admin',
|
|
361
|
+
roleName: 'Test Seed Super Admin',
|
|
362
|
+
};
|
|
363
|
+
it('creates role + user + assignment on first run', async () => {
|
|
364
|
+
// Pre-clean in case a prior run left the seed in place.
|
|
365
|
+
await db.delete(adminUsers).where(eq(adminUsers.email, seedInput.email));
|
|
366
|
+
await db.delete(adminRoles).where(eq(adminRoles.machine_name, seedInput.roleMachineName));
|
|
367
|
+
const result = await seedSuperAdmin(store, seedInput);
|
|
368
|
+
trackUser(result.userId);
|
|
369
|
+
trackRole(result.roleId);
|
|
370
|
+
assert.ok(result.userId);
|
|
371
|
+
assert.ok(result.roleId);
|
|
372
|
+
assert.deepStrictEqual(result.created, { user: true, role: true, assignment: true });
|
|
373
|
+
const actor = await resolveActor(store, result.userId);
|
|
374
|
+
assert.ok(actor);
|
|
375
|
+
assert.strictEqual(actor.isSuperAdmin, true);
|
|
376
|
+
});
|
|
377
|
+
it('is idempotent — second run reports nothing newly created', async () => {
|
|
378
|
+
await db.delete(adminUsers).where(eq(adminUsers.email, seedInput.email));
|
|
379
|
+
await db.delete(adminRoles).where(eq(adminRoles.machine_name, seedInput.roleMachineName));
|
|
380
|
+
const first = await seedSuperAdmin(store, seedInput);
|
|
381
|
+
trackUser(first.userId);
|
|
382
|
+
trackRole(first.roleId);
|
|
383
|
+
const second = await seedSuperAdmin(store, seedInput);
|
|
384
|
+
assert.deepStrictEqual(second.created, {
|
|
385
|
+
user: false,
|
|
386
|
+
role: false,
|
|
387
|
+
assignment: false,
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
//# sourceMappingURL=auth-integration.test.js.map
|