@things-factory/auth-ui 10.1.215 → 10.1.219
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/bootstrap.js +18 -14
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/components/abstract-password-reset.d.ts +5 -0
- package/dist-client/components/abstract-password-reset.js +20 -0
- package/dist-client/components/abstract-password-reset.js.map +1 -1
- package/dist-client/components/ownership-transfer-popup.d.ts +3 -1
- package/dist-client/components/ownership-transfer-popup.js +38 -41
- package/dist-client/components/ownership-transfer-popup.js.map +1 -1
- package/dist-client/components/password-setup-link-popup.d.ts +46 -0
- package/dist-client/components/password-setup-link-popup.js +254 -0
- package/dist-client/components/password-setup-link-popup.js.map +1 -0
- package/dist-client/components/user-detail.d.ts +20 -30
- package/dist-client/components/user-detail.js +114 -186
- package/dist-client/components/user-detail.js.map +1 -1
- package/dist-client/components/user-invite.d.ts +18 -25
- package/dist-client/components/user-invite.js +157 -181
- package/dist-client/components/user-invite.js.map +1 -1
- package/dist-client/components/user-popups-standard.test.js +69 -0
- package/dist-client/components/user-popups-standard.test.js.map +1 -0
- package/dist-client/components/user-role-editor.js +5 -26
- package/dist-client/components/user-role-editor.js.map +1 -1
- package/dist-client/components/user-status-renderer.js +4 -0
- package/dist-client/components/user-status-renderer.js.map +1 -1
- package/dist-client/entries/auth/reset-password.d.ts +1 -0
- package/dist-client/entries/auth/reset-password.js +5 -1
- package/dist-client/entries/auth/reset-password.js.map +1 -1
- package/dist-client/index.js +10 -28
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/user/user-list-page.d.ts +5 -1
- package/dist-client/pages/user/user-list-page.js +14 -5
- package/dist-client/pages/user/user-list-page.js.map +1 -1
- package/dist-client/route.js +0 -3
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/link-token.d.ts +3 -3
- package/dist-client/utils/link-token.js +4 -4
- package/dist-client/utils/link-token.js.map +1 -1
- package/dist-client/utils/link-token.test.js +2 -2
- package/dist-client/utils/link-token.test.js.map +1 -1
- package/package.json +6 -5
- package/things-factory.config.js +0 -1
- package/translations/en.json +30 -20
- package/translations/es.json +30 -20
- package/translations/ja.json +30 -20
- package/translations/ko.json +30 -20
- package/translations/ms.json +30 -20
- package/translations/zh.json +30 -20
- package/dist-client/components/accept-invitation.d.ts +0 -47
- package/dist-client/components/accept-invitation.js +0 -258
- package/dist-client/components/accept-invitation.js.map +0 -1
- package/dist-client/entries/auth/accept-invitation.d.ts +0 -3
- package/dist-client/entries/auth/accept-invitation.js +0 -10
- package/dist-client/entries/auth/accept-invitation.js.map +0 -1
- package/dist-client/pages/invitation/invitation-list-query.test.js +0 -69
- package/dist-client/pages/invitation/invitation-list-query.test.js.map +0 -1
- package/dist-client/pages/invitation/invitations.d.ts +0 -63
- package/dist-client/pages/invitation/invitations.js +0 -284
- package/dist-client/pages/invitation/invitations.js.map +0 -1
- /package/dist-client/{pages/invitation/invitation-list-query.test.d.ts → components/user-popups-standard.test.d.ts} +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* The user management popups keep the house shape of a popup (operato-application design/ui/page-standard.md §7·§8).
|
|
5
|
+
*
|
|
6
|
+
* They drew their own: Material buttons in the middle of the body, save and cancel above a separate "cannot be undone"
|
|
7
|
+
* strip, Material text fields 56px tall with the label on the border, and the whole card scrolling with its buttons.
|
|
8
|
+
* Now only the body scrolls, every command is in the one `ox-popup-actions` row (irreversible ones at the start in red),
|
|
9
|
+
* and fields are labels above native inputs.
|
|
10
|
+
*/
|
|
11
|
+
const POPUPS = ['user-detail.ts', 'user-invite.ts', 'ownership-transfer-popup.ts', 'password-setup-link-popup.ts'];
|
|
12
|
+
const read = (name) => readFileSync(path.join(__dirname, name), 'utf-8');
|
|
13
|
+
describe.each(POPUPS)('%s', name => {
|
|
14
|
+
const source = read(name);
|
|
15
|
+
it('scrolls its body only and ends in the shared action row', () => {
|
|
16
|
+
expect(source.includes('PopupBodyStyles')).toBe(true);
|
|
17
|
+
expect(source.includes('<div class="body">')).toBe(true);
|
|
18
|
+
expect(source.includes("import '@operato/popup/ox-popup-actions.js'")).toBe(true);
|
|
19
|
+
expect((source.match(/<ox-popup-actions>/g) || []).length).toBe(1);
|
|
20
|
+
});
|
|
21
|
+
it('has exactly one way out and one main action', () => {
|
|
22
|
+
expect((source.match(/slot="cancel"/g) || []).length).toBe(1);
|
|
23
|
+
expect((source.match(/slot="confirm"/g) || []).length).toBe(1);
|
|
24
|
+
});
|
|
25
|
+
it('draws no Material field, checkbox or raised button, and no row of its own', () => {
|
|
26
|
+
expect(/<md-(filled|outlined)-text-field|<md-checkbox|<md-elevated-button/.test(source)).toBe(false);
|
|
27
|
+
expect(/class="button-container"/.test(source)).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
it('writes no font size of its own', () => {
|
|
30
|
+
expect(/font-size:\s*[\d.]+(rem|px|em)/.test(source)).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('user-detail', () => {
|
|
34
|
+
const source = read('user-detail.ts');
|
|
35
|
+
it('★ puts every irreversible action at the start, in red', () => {
|
|
36
|
+
for (const action of ['onPasswordSetup', 'onTransfer', 'onRemoveFromDomain']) {
|
|
37
|
+
expect(new RegExp(`<md-text-button slot="start" destructive @click=\\$\\{\\(\\) => this\\.${action}\\(\\)\\}>`).test(source)).toBe(true);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('the user list', () => {
|
|
42
|
+
it('★ titles the detail popup by what it is, not by whom', () => {
|
|
43
|
+
const page = readFileSync(path.join(__dirname, '..', 'pages', 'user', 'user-list-page.ts'), 'utf-8');
|
|
44
|
+
expect(page.includes("title: i18next.t('title.user details')")).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('user-invite', () => {
|
|
48
|
+
const source = read('user-invite.ts');
|
|
49
|
+
it('★ says what adding a user is before an email is typed', () => {
|
|
50
|
+
expect(/<div class="body">\s*\$\{this\.renderGuide\(\)\}/.test(source)).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
it('★ does not take a failed lookup for "no account"', () => {
|
|
53
|
+
expect(source.includes("this.lookup = 'failed'")).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('the password setup link (ADR-0161)', () => {
|
|
57
|
+
it('★ every way to take back or give a password opens the one popup', () => {
|
|
58
|
+
for (const name of ['user-detail.ts', 'user-role-editor.ts', path.join('..', 'pages', 'user', 'user-list-page.ts')]) {
|
|
59
|
+
const source = read(name);
|
|
60
|
+
expect(source.includes('openPasswordSetupLink(')).toBe(true);
|
|
61
|
+
expect(/resetPasswordToDefault|checkDefaultPassword/.test(source)).toBe(false);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
it('★ the add-user popup sets no password and sends no invitation', () => {
|
|
65
|
+
const source = read('user-invite.ts');
|
|
66
|
+
expect(/password|sendInvitation|checkDefaultPassword/i.test(source.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\/\/.*$/gm, ''))).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=user-popups-standard.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-popups-standard.test.js","sourceRoot":"","sources":["../../client/components/user-popups-standard.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from 'fs'\nimport path from 'path'\n\n/**\n * The user management popups keep the house shape of a popup (operato-application design/ui/page-standard.md §7·§8).\n *\n * They drew their own: Material buttons in the middle of the body, save and cancel above a separate \"cannot be undone\"\n * strip, Material text fields 56px tall with the label on the border, and the whole card scrolling with its buttons.\n * Now only the body scrolls, every command is in the one `ox-popup-actions` row (irreversible ones at the start in red),\n * and fields are labels above native inputs.\n */\n\nconst POPUPS = ['user-detail.ts', 'user-invite.ts', 'ownership-transfer-popup.ts', 'password-setup-link-popup.ts']\n\nconst read = (name: string) => readFileSync(path.join(__dirname, name), 'utf-8')\n\ndescribe.each(POPUPS)('%s', name => {\n const source = read(name)\n\n it('scrolls its body only and ends in the shared action row', () => {\n expect(source.includes('PopupBodyStyles')).toBe(true)\n expect(source.includes('<div class=\"body\">')).toBe(true)\n expect(source.includes(\"import '@operato/popup/ox-popup-actions.js'\")).toBe(true)\n expect((source.match(/<ox-popup-actions>/g) || []).length).toBe(1)\n })\n\n it('has exactly one way out and one main action', () => {\n expect((source.match(/slot=\"cancel\"/g) || []).length).toBe(1)\n expect((source.match(/slot=\"confirm\"/g) || []).length).toBe(1)\n })\n\n it('draws no Material field, checkbox or raised button, and no row of its own', () => {\n expect(/<md-(filled|outlined)-text-field|<md-checkbox|<md-elevated-button/.test(source)).toBe(false)\n expect(/class=\"button-container\"/.test(source)).toBe(false)\n })\n\n it('writes no font size of its own', () => {\n expect(/font-size:\\s*[\\d.]+(rem|px|em)/.test(source)).toBe(false)\n })\n})\n\ndescribe('user-detail', () => {\n const source = read('user-detail.ts')\n\n it('★ puts every irreversible action at the start, in red', () => {\n for (const action of ['onPasswordSetup', 'onTransfer', 'onRemoveFromDomain']) {\n expect(new RegExp(`<md-text-button slot=\"start\" destructive @click=\\\\$\\\\{\\\\(\\\\) => this\\\\.${action}\\\\(\\\\)\\\\}>`).test(source)).toBe(\n true\n )\n }\n })\n})\n\ndescribe('the user list', () => {\n it('★ titles the detail popup by what it is, not by whom', () => {\n const page = readFileSync(path.join(__dirname, '..', 'pages', 'user', 'user-list-page.ts'), 'utf-8')\n expect(page.includes(\"title: i18next.t('title.user details')\")).toBe(true)\n })\n})\n\ndescribe('user-invite', () => {\n const source = read('user-invite.ts')\n\n it('★ says what adding a user is before an email is typed', () => {\n expect(/<div class=\"body\">\\s*\\$\\{this\\.renderGuide\\(\\)\\}/.test(source)).toBe(true)\n })\n\n it('★ does not take a failed lookup for \"no account\"', () => {\n expect(source.includes(\"this.lookup = 'failed'\")).toBe(true)\n })\n})\n\ndescribe('the password setup link (ADR-0161)', () => {\n it('★ every way to take back or give a password opens the one popup', () => {\n for (const name of ['user-detail.ts', 'user-role-editor.ts', path.join('..', 'pages', 'user', 'user-list-page.ts')]) {\n const source = read(name)\n expect(source.includes('openPasswordSetupLink(')).toBe(true)\n expect(/resetPasswordToDefault|checkDefaultPassword/.test(source)).toBe(false)\n }\n })\n\n it('★ the add-user popup sets no password and sends no invitation', () => {\n const source = read('user-invite.ts')\n expect(/password|sendInvitation|checkDefaultPassword/i.test(source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').replace(/\\/\\/.*$/gm, ''))).toBe(\n false\n )\n })\n})\n"]}
|
|
@@ -3,6 +3,7 @@ import '@material/web/icon/icon.js';
|
|
|
3
3
|
import '@material/web/button/elevated-button.js';
|
|
4
4
|
import './ownership-transfer-popup.js';
|
|
5
5
|
import './role-selector.js';
|
|
6
|
+
import { openPasswordSetupLink } from './password-setup-link-popup.js';
|
|
6
7
|
import gql from 'graphql-tag';
|
|
7
8
|
import { css, html, LitElement } from 'lit';
|
|
8
9
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
@@ -155,7 +156,7 @@ let UserRoleEditor = class UserRoleEditor extends LitElement {
|
|
|
155
156
|
: ''}
|
|
156
157
|
${this.isPasswordResettable(user)
|
|
157
158
|
? html `<md-elevated-button danger @click=${() => this.onResetPassword(user)}
|
|
158
|
-
>${String(i18next.t('
|
|
159
|
+
>${String(i18next.t('button.password reset link'))}</md-elevated-button
|
|
159
160
|
>`
|
|
160
161
|
: ''}
|
|
161
162
|
`
|
|
@@ -394,31 +395,9 @@ let UserRoleEditor = class UserRoleEditor extends LitElement {
|
|
|
394
395
|
title: `${i18next.t('title.owner_transfer')}`
|
|
395
396
|
});
|
|
396
397
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
text: i18next.t('text.are_you_sure_to_x', { x: i18next.t('title.reset password') }),
|
|
401
|
-
confirmButton: { text: i18next.t('button.confirm') },
|
|
402
|
-
cancelButton: { text: i18next.t('button.cancel') }
|
|
403
|
-
})) {
|
|
404
|
-
const response = await client.mutate({
|
|
405
|
-
mutation: gql `
|
|
406
|
-
mutation resetPasswordToDefault($username: String!) {
|
|
407
|
-
resetPasswordToDefault(username: $username)
|
|
408
|
-
}
|
|
409
|
-
`,
|
|
410
|
-
variables: { username: user.username || user.email },
|
|
411
|
-
context: gqlContext()
|
|
412
|
-
});
|
|
413
|
-
if (!response.errors) {
|
|
414
|
-
await OxPrompt.open({
|
|
415
|
-
type: 'success',
|
|
416
|
-
title: i18next.t('text.completed'),
|
|
417
|
-
text: i18next.t('text.password reset succeed'),
|
|
418
|
-
confirmButton: { text: i18next.t('button.confirm') }
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
}
|
|
398
|
+
/* An administrator never sets the password - the person sets it through a one-time link (ADR-0161). */
|
|
399
|
+
onResetPassword(user) {
|
|
400
|
+
openPasswordSetupLink(user, { onIssued: () => this.dispatchUserUpdated() });
|
|
422
401
|
}
|
|
423
402
|
dispatchUserUpdated() {
|
|
424
403
|
this.dispatchEvent(new CustomEvent('userUpdated'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-role-editor.js","sourceRoot":"","sources":["../../client/components/user-role-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\n\nimport './ownership-transfer-popup.js'\nimport './role-selector.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { client, gqlContext } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { openPopup } from '@operato/layout'\nimport { store } from '@operato/shell'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { ButtonContainerStyles } from '@operato/styles'\nimport { RoleSelector } from './role-selector.js'\nimport { InheritedValueType } from '@operato/data-grist'\n\n@customElement('user-role-editor')\nclass UserRoleEditor extends LitElement {\n static styles = [\n ButtonContainerStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n\n border: 1px solid var(--md-sys-color-primary);\n font: normal 15px var(--theme-font);\n color: var(--md-sys-color-secondary);\n }\n ul {\n flex: 1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n column-gap: 20px;\n\n overflow: auto;\n margin: 0;\n padding: var(--spacing-medium);\n list-style: none;\n border: 1px dashed rgba(0, 0, 0, 0.1);\n border-width: 1px 0;\n }\n input[readonly] {\n border: none;\n background-color: transparent;\n color: var(--md-sys-color-secondary);\n font: var(--input-font);\n }\n li {\n padding: var(--spacing-small);\n }\n [detail] {\n background-color: var(--md-sys-color-surface);\n }\n [detail] md-icon {\n --md-icon-size: var(--fontsize-default);\n vertical-align: middle;\n color: var(--md-sys-color-primary);\n }\n [detail] li {\n display: flex;\n }\n [detail] li input {\n flex: 1;\n }\n\n md-elevated-button {\n margin: 5px;\n }\n\n md-outlined-button {\n background-color: var(--md-sys-color-surface-variant);\n }\n\n @media screen and (max-width: 480px) {\n ul {\n grid-template-columns: 1fr;\n }\n }\n `\n ]\n\n @property({ type: Object }) user: any = {}\n @property({ type: Boolean }) activate: boolean = false\n @property({ type: Object }) domainOwner: any\n\n @state() domainRoles: any[] = []\n @state() grantedRoles: any = {}\n @state() userRoles: any[] = []\n @state() isSuperOwner: boolean = false\n @state() isDomainOwner: boolean = false\n\n private me: any\n\n render() {\n const user = this.user || {}\n const domainRoles = this.domainRoles || []\n const grantedRoles = this.grantedRoles || {}\n let currentDomainName = 'roles'\n if (domainRoles?.length) {\n currentDomainName = domainRoles[0].domain.name\n }\n\n return html`\n ${this.activate\n ? html`\n <ul detail>\n ${user.userType === 'user'\n ? html`\n <li>\n <span>\n ${user.username || user.email} (<md-icon>email</md-icon>\n ${user.email})\n </span>\n </li>\n `\n : ''}\n </ul>\n\n <role-selector .user=${this.user} .roles=${domainRoles} .userRoles=${this.userRoles}></role-selector>\n\n ${Object.keys(grantedRoles).map(\n partnerName => html`\n <role-selector\n .roleCategory=${partnerName}\n .user=${this.user}\n .roles=${this.grantedRoles[partnerName]}\n .userRoles=${this.userRoles}\n >\n </role-selector>\n `\n )}\n `\n : ''}\n\n <div class=\"button-container\">\n ${this.isRoleEditable()\n ? html` <md-elevated-button\n @click=${() => {\n // GraphQL 의 ObjectRef 타입은 { id } 만 받음. Apollo 가 query\n // 결과에 자동으로 붙이는 __typename 이 그대로 들어가면\n // \"Field __typename is not defined by type ObjectRef\" 에러.\n // 원본 객체를 mutate (delete) 하지 않고 { id } 만 추려서 넘긴다.\n const toRef = (r: any) => ({ id: r.id })\n const { availableRoles, selectedRoles } = Array.from(\n this.renderRoot.querySelectorAll('role-selector') as NodeListOf<RoleSelector>\n ).reduce(\n (roles, roleSelector) => {\n roles.availableRoles = roles.availableRoles.concat(\n roleSelector.roles.map(toRef)\n )\n roles.selectedRoles = roles.selectedRoles.concat(\n roleSelector.selectedRoles().map(toRef)\n )\n return roles\n },\n { availableRoles: [], selectedRoles: [] } as { availableRoles: any[]; selectedRoles: any[] }\n )\n this.onSave(user, availableRoles, selectedRoles)\n }}\n >${String(i18next.t('button.save'))}</md-elevated-button\n >`\n : ''}\n ${user.userType === 'user'\n ? html`\n ${this.isTransferable(user) && this.userRoles && this.userRoles.length > 0\n ? html`\n <md-elevated-button danger @click=${() => this.onTransfer(user)}\n >${String(i18next.t('button.transfer owner'))}</md-elevated-button\n >\n `\n : ''}\n ${this.isPasswordResettable(user)\n ? html`<md-elevated-button danger @click=${() => this.onResetPassword(user)}\n >${String(i18next.t('title.reset password'))}</md-elevated-button\n >`\n : ''}\n `\n : ''}\n ${this.isRemovable(user)\n ? html`\n <md-elevated-button danger @click=${() => this.onDelete(user)}\n >${String(i18next.t('button.delete user'))}</md-elevated-button\n >\n `\n : ''}\n ${this.isActivatable(user)\n ? html`<md-elevated-button danger @click=${() => this.onActivate(user)}\n >${String(i18next.t('button.activate'))}</md-elevated-button\n >`\n : ''}\n ${this.isInactivatable(user)\n ? html`<md-elevated-button danger @click=${() => this.onInactivate(user)}\n >${String(i18next.t('button.deactivate'))}</md-elevated-button\n >`\n : ''}\n </div>\n `\n }\n\n isRemovable(user) {\n return this.isDomainOwner && user.email !== this.me.email && !user.owner\n }\n\n isTransferable(user) {\n return this.activate && (this.isSuperOwner || this.isDomainOwner) && !user.owner\n }\n\n isRoleEditable() {\n return this.activate && (this.domainRoles?.length || Object.keys(this.grantedRoles || {}).length)\n }\n\n isPasswordResettable(user) {\n return (this.isSuperOwner || this.isDomainOwner) && user.email !== this.me.email\n }\n\n isActivatable(user) {\n return (this.isSuperOwner || this.isDomainOwner) && !this.activate\n }\n\n isInactivatable(user) {\n return (\n (this.isSuperOwner || this.isDomainOwner) &&\n user.id !== this.domainOwner.id &&\n user.userType !== 'admin' &&\n this.activate\n )\n }\n\n async updated(changedProps) {\n if (changedProps.has('user')) {\n this.fetchAvailableRoles()\n\n if (this.user?.email) {\n this.userRoles = await this.fetchRolesOnUser(this.user.email)\n } else {\n this.userRoles = []\n }\n }\n }\n\n async fetchRolesOnUser(email) {\n const response = await client.query({\n query: gql`\n query ($email: EmailAddress!) {\n user(email: $email) {\n id\n name\n email\n roles {\n id\n name\n description\n domain {\n id\n }\n }\n }\n }\n `,\n variables: { email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n return response.data.user?.roles || []\n }\n }\n\n async fetchAvailableRoles() {\n const response = await client.query({\n query: gql`\n query roles($inherited: InheritedValueType) {\n roles(inherited: $inherited) {\n items {\n id\n domain {\n name\n }\n name\n description\n }\n total\n }\n grantedRoles {\n id\n role {\n id\n name\n description\n domain {\n name\n }\n }\n }\n }\n `,\n variables: {\n inherited: InheritedValueType.Include\n },\n context: gqlContext()\n })\n\n if (!response.errors?.length) {\n this.domainRoles = response.data.roles.items || []\n this.grantedRoles = response.data.grantedRoles.reduce((grantedRoles, grantedRole) => {\n const { role } = grantedRole\n const { domain } = role\n if (grantedRoles[domain.name]) {\n grantedRoles[domain.name].push(role)\n } else {\n grantedRoles[domain.name] = [role]\n }\n\n return grantedRoles\n }, {})\n } else {\n this.domainRoles = []\n this.grantedRoles = []\n }\n }\n\n async onSave(user, availableRoles, selectedRoles) {\n if (user?.id) {\n const response = await client.mutate({\n mutation: gql`\n mutation ($username: String!, $availableRoles: [ObjectRef!]!, $selectedRoles: [ObjectRef!]!) {\n updateUserRoles(username: $username, availableRoles: $availableRoles, selectedRoles: $selectedRoles) {\n id\n name\n roles {\n id\n description\n }\n }\n }\n `,\n variables: { username: user.username || user.email, availableRoles, selectedRoles },\n context: gqlContext()\n })\n\n if (!response.errors) {\n this.showToast(i18next.t('text.data_updated_successfully'))\n this.dispatchUserUpdated()\n }\n }\n }\n\n async onActivate(user) {\n const response = await client.mutate({\n mutation: gql`\n mutation activateUser($username: String!) {\n activateUser(username: $username)\n }\n `,\n variables: { username: user.username || user.email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n this.showToast(i18next.t('text.user activated successfully'))\n\n this.dispatchUserUpdated()\n }\n }\n\n async onInactivate(user) {\n const response = await client.mutate({\n mutation: gql`\n mutation inactivateUser($username: String!) {\n inactivateUser(username: $username)\n }\n `,\n variables: { username: user.username || user.email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n this.showToast(i18next.t('text.user inactivated successfully'))\n\n this.dispatchUserUpdated()\n }\n }\n\n async onDelete(user) {\n if (user.owner) {\n await OxPrompt.open({\n type: 'warning',\n title: i18next.t('text.cannot_delete'),\n text: i18next.t('text.x_cannot_delete', {\n x: i18next.t('label.domain-owner')\n }),\n confirmButton: { text: i18next.t('button.confirm') }\n })\n\n return\n }\n\n if (\n await OxPrompt.open({\n title: i18next.t('text.are_you_sure'),\n text: i18next.t('text.are_you_sure_to_x_user', {\n x: i18next.t('button.delete')\n }),\n confirmButton: { text: i18next.t('button.delete') },\n cancelButton: { text: i18next.t('button.cancel') }\n })\n ) {\n const response = await client.mutate({\n mutation: gql`\n mutation deleteDomaineUser($username: String!) {\n deleteDomainUser(username: $username)\n }\n `,\n variables: { username: user.username || user.email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n await OxPrompt.open({\n type: 'success',\n title: i18next.t('text.completed'),\n confirmButton: { text: i18next.t('button.confirm') }\n })\n\n this.dispatchUserUpdated()\n }\n }\n }\n\n async onTransfer(user) {\n openPopup(\n html`\n <ownership-transfer-popup\n .user=${user}\n @ownershipTransferred=\"${this.dispatchOwnershipTransferred.bind(this)}\"\n ></ownership-transfer-popup>\n `,\n {\n size: 'small',\n title: `${i18next.t('title.owner_transfer')}`\n }\n )\n }\n\n async onResetPassword(user) {\n if (\n await OxPrompt.open({\n title: i18next.t('text.are_you_sure'),\n text: i18next.t('text.are_you_sure_to_x', { x: i18next.t('title.reset password') }),\n confirmButton: { text: i18next.t('button.confirm') },\n cancelButton: { text: i18next.t('button.cancel') }\n })\n ) {\n const response = await client.mutate({\n mutation: gql`\n mutation resetPasswordToDefault($username: String!) {\n resetPasswordToDefault(username: $username)\n }\n `,\n variables: { username: user.username || user.email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n await OxPrompt.open({\n type: 'success',\n title: i18next.t('text.completed'),\n text: i18next.t('text.password reset succeed'),\n confirmButton: { text: i18next.t('button.confirm') }\n })\n }\n }\n }\n\n dispatchUserUpdated() {\n this.dispatchEvent(new CustomEvent('userUpdated'))\n }\n\n dispatchOwnershipTransferred() {\n this.dispatchEvent(new CustomEvent('ownershipTransferred'))\n }\n\n showToast(message) {\n document.dispatchEvent(new CustomEvent('notify', { detail: { message, option: { timer: 1000 } } }))\n }\n\n private _unsubscribe?: () => void\n\n\n connectedCallback() {\n\n super.connectedCallback()\n\n this._applyState()\n\n this._unsubscribe = store.subscribe(() => this._applyState())\n\n }\n\n\n disconnectedCallback() {\n\n super.disconnectedCallback()\n\n this._unsubscribe?.()\n\n }\n\n\n private _applyState() {\n\n const __state__ = store.getState() as any\nthis.me = __state__.auth?.user || {}\n this.isSuperOwner = this.me.super || false\n this.isDomainOwner = this.me.email === this.domainOwner.email || false\n\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"user-role-editor.js","sourceRoot":"","sources":["../../client/components/user-role-editor.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,yCAAyC,CAAA;AAEhD,OAAO,+BAA+B,CAAA;AACtC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAEvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAGxD,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,UAAU;IAAvC;;QAiE8B,SAAI,GAAQ,EAAE,CAAA;QACb,aAAQ,GAAY,KAAK,CAAA;QAG7C,gBAAW,GAAU,EAAE,CAAA;QACvB,iBAAY,GAAQ,EAAE,CAAA;QACtB,cAAS,GAAU,EAAE,CAAA;QACrB,iBAAY,GAAY,KAAK,CAAA;QAC7B,kBAAa,GAAY,KAAK,CAAA;IAmZzC,CAAC;aA3dQ,WAAM,GAAG;QACd,qBAAqB;QACrB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2DF;KACF,AA9DY,CA8DZ;IAcD,MAAM;QACJ,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAA;QAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,EAAE,CAAA;QAC5C,IAAI,iBAAiB,GAAG,OAAO,CAAA;QAC/B,IAAI,WAAW,EAAE,MAAM,EAAE,CAAC;YACxB,iBAAiB,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAA;QAChD,CAAC;QAED,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,QAAQ;YACb,CAAC,CAAC,IAAI,CAAA;;gBAEE,IAAI,CAAC,QAAQ,KAAK,MAAM;gBACxB,CAAC,CAAC,IAAI,CAAA;;;0BAGI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK;0BAC3B,IAAI,CAAC,KAAK;;;mBAGjB;gBACH,CAAC,CAAC,EAAE;;;mCAGe,IAAI,CAAC,IAAI,WAAW,WAAW,eAAe,IAAI,CAAC,SAAS;;cAEjF,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,CAC7B,WAAW,CAAC,EAAE,CAAC,IAAI,CAAA;;kCAEC,WAAW;0BACnB,IAAI,CAAC,IAAI;2BACR,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC;+BAC1B,IAAI,CAAC,SAAS;;;eAG9B,CACF;WACF;YACH,CAAC,CAAC,EAAE;;;UAGF,IAAI,CAAC,cAAc,EAAE;YACrB,CAAC,CAAC,IAAI,CAAA;uBACO,GAAG,EAAE;gBACZ,sDAAsD;gBACtD,qCAAqC;gBACrC,0DAA0D;gBAC1D,iDAAiD;gBACjD,MAAM,KAAK,GAAG,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;gBACxC,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC,IAAI,CAClD,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,eAAe,CAA6B,CAC9E,CAAC,MAAM,CACN,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE;oBACtB,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAChD,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAC9B,CAAA;oBACD,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC,MAAM,CAC9C,YAAY,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CACxC,CAAA;oBACD,OAAO,KAAK,CAAA;gBACd,CAAC,EACD,EAAE,cAAc,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAqD,CAC7F,CAAA;gBACD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,aAAa,CAAC,CAAA;YAClD,CAAC;iBACE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;cACnC;YACJ,CAAC,CAAC,EAAE;UACJ,IAAI,CAAC,QAAQ,KAAK,MAAM;YACxB,CAAC,CAAC,IAAI,CAAA;gBACA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;gBACxE,CAAC,CAAC,IAAI,CAAA;wDACkC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;yBAC1D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC;;mBAEhD;gBACH,CAAC,CAAC,EAAE;gBACJ,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC;gBAC/B,CAAC,CAAC,IAAI,CAAA,qCAAqC,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;uBACpE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC;oBAClD;gBACJ,CAAC,CAAC,EAAE;aACP;YACH,CAAC,CAAC,EAAE;UACJ,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YACtB,CAAC,CAAC,IAAI,CAAA;kDACkC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;mBACxD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;;aAE7C;YACH,CAAC,CAAC,EAAE;UACJ,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YACxB,CAAC,CAAC,IAAI,CAAA,qCAAqC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;iBAC/D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;cACvC;YACJ,CAAC,CAAC,EAAE;UACJ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YAC1B,CAAC,CAAC,IAAI,CAAA,qCAAqC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;iBACjE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;cACzC;YACJ,CAAC,CAAC,EAAE;;KAET,CAAA;IACH,CAAC;IAED,WAAW,CAAC,IAAI;QACd,OAAO,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,CAAA;IAC1E,CAAC;IAED,cAAc,CAAC,IAAI;QACjB,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAA;IAClF,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;IACnG,CAAC;IAED,oBAAoB,CAAC,IAAI;QACvB,OAAO,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC,KAAK,CAAA;IAClF,CAAC;IAED,aAAa,CAAC,IAAI;QAChB,OAAO,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAA;IACpE,CAAC;IAED,eAAe,CAAC,IAAI;QAClB,OAAO,CACL,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,CAAC;YACzC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,WAAW,CAAC,EAAE;YAC/B,IAAI,CAAC,QAAQ,KAAK,OAAO;YACzB,IAAI,CAAC,QAAQ,CACd,CAAA;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,YAAY;QACxB,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,mBAAmB,EAAE,CAAA;YAE1B,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;gBACrB,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAC/D,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,KAAK;QAC1B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;OAgBT;YACD,SAAS,EAAE,EAAE,KAAK,EAAE;YACpB,OAAO,EAAE,UAAU,EAAE;SACtB,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAA;QACxC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;OAyBT;YACD,SAAS,EAAE;gBACT,SAAS,EAAE,kBAAkB,CAAC,OAAO;aACtC;YACD,OAAO,EAAE,UAAU,EAAE;SACtB,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YAC7B,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAA;YAClD,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;gBAClF,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,CAAA;gBAC5B,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;gBACvB,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC9B,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACtC,CAAC;qBAAM,CAAC;oBACN,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBACpC,CAAC;gBAED,OAAO,YAAY,CAAA;YACrB,CAAC,EAAE,EAAE,CAAC,CAAA;QACR,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,WAAW,GAAG,EAAE,CAAA;YACrB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAA;QACxB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,aAAa;QAC9C,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;gBACnC,QAAQ,EAAE,GAAG,CAAA;;;;;;;;;;;SAWZ;gBACD,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE;gBACnF,OAAO,EAAE,UAAU,EAAE;aACtB,CAAC,CAAA;YAEF,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACrB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAA;gBAC3D,IAAI,CAAC,mBAAmB,EAAE,CAAA;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAI;QACnB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;YACnC,QAAQ,EAAE,GAAG,CAAA;;;;OAIZ;YACD,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE;YACpD,OAAO,EAAE,UAAU,EAAE;SACtB,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAA;YAE7D,IAAI,CAAC,mBAAmB,EAAE,CAAA;QAC5B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAI;QACrB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;YACnC,QAAQ,EAAE,GAAG,CAAA;;;;OAIZ;YACD,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE;YACpD,OAAO,EAAE,UAAU,EAAE;SACtB,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAA;YAE/D,IAAI,CAAC,mBAAmB,EAAE,CAAA;QAC5B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAI;QACjB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,QAAQ,CAAC,IAAI,CAAC;gBAClB,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC;gBACtC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,sBAAsB,EAAE;oBACtC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC;iBACnC,CAAC;gBACF,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE;aACrD,CAAC,CAAA;YAEF,OAAM;QACR,CAAC;QAED,IACE,MAAM,QAAQ,CAAC,IAAI,CAAC;YAClB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;YACrC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,6BAA6B,EAAE;gBAC7C,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;aAC9B,CAAC;YACF,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE;YACnD,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE;SACnD,CAAC,EACF,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;gBACnC,QAAQ,EAAE,GAAG,CAAA;;;;SAIZ;gBACD,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE;gBACpD,OAAO,EAAE,UAAU,EAAE;aACtB,CAAC,CAAA;YAEF,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACrB,MAAM,QAAQ,CAAC,IAAI,CAAC;oBAClB,IAAI,EAAE,SAAS;oBACf,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;oBAClC,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE;iBACrD,CAAC,CAAA;gBAEF,IAAI,CAAC,mBAAmB,EAAE,CAAA;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAI;QACnB,SAAS,CACP,IAAI,CAAA;;kBAEQ,IAAI;mCACa,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC;;OAExE,EACD;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,EAAE;SAC9C,CACF,CAAA;IACH,CAAC;IAED,uGAAuG;IACvG,eAAe,CAAC,IAAI;QAClB,qBAAqB,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAA;IAC7E,CAAC;IAED,mBAAmB;QACjB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IACpD,CAAC;IAED,4BAA4B;QAC1B,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAAA;IAC7D,CAAC;IAED,SAAS,CAAC,OAAO;QACf,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IACrG,CAAC;IAKD,iBAAiB;QAEf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB,IAAI,CAAC,WAAW,EAAE,CAAA;QAElB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;IAE/D,CAAC;IAGD,oBAAoB;QAElB,KAAK,CAAC,oBAAoB,EAAE,CAAA;QAE5B,IAAI,CAAC,YAAY,EAAE,EAAE,CAAA;IAEvB,CAAC;IAGO,WAAW;QAEjB,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAS,CAAA;QAC7C,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAA;QAChC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,KAAK,CAAA;QAC1C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,KAAK,CAAA;IAExE,CAAC;;AA1Z2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;4CAAe;AACb;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;;gDAA0B;AAC1B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mDAAiB;AAEnC;IAAR,KAAK,EAAE;;mDAAwB;AACvB;IAAR,KAAK,EAAE;;oDAAuB;AACtB;IAAR,KAAK,EAAE;;iDAAsB;AACrB;IAAR,KAAK,EAAE;;oDAA8B;AAC7B;IAAR,KAAK,EAAE;;qDAA+B;AAzEnC,cAAc;IADnB,aAAa,CAAC,kBAAkB,CAAC;GAC5B,cAAc,CA4dnB","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\n\nimport './ownership-transfer-popup.js'\nimport './role-selector.js'\nimport { openPasswordSetupLink } from './password-setup-link-popup.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { client, gqlContext } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { openPopup } from '@operato/layout'\nimport { store } from '@operato/shell'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { ButtonContainerStyles } from '@operato/styles'\nimport { RoleSelector } from './role-selector.js'\nimport { InheritedValueType } from '@operato/data-grist'\n\n@customElement('user-role-editor')\nclass UserRoleEditor extends LitElement {\n static styles = [\n ButtonContainerStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n\n border: 1px solid var(--md-sys-color-primary);\n font: normal 15px var(--theme-font);\n color: var(--md-sys-color-secondary);\n }\n ul {\n flex: 1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n column-gap: 20px;\n\n overflow: auto;\n margin: 0;\n padding: var(--spacing-medium);\n list-style: none;\n border: 1px dashed rgba(0, 0, 0, 0.1);\n border-width: 1px 0;\n }\n input[readonly] {\n border: none;\n background-color: transparent;\n color: var(--md-sys-color-secondary);\n font: var(--input-font);\n }\n li {\n padding: var(--spacing-small);\n }\n [detail] {\n background-color: var(--md-sys-color-surface);\n }\n [detail] md-icon {\n --md-icon-size: var(--fontsize-default);\n vertical-align: middle;\n color: var(--md-sys-color-primary);\n }\n [detail] li {\n display: flex;\n }\n [detail] li input {\n flex: 1;\n }\n\n md-elevated-button {\n margin: 5px;\n }\n\n md-outlined-button {\n background-color: var(--md-sys-color-surface-variant);\n }\n\n @media screen and (max-width: 480px) {\n ul {\n grid-template-columns: 1fr;\n }\n }\n `\n ]\n\n @property({ type: Object }) user: any = {}\n @property({ type: Boolean }) activate: boolean = false\n @property({ type: Object }) domainOwner: any\n\n @state() domainRoles: any[] = []\n @state() grantedRoles: any = {}\n @state() userRoles: any[] = []\n @state() isSuperOwner: boolean = false\n @state() isDomainOwner: boolean = false\n\n private me: any\n\n render() {\n const user = this.user || {}\n const domainRoles = this.domainRoles || []\n const grantedRoles = this.grantedRoles || {}\n let currentDomainName = 'roles'\n if (domainRoles?.length) {\n currentDomainName = domainRoles[0].domain.name\n }\n\n return html`\n ${this.activate\n ? html`\n <ul detail>\n ${user.userType === 'user'\n ? html`\n <li>\n <span>\n ${user.username || user.email} (<md-icon>email</md-icon>\n ${user.email})\n </span>\n </li>\n `\n : ''}\n </ul>\n\n <role-selector .user=${this.user} .roles=${domainRoles} .userRoles=${this.userRoles}></role-selector>\n\n ${Object.keys(grantedRoles).map(\n partnerName => html`\n <role-selector\n .roleCategory=${partnerName}\n .user=${this.user}\n .roles=${this.grantedRoles[partnerName]}\n .userRoles=${this.userRoles}\n >\n </role-selector>\n `\n )}\n `\n : ''}\n\n <div class=\"button-container\">\n ${this.isRoleEditable()\n ? html` <md-elevated-button\n @click=${() => {\n // GraphQL 의 ObjectRef 타입은 { id } 만 받음. Apollo 가 query\n // 결과에 자동으로 붙이는 __typename 이 그대로 들어가면\n // \"Field __typename is not defined by type ObjectRef\" 에러.\n // 원본 객체를 mutate (delete) 하지 않고 { id } 만 추려서 넘긴다.\n const toRef = (r: any) => ({ id: r.id })\n const { availableRoles, selectedRoles } = Array.from(\n this.renderRoot.querySelectorAll('role-selector') as NodeListOf<RoleSelector>\n ).reduce(\n (roles, roleSelector) => {\n roles.availableRoles = roles.availableRoles.concat(\n roleSelector.roles.map(toRef)\n )\n roles.selectedRoles = roles.selectedRoles.concat(\n roleSelector.selectedRoles().map(toRef)\n )\n return roles\n },\n { availableRoles: [], selectedRoles: [] } as { availableRoles: any[]; selectedRoles: any[] }\n )\n this.onSave(user, availableRoles, selectedRoles)\n }}\n >${String(i18next.t('button.save'))}</md-elevated-button\n >`\n : ''}\n ${user.userType === 'user'\n ? html`\n ${this.isTransferable(user) && this.userRoles && this.userRoles.length > 0\n ? html`\n <md-elevated-button danger @click=${() => this.onTransfer(user)}\n >${String(i18next.t('button.transfer owner'))}</md-elevated-button\n >\n `\n : ''}\n ${this.isPasswordResettable(user)\n ? html`<md-elevated-button danger @click=${() => this.onResetPassword(user)}\n >${String(i18next.t('button.password reset link'))}</md-elevated-button\n >`\n : ''}\n `\n : ''}\n ${this.isRemovable(user)\n ? html`\n <md-elevated-button danger @click=${() => this.onDelete(user)}\n >${String(i18next.t('button.delete user'))}</md-elevated-button\n >\n `\n : ''}\n ${this.isActivatable(user)\n ? html`<md-elevated-button danger @click=${() => this.onActivate(user)}\n >${String(i18next.t('button.activate'))}</md-elevated-button\n >`\n : ''}\n ${this.isInactivatable(user)\n ? html`<md-elevated-button danger @click=${() => this.onInactivate(user)}\n >${String(i18next.t('button.deactivate'))}</md-elevated-button\n >`\n : ''}\n </div>\n `\n }\n\n isRemovable(user) {\n return this.isDomainOwner && user.email !== this.me.email && !user.owner\n }\n\n isTransferable(user) {\n return this.activate && (this.isSuperOwner || this.isDomainOwner) && !user.owner\n }\n\n isRoleEditable() {\n return this.activate && (this.domainRoles?.length || Object.keys(this.grantedRoles || {}).length)\n }\n\n isPasswordResettable(user) {\n return (this.isSuperOwner || this.isDomainOwner) && user.email !== this.me.email\n }\n\n isActivatable(user) {\n return (this.isSuperOwner || this.isDomainOwner) && !this.activate\n }\n\n isInactivatable(user) {\n return (\n (this.isSuperOwner || this.isDomainOwner) &&\n user.id !== this.domainOwner.id &&\n user.userType !== 'admin' &&\n this.activate\n )\n }\n\n async updated(changedProps) {\n if (changedProps.has('user')) {\n this.fetchAvailableRoles()\n\n if (this.user?.email) {\n this.userRoles = await this.fetchRolesOnUser(this.user.email)\n } else {\n this.userRoles = []\n }\n }\n }\n\n async fetchRolesOnUser(email) {\n const response = await client.query({\n query: gql`\n query ($email: EmailAddress!) {\n user(email: $email) {\n id\n name\n email\n roles {\n id\n name\n description\n domain {\n id\n }\n }\n }\n }\n `,\n variables: { email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n return response.data.user?.roles || []\n }\n }\n\n async fetchAvailableRoles() {\n const response = await client.query({\n query: gql`\n query roles($inherited: InheritedValueType) {\n roles(inherited: $inherited) {\n items {\n id\n domain {\n name\n }\n name\n description\n }\n total\n }\n grantedRoles {\n id\n role {\n id\n name\n description\n domain {\n name\n }\n }\n }\n }\n `,\n variables: {\n inherited: InheritedValueType.Include\n },\n context: gqlContext()\n })\n\n if (!response.errors?.length) {\n this.domainRoles = response.data.roles.items || []\n this.grantedRoles = response.data.grantedRoles.reduce((grantedRoles, grantedRole) => {\n const { role } = grantedRole\n const { domain } = role\n if (grantedRoles[domain.name]) {\n grantedRoles[domain.name].push(role)\n } else {\n grantedRoles[domain.name] = [role]\n }\n\n return grantedRoles\n }, {})\n } else {\n this.domainRoles = []\n this.grantedRoles = []\n }\n }\n\n async onSave(user, availableRoles, selectedRoles) {\n if (user?.id) {\n const response = await client.mutate({\n mutation: gql`\n mutation ($username: String!, $availableRoles: [ObjectRef!]!, $selectedRoles: [ObjectRef!]!) {\n updateUserRoles(username: $username, availableRoles: $availableRoles, selectedRoles: $selectedRoles) {\n id\n name\n roles {\n id\n description\n }\n }\n }\n `,\n variables: { username: user.username || user.email, availableRoles, selectedRoles },\n context: gqlContext()\n })\n\n if (!response.errors) {\n this.showToast(i18next.t('text.data_updated_successfully'))\n this.dispatchUserUpdated()\n }\n }\n }\n\n async onActivate(user) {\n const response = await client.mutate({\n mutation: gql`\n mutation activateUser($username: String!) {\n activateUser(username: $username)\n }\n `,\n variables: { username: user.username || user.email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n this.showToast(i18next.t('text.user activated successfully'))\n\n this.dispatchUserUpdated()\n }\n }\n\n async onInactivate(user) {\n const response = await client.mutate({\n mutation: gql`\n mutation inactivateUser($username: String!) {\n inactivateUser(username: $username)\n }\n `,\n variables: { username: user.username || user.email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n this.showToast(i18next.t('text.user inactivated successfully'))\n\n this.dispatchUserUpdated()\n }\n }\n\n async onDelete(user) {\n if (user.owner) {\n await OxPrompt.open({\n type: 'warning',\n title: i18next.t('text.cannot_delete'),\n text: i18next.t('text.x_cannot_delete', {\n x: i18next.t('label.domain-owner')\n }),\n confirmButton: { text: i18next.t('button.confirm') }\n })\n\n return\n }\n\n if (\n await OxPrompt.open({\n title: i18next.t('text.are_you_sure'),\n text: i18next.t('text.are_you_sure_to_x_user', {\n x: i18next.t('button.delete')\n }),\n confirmButton: { text: i18next.t('button.delete') },\n cancelButton: { text: i18next.t('button.cancel') }\n })\n ) {\n const response = await client.mutate({\n mutation: gql`\n mutation deleteDomaineUser($username: String!) {\n deleteDomainUser(username: $username)\n }\n `,\n variables: { username: user.username || user.email },\n context: gqlContext()\n })\n\n if (!response.errors) {\n await OxPrompt.open({\n type: 'success',\n title: i18next.t('text.completed'),\n confirmButton: { text: i18next.t('button.confirm') }\n })\n\n this.dispatchUserUpdated()\n }\n }\n }\n\n async onTransfer(user) {\n openPopup(\n html`\n <ownership-transfer-popup\n .user=${user}\n @ownershipTransferred=\"${this.dispatchOwnershipTransferred.bind(this)}\"\n ></ownership-transfer-popup>\n `,\n {\n size: 'small',\n title: `${i18next.t('title.owner_transfer')}`\n }\n )\n }\n\n /* An administrator never sets the password - the person sets it through a one-time link (ADR-0161). */\n onResetPassword(user) {\n openPasswordSetupLink(user, { onIssued: () => this.dispatchUserUpdated() })\n }\n\n dispatchUserUpdated() {\n this.dispatchEvent(new CustomEvent('userUpdated'))\n }\n\n dispatchOwnershipTransferred() {\n this.dispatchEvent(new CustomEvent('ownershipTransferred'))\n }\n\n showToast(message) {\n document.dispatchEvent(new CustomEvent('notify', { detail: { message, option: { timer: 1000 } } }))\n }\n\n private _unsubscribe?: () => void\n\n\n connectedCallback() {\n\n super.connectedCallback()\n\n this._applyState()\n\n this._unsubscribe = store.subscribe(() => this._applyState())\n\n }\n\n\n disconnectedCallback() {\n\n super.disconnectedCallback()\n\n this._unsubscribe?.()\n\n }\n\n\n private _applyState() {\n\n const __state__ = store.getState() as any\nthis.me = __state__.auth?.user || {}\n this.isSuperOwner = this.me.super || false\n this.isDomainOwner = this.me.email === this.domainOwner.email || false\n\n }\n}\n"]}
|
|
@@ -19,6 +19,10 @@ export function statusRenderer(durationMinutes) {
|
|
|
19
19
|
if (value === 'inactive') {
|
|
20
20
|
return html `<auth-badge tone="quiet">${i18next.t('label.inactive-user')}</auth-badge>`;
|
|
21
21
|
}
|
|
22
|
+
/* Made, or its password taken back, and waiting for its person to set one through the setup link (ADR-0161). */
|
|
23
|
+
if (value === 'password_reset_required') {
|
|
24
|
+
return html `<auth-badge tone="quiet">${i18next.t('label.password-setup-pending-user')}</auth-badge>`;
|
|
25
|
+
}
|
|
22
26
|
/* 활성은 기본값이다 — 색을 쓰지 않는다. 색은 「무엇이 나를 기다리나」에만 쓴다. */
|
|
23
27
|
return html `<auth-badge>${i18next.t('label.activated-user', { defaultValue: value })}</auth-badge>`;
|
|
24
28
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-status-renderer.js","sourceRoot":"","sources":["../../client/components/user-status-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,CAAA;AAExB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AAEnC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,8FAA8F;AAE9F;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,eAA6B;IAC1D,OAAO,CAAC,KAAa,EAAE,OAAY,EAAE,MAAW,EAAE,EAAE;QAClD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvB,OAAO,IAAI,CAAA;WACN,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;QACvE,CAAA;QACJ,CAAC;QAED,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;YACzB,OAAO,IAAI,CAAA,4BAA4B,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,eAAe,CAAA;QACxF,CAAC;QAED,mDAAmD;QACnD,OAAO,IAAI,CAAA,eAAe,OAAO,CAAC,CAAC,CAAC,sBAAsB,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,eAAe,CAAA;IACrG,CAAC,CAAA;AACH,CAAC;AAED,+CAA+C;AAC/C,SAAS,QAAQ,CAAC,MAAW,EAAE,OAAe;IAC5C,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;IAE7E,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;QAC7C,wDAAwD;QACxD,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,GAAG,OAAO,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,CAAA;IAE7E,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,MAAM,OAAO,CAAC,CAAC,CAAC,2BAA2B,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;AAC7F,CAAC","sourcesContent":["import './auth-badge.js'\n\nimport { html, nothing } from 'lit'\n\nimport { i18next } from '@operato/i18n'\n\n/* An account's state as a badge - the user list and the audit screen draw it the same way. */\n\n/**\n * 잠긴 계정이 **언제 풀리는지**까지 말한다.\n *\n * 판정은 서버(`account-lock-rule.ts`)가 하고 여기서는 남은 시간만 보여 준다 —\n * 화면이 판정을 다시 하면 두 곳이 다른 답을 낸다. `lockedAt` 이 비어 있으면 자동 해제가\n * 없다는 뜻이므로 남은 시간을 말하지 않는다.\n */\nexport function statusRenderer(durationMinutes: () => number) {\n return (value: string, _column: any, record: any) => {\n if (value === 'locked') {\n return html`<auth-badge tone=\"attention\"\n >${i18next.t('label.locked-user')}${lockLeft(record, durationMinutes())}</auth-badge\n >`\n }\n\n if (value === 'inactive') {\n return html`<auth-badge tone=\"quiet\">${i18next.t('label.inactive-user')}</auth-badge>`\n }\n\n /* 활성은 기본값이다 — 색을 쓰지 않는다. 색은 「무엇이 나를 기다리나」에만 쓴다. */\n return html`<auth-badge>${i18next.t('label.activated-user', { defaultValue: value })}</auth-badge>`\n }\n}\n\n/** 잠금이 언제 풀리는지. 판정은 서버가 하고 여기서는 남은 시간만 말한다. */\nfunction lockLeft(record: any, minutes: number) {\n const lockedAt = record?.lockedAt ? new Date(record.lockedAt).getTime() : NaN\n\n if (Number.isNaN(lockedAt) || !(minutes > 0)) {\n /* `lockedAt` 이 없으면 자동 해제가 없다는 뜻이다 — 남은 시간을 지어내지 않는다. */\n return nothing\n }\n\n const left = Math.ceil((lockedAt + minutes * 60 * 1000 - Date.now()) / 60000)\n\n return left > 0 ? html` · ${i18next.t('text.unlocks in x minutes', { x: left })}` : nothing\n}\n"]}
|
|
1
|
+
{"version":3,"file":"user-status-renderer.js","sourceRoot":"","sources":["../../client/components/user-status-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,CAAA;AAExB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AAEnC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,8FAA8F;AAE9F;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,eAA6B;IAC1D,OAAO,CAAC,KAAa,EAAE,OAAY,EAAE,MAAW,EAAE,EAAE;QAClD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvB,OAAO,IAAI,CAAA;WACN,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;QACvE,CAAA;QACJ,CAAC;QAED,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;YACzB,OAAO,IAAI,CAAA,4BAA4B,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,eAAe,CAAA;QACxF,CAAC;QAED,gHAAgH;QAChH,IAAI,KAAK,KAAK,yBAAyB,EAAE,CAAC;YACxC,OAAO,IAAI,CAAA,4BAA4B,OAAO,CAAC,CAAC,CAAC,mCAAmC,CAAC,eAAe,CAAA;QACtG,CAAC;QAED,mDAAmD;QACnD,OAAO,IAAI,CAAA,eAAe,OAAO,CAAC,CAAC,CAAC,sBAAsB,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,eAAe,CAAA;IACrG,CAAC,CAAA;AACH,CAAC;AAED,+CAA+C;AAC/C,SAAS,QAAQ,CAAC,MAAW,EAAE,OAAe;IAC5C,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;IAE7E,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;QAC7C,wDAAwD;QACxD,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,GAAG,OAAO,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,CAAA;IAE7E,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,MAAM,OAAO,CAAC,CAAC,CAAC,2BAA2B,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;AAC7F,CAAC","sourcesContent":["import './auth-badge.js'\n\nimport { html, nothing } from 'lit'\n\nimport { i18next } from '@operato/i18n'\n\n/* An account's state as a badge - the user list and the audit screen draw it the same way. */\n\n/**\n * 잠긴 계정이 **언제 풀리는지**까지 말한다.\n *\n * 판정은 서버(`account-lock-rule.ts`)가 하고 여기서는 남은 시간만 보여 준다 —\n * 화면이 판정을 다시 하면 두 곳이 다른 답을 낸다. `lockedAt` 이 비어 있으면 자동 해제가\n * 없다는 뜻이므로 남은 시간을 말하지 않는다.\n */\nexport function statusRenderer(durationMinutes: () => number) {\n return (value: string, _column: any, record: any) => {\n if (value === 'locked') {\n return html`<auth-badge tone=\"attention\"\n >${i18next.t('label.locked-user')}${lockLeft(record, durationMinutes())}</auth-badge\n >`\n }\n\n if (value === 'inactive') {\n return html`<auth-badge tone=\"quiet\">${i18next.t('label.inactive-user')}</auth-badge>`\n }\n\n /* Made, or its password taken back, and waiting for its person to set one through the setup link (ADR-0161). */\n if (value === 'password_reset_required') {\n return html`<auth-badge tone=\"quiet\">${i18next.t('label.password-setup-pending-user')}</auth-badge>`\n }\n\n /* 활성은 기본값이다 — 색을 쓰지 않는다. 색은 「무엇이 나를 기다리나」에만 쓴다. */\n return html`<auth-badge>${i18next.t('label.activated-user', { defaultValue: value })}</auth-badge>`\n }\n}\n\n/** 잠금이 언제 풀리는지. 판정은 서버가 하고 여기서는 남은 시간만 말한다. */\nfunction lockLeft(record: any, minutes: number) {\n const lockedAt = record?.lockedAt ? new Date(record.lockedAt).getTime() : NaN\n\n if (Number.isNaN(lockedAt) || !(minutes > 0)) {\n /* `lockedAt` 이 없으면 자동 해제가 없다는 뜻이다 — 남은 시간을 지어내지 않는다. */\n return nothing\n }\n\n const left = Math.ceil((lockedAt + minutes * 60 * 1000 - Date.now()) / 60000)\n\n return left > 0 ? html` · ${i18next.t('text.unlocks in x minutes', { x: left })}` : nothing\n}\n"]}
|
|
@@ -11,8 +11,12 @@ let ResetPassword = class ResetPassword extends AbstractPasswordReset {
|
|
|
11
11
|
get submitButtonLabel() {
|
|
12
12
|
return 'label.change password';
|
|
13
13
|
}
|
|
14
|
+
/* A forgotten password and an administrator's setup link both arrive here (ADR-0161) - the title says what it does. */
|
|
14
15
|
get title() {
|
|
15
|
-
return '
|
|
16
|
+
return 'set a new password';
|
|
17
|
+
}
|
|
18
|
+
get asksEmail() {
|
|
19
|
+
return true;
|
|
16
20
|
}
|
|
17
21
|
};
|
|
18
22
|
ResetPassword = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reset-password.js","sourceRoot":"","sources":["../../../client/entries/auth/reset-password.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAA;AAG5E,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,qBAAqB;IACtD,IAAI,QAAQ;QACV,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,IAAI,SAAS;QACX,OAAO,sBAAsB,CAAA;IAC/B,CAAC;IAED,IAAI,iBAAiB;QACnB,OAAO,uBAAuB,CAAA;IAChC,CAAC;IAED,IAAI,KAAK;QACP,OAAO,
|
|
1
|
+
{"version":3,"file":"reset-password.js","sourceRoot":"","sources":["../../../client/entries/auth/reset-password.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAA;AAG5E,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,qBAAqB;IACtD,IAAI,QAAQ;QACV,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,IAAI,SAAS;QACX,OAAO,sBAAsB,CAAA;IAC/B,CAAC;IAED,IAAI,iBAAiB;QACnB,OAAO,uBAAuB,CAAA;IAChC,CAAC;IAED,uHAAuH;IACvH,IAAI,KAAK;QACP,OAAO,oBAAoB,CAAA;IAC7B,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAA;IACb,CAAC;CACF,CAAA;AArBY,aAAa;IADzB,aAAa,CAAC,gBAAgB,CAAC;GACnB,aAAa,CAqBzB","sourcesContent":["import { customElement } from 'lit/decorators.js'\n\nimport { AbstractPasswordReset } from '../../components/abstract-password-reset.js'\n\n@customElement('reset-password')\nexport class ResetPassword extends AbstractPasswordReset {\n get pageName() {\n return 'reset password'\n }\n\n get actionUrl() {\n return '/auth/reset-password'\n }\n\n get submitButtonLabel() {\n return 'label.change password'\n }\n\n /* A forgotten password and an administrator's setup link both arrive here (ADR-0161) - the title says what it does. */\n get title() {\n return 'set a new password'\n }\n\n get asksEmail() {\n return true\n }\n}\n"]}
|
package/dist-client/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js';
|
|
2
2
|
import '@operato/i18n/ox-i18n.js';
|
|
3
3
|
import { html } from 'lit-html';
|
|
4
|
-
import {
|
|
4
|
+
import { store } from '@operato/shell';
|
|
5
5
|
import { ADD_MORENDA } from '@things-factory/more-base/client';
|
|
6
6
|
import { hasPrivilege } from '@things-factory/auth-base/dist-client';
|
|
7
7
|
export * from './components/role-selector.js';
|
|
@@ -16,9 +16,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
16
16
|
morenda: {
|
|
17
17
|
icon: html ` <md-icon>how_to_reg</md-icon> `,
|
|
18
18
|
name: html ` <ox-i18n msgid="text.role_management"></ox-i18n> `,
|
|
19
|
-
|
|
20
|
-
navigate('roles');
|
|
21
|
-
}
|
|
19
|
+
page: 'roles'
|
|
22
20
|
}
|
|
23
21
|
});
|
|
24
22
|
appliance &&
|
|
@@ -27,9 +25,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
27
25
|
morenda: {
|
|
28
26
|
icon: html ` <md-icon>devices</md-icon> `,
|
|
29
27
|
name: html ` <ox-i18n msgid="text.appliance"></ox-i18n> `,
|
|
30
|
-
|
|
31
|
-
navigate('appliance-home');
|
|
32
|
-
}
|
|
28
|
+
page: 'appliance-home'
|
|
33
29
|
}
|
|
34
30
|
});
|
|
35
31
|
application &&
|
|
@@ -38,9 +34,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
38
34
|
morenda: {
|
|
39
35
|
icon: html ` <md-icon>apps</md-icon> `,
|
|
40
36
|
name: html ` <ox-i18n msgid="text.application management"></ox-i18n> `,
|
|
41
|
-
|
|
42
|
-
navigate('applications');
|
|
43
|
-
}
|
|
37
|
+
page: 'applications'
|
|
44
38
|
}
|
|
45
39
|
});
|
|
46
40
|
user &&
|
|
@@ -49,9 +43,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
49
43
|
morenda: {
|
|
50
44
|
icon: html ` <md-icon>people</md-icon> `,
|
|
51
45
|
name: html ` <ox-i18n msgid="text.user management"></ox-i18n> `,
|
|
52
|
-
|
|
53
|
-
navigate('users');
|
|
54
|
-
}
|
|
46
|
+
page: 'users'
|
|
55
47
|
}
|
|
56
48
|
});
|
|
57
49
|
authProvider &&
|
|
@@ -60,9 +52,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
60
52
|
morenda: {
|
|
61
53
|
icon: html ` <md-icon>id_card</md-icon> `,
|
|
62
54
|
name: html ` <ox-i18n msgid="text.auth-provider management"></ox-i18n> `,
|
|
63
|
-
|
|
64
|
-
navigate('auth-providers');
|
|
65
|
-
}
|
|
55
|
+
page: 'auth-providers'
|
|
66
56
|
}
|
|
67
57
|
});
|
|
68
58
|
}
|
|
@@ -73,9 +63,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
73
63
|
morenda: {
|
|
74
64
|
icon: html ` <md-icon>policy</md-icon> `,
|
|
75
65
|
name: html ` <ox-i18n msgid="audit.title"></ox-i18n> `,
|
|
76
|
-
|
|
77
|
-
navigate('audit');
|
|
78
|
-
}
|
|
66
|
+
page: 'audit'
|
|
79
67
|
}
|
|
80
68
|
});
|
|
81
69
|
}
|
|
@@ -86,9 +74,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
86
74
|
morenda: {
|
|
87
75
|
icon: html ` <md-icon>supervised_user_circle</md-icon> `,
|
|
88
76
|
name: html ` <ox-i18n msgid="text.domain owners"></ox-i18n> `,
|
|
89
|
-
|
|
90
|
-
navigate('domain-owners');
|
|
91
|
-
}
|
|
77
|
+
page: 'domain-owners'
|
|
92
78
|
}
|
|
93
79
|
});
|
|
94
80
|
}
|
|
@@ -99,9 +85,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
99
85
|
morenda: {
|
|
100
86
|
icon: html ` <md-icon>business</md-icon> `,
|
|
101
87
|
name: html ` <ox-i18n msgid="text.domain management"></ox-i18n> `,
|
|
102
|
-
|
|
103
|
-
navigate('domains');
|
|
104
|
-
}
|
|
88
|
+
page: 'domains'
|
|
105
89
|
}
|
|
106
90
|
});
|
|
107
91
|
attribute &&
|
|
@@ -110,9 +94,7 @@ export async function setAuthManagementMenus(options) {
|
|
|
110
94
|
morenda: {
|
|
111
95
|
icon: html ` <md-icon>dataset</md-icon> `,
|
|
112
96
|
name: html ` <ox-i18n msgid="text.attribute management"></ox-i18n> `,
|
|
113
|
-
|
|
114
|
-
navigate('attributes');
|
|
115
|
-
}
|
|
97
|
+
page: 'attributes'
|
|
116
98
|
}
|
|
117
99
|
});
|
|
118
100
|
}
|
package/dist-client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,0BAA0B,CAAA;AAEjC,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAE/B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/i18n/ox-i18n.js'\n\nimport { html } from 'lit-html'\n\nimport { store } from '@operato/shell'\nimport { ADD_MORENDA } from '@things-factory/more-base/client'\nimport { hasPrivilege } from '@things-factory/auth-base/dist-client'\n\nexport * from './components/role-selector.js'\nexport * from './components/domain-switch.js'\nexport * from './components/invite-user.js'\n\nexport type AuthManagementMenuOptions = {\n role?: boolean\n appliance?: boolean\n application?: boolean\n user?: boolean\n authProvider?: boolean\n domain?: boolean\n attribute?: boolean\n audit?: boolean\n}\n\nexport async function setAuthManagementMenus(options?: any) {\n const {\n role = true,\n appliance = true,\n application = true,\n user = true,\n authProvider = true,\n domain = true,\n attribute = true,\n audit = true\n } = options || {}\n\n if (\n await hasPrivilege({ privilege: 'mutation', category: 'user', domainOwnerGranted: true, superUserGranted: true })\n ) {\n role &&\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>how_to_reg</md-icon> `,\n name: html` <ox-i18n msgid=\"text.role_management\"></ox-i18n> `,\n page: 'roles'\n }\n })\n\n appliance &&\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>devices</md-icon> `,\n name: html` <ox-i18n msgid=\"text.appliance\"></ox-i18n> `,\n page: 'appliance-home'\n }\n })\n\n application &&\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>apps</md-icon> `,\n name: html` <ox-i18n msgid=\"text.application management\"></ox-i18n> `,\n page: 'applications'\n }\n })\n\n user &&\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>people</md-icon> `,\n name: html` <ox-i18n msgid=\"text.user management\"></ox-i18n> `,\n page: 'users'\n }\n })\n\n authProvider &&\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>id_card</md-icon> `,\n name: html` <ox-i18n msgid=\"text.auth-provider management\"></ox-i18n> `,\n page: 'auth-providers'\n }\n })\n }\n\n /* The audit asks its own privilege - the domain owner does not pass on ownership (ADR-0141 §5). */\n if (audit && (await hasPrivilege({ privilege: 'query', category: 'audit', superUserGranted: true }))) {\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>policy</md-icon> `,\n name: html` <ox-i18n msgid=\"audit.title\"></ox-i18n> `,\n page: 'audit'\n }\n })\n }\n\n if (await hasPrivilege({ domainOwnerGranted: true, superUserGranted: true })) {\n domain &&\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>supervised_user_circle</md-icon> `,\n name: html` <ox-i18n msgid=\"text.domain owners\"></ox-i18n> `,\n page: 'domain-owners'\n }\n })\n }\n\n if (await hasPrivilege({ superUserGranted: true })) {\n domain &&\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>business</md-icon> `,\n name: html` <ox-i18n msgid=\"text.domain management\"></ox-i18n> `,\n page: 'domains'\n }\n })\n\n attribute &&\n store.dispatch({\n type: ADD_MORENDA,\n morenda: {\n icon: html` <md-icon>dataset</md-icon> `,\n name: html` <ox-i18n msgid=\"text.attribute management\"></ox-i18n> `,\n page: 'attributes'\n }\n })\n }\n}\n"]}
|
|
@@ -108,7 +108,11 @@ export declare class UserListPage extends UserListPageBase {
|
|
|
108
108
|
* 묻는다**는 뜻이다 — 편집면에서 원하는 거동이 기본값이다.
|
|
109
109
|
*/
|
|
110
110
|
private onSelectUser;
|
|
111
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* 목록의 역할 편집과 같은 모양으로 연다 — `openPopup` 에 template 을 넘긴다.
|
|
113
|
+
*
|
|
114
|
+
* 새로 만든 계정은 「비밀번호 설정 대기」다. 그 자리에서 설정 링크를 건네도록 이어서 연다(ADR-0161).
|
|
115
|
+
*/
|
|
112
116
|
private onInvite;
|
|
113
117
|
}
|
|
114
118
|
export {};
|
|
@@ -7,6 +7,7 @@ import '@operato/list-state/ox-empty-note.js';
|
|
|
7
7
|
import '@operato/list-state/ox-page-state.js';
|
|
8
8
|
import '../../components/user-detail.js';
|
|
9
9
|
import '../../components/user-invite.js';
|
|
10
|
+
import { openPasswordSetupLink } from '../../components/password-setup-link-popup.js';
|
|
10
11
|
import gql from 'graphql-tag';
|
|
11
12
|
import { css, html, nothing } from 'lit';
|
|
12
13
|
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
@@ -104,8 +105,8 @@ let UserListPage = class UserListPage extends UserListPageBase {
|
|
|
104
105
|
* Calling someone in is what this screen is for, and it belongs in the page action bar
|
|
105
106
|
* (ADR-0060 decision 9). It used to float over the list. A button that does the same thing in a
|
|
106
107
|
* different place on every screen makes what you learned on one screen useless on the next.
|
|
107
|
-
* Which of the two acts it is - adding an account that already exists, or
|
|
108
|
-
* - is said by the window it opens.
|
|
108
|
+
* Which of the two acts it is - adding an account that already exists, or making one that waits
|
|
109
|
+
* for its password - is said by the window it opens.
|
|
109
110
|
*/
|
|
110
111
|
return {
|
|
111
112
|
title: i18next.t('text.user management'),
|
|
@@ -376,17 +377,25 @@ let UserListPage = class UserListPage extends UserListPageBase {
|
|
|
376
377
|
`, {
|
|
377
378
|
backdrop: true,
|
|
378
379
|
size: 'large',
|
|
379
|
-
title:
|
|
380
|
+
title: i18next.t('title.user details')
|
|
380
381
|
});
|
|
381
382
|
}
|
|
382
|
-
/**
|
|
383
|
+
/**
|
|
384
|
+
* 목록의 역할 편집과 같은 모양으로 연다 — `openPopup` 에 template 을 넘긴다.
|
|
385
|
+
*
|
|
386
|
+
* 새로 만든 계정은 「비밀번호 설정 대기」다. 그 자리에서 설정 링크를 건네도록 이어서 연다(ADR-0161).
|
|
387
|
+
*/
|
|
383
388
|
onInvite() {
|
|
384
389
|
const popup = openPopup(html `
|
|
385
390
|
<user-invite
|
|
386
391
|
@close=${() => popup.close()}
|
|
387
|
-
@user-invited=${() => {
|
|
392
|
+
@user-invited=${(e) => {
|
|
388
393
|
popup.close();
|
|
389
394
|
this.grist.fetch();
|
|
395
|
+
const created = e.detail?.created;
|
|
396
|
+
if (created) {
|
|
397
|
+
openPasswordSetupLink(created, { onIssued: () => this.grist.fetch() });
|
|
398
|
+
}
|
|
390
399
|
}}
|
|
391
400
|
></user-invite>
|
|
392
401
|
`, {
|