@genesislcap/foundation-auth 15.14.2-FUI-2603.2 → 15.14.2-FUI-2603.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dts/machine/actions.d.ts +0 -13
- package/dist/dts/machine/actions.d.ts.map +1 -1
- package/dist/dts/machine/errors.d.ts +0 -5
- package/dist/dts/machine/errors.d.ts.map +1 -1
- package/dist/dts/machine/guards.d.ts +1 -2
- package/dist/dts/machine/guards.d.ts.map +1 -1
- package/dist/dts/machine/machine.d.ts +0 -4
- package/dist/dts/machine/machine.d.ts.map +1 -1
- package/dist/dts/machine/types.d.ts +0 -2
- package/dist/dts/machine/types.d.ts.map +1 -1
- package/dist/dts/mapper/utils.d.ts +0 -11
- package/dist/dts/mapper/utils.d.ts.map +1 -1
- package/dist/dts/routes/base.d.ts +0 -6
- package/dist/dts/routes/base.d.ts.map +1 -1
- package/dist/dts/routes/forgot-password/forgot-password.d.ts.map +1 -1
- package/dist/dts/routes/reset-password/reset-password.d.ts +0 -2
- package/dist/dts/routes/reset-password/reset-password.d.ts.map +1 -1
- package/dist/dts/routes/reset-password/reset-password.template.d.ts.map +1 -1
- package/dist/esm/machine/actions.js +14 -16
- package/dist/esm/machine/errors.js +8 -39
- package/dist/esm/machine/guards.js +5 -13
- package/dist/esm/machine/machine.js +45 -90
- package/dist/esm/mapper/utils.js +0 -16
- package/dist/esm/routes/base.js +0 -20
- package/dist/esm/routes/forgot-password/forgot-password.js +0 -5
- package/dist/esm/routes/reset-password/reset-password.js +13 -19
- package/dist/esm/routes/reset-password/reset-password.template.js +2 -6
- package/dist/esm/translation.json +1 -2
- package/dist/foundation-auth.api.json +2 -175
- package/dist/foundation-auth.d.ts +1 -35
- package/package.json +19 -19
- package/dist/dts/machine/actions.test.d.ts +0 -2
- package/dist/dts/machine/actions.test.d.ts.map +0 -1
- package/dist/dts/machine/dto.d.ts +0 -34
- package/dist/dts/machine/dto.d.ts.map +0 -1
- package/dist/dts/machine/dto.test.d.ts +0 -2
- package/dist/dts/machine/dto.test.d.ts.map +0 -1
- package/dist/dts/machine/guards.test.d.ts +0 -2
- package/dist/dts/machine/guards.test.d.ts.map +0 -1
- package/dist/dts/mapper/utils.test.d.ts +0 -2
- package/dist/dts/mapper/utils.test.d.ts.map +0 -1
- package/dist/dts/routes/reset-password/reset-identity.d.ts +0 -38
- package/dist/dts/routes/reset-password/reset-identity.d.ts.map +0 -1
- package/dist/dts/routes/reset-password/reset-identity.test.d.ts +0 -2
- package/dist/dts/routes/reset-password/reset-identity.test.d.ts.map +0 -1
- package/dist/esm/machine/actions.test.js +0 -21
- package/dist/esm/machine/dto.js +0 -76
- package/dist/esm/machine/dto.test.js +0 -88
- package/dist/esm/machine/guards.test.js +0 -53
- package/dist/esm/mapper/utils.test.js +0 -56
- package/dist/esm/routes/reset-password/reset-identity.js +0 -99
- package/dist/esm/routes/reset-password/reset-identity.test.js +0 -55
package/dist/esm/machine/dto.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
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();
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
2
|
-
import { is200Nack } from './guards';
|
|
3
|
-
import { isResetPasswordParams } from './types';
|
|
4
|
-
const Suite = createLogicSuite('auth machine password reset guards');
|
|
5
|
-
const nackDto = {
|
|
6
|
-
MESSAGE_TYPE: 'EVENT_NACK',
|
|
7
|
-
SOURCE_REF: 'ref',
|
|
8
|
-
ERROR: [
|
|
9
|
-
{
|
|
10
|
-
'@type': 'StandardError',
|
|
11
|
-
CODE: 'INTERNAL_ERROR',
|
|
12
|
-
TEXT: 'Password validation failed',
|
|
13
|
-
STATUS_CODE: '500 Internal Server Error',
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
WARNING: [],
|
|
17
|
-
};
|
|
18
|
-
Suite('is200Nack is true for FetchMachineOutput wrapping EVENT_NACK', () => {
|
|
19
|
-
assert.ok(is200Nack({
|
|
20
|
-
type: 'done.invoke.resetPasswordFetcher',
|
|
21
|
-
output: { data: nackDto, response: { ok: true } },
|
|
22
|
-
}));
|
|
23
|
-
});
|
|
24
|
-
Suite('is200Nack is true for EVENT_NACK even when HTTP is not ok', () => {
|
|
25
|
-
assert.ok(is200Nack({
|
|
26
|
-
type: 'done.invoke.resetPasswordFetcher',
|
|
27
|
-
output: { data: nackDto, response: { ok: false } },
|
|
28
|
-
}));
|
|
29
|
-
});
|
|
30
|
-
Suite('is200Nack is false for EVENT_ACK without errors', () => {
|
|
31
|
-
assert.not.ok(is200Nack({
|
|
32
|
-
type: 'done.invoke.resetPasswordFetcher',
|
|
33
|
-
output: { data: { MESSAGE_TYPE: 'EVENT_ACK', SOURCE_REF: 'ref' }, response: { ok: true } },
|
|
34
|
-
}));
|
|
35
|
-
});
|
|
36
|
-
Suite('isResetPasswordParams requires username, token and new password', () => {
|
|
37
|
-
assert.ok(isResetPasswordParams({
|
|
38
|
-
username: 'JaneDee',
|
|
39
|
-
resetToken: 'token',
|
|
40
|
-
newPassword: 'Password11*',
|
|
41
|
-
}));
|
|
42
|
-
assert.not.ok(isResetPasswordParams({
|
|
43
|
-
username: '',
|
|
44
|
-
resetToken: 'token',
|
|
45
|
-
newPassword: 'Password11*',
|
|
46
|
-
}));
|
|
47
|
-
assert.not.ok(isResetPasswordParams({
|
|
48
|
-
username: 'JaneDee',
|
|
49
|
-
resetToken: '',
|
|
50
|
-
newPassword: 'Password11*',
|
|
51
|
-
}));
|
|
52
|
-
});
|
|
53
|
-
Suite.run();
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { APIError } from '@genesislcap/foundation-state-machine';
|
|
2
|
-
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
3
|
-
import { StatusCodes } from 'http-status-codes';
|
|
4
|
-
import { nackErrorFromUnknown } from '../machine/errors';
|
|
5
|
-
import { hasDTOErrors, isFailedAuthDTO, isNackDTO } from './utils';
|
|
6
|
-
const Suite = createLogicSuite('password-reset response handling');
|
|
7
|
-
const passwordValidationNack = {
|
|
8
|
-
WARNING: [],
|
|
9
|
-
ERROR: [
|
|
10
|
-
{
|
|
11
|
-
'@type': 'StandardError',
|
|
12
|
-
CODE: 'INTERNAL_ERROR',
|
|
13
|
-
TEXT: 'Password validation failed Password must be 8 or more characters in length.\nPassword must contain 1 or more special characters.',
|
|
14
|
-
STATUS_CODE: '500 Internal Server Error',
|
|
15
|
-
},
|
|
16
|
-
],
|
|
17
|
-
MESSAGE_TYPE: 'EVENT_NACK',
|
|
18
|
-
SOURCE_REF: '17605761-55cb-4b5a-a1ec-7235d3cae393',
|
|
19
|
-
};
|
|
20
|
-
const eventAck = {
|
|
21
|
-
MESSAGE_TYPE: 'EVENT_ACK',
|
|
22
|
-
SOURCE_REF: 'ack-ref',
|
|
23
|
-
};
|
|
24
|
-
Suite('detects EVENT_NACK as failure', () => {
|
|
25
|
-
assert.ok(isNackDTO(passwordValidationNack));
|
|
26
|
-
assert.ok(isFailedAuthDTO(passwordValidationNack));
|
|
27
|
-
assert.ok(hasDTOErrors(passwordValidationNack));
|
|
28
|
-
});
|
|
29
|
-
Suite('detects ERROR payload as failure even without NACK suffix', () => {
|
|
30
|
-
const ackWithErrors = Object.assign(Object.assign({}, eventAck), { ERROR: passwordValidationNack.ERROR });
|
|
31
|
-
assert.not.ok(isNackDTO(ackWithErrors));
|
|
32
|
-
assert.ok(hasDTOErrors(ackWithErrors));
|
|
33
|
-
assert.ok(isFailedAuthDTO(ackWithErrors));
|
|
34
|
-
});
|
|
35
|
-
Suite('treats EVENT_ACK without ERROR as success', () => {
|
|
36
|
-
assert.not.ok(isNackDTO(eventAck));
|
|
37
|
-
assert.not.ok(hasDTOErrors(eventAck));
|
|
38
|
-
assert.not.ok(isFailedAuthDTO(eventAck));
|
|
39
|
-
});
|
|
40
|
-
Suite('extracts strong-password error text from EVENT_NACK', () => {
|
|
41
|
-
const error = nackErrorFromUnknown(passwordValidationNack);
|
|
42
|
-
assert.ok(error);
|
|
43
|
-
assert.ok(error.message.includes('Password validation failed'));
|
|
44
|
-
assert.is(error.status, StatusCodes.INTERNAL_SERVER_ERROR);
|
|
45
|
-
});
|
|
46
|
-
Suite('extracts NACK from FetchMachineOutput and APIError wrappers', () => {
|
|
47
|
-
const fromFetch = nackErrorFromUnknown({ data: passwordValidationNack, response: { ok: true } });
|
|
48
|
-
assert.ok(fromFetch === null || fromFetch === void 0 ? void 0 : fromFetch.message.includes('Password validation failed'));
|
|
49
|
-
const fromApiError = nackErrorFromUnknown(new APIError(StatusCodes.INTERNAL_SERVER_ERROR, passwordValidationNack));
|
|
50
|
-
assert.ok(fromApiError === null || fromApiError === void 0 ? void 0 : fromApiError.message.includes('Password validation failed'));
|
|
51
|
-
});
|
|
52
|
-
Suite('does not treat EVENT_ACK as an error', () => {
|
|
53
|
-
assert.is(nackErrorFromUnknown(eventAck), null);
|
|
54
|
-
assert.is(nackErrorFromUnknown({ data: eventAck }), null);
|
|
55
|
-
});
|
|
56
|
-
Suite.run();
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Identity captured during forgot-password so the token reset screen can
|
|
3
|
-
* submit USER_NAME without asking the user to type it again.
|
|
4
|
-
*/
|
|
5
|
-
export const RESET_IDENTITY_STORAGE_KEY = 'foundation-auth:password-reset-identity';
|
|
6
|
-
const getStorage = (storage) => {
|
|
7
|
-
if (storage) {
|
|
8
|
-
return storage;
|
|
9
|
-
}
|
|
10
|
-
try {
|
|
11
|
-
return globalThis.localStorage;
|
|
12
|
-
}
|
|
13
|
-
catch (_a) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* @public
|
|
19
|
-
*/
|
|
20
|
-
export function persistResetIdentity(identity, storage) {
|
|
21
|
-
var _a, _b;
|
|
22
|
-
if (!((_a = identity === null || identity === void 0 ? void 0 : identity.username) === null || _a === void 0 ? void 0 : _a.trim())) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const target = getStorage(storage);
|
|
26
|
-
if (!target) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
try {
|
|
30
|
-
target.setItem(RESET_IDENTITY_STORAGE_KEY, JSON.stringify({
|
|
31
|
-
username: identity.username.trim(),
|
|
32
|
-
organisation: ((_b = identity.organisation) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
catch (_c) {
|
|
36
|
-
// Storage may be unavailable (private mode, SSR).
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* @public
|
|
41
|
-
*/
|
|
42
|
-
export function readResetIdentity(storage) {
|
|
43
|
-
var _a, _b;
|
|
44
|
-
const target = getStorage(storage);
|
|
45
|
-
if (!target) {
|
|
46
|
-
return undefined;
|
|
47
|
-
}
|
|
48
|
-
try {
|
|
49
|
-
const raw = target.getItem(RESET_IDENTITY_STORAGE_KEY);
|
|
50
|
-
if (!raw) {
|
|
51
|
-
return undefined;
|
|
52
|
-
}
|
|
53
|
-
const parsed = JSON.parse(raw);
|
|
54
|
-
if ((_a = parsed === null || parsed === void 0 ? void 0 : parsed.username) === null || _a === void 0 ? void 0 : _a.trim()) {
|
|
55
|
-
return {
|
|
56
|
-
username: parsed.username.trim(),
|
|
57
|
-
organisation: ((_b = parsed.organisation) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
catch (_c) {
|
|
62
|
-
// Ignore malformed payloads.
|
|
63
|
-
}
|
|
64
|
-
return undefined;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* @public
|
|
68
|
-
*/
|
|
69
|
-
export function clearResetIdentity(storage) {
|
|
70
|
-
const target = getStorage(storage);
|
|
71
|
-
if (!target) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
try {
|
|
75
|
-
target.removeItem(RESET_IDENTITY_STORAGE_KEY);
|
|
76
|
-
}
|
|
77
|
-
catch (_a) {
|
|
78
|
-
// Storage may be unavailable.
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* @public
|
|
83
|
-
*/
|
|
84
|
-
export function resolveResetUsername(queryParams = {}, stored) {
|
|
85
|
-
return (queryParams.username ||
|
|
86
|
-
queryParams.user ||
|
|
87
|
-
queryParams.USER_NAME ||
|
|
88
|
-
(stored === null || stored === void 0 ? void 0 : stored.username) ||
|
|
89
|
-
'').trim();
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Username is required by EVENT_PASSWORD_RESET_ACTION. Hide it only when a
|
|
93
|
-
* reset token is present and the username is already known.
|
|
94
|
-
*
|
|
95
|
-
* @public
|
|
96
|
-
*/
|
|
97
|
-
export function shouldShowIdentityFields(passwordResetToken, username) {
|
|
98
|
-
return !passwordResetToken || !username.trim();
|
|
99
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
2
|
-
import { clearResetIdentity, persistResetIdentity, readResetIdentity, resolveResetUsername, RESET_IDENTITY_STORAGE_KEY, shouldShowIdentityFields, } from './reset-identity';
|
|
3
|
-
const Suite = createLogicSuite('reset-identity');
|
|
4
|
-
const createMemoryStorage = () => {
|
|
5
|
-
const map = new Map();
|
|
6
|
-
return {
|
|
7
|
-
get length() {
|
|
8
|
-
return map.size;
|
|
9
|
-
},
|
|
10
|
-
clear: () => map.clear(),
|
|
11
|
-
getItem: (key) => { var _a; return (_a = map.get(key)) !== null && _a !== void 0 ? _a : null; },
|
|
12
|
-
key: (index) => { var _a; return (_a = [...map.keys()][index]) !== null && _a !== void 0 ? _a : null; },
|
|
13
|
-
removeItem: (key) => {
|
|
14
|
-
map.delete(key);
|
|
15
|
-
},
|
|
16
|
-
setItem: (key, value) => {
|
|
17
|
-
map.set(key, value);
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
Suite('hides username when token is present and username is known', () => {
|
|
22
|
-
assert.not.ok(shouldShowIdentityFields('reset-token', 'JaneDee'));
|
|
23
|
-
});
|
|
24
|
-
Suite('shows username when token is present but username is missing', () => {
|
|
25
|
-
assert.ok(shouldShowIdentityFields('reset-token', ''));
|
|
26
|
-
assert.ok(shouldShowIdentityFields('reset-token', ' '));
|
|
27
|
-
});
|
|
28
|
-
Suite('shows username when token is absent', () => {
|
|
29
|
-
assert.ok(shouldShowIdentityFields('', 'JaneDee'));
|
|
30
|
-
assert.ok(shouldShowIdentityFields(undefined, ''));
|
|
31
|
-
});
|
|
32
|
-
Suite('resolves username from query params before stored identity', () => {
|
|
33
|
-
const stored = { username: 'stored-user' };
|
|
34
|
-
assert.is(resolveResetUsername({ username: 'query-user' }, stored), 'query-user');
|
|
35
|
-
assert.is(resolveResetUsername({ user: 'alias-user' }, stored), 'alias-user');
|
|
36
|
-
assert.is(resolveResetUsername({ USER_NAME: 'legacy-user' }, stored), 'legacy-user');
|
|
37
|
-
});
|
|
38
|
-
Suite('resolves username from stored identity when query has no username', () => {
|
|
39
|
-
assert.is(resolveResetUsername({ password: 'token' }, { username: 'stored-user' }), 'stored-user');
|
|
40
|
-
assert.is(resolveResetUsername({ password: 'token' }), '');
|
|
41
|
-
});
|
|
42
|
-
Suite('persists, reads and clears reset identity', () => {
|
|
43
|
-
const storage = createMemoryStorage();
|
|
44
|
-
persistResetIdentity({ username: ' JaneDee ', organisation: ' FBN ' }, storage);
|
|
45
|
-
assert.equal(readResetIdentity(storage), { username: 'JaneDee', organisation: 'FBN' });
|
|
46
|
-
assert.ok(storage.getItem(RESET_IDENTITY_STORAGE_KEY));
|
|
47
|
-
clearResetIdentity(storage);
|
|
48
|
-
assert.is(readResetIdentity(storage), undefined);
|
|
49
|
-
});
|
|
50
|
-
Suite('does not persist empty username', () => {
|
|
51
|
-
const storage = createMemoryStorage();
|
|
52
|
-
persistResetIdentity({ username: ' ' }, storage);
|
|
53
|
-
assert.is(readResetIdentity(storage), undefined);
|
|
54
|
-
});
|
|
55
|
-
Suite.run();
|