@things-factory/auth-ui 7.0.1-alpha.88 → 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.
Files changed (143) hide show
  1. package/client/auth-style-sign.ts +29 -18
  2. package/client/components/abstract-auth-page.ts +41 -22
  3. package/client/components/abstract-password-reset.ts +11 -9
  4. package/client/components/abstract-sign.ts +138 -0
  5. package/client/components/change-password.ts +2 -2
  6. package/client/components/contact-us.ts +18 -16
  7. package/client/components/create-domain-popup.ts +11 -7
  8. package/client/components/create-role.ts +8 -20
  9. package/client/components/create-user.ts +8 -16
  10. package/client/components/credential-manager.ts +64 -0
  11. package/client/components/invite-customer.ts +7 -12
  12. package/client/components/invite-user.ts +2 -7
  13. package/client/components/ownership-transfer-popup.ts +3 -3
  14. package/client/components/partner-role-editor.ts +9 -15
  15. package/client/components/profile-component.ts +124 -7
  16. package/client/components/role-privilege-editor.ts +10 -17
  17. package/client/components/user-role-editor.ts +27 -38
  18. package/client/entries/auth/activate.ts +17 -17
  19. package/client/entries/auth/checkin.ts +15 -19
  20. package/client/entries/auth/forgot-password.ts +8 -6
  21. package/client/entries/auth/result.ts +13 -12
  22. package/client/entries/auth/signup.ts +20 -24
  23. package/client/entries/oauth2/oauth2-decision-error-page.ts +2 -2
  24. package/client/entries/oauth2/oauth2-decision-page.ts +60 -55
  25. package/client/entries/public/home.ts +40 -18
  26. package/client/pages/app-binding/app-binding.ts +5 -9
  27. package/client/pages/app-binding/app-bindings.ts +2 -2
  28. package/client/pages/appliance/appliance.ts +6 -9
  29. package/client/pages/appliance/home.ts +3 -3
  30. package/client/pages/appliance/register.ts +1 -1
  31. package/client/pages/application/application.ts +30 -14
  32. package/client/pages/application/applications.ts +4 -12
  33. package/client/pages/application/register.ts +1 -1
  34. package/client/pages/attribute/attribute-set-management.ts +2 -0
  35. package/client/pages/auth-provider/auth-provider-management.ts +2 -0
  36. package/client/pages/domain/domain-management.ts +2 -0
  37. package/client/pages/user/user-management.ts +5 -5
  38. package/dist-client/auth-style-sign.js +29 -18
  39. package/dist-client/auth-style-sign.js.map +1 -1
  40. package/dist-client/components/abstract-auth-page.d.ts +4 -4
  41. package/dist-client/components/abstract-auth-page.js +40 -22
  42. package/dist-client/components/abstract-auth-page.js.map +1 -1
  43. package/dist-client/components/abstract-password-reset.d.ts +3 -2
  44. package/dist-client/components/abstract-password-reset.js +10 -9
  45. package/dist-client/components/abstract-password-reset.js.map +1 -1
  46. package/dist-client/components/abstract-sign.d.ts +3 -0
  47. package/dist-client/components/abstract-sign.js +110 -0
  48. package/dist-client/components/abstract-sign.js.map +1 -1
  49. package/dist-client/components/change-password.js +2 -2
  50. package/dist-client/components/change-password.js.map +1 -1
  51. package/dist-client/components/contact-us.d.ts +4 -4
  52. package/dist-client/components/contact-us.js +17 -16
  53. package/dist-client/components/contact-us.js.map +1 -1
  54. package/dist-client/components/create-domain-popup.d.ts +1 -1
  55. package/dist-client/components/create-domain-popup.js +11 -7
  56. package/dist-client/components/create-domain-popup.js.map +1 -1
  57. package/dist-client/components/create-role.d.ts +1 -1
  58. package/dist-client/components/create-role.js +7 -19
  59. package/dist-client/components/create-role.js.map +1 -1
  60. package/dist-client/components/create-user.js +6 -14
  61. package/dist-client/components/create-user.js.map +1 -1
  62. package/dist-client/components/credential-manager.d.ts +11 -0
  63. package/dist-client/components/credential-manager.js +64 -0
  64. package/dist-client/components/credential-manager.js.map +1 -0
  65. package/dist-client/components/invite-customer.js +5 -7
  66. package/dist-client/components/invite-customer.js.map +1 -1
  67. package/dist-client/components/invite-user.js +2 -7
  68. package/dist-client/components/invite-user.js.map +1 -1
  69. package/dist-client/components/ownership-transfer-popup.d.ts +1 -1
  70. package/dist-client/components/ownership-transfer-popup.js +3 -3
  71. package/dist-client/components/ownership-transfer-popup.js.map +1 -1
  72. package/dist-client/components/partner-role-editor.js +9 -15
  73. package/dist-client/components/partner-role-editor.js.map +1 -1
  74. package/dist-client/components/profile-component.d.ts +6 -0
  75. package/dist-client/components/profile-component.js +111 -7
  76. package/dist-client/components/profile-component.js.map +1 -1
  77. package/dist-client/components/role-privilege-editor.js +10 -17
  78. package/dist-client/components/role-privilege-editor.js.map +1 -1
  79. package/dist-client/components/user-role-editor.d.ts +2 -0
  80. package/dist-client/components/user-role-editor.js +26 -37
  81. package/dist-client/components/user-role-editor.js.map +1 -1
  82. package/dist-client/entries/auth/activate.d.ts +2 -1
  83. package/dist-client/entries/auth/activate.js +16 -17
  84. package/dist-client/entries/auth/activate.js.map +1 -1
  85. package/dist-client/entries/auth/checkin.d.ts +2 -2
  86. package/dist-client/entries/auth/checkin.js +13 -16
  87. package/dist-client/entries/auth/checkin.js.map +1 -1
  88. package/dist-client/entries/auth/forgot-password.d.ts +2 -1
  89. package/dist-client/entries/auth/forgot-password.js +7 -6
  90. package/dist-client/entries/auth/forgot-password.js.map +1 -1
  91. package/dist-client/entries/auth/result.d.ts +2 -2
  92. package/dist-client/entries/auth/result.js +12 -12
  93. package/dist-client/entries/auth/result.js.map +1 -1
  94. package/dist-client/entries/auth/signup.js +19 -24
  95. package/dist-client/entries/auth/signup.js.map +1 -1
  96. package/dist-client/entries/oauth2/oauth2-decision-error-page.d.ts +1 -1
  97. package/dist-client/entries/oauth2/oauth2-decision-error-page.js +2 -2
  98. package/dist-client/entries/oauth2/oauth2-decision-error-page.js.map +1 -1
  99. package/dist-client/entries/oauth2/oauth2-decision-page.d.ts +1 -1
  100. package/dist-client/entries/oauth2/oauth2-decision-page.js +59 -54
  101. package/dist-client/entries/oauth2/oauth2-decision-page.js.map +1 -1
  102. package/dist-client/entries/public/home.d.ts +3 -2
  103. package/dist-client/entries/public/home.js +40 -18
  104. package/dist-client/entries/public/home.js.map +1 -1
  105. package/dist-client/pages/app-binding/app-binding.d.ts +1 -1
  106. package/dist-client/pages/app-binding/app-binding.js +4 -9
  107. package/dist-client/pages/app-binding/app-binding.js.map +1 -1
  108. package/dist-client/pages/app-binding/app-bindings.js +2 -2
  109. package/dist-client/pages/app-binding/app-bindings.js.map +1 -1
  110. package/dist-client/pages/appliance/appliance.d.ts +1 -1
  111. package/dist-client/pages/appliance/appliance.js +5 -9
  112. package/dist-client/pages/appliance/appliance.js.map +1 -1
  113. package/dist-client/pages/appliance/home.js +3 -3
  114. package/dist-client/pages/appliance/home.js.map +1 -1
  115. package/dist-client/pages/appliance/register.js +1 -1
  116. package/dist-client/pages/appliance/register.js.map +1 -1
  117. package/dist-client/pages/application/application.js +26 -13
  118. package/dist-client/pages/application/application.js.map +1 -1
  119. package/dist-client/pages/application/applications.js +4 -12
  120. package/dist-client/pages/application/applications.js.map +1 -1
  121. package/dist-client/pages/application/register.js +1 -1
  122. package/dist-client/pages/application/register.js.map +1 -1
  123. package/dist-client/pages/attribute/attribute-set-management.d.ts +1 -0
  124. package/dist-client/pages/attribute/attribute-set-management.js +1 -0
  125. package/dist-client/pages/attribute/attribute-set-management.js.map +1 -1
  126. package/dist-client/pages/auth-provider/auth-provider-management.d.ts +1 -0
  127. package/dist-client/pages/auth-provider/auth-provider-management.js +1 -0
  128. package/dist-client/pages/auth-provider/auth-provider-management.js.map +1 -1
  129. package/dist-client/pages/domain/domain-management.d.ts +1 -0
  130. package/dist-client/pages/domain/domain-management.js +1 -0
  131. package/dist-client/pages/domain/domain-management.js.map +1 -1
  132. package/dist-client/pages/user/user-management.d.ts +1 -0
  133. package/dist-client/pages/user/user-management.js +4 -5
  134. package/dist-client/pages/user/user-management.js.map +1 -1
  135. package/dist-client/tsconfig.tsbuildinfo +1 -1
  136. package/package.json +5 -10
  137. package/translations/en.json +1 -0
  138. package/translations/ja.json +1 -0
  139. package/translations/ko.json +1 -0
  140. package/translations/ms.json +1 -0
  141. package/translations/zh.json +1 -0
  142. package/views/auth-page.html +2 -2
  143. package/views/oauth2-page.html +3 -3
