@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
@@ -0,0 +1,40 @@
1
+ import { APIError } from '@genesislcap/foundation-state-machine';
2
+ /**
3
+ * NackError.
4
+ *
5
+ * @remarks
6
+ * If Required until http status codes are aligned on backend.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * NackError.fromEntity(event.output);
11
+ * ```
12
+ *
13
+ * @public
14
+ */
15
+ export class NackError extends APIError {
16
+ constructor(status, data, message = 'API Error Occurred') {
17
+ super(status, data, message);
18
+ this.status = status;
19
+ this.data = data;
20
+ }
21
+ /**
22
+ * Construct a {@link NackError} from a {@link Nack}
23
+ * @param entity - The Nack.
24
+ */
25
+ static fromEntity(entity) {
26
+ if (!entity) {
27
+ return null;
28
+ }
29
+ /**
30
+ * Prioritize errors
31
+ */
32
+ if (entity.normalisedErrorStatusCode > 0) {
33
+ return new NackError(entity.normalisedErrorStatusCode, entity, entity.normalisedErrorText);
34
+ }
35
+ if (entity.normalisedWarningStatusCode > 0) {
36
+ return new NackError(entity.normalisedWarningStatusCode, entity, entity.normalisedWarningText);
37
+ }
38
+ return null;
39
+ }
40
+ }
@@ -0,0 +1,11 @@
1
+ import { isDoneInvokeEvent } from '@genesislcap/foundation-state-machine';
2
+ import { isNackDTO, isNackEntity } from '../mapper';
3
+ /**
4
+ * is200Nack.
5
+ * @privateRemarks
6
+ * Required until http status codes are aligned on backend.
7
+ * @public
8
+ */
9
+ export const is200Nack = (event) => isDoneInvokeEvent(event)
10
+ ? isNackEntity(event.output) || isNackDTO(event.output)
11
+ : false;
@@ -1,2 +1,4 @@
1
+ export * from './actions';
2
+ export * from './guards';
1
3
  export * from './machine';
2
4
  export * from './types';
@@ -1,5 +1,5 @@
1
1
  import { __awaiter, __decorate, __param } from "tslib";
2
- import { AbstractMachine, createErrorStateNode, FetchMachine, isDoneInvokeEvent, isErrorEvent, isEventWithParams, isUnauthorizedError, setError, } from '@genesislcap/foundation-state-machine';
2
+ import { AbstractMachine, createErrorStateNode, FetchMachine, isDoneInvokeEvent, isErrorEvent, isEventWithParams, isUnauthorizedError, } from '@genesislcap/foundation-state-machine';
3
3
  import { UUID } from '@genesislcap/foundation-utils';
4
4
  import { DI } from '@microsoft/fast-foundation';
5
5
  import { and, assign, createMachine, fromPromise, not, or, raise, sendTo } from 'xstate';
@@ -11,6 +11,7 @@ import { AuthMessageMapper, createHTTPHeadersFromDTO, isLoginAckEntity, isLoginD
11
11
  import { AuthRouting } from '../routes/routing';
12
12
  import { User } from '../user';
13
13
  import { logger } from '../utils';
14
+ import { setError } from './actions';
14
15
  import { defaultAuthMachineContext, isLoginParams, isQueryParams } from './types';
15
16
  /**
16
17
  * Default AuthMachine.
@@ -26,25 +27,28 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
26
27
  this.messageMapper = messageMapper;
27
28
  this.config = config;
28
29
  this.routing = routing;
29
- this.onIdleEvents = () => ({
30
- login: {
31
- actions: ['resetContext', 'setParams'],
32
- target: '#authMachine.loggingIn',
33
- },
34
- ['forgot-password']: {
35
- actions: ['resetContext', 'setParams'],
36
- target: '#authMachine.forgotPassword',
37
- },
38
- ['change-password']: {
39
- actions: ['resetContext', 'setParams'],
40
- target: '#authMachine.changePassword',
41
- },
42
- ['reset-password']: {
43
- actions: ['resetContext', 'setParams'],
44
- target: '#authMachine.resetPassword',
45
- },
46
- });
47
- this.onDoneDTO = () => ({
30
+ this.onIdleEvents = () => {
31
+ const actions = ['resetContext', 'setParams'];
32
+ return {
33
+ login: {
34
+ actions,
35
+ target: '#authMachine.loggingIn',
36
+ },
37
+ ['forgot-password']: {
38
+ actions,
39
+ target: '#authMachine.forgotPassword',
40
+ },
41
+ ['change-password']: {
42
+ actions,
43
+ target: '#authMachine.changePassword',
44
+ },
45
+ ['reset-password']: {
46
+ actions,
47
+ target: '#authMachine.resetPassword',
48
+ },
49
+ };
50
+ };
51
+ this.dtoTransition = () => ({
48
52
  actions: ['setDTO'],
49
53
  target: 'mapEntity',
50
54
  });
@@ -90,8 +94,9 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
90
94
  },
91
95
  {
92
96
  /**
93
- * Silent login (cookie based, only when on login screen)
97
+ * Silent login (cookie based)
94
98
  */
99
+ guard: and([not('hasQueryParams'), not('hasLoginParams')]),
95
100
  target: '#authMachine.silentLogin',
96
101
  },
