@things-factory/auth-base 10.1.192 → 10.1.198
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/controllers/signin.d.ts +5 -0
- package/dist-server/controllers/signin.js +25 -0
- package/dist-server/controllers/signin.js.map +1 -1
- package/dist-server/index.js +7 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/middlewares/audit-scope-middleware.d.ts +7 -0
- package/dist-server/middlewares/audit-scope-middleware.js +15 -0
- package/dist-server/middlewares/audit-scope-middleware.js.map +1 -0
- package/dist-server/middlewares/index.js +3 -0
- package/dist-server/middlewares/index.js.map +1 -1
- package/dist-server/role-tasks.d.ts +2 -0
- package/dist-server/role-tasks.js +20 -0
- package/dist-server/role-tasks.js.map +1 -0
- package/dist-server/router/auth-checkin-router.js +3 -5
- package/dist-server/router/auth-checkin-router.js.map +1 -1
- package/dist-server/router/auth-public-process-router.js +7 -1
- package/dist-server/router/auth-public-process-router.js.map +1 -1
- package/dist-server/router/site-root-router.d.ts +2 -0
- package/dist-server/router/site-root-router.js +2 -0
- package/dist-server/router/site-root-router.js.map +1 -1
- package/dist-server/service/access-request/index.d.ts +1 -1
- package/dist-server/service/audit/audit-action.d.ts +36 -0
- package/dist-server/service/audit/audit-action.js +137 -0
- package/dist-server/service/audit/audit-action.js.map +1 -0
- package/dist-server/service/audit/audit-kinds.d.ts +19 -0
- package/dist-server/service/audit/audit-kinds.js +70 -0
- package/dist-server/service/audit/audit-kinds.js.map +1 -0
- package/dist-server/service/audit/audit-query.d.ts +11 -0
- package/dist-server/service/audit/audit-query.js +295 -0
- package/dist-server/service/audit/audit-query.js.map +1 -0
- package/dist-server/service/audit/audit-recorder.d.ts +77 -0
- package/dist-server/service/audit/audit-recorder.js +247 -0
- package/dist-server/service/audit/audit-recorder.js.map +1 -0
- package/dist-server/service/audit/audit-request.d.ts +28 -0
- package/dist-server/service/audit/audit-request.js +96 -0
- package/dist-server/service/audit/audit-request.js.map +1 -0
- package/dist-server/service/audit/audit-retention.d.ts +12 -0
- package/dist-server/service/audit/audit-retention.js +42 -0
- package/dist-server/service/audit/audit-retention.js.map +1 -0
- package/dist-server/service/audit/audit-subscriber.d.ts +39 -0
- package/dist-server/service/audit/audit-subscriber.js +191 -0
- package/dist-server/service/audit/audit-subscriber.js.map +1 -0
- package/dist-server/service/audit/audit-target.d.ts +19 -0
- package/dist-server/service/audit/audit-target.js +46 -0
- package/dist-server/service/audit/audit-target.js.map +1 -0
- package/dist-server/service/audit/audit-types.d.ts +44 -0
- package/dist-server/service/audit/audit-types.js +161 -0
- package/dist-server/service/audit/audit-types.js.map +1 -0
- package/dist-server/service/audit/index.d.ts +6 -0
- package/dist-server/service/audit/index.js +11 -0
- package/dist-server/service/audit/index.js.map +1 -0
- package/dist-server/service/domain-owner/domain-owner-mutation.js +3 -0
- package/dist-server/service/domain-owner/domain-owner-mutation.js.map +1 -1
- package/dist-server/service/index.d.ts +9 -2
- package/dist-server/service/index.js +19 -4
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/open-fields.js +1 -1
- package/dist-server/service/open-fields.js.map +1 -1
- package/dist-server/service/privilege/privilege-directive.js +25 -1
- package/dist-server/service/privilege/privilege-directive.js.map +1 -1
- package/dist-server/service/role/role-mutation.js +8 -1
- package/dist-server/service/role/role-mutation.js.map +1 -1
- package/dist-server/service/role-template/index.d.ts +1 -1
- package/dist-server/service/role-template/role-task.d.ts +74 -0
- package/dist-server/service/role-template/role-task.js +113 -0
- package/dist-server/service/role-template/role-task.js.map +1 -0
- package/dist-server/service/role-template/role-template-gap-resolver.d.ts +9 -5
- package/dist-server/service/role-template/role-template-gap-resolver.js +41 -13
- package/dist-server/service/role-template/role-template-gap-resolver.js.map +1 -1
- package/dist-server/service/role-template/role-template-mutation.js +10 -1
- package/dist-server/service/role-template/role-template-mutation.js.map +1 -1
- package/dist-server/service/role-template/role-template-query.js +4 -2
- package/dist-server/service/role-template/role-template-query.js.map +1 -1
- package/dist-server/service/role-template/role-template-types.d.ts +24 -0
- package/dist-server/service/role-template/role-template-types.js +63 -1
- package/dist-server/service/role-template/role-template-types.js.map +1 -1
- package/dist-server/service/role-template/role-template.d.ts +63 -10
- package/dist-server/service/role-template/role-template.js +92 -18
- package/dist-server/service/role-template/role-template.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/dist-server/utils/check-permission.d.ts +6 -0
- package/dist-server/utils/check-permission.js +23 -8
- package/dist-server/utils/check-permission.js.map +1 -1
- package/package.json +3 -2
- package/tests/audit-db.test.ts +394 -0
- package/tests/auth-base-role-tasks.test.ts +58 -0
- package/tests/list-inheritance-db.test.ts +0 -7
- package/tests/open-doors.test.ts +2 -2
- package/tests/refusal-cause.test.ts +1 -1
- package/tests/role-task.test.ts +168 -0
- package/tests/role-template-gap-db.test.ts +77 -2
- package/translations/en.json +13 -1
- package/translations/es.json +13 -1
- package/translations/ja.json +13 -1
- package/translations/ko.json +13 -1
- package/translations/ms.json +13 -1
- package/translations/zh.json +13 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role tasks — the registry, what it refuses, and how a role is laid against tasks (ADR-0139 decision 11).
|
|
3
|
+
*
|
|
4
|
+
* The comparison is pure: a role's held privileges, the registered tasks, the declared privileges. The role screen
|
|
5
|
+
* draws exactly this, so what "all", "some", "none" and "broken" mean is pinned here.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { loadCompiled } from './compiled'
|
|
9
|
+
|
|
10
|
+
const { registerRoleTask, roleTasks, roleTaskById, mergeGrants, taskCoverageOf, undeclaredTaskGrants } = loadCompiled('service/role-template/role-task')
|
|
11
|
+
const { registerRoleTemplate, templateGrantsOf, templateDefinitionErrors, unknownTemplateGrants } = loadCompiled('service/role-template/role-template')
|
|
12
|
+
|
|
13
|
+
const DECLARED = {
|
|
14
|
+
'board query': ['board', 'query'],
|
|
15
|
+
'board mutation': ['board', 'mutation'],
|
|
16
|
+
'order query': ['order', 'query'],
|
|
17
|
+
'worklist query': ['worklist', 'query'],
|
|
18
|
+
'worklist mutation': ['worklist', 'mutation']
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
;(process as any)['ROLE_TASKS'] = {}
|
|
23
|
+
;(process as any)['ROLE_TEMPLATES'] = {}
|
|
24
|
+
;(process as any).PRIVILEGES = { ...DECLARED }
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const held = (...pairs: string[]) => new Set(pairs.map(pair => pair.replace(':', ' ')))
|
|
28
|
+
|
|
29
|
+
describe('declaring a task', () => {
|
|
30
|
+
it('can be found again by id', () => {
|
|
31
|
+
registerRoleTask({ id: 'board.reading', grants: [{ category: 'board', axes: ['query'] }] })
|
|
32
|
+
|
|
33
|
+
expect(roleTaskById('board.reading')).toEqual({ id: 'board.reading', grants: [{ category: 'board', axes: ['query'] }] })
|
|
34
|
+
expect(roleTasks()).toHaveLength(1)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it.each([['reading'], [''], ['.reading']])('refuses the id "%s" - the declaring module comes first', id => {
|
|
38
|
+
expect(() => registerRoleTask({ id, grants: [{ category: 'board', axes: ['query'] }] })).toThrow(/<module>.<work>/)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('refuses a task that holds no privileges', () => {
|
|
42
|
+
expect(() => registerRoleTask({ id: 'board.nothing', grants: [] })).toThrow(/holds no privileges/)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('refuses a grant with no axes - axes are listed one by one', () => {
|
|
46
|
+
expect(() => registerRoleTask({ id: 'board.reading', grants: [{ category: 'board', axes: [] }] })).toThrow(/one by one/)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('refuses the same task declared twice - one piece of work is one task', () => {
|
|
50
|
+
registerRoleTask({ id: 'board.reading', grants: [{ category: 'board', axes: ['query'] }] })
|
|
51
|
+
|
|
52
|
+
expect(() => registerRoleTask({ id: 'board.reading', grants: [{ category: 'order', axes: ['query'] }] })).toThrow(/declared twice/)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('holds a privilege written twice once', () => {
|
|
56
|
+
registerRoleTask({ id: 'board.reading', grants: [{ category: 'board', axes: ['query'] }, { category: 'board', axes: ['query'] }] })
|
|
57
|
+
|
|
58
|
+
expect(roleTaskById('board.reading').grants).toEqual([{ category: 'board', axes: ['query'] }])
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('★ lets two tasks share a privilege - that is not a duplicate', () => {
|
|
62
|
+
registerRoleTask({ id: 'board.reading', grants: [{ category: 'board', axes: ['query'] }] })
|
|
63
|
+
registerRoleTask({ id: 'order.reading', grants: [{ category: 'order', axes: ['query'] }, { category: 'board', axes: ['query'] }] })
|
|
64
|
+
|
|
65
|
+
expect(roleTasks()).toHaveLength(2)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('keeps a change-only grant as written - nothing adds query to it', () => {
|
|
69
|
+
registerRoleTask({ id: 'worklist.putting-up', grants: [{ category: 'worklist', axes: ['mutation'] }] })
|
|
70
|
+
|
|
71
|
+
expect(roleTaskById('worklist.putting-up').grants).toEqual([{ category: 'worklist', axes: ['mutation'] }])
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
describe('a template built from tasks', () => {
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
registerRoleTask({ id: 'board.reading', grants: [{ category: 'board', axes: ['query'] }] })
|
|
78
|
+
registerRoleTask({ id: 'order.reading', grants: [{ category: 'order', axes: ['query'] }, { category: 'board', axes: ['query'] }] })
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('★ holds the union of its tasks and its own grants, each privilege once', () => {
|
|
82
|
+
registerRoleTemplate({ id: 'plant.reader', name: 'READER', tasks: ['board.reading', 'order.reading'], grants: [{ category: 'board', axes: ['mutation', 'query'] }] })
|
|
83
|
+
|
|
84
|
+
expect(templateGrantsOf({ id: 'plant.reader', name: 'READER', tasks: ['board.reading', 'order.reading'], grants: [{ category: 'board', axes: ['mutation', 'query'] }] })).toEqual([
|
|
85
|
+
{ category: 'board', axes: ['query', 'mutation'] },
|
|
86
|
+
{ category: 'order', axes: ['query'] }
|
|
87
|
+
])
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('may be written with tasks and no grants', () => {
|
|
91
|
+
expect(() => registerRoleTemplate({ id: 'plant.reader', name: 'READER', tasks: ['board.reading'] })).not.toThrow()
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('still refuses a template with neither - leaving both out is forgetting', () => {
|
|
95
|
+
expect(() => registerRoleTemplate({ id: 'plant.reader', name: 'READER' } as any)).toThrow(/has no grants/)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('★ names an unregistered task as a definition error', () => {
|
|
99
|
+
expect(templateDefinitionErrors({ id: 'plant.reader', name: 'READER', tasks: ['board.reading', 'board.writting'] })).toEqual(['task "board.writting" is not registered'])
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('★ names a task privilege this installation does not declare as a definition error', () => {
|
|
103
|
+
registerRoleTask({ id: 'board.exporting', grants: [{ category: 'board-export', axes: ['query'] }] })
|
|
104
|
+
|
|
105
|
+
expect(undeclaredTaskGrants(roleTaskById('board.exporting'))).toEqual(['board-export:query'])
|
|
106
|
+
expect(templateDefinitionErrors({ id: 'plant.reader', name: 'READER', tasks: ['board.exporting'] })).toEqual([
|
|
107
|
+
'task "board.exporting" names board-export:query, which this installation does not declare'
|
|
108
|
+
])
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it("keeps a template's own undeclared grants as before - skipped, not a definition error", () => {
|
|
112
|
+
const template = { id: 'plant.reader', name: 'READER', grants: [{ category: 'kpi', axes: ['query'] }] }
|
|
113
|
+
|
|
114
|
+
expect(templateDefinitionErrors(template)).toEqual([])
|
|
115
|
+
expect(unknownTemplateGrants(template)).toEqual(['kpi:query'])
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
describe('a role laid against the tasks', () => {
|
|
120
|
+
beforeEach(() => {
|
|
121
|
+
registerRoleTask({ id: 'board.reading', grants: [{ category: 'board', axes: ['query'] }] })
|
|
122
|
+
registerRoleTask({ id: 'board.keeping', grants: [{ category: 'board', axes: ['query', 'mutation'] }] })
|
|
123
|
+
registerRoleTask({ id: 'order.reading', grants: [{ category: 'order', axes: ['query'] }, { category: 'board', axes: ['query'] }] })
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const statuses = (coverage: any) => Object.fromEntries(coverage.tasks.map((task: any) => [task.taskId, task.status]))
|
|
127
|
+
|
|
128
|
+
it('★ says all, some and none by what the role holds of each task', () => {
|
|
129
|
+
const coverage = taskCoverageOf(held('board:query'))
|
|
130
|
+
|
|
131
|
+
expect(statuses(coverage)).toEqual({ 'board.reading': 'all', 'board.keeping': 'some', 'order.reading': 'some' })
|
|
132
|
+
expect(coverage.tasks.find((task: any) => task.taskId === 'board.keeping').missing).toEqual([{ category: 'board', axes: ['mutation'] }])
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('★ a shared privilege alone makes every task that names it "some" - reported, not supplied', () => {
|
|
136
|
+
const coverage = taskCoverageOf(held('board:query'))
|
|
137
|
+
|
|
138
|
+
expect(coverage.tasks.find((task: any) => task.taskId === 'order.reading')).toMatchObject({
|
|
139
|
+
status: 'some',
|
|
140
|
+
held: [{ category: 'board', axes: ['query'] }],
|
|
141
|
+
missing: [{ category: 'order', axes: ['query'] }]
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('says none for a role that holds nothing of a task', () => {
|
|
146
|
+
expect(statuses(taskCoverageOf(held('worklist:query')))).toEqual({ 'board.reading': 'none', 'board.keeping': 'none', 'order.reading': 'none' })
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('★ keeps what no task names apart - and leaves out what nothing declares any more', () => {
|
|
150
|
+
const coverage = taskCoverageOf(held('board:query', 'worklist:query', 'worklist:mutation', 'retired:query'))
|
|
151
|
+
|
|
152
|
+
expect(coverage.unclassified).toEqual([{ category: 'worklist', axes: ['mutation', 'query'] }])
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it('★ says broken for a task naming an undeclared privilege, whatever the role holds', () => {
|
|
156
|
+
registerRoleTask({ id: 'board.exporting', grants: [{ category: 'board', axes: ['query'] }, { category: 'board-export', axes: ['query'] }] })
|
|
157
|
+
|
|
158
|
+
const task = taskCoverageOf(held('board:query')).tasks.find((one: any) => one.taskId === 'board.exporting')
|
|
159
|
+
expect(task).toMatchObject({ status: 'broken', module: 'board', undeclared: [{ category: 'board-export', axes: ['query'] }] })
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('merges grants by category in the order first written', () => {
|
|
163
|
+
expect(mergeGrants([[{ category: 'b', axes: ['x'] }], [{ category: 'a', axes: ['y'] }, { category: 'b', axes: ['z', 'x'] }]])).toEqual([
|
|
164
|
+
{ category: 'b', axes: ['x', 'z'] },
|
|
165
|
+
{ category: 'a', axes: ['y'] }
|
|
166
|
+
])
|
|
167
|
+
})
|
|
168
|
+
})
|
|
@@ -16,9 +16,11 @@ const { User } = loadCompiled('service/user/user')
|
|
|
16
16
|
const { RoleTemplateMutation } = loadCompiled('service/role-template/role-template-mutation')
|
|
17
17
|
const { RoleTemplateGapResolver } = loadCompiled('service/role-template/role-template-gap-resolver')
|
|
18
18
|
const { registerRoleTemplate } = loadCompiled('service/role-template/role-template')
|
|
19
|
+
const { registerRoleTask } = loadCompiled('service/role-template/role-task')
|
|
19
20
|
|
|
20
21
|
const mutation = new RoleTemplateMutation()
|
|
21
|
-
const gapOf = (role: any) => new RoleTemplateGapResolver().templateGap(role)
|
|
22
|
+
const gapOf = (role: any, templateId?: string) => new RoleTemplateGapResolver().templateGap(role, templateId)
|
|
23
|
+
const coverageOf = (role: any) => new RoleTemplateGapResolver().taskCoverage(role)
|
|
22
24
|
|
|
23
25
|
let domain: any
|
|
24
26
|
let actor: any
|
|
@@ -71,7 +73,9 @@ describe('the gap between a role and its template', () => {
|
|
|
71
73
|
templateId: 'plant.qi',
|
|
72
74
|
templateName: 'QUALITY-INSPECTOR',
|
|
73
75
|
missing: [],
|
|
74
|
-
missingCount: 0
|
|
76
|
+
missingCount: 0,
|
|
77
|
+
extra: [],
|
|
78
|
+
extraCount: 0
|
|
75
79
|
})
|
|
76
80
|
})
|
|
77
81
|
|
|
@@ -120,6 +124,77 @@ describe('the gap between a role and its template', () => {
|
|
|
120
124
|
]
|
|
121
125
|
await getRepository(Role).save(stored)
|
|
122
126
|
|
|
127
|
+
const gap = await gapOf(role)
|
|
128
|
+
expect(gap.missingCount).toBe(0)
|
|
129
|
+
/* Shown as wider than the template - not a fault, and nothing takes it away. */
|
|
130
|
+
expect(gap.extra).toEqual([{ category: 'board', axes: ['mutation'] }])
|
|
131
|
+
expect(gap.extraCount).toBe(1)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it('★ lays a role against a template the administrator picks, whatever the role is called', async () => {
|
|
135
|
+
declareTemplate(['query', 'mutation'])
|
|
136
|
+
const role = await getRepository(Role).save({ domain, name: '품질검사', privileges: [await getRepository(Privilege).findOneBy({ category: 'board', name: 'query' })] })
|
|
137
|
+
|
|
138
|
+
expect(await gapOf(role)).toBeNull()
|
|
139
|
+
expect(await gapOf(role, 'plant.qi')).toMatchObject({ templateId: 'plant.qi', missing: [{ category: 'board', axes: ['mutation'] }], extraCount: 0 })
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('refuses a template id that does not exist rather than answering null', async () => {
|
|
143
|
+
declareTemplate(['query'])
|
|
144
|
+
const role = await mutation.createRoleFromTemplate('plant.qi', undefined, context())
|
|
145
|
+
|
|
146
|
+
await expect(gapOf(role, 'plant.nobody')).rejects.toThrow(/no role template "plant.nobody"/)
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
describe('a template built from tasks (ADR-0139 decision 11)', () => {
|
|
151
|
+
beforeEach(async () => {
|
|
152
|
+
;(process as any)['ROLE_TASKS'] = {}
|
|
153
|
+
;(process as any)['ROLE_TEMPLATES'] = {}
|
|
154
|
+
await getRepository(Privilege).save({ name: 'query', category: 'order' })
|
|
155
|
+
;(process as any).PRIVILEGES['order query'] = ['order', 'query']
|
|
156
|
+
registerRoleTask({ id: 'board.reading', grants: [{ category: 'board', axes: ['query'] }] })
|
|
157
|
+
registerRoleTask({ id: 'order.reading', grants: [{ category: 'order', axes: ['query'] }, { category: 'board', axes: ['query'] }] })
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('★ holds every privilege of every task once, plus its own grants', async () => {
|
|
161
|
+
registerRoleTemplate({ id: 'plant.reader', name: 'READER', tasks: ['board.reading', 'order.reading'], grants: [{ category: 'board', axes: ['mutation'] }] })
|
|
162
|
+
const role = await mutation.createRoleFromTemplate('plant.reader', undefined, context())
|
|
163
|
+
|
|
164
|
+
const held = (await getRepository(Role).findOne({ where: { id: role.id }, relations: ['privileges'] })).privileges.map((p: any) => `${p.category}:${p.name}`).sort()
|
|
165
|
+
expect(held).toEqual(['board:mutation', 'board:query', 'order:query'])
|
|
123
166
|
expect((await gapOf(role)).missingCount).toBe(0)
|
|
124
167
|
})
|
|
168
|
+
|
|
169
|
+
it('★ is refused whole when a task is not registered - no role is made, no privilege added', async () => {
|
|
170
|
+
registerRoleTemplate({ id: 'plant.reader', name: 'READER', tasks: ['board.reading', 'board.writting'] })
|
|
171
|
+
|
|
172
|
+
await expect(mutation.createRoleFromTemplate('plant.reader', undefined, context())).rejects.toThrow(/task "board.writting" is not registered/)
|
|
173
|
+
expect(await getRepository(Role).findOneBy({ name: 'READER' })).toBeNull()
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('★ is refused whole when a task names a privilege this installation does not declare', async () => {
|
|
177
|
+
registerRoleTask({ id: 'board.exporting', grants: [{ category: 'board-export', axes: ['query'] }] })
|
|
178
|
+
registerRoleTemplate({ id: 'plant.reader', name: 'READER', tasks: ['board.reading', 'board.exporting'] })
|
|
179
|
+
const standing = await getRepository(Role).save({ domain, name: 'READER', privileges: [] })
|
|
180
|
+
|
|
181
|
+
await expect(mutation.createRoleFromTemplate('plant.reader', undefined, context())).rejects.toThrow(/board-export:query/)
|
|
182
|
+
expect((await getRepository(Role).findOne({ where: { id: standing.id }, relations: ['privileges'] })).privileges).toEqual([])
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('★ the role screen sees a role by task: all, some, none, and what no task names', async () => {
|
|
186
|
+
const role = await getRepository(Role).save({
|
|
187
|
+
domain,
|
|
188
|
+
name: '판독',
|
|
189
|
+
privileges: [await getRepository(Privilege).findOneBy({ category: 'board', name: 'query' }), await getRepository(Privilege).findOneBy({ category: 'board', name: 'mutation' })]
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
const coverage = await coverageOf(role)
|
|
193
|
+
expect(coverage.tasks.map((task: any) => [task.taskId, task.status])).toEqual([
|
|
194
|
+
['board.reading', 'all'],
|
|
195
|
+
['order.reading', 'some']
|
|
196
|
+
])
|
|
197
|
+
expect(coverage.tasks[1].missing).toEqual([{ category: 'order', axes: ['query'] }])
|
|
198
|
+
expect(coverage.unclassified).toEqual([{ category: 'board', axes: ['mutation'] }])
|
|
199
|
+
})
|
|
125
200
|
})
|
package/translations/en.json
CHANGED
|
@@ -251,5 +251,17 @@
|
|
|
251
251
|
"access-request.notify.denied.body": "{privilege}: {reason}",
|
|
252
252
|
"error.access-request-needs-reason": "write why you need it.",
|
|
253
253
|
"error.access-request-same-reason-as-denied": "this was denied lately for the same reason ({reason}). write what has changed.",
|
|
254
|
-
"error.role-belongs-to-parent": "{roles}: a role of the parent domain. only someone who decides roles there can give or take it."
|
|
254
|
+
"error.role-belongs-to-parent": "{roles}: a role of the parent domain. only someone who decides roles there can give or take it.",
|
|
255
|
+
"task.auth-base.users-and-roles.name": "Keeping accounts and roles",
|
|
256
|
+
"task.auth-base.users-and-roles.description": "Reads and changes users, roles and who holds them, invitations, access requests, applications, devices and sign-in providers. Whoever holds this can give any role, to themselves as well.",
|
|
257
|
+
"task.auth-base.privilege-reading.name": "Reading the privilege list",
|
|
258
|
+
"task.auth-base.privilege-reading.description": "Reads the privileges roles are made of.",
|
|
259
|
+
"task.auth-base.security.name": "Keeping security settings",
|
|
260
|
+
"task.auth-base.security.description": "Reads and changes the domain's protected addresses and sign-in rules.",
|
|
261
|
+
"task.auth-base.env-vars.name": "Keeping environment variables",
|
|
262
|
+
"task.auth-base.env-vars.description": "Reads and changes the domain's environment variables.",
|
|
263
|
+
"privilege.category.audit": "audit log",
|
|
264
|
+
"privilege.allows.audit.query": "see everyone’s sign-ins, privilege use and refusals, and role changes",
|
|
265
|
+
"task.auth-base.audit-reading.name": "Reading the audit log",
|
|
266
|
+
"task.auth-base.audit-reading.description": "Reads everyone's sign-ins, privilege use and refusals, and role changes in the domain."
|
|
255
267
|
}
|
package/translations/es.json
CHANGED
|
@@ -251,5 +251,17 @@
|
|
|
251
251
|
"access-request.notify.denied.body": "{privilege}: {reason}",
|
|
252
252
|
"error.access-request-needs-reason": "indique por qué lo necesita.",
|
|
253
253
|
"error.access-request-same-reason-as-denied": "se rechazó hace poco por el mismo motivo ({reason}). indique qué ha cambiado.",
|
|
254
|
-
"error.role-belongs-to-parent": "{roles}: un rol del dominio principal. solo quien decide los roles allí puede concederlo o quitarlo."
|
|
254
|
+
"error.role-belongs-to-parent": "{roles}: un rol del dominio principal. solo quien decide los roles allí puede concederlo o quitarlo.",
|
|
255
|
+
"task.auth-base.users-and-roles.name": "Mantener cuentas y roles",
|
|
256
|
+
"task.auth-base.users-and-roles.description": "Lee y modifica usuarios, roles y quién los tiene, invitaciones, solicitudes de acceso, aplicaciones, dispositivos y proveedores de acceso. Quien lo tiene puede dar cualquier rol, también a sí mismo.",
|
|
257
|
+
"task.auth-base.privilege-reading.name": "Leer la lista de privilegios",
|
|
258
|
+
"task.auth-base.privilege-reading.description": "Lee los privilegios de los que se componen los roles.",
|
|
259
|
+
"task.auth-base.security.name": "Mantener la seguridad",
|
|
260
|
+
"task.auth-base.security.description": "Lee y modifica las direcciones protegidas y las reglas de acceso del dominio.",
|
|
261
|
+
"task.auth-base.env-vars.name": "Mantener variables de entorno",
|
|
262
|
+
"task.auth-base.env-vars.description": "Lee y modifica las variables de entorno del dominio.",
|
|
263
|
+
"privilege.category.audit": "registro de auditoría",
|
|
264
|
+
"privilege.allows.audit.query": "ver los inicios de sesión, el uso y rechazo de privilegios y los cambios de rol de todos",
|
|
265
|
+
"task.auth-base.audit-reading.name": "Consultar el registro de auditoría",
|
|
266
|
+
"task.auth-base.audit-reading.description": "Lee los inicios de sesión, el uso y rechazo de privilegios y los cambios de rol de todos en el dominio."
|
|
255
267
|
}
|
package/translations/ja.json
CHANGED
|
@@ -251,5 +251,17 @@
|
|
|
251
251
|
"access-request.notify.denied.body": "{privilege}: {reason}",
|
|
252
252
|
"error.access-request-needs-reason": "必要な理由を書いてください。",
|
|
253
253
|
"error.access-request-same-reason-as-denied": "同じ理由で最近拒否されました({reason})。何が変わったかを書いてください。",
|
|
254
|
-
"error.role-belongs-to-parent": "{roles}: 上位$t(term.domain)のロールです。その$t(term.domain)で権限を決める人だけが付与・解除できます。"
|
|
254
|
+
"error.role-belongs-to-parent": "{roles}: 上位$t(term.domain)のロールです。その$t(term.domain)で権限を決める人だけが付与・解除できます。",
|
|
255
|
+
"task.auth-base.users-and-roles.name": "アカウント・ロールの管理",
|
|
256
|
+
"task.auth-base.users-and-roles.description": "ユーザー・ロールとその付与・招待・アクセス申請・アプリ・機器・ログイン提供者を読み、変更する。自分にもどのロールでも付与できる。",
|
|
257
|
+
"task.auth-base.privilege-reading.name": "権限一覧の閲覧",
|
|
258
|
+
"task.auth-base.privilege-reading.description": "ロールを構成する権限の一覧を読む。",
|
|
259
|
+
"task.auth-base.security.name": "セキュリティ設定",
|
|
260
|
+
"task.auth-base.security.description": "ドメインの保護アドレスとログイン規則を読み、変更する。",
|
|
261
|
+
"task.auth-base.env-vars.name": "環境変数",
|
|
262
|
+
"task.auth-base.env-vars.description": "ドメインの環境変数を読み、変更する。",
|
|
263
|
+
"privilege.category.audit": "監査ログ",
|
|
264
|
+
"privilege.allows.audit.query": "全ユーザーのログイン、権限の使用と拒否、ロール変更の記録を見ることができます。",
|
|
265
|
+
"task.auth-base.audit-reading.name": "監査ログの閲覧",
|
|
266
|
+
"task.auth-base.audit-reading.description": "全ユーザーのログイン、権限の使用と拒否、ロール変更の記録を読む。"
|
|
255
267
|
}
|
package/translations/ko.json
CHANGED
|
@@ -251,5 +251,17 @@
|
|
|
251
251
|
"access-request.notify.denied.body": "{privilege}: {reason}",
|
|
252
252
|
"error.access-request-needs-reason": "필요한 사유를 입력해 주세요.",
|
|
253
253
|
"error.access-request-same-reason-as-denied": "동일한 사유로 최근에 거부된 요청입니다({reason}). 다시 요청하려면 변경된 사항을 입력해 주세요.",
|
|
254
|
-
"error.role-belongs-to-parent": "{roles}: 상위 $t(term.domain)의 역할입니다. 그 $t(term.domain)에서 권한을 정하는 사람만 주거나 뺄 수 있습니다."
|
|
254
|
+
"error.role-belongs-to-parent": "{roles}: 상위 $t(term.domain)의 역할입니다. 그 $t(term.domain)에서 권한을 정하는 사람만 주거나 뺄 수 있습니다.",
|
|
255
|
+
"task.auth-base.users-and-roles.name": "계정·역할 관리",
|
|
256
|
+
"task.auth-base.users-and-roles.description": "사용자·역할과 역할 부여·초대·접근 요청·앱·기기·로그인 제공자를 읽고 바꾼다. 자기에게도 어떤 역할이든 줄 수 있다.",
|
|
257
|
+
"task.auth-base.privilege-reading.name": "권한 목록 열람",
|
|
258
|
+
"task.auth-base.privilege-reading.description": "역할을 이루는 권한 목록을 읽는다.",
|
|
259
|
+
"task.auth-base.security.name": "보안 설정",
|
|
260
|
+
"task.auth-base.security.description": "도메인의 보호 주소와 로그인 규칙을 읽고 바꾼다.",
|
|
261
|
+
"task.auth-base.env-vars.name": "환경 변수",
|
|
262
|
+
"task.auth-base.env-vars.description": "도메인의 환경 변수를 읽고 바꾼다.",
|
|
263
|
+
"privilege.category.audit": "감사 기록",
|
|
264
|
+
"privilege.allows.audit.query": "모든 사용자의 로그인, 권한 사용과 거절, 역할 변경 기록을 볼 수 있습니다.",
|
|
265
|
+
"task.auth-base.audit-reading.name": "감사 기록 열람",
|
|
266
|
+
"task.auth-base.audit-reading.description": "모든 사용자의 로그인, 권한 사용과 거절, 역할 변경 기록을 읽는다."
|
|
255
267
|
}
|
package/translations/ms.json
CHANGED
|
@@ -251,5 +251,17 @@
|
|
|
251
251
|
"access-request.notify.denied.body": "{privilege}: {reason}",
|
|
252
252
|
"error.access-request-needs-reason": "tulis sebab anda memerlukannya.",
|
|
253
253
|
"error.access-request-same-reason-as-denied": "ini ditolak baru-baru ini atas sebab yang sama ({reason}). tulis apa yang telah berubah.",
|
|
254
|
-
"error.role-belongs-to-parent": "{roles}: peranan $t(term.domain) induk. hanya mereka yang memutuskan peranan di sana boleh memberi atau menariknya."
|
|
254
|
+
"error.role-belongs-to-parent": "{roles}: peranan $t(term.domain) induk. hanya mereka yang memutuskan peranan di sana boleh memberi atau menariknya.",
|
|
255
|
+
"task.auth-base.users-and-roles.name": "Menyelenggara akaun dan peranan",
|
|
256
|
+
"task.auth-base.users-and-roles.description": "Membaca dan mengubah pengguna, peranan dan pemegangnya, jemputan, permintaan akses, aplikasi, peranti dan penyedia log masuk. Pemegangnya boleh memberi apa-apa peranan, termasuk kepada diri sendiri.",
|
|
257
|
+
"task.auth-base.privilege-reading.name": "Membaca senarai keistimewaan",
|
|
258
|
+
"task.auth-base.privilege-reading.description": "Membaca keistimewaan yang membentuk peranan.",
|
|
259
|
+
"task.auth-base.security.name": "Menyelenggara tetapan keselamatan",
|
|
260
|
+
"task.auth-base.security.description": "Membaca dan mengubah alamat dilindungi dan peraturan log masuk domain.",
|
|
261
|
+
"task.auth-base.env-vars.name": "Menyelenggara pemboleh ubah persekitaran",
|
|
262
|
+
"task.auth-base.env-vars.description": "Membaca dan mengubah pemboleh ubah persekitaran domain.",
|
|
263
|
+
"privilege.category.audit": "log audit",
|
|
264
|
+
"privilege.allows.audit.query": "boleh melihat log masuk, penggunaan dan penolakan keistimewaan, serta perubahan peranan semua orang.",
|
|
265
|
+
"task.auth-base.audit-reading.name": "Membaca log audit",
|
|
266
|
+
"task.auth-base.audit-reading.description": "Membaca log masuk, penggunaan dan penolakan keistimewaan, serta perubahan peranan semua orang dalam domain."
|
|
255
267
|
}
|
package/translations/zh.json
CHANGED
|
@@ -251,5 +251,17 @@
|
|
|
251
251
|
"access-request.notify.denied.body": "{privilege}: {reason}",
|
|
252
252
|
"error.access-request-needs-reason": "请填写需要的理由。",
|
|
253
253
|
"error.access-request-same-reason-as-denied": "最近以相同理由被拒绝({reason})。请写明有何变化。",
|
|
254
|
-
"error.role-belongs-to-parent": "{roles}: 上级$t(term.domain)的角色。只有在该$t(term.domain)负责权限的人才能授予或移除。"
|
|
254
|
+
"error.role-belongs-to-parent": "{roles}: 上级$t(term.domain)的角色。只有在该$t(term.domain)负责权限的人才能授予或移除。",
|
|
255
|
+
"task.auth-base.users-and-roles.name": "管理账户与角色",
|
|
256
|
+
"task.auth-base.users-and-roles.description": "读取并修改用户、角色及其授予、邀请、访问申请、应用、设备和登录提供方。持有者可以给任何人(包括自己)任何角色。",
|
|
257
|
+
"task.auth-base.privilege-reading.name": "查看权限列表",
|
|
258
|
+
"task.auth-base.privilege-reading.description": "读取构成角色的权限列表。",
|
|
259
|
+
"task.auth-base.security.name": "安全设置",
|
|
260
|
+
"task.auth-base.security.description": "读取并修改域的受保护地址和登录规则。",
|
|
261
|
+
"task.auth-base.env-vars.name": "环境变量",
|
|
262
|
+
"task.auth-base.env-vars.description": "读取并修改域的环境变量。",
|
|
263
|
+
"privilege.category.audit": "审计日志",
|
|
264
|
+
"privilege.allows.audit.query": "可以查看所有用户的登录、权限使用与拒绝以及角色变更记录。",
|
|
265
|
+
"task.auth-base.audit-reading.name": "查看审计日志",
|
|
266
|
+
"task.auth-base.audit-reading.description": "读取所有用户的登录、权限使用与拒绝以及角色变更记录。"
|
|
255
267
|
}
|