@things-factory/auth-ui 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/{entries/auth/activate-page.test.js → activate-page.test.js} +4 -1
- package/dist-client/activate-page.test.js.map +1 -0
- package/dist-client/bootstrap.js +4 -1
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/components/my-login-history.js +14 -10
- package/dist-client/components/my-login-history.js.map +1 -1
- package/dist-client/components/role-template-picker.d.ts +5 -0
- package/dist-client/components/role-template-picker.js +41 -5
- package/dist-client/components/role-template-picker.js.map +1 -1
- package/dist-client/components/user-status-renderer.d.ts +9 -0
- package/dist-client/components/user-status-renderer.js +36 -0
- package/dist-client/components/user-status-renderer.js.map +1 -0
- package/dist-client/entity360/person-360.d.ts +13 -0
- package/dist-client/entity360/person-360.js +96 -0
- package/dist-client/entity360/person-360.js.map +1 -1
- package/dist-client/entries-hold-only-pages.test.d.ts +1 -0
- package/dist-client/entries-hold-only-pages.test.js +25 -0
- package/dist-client/entries-hold-only-pages.test.js.map +1 -0
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +14 -1
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/audit/audit-page.d.ts +46 -0
- package/dist-client/pages/audit/audit-page.js +417 -0
- package/dist-client/pages/audit/audit-page.js.map +1 -0
- package/dist-client/pages/role/role-privilege-page.d.ts +38 -0
- package/dist-client/pages/role/role-privilege-page.js +441 -5
- package/dist-client/pages/role/role-privilege-page.js.map +1 -1
- package/dist-client/pages/role/role-task-review.test.d.ts +1 -0
- package/dist-client/pages/role/role-task-review.test.js +49 -0
- package/dist-client/pages/role/role-task-review.test.js.map +1 -0
- package/dist-client/pages/user/user-list-page.js +1 -31
- package/dist-client/pages/user/user-list-page.js.map +1 -1
- package/dist-client/route.js +3 -0
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/audit-words.d.ts +30 -0
- package/dist-client/utils/audit-words.js +57 -0
- package/dist-client/utils/audit-words.js.map +1 -0
- package/dist-client/utils/audit-words.test.d.ts +1 -0
- package/dist-client/utils/audit-words.test.js +47 -0
- package/dist-client/utils/audit-words.test.js.map +1 -0
- package/package.json +4 -4
- package/things-factory.config.js +1 -0
- package/translations/en.json +68 -1
- package/translations/es.json +68 -1
- package/translations/ja.json +68 -1
- package/translations/ko.json +68 -1
- package/translations/ms.json +68 -1
- package/translations/zh.json +68 -1
- package/dist-client/entries/auth/activate-page.test.js.map +0 -1
- /package/dist-client/{entries/auth/activate-page.test.d.ts → activate-page.test.d.ts} +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the audit screen says what an audit row holds (ADR-0141 §6). The rows hold codes; the screen
|
|
3
|
+
* shows words. Pure, so the words are tested without a screen.
|
|
4
|
+
*/
|
|
5
|
+
type Translate = (key: string, options?: Record<string, unknown>) => string;
|
|
6
|
+
export interface AuditActionRow {
|
|
7
|
+
kind: string;
|
|
8
|
+
door?: string | null;
|
|
9
|
+
decision?: string | null;
|
|
10
|
+
outcome?: string | null;
|
|
11
|
+
code?: string | null;
|
|
12
|
+
count?: number | null;
|
|
13
|
+
objectId?: string | null;
|
|
14
|
+
detail?: Record<string, unknown> | null;
|
|
15
|
+
}
|
|
16
|
+
/** The door in words: the category's name and the declared axis - `payroll:query` → 「급여 query」. */
|
|
17
|
+
export declare function doorWords(t: Translate, door?: string | null): string;
|
|
18
|
+
/** One action in words, with how many times when more than once. */
|
|
19
|
+
export declare function actionWords(t: Translate, action: AuditActionRow): string;
|
|
20
|
+
/**
|
|
21
|
+
* A request's actions in one line - refusals and errors first, then events, then the doors passed.
|
|
22
|
+
* A door passed and its result say the same thing twice, so only an error result is shown.
|
|
23
|
+
*/
|
|
24
|
+
export declare function recordWords(t: Translate, actions: AuditActionRow[]): string;
|
|
25
|
+
/** The last `days` days up to `now`. */
|
|
26
|
+
export declare function lastDays(days: number, now?: Date): {
|
|
27
|
+
from: Date;
|
|
28
|
+
to: Date;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the audit screen says what an audit row holds (ADR-0141 §6). The rows hold codes; the screen
|
|
3
|
+
* shows words. Pure, so the words are tested without a screen.
|
|
4
|
+
*/
|
|
5
|
+
/** The door in words: the category's name and the declared axis - `payroll:query` → 「급여 query」. */
|
|
6
|
+
export function doorWords(t, door) {
|
|
7
|
+
if (!door)
|
|
8
|
+
return '';
|
|
9
|
+
if (!door.includes(':')) {
|
|
10
|
+
return door
|
|
11
|
+
.split('+')
|
|
12
|
+
.map(part => t(`audit.door.${part}`, { defaultValue: part }))
|
|
13
|
+
.join(' · ');
|
|
14
|
+
}
|
|
15
|
+
const [category, privilege] = door.split(':');
|
|
16
|
+
return `${t(`privilege.category.${category}`, { defaultValue: category })} ${privilege}`;
|
|
17
|
+
}
|
|
18
|
+
function statusWords(t, status) {
|
|
19
|
+
return t(`label.${status}-user`, { defaultValue: String(status ?? '') });
|
|
20
|
+
}
|
|
21
|
+
/** One action in words, with how many times when more than once. */
|
|
22
|
+
export function actionWords(t, action) {
|
|
23
|
+
const times = (action.count ?? 1) > 1 ? ` ×${action.count}` : '';
|
|
24
|
+
if (action.kind === 'door.check') {
|
|
25
|
+
const refused = action.decision === 'denied' ? ` ${t('audit.outcome.denied')}` : '';
|
|
26
|
+
return `${doorWords(t, action.door)}${refused}${times}`;
|
|
27
|
+
}
|
|
28
|
+
if (action.kind === 'door.result') {
|
|
29
|
+
return action.outcome === 'error' ? `${doorWords(t, action.door)} ${t('audit.outcome.error')}${times}` : '';
|
|
30
|
+
}
|
|
31
|
+
const kind = t(`audit.kind.${action.kind}`, { defaultValue: action.kind });
|
|
32
|
+
const failed = action.outcome === 'error' ? ` ${t('audit.outcome.failed')}` : '';
|
|
33
|
+
const change = action.kind === 'user.status' && action.detail
|
|
34
|
+
? ` ${statusWords(t, action.detail.from)} → ${statusWords(t, action.detail.to)}`
|
|
35
|
+
: '';
|
|
36
|
+
return `${kind}${change}${failed}${times}`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A request's actions in one line - refusals and errors first, then events, then the doors passed.
|
|
40
|
+
* A door passed and its result say the same thing twice, so only an error result is shown.
|
|
41
|
+
*/
|
|
42
|
+
export function recordWords(t, actions) {
|
|
43
|
+
const weight = (action) => action.decision === 'denied' || action.outcome === 'error' ? 0 : action.kind.startsWith('door.') ? 2 : 1;
|
|
44
|
+
return [...actions]
|
|
45
|
+
.sort((a, b) => weight(a) - weight(b))
|
|
46
|
+
.map(action => actionWords(t, action))
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.join(', ');
|
|
49
|
+
}
|
|
50
|
+
/** The last `days` days up to `now`. */
|
|
51
|
+
export function lastDays(days, now = new Date()) {
|
|
52
|
+
const from = new Date(now);
|
|
53
|
+
from.setHours(0, 0, 0, 0);
|
|
54
|
+
from.setDate(from.getDate() - (days - 1));
|
|
55
|
+
return { from, to: now };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=audit-words.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-words.js","sourceRoot":"","sources":["../../client/utils/audit-words.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * How the audit screen says what an audit row holds (ADR-0141 §6). The rows hold codes; the screen\n * shows words. Pure, so the words are tested without a screen.\n */\n\ntype Translate = (key: string, options?: Record<string, unknown>) => string\n\nexport interface AuditActionRow {\n kind: string\n door?: string | null\n decision?: string | null\n outcome?: string | null\n code?: string | null\n count?: number | null\n objectId?: string | null\n detail?: Record<string, unknown> | null\n}\n\n/** The door in words: the category's name and the declared axis - `payroll:query` → 「급여 query」. */\nexport function doorWords(t: Translate, door?: string | null): string {\n if (!door) return ''\n if (!door.includes(':')) {\n return door\n .split('+')\n .map(part => t(`audit.door.${part}`, { defaultValue: part }))\n .join(' · ')\n }\n const [category, privilege] = door.split(':')\n return `${t(`privilege.category.${category}`, { defaultValue: category })} ${privilege}`\n}\n\nfunction statusWords(t: Translate, status: unknown) {\n return t(`label.${status}-user`, { defaultValue: String(status ?? '') })\n}\n\n/** One action in words, with how many times when more than once. */\nexport function actionWords(t: Translate, action: AuditActionRow): string {\n const times = (action.count ?? 1) > 1 ? ` ×${action.count}` : ''\n\n if (action.kind === 'door.check') {\n const refused = action.decision === 'denied' ? ` ${t('audit.outcome.denied')}` : ''\n return `${doorWords(t, action.door)}${refused}${times}`\n }\n if (action.kind === 'door.result') {\n return action.outcome === 'error' ? `${doorWords(t, action.door)} ${t('audit.outcome.error')}${times}` : ''\n }\n\n const kind = t(`audit.kind.${action.kind}`, { defaultValue: action.kind })\n const failed = action.outcome === 'error' ? ` ${t('audit.outcome.failed')}` : ''\n const change =\n action.kind === 'user.status' && action.detail\n ? ` ${statusWords(t, action.detail.from)} → ${statusWords(t, action.detail.to)}`\n : ''\n return `${kind}${change}${failed}${times}`\n}\n\n/**\n * A request's actions in one line - refusals and errors first, then events, then the doors passed.\n * A door passed and its result say the same thing twice, so only an error result is shown.\n */\nexport function recordWords(t: Translate, actions: AuditActionRow[]): string {\n const weight = (action: AuditActionRow) =>\n action.decision === 'denied' || action.outcome === 'error' ? 0 : action.kind.startsWith('door.') ? 2 : 1\n return [...actions]\n .sort((a, b) => weight(a) - weight(b))\n .map(action => actionWords(t, action))\n .filter(Boolean)\n .join(', ')\n}\n\n/** The last `days` days up to `now`. */\nexport function lastDays(days: number, now = new Date()): { from: Date; to: Date } {\n const from = new Date(now)\n from.setHours(0, 0, 0, 0)\n from.setDate(from.getDate() - (days - 1))\n return { from, to: now }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { actionWords, doorWords, lastDays, recordWords } from './audit-words';
|
|
2
|
+
const WORDS = {
|
|
3
|
+
'privilege.category.payroll': '급여',
|
|
4
|
+
'audit.door.super': '시스템 소유자',
|
|
5
|
+
'audit.outcome.denied': '거절',
|
|
6
|
+
'audit.outcome.error': '오류',
|
|
7
|
+
'audit.outcome.failed': '실패',
|
|
8
|
+
'audit.kind.auth.signin': '로그인',
|
|
9
|
+
'audit.kind.role.grant': '역할 부여',
|
|
10
|
+
'audit.kind.user.status': '계정 상태',
|
|
11
|
+
'label.activated-user': '정상',
|
|
12
|
+
'label.locked-user': '잠김'
|
|
13
|
+
};
|
|
14
|
+
const t = (key, options) => WORDS[key] ?? options?.defaultValue ?? key;
|
|
15
|
+
describe('the audit screen says what a row holds', () => {
|
|
16
|
+
it('a door is its category in words and the declared axis', () => {
|
|
17
|
+
expect(doorWords(t, 'payroll:query')).toBe('급여 query');
|
|
18
|
+
expect(doorWords(t, 'super')).toBe('시스템 소유자');
|
|
19
|
+
expect(doorWords(t, 'unknown-category:query')).toBe('unknown-category query');
|
|
20
|
+
});
|
|
21
|
+
it('a refusal says so, with how many times', () => {
|
|
22
|
+
expect(actionWords(t, { kind: 'door.check', door: 'payroll:query', decision: 'denied', count: 3 })).toBe('급여 query 거절 ×3');
|
|
23
|
+
});
|
|
24
|
+
it('a result is shown only when it failed - passing already said it ran', () => {
|
|
25
|
+
expect(actionWords(t, { kind: 'door.result', door: 'payroll:query', outcome: 'ok' })).toBe('');
|
|
26
|
+
expect(actionWords(t, { kind: 'door.result', door: 'payroll:query', outcome: 'error' })).toBe('급여 query 오류');
|
|
27
|
+
});
|
|
28
|
+
it('an event in words, a status change with both states', () => {
|
|
29
|
+
expect(actionWords(t, { kind: 'auth.signin', outcome: 'error', code: 'user not found' })).toBe('로그인 실패');
|
|
30
|
+
expect(actionWords(t, { kind: 'user.status', detail: { from: 'activated', to: 'locked' } })).toBe('계정 상태 정상 → 잠김');
|
|
31
|
+
});
|
|
32
|
+
it('a request reads refusals first, then events, then doors passed', () => {
|
|
33
|
+
expect(recordWords(t, [
|
|
34
|
+
{ kind: 'door.check', door: 'payroll:query', decision: 'granted' },
|
|
35
|
+
{ kind: 'door.result', door: 'payroll:query', outcome: 'ok' },
|
|
36
|
+
{ kind: 'role.grant' },
|
|
37
|
+
{ kind: 'door.check', door: 'payroll:mutation', decision: 'denied' }
|
|
38
|
+
])).toBe('급여 mutation 거절, 역할 부여, 급여 query');
|
|
39
|
+
});
|
|
40
|
+
it('the last seven days start at midnight six days back', () => {
|
|
41
|
+
const now = new Date(2026, 9, 19, 15, 30);
|
|
42
|
+
const { from, to } = lastDays(7, now);
|
|
43
|
+
expect(from).toEqual(new Date(2026, 9, 13, 0, 0));
|
|
44
|
+
expect(to).toBe(now);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=audit-words.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-words.test.js","sourceRoot":"","sources":["../../client/utils/audit-words.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { actionWords, doorWords, lastDays, recordWords } from './audit-words'\n\nconst WORDS: Record<string, string> = {\n 'privilege.category.payroll': '급여',\n 'audit.door.super': '시스템 소유자',\n 'audit.outcome.denied': '거절',\n 'audit.outcome.error': '오류',\n 'audit.outcome.failed': '실패',\n 'audit.kind.auth.signin': '로그인',\n 'audit.kind.role.grant': '역할 부여',\n 'audit.kind.user.status': '계정 상태',\n 'label.activated-user': '정상',\n 'label.locked-user': '잠김'\n}\nconst t = (key: string, options?: any) => WORDS[key] ?? options?.defaultValue ?? key\n\ndescribe('the audit screen says what a row holds', () => {\n it('a door is its category in words and the declared axis', () => {\n expect(doorWords(t, 'payroll:query')).toBe('급여 query')\n expect(doorWords(t, 'super')).toBe('시스템 소유자')\n expect(doorWords(t, 'unknown-category:query')).toBe('unknown-category query')\n })\n\n it('a refusal says so, with how many times', () => {\n expect(actionWords(t, { kind: 'door.check', door: 'payroll:query', decision: 'denied', count: 3 })).toBe('급여 query 거절 ×3')\n })\n\n it('a result is shown only when it failed - passing already said it ran', () => {\n expect(actionWords(t, { kind: 'door.result', door: 'payroll:query', outcome: 'ok' })).toBe('')\n expect(actionWords(t, { kind: 'door.result', door: 'payroll:query', outcome: 'error' })).toBe('급여 query 오류')\n })\n\n it('an event in words, a status change with both states', () => {\n expect(actionWords(t, { kind: 'auth.signin', outcome: 'error', code: 'user not found' })).toBe('로그인 실패')\n expect(actionWords(t, { kind: 'user.status', detail: { from: 'activated', to: 'locked' } })).toBe('계정 상태 정상 → 잠김')\n })\n\n it('a request reads refusals first, then events, then doors passed', () => {\n expect(\n recordWords(t, [\n { kind: 'door.check', door: 'payroll:query', decision: 'granted' },\n { kind: 'door.result', door: 'payroll:query', outcome: 'ok' },\n { kind: 'role.grant' },\n { kind: 'door.check', door: 'payroll:mutation', decision: 'denied' }\n ])\n ).toBe('급여 mutation 거절, 역할 부여, 급여 query')\n })\n\n it('the last seven days start at midnight six days back', () => {\n const now = new Date(2026, 9, 19, 15, 30)\n const { from, to } = lastDays(7, now)\n expect(from).toEqual(new Date(2026, 9, 13, 0, 0))\n expect(to).toBe(now)\n })\n})\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/auth-ui",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.198",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"@operato/popup": "^10.29.39",
|
|
40
40
|
"@operato/shell": "^10.29.39",
|
|
41
41
|
"@operato/styles": "^10.0.0",
|
|
42
|
-
"@things-factory/auth-base": "^10.1.
|
|
43
|
-
"@things-factory/component-ui": "^10.1.
|
|
42
|
+
"@things-factory/auth-base": "^10.1.198",
|
|
43
|
+
"@things-factory/component-ui": "^10.1.198",
|
|
44
44
|
"@things-factory/more-base": "^10.1.188",
|
|
45
45
|
"base64url": "^3.0.1",
|
|
46
46
|
"clipboard": "^2.0.6"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "68f884a78ca3a779c2b057ba5b8f6e03f477d701"
|
|
49
49
|
}
|
package/things-factory.config.js
CHANGED
|
@@ -11,6 +11,7 @@ export default {
|
|
|
11
11
|
{ tagname: 'role-list-page', page: 'roles' },
|
|
12
12
|
{ tagname: 'role-privilege-page', page: 'role-privileges' },
|
|
13
13
|
{ tagname: 'user-list-page', page: 'users' },
|
|
14
|
+
{ tagname: 'audit-page', page: 'audit' },
|
|
14
15
|
{ tagname: 'invitations-page', page: 'invitations' },
|
|
15
16
|
{ tagname: 'partner-management', page: 'partners' },
|
|
16
17
|
{ tagname: 'domain-management', page: 'domains' },
|
package/translations/en.json
CHANGED
|
@@ -420,5 +420,72 @@
|
|
|
420
420
|
"access-request.dock.example today": "sort out today's access requests",
|
|
421
421
|
"access-request.dock.example smallest": "grant each with the smallest role that gives it",
|
|
422
422
|
"access-request.dock.example one person": "show what one person asked for and what each role would give",
|
|
423
|
-
"access-request.text.and more": "{list} and {count} more"
|
|
423
|
+
"access-request.text.and more": "{list} and {count} more",
|
|
424
|
+
"label.privileges view": "Privileges",
|
|
425
|
+
"label.tasks view": "Tasks",
|
|
426
|
+
"label.template view": "Against a template",
|
|
427
|
+
"text.counted from the saved privileges": "Counted from the saved privileges.",
|
|
428
|
+
"text.this role holds no task": "This role holds no privilege of any task.",
|
|
429
|
+
"label.tasks this role does not hold": "Tasks this role holds nothing of",
|
|
430
|
+
"button.unfold": "Show",
|
|
431
|
+
"button.fold": "Hide",
|
|
432
|
+
"label.privileges no task names": "Privileges no task names",
|
|
433
|
+
"text.task names an undeclared privilege": "Definition error",
|
|
434
|
+
"text.task held whole": "All",
|
|
435
|
+
"text.task held in part": "{held} of {total}",
|
|
436
|
+
"text.not held x": "Not held: {x}",
|
|
437
|
+
"text.no template to compare with": "There is no template to compare with, or reading them is not among your privileges.",
|
|
438
|
+
"text.pick a template to compare with": "Pick a template",
|
|
439
|
+
"text.template cannot be applied because": "This template cannot be applied: {list}.",
|
|
440
|
+
"text.template cannot be applied": "Cannot be applied",
|
|
441
|
+
"label.missing against the template": "Missing against the template",
|
|
442
|
+
"text.nothing missing against the template": "Nothing is missing.",
|
|
443
|
+
"label.wider than the template": "Wider than the template",
|
|
444
|
+
"audit.title": "Audit log",
|
|
445
|
+
"audit.view.people": "By person",
|
|
446
|
+
"audit.view.doors": "By privilege",
|
|
447
|
+
"audit.view.records": "Records",
|
|
448
|
+
"audit.period.days": "{count} days",
|
|
449
|
+
"audit.period.from": "From",
|
|
450
|
+
"audit.period.to": "To",
|
|
451
|
+
"audit.outcome.all": "All",
|
|
452
|
+
"audit.outcome.denied": "Refused",
|
|
453
|
+
"audit.outcome.error": "Error",
|
|
454
|
+
"audit.outcome.failed": "Failed",
|
|
455
|
+
"audit.button.all-people": "All people",
|
|
456
|
+
"audit.button.all-privileges": "All privileges",
|
|
457
|
+
"audit.health.failures": "{count} not recorded (since {since})",
|
|
458
|
+
"audit.health.unknown": "Unrecorded count unavailable",
|
|
459
|
+
"audit.field.last-checkin": "Last access",
|
|
460
|
+
"audit.field.checkins": "Accesses",
|
|
461
|
+
"audit.field.failed-signins": "Failed sign-ins",
|
|
462
|
+
"audit.field.granted": "Allowed",
|
|
463
|
+
"audit.field.denied": "Refused",
|
|
464
|
+
"audit.field.people": "People",
|
|
465
|
+
"audit.field.privilege": "Privilege",
|
|
466
|
+
"audit.field.time": "Time",
|
|
467
|
+
"audit.field.actor": "User",
|
|
468
|
+
"audit.field.actions": "Actions",
|
|
469
|
+
"audit.field.request": "Request",
|
|
470
|
+
"audit.field.address": "IP address",
|
|
471
|
+
"audit.field.duration": "ms",
|
|
472
|
+
"audit.door.owner": "domain owner",
|
|
473
|
+
"audit.door.super": "superuser",
|
|
474
|
+
"audit.kind.auth.signin": "Sign-in",
|
|
475
|
+
"audit.kind.auth.checkin": "Access",
|
|
476
|
+
"audit.kind.auth.signout": "Sign-out",
|
|
477
|
+
"audit.kind.password.change": "Password changed",
|
|
478
|
+
"audit.kind.password.reset-by-admin": "Password reset",
|
|
479
|
+
"audit.kind.credential.issue": "Credential reissued",
|
|
480
|
+
"audit.kind.webauthn.register": "Passkey registered",
|
|
481
|
+
"audit.kind.role.grant": "Role granted",
|
|
482
|
+
"audit.kind.role.revoke": "Role revoked",
|
|
483
|
+
"audit.kind.role.privilege.add": "Privilege added to role",
|
|
484
|
+
"audit.kind.role.privilege.remove": "Privilege removed from role",
|
|
485
|
+
"audit.kind.role.delete": "Role deleted",
|
|
486
|
+
"audit.kind.user.status": "Account status",
|
|
487
|
+
"audit.kind.domain.owner.add": "Domain owner added",
|
|
488
|
+
"audit.kind.domain.owner.remove": "Domain owner removed",
|
|
489
|
+
"audit.kind.invitation.create": "Invitation sent",
|
|
490
|
+
"audit.kind.invitation.status": "Invitation status"
|
|
424
491
|
}
|
package/translations/es.json
CHANGED
|
@@ -420,5 +420,72 @@
|
|
|
420
420
|
"access-request.dock.example today": "resolver las solicitudes de acceso de hoy",
|
|
421
421
|
"access-request.dock.example smallest": "conceder cada una con el rol más reducido que lo permita",
|
|
422
422
|
"access-request.dock.example one person": "mostrar lo que pidió una persona y lo que daría cada rol",
|
|
423
|
-
"access-request.text.and more": "{list} y {count} más"
|
|
423
|
+
"access-request.text.and more": "{list} y {count} más",
|
|
424
|
+
"label.privileges view": "Privilegios",
|
|
425
|
+
"label.tasks view": "Tareas",
|
|
426
|
+
"label.template view": "Frente a una plantilla",
|
|
427
|
+
"text.counted from the saved privileges": "Contado sobre los privilegios guardados.",
|
|
428
|
+
"text.this role holds no task": "Este rol no tiene ningún privilegio de ninguna tarea.",
|
|
429
|
+
"label.tasks this role does not hold": "Tareas de las que este rol no tiene nada",
|
|
430
|
+
"button.unfold": "Mostrar",
|
|
431
|
+
"button.fold": "Ocultar",
|
|
432
|
+
"label.privileges no task names": "Privilegios que ninguna tarea nombra",
|
|
433
|
+
"text.task names an undeclared privilege": "Error de definición",
|
|
434
|
+
"text.task held whole": "Todo",
|
|
435
|
+
"text.task held in part": "{held} de {total}",
|
|
436
|
+
"text.not held x": "No tiene: {x}",
|
|
437
|
+
"text.no template to compare with": "No hay plantilla con la que comparar, o no tiene privilegio para leerlas.",
|
|
438
|
+
"text.pick a template to compare with": "Elegir una plantilla",
|
|
439
|
+
"text.template cannot be applied because": "Esta plantilla no se puede aplicar: {list}.",
|
|
440
|
+
"text.template cannot be applied": "No aplicable",
|
|
441
|
+
"label.missing against the template": "Falta frente a la plantilla",
|
|
442
|
+
"text.nothing missing against the template": "No falta nada.",
|
|
443
|
+
"label.wider than the template": "Más amplio que la plantilla",
|
|
444
|
+
"audit.title": "Registro de auditoría",
|
|
445
|
+
"audit.view.people": "Por persona",
|
|
446
|
+
"audit.view.doors": "Por privilegio",
|
|
447
|
+
"audit.view.records": "Registros",
|
|
448
|
+
"audit.period.days": "{count} días",
|
|
449
|
+
"audit.period.from": "Desde",
|
|
450
|
+
"audit.period.to": "Hasta",
|
|
451
|
+
"audit.outcome.all": "Todo",
|
|
452
|
+
"audit.outcome.denied": "Rechazado",
|
|
453
|
+
"audit.outcome.error": "Error",
|
|
454
|
+
"audit.outcome.failed": "Fallido",
|
|
455
|
+
"audit.button.all-people": "Todas las personas",
|
|
456
|
+
"audit.button.all-privileges": "Todos los privilegios",
|
|
457
|
+
"audit.health.failures": "{count} sin registrar (desde {since})",
|
|
458
|
+
"audit.health.unknown": "No se pudo leer el número de fallos",
|
|
459
|
+
"audit.field.last-checkin": "Último acceso",
|
|
460
|
+
"audit.field.checkins": "Accesos",
|
|
461
|
+
"audit.field.failed-signins": "Inicios fallidos",
|
|
462
|
+
"audit.field.granted": "Permitidos",
|
|
463
|
+
"audit.field.denied": "Rechazados",
|
|
464
|
+
"audit.field.people": "Personas",
|
|
465
|
+
"audit.field.privilege": "Privilegio",
|
|
466
|
+
"audit.field.time": "Hora",
|
|
467
|
+
"audit.field.actor": "Usuario",
|
|
468
|
+
"audit.field.actions": "Acciones",
|
|
469
|
+
"audit.field.request": "Solicitud",
|
|
470
|
+
"audit.field.address": "Dirección IP",
|
|
471
|
+
"audit.field.duration": "ms",
|
|
472
|
+
"audit.door.owner": "propietario del dominio",
|
|
473
|
+
"audit.door.super": "superusuario",
|
|
474
|
+
"audit.kind.auth.signin": "Inicio de sesión",
|
|
475
|
+
"audit.kind.auth.checkin": "Acceso",
|
|
476
|
+
"audit.kind.auth.signout": "Cierre de sesión",
|
|
477
|
+
"audit.kind.password.change": "Cambio de contraseña",
|
|
478
|
+
"audit.kind.password.reset-by-admin": "Restablecimiento de contraseña",
|
|
479
|
+
"audit.kind.credential.issue": "Credencial reemitida",
|
|
480
|
+
"audit.kind.webauthn.register": "Llave de acceso registrada",
|
|
481
|
+
"audit.kind.role.grant": "Rol concedido",
|
|
482
|
+
"audit.kind.role.revoke": "Rol retirado",
|
|
483
|
+
"audit.kind.role.privilege.add": "Privilegio añadido al rol",
|
|
484
|
+
"audit.kind.role.privilege.remove": "Privilegio quitado del rol",
|
|
485
|
+
"audit.kind.role.delete": "Rol eliminado",
|
|
486
|
+
"audit.kind.user.status": "Estado de la cuenta",
|
|
487
|
+
"audit.kind.domain.owner.add": "Propietario del dominio añadido",
|
|
488
|
+
"audit.kind.domain.owner.remove": "Propietario del dominio quitado",
|
|
489
|
+
"audit.kind.invitation.create": "Invitación enviada",
|
|
490
|
+
"audit.kind.invitation.status": "Estado de la invitación"
|
|
424
491
|
}
|
package/translations/ja.json
CHANGED
|
@@ -420,5 +420,72 @@
|
|
|
420
420
|
"access-request.dock.example today": "今日届いた権限リクエストを整理して",
|
|
421
421
|
"access-request.dock.example smallest": "リクエストごとに最小のロールで付与案を作って",
|
|
422
422
|
"access-request.dock.example one person": "一人のリクエストと、ロールごとに追加で与えるものを見せて",
|
|
423
|
-
"access-request.text.and more": "{list} ほか {count} 件"
|
|
423
|
+
"access-request.text.and more": "{list} ほか {count} 件",
|
|
424
|
+
"label.privileges view": "権限",
|
|
425
|
+
"label.tasks view": "業務",
|
|
426
|
+
"label.template view": "テンプレートと比較",
|
|
427
|
+
"text.counted from the saved privileges": "保存した権限で数えます。",
|
|
428
|
+
"text.this role holds no task": "このロールはどの業務の権限も持っていません。",
|
|
429
|
+
"label.tasks this role does not hold": "このロールにない業務",
|
|
430
|
+
"button.unfold": "開く",
|
|
431
|
+
"button.fold": "閉じる",
|
|
432
|
+
"label.privileges no task names": "どの業務にもない権限",
|
|
433
|
+
"text.task names an undeclared privilege": "定義エラー",
|
|
434
|
+
"text.task held whole": "すべて",
|
|
435
|
+
"text.task held in part": "一部 {held}/{total}",
|
|
436
|
+
"text.not held x": "ない権限: {x}",
|
|
437
|
+
"text.no template to compare with": "比較するテンプレートがないか、テンプレートを読む権限がありません。",
|
|
438
|
+
"text.pick a template to compare with": "テンプレートを選ぶ",
|
|
439
|
+
"text.template cannot be applied because": "このテンプレートは適用できません: {list}。",
|
|
440
|
+
"text.template cannot be applied": "適用不可",
|
|
441
|
+
"label.missing against the template": "テンプレートにあってこのロールにない権限",
|
|
442
|
+
"text.nothing missing against the template": "足りない権限はありません。",
|
|
443
|
+
"label.wider than the template": "テンプレートより広い権限",
|
|
444
|
+
"audit.title": "監査ログ",
|
|
445
|
+
"audit.view.people": "ユーザー別",
|
|
446
|
+
"audit.view.doors": "権限別",
|
|
447
|
+
"audit.view.records": "記録",
|
|
448
|
+
"audit.period.days": "{count}日",
|
|
449
|
+
"audit.period.from": "開始日",
|
|
450
|
+
"audit.period.to": "終了日",
|
|
451
|
+
"audit.outcome.all": "すべて",
|
|
452
|
+
"audit.outcome.denied": "拒否",
|
|
453
|
+
"audit.outcome.error": "エラー",
|
|
454
|
+
"audit.outcome.failed": "失敗",
|
|
455
|
+
"audit.button.all-people": "全員",
|
|
456
|
+
"audit.button.all-privileges": "すべての権限",
|
|
457
|
+
"audit.health.failures": "記録失敗 {count}件({since} 以降)",
|
|
458
|
+
"audit.health.unknown": "記録失敗数を取得できません",
|
|
459
|
+
"audit.field.last-checkin": "最終アクセス",
|
|
460
|
+
"audit.field.checkins": "アクセス",
|
|
461
|
+
"audit.field.failed-signins": "ログイン失敗",
|
|
462
|
+
"audit.field.granted": "許可",
|
|
463
|
+
"audit.field.denied": "拒否",
|
|
464
|
+
"audit.field.people": "人数",
|
|
465
|
+
"audit.field.privilege": "権限",
|
|
466
|
+
"audit.field.time": "日時",
|
|
467
|
+
"audit.field.actor": "ユーザー",
|
|
468
|
+
"audit.field.actions": "操作",
|
|
469
|
+
"audit.field.request": "リクエスト",
|
|
470
|
+
"audit.field.address": "接続IP",
|
|
471
|
+
"audit.field.duration": "処理 ms",
|
|
472
|
+
"audit.door.owner": "$t(term.domain)のオーナー",
|
|
473
|
+
"audit.door.super": "スーパーユーザー",
|
|
474
|
+
"audit.kind.auth.signin": "ログイン",
|
|
475
|
+
"audit.kind.auth.checkin": "アクセス",
|
|
476
|
+
"audit.kind.auth.signout": "ログアウト",
|
|
477
|
+
"audit.kind.password.change": "パスワード変更",
|
|
478
|
+
"audit.kind.password.reset-by-admin": "パスワード初期化",
|
|
479
|
+
"audit.kind.credential.issue": "認証情報の再発行",
|
|
480
|
+
"audit.kind.webauthn.register": "パスキー登録",
|
|
481
|
+
"audit.kind.role.grant": "ロール付与",
|
|
482
|
+
"audit.kind.role.revoke": "ロール取消",
|
|
483
|
+
"audit.kind.role.privilege.add": "ロールに権限追加",
|
|
484
|
+
"audit.kind.role.privilege.remove": "ロールから権限除外",
|
|
485
|
+
"audit.kind.role.delete": "ロール削除",
|
|
486
|
+
"audit.kind.user.status": "アカウント状態",
|
|
487
|
+
"audit.kind.domain.owner.add": "$t(term.domain)オーナー追加",
|
|
488
|
+
"audit.kind.domain.owner.remove": "$t(term.domain)オーナー解除",
|
|
489
|
+
"audit.kind.invitation.create": "招待",
|
|
490
|
+
"audit.kind.invitation.status": "招待状態"
|
|
424
491
|
}
|
package/translations/ko.json
CHANGED
|
@@ -420,5 +420,72 @@
|
|
|
420
420
|
"access-request.dock.example today": "오늘 들어온 권한 요청 정리해 줘",
|
|
421
421
|
"access-request.dock.example smallest": "요청마다 가장 작은 역할로 부여안을 만들어 줘",
|
|
422
422
|
"access-request.dock.example one person": "한 사람이 요청한 것과 역할마다 더 주는 것을 보여 줘",
|
|
423
|
-
"access-request.text.and more": "{list} 외 {count}개"
|
|
423
|
+
"access-request.text.and more": "{list} 외 {count}개",
|
|
424
|
+
"label.privileges view": "권한",
|
|
425
|
+
"label.tasks view": "업무",
|
|
426
|
+
"label.template view": "템플릿과 견주기",
|
|
427
|
+
"text.counted from the saved privileges": "저장한 권한으로 셉니다.",
|
|
428
|
+
"text.this role holds no task": "이 역할은 어느 업무의 권한도 갖고 있지 않습니다.",
|
|
429
|
+
"label.tasks this role does not hold": "이 역할에 없는 업무",
|
|
430
|
+
"button.unfold": "펼치기",
|
|
431
|
+
"button.fold": "접기",
|
|
432
|
+
"label.privileges no task names": "어느 업무에도 없는 권한",
|
|
433
|
+
"text.task names an undeclared privilege": "정의 오류",
|
|
434
|
+
"text.task held whole": "전부",
|
|
435
|
+
"text.task held in part": "일부 {held}/{total}",
|
|
436
|
+
"text.not held x": "없는 권한: {x}",
|
|
437
|
+
"text.no template to compare with": "견줄 템플릿이 없거나 템플릿을 읽을 권한이 없습니다.",
|
|
438
|
+
"text.pick a template to compare with": "템플릿 고르기",
|
|
439
|
+
"text.template cannot be applied because": "이 템플릿은 적용할 수 없습니다: {list}.",
|
|
440
|
+
"text.template cannot be applied": "적용 불가",
|
|
441
|
+
"label.missing against the template": "템플릿에 있고 이 역할에 없는 권한",
|
|
442
|
+
"text.nothing missing against the template": "빠진 권한이 없습니다.",
|
|
443
|
+
"label.wider than the template": "템플릿보다 넓은 권한",
|
|
444
|
+
"audit.title": "감사 기록",
|
|
445
|
+
"audit.view.people": "사람별",
|
|
446
|
+
"audit.view.doors": "권한별",
|
|
447
|
+
"audit.view.records": "기록",
|
|
448
|
+
"audit.period.days": "{count}일",
|
|
449
|
+
"audit.period.from": "시작일",
|
|
450
|
+
"audit.period.to": "종료일",
|
|
451
|
+
"audit.outcome.all": "전체",
|
|
452
|
+
"audit.outcome.denied": "거절",
|
|
453
|
+
"audit.outcome.error": "오류",
|
|
454
|
+
"audit.outcome.failed": "실패",
|
|
455
|
+
"audit.button.all-people": "모든 사람",
|
|
456
|
+
"audit.button.all-privileges": "모든 권한",
|
|
457
|
+
"audit.health.failures": "기록 실패 {count}건 ({since} 이후)",
|
|
458
|
+
"audit.health.unknown": "기록 실패 수를 읽지 못함",
|
|
459
|
+
"audit.field.last-checkin": "마지막 접속",
|
|
460
|
+
"audit.field.checkins": "접속",
|
|
461
|
+
"audit.field.failed-signins": "로그인 실패",
|
|
462
|
+
"audit.field.granted": "통과",
|
|
463
|
+
"audit.field.denied": "거절",
|
|
464
|
+
"audit.field.people": "사람 수",
|
|
465
|
+
"audit.field.privilege": "권한",
|
|
466
|
+
"audit.field.time": "시각",
|
|
467
|
+
"audit.field.actor": "사용자",
|
|
468
|
+
"audit.field.actions": "행위",
|
|
469
|
+
"audit.field.request": "요청",
|
|
470
|
+
"audit.field.address": "접속 IP",
|
|
471
|
+
"audit.field.duration": "처리 ms",
|
|
472
|
+
"audit.door.owner": "$t(term.domain) 소유자",
|
|
473
|
+
"audit.door.super": "수퍼유저",
|
|
474
|
+
"audit.kind.auth.signin": "로그인",
|
|
475
|
+
"audit.kind.auth.checkin": "접속",
|
|
476
|
+
"audit.kind.auth.signout": "로그아웃",
|
|
477
|
+
"audit.kind.password.change": "비밀번호 변경",
|
|
478
|
+
"audit.kind.password.reset-by-admin": "비밀번호 초기화",
|
|
479
|
+
"audit.kind.credential.issue": "인증 정보 재발급",
|
|
480
|
+
"audit.kind.webauthn.register": "패스키 등록",
|
|
481
|
+
"audit.kind.role.grant": "역할 부여",
|
|
482
|
+
"audit.kind.role.revoke": "역할 회수",
|
|
483
|
+
"audit.kind.role.privilege.add": "역할에 권한 추가",
|
|
484
|
+
"audit.kind.role.privilege.remove": "역할에서 권한 제외",
|
|
485
|
+
"audit.kind.role.delete": "역할 삭제",
|
|
486
|
+
"audit.kind.user.status": "계정 상태",
|
|
487
|
+
"audit.kind.domain.owner.add": "$t(term.domain) 소유자 지정",
|
|
488
|
+
"audit.kind.domain.owner.remove": "$t(term.domain) 소유자 해제",
|
|
489
|
+
"audit.kind.invitation.create": "초대",
|
|
490
|
+
"audit.kind.invitation.status": "초대 상태"
|
|
424
491
|
}
|
package/translations/ms.json
CHANGED
|
@@ -420,5 +420,72 @@
|
|
|
420
420
|
"access-request.dock.example today": "susun permintaan akses hari ini",
|
|
421
421
|
"access-request.dock.example smallest": "sediakan draf pemberian dengan peranan terkecil bagi setiap permintaan",
|
|
422
422
|
"access-request.dock.example one person": "tunjukkan apa yang diminta seseorang dan apa yang diberi oleh setiap peranan",
|
|
423
|
-
"access-request.text.and more": "{list} dan {count} lagi"
|
|
423
|
+
"access-request.text.and more": "{list} dan {count} lagi",
|
|
424
|
+
"label.privileges view": "Keistimewaan",
|
|
425
|
+
"label.tasks view": "Tugas",
|
|
426
|
+
"label.template view": "Berbanding templat",
|
|
427
|
+
"text.counted from the saved privileges": "Dikira daripada keistimewaan yang disimpan.",
|
|
428
|
+
"text.this role holds no task": "Peranan ini tidak memegang keistimewaan mana-mana tugas.",
|
|
429
|
+
"label.tasks this role does not hold": "Tugas yang tiada pada peranan ini",
|
|
430
|
+
"button.unfold": "Tunjuk",
|
|
431
|
+
"button.fold": "Sembunyi",
|
|
432
|
+
"label.privileges no task names": "Keistimewaan yang tiada dalam mana-mana tugas",
|
|
433
|
+
"text.task names an undeclared privilege": "Ralat definisi",
|
|
434
|
+
"text.task held whole": "Semua",
|
|
435
|
+
"text.task held in part": "{held} daripada {total}",
|
|
436
|
+
"text.not held x": "Tiada: {x}",
|
|
437
|
+
"text.no template to compare with": "Tiada templat untuk dibandingkan, atau anda tiada keistimewaan untuk membacanya.",
|
|
438
|
+
"text.pick a template to compare with": "Pilih templat",
|
|
439
|
+
"text.template cannot be applied because": "Templat ini tidak boleh digunakan: {list}.",
|
|
440
|
+
"text.template cannot be applied": "Tidak boleh digunakan",
|
|
441
|
+
"label.missing against the template": "Tiada berbanding templat",
|
|
442
|
+
"text.nothing missing against the template": "Tiada yang kurang.",
|
|
443
|
+
"label.wider than the template": "Lebih luas daripada templat",
|
|
444
|
+
"audit.title": "Log audit",
|
|
445
|
+
"audit.view.people": "Mengikut orang",
|
|
446
|
+
"audit.view.doors": "Mengikut keistimewaan",
|
|
447
|
+
"audit.view.records": "Rekod",
|
|
448
|
+
"audit.period.days": "{count} hari",
|
|
449
|
+
"audit.period.from": "Dari",
|
|
450
|
+
"audit.period.to": "Hingga",
|
|
451
|
+
"audit.outcome.all": "Semua",
|
|
452
|
+
"audit.outcome.denied": "Ditolak",
|
|
453
|
+
"audit.outcome.error": "Ralat",
|
|
454
|
+
"audit.outcome.failed": "Gagal",
|
|
455
|
+
"audit.button.all-people": "Semua orang",
|
|
456
|
+
"audit.button.all-privileges": "Semua keistimewaan",
|
|
457
|
+
"audit.health.failures": "{count} tidak direkod (sejak {since})",
|
|
458
|
+
"audit.health.unknown": "Bilangan gagal rekod tidak dapat dibaca",
|
|
459
|
+
"audit.field.last-checkin": "Akses terakhir",
|
|
460
|
+
"audit.field.checkins": "Akses",
|
|
461
|
+
"audit.field.failed-signins": "Log masuk gagal",
|
|
462
|
+
"audit.field.granted": "Dibenarkan",
|
|
463
|
+
"audit.field.denied": "Ditolak",
|
|
464
|
+
"audit.field.people": "Orang",
|
|
465
|
+
"audit.field.privilege": "Keistimewaan",
|
|
466
|
+
"audit.field.time": "Masa",
|
|
467
|
+
"audit.field.actor": "Pengguna",
|
|
468
|
+
"audit.field.actions": "Tindakan",
|
|
469
|
+
"audit.field.request": "Permintaan",
|
|
470
|
+
"audit.field.address": "Alamat IP",
|
|
471
|
+
"audit.field.duration": "ms",
|
|
472
|
+
"audit.door.owner": "pemilik $t(term.domain)",
|
|
473
|
+
"audit.door.super": "superuser",
|
|
474
|
+
"audit.kind.auth.signin": "Log masuk",
|
|
475
|
+
"audit.kind.auth.checkin": "Akses",
|
|
476
|
+
"audit.kind.auth.signout": "Log keluar",
|
|
477
|
+
"audit.kind.password.change": "Kata laluan ditukar",
|
|
478
|
+
"audit.kind.password.reset-by-admin": "Set semula kata laluan",
|
|
479
|
+
"audit.kind.credential.issue": "Kelayakan dikeluarkan semula",
|
|
480
|
+
"audit.kind.webauthn.register": "Kunci laluan didaftar",
|
|
481
|
+
"audit.kind.role.grant": "Peranan diberi",
|
|
482
|
+
"audit.kind.role.revoke": "Peranan ditarik",
|
|
483
|
+
"audit.kind.role.privilege.add": "Keistimewaan ditambah pada peranan",
|
|
484
|
+
"audit.kind.role.privilege.remove": "Keistimewaan dibuang daripada peranan",
|
|
485
|
+
"audit.kind.role.delete": "Peranan dipadam",
|
|
486
|
+
"audit.kind.user.status": "Status akaun",
|
|
487
|
+
"audit.kind.domain.owner.add": "Pemilik $t(term.domain) ditambah",
|
|
488
|
+
"audit.kind.domain.owner.remove": "Pemilik $t(term.domain) dibuang",
|
|
489
|
+
"audit.kind.invitation.create": "Jemputan dihantar",
|
|
490
|
+
"audit.kind.invitation.status": "Status jemputan"
|
|
424
491
|
}
|