@@ -71,34 +71,45 @@ export const AUTH_STYLE_SIGN = css`
71
71
  text-align: left;
72
72
  }
73
73
 
74
- .field mwc-textfield {
74
+ .submit-buttons-container {
75
+ grid-column: 1 / -1;
76
+ text-align: center;
77
+
78
+ display: flex;
79
+ align-items: center;
80
+ gap: 10px;
81
+ }
82
+
83
+ .fingerprint {
84
+ color: var(--md-sys-color-primary-container);
85
+ border: 1.5px solid var(--md-sys-color-primary-container);
86
+ border-radius: 20%;
87
+ width: 36px;
88
+ height: 36px;
89
+ }
90
+
91
+ .field md-filled-text-field {
92
+ grid-column: 1 / -1;
75
93
  width: 100%;
76
- --mdc-theme-primary: var(--auth-input-color);
77
- --mdc-theme-error: #fdd55f;
78
- --mdc-text-field-fill-color: transparent;
79
- --mdc-text-field-ink-color: var(--auth-input-color);
80
- --mdc-text-field-label-ink-color: var(--auth-input-color);
81
- --mdc-text-field-idle-line-color: var(--auth-input-color);
82
- --mdc-text-field-hover-line-color: var(--auth-input-color);
83
- font: var(--auth-input-font);
84
94
  }
85
95
 
86
- mwc-button {
87
- --mdc-theme-primary: var(--auth-button-background-color);
88
- --mdc-theme-on-primary: var(--primary-color);
89
- --mdc-button-horizontal-padding: var(--padding-default);
90
- --mdc-button-ink-color: var(--primary-color);
96
+ md-text-button,
97
+ md-elevated-button {
91
98
  grid-column: 1 / -1;
99
+ flex: 1;
92
100
  }
93
101
 
94
102
  .wrap .link {
95
103
  text-decoration: none;
96
104
  justify-self: flex-start;
97
- color: var(--auth-title-color);
98
105
  }
99
106
 
100
- .wrap .link > mwc-button {
101
- --mdc-theme-primary: var(--auth-title-color);
107
+ .wrap .link md-text-button {
108
+ --md-text-button-label-text-color: var(--md-sys-color-primary-container);
109
+ }
110
+
111
+ .wrap .link md-icon {
112
+ color: var(--md-sys-color-primary-container);
102
113
  }
103
114
 
104
115
  #locale-area {
@@ -111,7 +122,7 @@ export const AUTH_STYLE_SIGN = css`
111
122
  display: flex;