97
102
  ],
@@ -114,7 +119,7 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
114
119
  invoke: {
115
120
  id: 'loginDetailsFetcher',
116
121
  src: fetchMachine.machine,
117
- onDone: this.onDoneDTO(),
122
+ onDone: this.dtoTransition(),
118
123
  onError: [
119
124
  {
120
125
  guard: 'isUnauthorizedError',
@@ -138,7 +143,7 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
138
143
  invoke: {
139
144
  id: 'loginFetcher',
140
145
  src: fetchMachine.machine,
141
- onDone: this.onDoneDTO(),
146
+ onDone: this.dtoTransition(),
142
147
  onError: 'error.login',
143
148
  },
144
149
  entry: [
@@ -173,7 +178,7 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
173
178
  invoke: {
174
179
  id: 'logoutFetcher',
175
180
  src: fetchMachine.machine,
176
- onDone: this.onDoneDTO(),
181
+ onDone: this.dtoTransition(),
177
182
  onError: 'error.logout',
178
183
  },
179
184
  entry: [
@@ -226,7 +231,7 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
226
231
  src: fetchMachine.machine,
227
232
  onDone: [
228
233
  {
229
- guard: 'is200Nack',
234
+ guard: 'is200NackDTO',
230
235
  target: 'error.changePassword',
231
236
  },
232
237
  {
@@ -329,9 +334,8 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
329
334
  target: '#authMachine.authCheck',
330
335
  },
331
336
  {
332
- guard: 'isLogoutAckEntity',
333
- actions: ['unsetUser'],
334
- target: '#authMachine.authCheck',
337
+ guard: and(['isLoginNackEntity', 'hasIncorrectCredentials']),
338
+ target: '#authMachine.feedback.incorrectCredentials',
335
339
  },
336
340
  {
337
341
  guard: and(['isLoginNackEntity', 'isMFARequired']),
@@ -343,14 +347,15 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
343
347
  actions: 'storeBasicCredentials',
344
348
  target: '#authMachine.feedback.passwordExpired',
345
349
  },
346
- /**
347
- * Old login mf logic used to cross-check compid / organisation field to see if it might be a validation
348
- * error around that, but I'm not sure if it's still being used? TODO: Ask around.
349
- */
350
350
  {
351
351
  guard: 'isLoginNackEntity',
352
352
  target: '#authMachine.error.login',
353
353
  },
354
+ {
355
+ guard: 'isLogoutAckEntity',
356
+ actions: ['unsetUser'],
357
+ target: '#authMachine.authCheck',
358
+ },
354
359
  {
355
360
  guard: 'isLogoutNackEntity',
356
361
  target: '#authMachine.error.logout',
@@ -380,6 +385,7 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
380
385
  },
381
386
  /**
382
387
  * Feedback states. These are transient and revert back to idle after a short delay.
388
+ * These can help improve UX in when the backend nack text is lacking clarity, as with incorrect credentials.
383
389
  */
384
390
  feedback: {
385
391
  initial: 'none',
@@ -414,6 +420,15 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
414
420
  feedbackDelay: '#authMachine.idle',
415
421
  },
416
422
  },
423
+ incorrectCredentials: {
424
+ tags: ['feedback', 'incorrectCredentials'],
425
+ meta: {
426
+ content: 'Incorrect credentials, please try again.',
427
+ },
428
+ after: {
429
+ feedbackDelay: '#authMachine.idle',
430
+ },
431
+ },
417
432
  mfaRequired: {
418
433
  tags: ['feedback', 'mfaRequired'],
419
434
  meta: {
@@ -452,7 +467,6 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
452
467
  resetPassword: createErrorStateNode('reset-password', 'Reset password error.'),
453
468
  logout: createErrorStateNode('logout', 'Logout error.'),
454
469
  mapping: createErrorStateNode('mapping', 'Mapping error.'),
455
- auth: createErrorStateNode('Auth', 'Auth error.'),
456
470
  },
457
471
  on: this.onIdleEvents(),
458
472
  },
@@ -466,10 +480,6 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
466
480
  },
467
481
  }, {
468
482
  actors: {
469
- /**
470
- * TODO: Test reusing a single fetch machine here, not that it matters much
471
- */
472
- fetcher: this.fetchMachine.machine,
473
483
  mapper: fromPromise(({ input }) => __awaiter(this, void 0, void 0, function* () { return input.mapper(input.dto); })),
474
484
  },
475
485
  actions: {
@@ -540,33 +550,9 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
540
550
  postLoginRedirect: this.config.postLoginRedirect,
541
551
  postLogoutRedirect: this.config.postLogoutRedirect,
542
552
  resetPasswordRedirect: () => this.routing.navigateTo('reset-password?expired'),
543
- /**
544
- * loggedInCallback.
545
- * @remarks
546
- * Can be overridden by the caller. Alternatively callers can observe machine.context.
547
- * @public
548
- */
549
- loggedInCallback: () => {
550
- logger.debug('AuthMachine.loggedInCallback invoked. Should be overwritten in most cases.');
551
- },
552
- /**
553
- * loggedOutCallback.
554
- * @remarks
555
- * Can be overridden by the caller. Alternatively callers can observe machine.context.
556
- * @public
557
- */
558
- loggedOutCallback: () => {
559
- logger.debug('AuthMachine.loggedOutCallback invoked. Should be overwritten in most cases.');
560
- },
561
- /**
562
- * errorCallback.
563
- * @remarks
564
- * Can be overridden by the caller. Alternatively callers can observe machine.context.
565
- * @public
566
- */
567
- errorCallback: () => {
568
- logger.debug('AuthMachine.errorCallback invoked. Should be overwritten in most cases.');
569
- },
553
+ loggedInCallback: () => logger.debug('AuthMachine.loggedInCallback invoked.'),
554
+ loggedOutCallback: () => logger.debug('AuthMachine.loggedOutCallback invoked.'),
555
+ errorCallback: () => logger.debug('AuthMachine.errorCallback invoked.'),
570
556
  },
571
557
  guards: {
572
558
  hasParams: ({ context }) => context.params !== undefined,
@@ -581,6 +567,9 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
581
567
  isLoginAckEntity: ({ event }) => isDoneInvokeEvent(event) ? isLoginAckEntity(event.output) : false,
582
568
  isLoginDetailsAckEntity: ({ event }) => isDoneInvokeEvent(event) ? isLoginDetailsAckEntity(event.output) : false,
583
569
  isLoginNackEntity: ({ event }) => isDoneInvokeEvent(event) ? isLoginNackEntity(event.output) : false,
570
+ hasIncorrectCredentials: ({ event }) => isDoneInvokeEvent(event)
571
+ ? isLoginNackEntity(event.output) && event.output.hasIncorrectCredentials
572
+ : false,
584
573
  isMFARequired: ({ event }) => isDoneInvokeEvent(event)
585
574
  ? isLoginNackEntity(event.output) && event.output.isMFARequired
586
575
  : false,
@@ -590,9 +579,9 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
590
579
  isLogoutAckEntity: ({ event }) => isDoneInvokeEvent(event) ? isLogoutAckEntity(event.output) : false,
591
580
  isLogoutNackEntity: ({ event }) => isDoneInvokeEvent(event) ? isLogoutNackEntity(event.output) : false,
592
581
  /**
593
- * Temp until server guys fix http status codes
582
+ * Required until strict http status codes are enabled on the backend by default.
594
583
  */
595
- is200Nack: ({ event }) => {
584
+ is200NackDTO: ({ event }) => {
596
585
  var _a, _b;
597
586
  return isDoneInvokeEvent(event)
598
587
  ? ((_b = (_a = event.output) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.ok) && isNackDTO(event.output.data)
@@ -627,6 +616,7 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
627
616
  convertQueryParamsToLoginParams(params) {
628
617
  const ssoCredentials = params.SSO_TOKEN
629
618
  ? {
619
+ type: CredentialType.SSO,
630
620
  ssoToken: params.SSO_TOKEN,
631
621
  }
632
622
  : undefined;
@@ -636,6 +626,7 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
636
626
  }
637
627
  const mfaCredentials = params.MFA_CODE
638
628
  ? {
629
+ type: CredentialType.MFA,
639
630
  mfaToken: params.MFA_CODE,
640
631
  }
641
632
  : undefined;
@@ -3,6 +3,7 @@ import { EventEmitter } from '@genesislcap/foundation-events';
3
3
  import { customElement, FASTElement } from '@microsoft/fast-element';
4
4
  import { Container, inject, Registration } from '@microsoft/fast-foundation';
5
5
  import { DefaultRouteRecognizer } from '@microsoft/fast-router';
6
+ import { classNames } from '@microsoft/fast-web-utilities';
6
7
  import '../components/core-components';
7
8
  import { AuthRouterConfig } from '../routes/config';
8
9
  import { AuthStore } from '../store';
@@ -27,6 +28,7 @@ export class FoundationAuth extends EventEmitter(FASTElement) {
27
28
  connectedCallback() {
28
29
  this.registerDIDependencies();
29
30
  super.connectedCallback();
31
+ this.addBindings();
30
32
  this.addEventListeners();
31
33
  this.readyStore();
32
34
  }
@@ -35,6 +37,7 @@ export class FoundationAuth extends EventEmitter(FASTElement) {
35
37
  */
36
38
  disconnectedCallback() {
37
39
  super.disconnectedCallback();
40
+ this.removeBindings();
38
41
  this.removeEventListeners();
39
42
  }
40
43
  /**
@@ -43,6 +46,22 @@ export class FoundationAuth extends EventEmitter(FASTElement) {
43
46
  registerDIDependencies() {
44
47
  this.container.register(Registration.transient(DefaultRouteRecognizer, DefaultRouteRecognizer));
45
48
  }
49
+ /**
50
+ * @internal
51
+ */
52
+ addBindings() {
53
+ this.machineBinding = this.store.authMachine.binding((x) => x.snapshot.value, (value) => {
54
+ if (value === 'loggedOut') {
55
+ this.attemptAutofill();
56
+ }
57
+ });
58
+ }
59
+ /**
60
+ * @internal
61
+ */
62
+ removeBindings() {
63
+ this.machineBinding.disconnect();
64
+ }
46
65
  /**
47
66
  * @internal
48
67
  */
@@ -66,7 +85,23 @@ export class FoundationAuth extends EventEmitter(FASTElement) {
66
85
  * @internal
67
86
  */
68
87
  get isReady() {
69
- return !this.store.isPending;
88
+ return (!this.store.authMachine.hasTag('initializing') &&
89
+ !this.store.authMachine.hasTag('silentLogin'));
90
+ }
91
+ /**
92
+ * @internal
93
+ */
94
+ get classNames() {
95
+ return classNames(['ready', this.isReady], ['not-ready', !this.isReady]);
96
+ }
97
+ /**
98
+ * @internal
99
+ */
100
+ attemptAutofill() {
101
+ const { autofilling, ssoToggled, username, password } = this.store.formEntry;
102
+ if (!autofilling && !ssoToggled && !username && !password) {
103
+ this.$emit('auth-autofill-form');
104
+ }
70
105
  }
71
106
  }
72
107
  __decorate([
@@ -111,6 +146,13 @@ __decorate([
111
146
  * @public
112
147
  */
113
148
  let ZeroAuth = class ZeroAuth extends FoundationAuth {
149
+ constructor() {
150
+ super(...arguments);
151
+ /**
152
+ * @internal
153
+ */
154
+ this.zeroReady = false;
155
+ }
114
156
  /**
115
157
  * @internal
116
158
  */
@@ -135,9 +177,11 @@ let ZeroAuth = class ZeroAuth extends FoundationAuth {
135
177
  }
136
178
  /**
137
179
  * @internal
180
+ * @privateRemarks
181
+ * The order of the check is important here, check super first.
138
182
  */
139
183
  get isReady() {
140
- return this.zeroReady && super.isReady;
184
+ return super.isReady && this.zeroReady;
141
185
  }
142
186
  };
143
187
  ZeroAuth = __decorate([
@@ -18,7 +18,9 @@ export const styles = css `
18
18
  height: 100%;
19
19
  }
20
20
 
21
- :host([hidden]) {
21
+ :host([hidden]),
22
+ :host(.not-ready),
23
+ ${providerTag}.not-ready {
22
24
  display: none;
23
25
  }
24
26
 
@@ -4,7 +4,8 @@ import { providerTag, routerTag } from '../tags';
4
4
  * @public
5
5
  */
6
6
  export const template = html `
7
- <${providerTag} data-test-id="auth-provider">
7
+ <${providerTag} data-test-id="auth-provider" class="${(x) => x.classNames}">
8
8
  <${routerTag} :config=${(x) => x.config} data-test-id="auth-router"></${routerTag}>
9
+ <slot></slot>
9
10
  </${providerTag}>
10
11
  `;
@@ -3,7 +3,7 @@ import { UUID } from '@genesislcap/foundation-utils';
3
3
  import { DI } from '@microsoft/fast-foundation';
4
4
  import { CredentialType } from '../credential';
5
5
  import { MESSAGE_TYPE } from '../dto';
6
- import { isLoginParams } from '../machine';
6
+ import { isLoginParams } from '../machine/types';
7
7
  import { logger } from '../utils';
8
8
  import { MappingError } from './error';
9
9
  import { fromDTOAck, fromDTONack, fromDTOStringArray, hasDTOErrorWarningCode } from './utils';
@@ -82,7 +82,7 @@ export class DefaultLoginMapper {
82
82
  return ack;
83
83
  }
84
84
  if (isLoginNackDTO(dto)) {
85
- const nack = Object.assign(Object.assign({}, fromDTONack(dto)), { refreshAuthToken: dto.REFRESH_AUTH_TOKEN, isMFARequired: hasDTOErrorWarningCode(dto, 'MFA_REQUIRED'), hasPasswordExpired: hasDTOErrorWarningCode(dto, 'PASSWORD_EXPIRED') });
85
+ const nack = Object.assign(Object.assign({}, fromDTONack(dto)), { refreshAuthToken: dto.REFRESH_AUTH_TOKEN, hasIncorrectCredentials: hasDTOErrorWarningCode(dto, 'INCORRECT_CREDENTIALS'), maxTriesReached: hasDTOErrorWarningCode(dto, 'MAX_TRIES_REACHED'), isMFARequired: hasDTOErrorWarningCode(dto, 'MFA_REQUIRED'), hasPasswordExpired: hasDTOErrorWarningCode(dto, 'PASSWORD_EXPIRED') });
86
86
  return nack;
87
87
  }
88
88
  throw new Error('No Entity mapping implementation for provided DTO');
@@ -2,7 +2,7 @@ import { __decorate } from "tslib";
2
2
  import { UUID } from '@genesislcap/foundation-utils';
3
3
  import { DI } from '@microsoft/fast-foundation';
4
4
  import { MESSAGE_TYPE } from '../dto';
5
- import { isChangePasswordParams, isForgotPasswordParams, isResetPasswordParams } from '../machine';
5
+ import { isChangePasswordParams, isForgotPasswordParams, isResetPasswordParams, } from '../machine/types';
6
6
  import { logger } from '../utils';
7
7
  import { MappingError } from './error';
8
8
  /**
@@ -1,12 +1,11 @@
1
- import { MESSAGE_TYPE } from '../dto';
2
1
  /**
3
2
  * @public
4
3
  */
5
4
  export const fromDTOStringArray = (arr) => Array.isArray(arr) ? arr.map((v) => (v !== null && v !== void 0 ? v : '').toLowerCase()) : [];
6
5
  /**
7
- * @public
6
+ * @internal
8
7
  */
9
- export const fromDTONackErrorWarningArray = (arr) => Array.isArray(arr)
8
+ const fromDTONackErrorWarningArray = (arr) => Array.isArray(arr)
10
9
  ? arr.map((v) => ({
11
10
  type: v['@type'],
12
11
  code: v.CODE,
@@ -16,9 +15,36 @@ export const fromDTONackErrorWarningArray = (arr) => Array.isArray(arr)
16
15
  : [];
17
16
  /**
18
17
  * includesErrorWarningCode
19
- * @public
18
+ * @internal
19
+ */
20
+ const includesErrorWarningCode = (arr, code) => Array.isArray(arr) ? arr.some((e) => e.CODE === code || e.STATUS_CODE === code) : false;
21
+ /**
22
+ * getNormalisedStatusCode
23
+ * @param arr - A NackErrorWarning array.
24
+ * @returns The highest status code.
25
+ * @internal
26
+ */
27
+ const getNormalisedStatusCode = (arr) => {
28
+ if (!Array.isArray(arr) || arr.length === 0) {
29
+ return;
30
+ }
31
+ const codes = arr.map((msg) => {
32
+ try {
33
+ return parseInt(msg.statusCode);
34
+ }
35
+ catch (e) {
36
+ return 0;
37
+ }
38
+ });
39
+ return codes.sort().pop();
40
+ };
41
+ /**
42
+ * getNormalisedText
43
+ * @param arr - A NackErrorWarning array.
44
+ * @returns A combined text string.
45
+ * @internal
20
46
  */
21
- export const includesErrorWarningCode = (arr, code) => Array.isArray(arr) ? arr.some((e) => e.CODE === code || e.STATUS_CODE === code) : false;
47
+ export const getNormalisedText = (arr) => Array.isArray(arr) && arr.length ? arr.map((msg) => msg.text).join(' ') : undefined;
22
48
  /**
23
49
  * hasDTOErrorWarningCode
24
50
  * @remarks
@@ -46,19 +72,49 @@ export const fromDTOAck = (dto) => ({
46
72
  * @param dto - NACK.
47
73
  * @public
48
74
  */
49
- export const fromDTONack = (dto) => ({
50
- messageType: dto.MESSAGE_TYPE,
51
- sourceRef: dto.SOURCE_REF,
52
- error: fromDTONackErrorWarningArray(dto.ERROR),
53
- warning: fromDTONackErrorWarningArray(dto.WARNING),
54
- });
75
+ export const fromDTONack = (dto) => {
76
+ const error = fromDTONackErrorWarningArray(dto.ERROR);
77
+ const warning = fromDTONackErrorWarningArray(dto.WARNING);
78
+ return {
79
+ messageType: dto.MESSAGE_TYPE,
80
+ sourceRef: dto.SOURCE_REF,
81
+ error,
82
+ warning,
83
+ normalisedErrorStatusCode: getNormalisedStatusCode(error),
84
+ normalisedWarningStatusCode: getNormalisedStatusCode(warning),
85
+ normalisedErrorText: getNormalisedText(error),
86
+ normalisedWarningText: getNormalisedText(warning),
87
+ };
88
+ };
89
+ /**
90
+ * fromIDPDTO
91
+ * @param dto - IDP.
92
+ * @public
93
+ */
94
+ export const fromIDPDTO = (dto) => {
95
+ return {
96
+ id: dto.ID,
97
+ type: dto.TYPE,
98
+ description: dto.DESCRIPTION,
99
+ };
100
+ };
55
101
  /**
56
- * isDTONack.
102
+ * isNackDTO.
57
103
  * @param dto - Potential NACK.
58
104
  * @public
59
105
  */
60
106
  export function isNackDTO(dto) {
61
- return (dto === null || dto === void 0 ? void 0 : dto.MESSAGE_TYPE) === MESSAGE_TYPE.EVENT_NACK;
107
+ var _a;
108
+ return (_a = dto === null || dto === void 0 ? void 0 : dto.MESSAGE_TYPE) === null || _a === void 0 ? void 0 : _a.endsWith('_NACK');
109
+ }
110
+ /**
111
+ * isNackEntity.
112
+ * @param entity - Potential Nack.
113
+ * @public
114
+ */
115
+ export function isNackEntity(entity) {
116
+ var _a;
117
+ return (_a = entity === null || entity === void 0 ? void 0 : entity.messageType) === null || _a === void 0 ? void 0 : _a.endsWith('_NACK');
62
118
  }
63
119
  /**
64
120
  * createHTTPHeadersFromDTO.
@@ -45,12 +45,6 @@ export class BaseRoute extends ConfigHostElement {
45
45
  super(...arguments);
46
46
  this.onBack = () => this.routing.navigateTo('/');
47
47
  }
48
- attemptAutofill() {
49
- const { autofilling, ssoToggled, username, password } = this.store.formEntry;
50
- if (!autofilling && !ssoToggled && !username && !password) {
51
- this.$emit('auth-autofill-form');
52
- }
53
- }
54
48
  }
55
49
  __decorate([
56
50
  AuthStore
@@ -313,13 +307,15 @@ export const showPasswordsCheckbox = () => html `
313
307
  */
314
308
  let MessageElement = class MessageElement extends FASTElement {
315
309
  get message() {
316
- return this.store.authMachine.getMetaValuesByKey().join('/n');
310
+ const meta = this.store.metaMessages.join('/n');
311
+ const error = this.store.errorMessages.join('/n');
312
+ return !error ? meta : `${meta} ${error}.`;
317
313
  }
318
- get nonError() {
319
- return this.store.authMachine.errors.size === 0;
314
+ get hasError() {
315
+ return this.store.errorMessages.length > 0;
320
316
  }
321
317
  get classNames() {
322
- return classNames('message', ['non-error', this.nonError]);
318
+ return classNames('message', ['has-error', this.hasError]);
323
319
  }
324
320
  };
325
321
  __decorate([
@@ -340,12 +336,12 @@ MessageElement = __decorate([
340
336
  text-align: center;
341
337
  }
342
338
  .message {
343
- color: ${SecondaryRapidColorHEX.orange};
339
+ color: ${SecondaryRapidColorHEX.teal};
344
340
  margin-top: calc(var(--design-unit) * 3px);
345
341
  white-space: pre-line;
346
342
  }
347
- .message.non-error {
348
- color: ${SecondaryRapidColorHEX.teal};
343
+ .message.has-error {
344
+ color: ${SecondaryRapidColorHEX.orange};
349
345
  }
350
346
  `,
351
347
  })
@@ -18,7 +18,7 @@ let AuthRouterConfig = class AuthRouterConfig extends RouterConfiguration {
18
18
  this.authConfig = authConfig;
19
19
  }
20
20
  configure() {
21
- this.title = 'Login';
21
+ this.title = 'Auth';
22
22
  this.defaultLayout = defaultLayout;
23
23
  const routes = [
24
24
  {
@@ -5,10 +5,6 @@ import { logger } from '../../utils';
5
5
  import { BaseRoute } from '../base';
6
6
  import { ForgotPasswordTemplate as template } from './forgot-password.template';
7
7
  let ForgotPassword = class ForgotPassword extends BaseRoute {
8
- connectedCallback() {
9
- super.connectedCallback();
10
- this.attemptAutofill();
11
- }
12
8
  onSubmit() {
13
9
  return __awaiter(this, void 0, void 0, function* () {
14
10
  logger.debug('forgot password submission');
@@ -7,10 +7,10 @@ export const ForgotPasswordTemplate = html `
7
7
  <${cardTag} class="card-pd">
8
8
  <div class="column-content">
9
9
  <auth-logo></auth-logo>
10
- <div class="heading2">Forgotten Password</div>
10
+ <div class="heading2" data-test-id="heading">Forgotten Password</div>
11
11
  <div class="heading3">Enter your account username</div>
12
12
  </div>
13
- <form @submit=${(x) => x.onSubmit()}>
13
+ <form @submit=${(x) => x.onSubmit()} data-test-id="form">
14
14
  ${organisationField()} ${usernameField()}
15
15
  <div class="form-buttons">
16
16
  ${submitButton('Send Recovery Link')} ${backButton((x) => x.onBack())}
@@ -1,4 +1,3 @@
1
1
  export * from './config';
2
- export * from './routing';
3
2
  export * from './types';
4
3
  export * from './utils';