@genesislcap/foundation-auth 14.71.1-auth-mf.21 → 14.103.0-auth-mf.23

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 (196) hide show
  1. package/README.md +62 -12
  2. package/dist/dts/config/config.d.ts +0 -9
  3. package/dist/dts/config/config.d.ts.map +1 -1
  4. package/dist/dts/dto/IDP.d.ts +9 -0
  5. package/dist/dts/dto/IDP.d.ts.map +1 -0
  6. package/dist/dts/dto/index.d.ts +1 -0
  7. package/dist/dts/dto/index.d.ts.map +1 -1
  8. package/dist/dts/entity/idp.d.ts +9 -0
  9. package/dist/dts/entity/idp.d.ts.map +1 -0
  10. package/dist/dts/entity/index.d.ts +1 -0
  11. package/dist/dts/entity/index.d.ts.map +1 -1
  12. package/dist/dts/entity/loginNack.d.ts +2 -0
  13. package/dist/dts/entity/loginNack.d.ts.map +1 -1
  14. package/dist/dts/entity/nack.d.ts +4 -0
  15. package/dist/dts/entity/nack.d.ts.map +1 -1
  16. package/dist/dts/env.d.ts +10 -0
  17. package/dist/dts/env.d.ts.map +1 -1
  18. package/dist/dts/machine/actions.d.ts +15 -0
  19. package/dist/dts/machine/actions.d.ts.map +1 -0
  20. package/dist/dts/machine/errors.d.ts +26 -0
  21. package/dist/dts/machine/errors.d.ts.map +1 -0
  22. package/dist/dts/machine/guards.d.ts +9 -0
  23. package/dist/dts/machine/guards.d.ts.map +1 -0
  24. package/dist/dts/machine/index.d.ts +2 -0
  25. package/dist/dts/machine/index.d.ts.map +1 -1
  26. package/dist/dts/machine/machine.d.ts +1 -1
  27. package/dist/dts/machine/machine.d.ts.map +1 -1
  28. package/dist/dts/main/main.d.ts +35 -3
  29. package/dist/dts/main/main.d.ts.map +1 -1
  30. package/dist/dts/main/main.styles.d.ts.map +1 -1
  31. package/dist/dts/main/main.template.d.ts.map +1 -1
  32. package/dist/dts/mapper/loginMapper.d.ts.map +1 -1
  33. package/dist/dts/mapper/passwordManagementMapper.d.ts +1 -1
  34. package/dist/dts/mapper/passwordManagementMapper.d.ts.map +1 -1
  35. package/dist/dts/mapper/types.d.ts +2 -2
  36. package/dist/dts/mapper/utils.d.ts +20 -10
  37. package/dist/dts/mapper/utils.d.ts.map +1 -1
  38. package/dist/dts/routes/base.d.ts +4 -11
  39. package/dist/dts/routes/base.d.ts.map +1 -1
  40. package/dist/dts/routes/forgot-password/forgot-password.d.ts +0 -1
  41. package/dist/dts/routes/forgot-password/forgot-password.d.ts.map +1 -1
  42. package/dist/dts/routes/index.d.ts +0 -1
  43. package/dist/dts/routes/index.d.ts.map +1 -1
  44. package/dist/dts/routes/login/login.d.ts +1 -1
  45. package/dist/dts/routes/login/login.d.ts.map +1 -1
  46. package/dist/dts/routes/login/login.template.d.ts.map +1 -1
  47. package/dist/dts/routes/logout/logout.template.d.ts.map +1 -1
  48. package/dist/dts/routes/request-account/request-account.template.d.ts.map +1 -1
  49. package/dist/dts/routes/reset-password/reset-password.d.ts +0 -1
  50. package/dist/dts/routes/reset-password/reset-password.d.ts.map +1 -1
  51. package/dist/dts/routes/verify/verify.template.d.ts.map +1 -1
  52. package/dist/dts/services/idp.d.ts +41 -0
  53. package/dist/dts/services/idp.d.ts.map +1 -0
  54. package/dist/dts/services/index.d.ts +2 -0
  55. package/dist/dts/services/index.d.ts.map +1 -0
  56. package/dist/dts/store/auth.d.ts +18 -5
  57. package/dist/dts/store/auth.d.ts.map +1 -1
  58. package/dist/dts/store/authFormEntry.d.ts +57 -21
  59. package/dist/dts/store/authFormEntry.d.ts.map +1 -1
  60. package/dist/dts/tags/tags.d.ts +0 -7
  61. package/dist/dts/tags/tags.d.ts.map +1 -1
  62. package/dist/dts/user/user.d.ts +2 -2
  63. package/dist/dts/user/user.d.ts.map +1 -1
  64. package/dist/dts/utils/index.d.ts +0 -1
  65. package/dist/dts/utils/index.d.ts.map +1 -1
  66. package/dist/dts/utils/logger.d.ts +1 -1
  67. package/dist/dts/utils/logger.d.ts.map +1 -1
  68. package/dist/esm/config/config.js +1 -1
  69. package/dist/esm/dto/IDP.js +1 -0
  70. package/dist/esm/entity/idp.js +1 -0
  71. package/dist/esm/entity/index.js +1 -0
  72. package/dist/esm/env.js +29 -1
  73. package/dist/esm/machine/actions.js +24 -0
  74. package/dist/esm/machine/errors.js +40 -0
  75. package/dist/esm/machine/guards.js +11 -0
  76. package/dist/esm/machine/index.js +2 -0
  77. package/dist/esm/machine/machine.js +57 -66
  78. package/dist/esm/main/main.js +46 -2
  79. package/dist/esm/main/main.styles.js +3 -1
  80. package/dist/esm/main/main.template.js +2 -1
  81. package/dist/esm/mapper/loginMapper.js +2 -2
  82. package/dist/esm/mapper/passwordManagementMapper.js +1 -1
  83. package/dist/esm/mapper/utils.js +69 -13
  84. package/dist/esm/routes/base.js +9 -13
  85. package/dist/esm/routes/config.js +1 -1
  86. package/dist/esm/routes/forgot-password/forgot-password.js +0 -4
  87. package/dist/esm/routes/forgot-password/forgot-password.template.js +2 -2
  88. package/dist/esm/routes/index.js +0 -1
  89. package/dist/esm/routes/login/login.js +13 -12
  90. package/dist/esm/routes/login/login.template.js +8 -7
  91. package/dist/esm/routes/logout/logout.template.js +1 -0
  92. package/dist/esm/routes/request-account/request-account.template.js +3 -2
  93. package/dist/esm/routes/reset-password/reset-password.js +0 -4
  94. package/dist/esm/routes/reset-password/reset-password.template.js +1 -1
  95. package/dist/esm/routes/verify/verify.template.js +3 -2
  96. package/dist/esm/services/idp.js +71 -0
  97. package/dist/esm/services/index.js +1 -0
  98. package/dist/esm/store/auth.js +25 -3
  99. package/dist/esm/store/authFormEntry.js +62 -49
  100. package/dist/esm/tags/tags.js +0 -22
  101. package/dist/esm/user/user.js +6 -2
  102. package/dist/esm/utils/index.js +0 -1
  103. package/dist/esm/utils/logger.js +1 -1
  104. package/dist/foundation-auth.api.json +749 -784
  105. package/dist/foundation-auth.d.ts +202 -96
  106. package/docs/api/foundation-auth.authformentryeventmap.md +1 -1
  107. package/docs/api/foundation-auth.authformentrystore.idps.md +1 -1
  108. package/docs/api/foundation-auth.authformentrystore.md +4 -6
  109. package/docs/api/foundation-auth.authformentrystore.onselectedidpchanged.md +3 -3
  110. package/docs/api/foundation-auth.authformentrystore.password2.md +5 -0
  111. package/docs/api/foundation-auth.authformentrystore.selectedidp.md +3 -3
  112. package/docs/api/{foundation-auth.authformentrystore.host.md → foundation-auth.authformentrystore.ssologinurl.md} +3 -3
  113. package/docs/api/foundation-auth.authstore.errormessages.md +11 -0
  114. package/docs/api/foundation-auth.authstore.md +2 -0
  115. package/docs/api/foundation-auth.authstore.metamessages.md +11 -0
  116. package/docs/api/foundation-auth.defaultauthformentrystore.autofilling.md +1 -0
  117. package/docs/api/foundation-auth.defaultauthformentrystore.email.md +1 -0
  118. package/docs/api/foundation-auth.defaultauthformentrystore.haspasswordexpired.md +1 -0
  119. package/docs/api/foundation-auth.defaultauthformentrystore.idps.md +2 -1
  120. package/docs/api/{foundation-auth.defaultauthformentrystore.haserrors.md → foundation-auth.defaultauthformentrystore.idpservice.md} +3 -3
  121. package/docs/api/foundation-auth.defaultauthformentrystore.md +6 -16
  122. package/docs/api/foundation-auth.defaultauthformentrystore.mfacode.md +1 -0
  123. package/docs/api/foundation-auth.defaultauthformentrystore.onautofillform.md +1 -0
  124. package/docs/api/foundation-auth.defaultauthformentrystore.onemailchanged.md +1 -0
  125. package/docs/api/foundation-auth.defaultauthformentrystore.onorganisationchanged.md +1 -0
  126. package/docs/api/foundation-auth.defaultauthformentrystore.onpassword2changed.md +1 -0
  127. package/docs/api/foundation-auth.defaultauthformentrystore.onpasswordchanged.md +1 -0
  128. package/docs/api/foundation-auth.defaultauthformentrystore.onselectedidpchanged.md +4 -3
  129. package/docs/api/foundation-auth.defaultauthformentrystore.onshowpasswordschanged.md +1 -0
  130. package/docs/api/foundation-auth.defaultauthformentrystore.onssotogglechanged.md +1 -0
  131. package/docs/api/foundation-auth.defaultauthformentrystore.onusernamechanged.md +1 -0
  132. package/docs/api/foundation-auth.defaultauthformentrystore.organisation.md +1 -0
  133. package/docs/api/foundation-auth.defaultauthformentrystore.orgusername.md +1 -0
  134. package/docs/api/foundation-auth.defaultauthformentrystore.password.md +1 -0
  135. package/docs/api/foundation-auth.defaultauthformentrystore.password2.md +5 -0
  136. package/docs/api/foundation-auth.defaultauthformentrystore.passwordresettoken.md +1 -0
  137. package/docs/api/foundation-auth.defaultauthformentrystore.selectedidp.md +4 -3
  138. package/docs/api/foundation-auth.defaultauthformentrystore.showpasswords.md +1 -0
  139. package/docs/api/{foundation-auth.defaultauthformentrystore.message.md → foundation-auth.defaultauthformentrystore.ssologinurl.md} +4 -3
  140. package/docs/api/foundation-auth.defaultauthformentrystore.ssotoggled.md +1 -0
  141. package/docs/api/foundation-auth.defaultauthformentrystore.termsagreed.md +1 -0
  142. package/docs/api/foundation-auth.defaultauthformentrystore.username.md +1 -0
  143. package/docs/api/foundation-auth.defaultauthmachine._constructor_.md +1 -1
  144. package/docs/api/{foundation-auth.defaultauthmachine.ondonedto.md → foundation-auth.defaultauthmachine.dtotransition.md} +3 -3
  145. package/docs/api/foundation-auth.defaultauthmachine.md +1 -1
  146. package/docs/api/foundation-auth.defaultauthstore.errormessages.md +12 -0
  147. package/docs/api/foundation-auth.defaultauthstore.ispending.md +1 -0
  148. package/docs/api/foundation-auth.defaultauthstore.md +3 -1
  149. package/docs/api/foundation-auth.defaultauthstore.metamessages.md +12 -0
  150. package/docs/api/foundation-auth.defaultauthstore.onchangepassword.md +1 -0
  151. package/docs/api/foundation-auth.defaultauthstore.onforgotpassword.md +1 -0
  152. package/docs/api/foundation-auth.defaultauthstore.onlogin.md +1 -0
  153. package/docs/api/foundation-auth.defaultauthstore.onlogout.md +1 -0
  154. package/docs/api/foundation-auth.defaultauthstore.onresetpassword.md +1 -0
  155. package/docs/api/{foundation-auth.idpresponse.id.md → foundation-auth.fromidpdto.md} +5 -3
  156. package/docs/api/foundation-auth.idp.description.md +11 -0
  157. package/docs/api/foundation-auth.idp.id.md +3 -3
  158. package/docs/api/foundation-auth.idp.md +3 -2
  159. package/docs/api/foundation-auth.idp.type.md +3 -3
  160. package/docs/api/foundation-auth.is200nack.md +13 -0
  161. package/docs/api/foundation-auth.isnackdto.md +1 -1
  162. package/docs/api/foundation-auth.isnackentity.md +24 -0
  163. package/docs/api/foundation-auth.logger.md +1 -1
  164. package/docs/api/foundation-auth.loginnack.hasincorrectcredentials.md +11 -0
  165. package/docs/api/foundation-auth.loginnack.maxtriesreached.md +11 -0
  166. package/docs/api/foundation-auth.loginnack.md +2 -0
  167. package/docs/api/foundation-auth.md +10 -11
  168. package/docs/api/foundation-auth.seterror.md +25 -0
  169. package/docs/api/{foundation-auth.idpresponse.type.md → foundation-auth.sso_list_url.md} +4 -3
  170. package/docs/api/foundation-auth.sso_login_url.md +12 -0
  171. package/docs/api/foundation-auth.ssoconfig.md +0 -1
  172. package/docs/api/foundation-auth.user.addauthenticationchangelistener.md +3 -3
  173. package/docs/api-report.md +170 -80
  174. package/package.json +12 -13
  175. package/dist/dts/utils/sso.d.ts +0 -27
  176. package/dist/dts/utils/sso.d.ts.map +0 -1
  177. package/dist/esm/utils/sso.js +0 -50
  178. package/docs/api/foundation-auth.authformentrystore.haserrors.md +0 -11
  179. package/docs/api/foundation-auth.authformentrystore.message.md +0 -11
  180. package/docs/api/foundation-auth.authrouting.getroutepath.md +0 -13
  181. package/docs/api/foundation-auth.authrouting.md +0 -37
  182. package/docs/api/foundation-auth.authrouting.navigateto.md +0 -16
  183. package/docs/api/foundation-auth.defaultauthformentrystore.autofill.md +0 -15
  184. package/docs/api/foundation-auth.defaultauthformentrystore.fetchmachine.md +0 -11
  185. package/docs/api/foundation-auth.defaultauthformentrystore.host.md +0 -11
  186. package/docs/api/foundation-auth.defaultauthformentrystore.resetidpstate.md +0 -15
  187. package/docs/api/foundation-auth.defaultauthformentrystore.ssotoggledchanged.md +0 -23
  188. package/docs/api/foundation-auth.defaultauthrouting.getroutepath.md +0 -24
  189. package/docs/api/foundation-auth.defaultauthrouting.md +0 -22
  190. package/docs/api/foundation-auth.defaultauthrouting.navigateto.md +0 -26
  191. package/docs/api/foundation-auth.fetchidps.md +0 -13
  192. package/docs/api/foundation-auth.fromdtonackerrorwarningarray.md +0 -12
  193. package/docs/api/foundation-auth.getauthrouting.md +0 -32
  194. package/docs/api/foundation-auth.getssologinurl.md +0 -13
  195. package/docs/api/foundation-auth.idpresponse.md +0 -20
  196. package/docs/api/foundation-auth.includeserrorwarningcode.md +0 -13
