@things-factory/auth-ui 8.0.0-alpha.8 → 8.0.0-beta.1
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/client/components/abstract-auth-page.ts +10 -10
- package/client/components/abstract-password-reset.ts +9 -14
- package/client/components/abstract-sign.ts +13 -13
- package/client/components/change-password.ts +1 -0
- package/client/components/contact-us.ts +11 -8
- package/client/components/create-role.ts +1 -0
- package/client/components/create-user.ts +27 -5
- package/client/components/invite-user.ts +19 -10
- package/client/components/ownership-transfer-popup.ts +3 -3
- package/client/components/profile-component.ts +68 -4
- package/client/components/role-privilege-editor.ts +34 -6
- package/client/components/user-role-editor.ts +20 -20
- package/client/entries/auth/checkin.ts +1 -1
- package/client/entries/auth/forgot-password.ts +11 -2
- package/client/entries/auth/signup.ts +13 -7
- package/client/index.ts +1 -1
- package/client/pages/attribute/attribute-set-item-list.ts +1 -1
- package/client/pages/role/role-management.ts +2 -0
- package/client/pages/user/user-management.ts +10 -11
- package/dist-client/components/abstract-auth-page.js +10 -10
- package/dist-client/components/abstract-auth-page.js.map +1 -1
- package/dist-client/components/abstract-password-reset.d.ts +1 -2
- package/dist-client/components/abstract-password-reset.js +7 -14
- package/dist-client/components/abstract-password-reset.js.map +1 -1
- package/dist-client/components/abstract-sign.js +12 -11
- package/dist-client/components/abstract-sign.js.map +1 -1
- package/dist-client/components/change-password.js +1 -0
- package/dist-client/components/change-password.js.map +1 -1
- package/dist-client/components/contact-us.d.ts +1 -1
- package/dist-client/components/contact-us.js +10 -7
- package/dist-client/components/contact-us.js.map +1 -1
- package/dist-client/components/create-role.js +1 -0
- package/dist-client/components/create-role.js.map +1 -1
- package/dist-client/components/create-user.js +28 -5
- package/dist-client/components/create-user.js.map +1 -1
- package/dist-client/components/invite-user.js +20 -11
- package/dist-client/components/invite-user.js.map +1 -1
- package/dist-client/components/ownership-transfer-popup.js +3 -3
- package/dist-client/components/ownership-transfer-popup.js.map +1 -1
- package/dist-client/components/profile-component.d.ts +5 -1
- package/dist-client/components/profile-component.js +68 -4
- package/dist-client/components/profile-component.js.map +1 -1
- package/dist-client/components/role-privilege-editor.js +41 -10
- package/dist-client/components/role-privilege-editor.js.map +1 -1
- package/dist-client/components/user-role-editor.js +20 -20
- package/dist-client/components/user-role-editor.js.map +1 -1
- package/dist-client/entries/auth/checkin.js +1 -1
- package/dist-client/entries/auth/checkin.js.map +1 -1
- package/dist-client/entries/auth/forgot-password.js +11 -2
- package/dist-client/entries/auth/forgot-password.js.map +1 -1
- package/dist-client/entries/auth/signup.js +13 -7
- package/dist-client/entries/auth/signup.js.map +1 -1
- package/dist-client/index.js +1 -1
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/attribute/attribute-set-item-list.js +1 -1
- package/dist-client/pages/attribute/attribute-set-item-list.js.map +1 -1
- package/dist-client/pages/role/role-management.js +2 -0
- package/dist-client/pages/role/role-management.js.map +1 -1
- package/dist-client/pages/user/user-management.d.ts +29 -0
- package/dist-client/pages/user/user-management.js +9 -9
- package/dist-client/pages/user/user-management.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -12
- package/translations/en.json +8 -2
- package/translations/ja.json +7 -2
- package/translations/ko.json +7 -2
- package/translations/ms.json +8 -2
- package/translations/zh.json +8 -2
|
@@ -113,8 +113,8 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
113
113
|
? html`
|
|
114
114
|
<li>
|
|
115
115
|
<span>
|
|
116
|
-
<md-icon>email</md-icon>
|
|
117
|
-
${user.email}
|
|
116
|
+
${user.username || user.email} (<md-icon>email</md-icon>
|
|
117
|
+
${user.email})
|
|
118
118
|
</span>
|
|
119
119
|
</li>
|
|
120
120
|
`
|
|
@@ -169,7 +169,7 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
169
169
|
: ''}
|
|
170
170
|
${user.userType === 'user'
|
|
171
171
|
? html`
|
|
172
|
-
${this.isTransferable(user)
|
|
172
|
+
${this.isTransferable(user) && this.userRoles && this.userRoles.length > 0
|
|
173
173
|
? html`
|
|
174
174
|
<md-elevated-button danger @click=${() => this.onTransfer(user)}
|
|
175
175
|
>${String(i18next.t('button.transfer owner'))}</md-elevated-button
|
|
@@ -209,7 +209,7 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
isTransferable(user) {
|
|
212
|
-
return (this.isSuperOwner || this.isDomainOwner) && !user.owner
|
|
212
|
+
return this.activate && (this.isSuperOwner || this.isDomainOwner) && !user.owner
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
isRoleEditable() {
|
|
@@ -330,8 +330,8 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
330
330
|
if (user?.id) {
|
|
331
331
|
const response = await client.mutate({
|
|
332
332
|
mutation: gql`
|
|
333
|
-
mutation ($
|
|
334
|
-
updateUserRoles(
|
|
333
|
+
mutation ($username: String!, $availableRoles: [ObjectRef!]!, $selectedRoles: [ObjectRef!]!) {
|
|
334
|
+
updateUserRoles(username: $username, availableRoles: $availableRoles, selectedRoles: $selectedRoles) {
|
|
335
335
|
id
|
|
336
336
|
name
|
|
337
337
|
roles {
|
|
@@ -341,7 +341,7 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
341
341
|
}
|
|
342
342
|
}
|
|
343
343
|
`,
|
|
344
|
-
variables: {
|
|
344
|
+
variables: { username: user.username || user.email, availableRoles, selectedRoles },
|
|
345
345
|
context: gqlContext()
|
|
346
346
|
})
|
|
347
347
|
|
|
@@ -355,11 +355,11 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
355
355
|
async onActivate(user) {
|
|
356
356
|
const response = await client.mutate({
|
|
357
357
|
mutation: gql`
|
|
358
|
-
mutation activateUser($
|
|
359
|
-
activateUser(
|
|
358
|
+
mutation activateUser($username: String!) {
|
|
359
|
+
activateUser(username: $username)
|
|
360
360
|
}
|
|
361
361
|
`,
|
|
362
|
-
variables: {
|
|
362
|
+
variables: { username: user.username || user.email },
|
|
363
363
|
context: gqlContext()
|
|
364
364
|
})
|
|
365
365
|
|
|
@@ -373,16 +373,16 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
373
373
|
async onInactivate(user) {
|
|
374
374
|
const response = await client.mutate({
|
|
375
375
|
mutation: gql`
|
|
376
|
-
mutation inactivateUser($
|
|
377
|
-
inactivateUser(
|
|
376
|
+
mutation inactivateUser($username: String!) {
|
|
377
|
+
inactivateUser(username: $username)
|
|
378
378
|
}
|
|
379
379
|
`,
|
|
380
|
-
variables: {
|
|
380
|
+
variables: { username: user.username || user.email },
|
|
381
381
|
context: gqlContext()
|
|
382
382
|
})
|
|
383
383
|
|
|
384
384
|
if (!response.errors) {
|
|
385
|
-
this.showToast(i18next.t('text.user
|
|
385
|
+
this.showToast(i18next.t('text.user inactivated successfully'))
|
|
386
386
|
|
|
387
387
|
this.dispatchUserUpdated()
|
|
388
388
|
}
|
|
@@ -414,11 +414,11 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
414
414
|
) {
|
|
415
415
|
const response = await client.mutate({
|
|
416
416
|
mutation: gql`
|
|
417
|
-
mutation deleteDomaineUser($
|
|
418
|
-
deleteDomainUser(
|
|
417
|
+
mutation deleteDomaineUser($username: String!) {
|
|
418
|
+
deleteDomainUser(username: $username)
|
|
419
419
|
}
|
|
420
420
|
`,
|
|
421
|
-
variables: {
|
|
421
|
+
variables: { username: user.username || user.email },
|
|
422
422
|
context: gqlContext()
|
|
423
423
|
})
|
|
424
424
|
|
|
@@ -460,11 +460,11 @@ class UserRoleEditor extends connect(store)(LitElement) {
|
|
|
460
460
|
) {
|
|
461
461
|
const response = await client.mutate({
|
|
462
462
|
mutation: gql`
|
|
463
|
-
mutation resetPasswordToDefault($
|
|
464
|
-
resetPasswordToDefault(
|
|
463
|
+
mutation resetPasswordToDefault($username: String!) {
|
|
464
|
+
resetPasswordToDefault(username: $username)
|
|
465
465
|
}
|
|
466
466
|
`,
|
|
467
|
-
variables: {
|
|
467
|
+
variables: { username: user.username || user.email },
|
|
468
468
|
context: gqlContext()
|
|
469
469
|
})
|
|
470
470
|
|
|
@@ -58,8 +58,8 @@ export class AuthCheckIn extends localize(i18next)(LitElement) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
li:hover {
|
|
61
|
-
background-color: var(--md-sys-color-primary-container);
|
|
62
61
|
color: var(--md-sys-color-on-primary-container);
|
|
62
|
+
background-color: var(--md-sys-color-primary-container);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
li span {
|
|
@@ -43,9 +43,18 @@ export class ForgotPassword extends AbstractAuthPage {
|
|
|
43
43
|
target.setCustomValidity('')
|
|
44
44
|
}
|
|
45
45
|
}}
|
|
46
|
-
|
|
46
|
+
><md-icon slot="leading-icon">mail</md-icon></md-filled-text-field
|
|
47
|
+
>
|
|
47
48
|
</div>
|
|
48
|
-
<md-elevated-button
|
|
49
|
+
<md-elevated-button
|
|
50
|
+
id="submit-button"
|
|
51
|
+
class="ui button"
|
|
52
|
+
type="button"
|
|
53
|
+
@click=${e => {
|
|
54
|
+
this._onSubmit(e)
|
|
55
|
+
return false
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
49
58
|
<ox-i18n msgid="button.submit"></ox-i18n>
|
|
50
59
|
</md-elevated-button>
|
|
51
60
|
`
|
|
@@ -24,7 +24,7 @@ export class AuthSignup extends AbstractSign {
|
|
|
24
24
|
@query('#confirm-password') confirmPass!: HTMLInputElement
|
|
25
25
|
|
|
26
26
|
get formfields() {
|
|
27
|
-
const { name = '', email = '' } = this.data || {}
|
|
27
|
+
const { username = '', name = '', email = '' } = this.data || {}
|
|
28
28
|
|
|
29
29
|
// .validationMessage=${this.passwordHelp || ''}
|
|
30
30
|
// .validationMessage=${String(i18next.t('text.passwords do not match'))}
|
|
@@ -32,12 +32,18 @@ export class AuthSignup extends AbstractSign {
|
|
|
32
32
|
return html`
|
|
33
33
|
<div class="field">
|
|
34
34
|
<md-filled-text-field
|
|
35
|
-
name="
|
|
35
|
+
name="username"
|
|
36
36
|
type="text"
|
|
37
|
-
label=${String(i18next.t('field.
|
|
38
|
-
.value=${
|
|
37
|
+
label=${String(i18next.t('field.username'))}
|
|
38
|
+
.value=${username}
|
|
39
39
|
required
|
|
40
|
-
|
|
40
|
+
><md-icon slot="leading-icon">badge</md-icon></md-filled-text-field
|
|
41
|
+
>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="field">
|
|
44
|
+
<md-filled-text-field name="name" type="text" label=${String(i18next.t('field.name'))} .value=${name} required
|
|
45
|
+
><md-icon slot="leading-icon">id_card</md-icon></md-filled-text-field
|
|
46
|
+
>
|
|
41
47
|
</div>
|
|
42
48
|
<div class="field">
|
|
43
49
|
<md-filled-text-field
|
|
@@ -73,7 +79,7 @@ export class AuthSignup extends AbstractSign {
|
|
|
73
79
|
this.confirmPass.setAttribute('pattern', val.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '[$&]'))
|
|
74
80
|
}}
|
|
75
81
|
>
|
|
76
|
-
></md-filled-text-field
|
|
82
|
+
><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
|
|
77
83
|
>
|
|
78
84
|
</div>
|
|
79
85
|
<div class="field">
|
|
@@ -85,7 +91,7 @@ export class AuthSignup extends AbstractSign {
|
|
|
85
91
|
label=${String(i18next.t('field.confirm password'))}
|
|
86
92
|
required
|
|
87
93
|
>
|
|
88
|
-
></md-filled-text-field
|
|
94
|
+
><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
|
|
89
95
|
>
|
|
90
96
|
</div>
|
|
91
97
|
<md-elevated-button class="ui button" @click=${e => this._onSubmit(e)}>
|
package/client/index.ts
CHANGED
|
@@ -87,7 +87,7 @@ export async function setAuthManagementMenus(options?: any) {
|
|
|
87
87
|
store.dispatch({
|
|
88
88
|
type: ADD_MORENDA,
|
|
89
89
|
morenda: {
|
|
90
|
-
icon: html` <md-icon>
|
|
90
|
+
icon: html` <md-icon>id_card</md-icon> `,
|
|
91
91
|
name: html` <ox-i18n msgid="text.auth-provider management"></ox-i18n> `,
|
|
92
92
|
action: () => {
|
|
93
93
|
navigate('auth-providers')
|
|
@@ -11,12 +11,12 @@ import { css, html } from 'lit'
|
|
|
11
11
|
import { customElement, property, query } from 'lit/decorators.js'
|
|
12
12
|
|
|
13
13
|
import { client, gqlContext } from '@operato/graphql'
|
|
14
|
-
import { i18next } from '@operato/i18n'
|
|
14
|
+
import { i18next, localize } from '@operato/i18n'
|
|
15
15
|
import { PageView } from '@operato/shell'
|
|
16
16
|
import { OxPrompt } from '@operato/popup/ox-prompt.js'
|
|
17
17
|
|
|
18
18
|
@customElement('user-management')
|
|
19
|
-
class UserManagement extends PageView {
|
|
19
|
+
export class UserManagement extends localize(i18next)(PageView) {
|
|
20
20
|
static styles = [
|
|
21
21
|
css`
|
|
22
22
|
:host {
|
|
@@ -98,14 +98,12 @@ class UserManagement extends PageView {
|
|
|
98
98
|
.data=${userSet}
|
|
99
99
|
@tabChanged=${e => (this.currentTab = e.detail.currentTabKey)}
|
|
100
100
|
.headerRenderer=${user => {
|
|
101
|
-
return
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
: html` ${user.owner ? html` <md-icon>supervisor_account</md-icon> ` : ''} ${user.name} `}
|
|
108
|
-
`
|
|
101
|
+
return !user.activated
|
|
102
|
+
? html`
|
|
103
|
+
<md-icon>do_disturb</md-icon>
|
|
104
|
+
${user.name}
|
|
105
|
+
`
|
|
106
|
+
: html` ${user.owner ? html` <md-icon>supervisor_account</md-icon> ` : ''} ${user.name} `
|
|
109
107
|
}}
|
|
110
108
|
.contentRenderer=${user =>
|
|
111
109
|
html` <user-role-editor
|
|
@@ -139,6 +137,7 @@ class UserManagement extends PageView {
|
|
|
139
137
|
users {
|
|
140
138
|
items {
|
|
141
139
|
id
|
|
140
|
+
username
|
|
142
141
|
name
|
|
143
142
|
email
|
|
144
143
|
userType
|
|
@@ -186,7 +185,7 @@ class UserManagement extends PageView {
|
|
|
186
185
|
}
|
|
187
186
|
}
|
|
188
187
|
|
|
189
|
-
async createUser(user) {
|
|
188
|
+
async createUser(user: { username: string; name: string; email: string }) {
|
|
190
189
|
if (
|
|
191
190
|
await OxPrompt.open({
|
|
192
191
|
title: i18next.t('text.are_you_sure'),
|
|
@@ -99,21 +99,21 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
99
99
|
}
|
|
100
100
|
get formfields() {
|
|
101
101
|
var _a;
|
|
102
|
-
const
|
|
103
|
-
// .validationMessage=${String(i18next.t('text.invalid-
|
|
102
|
+
const username = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.username) || '';
|
|
103
|
+
// .validationMessage=${String(i18next.t('text.invalid-username'))}
|
|
104
104
|
return html `
|
|
105
105
|
<input id="redirectTo" type="hidden" name="redirectTo" .value=${this.redirectTo || '/'} />
|
|
106
106
|
|
|
107
107
|
<div class="field">
|
|
108
108
|
<md-filled-text-field
|
|
109
|
-
name="
|
|
110
|
-
type="
|
|
111
|
-
label=${String(i18next.t('field.email'))}
|
|
109
|
+
name="username"
|
|
110
|
+
type="text"
|
|
111
|
+
label=${String(i18next.t('field.user-id or email'))}
|
|
112
112
|
required
|
|
113
|
-
.value=${
|
|
113
|
+
.value=${username}
|
|
114
114
|
autocomplete="off"
|
|
115
115
|
autocapitalize="off"
|
|
116
|
-
><md-icon slot="leading-icon">
|
|
116
|
+
><md-icon slot="leading-icon">id_card</md-icon></md-filled-text-field
|
|
117
117
|
>
|
|
118
118
|
</div>
|
|
119
119
|
<div class="field">
|
|
@@ -123,11 +123,11 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
123
123
|
label=${String(i18next.t('field.password'))}
|
|
124
124
|
autocomplete="off"
|
|
125
125
|
required
|
|
126
|
-
><md-icon slot="leading-icon">
|
|
126
|
+
><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
|
|
127
127
|
>
|
|
128
128
|
</div>
|
|
129
129
|
|
|
130
|
-
<md-elevated-button class="ui" type="
|
|
130
|
+
<md-elevated-button class="ui" type="button" raised @click=${e => this._onSubmit(e)}>
|
|
131
131
|
<ox-i18n msgid="field.${this.pageName}"> </ox-i18n>
|
|
132
132
|
</md-elevated-button>
|
|
133
133
|
`;
|
|
@@ -154,7 +154,7 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
154
154
|
${ssoLinks.map(sso => html `
|
|
155
155
|
<a class="link" href=${sso.link}>
|
|
156
156
|
<md-text-button>
|
|
157
|
-
<md-icon slot="icon">
|
|
157
|
+
<md-icon slot="icon">id_card</md-icon>
|
|
158
158
|
${i18next.t('label.signin with', { title: sso.title })}
|
|
159
159
|
</md-text-button>
|
|
160
160
|
</a>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract-auth-page.js","sourceRoot":"","sources":["../../client/components/abstract-auth-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/textfield/filled-text-field.js'\n\nimport '@operato/lottie-player'\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/i18n/ox-i18n-selector.js'\nimport '@operato/layout/ox-snack-bar.js'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { isSafari } from '@operato/utils'\n\nimport { AUTH_STYLE_SIGN } from '../auth-style-sign.js'\n\nexport abstract class AbstractAuthPage extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n position: relative;\n overflow: hidden;\n\n display: flex;\n flex-direction: row;\n\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n }\n\n .content {\n flex: 1;\n overflow: auto;\n }\n\n .home {\n position: absolute;\n padding: var(--padding-dufault, 9px);\n left: 20px;\n top: 10px;\n color: var(--md-sys-color-on-primary);\n }\n\n div.field {\n margin-bottom: var(--spacing-medium);\n }\n\n [hidden] {\n display: none;\n }\n\n #snackbar {\n width: 100%;\n z-index: 10;\n }\n\n @media print {\n :host {\n width: 100%;\n height: 100%;\n min-height: 100vh;\n min-height: 100dvh;\n }\n }\n `,\n AUTH_STYLE_SIGN\n ]\n\n @property({ type: Object }) data: any\n @property({ type: String }) message?: string\n @property({ type: Object }) detail: any\n @property({ type: String }) redirectTo?: string\n\n @query('#form') formEl!: HTMLFormElement\n\n private _applicationMeta?: {\n icon: string\n title: string\n description: string\n }\n\n get autocompletable() {\n return false\n }\n\n render() {\n const { disableUserFavoredLanguage, languages } = this.data || {}\n var { icon, title, description } = this.applicationMeta\n\n return html`\n <div class=\"content md-typescale-display-medium\">\n <div class=\"wrap\">\n <div class=\"auth-brand\">\n <img src=${icon} />\n <strong class=\"name\">${title}</strong>\n <span class=\"welcome-msg\">${description}</span>\n </div>\n\n <div class=\"auth-form\">\n <h3><ox-i18n msgid=\"title.${this.pageName}\"></ox-i18n></h3>\n\n <form\n id=\"form\"\n action=\"${this.actionUrl}\"\n method=\"post\"\n autocomplete=${this.autocompletable ? 'on' : 'off'}\n @keypress=${e => {\n if (e.key == 'Enter') this._onSubmit(e)\n }}\n >\n ${this.formfields}\n </form>\n ${this.links}\n ${!disableUserFavoredLanguage\n ? html` <div id=\"locale-area\">\n <label for=\"locale-selector\"><md-icon>language</md-icon></label>\n <ox-i18n-selector\n id=\"locale-selector\"\n value=${i18next.language || 'en-US'}\n .languages=${languages}\n @change=${e => {\n var locale = e.detail\n if (!locale) return\n\n i18next.changeLanguage(locale)\n }}\n ></ox-i18n-selector>\n </div>`\n : nothing}\n </div>\n </div>\n\n <md-icon-button class=\"home\" @click=${e => (window.location.href = '/')}\n ><md-icon>home</md-icon></md-icon-button\n >\n <ox-snack-bar id=\"snackbar\" level=\"error\" .message=${this.message}></ox-snack-bar>\n\n ${isSafari()\n ? html``\n : html`\n <div class=\"lottie-container\">\n <lottie-player autoplay loop src=\"../../assets/images/background-animation.json\"></lottie-player>\n </div>\n `}\n </div>\n `\n }\n\n firstUpdated() {\n setTimeout(() => {\n ;(this.renderRoot.querySelector('md-filled-text-field') as any).focus()\n }, 100)\n\n this.formEl.reset = () => {\n this.formElements.filter(el => !(el.hidden || el.type == 'hidden')).forEach(el => (el.value = ''))\n }\n }\n\n updated(changed) {\n if (changed.has('data') && this.data) {\n this.message = this.data.message\n this.redirectTo = this.data.redirectTo\n }\n }\n\n abstract get pageName(): string\n abstract get actionUrl(): string\n\n get formElements(): HTMLInputElement[] {\n return Array.from(this.formEl.querySelectorAll('[name]'))\n }\n\n get formfields() {\n const email = this.data?.email || ''\n // .validationMessage=${String(i18next.t('text.invalid-email'))}\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <md-filled-text-field\n name=\"email\"\n type=\"email\"\n label=${String(i18next.t('field.email'))}\n required\n .value=${email}\n autocomplete=\"off\"\n autocapitalize=\"off\"\n ><md-icon slot=\"leading-icon\">mail</md-icon></md-filled-text-field\n >\n </div>\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('field.password'))}\n autocomplete=\"off\"\n required\n ><md-icon slot=\"leading-icon\">vpn_key</md-icon></md-filled-text-field\n >\n </div>\n\n <md-elevated-button class=\"ui\" type=\"submit\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </md-elevated-button>\n `\n }\n\n get links() {\n const { disableUserSignupProcess, ssoLinks = [] } = this.data || {}\n\n return html`\n ${!disableUserSignupProcess\n ? html`\n <a class=\"link\" href=\"/auth/signup\">\n <md-text-button>\n <md-icon slot=\"icon\">add_task</md-icon>\n <ox-i18n msgid=\"field.sign up\"></ox-i18n>\n </md-text-button>\n </a>\n <a class=\"link\" href=\"/auth/forgot-password\">\n <md-text-button>\n <md-icon slot=\"icon\">lock_open</md-icon>\n <ox-i18n msgid=\"field.forgot-password\"></ox-i18n>\n </md-text-button>\n </a>\n `\n : nothing}\n ${ssoLinks.map(\n sso => html`\n <a class=\"link\" href=${sso.link}>\n <md-text-button>\n <md-icon slot=\"icon\">badge</md-icon>\n ${i18next.t('label.signin with', { title: sso.title })}\n </md-text-button>\n </a>\n `\n )}\n `\n }\n\n async _onSubmit(e) {\n if (this.checkValidity()) {\n this.submit()\n }\n }\n\n checkValidity() {\n return this.formElements.every(el => el.checkValidity())\n }\n\n abstract submit()\n\n showSnackbar({ level, message, timer = 3000 }: { level?: string; message?: string; timer?: number } = {}) {\n const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {\n level: string\n message: string\n active: boolean\n }\n\n if (level) snackbar.level = level\n if (message) snackbar.message = message\n snackbar.active = true\n\n if (timer > -1)\n setTimeout(() => {\n this.hideSnackbar()\n }, timer)\n }\n\n hideSnackbar() {\n const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {\n level: string\n message: string\n active: boolean\n }\n\n snackbar.active = false\n }\n\n get applicationMeta() {\n if (!this._applicationMeta) {\n var iconLink: HTMLLinkElement | null = document.querySelector('link[rel=\"application-icon\"]')\n var titleMeta: HTMLMetaElement | null = document.querySelector('meta[name=\"application-name\"]')\n var descriptionMeta: HTMLMetaElement | null = document.querySelector('meta[name=\"application-description\"]')\n\n this._applicationMeta = {\n icon: iconLink?.href || '',\n title: titleMeta?.content || 'Things Factory',\n description: descriptionMeta?.content || 'Reimagining Software'\n }\n }\n\n return this._applicationMeta\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"abstract-auth-page.js","sourceRoot":"","sources":["../../client/components/abstract-auth-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/textfield/filled-text-field.js'\n\nimport '@operato/lottie-player'\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/i18n/ox-i18n-selector.js'\nimport '@operato/layout/ox-snack-bar.js'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { isSafari } from '@operato/utils'\n\nimport { AUTH_STYLE_SIGN } from '../auth-style-sign.js'\n\nexport abstract class AbstractAuthPage extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n position: relative;\n overflow: hidden;\n\n display: flex;\n flex-direction: row;\n\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n }\n\n .content {\n flex: 1;\n overflow: auto;\n }\n\n .home {\n position: absolute;\n padding: var(--padding-dufault, 9px);\n left: 20px;\n top: 10px;\n color: var(--md-sys-color-on-primary);\n }\n\n div.field {\n margin-bottom: var(--spacing-medium);\n }\n\n [hidden] {\n display: none;\n }\n\n #snackbar {\n width: 100%;\n z-index: 10;\n }\n\n @media print {\n :host {\n width: 100%;\n height: 100%;\n min-height: 100vh;\n min-height: 100dvh;\n }\n }\n `,\n AUTH_STYLE_SIGN\n ]\n\n @property({ type: Object }) data: any\n @property({ type: String }) message?: string\n @property({ type: Object }) detail: any\n @property({ type: String }) redirectTo?: string\n\n @query('#form') formEl!: HTMLFormElement\n\n private _applicationMeta?: {\n icon: string\n title: string\n description: string\n }\n\n get autocompletable() {\n return false\n }\n\n render() {\n const { disableUserFavoredLanguage, languages } = this.data || {}\n var { icon, title, description } = this.applicationMeta\n\n return html`\n <div class=\"content md-typescale-display-medium\">\n <div class=\"wrap\">\n <div class=\"auth-brand\">\n <img src=${icon} />\n <strong class=\"name\">${title}</strong>\n <span class=\"welcome-msg\">${description}</span>\n </div>\n\n <div class=\"auth-form\">\n <h3><ox-i18n msgid=\"title.${this.pageName}\"></ox-i18n></h3>\n\n <form\n id=\"form\"\n action=\"${this.actionUrl}\"\n method=\"post\"\n autocomplete=${this.autocompletable ? 'on' : 'off'}\n @keypress=${e => {\n if (e.key == 'Enter') this._onSubmit(e)\n }}\n >\n ${this.formfields}\n </form>\n ${this.links}\n ${!disableUserFavoredLanguage\n ? html` <div id=\"locale-area\">\n <label for=\"locale-selector\"><md-icon>language</md-icon></label>\n <ox-i18n-selector\n id=\"locale-selector\"\n value=${i18next.language || 'en-US'}\n .languages=${languages}\n @change=${e => {\n var locale = e.detail\n if (!locale) return\n\n i18next.changeLanguage(locale)\n }}\n ></ox-i18n-selector>\n </div>`\n : nothing}\n </div>\n </div>\n\n <md-icon-button class=\"home\" @click=${e => (window.location.href = '/')}\n ><md-icon>home</md-icon></md-icon-button\n >\n <ox-snack-bar id=\"snackbar\" level=\"error\" .message=${this.message}></ox-snack-bar>\n\n ${isSafari()\n ? html``\n : html`\n <div class=\"lottie-container\">\n <lottie-player autoplay loop src=\"../../assets/images/background-animation.json\"></lottie-player>\n </div>\n `}\n </div>\n `\n }\n\n firstUpdated() {\n setTimeout(() => {\n ;(this.renderRoot.querySelector('md-filled-text-field') as any).focus()\n }, 100)\n\n this.formEl.reset = () => {\n this.formElements.filter(el => !(el.hidden || el.type == 'hidden')).forEach(el => (el.value = ''))\n }\n }\n\n updated(changed) {\n if (changed.has('data') && this.data) {\n this.message = this.data.message\n this.redirectTo = this.data.redirectTo\n }\n }\n\n abstract get pageName(): string\n abstract get actionUrl(): string\n\n get formElements(): HTMLInputElement[] {\n return Array.from(this.formEl.querySelectorAll('[name]'))\n }\n\n get formfields() {\n const username = this.data?.username || ''\n // .validationMessage=${String(i18next.t('text.invalid-username'))}\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <md-filled-text-field\n name=\"username\"\n type=\"text\"\n label=${String(i18next.t('field.user-id or email'))}\n required\n .value=${username}\n autocomplete=\"off\"\n autocapitalize=\"off\"\n ><md-icon slot=\"leading-icon\">id_card</md-icon></md-filled-text-field\n >\n </div>\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('field.password'))}\n autocomplete=\"off\"\n required\n ><md-icon slot=\"leading-icon\">password</md-icon></md-filled-text-field\n >\n </div>\n\n <md-elevated-button class=\"ui\" type=\"button\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </md-elevated-button>\n `\n }\n\n get links() {\n const { disableUserSignupProcess, ssoLinks = [] } = this.data || {}\n\n return html`\n ${!disableUserSignupProcess\n ? html`\n <a class=\"link\" href=\"/auth/signup\">\n <md-text-button>\n <md-icon slot=\"icon\">add_task</md-icon>\n <ox-i18n msgid=\"field.sign up\"></ox-i18n>\n </md-text-button>\n </a>\n <a class=\"link\" href=\"/auth/forgot-password\">\n <md-text-button>\n <md-icon slot=\"icon\">lock_open</md-icon>\n <ox-i18n msgid=\"field.forgot-password\"></ox-i18n>\n </md-text-button>\n </a>\n `\n : nothing}\n ${ssoLinks.map(\n sso => html`\n <a class=\"link\" href=${sso.link}>\n <md-text-button>\n <md-icon slot=\"icon\">id_card</md-icon>\n ${i18next.t('label.signin with', { title: sso.title })}\n </md-text-button>\n </a>\n `\n )}\n `\n }\n\n async _onSubmit(e) {\n if (this.checkValidity()) {\n this.submit()\n }\n }\n\n checkValidity() {\n return this.formElements.every(el => el.checkValidity())\n }\n\n abstract submit()\n\n showSnackbar({ level, message, timer = 3000 }: { level?: string; message?: string; timer?: number } = {}) {\n const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {\n level: string\n message: string\n active: boolean\n }\n\n if (level) snackbar.level = level\n if (message) snackbar.message = message\n snackbar.active = true\n\n if (timer > -1)\n setTimeout(() => {\n this.hideSnackbar()\n }, timer)\n }\n\n hideSnackbar() {\n const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {\n level: string\n message: string\n active: boolean\n }\n\n snackbar.active = false\n }\n\n get applicationMeta() {\n if (!this._applicationMeta) {\n var iconLink: HTMLLinkElement | null = document.querySelector('link[rel=\"application-icon\"]')\n var titleMeta: HTMLMetaElement | null = document.querySelector('meta[name=\"application-name\"]')\n var descriptionMeta: HTMLMetaElement | null = document.querySelector('meta[name=\"application-description\"]')\n\n this._applicationMeta = {\n icon: iconLink?.href || '',\n title: titleMeta?.content || 'Things Factory',\n description: descriptionMeta?.content || 'Reimagining Software'\n }\n }\n\n return this._applicationMeta\n }\n}\n"]}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js';
|
|
2
2
|
import '@material/web/button/elevated-button.js';
|
|
3
3
|
import '@material/web/textfield/filled-text-field.js';
|
|
4
|
-
import '@operato/lottie-player';
|
|
5
|
-
import '../components/profile-component';
|
|
6
4
|
import '@operato/i18n/ox-i18n.js';
|
|
7
5
|
import '@operato/i18n/ox-i18n-selector.js';
|
|
8
6
|
import '@operato/layout/ox-snack-bar.js';
|
|
7
|
+
import '../components/profile-component';
|
|
9
8
|
import { AbstractAuthPage } from './abstract-auth-page';
|
|
10
9
|
export declare abstract class AbstractPasswordReset extends AbstractAuthPage {
|
|
11
10
|
static styles: import("lit").CSSResult[];
|
|
@@ -2,15 +2,13 @@ import { __decorate, __metadata } from "tslib";
|
|
|
2
2
|
import '@material/web/icon/icon.js';
|
|
3
3
|
import '@material/web/button/elevated-button.js';
|
|
4
4
|
import '@material/web/textfield/filled-text-field.js';
|
|
5
|
-
import '@operato/lottie-player';
|
|
6
|
-
import '../components/profile-component';
|
|
7
5
|
import '@operato/i18n/ox-i18n.js';
|
|
8
6
|
import '@operato/i18n/ox-i18n-selector.js';
|
|
9
7
|
import '@operato/layout/ox-snack-bar.js';
|
|
8
|
+
import '../components/profile-component';
|
|
10
9
|
import { css, html, nothing } from 'lit';
|
|
11
10
|
import { property, query } from 'lit/decorators.js';
|
|
12
11
|
import { i18next } from '@operato/i18n';
|
|
13
|
-
import { isSafari } from '@operato/utils';
|
|
14
12
|
import { AUTH_STYLE_SIGN } from '../auth-style-sign';
|
|
15
13
|
import { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule';
|
|
16
14
|
import { AbstractAuthPage } from './abstract-auth-page';
|
|
@@ -56,7 +54,8 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
56
54
|
this.confirmPass.setAttribute('pattern', val.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '[$&]'));
|
|
57
55
|
}}
|
|
58
56
|
required
|
|
59
|
-
|
|
57
|
+
><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
|
|
58
|
+
>
|
|
60
59
|
</div>
|
|
61
60
|
|
|
62
61
|
<div class="field">
|
|
@@ -67,10 +66,11 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
67
66
|
label=${String(i18next.t('field.confirm password'))}
|
|
68
67
|
autocomplete="off"
|
|
69
68
|
required
|
|
70
|
-
|
|
69
|
+
><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
|
|
70
|
+
>
|
|
71
71
|
</div>
|
|
72
72
|
|
|
73
|
-
<md-elevated-button id="submit-button" type="
|
|
73
|
+
<md-elevated-button id="submit-button" type="button" @click=${e => this._onSubmit(e)}>
|
|
74
74
|
<ox-i18n msgid="${this.submitButtonLabel}"></ox-i18n>
|
|
75
75
|
</md-elevated-button>
|
|
76
76
|
|
|
@@ -93,15 +93,8 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
93
93
|
</form>
|
|
94
94
|
</div>
|
|
95
95
|
</div>
|
|
96
|
-
<ox-snack-bar id="snackbar" level="error" .message=${this.message}></ox-snack-bar>
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
? html ``
|
|
100
|
-
: html `
|
|
101
|
-
<div class="lottie-container">
|
|
102
|
-
<lottie-player autoplay loop src="../../assets/images/background-animation.json"></lottie-player>
|
|
103
|
-
</div>
|
|
104
|
-
`}
|
|
97
|
+
<ox-snack-bar id="snackbar" level="error" .message=${this.message}></ox-snack-bar>
|
|
105
98
|
`;
|
|
106
99
|
}
|
|
107
100
|
updated(changed) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract-password-reset.js","sourceRoot":"","sources":["../../client/components/abstract-password-reset.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,yCAAyC,CAAA;AAChD,OAAO,8CAA8C,CAAA;AAErD,OAAO,
|
|
1
|
+
{"version":3,"file":"abstract-password-reset.js","sourceRoot":"","sources":["../../client/components/abstract-password-reset.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/textfield/filled-text-field.js'\n\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/i18n/ox-i18n-selector.js'\nimport '@operato/layout/ox-snack-bar.js'\n\nimport '../components/profile-component'\n\nimport { css, html, nothing } from 'lit'\nimport { property, query } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\n\nimport { AUTH_STYLE_SIGN } from '../auth-style-sign'\nimport { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule'\nimport { AbstractAuthPage } from './abstract-auth-page'\n\nexport abstract class AbstractPasswordReset extends AbstractAuthPage {\n static styles = [\n css`\n :host {\n position: relative;\n overflow: hidden;\n\n display: flex;\n flex-direction: row;\n\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n }\n\n @media print {\n :host {\n width: 100%;\n height: 100%;\n min-height: 100vh;\n min-height: 100dvh;\n }\n }\n `,\n AUTH_STYLE_SIGN\n ]\n\n @property({ type: Object }) data: any\n @property({ type: String }) token?: string\n\n @query('#confirm-password') confirmPass!: HTMLElement\n\n private passwordPattern: string = ''\n private passwordHelp: string = ''\n\n abstract get submitButtonLabel(): string\n\n render() {\n var { icon, title, description } = this.applicationMeta\n const { disableUserFavoredLanguage, languages } = this.data || {}\n\n return html`\n <div class=\"wrap\">\n <div class=\"auth-brand\">\n <img src=${icon} />\n <strong class=\"name\">${title}</strong>\n <span class=\"welcome-msg\">${description}</span>\n </div>\n\n <div class=\"auth-form\">\n <h3><ox-i18n msgid=\"title.${this.title}\"></ox-i18n></h3>\n <form\n id=\"form\"\n action=\"${this.actionUrl}\"\n method=\"post\"\n @keypress=${e => {\n if (e.key == 'Enter') this._onSubmit(e)\n }}\n >\n <input name=\"token\" type=\"hidden\" .value=${this.token || ''} required />\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('label.password'))}\n pattern=${this.passwordPattern || ''}\n supporting-text=${this.passwordHelp}\n autocomplete=\"off\"\n @input=${e => {\n var val = e.target.value\n this.confirmPass.setAttribute('pattern', val.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '[$&]'))\n }}\n required\n ><md-icon slot=\"leading-icon\">password</md-icon></md-filled-text-field\n >\n </div>\n\n <div class=\"field\">\n <md-filled-text-field\n id=\"confirm-password\"\n name=\"confirm-password\"\n type=\"password\"\n label=${String(i18next.t('field.confirm password'))}\n autocomplete=\"off\"\n required\n ><md-icon slot=\"leading-icon\">password</md-icon></md-filled-text-field\n >\n </div>\n\n <md-elevated-button id=\"submit-button\" type=\"button\" @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"${this.submitButtonLabel}\"></ox-i18n>\n </md-elevated-button>\n\n ${!disableUserFavoredLanguage\n ? html` <div id=\"locale-area\">\n <label for=\"locale-selector\"><md-icon>language</md-icon></label>\n <ox-i18n-selector\n id=\"locale-selector\"\n value=${i18next.language || 'en-US'}\n .languages=${languages}\n @change=${e => {\n var locale = e.detail\n if (!locale) return\n\n i18next.changeLanguage(locale)\n }}\n ></ox-i18n-selector>\n </div>`\n : nothing}\n </form>\n </div>\n </div>\n\n <ox-snack-bar id=\"snackbar\" level=\"error\" .message=${this.message}></ox-snack-bar>\n `\n }\n\n updated(changed) {\n super.updated(changed)\n\n if (changed.has('data')) {\n this.token = this.data.token\n }\n\n if (changed.has('message')) {\n if (!this.message) {\n this.hideSnackbar()\n } else {\n this.showSnackbar({\n timer: -1\n })\n }\n }\n }\n\n languageUpdated() {\n this.passwordPattern = generatePasswordPatternRegExp(this.data.passwordRule).source\n this.passwordHelp = generatePasswordPatternHelp(this.data.passwordRule)\n }\n\n async submit() {\n this.formEl.submit()\n }\n}\n"]}
|
|
@@ -25,30 +25,31 @@ export class AbstractSign extends AbstractAuthPage {
|
|
|
25
25
|
}
|
|
26
26
|
get formfields() {
|
|
27
27
|
var _a;
|
|
28
|
-
const
|
|
28
|
+
const username = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.username) || '';
|
|
29
29
|
const autocompletable = this.autocompletable;
|
|
30
30
|
return html `
|
|
31
31
|
<input id="redirectTo" type="hidden" name="redirectTo" .value=${this.redirectTo || '/'} />
|
|
32
32
|
|
|
33
33
|
<div class="field">
|
|
34
34
|
<md-filled-text-field
|
|
35
|
-
name="
|
|
36
|
-
type="
|
|
37
|
-
label=${String(i18next.t('field.email'))}
|
|
35
|
+
name="username"
|
|
36
|
+
type="text"
|
|
37
|
+
label=${String(i18next.t('field.user-id or email'))}
|
|
38
38
|
required
|
|
39
|
-
.value=${
|
|
40
|
-
autocomplete=${autocompletable ?
|
|
39
|
+
.value=${username}
|
|
40
|
+
autocomplete=${autocompletable ? 'username' : 'off'}
|
|
41
41
|
autocapitalize="off"
|
|
42
|
+
pattern="^(?:[A-Za-z0-9]*|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,})$"
|
|
42
43
|
@input=${(e) => {
|
|
43
44
|
const target = e.target;
|
|
44
45
|
if (target.validity.typeMismatch) {
|
|
45
|
-
target.setCustomValidity(i18next.t('text.invalid-
|
|
46
|
+
target.setCustomValidity(i18next.t('text.invalid-username'));
|
|
46
47
|
}
|
|
47
48
|
else {
|
|
48
49
|
target.setCustomValidity('');
|
|
49
50
|
}
|
|
50
51
|
}}
|
|
51
|
-
><md-icon slot="leading-icon">
|
|
52
|
+
><md-icon slot="leading-icon">id_card</md-icon></md-filled-text-field
|
|
52
53
|
>
|
|
53
54
|
</div>
|
|
54
55
|
<div class="field">
|
|
@@ -56,14 +57,14 @@ export class AbstractSign extends AbstractAuthPage {
|
|
|
56
57
|
name="password"
|
|
57
58
|
type="password"
|
|
58
59
|
label=${String(i18next.t('field.password'))}
|
|
59
|
-
autocomplete=${autocompletable ?
|
|
60
|
+
autocomplete=${autocompletable ? 'current-password' : 'off'}
|
|
60
61
|
required
|
|
61
|
-
><md-icon slot="leading-icon">
|
|
62
|
+
><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
|
|
62
63
|
>
|
|
63
64
|
</div>
|
|
64
65
|
|
|
65
66
|
<div class="submit-buttons-container">
|
|
66
|
-
<md-elevated-button class="submit-button" type="
|
|
67
|
+
<md-elevated-button class="submit-button" type="button" raised @click=${e => this._onSubmit(e)}>
|
|
67
68
|
<ox-i18n msgid="field.${this.pageName}"> </ox-i18n>
|
|
68
69
|
</md-elevated-button>
|
|
69
70
|
${isAvailableWebauthn
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract-sign.js","sourceRoot":"","sources":["../../client/components/abstract-sign.ts"],"names":[],"mappings":"AAAA,OAAO,0BAA0B,CAAA;AAEjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAE7D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,MAAM,mBAAmB,GAAG,qBAAqB,IAAI,MAAM,CAAA;AAe3D,MAAM,OAAgB,YAAa,SAAQ,gBAAgB;IACzD,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;IACtB,CAAC;IAED,OAAO,CAAC,OAAO;QACb,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAEtB,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,IAAI,CAAC,YAAY,EAAE,CAAA;YACrB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,YAAY,CAAC;oBAChB,KAAK,EAAE,OAAO;oBACd,KAAK,EAAE,CAAC,CAAC;iBACV,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,UAAU;;QACZ,MAAM,
|
|
1
|
+
{"version":3,"file":"abstract-sign.js","sourceRoot":"","sources":["../../client/components/abstract-sign.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/i18n/ox-i18n.js'\n\nimport { html, nothing } from 'lit'\nimport { startAuthentication } from '@simplewebauthn/browser'\n\nimport { i18next } from '@operato/i18n'\nimport { notify } from '@operato/layout'\n\nimport { AbstractAuthPage } from './abstract-auth-page.js'\n\nconst isAvailableWebauthn = 'PublicKeyCredential' in window\n\ninterface AssertionResponse {\n id: string\n rawId?: number[]\n response: {\n authenticatorData: string\n clientDataJSON: string\n signature: string\n userHandle: string | null\n }\n type: PublicKeyCredentialType\n authenticatorAttachment?: AuthenticatorAttachment\n}\n\nexport abstract class AbstractSign extends AbstractAuthPage {\n async submit() {\n this.formEl.submit()\n }\n\n updated(changed) {\n super.updated(changed)\n\n if (changed.has('message')) {\n if (!this.message) {\n this.hideSnackbar()\n } else {\n this.showSnackbar({\n level: 'error',\n timer: -1\n })\n }\n }\n }\n\n get formfields() {\n const username = this.data?.username || ''\n const autocompletable = this.autocompletable\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <md-filled-text-field\n name=\"username\"\n type=\"text\"\n label=${String(i18next.t('field.user-id or email'))}\n required\n .value=${username}\n autocomplete=${autocompletable ? 'username' : 'off'}\n autocapitalize=\"off\"\n pattern=\"^(?:[A-Za-z0-9]*|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,})$\"\n @input=${(e: Event) => {\n const target = e.target as HTMLInputElement\n if (target.validity.typeMismatch) {\n target.setCustomValidity(i18next.t('text.invalid-username'))\n } else {\n target.setCustomValidity('')\n }\n }}\n ><md-icon slot=\"leading-icon\">id_card</md-icon></md-filled-text-field\n >\n </div>\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('field.password'))}\n autocomplete=${autocompletable ? 'current-password' : 'off'}\n required\n ><md-icon slot=\"leading-icon\">password</md-icon></md-filled-text-field\n >\n </div>\n\n <div class=\"submit-buttons-container\">\n <md-elevated-button class=\"submit-button\" type=\"button\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </md-elevated-button>\n ${isAvailableWebauthn\n ? html` <md-icon class=\"fingerprint\" raised @click=${e => this.authenticateUser()}> fingerprint </md-icon>`\n : nothing}\n </div>\n `\n }\n\n async authenticateUser() {\n try {\n const options = await fetch('/auth/signin-webauthn/challenge').then(res => res.json())\n const assertionResp = await startAuthentication(options)\n const verification = await fetch('/auth/signin-webauthn', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(assertionResp)\n }).then(res => res.json())\n\n if (verification.verified) {\n const { redirectURL } = verification\n\n if (redirectURL) {\n window.location.href = redirectURL\n }\n } else {\n notify({\n level: 'error',\n message: verification.message\n })\n }\n } catch (error) {\n notify({\n level: 'error',\n message: i18next.t('error.authn verification failed')\n })\n }\n }\n}\n"]}
|