@genesislcap/foundation-auth 15.14.2-FUI-2603.1 → 15.14.2-FUI-2603.2

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.
@@ -0,0 +1,34 @@
1
+ import type { EventObject } from 'xstate';
2
+ import type { CredentialData } from '../credential';
3
+ /**
4
+ * Unwrap a Genesis auth DTO from FetchMachine output or APIError.
5
+ * @public
6
+ */
7
+ export declare function unwrapAuthDto(value: unknown): unknown;
8
+ type AuthMachineEventLike = EventObject & {
9
+ data?: unknown;
10
+ error?: unknown;
11
+ output?: unknown;
12
+ };
13
+ /**
14
+ * Read the auth DTO from a fetch done/error event.
15
+ * @public
16
+ */
17
+ export declare function authDtoFromMachineEvent(event: AuthMachineEventLike): unknown;
18
+ /**
19
+ * True when a fetch done/error event carries a Genesis NACK / ERROR payload.
20
+ * @public
21
+ */
22
+ export declare function isAuthNackEvent(event: AuthMachineEventLike): boolean;
23
+ /**
24
+ * True when fetch completed in the failed final state without a Genesis NACK body.
25
+ * @public
26
+ */
27
+ export declare function isFetchFailureOutput(event: AuthMachineEventLike): boolean;
28
+ /**
29
+ * Fire-and-forget credential persistence so xstate does not hold pending on the Promise.
30
+ * @public
31
+ */
32
+ export declare function persistCredentials(store: (data: CredentialData) => Promise<unknown> | unknown, data: CredentialData): void;
33
+ export {};
34
+ //# sourceMappingURL=dto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dto.d.ts","sourceRoot":"","sources":["../../../src/machine/dto.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAMpD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcrD;AAED,KAAK,oBAAoB,GAAG,WAAW,GAAG;IACxC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAMF;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAQ5E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAEpE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CASzE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,EAC3D,IAAI,EAAE,cAAc,GACnB,IAAI,CASN"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dto.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dto.test.d.ts","sourceRoot":"","sources":["../../../src/machine/dto.test.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../../src/machine/machine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAEf,YAAY,EACZ,iBAAiB,EAMjB,OAAO,EACR,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACpD,OAAO,EACL,IAAI,EAQL,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAEL,iBAAiB,EAIlB,MAAM,eAAe,CAAC;AAIvB,OAAO,EACL,iBAAiB,EAQlB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,EAEV,kBAAkB,EAClB,gBAAgB,EAGhB,WAAW,EACX,WAAW,EAEZ,MAAM,SAAS,CAAC;AAGjB;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,OAAO,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;CAAG;AAErF;;;GAGG;AACH,qBAAa,kBACX,SAAQ,eAAe,CAAC,kBAAkB,EAAE,gBAAgB,CAC5D,YAAW,WAAW;IAGd,OAAO,CAAC,IAAI;IACJ,OAAO,CAAC,YAAY;IACf,OAAO,CAAC,EAAE;IACvB,OAAO,CAAC,IAAI;IACC,OAAO,CAAC,aAAa;IAC5B,OAAO,CAAC,MAAM;IACb,OAAO,CAAC,OAAO;gBANd,IAAI,EAAE,IAAI,EACF,YAAY,EAAE,YAAY,EACrB,EAAE,EAAE,iBAAiB,EAClC,IAAI,EAAE,IAAI,EACG,aAAa,EAAE,iBAAiB,EACvC,MAAM,EAAE,UAAU,EACjB,OAAO,EAAE,WAAW;IAyqB3C,KAAK,CACH,OAAO,GAAE,kBAAkB,CAAC,OAAO,IAAI,CAAC,OAAO,CAM9C;IAKH;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAIxB,SAAS,CAAC,sBAAsB,IAAI,WAAW;IAQ/C,SAAS,CAAC,+BAA+B,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW;IAuB3E,SAAS,CAAC,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,GAAG,iBAAiB;IAgB3E,SAAS,CAAC,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;MA4BpB;IAEF,SAAS,CAAC,aAAa;;;MAGpB;CACJ;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,mEAA0E,CAAC;AAEnG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C"}
1
+ {"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../../src/machine/machine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAEf,YAAY,EACZ,iBAAiB,EAKjB,OAAO,EACR,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACpD,OAAO,EACL,IAAI,EAQL,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAEL,iBAAiB,EAIlB,MAAM,eAAe,CAAC;AAIvB,OAAO,EACL,iBAAiB,EAQlB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAShD,OAAO,KAAK,EAEV,kBAAkB,EAClB,gBAAgB,EAGhB,WAAW,EACX,WAAW,EAEZ,MAAM,SAAS,CAAC;AAGjB;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,OAAO,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;CAAG;AAErF;;;GAGG;AACH,qBAAa,kBACX,SAAQ,eAAe,CAAC,kBAAkB,EAAE,gBAAgB,CAC5D,YAAW,WAAW;IAGd,OAAO,CAAC,IAAI;IACJ,OAAO,CAAC,YAAY;IACf,OAAO,CAAC,EAAE;IACvB,OAAO,CAAC,IAAI;IACC,OAAO,CAAC,aAAa;IAC5B,OAAO,CAAC,MAAM;IACb,OAAO,CAAC,OAAO;gBANd,IAAI,EAAE,IAAI,EACF,YAAY,EAAE,YAAY,EACrB,EAAE,EAAE,iBAAiB,EAClC,IAAI,EAAE,IAAI,EACG,aAAa,EAAE,iBAAiB,EACvC,MAAM,EAAE,UAAU,EACjB,OAAO,EAAE,WAAW;IA4sB3C,KAAK,CACH,OAAO,GAAE,kBAAkB,CAAC,OAAO,IAAI,CAAC,OAAO,CAM9C;IAKH;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAIxB,SAAS,CAAC,sBAAsB,IAAI,WAAW;IAQ/C,SAAS,CAAC,+BAA+B,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW;IAuB3E,SAAS,CAAC,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,GAAG,iBAAiB;IAgB3E,SAAS,CAAC,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;MA4BpB;IAEF,SAAS,CAAC,aAAa;;;MAGpB;CACJ;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,mEAA0E,CAAC;AAEnG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C"}
@@ -405,6 +405,11 @@ export declare class BaseRoute extends ConfigHostElement {
405
405
  store: AuthStore;
406
406
  routing: AuthRouting;
407
407
  connectedCallback(): void;
408
+ /**
409
+ * Skip dismiss while a request or MFA challenge is in flight so route
410
+ * (re)connect does not cancel the current auth step.
411
+ */
412
+ protected get shouldDismissOnConnect(): boolean;
408
413
  onBack: () => void;
409
414
  toLocalisedText(text: string): string;
410
415
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/routes/base.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAGpD,OAAO,EAEL,OAAO,EAQR,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAqB,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC;;GAEG;AACH,KAAK,QAAQ,GAAG,YAAY,GAAG,qBAAqB,GAAG,EAAE,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,SAAS,yKAAiC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,UAAU,yKAAkC,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,sBAAoC,YAAW,UAAU;IACnF,SAAS,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IAC/B;;;OAGG;IACM,OAAO,EAAG,OAAO,CAAC;IAE3B,iBAAiB;CAYlB;AAED;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,iBAAiB;IACxC,IAAI,EAAE,IAAI,CAAC;IACN,KAAK,EAAE,SAAS,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IAElC,iBAAiB;IAMjB,MAAM,aAAsC;IAE5C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAGtC;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,SAAS,6DAsBpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,SAAS,6DAmBhD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,SAAS,6DAoB7C,CAAC;AAoBF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,SAAS,EAAE,QAAQ,MAAM,2DAgBhE,CAAC;AAyBF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,SAAS,EAChD,MAAM,KAAK,GAAG,cAAc,GAAG,YAAY,2DAkB5C,CAAC;AAoHF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,UAAU,EAAE,SAAS,OAAO,EAAE,OAAO,MAAM,2DAU/E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,UAAU,EAC/C,OAAO,MAAM,EACb,aAAY,MAAiB,EAC7B,WAAU,OAAe,2DAW1B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,SAAS,6DAO3D,CAAC"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/routes/base.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAGpD,OAAO,EAEL,OAAO,EAQR,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAqB,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC;;GAEG;AACH,KAAK,QAAQ,GAAG,YAAY,GAAG,qBAAqB,GAAG,EAAE,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,SAAS,yKAAiC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,UAAU,yKAAkC,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,sBAAoC,YAAW,UAAU;IACnF,SAAS,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IAC/B;;;OAGG;IACM,OAAO,EAAG,OAAO,CAAC;IAE3B,iBAAiB;CAYlB;AAED;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,iBAAiB;IACxC,IAAI,EAAE,IAAI,CAAC;IACN,KAAK,EAAE,SAAS,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IAElC,iBAAiB;IAQjB;;;OAGG;IACH,SAAS,KAAK,sBAAsB,IAAI,OAAO,CAM9C;IAED,MAAM,aAAsC;IAE5C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAGtC;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,SAAS,6DAsBpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,SAAS,6DAmBhD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,SAAS,6DAoB7C,CAAC;AAoBF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,SAAS,EAAE,QAAQ,MAAM,2DAgBhE,CAAC;AAyBF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,SAAS,EAChD,MAAM,KAAK,GAAG,cAAc,GAAG,YAAY,2DAkB5C,CAAC;AAoHF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,UAAU,EAAE,SAAS,OAAO,EAAE,OAAO,MAAM,2DAU/E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,UAAU,EAC/C,OAAO,MAAM,EACb,aAAY,MAAiB,EAC7B,WAAU,OAAe,2DAW1B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,SAAS,6DAO3D,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { isAPIError, isDoneInvokeEvent, isErrorCustomEvent, isErrorEvent, } from '@genesislcap/foundation-state-machine';
2
+ import { isFailedAuthDTO } from '../mapper/utils';
3
+ const hasMessageType = (value) => typeof value === 'object' && value !== null && 'MESSAGE_TYPE' in value;
4
+ /**
5
+ * Unwrap a Genesis auth DTO from FetchMachine output or APIError.
6
+ * @public
7
+ */
8
+ export function unwrapAuthDto(value) {
9
+ if (value == null) {
10
+ return undefined;
11
+ }
12
+ if (isAPIError(value)) {
13
+ return unwrapAuthDto(value.data);
14
+ }
15
+ if (hasMessageType(value)) {
16
+ return value;
17
+ }
18
+ if (typeof value === 'object' && 'data' in value) {
19
+ return unwrapAuthDto(value.data);
20
+ }
21
+ return undefined;
22
+ }
23
+ function eventErrorPayload(event) {
24
+ var _a, _b;
25
+ return (_b = (_a = event.data) !== null && _a !== void 0 ? _a : event.error) !== null && _b !== void 0 ? _b : event.output;
26
+ }
27
+ /**
28
+ * Read the auth DTO from a fetch done/error event.
29
+ * @public
30
+ */
31
+ export function authDtoFromMachineEvent(event) {
32
+ var _a;
33
+ if (isDoneInvokeEvent(event)) {
34
+ return unwrapAuthDto(event.output);
35
+ }
36
+ if (isErrorEvent(event) || isErrorCustomEvent(event)) {
37
+ return unwrapAuthDto(eventErrorPayload(event));
38
+ }
39
+ return unwrapAuthDto((_a = eventErrorPayload(event)) !== null && _a !== void 0 ? _a : event);
40
+ }
41
+ /**
42
+ * True when a fetch done/error event carries a Genesis NACK / ERROR payload.
43
+ * @public
44
+ */
45
+ export function isAuthNackEvent(event) {
46
+ return isFailedAuthDTO(authDtoFromMachineEvent(event));
47
+ }
48
+ /**
49
+ * True when fetch completed in the failed final state without a Genesis NACK body.
50
+ * @public
51
+ */
52
+ export function isFetchFailureOutput(event) {
53
+ if (!isDoneInvokeEvent(event)) {
54
+ return false;
55
+ }
56
+ const output = event.output;
57
+ if ((output === null || output === void 0 ? void 0 : output.error) == null) {
58
+ return false;
59
+ }
60
+ return !isAuthNackEvent(event);
61
+ }
62
+ /**
63
+ * Fire-and-forget credential persistence so xstate does not hold pending on the Promise.
64
+ * @public
65
+ */
66
+ export function persistCredentials(store, data) {
67
+ try {
68
+ const result = store(data);
69
+ if (result && typeof result.then === 'function') {
70
+ void result.catch(() => undefined);
71
+ }
72
+ }
73
+ catch (_a) {
74
+ // Credential storage is best-effort.
75
+ }
76
+ }
@@ -0,0 +1,88 @@
1
+ import { __awaiter } from "tslib";
2
+ import { APIError } from '@genesislcap/foundation-state-machine';
3
+ import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
4
+ import { StatusCodes } from 'http-status-codes';
5
+ import { authDtoFromMachineEvent, isAuthNackEvent, isFetchFailureOutput, persistCredentials, unwrapAuthDto, } from './dto';
6
+ const Suite = createLogicSuite('authDtoFromMachineEvent');
7
+ const mfaNack = {
8
+ ERROR: [
9
+ {
10
+ '@type': 'LoginError',
11
+ CODE: 'MFA_REQUIRED',
12
+ TEXT: 'Problem logging in',
13
+ STATUS_CODE: '403 Forbidden',
14
+ },
15
+ ],
16
+ WARNING: [],
17
+ MESSAGE_TYPE: 'EVENT_LOGIN_AUTH_NACK',
18
+ SOURCE_REF: 'ref',
19
+ };
20
+ const eventAck = {
21
+ MESSAGE_TYPE: 'EVENT_ACK',
22
+ SOURCE_REF: 'ack-ref',
23
+ };
24
+ Suite('unwraps DTO from FetchMachineOutput', () => {
25
+ const dto = unwrapAuthDto({ data: mfaNack, response: { ok: false } });
26
+ assert.is(dto.MESSAGE_TYPE, 'EVENT_LOGIN_AUTH_NACK');
27
+ });
28
+ Suite('unwraps DTO from APIError', () => {
29
+ const dto = unwrapAuthDto(new APIError(StatusCodes.FORBIDDEN, mfaNack));
30
+ assert.is(dto.MESSAGE_TYPE, 'EVENT_LOGIN_AUTH_NACK');
31
+ });
32
+ Suite('treats HTTP 403 MFA NACK as auth nack on error.platform', () => {
33
+ assert.ok(isAuthNackEvent({
34
+ type: 'error.platform.loginFetcher',
35
+ data: new APIError(StatusCodes.FORBIDDEN, mfaNack),
36
+ }));
37
+ });
38
+ Suite('treats HTTP 403 MFA NACK as auth nack on done.invoke wrapping APIError', () => {
39
+ assert.ok(isAuthNackEvent({
40
+ type: 'done.invoke.loginFetcher',
41
+ output: new APIError(StatusCodes.FORBIDDEN, mfaNack),
42
+ }));
43
+ });
44
+ Suite('does not treat EVENT_ACK as nack', () => {
45
+ assert.not.ok(isAuthNackEvent({
46
+ type: 'done.invoke.resetPasswordFetcher',
47
+ output: { data: eventAck, response: { ok: true } },
48
+ }));
49
+ assert.is(authDtoFromMachineEvent({
50
+ type: 'done.invoke.resetPasswordFetcher',
51
+ output: { data: eventAck, response: { ok: true } },
52
+ }).MESSAGE_TYPE, 'EVENT_ACK');
53
+ });
54
+ Suite('unwraps DTO from xstate error payload on error field', () => {
55
+ assert.ok(isAuthNackEvent({
56
+ type: 'xstate.error.actor.0',
57
+ error: new APIError(StatusCodes.FORBIDDEN, mfaNack),
58
+ }));
59
+ });
60
+ Suite('does not treat HTTP 403 MFA NACK as a generic fetch failure', () => {
61
+ assert.not.ok(isFetchFailureOutput({
62
+ type: 'done.invoke.loginFetcher',
63
+ output: {
64
+ data: mfaNack,
65
+ error: new APIError(StatusCodes.FORBIDDEN, mfaNack),
66
+ },
67
+ }));
68
+ });
69
+ Suite('treats network/API failure without NACK as fetch failure', () => {
70
+ assert.ok(isFetchFailureOutput({
71
+ type: 'done.invoke.loginFetcher',
72
+ output: {
73
+ data: undefined,
74
+ error: new APIError(StatusCodes.INTERNAL_SERVER_ERROR),
75
+ },
76
+ }));
77
+ });
78
+ Suite('persistCredentials does not return the storage Promise', () => __awaiter(void 0, void 0, void 0, function* () {
79
+ let stored;
80
+ const result = persistCredentials((data) => new Promise((resolve) => {
81
+ stored = data;
82
+ resolve(true);
83
+ }), { id: 'jane', name: 'jane', password: 'x' });
84
+ assert.is(result, undefined);
85
+ yield Promise.resolve();
86
+ assert.is(stored === null || stored === void 0 ? void 0 : stored.id, 'jane');
87
+ }));
88
+ Suite.run();
@@ -12,6 +12,7 @@ import { clearResetIdentity } from '../routes/reset-password/reset-identity';
12
12
  import { AuthRouting } from '../routes/routing';
13
13
  import { logger } from '../utils';
14
14
  import { clearAuthErrorState, setError } from './actions';
15
+ import { authDtoFromMachineEvent, isAuthNackEvent as eventHasAuthNack, isFetchFailureOutput, persistCredentials, } from './dto';
15
16
  import { defaultAuthMachineContext, isLoginParams, isQueryParams } from './types';
16
17
  /**
17
18
  * Default AuthMachine.
@@ -127,7 +128,17 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
127
128
  invoke: {
128
129
  id: 'loginDetailsFetcher',
129
130
  src: fetchMachine.machine,
130
- onDone: this.dtoTransition(),
131
+ onDone: [
132
+ {
133
+ guard: 'isUnauthorizedError',
134
+ target: 'loggedOut',
135
+ },
136
+ {
137
+ guard: 'isFetchFailureOutput',
138
+ target: 'error.silentLogin',
139
+ },
140
+ this.dtoTransition(),
141
+ ],
131
142
  onError: [
132
143
  {
133
144
  guard: 'isUnauthorizedError',
@@ -151,8 +162,23 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
151
162
  invoke: {
152
163
  id: 'loginFetcher',
153
164
  src: fetchMachine.machine,
154
- onDone: this.dtoTransition(),
155
- onError: 'error.login',
165
+ onDone: [
166
+ {
167
+ guard: 'isFetchFailureOutput',
168
+ target: 'error.login',
169
+ },
170
+ this.dtoTransition(),
171
+ ],
172
+ onError: [
173
+ {
174
+ guard: 'isAuthNackEvent',
175
+ actions: ['setDTO'],
176
+ target: 'mapEntity',
177
+ },
178
+ {
179
+ target: 'error.login',
180
+ },
181
+ ],
156
182
  },
157
183
  entry: [
158
184
  sendTo('loginFetcher', ({ context }) => {
@@ -210,7 +236,13 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
210
236
  invoke: {
211
237
  id: 'logoutFetcher',
212
238
  src: fetchMachine.machine,
213
- onDone: this.dtoTransition(),
239
+ onDone: [
240
+ {
241
+ guard: 'isFetchFailureOutput',
242
+ target: 'error.logout',
243
+ },
244
+ this.dtoTransition(),
245
+ ],
214
246
  onError: 'error.logout',
215
247
  },
216
248
  entry: [
@@ -246,6 +278,10 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
246
278
  guard: 'is200NackDTO',
247
279
  target: 'error.forgotPassword',
248
280
  },
281
+ {
282
+ guard: 'isFetchFailureOutput',
283
+ target: 'error.forgotPassword',
284
+ },
249
285
  {
250
286
  target: 'feedback.forgotPassword',
251
287
  },
@@ -274,11 +310,15 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
274
310
  guard: 'is200NackDTO',
275
311
  target: 'error.changePassword',
276
312
  },
313
+ {
314
+ guard: 'isFetchFailureOutput',
315
+ target: 'error.changePassword',
316
+ },
277
317
  {
278
318
  actions: [
279
319
  ({ context }) => {
280
320
  const params = context.params;
281
- this.cm.storeCredentials({
321
+ persistCredentials(this.cm.storeCredentials.bind(this.cm), {
282
322
  id: params.username,
283
323
  name: params.username,
284
324
  password: params.newPassword,
@@ -312,11 +352,15 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
312
352
  guard: 'is200NackDTO',
313
353
  target: 'error.resetPassword',
314
354
  },
355
+ {
356
+ guard: 'isFetchFailureOutput',
357
+ target: 'error.resetPassword',
358
+ },
315
359
  {
316
360
  actions: [
317
361
  ({ context }) => {
318
362
  const params = context.params;
319
- this.cm.storeCredentials({
363
+ persistCredentials(this.cm.storeCredentials.bind(this.cm), {
320
364
  id: params.username,
321
365
  name: params.username,
322
366
  password: params.newPassword,
@@ -469,17 +513,12 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
469
513
  ],
470
514
  },
471
515
  /**
472
- * Feedback states. These are transient and revert back to idle after a short delay.
473
- * These can help improve UX in when the backend nack text is lacking clarity, as with incorrect credentials.
516
+ * Feedback states. Success paths auto-return after feedbackDelay.
517
+ * Error paths stay put so the user can retry immediately (login is handled here).
474
518
  */
475
519
  feedback: {
476
520
  initial: 'none',
477
- on: {
478
- dismiss: {
479
- actions: ['resetContext'],
480
- target: '#authMachine.idle',
481
- },
482
- },
521
+ on: this.onIdleEvents(),
483
522
  states: {
484
523
  none: {
485
524
  tags: ['feedback', 'none'],
@@ -522,17 +561,6 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
522
561
  meta: {
523
562
  content: 'MESSAGE_INCORRECT_CREDENTIALS',
524
563
  },
525
- after: {
526
- feedbackDelay: [
527
- {
528
- guard: 'isMfaLoginParams',
529
- target: '#authMachine.awaitingMfa',
530
- },
531
- {
532
- target: '#authMachine.idle',
533
- },
534
- ],
535
- },
536
564
  },
537
565
  mfaRequired: {
538
566
  tags: ['feedback', 'mfaRequired'],
@@ -607,9 +635,10 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
607
635
  params: ({ context }) => this.convertQueryParamsToLoginParams(context.params),
608
636
  }),
609
637
  setDTO: assign(({ event }) => {
610
- if (isDoneInvokeEvent(event)) {
638
+ const dto = authDtoFromMachineEvent(event);
639
+ if (dto) {
611
640
  return {
612
- dto: event.output.data,
641
+ dto,
613
642
  };
614
643
  }
615
644
  }),
@@ -657,7 +686,7 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
657
686
  password: loginParams.password,
658
687
  };
659
688
  if (this.cm.validateUserCredentialData(data, true)) {
660
- this.cm.storeCredentials(data);
689
+ persistCredentials(this.cm.storeCredentials.bind(this.cm), data);
661
690
  }
662
691
  },
663
692
  postLoginRedirect: this.config.postLoginRedirect,
@@ -678,7 +707,16 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
678
707
  hasSSOToken: ({ context }) => isQueryParams(context.params) && context.params.SSO_TOKEN !== undefined,
679
708
  hasMFACode: ({ context }) => isQueryParams(context.params) && context.params.MFA_CODE !== undefined,
680
709
  hasWindowOpener: () => window.opener,
681
- isUnauthorizedError: ({ event }) => isErrorEvent(event) ? isUnauthorizedError(event.data) : false,
710
+ isUnauthorizedError: ({ event }) => {
711
+ if (isErrorEvent(event)) {
712
+ return isUnauthorizedError(event.data);
713
+ }
714
+ if (isDoneInvokeEvent(event)) {
715
+ const output = event.output;
716
+ return (output === null || output === void 0 ? void 0 : output.error) ? isUnauthorizedError(output.error) : false;
717
+ }
718
+ return false;
719
+ },
682
720
  isAuthenticated: ({ context }) => { var _a; return (_a = context.user) === null || _a === void 0 ? void 0 : _a.isAuthenticated; },
683
721
  isBanned: ({ context }) => { var _a; return (_a = context.user) === null || _a === void 0 ? void 0 : _a.isBanned(); },
684
722
  isLoginAckEntity: ({ event }) => isDoneInvokeEvent(event) ? isLoginAckEntity(event.output) : false,
@@ -703,12 +741,9 @@ let DefaultAuthMachine = class DefaultAuthMachine extends AbstractMachine {
703
741
  * Required until strict http status codes are enabled on the backend by default.
704
742
  * Treats EVENT_NACK / ERROR payloads as failure regardless of HTTP status.
705
743
  */
706
- is200NackDTO: ({ event }) => {
707
- var _a;
708
- return isDoneInvokeEvent(event)
709
- ? isFailedAuthDTO((_a = event.output) === null || _a === void 0 ? void 0 : _a.data)
710
- : false;
711
- },
744
+ is200NackDTO: ({ event }) => isFailedAuthDTO(authDtoFromMachineEvent(event)),
745
+ isAuthNackEvent: ({ event }) => eventHasAuthNack(event),
746
+ isFetchFailureOutput: ({ event }) => isFetchFailureOutput(event),
712
747
  },
713
748
  delays: {
714
749
  feedbackDelay: this.config.feedbackDelay,
@@ -57,7 +57,21 @@ export class BaseRoute extends ConfigHostElement {
57
57
  var _a, _b, _c, _d, _e;
58
58
  super.connectedCallback();
59
59
  (_c = (_b = (_a = this.store) === null || _a === void 0 ? void 0 : _a.formEntry) === null || _b === void 0 ? void 0 : _b.errors) === null || _c === void 0 ? void 0 : _c.clear();
60
- (_e = (_d = this.store) === null || _d === void 0 ? void 0 : _d.authMachine) === null || _e === void 0 ? void 0 : _e.send({ type: 'dismiss' });
60
+ if (this.shouldDismissOnConnect) {
61
+ (_e = (_d = this.store) === null || _d === void 0 ? void 0 : _d.authMachine) === null || _e === void 0 ? void 0 : _e.send({ type: 'dismiss' });
62
+ }
63
+ }
64
+ /**
65
+ * Skip dismiss while a request or MFA challenge is in flight so route
66
+ * (re)connect does not cancel the current auth step.
67
+ */
68
+ get shouldDismissOnConnect() {
69
+ var _a;
70
+ const machine = (_a = this.store) === null || _a === void 0 ? void 0 : _a.authMachine;
71
+ if (!machine) {
72
+ return false;
73
+ }
74
+ return !machine.hasTag('pending') && !machine.hasTag('awaitingMfa');
61
75
  }
62
76
  toLocalisedText(text) {
63
77
  return this.i18next.t(`${defaultAuthConfig.name}:${text}`, { lng: this.i18next.language });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/foundation-auth",
3
3
  "description": "Genesis Foundation Auth",
4
- "version": "15.14.2-FUI-2603.1",
4
+ "version": "15.14.2-FUI-2603.2",
5
5
  "license": "SEE LICENSE IN license.txt",
6
6
  "main": "dist/esm/index.js",
7
7
  "types": "dist/foundation-auth.d.ts",
@@ -134,25 +134,25 @@
134
134
  }
135
135
  },
136
136
  "devDependencies": {
137
- "@genesislcap/foundation-testing": "15.14.2-FUI-2603.1",
138
- "@genesislcap/genx": "15.14.2-FUI-2603.1",
139
- "@genesislcap/rollup-builder": "15.14.2-FUI-2603.1",
140
- "@genesislcap/ts-builder": "15.14.2-FUI-2603.1",
141
- "@genesislcap/uvu-playwright-builder": "15.14.2-FUI-2603.1",
142
- "@genesislcap/vite-builder": "15.14.2-FUI-2603.1",
143
- "@genesislcap/webpack-builder": "15.14.2-FUI-2603.1"
137
+ "@genesislcap/foundation-testing": "15.14.2-FUI-2603.2",
138
+ "@genesislcap/genx": "15.14.2-FUI-2603.2",
139
+ "@genesislcap/rollup-builder": "15.14.2-FUI-2603.2",
140
+ "@genesislcap/ts-builder": "15.14.2-FUI-2603.2",
141
+ "@genesislcap/uvu-playwright-builder": "15.14.2-FUI-2603.2",
142
+ "@genesislcap/vite-builder": "15.14.2-FUI-2603.2",
143
+ "@genesislcap/webpack-builder": "15.14.2-FUI-2603.2"
144
144
  },
145
145
  "dependencies": {
146
- "@genesislcap/foundation-comms": "15.14.2-FUI-2603.1",
147
- "@genesislcap/foundation-events": "15.14.2-FUI-2603.1",
148
- "@genesislcap/foundation-i18n": "15.14.2-FUI-2603.1",
149
- "@genesislcap/foundation-logger": "15.14.2-FUI-2603.1",
150
- "@genesislcap/foundation-state-machine": "15.14.2-FUI-2603.1",
151
- "@genesislcap/foundation-store": "15.14.2-FUI-2603.1",
152
- "@genesislcap/foundation-ui": "15.14.2-FUI-2603.1",
153
- "@genesislcap/foundation-user": "15.14.2-FUI-2603.1",
154
- "@genesislcap/foundation-utils": "15.14.2-FUI-2603.1",
155
- "@genesislcap/foundation-zero": "15.14.2-FUI-2603.1",
146
+ "@genesislcap/foundation-comms": "15.14.2-FUI-2603.2",
147
+ "@genesislcap/foundation-events": "15.14.2-FUI-2603.2",
148
+ "@genesislcap/foundation-i18n": "15.14.2-FUI-2603.2",
149
+ "@genesislcap/foundation-logger": "15.14.2-FUI-2603.2",
150
+ "@genesislcap/foundation-state-machine": "15.14.2-FUI-2603.2",
151
+ "@genesislcap/foundation-store": "15.14.2-FUI-2603.2",
152
+ "@genesislcap/foundation-ui": "15.14.2-FUI-2603.2",
153
+ "@genesislcap/foundation-user": "15.14.2-FUI-2603.2",
154
+ "@genesislcap/foundation-utils": "15.14.2-FUI-2603.2",
155
+ "@genesislcap/foundation-zero": "15.14.2-FUI-2603.2",
156
156
  "@microsoft/fast-components": "2.30.6",
157
157
  "@microsoft/fast-element": "1.14.0",
158
158
  "@microsoft/fast-foundation": "2.50.0",
@@ -173,5 +173,5 @@
173
173
  "access": "public"
174
174
  },
175
175
  "customElements": "dist/custom-elements.json",
176
- "gitHead": "cb4bc1f9c157dc1ea3200aaa35eadf8971fe683b"
176
+ "gitHead": "470d546163b507cfe4bc8335cdb5955c40aeb58a"
177
177
  }