@@ -1,9 +1,9 @@
1
1
  import { __awaiter, __decorate } from "tslib";
2
2
  import { inIFrame, inSymphonyDesktop, openPopup } from '@genesislcap/foundation-utils';
3
- import { customElement, DOM, volatile } from '@microsoft/fast-element';
3
+ import { customElement, volatile } from '@microsoft/fast-element';
4
4
  import { CredentialManager, CredentialType } from '../../credential';
5
5
  import { User } from '../../user';
6
- import { getSSOLoginURL, logger } from '../../utils';
6
+ import { logger } from '../../utils';
7
7
  import { BaseRoute } from '../base';
8
8
  import { LoginStyles as styles } from './login.styles';
9
9
  import { LoginTemplate as template } from './login.template';
@@ -11,14 +11,14 @@ let Login = class Login extends BaseRoute {
11
11
  connectedCallback() {
12
12
  super.connectedCallback();
13
13
  /**
14
- * Retaining the logic that logs authenticated users out when this route is visited for now.
15
- * TODO: Revisit as shouldn't load mf if logged in already.
14
+ * For now, I'm retaining the logic that logs authenticated users out when this route is visited. However, this
15
+ * shouldn't happen. We shouldn't be loading this screen if logged-in.
16
+ * TODO: Remove pending investigation.
16
17
  */
17
18
  if (this.user.isAuthenticated) {
18
19
  this.logout();
19
20
  return;
20
21
  }
21
- this.attemptAutofill();
22
22
  }
23
23
  attemptBasicLogin() {
24
24
  const basicCredentials = {
@@ -34,13 +34,16 @@ let Login = class Login extends BaseRoute {
34
34
  this.login(basicCredentials);
35
35
  }
36
36
  get ssoToggleLabel() {
37
- const { selectedIDP, ssoToggled } = this.store.formEntry;
38
- const selectedIDPLabel = selectedIDP ? ` - ${selectedIDP}` : '';
37
+ const { selectedIdp, ssoToggled } = this.store.formEntry;
38
+ const selectedIDPLabel = selectedIdp ? ` - ${selectedIdp.id}` : '';
39
39
  return ssoToggled ? 'SSO Enabled' + selectedIDPLabel : 'Enable SSO?';
40
40
  }
41
41
  onSSOLogin() {
42
- const selectedIDP = this.store.formEntry.idps.find((idp) => idp.id === this.store.formEntry.selectedIDP);
43
- const ssoLoginUrl = getSSOLoginURL(selectedIDP);
42
+ const ssoLoginUrl = this.store.formEntry.ssoLoginUrl;
43
+ if (!ssoLoginUrl) {
44
+ logger.error(`SSO login url invalid, aborting login attempt.`);
45
+ return;
46
+ }
44
47
  if (inIFrame()) {
45
48
  if (inSymphonyDesktop()) {
46
49
  // symphony/electron opens new window in the default browser instead
@@ -57,9 +60,7 @@ let Login = class Login extends BaseRoute {
57
60
  }
58
61
  onLoginSubmit() {
59
62
  return __awaiter(this, void 0, void 0, function* () {
60
- DOM.queueUpdate(() => {
61
- this.attemptBasicLogin();
62
- });
63
+ this.attemptBasicLogin();
63
64
  });
64
65
  }
65
66
  login(params) {
@@ -8,7 +8,7 @@ const regularLogin = html `
8
8
  <span class="case-warning">*Fields are case-sensitive</span>
9
9
  ${showPasswordsCheckbox()}
10
10
  <div class="form-buttons">
11
- ${(x) => submitButton('Login', 'submit-login', x.submitDisabled)}
11
+ ${(x) => submitButton('Login', 'submit', x.submitDisabled)}
12
12
  <div class="links">
13
13
  <div class="password-links">
14
14
  ${when((x) => !x.config.omitRoutes.includes('forgot-password'), html `
@@ -62,13 +62,13 @@ const ssoLogin = html `
62
62
  <${selectTag}
63
63
  name="sso"
64
64
  data-test-id="sso"
65
- @change="${selectEmit('auth-selectedIDP-changed')}"
65
+ @change="${selectEmit('auth-selectedIdp-changed')}"
66
66
  ?disabled=${(x) => !x.store.formEntry.idps.length}
67
67
  >
68
68
  ${repeat((x) => x.store.formEntry.idps, html `
69
69
  <${listboxOptionTag}
70
70
  value=${({ id }) => id}
71
- ?selected=${(x, c) => c.parent.store.formEntry.selectedIDP == x.id}
71
+ ?selected=${(x, c) => c.parent.store.formEntry.selectedIdp === x}
72
72
  >
73
73
  ${({ id }) => id}
74
74
  </${listboxOptionTag}>
@@ -79,8 +79,8 @@ const ssoLogin = html `
79
79
  class="action-btn"
80
80
  appearance="primary-gradient"
81
81
  @click="${(x) => x.onSSOLogin()}"
82
- data-test-id="sso-login"
83
- ?disabled=${(x) => !x.store.formEntry.selectedIDP}
82
+ data-test-id="submit"
83
+ ?disabled=${(x) => !x.store.formEntry.selectedIdp}
84
84
  >
85
85
  SSO Login
86
86
  </${buttonTag}>
@@ -93,7 +93,7 @@ export const LoginTemplate = html `
93
93
  <${cardTag} class="card-pd">
94
94
  <div class="column-content">
95
95
  <auth-logo></auth-logo>
96
- <div class="heading2">Login</div>
96
+ <div class="heading2" data-test-id="heading">Login</div>
97
97
  </div>
98
98
  <form
99
99
  id="auth-login"
@@ -101,7 +101,7 @@ export const LoginTemplate = html `
101
101
  autocomplete="on"
102
102
  @submit=${(x) => x.onLoginSubmit()}
103
103
  ?disabled=${(x) => x.submitDisabled}
104
- data-test-id="auth-login"
104
+ data-test-id="form"
105
105
  >
106
106
  ${regularLogin} ${ssoLogin}
107
107
  ${when((x) => x.config.sso, html `
@@ -114,6 +114,7 @@ export const LoginTemplate = html `
114
114
  ${(x) => x.ssoToggleLabel}
115
115
  </${checkboxTag}>
116
116
  `)}
117
+ <submitting-indicator is-submitting="${(x) => x.store.isPending}"></submitting-indicator>
117
118
  <auth-message></auth-message>
118
119
  </form>
119
120
  </${cardTag}>
@@ -6,6 +6,7 @@ export const LogoutTemplate = html `
6
6
  <${cardTag} class="card-pd">
7
7
  <div class="column-content">
8
8
  <auth-logo></auth-logo>
9
+ <submitting-indicator is-submitting="${(x) => x.store.isPending}"></submitting-indicator>
9
10
  <auth-message></auth-message>
10
11
  </div>
11
12
  </${cardTag}>
@@ -8,9 +8,9 @@ export const RequestAccountTemplate = html `
8
8
  <${cardTag} class="card-pd">
9
9
  <div class="column-content">
10
10
  <auth-logo></auth-logo>
11
- <div class="heading2">Request Account</div>
11
+ <div class="heading2" data-test-id="heading">Request Account</div>
12
12
  </div>
13
- <form @submit=${(x) => x.onSubmit()}>
13
+ <form @submit=${(x) => x.onSubmit()} data-test-id="form">
14
14
  ${organisationField()} ${usernameField()} ${emailField()} ${passwordField()}
15
15
  ${password2Field('confirmation')}
16
16
  <${checkboxTag}
@@ -26,6 +26,7 @@ export const RequestAccountTemplate = html `
26
26
  <div class="form-buttons">
27
27
  ${submitButton('Request Account')} ${backButton((x) => x.onBack())}
28
28
  </div>
29
+ <submitting-indicator is-submitting="${(x) => x.store.isPending}"></submitting-indicator>
29
30
  <auth-message></auth-message>
30
31
  </form>
31
32
  </${cardTag}>
@@ -9,10 +9,6 @@ let ResetPassword = class ResetPassword extends BaseRoute {
9
9
  this.hasPasswordExpired = false;
10
10
  this.passwordResetToken = '';
11
11
  }
12
- connectedCallback() {
13
- super.connectedCallback();
14
- this.attemptAutofill();
15
- }
16
12
  enter(phase) {
17
13
  this.hasPasswordExpired = !!phase.route.queryParams.expired;
18
14
  this.passwordResetToken = phase.route.queryParams.password;
@@ -10,7 +10,7 @@ export const ResetPasswordTemplate = html `
10
10
  <div class="heading2" data-test-id="heading">${(x) => x.headingText}</div>
11
11
  <div class="heading3">Enter the username registered to your account</div>
12
12
  </div>
13
- <form @submit=${(x) => x.onSubmit()} autocomplete="on">
13
+ <form @submit=${(x) => x.onSubmit()} autocomplete="on" data-test-id="form">
14
14
  ${organisationField()} ${usernameField()}
15
15
  ${when((x) => !x.passwordResetToken, html `
16
16
  ${passwordField('Old Password')}
@@ -8,12 +8,12 @@ export const VerifyTemplate = html `
8
8
  <${cardTag} class="card-pd">
9
9
  <div class="column-content">
10
10
  <auth-logo></auth-logo>
11
- <div class="heading2">Verify that it's you</div>
11
+ <div class="heading2" data-test-id="heading">Verify that it's you</div>
12
12
  <div class="heading3">
13
13
  We've sent a code to the email address attached to this account.
14
14
  </div>
15
15
  </div>
16
- <form @submit=${(x) => x.onSubmit()}>
16
+ <form @submit=${(x) => x.onSubmit()} data-test-id="form">
17
17
  <${textFieldTag}
18
18
  type="text"
19
19
  name="code"
@@ -27,6 +27,7 @@ export const VerifyTemplate = html `
27
27
  <div class="form-buttons">
28
28
  ${submitButton('Verify and Login')} ${backButton((x) => x.onBack())}
29
29
  </div>
30
+ <submitting-indicator is-submitting="${(x) => x.store.isPending}"></submitting-indicator>
30
31
  <auth-message></auth-message>
31
32
  </form>
32
33
  </${cardTag}>
@@ -0,0 +1,71 @@
1
+ import { __awaiter, __decorate } from "tslib";
2
+ import { FetchMachine } from '@genesislcap/foundation-state-machine';
3
+ import { DI } from '@microsoft/fast-foundation';
4
+ import { SSO_LIST_URL, SSO_LOGIN_URL } from '../env';
5
+ import { fromIDPDTO } from '../mapper';
6
+ /**
7
+ * Default IDPService.
8
+ * @public
9
+ */
10
+ export class DefaultIDPService {
11
+ constructor() {
12
+ /**
13
+ * The pattern matches `{property}` values in the string.
14
+ * @internal
15
+ */
16
+ this.loginUrlReplacePattern = /{\s*(\w+?)\s*}/g;
17
+ /** {@inheritDoc IDPService.getList} */
18
+ this.getList = (url = SSO_LIST_URL) => __awaiter(this, void 0, void 0, function* () {
19
+ return new Promise((resolve, reject) => {
20
+ const fetcher = this.fetchMachine.getFromContainer();
21
+ fetcher.provide({
22
+ actions: {
23
+ successCallback: ({ context }) => {
24
+ const { data } = context;
25
+ /**
26
+ * Format reference:
27
+ * const IDPS: IDP[] = [
28
+ * { ID: 'hsbc', DESCRIPTION: 'hsbc', TYPE: 'saml' },
29
+ * { ID: 'mufg', DESCRIPTION: 'mufg', TYPE: 'saml' },
30
+ * ];
31
+ */
32
+ const IDPS = data === null || data === void 0 ? void 0 : data.IDPS;
33
+ if (!IDPS || !IDPS.length) {
34
+ reject(Error('Identity provider list empty'));
35
+ return;
36
+ }
37
+ const idps = IDPS.map((dto) => fromIDPDTO(dto));
38
+ resolve(idps);
39
+ },
40
+ errorCallback: () => reject(Error('Failed to fetch identity providers')),
41
+ },
42
+ });
43
+ fetcher.start();
44
+ fetcher.send({
45
+ type: 'fetch',
46
+ params: {
47
+ /**
48
+ * Used `url: 'https://hsbc-uat-priss1/gwf/sso/list'` during testing.
49
+ */
50
+ url,
51
+ },
52
+ });
53
+ });
54
+ });
55
+ /** {@inheritDoc IDPService.getLoginUrl} */
56
+ this.getLoginUrl = (idp, urlTemplate = SSO_LOGIN_URL) => {
57
+ if (!idp || !idp.type || !idp.id) {
58
+ throw new Error(`Invalid IDP: ${JSON.stringify(idp)}`);
59
+ }
60
+ return urlTemplate.replace(this.loginUrlReplacePattern, (_, token) => idp[token] || '');
61
+ };
62
+ }
63
+ }
64
+ __decorate([
65
+ FetchMachine
66
+ ], DefaultIDPService.prototype, "fetchMachine", void 0);
67
+ /**
68
+ * IDPService DI key.
69
+ * @internal
70
+ */
71
+ export const IDPService = DI.createInterface((x) => x.singleton(DefaultIDPService));
@@ -0,0 +1 @@
1
+ export * from './idp';
@@ -1,10 +1,10 @@
1
1
  import { __decorate, __param } from "tslib";
2
2
  import { AbstractStoreRoot, registerStore, } from '@genesislcap/foundation-store';
3
3
  import { AuthConfig } from '../config/config';
4
- import { AuthMachine } from '../machine';
4
+ import { AuthMachine } from '../machine/machine';
5
5
  import { AuthFormEntryStore } from './authFormEntry';
6
6
  /**
7
- * Default implementation of the store.
7
+ * Default AuthStore.
8
8
  * @public
9
9
  */
10
10
  let DefaultAuthStore = class DefaultAuthStore extends AbstractStoreRoot {
@@ -13,28 +13,50 @@ let DefaultAuthStore = class DefaultAuthStore extends AbstractStoreRoot {
13
13
  this.config = config;
14
14
  this.authMachine = authMachine;
15
15
  this.formEntry = formEntry;
16
+ /** {@inheritDoc AuthStore.onMachineEvent} */
16
17
  this.onMachineEvent = this.createListener('auth-machine-event', (event) => this.authMachine.send(event));
18
+ /** {@inheritDoc AuthStore.onLogin} */
17
19
  this.onLogin = this.createListener('auth-login', (params) => this.authMachine.send({
18
20
  type: 'login',
19
21
  params,
20
22
  }));
23
+ /** {@inheritDoc AuthStore.onLogout} */
21
24
  this.onLogout = this.createListener('auth-logout', () => this.authMachine.send({ type: 'logout' }));
25
+ /** {@inheritDoc AuthStore.onChangePassword} */
22
26
  this.onChangePassword = this.createListener('auth-change-password', (params) => this.authMachine.send({
23
27
  type: 'change-password',
24
28
  params,
25
29
  }));
30
+ /** {@inheritDoc AuthStore.onForgotPassword} */
26
31
  this.onForgotPassword = this.createListener('auth-forgot-password', (params) => this.authMachine.send({
27
32
  type: 'forgot-password',
28
33
  params,
29
34
  }));
35
+ /** {@inheritDoc AuthStore.onResetPassword} */
30
36
  this.onResetPassword = this.createListener('auth-reset-password', (params) => this.authMachine.send({
31
37
  type: 'reset-password',
32
38
  params,
33
39
  }));
34
40
  }
41
+ /** {@inheritDoc AuthStore.isPending} */
35
42
  get isPending() {
36
43
  return !this.ready || this.authMachine.hasTag('pending');
37
44
  }
45
+ /** {@inheritDoc AuthStore.metaMessages} */
46
+ get metaMessages() {
47
+ return this.authMachine.getMetaValuesByKey();
48
+ }
49
+ /** {@inheritDoc AuthStore.errorMessages} */
50
+ get errorMessages() {
51
+ const messages = [];
52
+ for (const { message } of this.authMachine.errors.values()) {
53
+ messages.push(message);
54
+ }
55
+ for (const { message } of this.formEntry.errors.values()) {
56
+ messages.push(message);
57
+ }
58
+ return messages;
59
+ }
38
60
  };
39
61
  DefaultAuthStore = __decorate([
40
62
  __param(0, AuthConfig),
@@ -43,7 +65,7 @@ DefaultAuthStore = __decorate([
43
65
  ], DefaultAuthStore);
44
66
  export { DefaultAuthStore };
45
67
  /**
46
- * DI key of the store.
68
+ * AuthStore DI key.
47
69
  * @internal
48
70
  */
49
71
  export const AuthStore = registerStore(DefaultAuthStore, 'AuthStore');
@@ -1,15 +1,16 @@
1
1
  import { __awaiter, __decorate } from "tslib";
2
- import { FetchMachine } from '@genesislcap/foundation-state-machine';
3
2
  import { AbstractStore, registerStore } from '@genesislcap/foundation-store';
4
3
  import { observable, volatile } from '@microsoft/fast-element';
5
4
  import { AuthConfig } from '../config/config';
6
5
  import { CredentialManager, credentialSeparator } from '../credential';
7
- import { fetchIDPs, logger } from '../utils';
6
+ import { IDPService } from '../services';
7
+ import { logger } from '../utils';
8
8
  /**
9
- * Default implementation of the store.
9
+ * Default AuthFormEntryStore.
10
10
  * @public
11
11
  */
12
12
  export class DefaultAuthFormEntryStore extends AbstractStore {
13
+ /** {@inheritDoc AuthFormEntryStore.orgUsername} */
13
14
  get orgUsername() {
14
15
  return this.config.fields.organisation && this.organisation.trim() !== ''
15
16
  ? `${this.username.trim()}:${this.organisation.trim()}`
@@ -18,55 +19,95 @@ export class DefaultAuthFormEntryStore extends AbstractStore {
18
19
  constructor() {
19
20
  var _a, _b;
20
21
  super();
21
- this.host = '';
22
+ /** {@inheritDoc AuthFormEntryStore.organisation} */
22
23
  this.organisation = '';
24
+ /** {@inheritDoc AuthFormEntryStore.username} */
23
25
  this.username = '';
26
+ /** {@inheritDoc AuthFormEntryStore.email} */
24
27
  this.email = '';
28
+ /** {@inheritDoc AuthFormEntryStore.password} */
25
29
  this.password = '';
26
- this.password2 = ''; // < New, confirm etc.
30
+ /** {@inheritDoc AuthFormEntryStore.password2} */
31
+ this.password2 = '';
32
+ /** {@inheritDoc AuthFormEntryStore.showPasswords} */
27
33
  this.showPasswords = false;
34
+ /** {@inheritDoc AuthFormEntryStore.hasPasswordExpired} */
28
35
  this.hasPasswordExpired = false;
36
+ /** {@inheritDoc AuthFormEntryStore.passwordResetToken} */
29
37
  this.passwordResetToken = '';
30
- this.message = '';
31
- this.hasErrors = false;
38
+ /** {@inheritDoc AuthFormEntryStore.mfaCode} */
32
39
  this.mfaCode = '';
40
+ /** {@inheritDoc AuthFormEntryStore.idps} */
33
41
  this.idps = [];
34
- this.selectedIDP = '';
42
+ /** {@inheritDoc AuthFormEntryStore.ssoToggled} */
35
43
  this.ssoToggled = false;
44
+ /** {@inheritDoc AuthFormEntryStore.termsAgreed} */
36
45
  this.termsAgreed = false;
46
+ /** {@inheritDoc AuthFormEntryStore.autofilling} */
37
47
  this.autofilling = false;
48
+ /** {@inheritDoc AuthFormEntryStore.onAutofillForm} */
38
49
  this.onAutofillForm = this.createListener('auth-autofill-form', () => this.autofill());
50
+ /** {@inheritDoc AuthFormEntryStore.onOrganisationChanged} */
39
51
  this.onOrganisationChanged = this.createListener('auth-organisation-changed', (detail) => (this.commit.organisation = detail));
52
+ /** {@inheritDoc AuthFormEntryStore.onUsernameChanged} */
40
53
  this.onUsernameChanged = this.createListener('auth-username-changed', (detail) => (this.commit.username = detail));
54
+ /** {@inheritDoc AuthFormEntryStore.onEmailChanged} */
41
55
  this.onEmailChanged = this.createListener('auth-email-changed', (detail) => (this.commit.email = detail));
56
+ /** {@inheritDoc AuthFormEntryStore.onPasswordChanged} */
42
57
  this.onPasswordChanged = this.createListener('auth-password-changed', (detail) => (this.commit.password = detail));
58
+ /** {@inheritDoc AuthFormEntryStore.onPassword2Changed} */
43
59
  this.onPassword2Changed = this.createListener('auth-password2-changed', (detail) => (this.commit.password2 = detail));
60
+ /** {@inheritDoc AuthFormEntryStore.onShowPasswordsChanged} */
44
61
  this.onShowPasswordsChanged = this.createListener('auth-showPasswords-changed', (detail) => (this.commit.showPasswords = detail));
45
- this.onSelectedIDPChanged = this.createListener('auth-selectedIDP-changed', (detail) => (this.commit.selectedIDP = detail));
62
+ /** {@inheritDoc AuthFormEntryStore.onSelectedIdpChanged} */
63
+ this.onSelectedIdpChanged = this.createListener('auth-selectedIdp-changed', (detail) => {
64
+ this.commit.selectedIdp = Array.isArray(this.idps)
65
+ ? this.idps.find((idp) => idp.id === detail)
66
+ : undefined;
67
+ });
68
+ /** {@inheritDoc AuthFormEntryStore.onSSOToggleChanged} */
46
69
  this.onSSOToggleChanged = this.createListener('auth-ssoToggled-changed', (detail) => (this.commit.ssoToggled = detail));
70
+ /**
71
+ * @privateRemarks
72
+ * Internally observed given constructor assignment.
73
+ * @internal
74
+ */
75
+ this.ssoToggledChanged = (prev, next) => __awaiter(this, void 0, void 0, function* () {
76
+ if (!next) {
77
+ this.resetIDPState();
78
+ this.commit.errors.delete('auth-fetch-idps-error');
79
+ return;
80
+ }
81
+ yield this.invokeAsyncAPI(this.idpService.getList, 'auth-fetch-idps-error', 'auth-fetch-idps-success');
82
+ });
47
83
  this.ssoToggled = (_b = (_a = this.config.sso) === null || _a === void 0 ? void 0 : _a.toggled) !== null && _b !== void 0 ? _b : false;
48
84
  /**
49
85
  * Listeners not on the public interface can be created anonymously
50
86
  */
51
87
  this.createListener('auth-fetch-idps-success', (idps) => {
52
88
  this.commit.idps = idps;
53
- this.commit.selectedIDP = idps && idps.length ? idps[0].id : '';
89
+ this.commit.selectedIdp = Array.isArray(idps) ? idps[0] : undefined;
54
90
  });
55
91
  this.createErrorListener('auth-fetch-idps-error', () => this.resetIDPState());
56
92
  }
93
+ /**
94
+ * @internal
95
+ */
57
96
  resetIDPState() {
58
97
  this.commit.idps = [];
59
- this.commit.selectedIDP = '';
98
+ this.commit.selectedIdp = undefined;
60
99
  }
100
+ /**
101
+ * @internal
102
+ */
61
103
  autofill() {
62
104
  var _a, _b, _c;
63
105
  return __awaiter(this, void 0, void 0, function* () {
64
106
  let credentialData;
65
107
  try {
66
108
  /**
67
- * TODO: Revert back to `credentialManager.getCredentials()` after Neptune deployment.
68
- * Neptune was using cookies directly. To provide them with a seamless upgrade, we should load from cookies if the
69
- * container is empty. These stored cookies become irrelevant after their first login in the new system.
109
+ * Neptune was using cookies to store user credentials. To provide them with a seamless upgrade, we should load
110
+ * from cookies if the container is empty. These cookies become irrelevant after first login using container.
70
111
  */
71
112
  this.autofilling = true;
72
113
  const containerData = yield this.credentialManager.getCredentialsFromContainer();
@@ -101,28 +142,9 @@ export class DefaultAuthFormEntryStore extends AbstractStore {
101
142
  return Promise.resolve(!!credentialData);
102
143
  });
103
144
  }
104
- ssoToggledChanged(prev, next) {
105
- var _a, _b;
106
- if (!next) {
107
- this.resetIDPState();
108
- return;
109
- }
110
- const path = `${(_b = (_a = this.config.sso) === null || _a === void 0 ? void 0 : _a.identityProvidersPath) !== null && _b !== void 0 ? _b : 'sso/list'}`;
111
- this.errors.delete('auth-fetch-idps-error');
112
- const emitError = () => this.emit('auth-fetch-idps-error', Error('Failed to fetch identity providers.'));
113
- /**
114
- * TODO: Port to FetchMachine, need to sort out all the utils/sso stuff.
115
- */
116
- fetchIDPs(path)
117
- .then((idps) => {
118
- var _a;
119
- if (!idps.length || (idps.length === 1 && ((_a = idps[0]) === null || _a === void 0 ? void 0 : _a.id) === 'error')) {
120
- emitError();
121
- return;
122
- }
123
- this.emit('auth-fetch-idps-success', idps);
124
- })
125
- .catch(() => emitError());
145
+ /** {@inheritDoc AuthFormEntryStore.ssoLoginUrl} */
146
+ get ssoLoginUrl() {
147
+ return this.selectedIdp ? this.idpService.getLoginUrl(this.selectedIdp) : null;
126
148
  }
127
149
  }
128
150
  __decorate([
@@ -132,11 +154,8 @@ __decorate([
132
154
  CredentialManager
133
155
  ], DefaultAuthFormEntryStore.prototype, "credentialManager", void 0);
134
156
  __decorate([
135
- FetchMachine
136
- ], DefaultAuthFormEntryStore.prototype, "fetchMachine", void 0);
137
- __decorate([
138
- observable
139
- ], DefaultAuthFormEntryStore.prototype, "host", void 0);
157
+ IDPService
158
+ ], DefaultAuthFormEntryStore.prototype, "idpService", void 0);
140
159
  __decorate([
141
160
  observable
142
161
  ], DefaultAuthFormEntryStore.prototype, "organisation", void 0);
@@ -161,12 +180,6 @@ __decorate([
161
180
  __decorate([
162
181
  observable
163
182
  ], DefaultAuthFormEntryStore.prototype, "passwordResetToken", void 0);
164
- __decorate([
165
- observable
166
- ], DefaultAuthFormEntryStore.prototype, "message", void 0);
167
- __decorate([
168
- observable
169
- ], DefaultAuthFormEntryStore.prototype, "hasErrors", void 0);
170
183
  __decorate([
171
184
  observable
172
185
  ], DefaultAuthFormEntryStore.prototype, "mfaCode", void 0);
@@ -175,7 +188,7 @@ __decorate([
175
188
  ], DefaultAuthFormEntryStore.prototype, "idps", void 0);
176
189
  __decorate([
177
190
  observable
178
- ], DefaultAuthFormEntryStore.prototype, "selectedIDP", void 0);
191
+ ], DefaultAuthFormEntryStore.prototype, "selectedIdp", void 0);
179
192
  __decorate([
180
193
  observable
181
194
  ], DefaultAuthFormEntryStore.prototype, "ssoToggled", void 0);
@@ -189,7 +202,7 @@ __decorate([
189
202
  volatile
190
203
  ], DefaultAuthFormEntryStore.prototype, "orgUsername", null);
191
204
  /**
192
- * DI key of the store.
205
+ * AuthFormEntryStore DI key.
193
206
  * @internal
194
207
  */
195
208
  export const AuthFormEntryStore = registerStore(DefaultAuthFormEntryStore, 'AuthFormEntryStore');
@@ -53,25 +53,3 @@ export const textFieldTag = tagFor(templateOptions.textField);
53
53
  * @internal
54
54
  */
55
55
  export const progressRingTag = tagFor(templateOptions.progressRing);
56
- /**
57
- * @privateRemarks
58
- * An alternative pattern under test.
59
- * @internal
60
- */
61
- export function getTags() {
62
- var _a;
63
- const config = DI.getOrCreateDOMContainer().get(AuthConfig);
64
- const components = (_a = config === null || config === void 0 ? void 0 : config.templateOptions) !== null && _a !== void 0 ? _a : defaultTemplateOptions;
65
- return {
66
- anchor: tagFor(components.anchor),
67
- button: tagFor(components.button),
68
- card: tagFor(components.card),
69
- checkbox: tagFor(components.checkbox),
70
- listboxOption: tagFor(components.listboxOption),
71
- provider: tagFor(components.provider),
72
- router: tagFor(components.router),
73
- select: tagFor(components.select),
74
- textField: tagFor(components.textField),
75
- progressRing: tagFor(components.progressRing),
76
- };
77
- }
@@ -18,6 +18,8 @@ export class DefaultUser {
18
18
  this.pathHistory = [];
19
19
  /** {@inheritDoc UserActionHistory.actionHistory} */
20
20
  this.actionHistory = [];
21
+ /** {@inheritDoc User.isAuthenticated} */
22
+ this.isAuthenticated = false;
21
23
  /** @internal */
22
24
  this.authenticationChangeListeners = createObserver();
23
25
  }
@@ -123,11 +125,13 @@ export class DefaultUser {
123
125
  }
124
126
  /** {@inheritDoc User.addAuthenticationChangeListener} */
125
127
  addAuthenticationChangeListener(listener) {
126
- return this.authenticationChangeListeners.subscribe(listener);
128
+ var _a;
129
+ return (_a = this.authenticationChangeListeners) === null || _a === void 0 ? void 0 : _a.subscribe(listener);
127
130
  }
128
131
  /** @internal */
129
132
  isAuthenticatedChanged() {
130
- this.authenticationChangeListeners.publish(new CustomEvent(UserAuthenticationChangeType, {
133
+ var _a;
134
+ (_a = this.authenticationChangeListeners) === null || _a === void 0 ? void 0 : _a.publish(new CustomEvent(UserAuthenticationChangeType, {
131
135
  detail: this.isAuthenticated,
132
136
  }));
133
137
  }
@@ -1,2 +1 @@
1
1
  export * from './logger';
2
- export * from './sso';
@@ -1,4 +1,4 @@
1
- import { createLogger } from '@genesislcap/foundation-utils';
1
+ import { createLogger } from '@genesislcap/foundation-logger';
2
2
  /**
3
3
  * @public
4
4
  */