@things-factory/auth-ui 7.0.1-alpha.9 → 7.0.1-alpha.90
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/auth-style-sign.ts +29 -18
- package/client/bootstrap.ts +6 -10
- package/client/components/abstract-auth-page.ts +41 -22
- package/client/components/abstract-password-reset.ts +11 -9
- package/client/components/abstract-sign.ts +138 -0
- package/client/components/change-password.ts +3 -3
- package/client/components/contact-us.ts +19 -23
- package/client/components/create-domain-popup.ts +11 -7
- package/client/components/create-role.ts +8 -20
- package/client/components/create-user.ts +8 -16
- package/client/components/credential-manager.ts +64 -0
- package/client/components/delete-user-popup.ts +1 -1
- package/client/components/domain-switch.ts +7 -4
- package/client/components/invite-customer.ts +7 -14
- package/client/components/invite-user.ts +2 -7
- package/client/components/ownership-transfer-popup.ts +3 -3
- package/client/components/partner-role-editor.ts +10 -16
- package/client/components/profile-component.ts +124 -7
- package/client/components/role-privilege-editor.ts +10 -17
- package/client/components/user-role-editor.ts +27 -38
- package/client/entries/auth/activate.ts +17 -17
- package/client/entries/auth/checkin.ts +15 -19
- package/client/entries/auth/forgot-password.ts +8 -6
- package/client/entries/auth/result.ts +13 -12
- package/client/entries/auth/signup.ts +20 -24
- package/client/entries/oauth2/oauth2-decision-error-page.ts +2 -2
- package/client/entries/oauth2/oauth2-decision-page.ts +60 -55
- package/client/entries/public/home.ts +40 -18
- package/client/index.ts +93 -66
- package/client/pages/app-binding/app-binding.ts +5 -9
- package/client/pages/app-binding/app-bindings.ts +2 -2
- package/client/pages/appliance/appliance.ts +6 -9
- package/client/pages/appliance/home.ts +3 -3
- package/client/pages/appliance/register.ts +1 -1
- package/client/pages/application/application.ts +29 -50
- package/client/pages/application/applications.ts +4 -12
- package/client/pages/application/register.ts +1 -1
- package/client/pages/attribute/attribute-set-item-list.ts +8 -22
- package/client/pages/attribute/attribute-set-management.ts +14 -20
- package/client/pages/auth-provider/auth-provider-management.ts +10 -16
- package/client/pages/domain/domain-management.ts +4 -9
- package/client/pages/user/user-management.ts +5 -5
- package/dist-client/auth-style-sign.js +29 -18
- package/dist-client/auth-style-sign.js.map +1 -1
- package/dist-client/bootstrap.d.ts +1 -1
- package/dist-client/bootstrap.js +5 -5
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/components/abstract-auth-page.d.ts +4 -4
- package/dist-client/components/abstract-auth-page.js +40 -22
- package/dist-client/components/abstract-auth-page.js.map +1 -1
- package/dist-client/components/abstract-password-reset.d.ts +3 -2
- package/dist-client/components/abstract-password-reset.js +10 -9
- package/dist-client/components/abstract-password-reset.js.map +1 -1
- package/dist-client/components/abstract-sign.d.ts +3 -0
- package/dist-client/components/abstract-sign.js +110 -0
- package/dist-client/components/abstract-sign.js.map +1 -1
- package/dist-client/components/change-password.js +3 -3
- package/dist-client/components/change-password.js.map +1 -1
- package/dist-client/components/contact-us.d.ts +4 -4
- package/dist-client/components/contact-us.js +18 -23
- package/dist-client/components/contact-us.js.map +1 -1
- package/dist-client/components/create-domain-popup.d.ts +1 -1
- package/dist-client/components/create-domain-popup.js +11 -7
- package/dist-client/components/create-domain-popup.js.map +1 -1
- package/dist-client/components/create-role.d.ts +1 -1
- package/dist-client/components/create-role.js +7 -19
- package/dist-client/components/create-role.js.map +1 -1
- package/dist-client/components/create-user.js +6 -14
- package/dist-client/components/create-user.js.map +1 -1
- package/dist-client/components/credential-manager.d.ts +11 -0
- package/dist-client/components/credential-manager.js +64 -0
- package/dist-client/components/credential-manager.js.map +1 -0
- package/dist-client/components/delete-user-popup.js +1 -1
- package/dist-client/components/delete-user-popup.js.map +1 -1
- package/dist-client/components/domain-switch.d.ts +2 -0
- package/dist-client/components/domain-switch.js +9 -4
- package/dist-client/components/domain-switch.js.map +1 -1
- package/dist-client/components/invite-customer.d.ts +1 -1
- package/dist-client/components/invite-customer.js +5 -8
- package/dist-client/components/invite-customer.js.map +1 -1
- package/dist-client/components/invite-user.js +2 -7
- package/dist-client/components/invite-user.js.map +1 -1
- package/dist-client/components/ownership-transfer-popup.d.ts +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/partner-role-editor.d.ts +1 -1
- package/dist-client/components/partner-role-editor.js +10 -16
- package/dist-client/components/partner-role-editor.js.map +1 -1
- package/dist-client/components/profile-component.d.ts +6 -0
- package/dist-client/components/profile-component.js +111 -7
- package/dist-client/components/profile-component.js.map +1 -1
- package/dist-client/components/role-privilege-editor.js +10 -17
- package/dist-client/components/role-privilege-editor.js.map +1 -1
- package/dist-client/components/user-role-editor.d.ts +2 -0
- package/dist-client/components/user-role-editor.js +26 -37
- package/dist-client/components/user-role-editor.js.map +1 -1
- package/dist-client/entries/auth/activate.d.ts +2 -1
- package/dist-client/entries/auth/activate.js +16 -17
- package/dist-client/entries/auth/activate.js.map +1 -1
- package/dist-client/entries/auth/checkin.d.ts +2 -2
- package/dist-client/entries/auth/checkin.js +13 -16
- package/dist-client/entries/auth/checkin.js.map +1 -1
- package/dist-client/entries/auth/forgot-password.d.ts +2 -1
- package/dist-client/entries/auth/forgot-password.js +7 -6
- package/dist-client/entries/auth/forgot-password.js.map +1 -1
- package/dist-client/entries/auth/result.d.ts +2 -2
- package/dist-client/entries/auth/result.js +12 -12
- package/dist-client/entries/auth/result.js.map +1 -1
- package/dist-client/entries/auth/signup.js +19 -24
- package/dist-client/entries/auth/signup.js.map +1 -1
- package/dist-client/entries/oauth2/oauth2-decision-error-page.d.ts +1 -1
- package/dist-client/entries/oauth2/oauth2-decision-error-page.js +2 -2
- package/dist-client/entries/oauth2/oauth2-decision-error-page.js.map +1 -1
- package/dist-client/entries/oauth2/oauth2-decision-page.d.ts +1 -1
- package/dist-client/entries/oauth2/oauth2-decision-page.js +59 -54
- package/dist-client/entries/oauth2/oauth2-decision-page.js.map +1 -1
- package/dist-client/entries/public/home.d.ts +3 -2
- package/dist-client/entries/public/home.js +40 -18
- package/dist-client/entries/public/home.js.map +1 -1
- package/dist-client/index.d.ts +11 -2
- package/dist-client/index.js +74 -66
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/app-binding/app-binding.d.ts +1 -1
- package/dist-client/pages/app-binding/app-binding.js +4 -9
- package/dist-client/pages/app-binding/app-binding.js.map +1 -1
- package/dist-client/pages/app-binding/app-bindings.js +2 -2
- package/dist-client/pages/app-binding/app-bindings.js.map +1 -1
- package/dist-client/pages/appliance/appliance.d.ts +1 -1
- package/dist-client/pages/appliance/appliance.js +5 -9
- package/dist-client/pages/appliance/appliance.js.map +1 -1
- package/dist-client/pages/appliance/home.js +3 -3
- package/dist-client/pages/appliance/home.js.map +1 -1
- package/dist-client/pages/appliance/register.js +1 -1
- package/dist-client/pages/appliance/register.js.map +1 -1
- package/dist-client/pages/application/application.d.ts +1 -1
- package/dist-client/pages/application/application.js +28 -50
- package/dist-client/pages/application/application.js.map +1 -1
- package/dist-client/pages/application/applications.js +4 -12
- package/dist-client/pages/application/applications.js.map +1 -1
- package/dist-client/pages/application/register.js +1 -1
- package/dist-client/pages/application/register.js.map +1 -1
- package/dist-client/pages/attribute/attribute-set-item-list.d.ts +1 -1
- package/dist-client/pages/attribute/attribute-set-item-list.js +6 -22
- package/dist-client/pages/attribute/attribute-set-item-list.js.map +1 -1
- package/dist-client/pages/attribute/attribute-set-management.d.ts +11 -2
- package/dist-client/pages/attribute/attribute-set-management.js +7 -11
- package/dist-client/pages/attribute/attribute-set-management.js.map +1 -1
- package/dist-client/pages/auth-provider/auth-provider-management.d.ts +11 -2
- package/dist-client/pages/auth-provider/auth-provider-management.js +8 -11
- package/dist-client/pages/auth-provider/auth-provider-management.js.map +1 -1
- package/dist-client/pages/domain/domain-management.d.ts +1 -0
- package/dist-client/pages/domain/domain-management.js +3 -7
- package/dist-client/pages/domain/domain-management.js.map +1 -1
- package/dist-client/pages/user/user-management.d.ts +1 -0
- package/dist-client/pages/user/user-management.js +4 -5
- 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 +8 -12
- package/translations/en.json +1 -0
- package/translations/ja.json +1 -0
- package/translations/ko.json +1 -0
- package/translations/ms.json +1 -0
- package/translations/zh.json +1 -0
- package/views/auth-page.html +3 -2
- package/views/oauth2-page.html +3 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import '@material/
|
|
1
|
+
import '@material/web/textfield/filled-text-field.js'
|
|
2
2
|
|
|
3
3
|
import gql from 'graphql-tag'
|
|
4
4
|
import { css, html, LitElement } from 'lit'
|
|
@@ -12,7 +12,7 @@ import { OxPrompt } from '@operato/popup/ox-prompt.js'
|
|
|
12
12
|
class CreateRole extends localize(i18next)(LitElement) {
|
|
13
13
|
static styles = css`
|
|
14
14
|
:host {
|
|
15
|
-
--
|
|
15
|
+
--md-text-field-fill-color: var(--theme-white-color);
|
|
16
16
|
background-color: var(--theme-white-color);
|
|
17
17
|
margin: var(--margin-wide) 0;
|
|
18
18
|
padding: var(--padding-wide);
|
|
@@ -28,7 +28,7 @@ class CreateRole extends localize(i18next)(LitElement) {
|
|
|
28
28
|
align-items: center;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
md-outlined-button {
|
|
32
32
|
margin: var(--input-margin);
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -37,7 +37,7 @@ class CreateRole extends localize(i18next)(LitElement) {
|
|
|
37
37
|
grid-template-columns: 1fr 1fr;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
md-outlined-button {
|
|
41
41
|
grid-column: span 2;
|
|
42
42
|
|
|
43
43
|
margin: var(--input-margin);
|
|
@@ -50,22 +50,10 @@ class CreateRole extends localize(i18next)(LitElement) {
|
|
|
50
50
|
|
|
51
51
|
render() {
|
|
52
52
|
return html`
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
></mwc-textfield>
|
|
58
|
-
<mwc-textfield
|
|
59
|
-
type="text"
|
|
60
|
-
name="description"
|
|
61
|
-
label=${String(i18next.t('label.x description', { x: i18next.t('label.role') }))}
|
|
62
|
-
></mwc-textfield>
|
|
63
|
-
|
|
64
|
-
<mwc-button
|
|
65
|
-
@click=${this.onCreateRole.bind(this)}
|
|
66
|
-
outlined
|
|
67
|
-
label=${String(i18next.t('button.create'))}
|
|
68
|
-
></mwc-button>
|
|
53
|
+
<md-filled-text-field type="text" name="name" label=${String(i18next.t('label.x name', { x: i18next.t('label.role') }))}></md-filled-text-field>
|
|
54
|
+
<md-filled-text-field type="text" name="description" label=${String(i18next.t('label.x description', { x: i18next.t('label.role') }))}></md-filled-text-field>
|
|
55
|
+
|
|
56
|
+
<md-outlined-button @click=${this.onCreateRole.bind(this)}>${String(i18next.t('button.create'))}</md-outlined-button>
|
|
69
57
|
`
|
|
70
58
|
}
|
|
71
59
|
|
|
@@ -7,7 +7,7 @@ import { i18next } from '@operato/i18n'
|
|
|
7
7
|
class CreateUser extends LitElement {
|
|
8
8
|
static styles = css`
|
|
9
9
|
:host {
|
|
10
|
-
--
|
|
10
|
+
--md-text-field-fill-color: var(--theme-white-color);
|
|
11
11
|
background-color: var(--theme-white-color);
|
|
12
12
|
margin: var(--margin-wide) 0;
|
|
13
13
|
padding: var(--padding-wide);
|
|
@@ -23,7 +23,7 @@ class CreateUser extends LitElement {
|
|
|
23
23
|
align-items: center;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
md-outlined-button {
|
|
27
27
|
margin: var(--input-margin);
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -32,7 +32,7 @@ class CreateUser extends LitElement {
|
|
|
32
32
|
grid-template-columns: 1fr 1fr;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
md-outlined-button {
|
|
36
36
|
grid-column: span 2;
|
|
37
37
|
|
|
38
38
|
margin: var(--input-margin);
|
|
@@ -45,19 +45,11 @@ class CreateUser extends LitElement {
|
|
|
45
45
|
|
|
46
46
|
render() {
|
|
47
47
|
return html`
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<mwc-textfield type="email" name="email" label=${String(i18next.t('field.email'))}></mwc-textfield>
|
|
55
|
-
|
|
56
|
-
<mwc-button
|
|
57
|
-
@click=${this.onCreateUser.bind(this)}
|
|
58
|
-
outlined
|
|
59
|
-
label=${String(i18next.t('button.create'))}
|
|
60
|
-
></mwc-button>
|
|
48
|
+
<md-outlined-text-field type="text" name="name" label=${String(i18next.t('label.x name', { x: i18next.t('label.user') }))}></md-outlined-text-field>
|
|
49
|
+
|
|
50
|
+
<md-outlined-text-field type="email" name="email" label=${String(i18next.t('field.email'))}></md-outlined-text-field>
|
|
51
|
+
|
|
52
|
+
<md-outlined-button @click=${this.onCreateUser.bind(this)}>${String(i18next.t('button.create'))}</md-outlined-button>
|
|
61
53
|
`
|
|
62
54
|
}
|
|
63
55
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import gql from 'graphql-tag'
|
|
2
|
+
import { LitElement, html, css } from 'lit'
|
|
3
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
4
|
+
|
|
5
|
+
import { client } from '@operato/graphql'
|
|
6
|
+
|
|
7
|
+
@customElement('credential-manager')
|
|
8
|
+
export class CredentialManager extends LitElement {
|
|
9
|
+
@property({ type: Array }) credentials: {
|
|
10
|
+
credentialId: string
|
|
11
|
+
}[] = []
|
|
12
|
+
|
|
13
|
+
static styles = css`
|
|
14
|
+
div {
|
|
15
|
+
margin: 20px;
|
|
16
|
+
}
|
|
17
|
+
button {
|
|
18
|
+
margin: 5px;
|
|
19
|
+
}
|
|
20
|
+
`
|
|
21
|
+
|
|
22
|
+
connectedCallback() {
|
|
23
|
+
super.connectedCallback()
|
|
24
|
+
this.fetchCredentials()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async fetchCredentials() {
|
|
28
|
+
const response = await fetch('/auth/credentials', {
|
|
29
|
+
method: 'GET',
|
|
30
|
+
credentials: 'include'
|
|
31
|
+
})
|
|
32
|
+
this.credentials = await response.json()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async deleteCredential(credentialId: string) {
|
|
36
|
+
const response = await fetch(`/credentials/${credentialId}`, {
|
|
37
|
+
method: 'DELETE',
|
|
38
|
+
credentials: 'include'
|
|
39
|
+
})
|
|
40
|
+
if (response.ok) {
|
|
41
|
+
this.fetchCredentials()
|
|
42
|
+
} else {
|
|
43
|
+
console.error('Failed to delete credential')
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
render() {
|
|
48
|
+
return html`
|
|
49
|
+
<div>
|
|
50
|
+
<h2>Manage Your WebAuthn Credentials</h2>
|
|
51
|
+
<ul>
|
|
52
|
+
${this.credentials.map(
|
|
53
|
+
credential => html`
|
|
54
|
+
<li>
|
|
55
|
+
${credential.credentialId}
|
|
56
|
+
<button @click=${() => this.deleteCredential(credential.credentialId)}>Delete</button>
|
|
57
|
+
</li>
|
|
58
|
+
`
|
|
59
|
+
)}
|
|
60
|
+
</ul>
|
|
61
|
+
</div>
|
|
62
|
+
`
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -5,7 +5,7 @@ import { customElement } from 'lit/decorators.js'
|
|
|
5
5
|
|
|
6
6
|
import { i18next, localize } from '@operato/i18n'
|
|
7
7
|
import { notify } from '@operato/layout'
|
|
8
|
-
import { auth } from '@things-factory/auth-base/dist-client'
|
|
8
|
+
import { auth } from '@things-factory/auth-base/dist-client/auth.js'
|
|
9
9
|
|
|
10
10
|
@customElement('delete-user-popup')
|
|
11
11
|
export class DeleteUserPopup extends localize(i18next)(LitElement) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import '@material/web/icon/icon.js'
|
|
2
|
+
|
|
3
|
+
import { css, html, LitElement, nothing } from 'lit'
|
|
2
4
|
import { customElement, property } from 'lit/decorators.js'
|
|
3
5
|
import { connect } from 'pwa-helpers/connect-mixin'
|
|
4
6
|
|
|
@@ -28,7 +30,7 @@ export class DomainSwitch extends connect(store)(LitElement) {
|
|
|
28
30
|
padding: var(--padding-default);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
md-icon {
|
|
32
34
|
background-color: rgba(var(--primary-color-rgb), 0.8);
|
|
33
35
|
margin-right: var(--margin-narrow);
|
|
34
36
|
padding: 2px;
|
|
@@ -56,7 +58,7 @@ export class DomainSwitch extends connect(store)(LitElement) {
|
|
|
56
58
|
padding: 0 !important;
|
|
57
59
|
border-bottom: none;
|
|
58
60
|
}
|
|
59
|
-
:host([dark])
|
|
61
|
+
:host([dark]) md-icon {
|
|
60
62
|
background-color: var(--secondary-text-color);
|
|
61
63
|
margin: 1px 4px 0px 0px;
|
|
62
64
|
padding: 1px 2px;
|
|
@@ -90,6 +92,7 @@ export class DomainSwitch extends connect(store)(LitElement) {
|
|
|
90
92
|
@property({ type: Array }) domains: any[] = []
|
|
91
93
|
@property({ type: Object }) domain: any
|
|
92
94
|
@property({ type: String, attribute: true }) attrname: string = 'name'
|
|
95
|
+
@property({ type: String, attribute: true }) icon?: string
|
|
93
96
|
|
|
94
97
|
render() {
|
|
95
98
|
const domains = this.domains || []
|
|
@@ -98,7 +101,7 @@ export class DomainSwitch extends connect(store)(LitElement) {
|
|
|
98
101
|
|
|
99
102
|
return html`
|
|
100
103
|
<div>
|
|
101
|
-
|
|
104
|
+
${this.icon ? html`<md-icon>${this.icon}</md-icon>` : nothing}
|
|
102
105
|
${domains.length <= 1
|
|
103
106
|
? html` <span>${domains[0]?.[attrname] || domain.name}</span> `
|
|
104
107
|
: html`
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import '@things-factory/auth-ui'
|
|
2
|
-
|
|
3
1
|
import gql from 'graphql-tag'
|
|
4
2
|
import { css, html, LitElement } from 'lit'
|
|
5
3
|
import { customElement, property, query } from 'lit/decorators.js'
|
|
@@ -20,7 +18,7 @@ class InviteCustomer extends localize(i18next)(LitElement) {
|
|
|
20
18
|
min-width: 250px;
|
|
21
19
|
font: var(--input-font);
|
|
22
20
|
}
|
|
23
|
-
|
|
21
|
+
md-outlined-button {
|
|
24
22
|
margin: var(--input-margin);
|
|
25
23
|
}
|
|
26
24
|
@media screen and (max-width: 480px) {
|
|
@@ -39,25 +37,20 @@ class InviteCustomer extends localize(i18next)(LitElement) {
|
|
|
39
37
|
return html`
|
|
40
38
|
<div>
|
|
41
39
|
<input id="customer-name" required />
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
label=${String(i18next.t('label.invite customer'))}
|
|
47
|
-
></mwc-button>
|
|
40
|
+
<md-outlined-button @click=${this.invite.bind(this)}>
|
|
41
|
+
<md-icon slot="icon">group_add</md-icon>
|
|
42
|
+
${String(i18next.t('label.invite customer'))}
|
|
43
|
+
</md-outlined-button>
|
|
48
44
|
</div>
|
|
49
45
|
`
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
async invite() {
|
|
53
49
|
try {
|
|
54
|
-
if (!this.customerNameInput.value)
|
|
55
|
-
throw new Error(i18next.t('error.value is empty', { value: i18next.t('field.name') }))
|
|
50
|
+
if (!this.customerNameInput.value) throw new Error(i18next.t('error.value is empty', { value: i18next.t('field.name') }))
|
|
56
51
|
|
|
57
52
|
if (this.customers.find(c => c.name?.toLowerCase() === this.customerNameInput.value.toLowerCase())) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
i18next.t('error.x already exists in y', { x: this.customerNameInput.value, y: i18next.t('field.customer') })
|
|
60
|
-
)
|
|
53
|
+
throw new Error(i18next.t('error.x already exists in y', { x: this.customerNameInput.value, y: i18next.t('field.customer') }))
|
|
61
54
|
}
|
|
62
55
|
|
|
63
56
|
if (
|
|
@@ -26,7 +26,7 @@ class InviteUser extends localize(i18next)(LitElement) {
|
|
|
26
26
|
font: var(--input-font);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
md-outlined-button {
|
|
30
30
|
margin: var(--input-margin);
|
|
31
31
|
}
|
|
32
32
|
`
|
|
@@ -36,12 +36,7 @@ class InviteUser extends localize(i18next)(LitElement) {
|
|
|
36
36
|
render() {
|
|
37
37
|
return html`
|
|
38
38
|
<input name="email" type="email" required name="invite-email" autocapitalize="off" />
|
|
39
|
-
<
|
|
40
|
-
@click=${this.invite.bind(this)}
|
|
41
|
-
outlined
|
|
42
|
-
icon="group_add"
|
|
43
|
-
label=${String(i18next.t('label.invite user'))}
|
|
44
|
-
></mwc-button>
|
|
39
|
+
<md-outlined-button @click=${this.invite.bind(this)}> <md-icon slot="icon">group_add</md-icon>${String(i18next.t('label.invite user'))} </md-outlined-button>
|
|
45
40
|
`
|
|
46
41
|
}
|
|
47
42
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import '@material/
|
|
1
|
+
import '@material/web/button/elevated-button.js'
|
|
2
2
|
|
|
3
3
|
import gql from 'graphql-tag'
|
|
4
4
|
import { css, html, LitElement } from 'lit'
|
|
@@ -36,7 +36,7 @@ class OwnershipTransferPopup extends localize(i18next)(LitElement) {
|
|
|
36
36
|
margin: auto;
|
|
37
37
|
display: flex;
|
|
38
38
|
}
|
|
39
|
-
.input-container
|
|
39
|
+
.input-container md-elevated-button {
|
|
40
40
|
margin: auto 0px auto var(--padding-wide);
|
|
41
41
|
}
|
|
42
42
|
`
|
|
@@ -52,7 +52,7 @@ class OwnershipTransferPopup extends localize(i18next)(LitElement) {
|
|
|
52
52
|
<div>${i18next.t('text.please enter the email of the user you want to transfer owner')}</div>
|
|
53
53
|
<div class="input-container">
|
|
54
54
|
<input name="email" />
|
|
55
|
-
<
|
|
55
|
+
<md-elevated-button @click=${this.transferOwnership}>${i18next.t('button.confirm')}</md-elevated-button>
|
|
56
56
|
</div>
|
|
57
57
|
</div>
|
|
58
58
|
`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '@material/mwc-icon'
|
|
2
|
-
import '
|
|
2
|
+
import './role-selector.js'
|
|
3
3
|
|
|
4
4
|
import gql from 'graphql-tag'
|
|
5
5
|
import { css, html, LitElement } from 'lit'
|
|
@@ -8,12 +8,14 @@ import { customElement, property, query } from 'lit/decorators.js'
|
|
|
8
8
|
import { client, gqlContext } from '@operato/graphql'
|
|
9
9
|
import { i18next, localize } from '@operato/i18n'
|
|
10
10
|
import { OxPrompt } from '@operato/popup/ox-prompt.js'
|
|
11
|
+
import { ButtonContainerStyles } from '@operato/styles'
|
|
11
12
|
|
|
12
13
|
import { RoleSelector } from './role-selector'
|
|
13
14
|
|
|
14
15
|
@customElement('partner-role-editor')
|
|
15
16
|
class PartnerRoleEditor extends localize(i18next)(LitElement) {
|
|
16
17
|
static styles = [
|
|
18
|
+
ButtonContainerStyles,
|
|
17
19
|
css`
|
|
18
20
|
:host {
|
|
19
21
|
display: flex;
|
|
@@ -24,16 +26,13 @@ class PartnerRoleEditor extends localize(i18next)(LitElement) {
|
|
|
24
26
|
font: normal 15px var(--theme-font);
|
|
25
27
|
color: var(--secondary-color);
|
|
26
28
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
padding: var(--padding-default);
|
|
30
|
-
background-color: rgba(var(--primary-color-rgb), 0.2);
|
|
31
|
-
}
|
|
32
|
-
mwc-button {
|
|
29
|
+
|
|
30
|
+
md-elevated-button {
|
|
33
31
|
margin-right: var(--padding-narrow);
|
|
34
32
|
}
|
|
33
|
+
|
|
35
34
|
[danger] {
|
|
36
|
-
--
|
|
35
|
+
--md-theme-primary: var(--md-danger-button-primary-color);
|
|
37
36
|
}
|
|
38
37
|
`
|
|
39
38
|
]
|
|
@@ -51,14 +50,9 @@ class PartnerRoleEditor extends localize(i18next)(LitElement) {
|
|
|
51
50
|
return html`
|
|
52
51
|
<role-selector .roles="${roles}" .userRoles="${grantingRoles}"></role-selector>
|
|
53
52
|
|
|
54
|
-
<div
|
|
55
|
-
<
|
|
56
|
-
<
|
|
57
|
-
@click=${this.onTerminateContract}
|
|
58
|
-
raised
|
|
59
|
-
danger
|
|
60
|
-
label="${i18next.t('button.terminate contract')}"
|
|
61
|
-
></mwc-button>
|
|
53
|
+
<div class="button-container">
|
|
54
|
+
<md-elevated-button @click=${this.onSave}>${i18next.t('button.save')}</md-elevated-button>
|
|
55
|
+
<md-elevated-button @click=${this.onTerminateContract} danger>${i18next.t('button.terminate contract')}</md-elevated-button>
|
|
62
56
|
</div>
|
|
63
57
|
`
|
|
64
58
|
}
|
|
@@ -4,13 +4,15 @@ import './change-password'
|
|
|
4
4
|
import './delete-user-popup'
|
|
5
5
|
import './my-login-history'
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import base64url from 'base64url'
|
|
8
|
+
import { css, html, LitElement, nothing } from 'lit'
|
|
8
9
|
import { customElement, property, query, state } from 'lit/decorators.js'
|
|
9
10
|
|
|
10
11
|
import { i18next, localize } from '@operato/i18n'
|
|
11
12
|
import { notify, openPopup } from '@operato/layout'
|
|
12
13
|
import { auth, getLanguages } from '@things-factory/auth-base/dist-client'
|
|
13
14
|
|
|
15
|
+
const isAvailableWebauthn = 'PublicKeyCredential' in window
|
|
14
16
|
@customElement('profile-component')
|
|
15
17
|
export class ProfileComponent extends localize(i18next)(LitElement) {
|
|
16
18
|
static styles = [
|
|
@@ -36,12 +38,12 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
input {
|
|
39
|
-
margin: var(--
|
|
40
|
-
border:
|
|
41
|
-
padding:
|
|
41
|
+
margin: var(--margin-narrow) 0;
|
|
42
|
+
border: 1px solid rgba(0, 0, 0, 0.2);
|
|
43
|
+
padding: 9px;
|
|
42
44
|
border-radius: var(--border-radius);
|
|
43
|
-
font: var(--input-font);
|
|
44
|
-
width: var(--
|
|
45
|
+
font: var(--auth-input-field-font);
|
|
46
|
+
width: var(--auth-input-field-width);
|
|
45
47
|
}
|
|
46
48
|
input:focus {
|
|
47
49
|
border: 1px solid var(--focus-background-color);
|
|
@@ -85,7 +87,7 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
[danger] {
|
|
88
|
-
--
|
|
90
|
+
--md-theme-primary: var(--md-danger-button-primary-color);
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
footer {
|
|
@@ -160,6 +162,14 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
|
|
|
160
162
|
|
|
161
163
|
<change-password id="change-password"></change-password>
|
|
162
164
|
|
|
165
|
+
${isAvailableWebauthn
|
|
166
|
+
? html`
|
|
167
|
+
<md-text-button @click=${() => this.registerWebAuthn()}
|
|
168
|
+
>${i18next.t('button.security-key registration')}</md-text-button
|
|
169
|
+
>
|
|
170
|
+
`
|
|
171
|
+
: nothing}
|
|
172
|
+
|
|
163
173
|
<footer>
|
|
164
174
|
<p>
|
|
165
175
|
${i18next.t('text.click login history')}
|
|
@@ -233,4 +243,111 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
|
|
|
233
243
|
title: i18next.t('label.delete account')
|
|
234
244
|
})
|
|
235
245
|
}
|
|
246
|
+
|
|
247
|
+
async registerWebAuthn() {
|
|
248
|
+
const challenge = await fetch('/auth/register-webauthn/challenge', {
|
|
249
|
+
method: 'POST',
|
|
250
|
+
headers: {
|
|
251
|
+
'Content-Type': 'application/json',
|
|
252
|
+
Accept: 'application/json'
|
|
253
|
+
},
|
|
254
|
+
body: JSON.stringify({ email: this.email }),
|
|
255
|
+
credentials: 'include'
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
if (!challenge.ok) {
|
|
259
|
+
notify({
|
|
260
|
+
level: 'error',
|
|
261
|
+
message: await challenge.text()
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
return
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const options = await challenge.json()
|
|
268
|
+
|
|
269
|
+
const credential = (await navigator.credentials.create({
|
|
270
|
+
publicKey: {
|
|
271
|
+
rp: {
|
|
272
|
+
name: this.applicationMeta.title
|
|
273
|
+
},
|
|
274
|
+
user: {
|
|
275
|
+
/* options.user.id must be the user's email */
|
|
276
|
+
id: Uint8Array.from(base64url.toBuffer(options.user.id)).buffer,
|
|
277
|
+
name: options.user.name,
|
|
278
|
+
displayName: options.user.displayName
|
|
279
|
+
},
|
|
280
|
+
challenge: Uint8Array.from(atob(options.challenge), c => c.charCodeAt(0)),
|
|
281
|
+
pubKeyCredParams: [
|
|
282
|
+
{
|
|
283
|
+
type: 'public-key',
|
|
284
|
+
alg: -7 // ES256
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
type: 'public-key',
|
|
288
|
+
alg: -257 // RS256
|
|
289
|
+
}
|
|
290
|
+
],
|
|
291
|
+
authenticatorSelection: {
|
|
292
|
+
userVerification: 'preferred'
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
})) as PublicKeyCredential
|
|
296
|
+
|
|
297
|
+
if (!credential) {
|
|
298
|
+
notify({
|
|
299
|
+
level: 'error',
|
|
300
|
+
message: 'can not get user credential'
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
return
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const response = credential.response as AuthenticatorAttestationResponse
|
|
307
|
+
|
|
308
|
+
var body = {
|
|
309
|
+
response: {
|
|
310
|
+
clientDataJSON: Buffer.from(response.clientDataJSON).toString('base64'),
|
|
311
|
+
attestationObject: Buffer.from(response.attestationObject).toString('base64')
|
|
312
|
+
} as any
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (response.getTransports) {
|
|
316
|
+
body.response.transports = response.getTransports()
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const signinResponse = await fetch('/auth/signin-webauthn', {
|
|
320
|
+
method: 'POST',
|
|
321
|
+
headers: {
|
|
322
|
+
'Content-Type': 'application/json',
|
|
323
|
+
Accept: 'application/json'
|
|
324
|
+
},
|
|
325
|
+
body: JSON.stringify(body),
|
|
326
|
+
credentials: 'include'
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
if (!signinResponse.ok) {
|
|
330
|
+
notify({
|
|
331
|
+
level: 'error',
|
|
332
|
+
message: await signinResponse.text()
|
|
333
|
+
})
|
|
334
|
+
} else {
|
|
335
|
+
notify({
|
|
336
|
+
level: 'info',
|
|
337
|
+
message: i18next.t('text.user credential registered successfully')
|
|
338
|
+
})
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
get applicationMeta() {
|
|
343
|
+
var iconLink: HTMLLinkElement | null = document.querySelector('link[rel="application-icon"]')
|
|
344
|
+
var titleMeta: HTMLMetaElement | null = document.querySelector('meta[name="application-name"]')
|
|
345
|
+
var descriptionMeta: HTMLMetaElement | null = document.querySelector('meta[name="application-description"]')
|
|
346
|
+
|
|
347
|
+
return {
|
|
348
|
+
icon: iconLink?.href || '',
|
|
349
|
+
title: titleMeta?.content || 'Things Factory',
|
|
350
|
+
description: descriptionMeta?.content || 'Reimagining Software'
|
|
351
|
+
}
|
|
352
|
+
}
|
|
236
353
|
}
|
|
@@ -5,10 +5,12 @@ import { customElement, property } from 'lit/decorators.js'
|
|
|
5
5
|
import { client, gqlContext } from '@operato/graphql'
|
|
6
6
|
import { i18next, localize } from '@operato/i18n'
|
|
7
7
|
import { OxPrompt } from '@operato/popup/ox-prompt.js'
|
|
8
|
+
import { ButtonContainerStyles } from '@operato/styles'
|
|
8
9
|
|
|
9
10
|
@customElement('role-privilege-editor')
|
|
10
11
|
class RolePrivilegeEditor extends localize(i18next)(LitElement) {
|
|
11
12
|
static styles = [
|
|
13
|
+
ButtonContainerStyles,
|
|
12
14
|
css`
|
|
13
15
|
:host {
|
|
14
16
|
display: flex;
|
|
@@ -49,21 +51,15 @@ class RolePrivilegeEditor extends localize(i18next)(LitElement) {
|
|
|
49
51
|
font-weight: bold;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
margin: 0;
|
|
54
|
-
padding: 5px;
|
|
55
|
-
background-color: rgba(var(--primary-color-rgb), 0.2);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
mwc-button {
|
|
54
|
+
md-elevated-button {
|
|
59
55
|
margin: 5px;
|
|
60
56
|
background-color: var(--theme-white-color);
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
[danger] {
|
|
64
|
-
--
|
|
60
|
+
--md-theme-primary: var(--md-danger-button-primary-color);
|
|
65
61
|
}
|
|
66
|
-
|
|
62
|
+
md-outlined-button {
|
|
67
63
|
background-color: var(--theme-white-color);
|
|
68
64
|
}
|
|
69
65
|
|
|
@@ -106,14 +102,11 @@ class RolePrivilegeEditor extends localize(i18next)(LitElement) {
|
|
|
106
102
|
)}
|
|
107
103
|
</ul>
|
|
108
104
|
|
|
109
|
-
<div
|
|
110
|
-
<
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
danger
|
|
115
|
-
label=${String(i18next.t('button.delete role'))}
|
|
116
|
-
></mwc-button>
|
|
105
|
+
<div class="button-container">
|
|
106
|
+
<md-elevated-button @click=${e => this.onSave()}>${String(i18next.t('button.save'))}</md-elevated-button>
|
|
107
|
+
<md-elevated-button @click=${e => this.onDeleteRole()} danger
|
|
108
|
+
>${String(i18next.t('button.delete role'))}</md-elevated-button
|
|
109
|
+
>
|
|
117
110
|
</div>
|
|
118
111
|
`
|
|
119
112
|
}
|