@things-factory/auth-base 10.1.254 → 10.1.257
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-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/router/auth-private-process-router.js +3 -7
- package/dist-server/router/auth-private-process-router.js.map +1 -1
- package/dist-server/service/audit/audit-work.d.ts +23 -0
- package/dist-server/service/audit/audit-work.js +43 -0
- package/dist-server/service/audit/audit-work.js.map +1 -0
- package/dist-server/service/index.d.ts +1 -0
- package/dist-server/service/index.js +5 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/dist-server/utils/profile-user.d.ts +31 -0
- package/dist-server/utils/profile-user.js +22 -0
- package/dist-server/utils/profile-user.js.map +1 -0
- package/package.json +2 -2
- package/tests/audit-work.test.ts +58 -0
- package/tests/profile-user.test.ts +24 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signed-in person as the client keeps them (`/auth/profile`, the store's `auth.user`).
|
|
3
|
+
*
|
|
4
|
+
* `id` is their own id, so nothing new is exposed. The client names whose unsaved drafts are kept in this
|
|
5
|
+
* browser by it (ADR-0098, `draftOwner()` in @operato/shell); without it no draft had an owner and none
|
|
6
|
+
* was written (ADR-0190, since 19ed1646178 left it out).
|
|
7
|
+
*/
|
|
8
|
+
export declare function profileUser(user: {
|
|
9
|
+
id: string;
|
|
10
|
+
username: string;
|
|
11
|
+
email?: string;
|
|
12
|
+
locale?: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
userType?: string;
|
|
15
|
+
}, grants: {
|
|
16
|
+
owner: boolean;
|
|
17
|
+
super: boolean;
|
|
18
|
+
unsafeIP?: boolean;
|
|
19
|
+
privileges: unknown[];
|
|
20
|
+
}): {
|
|
21
|
+
owner: boolean;
|
|
22
|
+
super: boolean;
|
|
23
|
+
unsafeIP?: boolean;
|
|
24
|
+
privileges: unknown[];
|
|
25
|
+
id: string;
|
|
26
|
+
username: string;
|
|
27
|
+
email: string;
|
|
28
|
+
locale: string;
|
|
29
|
+
name: string;
|
|
30
|
+
userType: string;
|
|
31
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.profileUser = profileUser;
|
|
4
|
+
/**
|
|
5
|
+
* The signed-in person as the client keeps them (`/auth/profile`, the store's `auth.user`).
|
|
6
|
+
*
|
|
7
|
+
* `id` is their own id, so nothing new is exposed. The client names whose unsaved drafts are kept in this
|
|
8
|
+
* browser by it (ADR-0098, `draftOwner()` in @operato/shell); without it no draft had an owner and none
|
|
9
|
+
* was written (ADR-0190, since 19ed1646178 left it out).
|
|
10
|
+
*/
|
|
11
|
+
function profileUser(user, grants) {
|
|
12
|
+
return {
|
|
13
|
+
id: user.id,
|
|
14
|
+
username: user.username,
|
|
15
|
+
email: user.email,
|
|
16
|
+
locale: user.locale,
|
|
17
|
+
name: user.name,
|
|
18
|
+
userType: user.userType,
|
|
19
|
+
...grants
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=profile-user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-user.js","sourceRoot":"","sources":["../../server/utils/profile-user.ts"],"names":[],"mappings":";;AAOA,kCAaC;AApBD;;;;;;GAMG;AACH,SAAgB,WAAW,CACzB,IAAyG,EACzG,MAAqF;IAErF,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG,MAAM;KACV,CAAA;AACH,CAAC","sourcesContent":["/**\n * The signed-in person as the client keeps them (`/auth/profile`, the store's `auth.user`).\n *\n * `id` is their own id, so nothing new is exposed. The client names whose unsaved drafts are kept in this\n * browser by it (ADR-0098, `draftOwner()` in @operato/shell); without it no draft had an owner and none\n * was written (ADR-0190, since 19ed1646178 left it out).\n */\nexport function profileUser(\n user: { id: string; username: string; email?: string; locale?: string; name?: string; userType?: string },\n grants: { owner: boolean; super: boolean; unsafeIP?: boolean; privileges: unknown[] }\n) {\n return {\n id: user.id,\n username: user.username,\n email: user.email,\n locale: user.locale,\n name: user.name,\n userType: user.userType,\n ...grants\n }\n}\n"]}
|
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.257",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"passport-jwt": "^4.0.0",
|
|
51
51
|
"passport-local": "^1.0.0"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "885b594299601ca4936f4f39701d6713273bbf1e"
|
|
54
54
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work done through the doors (ADR-0185 decision 6) - read from the audit: a declared mutation that went through is a
|
|
3
|
+
* piece of the person's work on that day; an undeclared one, a failed one, another person's or another day's is not.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { authDataSource, closeAuthDatabase, Domain, getRepository, openAuthDatabase, resetAuthDatabase } from './db'
|
|
7
|
+
import { loadCompiled } from './compiled'
|
|
8
|
+
|
|
9
|
+
const { registerWorkDoors, workDoneBy } = loadCompiled('service/audit/audit-work')
|
|
10
|
+
const { AuditAction } = loadCompiled('service/audit/audit-action')
|
|
11
|
+
const { AuditRequest } = loadCompiled('service/audit/audit-request')
|
|
12
|
+
const { User } = loadCompiled('service/user/user')
|
|
13
|
+
|
|
14
|
+
let domain: any, kim: any, lee: any
|
|
15
|
+
|
|
16
|
+
beforeAll(async () => {
|
|
17
|
+
await openAuthDatabase()
|
|
18
|
+
})
|
|
19
|
+
afterAll(async () => {
|
|
20
|
+
await closeAuthDatabase()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
beforeEach(async () => {
|
|
24
|
+
await resetAuthDatabase()
|
|
25
|
+
domain = await getRepository(Domain).save({ name: 'work', subdomain: 'work' })
|
|
26
|
+
kim = await getRepository(User).save({ name: 'kim', email: 'kim@work.test', status: 'activated' })
|
|
27
|
+
lee = await getRepository(User).save({ name: 'lee', email: 'lee@work.test', status: 'activated' })
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const request = async (actor: any, at: string, fields: string, outcome: 'ok' | 'error' | 'both' | null, operationType = 'mutation') => {
|
|
31
|
+
const one = await getRepository(AuditRequest).save({ id: require('crypto').randomUUID(), domain, actor, createdAt: new Date(at), channel: 'graphql', operationType, fields })
|
|
32
|
+
for (const each of outcome === 'both' ? ['ok', 'error'] : outcome ? [outcome] : [])
|
|
33
|
+
await getRepository(AuditAction).save({ domain, actor, requestId: one.id, createdAt: new Date(at), kind: 'door.result', door: 'office:mutation', outcome: each })
|
|
34
|
+
return one
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
it('a declared mutation that went through is a piece of work, once per request and work', async () => {
|
|
38
|
+
registerWorkDoors([
|
|
39
|
+
{ work: 'work.office.bank-lines', fields: ['updateMultipleCashTransaction', 'createCashTransaction'] },
|
|
40
|
+
{ work: 'work.office.tax-invoices', fields: ['importOfficeTaxInvoices'] }
|
|
41
|
+
])
|
|
42
|
+
expect(() => registerWorkDoors([{ work: 'work.other', fields: ['importOfficeTaxInvoices'] }])).toThrow(/declared as the work/)
|
|
43
|
+
|
|
44
|
+
await request(kim, '2026-11-10T01:00:00Z', 'updateMultipleCashTransaction,createCashTransaction', 'ok')
|
|
45
|
+
await request(kim, '2026-11-10T02:00:00Z', 'importOfficeTaxInvoices', 'ok')
|
|
46
|
+
await request(kim, '2026-11-10T03:00:00Z', 'importOfficeTaxInvoices', 'error')
|
|
47
|
+
await request(kim, '2026-11-10T03:30:00Z', 'createCashTransaction,importOfficeTaxInvoices', 'both')
|
|
48
|
+
await request(kim, '2026-11-10T04:00:00Z', 'saveMyDraft', 'ok')
|
|
49
|
+
await request(kim, '2026-11-10T05:00:00Z', 'importOfficeTaxInvoices', 'ok', 'query')
|
|
50
|
+
await request(lee, '2026-11-10T06:00:00Z', 'importOfficeTaxInvoices', 'ok')
|
|
51
|
+
await request(kim, '2026-11-17T01:00:00Z', 'importOfficeTaxInvoices', 'ok')
|
|
52
|
+
|
|
53
|
+
const done = await workDoneBy(authDataSource().manager, domain, kim.id, new Date('2026-11-09T00:00:00Z'), new Date('2026-11-16T00:00:00Z'))
|
|
54
|
+
expect(done.map((one: any) => [one.at.toISOString(), one.work])).toEqual([
|
|
55
|
+
['2026-11-10T01:00:00.000Z', 'work.office.bank-lines'],
|
|
56
|
+
['2026-11-10T02:00:00.000Z', 'work.office.tax-invoices']
|
|
57
|
+
])
|
|
58
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { profileUser } from '../server/utils/profile-user.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The profile carries the person's own id: the client names whose unsaved drafts this browser keeps by it
|
|
5
|
+
* (ADR-0190). It was left out in 19ed1646178, and from then on no draft had an owner and none was written.
|
|
6
|
+
*/
|
|
7
|
+
describe('profileUser', () => {
|
|
8
|
+
it('carries the id with what the client shows and the grants', () => {
|
|
9
|
+
const user = { id: 'u-1', username: 'kim', email: 'kim@example.com', locale: 'ko', name: '김', userType: 'user', password: 'hash', salt: 'salt' }
|
|
10
|
+
const profile = profileUser(user, { owner: false, super: false, unsafeIP: false, privileges: [] })
|
|
11
|
+
expect(profile).toEqual({
|
|
12
|
+
id: 'u-1',
|
|
13
|
+
username: 'kim',
|
|
14
|
+
email: 'kim@example.com',
|
|
15
|
+
locale: 'ko',
|
|
16
|
+
name: '김',
|
|
17
|
+
userType: 'user',
|
|
18
|
+
owner: false,
|
|
19
|
+
super: false,
|
|
20
|
+
unsafeIP: false,
|
|
21
|
+
privileges: []
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
})
|