@things-factory/auth-base 10.1.111 → 10.1.113
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-server/ai-entry/access-assistant.d.ts +8 -0
- package/dist-server/ai-entry/access-assistant.js +9 -1
- package/dist-server/ai-entry/access-assistant.js.map +1 -1
- package/dist-server/service/appliance/appliance-query.js +4 -2
- package/dist-server/service/appliance/appliance-query.js.map +1 -1
- package/dist-server/service/application/application-query.js +2 -1
- package/dist-server/service/application/application-query.js.map +1 -1
- package/dist-server/service/auth-provider/auth-provider-query.js +2 -1
- package/dist-server/service/auth-provider/auth-provider-query.js.map +1 -1
- package/dist-server/service/invitation/invitation-query.js +2 -1
- package/dist-server/service/invitation/invitation-query.js.map +1 -1
- package/dist-server/service/login-history/login-history-query.js +8 -4
- package/dist-server/service/login-history/login-history-query.js.map +1 -1
- package/dist-server/service/partner/partner-query.js +2 -1
- package/dist-server/service/partner/partner-query.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/tests/list-inheritance-db.test.ts +149 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/auth-base",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.113",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"passport-jwt": "^4.0.0",
|
|
49
49
|
"passport-local": "^1.0.0"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "9da1e467ddce23e600e64f08454289cb3b806212"
|
|
52
52
|
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A list reads this domain's rows only - whatever `inherited` the caller sent (2026-10-02).
|
|
3
|
+
*
|
|
4
|
+
* `getQueryBuilderFromListParams` honours `inherited: Include | Only`, so a list that hands the client's ListParam
|
|
5
|
+
* through lets a child domain read its parent's rows. For these lists a parent's rows are another tenant's
|
|
6
|
+
* configuration or people, and no screen asks for them: the query pins `inherited` to None. The same pin as
|
|
7
|
+
* `accessRequests` (access-request-db.test.ts).
|
|
8
|
+
*
|
|
9
|
+
* Roles are not here - the role screens ask for the parent's roles on purpose (assignable scope, docs/design/auth-rebuild.md).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { closeAuthDatabase, Domain, getRepository, openAuthDatabase, resetAuthDatabase } from './db'
|
|
13
|
+
import { loadCompiled } from './compiled'
|
|
14
|
+
|
|
15
|
+
const { User } = loadCompiled('service/user/user')
|
|
16
|
+
const { AuthProvider } = loadCompiled('service/auth-provider/auth-provider')
|
|
17
|
+
const { AuthProviderQuery } = loadCompiled('service/auth-provider/auth-provider-query')
|
|
18
|
+
const { Appliance } = loadCompiled('service/appliance/appliance')
|
|
19
|
+
const { ApplianceQuery } = loadCompiled('service/appliance/appliance-query')
|
|
20
|
+
const { Application } = loadCompiled('service/application/application')
|
|
21
|
+
const { ApplicationQuery } = loadCompiled('service/application/application-query')
|
|
22
|
+
const { Invitation } = loadCompiled('service/invitation/invitation')
|
|
23
|
+
const { InvitationStatus } = loadCompiled('utils/invitation-state')
|
|
24
|
+
const { InvitationQuery } = loadCompiled('service/invitation/invitation-query')
|
|
25
|
+
const { Partner } = loadCompiled('service/partner/partner')
|
|
26
|
+
const { PartnerQuery } = loadCompiled('service/partner/partner-query')
|
|
27
|
+
const { LoginHistory } = loadCompiled('service/login-history/login-history')
|
|
28
|
+
const { LoginHistoryQuery } = loadCompiled('service/login-history/login-history-query')
|
|
29
|
+
|
|
30
|
+
let parent: any
|
|
31
|
+
let child: any
|
|
32
|
+
let partnerDomain: any
|
|
33
|
+
let parentUser: any
|
|
34
|
+
let childUser: any
|
|
35
|
+
|
|
36
|
+
async function makeUser(name: string, domains: any[]) {
|
|
37
|
+
return await getRepository(User).save({
|
|
38
|
+
username: name,
|
|
39
|
+
email: `${name}@example.com`,
|
|
40
|
+
name,
|
|
41
|
+
salt: User.generateSalt(),
|
|
42
|
+
status: 'activated',
|
|
43
|
+
domains
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const from = (domain: any, user: any) => ({ state: { domain, user } }) as any
|
|
48
|
+
const ONLY = { inherited: 'Only' } as any
|
|
49
|
+
|
|
50
|
+
beforeAll(async () => {
|
|
51
|
+
await openAuthDatabase()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
afterAll(async () => {
|
|
55
|
+
await closeAuthDatabase()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
beforeEach(async () => {
|
|
59
|
+
await resetAuthDatabase()
|
|
60
|
+
|
|
61
|
+
const savedParent = await getRepository(Domain).save({ name: 'Plant A', subdomain: 'plant-a' })
|
|
62
|
+
parent = await getRepository(Domain).findOneBy({ id: savedParent.id })
|
|
63
|
+
const savedChild = await getRepository(Domain).save({ name: 'Plant A-1', subdomain: 'plant-a-1', parent })
|
|
64
|
+
child = await getRepository(Domain).findOneBy({ id: savedChild.id })
|
|
65
|
+
partnerDomain = await getRepository(Domain).save({ name: 'Vendor', subdomain: 'vendor' })
|
|
66
|
+
|
|
67
|
+
parentUser = await makeUser('parent-admin', [parent])
|
|
68
|
+
childUser = await makeUser('child-admin', [child])
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
/*
|
|
72
|
+
* Each list: the parent reads its own row (so an empty answer below is the pin, not a broken fixture), and the
|
|
73
|
+
* child asking for the parent's with `inherited: Only` reads nothing.
|
|
74
|
+
*/
|
|
75
|
+
const LISTS: [string, () => Promise<any>, (params: any, context: any) => Promise<any>][] = [
|
|
76
|
+
[
|
|
77
|
+
'auth providers',
|
|
78
|
+
() => getRepository(AuthProvider).save({ domain: parent, type: 'keycloak', clientSecret: 'parent-secret' }),
|
|
79
|
+
(params, context) => new AuthProviderQuery().authProviders(params, context)
|
|
80
|
+
],
|
|
81
|
+
[
|
|
82
|
+
'appliances',
|
|
83
|
+
() => getRepository(Appliance).save({ domain: parent, name: 'gate', serialNo: 'gate-SN', brand: 'Acme', model: 'X1' }),
|
|
84
|
+
(params, context) => new ApplianceQuery().appliances(params, context)
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
'edges',
|
|
88
|
+
() => getRepository(Appliance).save({ domain: parent, name: 'edge', serialNo: 'edge-SN', brand: 'Acme', model: 'X1' }),
|
|
89
|
+
(params, context) => new ApplianceQuery().edges(params, context)
|
|
90
|
+
],
|
|
91
|
+
[
|
|
92
|
+
'applications',
|
|
93
|
+
() =>
|
|
94
|
+
getRepository(Application).save({
|
|
95
|
+
domain: parent,
|
|
96
|
+
name: 'billing',
|
|
97
|
+
email: 'billing@acme.z',
|
|
98
|
+
url: 'https://billing.example.com',
|
|
99
|
+
redirectUrl: 'https://billing.example.com/callback',
|
|
100
|
+
status: 0,
|
|
101
|
+
type: 'OTHERS',
|
|
102
|
+
appSecret: 'parent-app-secret'
|
|
103
|
+
}),
|
|
104
|
+
(params, context) => new ApplicationQuery().applications(params, context)
|
|
105
|
+
],
|
|
106
|
+
[
|
|
107
|
+
'invitations',
|
|
108
|
+
() =>
|
|
109
|
+
getRepository(Invitation).save({
|
|
110
|
+
email: 'lee@acme.z',
|
|
111
|
+
domain: parent,
|
|
112
|
+
status: InvitationStatus.PENDING,
|
|
113
|
+
token: 'parent-token',
|
|
114
|
+
expiresAt: new Date(Date.now() + 3600_000)
|
|
115
|
+
}),
|
|
116
|
+
(params, context) => new InvitationQuery().invitations(params, context)
|
|
117
|
+
],
|
|
118
|
+
[
|
|
119
|
+
'partners',
|
|
120
|
+
() => getRepository(Partner).save({ domain: parent, partnerDomain, requestedAt: new Date() }),
|
|
121
|
+
(params, context) => new PartnerQuery().partners(params, context)
|
|
122
|
+
],
|
|
123
|
+
[
|
|
124
|
+
'login histories',
|
|
125
|
+
() => LoginHistory.stamp(parent, parentUser, '10.0.0.1'),
|
|
126
|
+
(params, context) => new LoginHistoryQuery().loginHistories(params, context)
|
|
127
|
+
]
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
describe.each(LISTS)('%s', (_name, seed, list) => {
|
|
131
|
+
it("★ the parent reads its own row - the fixture is real", async () => {
|
|
132
|
+
await seed()
|
|
133
|
+
const answer = await list({}, from(parent, parentUser))
|
|
134
|
+
expect(answer.items).toHaveLength(1)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it("★ a child domain asking for the parent's with inherited: Only reads nothing", async () => {
|
|
138
|
+
await seed()
|
|
139
|
+
const answer = await list(ONLY, from(child, childUser))
|
|
140
|
+
expect(answer.items).toEqual([])
|
|
141
|
+
expect(answer.total).toBe(0)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it("a child domain asking with inherited: Include reads nothing of the parent's", async () => {
|
|
145
|
+
await seed()
|
|
146
|
+
const answer = await list({ inherited: 'Include' }, from(child, childUser))
|
|
147
|
+
expect(answer.items).toEqual([])
|
|
148
|
+
})
|
|
149
|
+
})
|