112
123
  align-items: center;
113
124
  color: var(--theme-white-color);
114
- --mdc-icon-size: 16px;
125
+ --md-icon-size: 16px;
115
126
  }
116
127
 
117
128
  #locale-selector {
@@ -1,7 +1,8 @@
1
- import '@material/mwc-button'
2
- import '@material/mwc-icon'
3
- import '@material/mwc-icon-button'
4
- import '@material/mwc-textfield'
1
+ import '@material/web/icon/icon.js'
2
+ import '@material/web/button/elevated-button.js'
3
+ import '@material/web/button/text-button.js'
4
+ import '@material/web/textfield/filled-text-field.js'
5
+
5
6
  import '@operato/lottie-player'
6
7
  import '@operato/i18n/ox-i18n.js'
7
8
  import '@operato/i18n/ox-i18n-selector.js'
@@ -31,17 +32,22 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
31
32
  height: 100vh;
32
33
  height: 100dvh;
33
34
  }
35
+
34
36
  .content {
35
37
  flex: 1;
36
38
  overflow: auto;
37
39
  }
38
40
 
39
- [home] {
41
+ .home {
40
42
  position: absolute;
43
+ padding: var(--padding-dufault, 9px);
44
+ left: 20px;
41
45
  top: 10px;
42
- left: 10px;
43
- font-size: 2em;
44
- color: white;
46
+ color: var(--theme-white-color);
47
+ }
48
+
49
+ div.field {
50
+ margin-bottom: var(--margin-default);
45
51
  }
46
52
 
47
53
  [hidden] {
@@ -83,7 +89,7 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
83
89
  var { icon, title, description } = this.applicationMeta
84
90
 
85
91
  return html`
86
- <div class="content">
92
+ <div class="content md-typescale-display-medium">
87
93
  <div class="wrap">
88
94
  <div class="auth-brand">
89
95
  <img src=${icon} />
@@ -107,7 +113,7 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
107
113
  ${this.links}
108
114
  ${!disableUserFavoredLanguage
109
115
  ? html` <div id="locale-area">
110
- <label for="locale-selector"><mwc-icon>language</mwc-icon></label>
116
+ <label for="locale-selector"><md-icon>language</md-icon></label>
111
117
  <ox-i18n-selector
112
118
  id="locale-selector"
113
119
  value=${i18next.language || 'en-US'}
@@ -124,7 +130,9 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
124
130
  </div>
125
131
  </div>
126
132
 
127
- <mwc-icon-button home icon="home" @click=${e => (window.location.href = '/')}></mwc-icon-button>
133
+ <md-icon-button class="home" @click=${e => (window.location.href = '/')}
134
+ ><md-icon>home</md-icon></md-icon-button
135
+ >
128
136
  <ox-snack-bar id="snackbar" level="error" .message=${this.message}></ox-snack-bar>
129
137
 
130
138
  ${isSafari()
@@ -140,7 +148,7 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
140
148
 
141
149
  firstUpdated() {
142
150
  setTimeout(() => {
143
- ;(this.renderRoot.querySelector('mwc-textfield') as any).focus()
151
+ ;(this.renderRoot.querySelector('md-filled-text-field') as any).focus()
144
152
  }, 100)
145
153
 
146
154
  this.formEl.reset = () => {
@@ -164,35 +172,37 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
164
172
 
165
173
  get formfields() {
166
174
  const email = this.data?.email || ''
175
+ // .validationMessage=${String(i18next.t('text.invalid-email'))}
167
176
 
168
177
  return html`
169
178
  <input id="redirectTo" type="hidden" name="redirectTo" .value=${this.redirectTo || '/'} />
170
179
 
171
180
  <div class="field">
172
- <mwc-textfield
181
+ <md-filled-text-field
173
182
  name="email"
174
183
  type="email"
175
184
  label=${String(i18next.t('field.email'))}
176
185
  required
177
186
  .value=${email}
178
- .validationMessage=${String(i18next.t('text.invalid-email'))}
179
187
  autocomplete="username"
180
188
  autocapitalize="off"
181
- ></mwc-textfield>
189
+ ><md-icon slot="leading-icon">mail</md-icon></md-filled-text-field
190
+ >
182
191
  </div>
183
192
  <div class="field">
184
- <mwc-textfield
193
+ <md-filled-text-field
185
194
  name="password"
186
195
  type="password"
187
196
  label=${String(i18next.t('field.password'))}
188
197
  autocomplete="current-password"
189
198
  required
190
- ></mwc-textfield>
199
+ ><md-icon slot="leading-icon">vpn_key</md-icon></md-filled-text-field
200
+ >
191
201
  </div>
192
202
 
193
- <mwc-button class="ui" type="submit" raised @click=${e => this._onSubmit(e)}>
203
+ <md-elevated-button class="ui" type="submit" raised @click=${e => this._onSubmit(e)}>
194
204
  <ox-i18n msgid="field.${this.pageName}"> </ox-i18n>
195
- </mwc-button>
205
+ </md-elevated-button>
196
206
  `
197
207
  }
198
208
 
@@ -203,17 +213,26 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
203
213
  ${!disableUserSignupProcess
204
214
  ? html`
205
215
  <a class="link" href="/auth/signup">
206
- <mwc-button icon="add_task"><ox-i18n msgid="field.sign up"></ox-i18n></mwc-button>
216
+ <md-text-button>
217
+ <md-icon slot="icon">add_task</md-icon>
218
+ <ox-i18n msgid="field.sign up"></ox-i18n>
219
+ </md-text-button>
207
220
  </a>
208
221
  <a class="link" href="/auth/forgot-password">
209
- <mwc-button icon="lock_open"><ox-i18n msgid="field.forgot-password"></ox-i18n></mwc-button>
222
+ <md-text-button>
223
+ <md-icon slot="icon">lock_open</md-icon>
224
+ <ox-i18n msgid="field.forgot-password"></ox-i18n>
225
+ </md-text-button>
210
226
  </a>
211
227
  `
212
228
  : nothing}
213
229
  ${ssoLinks.map(
214
230
  sso => html`
215
231
  <a class="link" href=${sso.link}>
216
- <mwc-button icon="badge">${i18next.t('label.signin with', { title: sso.title })}</mwc-button>
232
+ <md-text-button>
233
+ <md-icon slot="icon">badge</md-icon>
234
+ ${i18next.t('label.signin with', { title: sso.title })}
235
+ </md-text-button>
217
236
  </a>
218
237
  `
219
238
  )}
@@ -1,5 +1,7 @@
1
- import '@material/mwc-button'
2
- import '@material/mwc-textfield'
1
+ import '@material/web/icon/icon.js'
2
+ import '@material/web/button/elevated-button.js'
3
+ import '@material/web/textfield/filled-text-field.js'
4
+
3
5
  import '@operato/lottie-player'
4
6
  import '../components/profile-component'
5
7
  import '@operato/i18n/ox-i18n.js'
@@ -77,7 +79,7 @@ export abstract class AbstractPasswordReset extends AbstractAuthPage {
77
79
  >
78
80
  <input name="token" type="hidden" .value=${this.token || ''} required />
79
81
  <div class="field">
80
- <mwc-textfield
82
+ <md-filled-text-field
81
83
  name="password"
82
84
  type="password"
83
85
  label=${String(i18next.t('label.password'))}
@@ -89,26 +91,26 @@ export abstract class AbstractPasswordReset extends AbstractAuthPage {
89
91
  this.confirmPass.setAttribute('pattern', val.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '[$&]'))
90
92
  }}
91
93
  required
92
- ></mwc-textfield>
94
+ ></md-filled-text-field>
93
95
  </div>
94
96
 
95
97
  <div class="field">
96
- <mwc-textfield
98
+ <md-filled-text-field
97
99
  id="confirm-password"
98
100
  name="confirm-password"
99
101
  type="password"
100
102
  label=${String(i18next.t('field.confirm password'))}
101
103
  required
102
- ></mwc-textfield>
104
+ ></md-filled-text-field>
103
105
  </div>
104
106
 
105
- <mwc-button id="submit-button" type="submit" raised @click=${e => this._onSubmit(e)}>
107
+ <md-elevated-button id="submit-button" type="submit" @click=${e => this._onSubmit(e)}>
106
108
  <ox-i18n msgid="${this.submitButtonLabel}"></ox-i18n>
107
- </mwc-button>
109
+ </md-elevated-button>
108
110
 
109
111
  ${!disableUserFavoredLanguage
110
112
  ? html` <div id="locale-area">
111
- <label for="locale-selector"><mwc-icon>language</mwc-icon></label>
113
+ <label for="locale-selector"><md-icon>language</md-icon></label>
112
114
  <ox-i18n-selector
113
115
  id="locale-selector"
114
116
  value=${i18next.language || 'en-US'}
@@ -1,5 +1,28 @@
1
+ import { html, nothing } from 'lit'
2
+ import base64url from 'base64url'
3
+
4
+ import '@operato/i18n/ox-i18n.js'
5
+
6
+ import { i18next } from '@operato/i18n'
7
+ import { notify } from '@operato/layout'
8
+
1
9
  import { AbstractAuthPage } from './abstract-auth-page.js'
2
10
 
11
+ const isAvailableWebauthn = 'PublicKeyCredential' in window
12
+
13
+ interface AssertionResponse {
14
+ id: string
15
+ rawId?: number[]
16
+ response: {
17
+ authenticatorData: string
18
+ clientDataJSON: string
19
+ signature: string
20
+ userHandle: string | null
21
+ }
22
+ type: PublicKeyCredentialType
23
+ authenticatorAttachment?: AuthenticatorAttachment
24
+ }
25
+
3
26
  export abstract class AbstractSign extends AbstractAuthPage {
4
27
  async submit() {
5
28
  this.formEl.submit()
@@ -19,4 +42,119 @@ export abstract class AbstractSign extends AbstractAuthPage {
19
42
  }
20
43
  }
21
44
  }
45
+
46
+ get formfields() {
47
+ const email = this.data?.email || ''
48
+
49
+ return html`
50
+ <input id="redirectTo" type="hidden" name="redirectTo" .value=${this.redirectTo || '/'} />
51
+
52
+ <div class="field">
53
+ <md-filled-text-field
54
+ name="email"
55
+ type="email"
56
+ label=${String(i18next.t('field.email'))}
57
+ required
58
+ .value=${email}
59
+ autocomplete="username"
60
+ autocapitalize="off"
61
+ ><md-icon slot="leading-icon">mail</md-icon></md-filled-text-field
62
+ >
63
+ </div>
64
+ <div class="field">
65
+ <md-filled-text-field
66
+ name="password"
67
+ type="password"
68
+ label=${String(i18next.t('field.password'))}
69
+ autocomplete="current-password"
70
+ required
71
+ ><md-icon slot="leading-icon">vpn_key</md-icon></md-filled-text-field
72
+ >
73
+ </div>
74
+
75
+ <div class="submit-buttons-container">
76
+ <md-elevated-button class="submit-button" type="submit" raised @click=${e => this._onSubmit(e)}>
77
+ <ox-i18n msgid="field.${this.pageName}"> </ox-i18n>
78
+ </md-elevated-button>
79
+ ${isAvailableWebauthn
80
+ ? html` <md-icon class="fingerprint" raised @click=${e => this.signinWithAuthn()}> fingerprint </md-icon>`
81
+ : nothing}
82
+ </div>
83
+ `
84
+ }
85
+
86
+ async signinWithAuthn() {
87
+ const response = await fetch('/auth/signin-webauthn/challenge', {
88
+ method: 'POST',
89
+ headers: {
90
+ 'Content-Type': 'application/json',
91
+ Accept: 'application/json'
92
+ },
93
+ credentials: 'include'
94
+ })
95
+
96
+ if (!response.ok) {
97
+ notify({
98
+ level: 'error',
99
+ message: await response.text()
100
+ })
101
+
102
+ return
103
+ }
104
+
105
+ const options = await response.json()
106
+ const credential = (await navigator.credentials.get({
107
+ publicKey: {
108
+ challenge: Buffer.from(options.challenge, 'base64')
109
+ }
110
+ })) as PublicKeyCredential
111
+
112
+ if (!credential) {
113
+ notify({
114
+ level: 'error',
115
+ message: 'can not get user credential'
116
+ })
117
+
118
+ return
119
+ }
120
+
121
+ const assertionResponse = {
122
+ id: credential.id,
123
+ response: {
124
+ clientDataJSON: base64url.encode(Buffer.from(credential.response.clientDataJSON)),
125
+ authenticatorData: base64url.encode((credential.response as any).authenticatorData),
126
+ signature: base64url.encode((credential.response as any).signature),
127
+ userHandle: (credential.response as any).userHandle
128
+ ? base64url.encode((credential.response as any).userHandle)
129
+ : null
130
+ }
131
+ } as AssertionResponse
132
+
133
+ if (credential.authenticatorAttachment) {
134
+ assertionResponse.authenticatorAttachment = credential.authenticatorAttachment as AuthenticatorAttachment
135
+ }
136
+
137
+ const signinResponse = await fetch('/auth/signin-webauthn', {
138
+ method: 'POST',
139
+ headers: {
140
+ 'Content-Type': 'application/json',
141
+ Accept: 'application/json'
142
+ },
143
+ body: JSON.stringify(assertionResponse),
144
+ credentials: 'include'
145
+ })
146
+
147
+ if (!signinResponse.ok) {
148
+ notify({
149
+ level: 'error',
150
+ message: await signinResponse.text()
151
+ })
152
+ } else {
153
+ const { redirectURL } = await signinResponse.json()
154
+
155
+ if (redirectURL) {
156
+ window.location.href = redirectURL
157
+ }
158
+ }
159
+ }
22
160
  }
@@ -40,7 +40,7 @@ export class ChangePassword extends localize(i18next)(LitElement) {
40
40
  text-transform: capitalize;
41
41
  }
42
42
 
43
- mwc-button {
43
+ md-elevated-button {
44
44
  margin: var(--margin-narrow) auto var(--margin-default) auto;
45
45
  }
46
46
 
@@ -78,7 +78,7 @@ export class ChangePassword extends localize(i18next)(LitElement) {
78
78
  <input type="password" name="confirm_pass" placeholder=${i18next.t('text.confirm password')} required />
79
79
  </div>
80
80
 
81
- <mwc-button raised label="${i18next.t('text.change password')}" @click=${this.submit.bind(this)}></mwc-button>
81
+ <md-elevated-button @click=${this.submit.bind(this)}>${i18next.t('text.change password')}</md-elevated-button>
82
82
  </form>
83
83
  `
84
84
  }
@@ -1,7 +1,8 @@
1
- import '@material/mwc-textarea'
2
- import '@material/mwc-textfield'
3
- import '@material/mwc-button'
4
- import '@material/mwc-dialog'
1
+ import '@material/web/button/text-button.js'
2
+ import '@material/web/button/elevated-button.js'
3
+ import '@material/web/textfield/filled-text-field.js'
4
+ import '@material/web/dialog/dialog.js'
5
+
5
6
  import '@operato/i18n'
6
7
 
7
8
  import { css, html, LitElement } from 'lit'
@@ -16,7 +17,7 @@ export class ContactUs extends localize(i18next)(LitElement) {
16
17
  return [
17
18
  css`
18
19
  :host {
19
- --mdc-theme-primary: var(--primary-color);
20
+ --md-theme-primary: var(--primary-color);
20
21
  }
21
22
 
22
23
  * {
@@ -43,16 +44,16 @@ export class ContactUs extends localize(i18next)(LitElement) {
43
44
 
44
45
  render() {
45
46
  return html`
46
- <mwc-button raised label=${i18next.t('button.need help')} @click=${e => (this.dialog.open = true)}></mwc-button>
47
+ <md-elevated-button @click=${e => (this.dialog.open = true)}>${i18next.t('button.need help')}</md-elevated-button>
47
48
 
48
- <mwc-dialog id="dialog" heading=${i18next.t('title.need help')}>
49
+ <md-dialog id="dialog" heading=${i18next.t('title.need help')}>
49
50
  <form action="" method="POST">
50
51
  <input id="subject-input" name="subject" type="hidden" />
51
52
  <input id="sender-input" name="sender" type="hidden" />
52
53
  <input id="content-input" name="content" type="hidden" />
53
54
  </form>
54
55
  <div id="input-form">
55
- <mwc-textfield
56
+ <md-filled-text-field
56
57
  type="text"
57
58
  label=${i18next.t('label.subject')}
58
59
  dialogInitialFocus
@@ -61,8 +62,8 @@ export class ContactUs extends localize(i18next)(LitElement) {
61
62
  const val = e.target.value
62
63
  this.subjectInput.value = val
63
64
  }}
64
- ></mwc-textfield>
65
- <mwc-textfield
65
+ ></md-filled-text-field>
66
+ <md-filled-text-field
66
67
  type="text"
67
68
  name="sender"
68
69
  label=${i18next.t('label.email')}
@@ -71,9 +72,10 @@ export class ContactUs extends localize(i18next)(LitElement) {
71
72
  const val = e.target.value
72
73
  this.senderInput.value = val
73
74
  }}
74
- ></mwc-textfield>
75
- <mwc-textarea
75
+ ></md-filled-text-field>
76
+ <md-filled-text-field
76
77
  name="content"
78
+ type="textarea"
77
79
  label=${i18next.t('label.content')}
78
80
  required
79
81
  @keydown=${e => e.stopPropagation()}
@@ -81,11 +83,11 @@ export class ContactUs extends localize(i18next)(LitElement) {
81
83
  const val = e.target.value
82
84
  this.contentInput.value = val
83
85
  }}
84
- ></mwc-textarea>
86
+ ></md-filled-text-field>
85
87
  </div>
86
- <mwc-button slot="primaryAction" type="submit" label=${i18next.t('button.submit')} raised @click=${e => this._submit(e)}></mwc-button>
87
- <mwc-button slot="secondaryAction" dialogAction="cancel" label=${i18next.t('button.cancel')}></mwc-button>
88
- </mwc-dialog>
88
+ <md-elevated-button slot="primaryAction" type="submit" @click=${e => this._submit(e)}>${i18next.t('button.submit')}</md-elevated-button>
89
+ <md-text-button slot="secondaryAction" dialogAction="cancel">${i18next.t('button.cancel')}</md-text-button>
90
+ </md-dialog>
89
91
  `
90
92
  }
91
93
 
@@ -1,4 +1,4 @@
1
- import '@material/mwc-button'
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'
@@ -7,10 +7,12 @@ import { customElement, query } from 'lit/decorators.js'
7
7
  import { client } from '@operato/graphql'
8
8
  import { i18next, localize } from '@operato/i18n'
9
9
  import { OxPrompt } from '@operato/popup/ox-prompt.js'
10
+ import { ButtonContainerStyles } from '@operato/styles'
10
11
 
11
12
  @customElement('create-domain-popup')
12
13
  class CreateDomainPopup extends localize(i18next)(LitElement) {
13
14
  static styles = [
15
+ ButtonContainerStyles,
14
16
  css`
15
17
  :host {
16
18
  display: flex;
@@ -19,13 +21,16 @@ class CreateDomainPopup extends localize(i18next)(LitElement) {
19
21
  padding: var(--padding-wide);
20
22
  overflow: auto;
21
23
  }
24
+
22
25
  input.checkValidName {
23
26
  background-color: #fce6e6;
24
27
  }
25
- mwc-button {
28
+
29
+ md-elevated-button {
26
30
  display: flex;
27
31
  justify-content: center;
28
32
  }
33
+
29
34
  label {
30
35
  display: flex;
31
36
  flex-direction: column;
@@ -34,6 +39,7 @@ class CreateDomainPopup extends localize(i18next)(LitElement) {
34
39
  color: var(--label-color);
35
40
  text-transform: var(--label-text-transform);
36
41
  }
42
+
37
43
  input {
38
44
  border: var(--border-dark-color);
39
45
  border-radius: var(--border-radius);
@@ -44,12 +50,10 @@ class CreateDomainPopup extends localize(i18next)(LitElement) {
44
50
 
45
51
  flex: 1;
46
52
  }
53
+
47
54
  [field] {
48
55
  grid-column: span 2;
49
56
  }
50
- [buttons] {
51
- margin-top: auto;
52
- }
53
57
  `
54
58
  ]
55
59
 
@@ -71,8 +75,8 @@ class CreateDomainPopup extends localize(i18next)(LitElement) {
71
75
  <label>${i18next.t('label.description')}<input type="text" name="description" /></label>
72
76
  </div>
73
77
 
74
- <div buttons>
75
- <mwc-button raised @click=${e => this.onCreateDomain()}>${i18next.t('button.create')}</mwc-button>
78
+ <div class="button-container">
79
+ <md-elevated-button @click=${e => this.onCreateDomain()}>${i18next.t('button.create')}</md-elevated-button>
76
80
  </div>
77
81
  `
78
82
  }
@@ -1,4 +1,4 @@
1
- import '@material/mwc-textfield'
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
- --mdc-text-field-fill-color: var(--theme-white-color);
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
- mwc-button {
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
- mwc-button {
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
- <mwc-textfield
54
- type="text"
55
- name="name"
56
- label=${String(i18next.t('label.x name', { x: i18next.t('label.role') }))}
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