@frontegg/redux-store 7.103.0 → 7.104.0-alpha.1
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/auth/ForgotPasswordState/actions.d.ts +9 -1
- package/auth/ForgotPasswordState/actions.js +66 -2
- package/auth/ForgotPasswordState/interfaces.d.ts +2 -0
- package/auth/ForgotPasswordState/state.js +2 -1
- package/auth/LoginState/actions/index.js +1 -0
- package/auth/LoginState/interfaces.d.ts +1 -0
- package/index.js +1 -1
- package/mocks/auth-mocks/forgotPasswordActions.mocks.d.ts +9 -1
- package/mocks/auth-mocks/forgotPasswordActions.mocks.js +14 -0
- package/node/auth/ForgotPasswordState/actions.js +65 -1
- package/node/auth/ForgotPasswordState/state.js +2 -1
- package/node/auth/LoginState/actions/index.js +1 -0
- package/node/index.js +1 -1
- package/node/mocks/auth-mocks/forgotPasswordActions.mocks.js +14 -0
- package/package.json +2 -2
|
@@ -7,7 +7,15 @@ declare const _default: (store: FronteggState, api: RestApi, sharedActions: Shar
|
|
|
7
7
|
resetForgotPasswordState: () => void;
|
|
8
8
|
forgotPassword: (payload: IForgotPasswordPayload) => Promise<void>;
|
|
9
9
|
resetPassword: (payload: IResetPasswordPayload) => Promise<void>;
|
|
10
|
-
loadPasswordConfig: (payload?: IGetUserPasswordConfig
|
|
10
|
+
loadPasswordConfig: (payload?: IGetUserPasswordConfig & {
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
}) => Promise<void>;
|
|
13
|
+
validateResetPasswordToken: (payload: {
|
|
14
|
+
userId: string;
|
|
15
|
+
token: string;
|
|
16
|
+
skipValidation?: boolean;
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}) => Promise<void>;
|
|
11
19
|
determinePasswordRecoveryStrategy: (payload: IDeterminePasswordRecoveryStrategyPayload) => Promise<void>;
|
|
12
20
|
sendPasswordRecoveryEmail: () => Promise<void>;
|
|
13
21
|
sendPasswordRecoverySms: () => Promise<void>;
|
|
@@ -3,7 +3,7 @@ const _excluded = ["callback"];
|
|
|
3
3
|
import { PasswordRecoveryStrategyEnum } from '@frontegg/rest-api';
|
|
4
4
|
import { ForgotPasswordStep } from './interfaces';
|
|
5
5
|
import { initialState } from './state';
|
|
6
|
-
import { errorHandler, deepResetState } from '../../helpers';
|
|
6
|
+
import { errorHandler, deepResetState, isFronteggApiError } from '../../helpers';
|
|
7
7
|
import { FORGOT_PASSWORD_ERROR_KEYS } from './consts';
|
|
8
8
|
export default ((store, api, sharedActions) => {
|
|
9
9
|
const actions = sharedActions;
|
|
@@ -206,18 +206,81 @@ export default ((store, api, sharedActions) => {
|
|
|
206
206
|
loading: true
|
|
207
207
|
});
|
|
208
208
|
try {
|
|
209
|
-
|
|
209
|
+
var _payload$signal;
|
|
210
|
+
const passwordConfig = await api.auth.loadPasswordConfig(payload ? {
|
|
211
|
+
userId: payload.userId
|
|
212
|
+
} : undefined);
|
|
213
|
+
if (payload != null && (_payload$signal = payload.signal) != null && _payload$signal.aborted) return;
|
|
210
214
|
setForgotPasswordState({
|
|
211
215
|
loading: false,
|
|
212
216
|
passwordConfig
|
|
213
217
|
});
|
|
214
218
|
} catch (e) {
|
|
219
|
+
var _payload$signal2;
|
|
220
|
+
if (payload != null && (_payload$signal2 = payload.signal) != null && _payload$signal2.aborted) return;
|
|
215
221
|
setForgotPasswordState({
|
|
216
222
|
loading: false,
|
|
217
223
|
error: errorHandler(e)
|
|
218
224
|
});
|
|
219
225
|
}
|
|
220
226
|
};
|
|
227
|
+
const validateResetPasswordToken = async payload => {
|
|
228
|
+
if (payload.skipValidation) {
|
|
229
|
+
var _payload$signal3;
|
|
230
|
+
if (!((_payload$signal3 = payload.signal) != null && _payload$signal3.aborted)) {
|
|
231
|
+
setForgotPasswordState({
|
|
232
|
+
resetTokenValidationStatus: 'valid',
|
|
233
|
+
error: undefined
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
setForgotPasswordState({
|
|
239
|
+
resetTokenValidationStatus: 'pending',
|
|
240
|
+
error: undefined
|
|
241
|
+
});
|
|
242
|
+
try {
|
|
243
|
+
var _payload$signal4;
|
|
244
|
+
await api.auth.validateResetPasswordToken({
|
|
245
|
+
userId: payload.userId,
|
|
246
|
+
token: payload.token
|
|
247
|
+
});
|
|
248
|
+
if ((_payload$signal4 = payload.signal) != null && _payload$signal4.aborted) return;
|
|
249
|
+
setForgotPasswordState({
|
|
250
|
+
resetTokenValidationStatus: 'valid',
|
|
251
|
+
error: undefined
|
|
252
|
+
});
|
|
253
|
+
} catch (e) {
|
|
254
|
+
var _payload$signal5;
|
|
255
|
+
if ((_payload$signal5 = payload.signal) != null && _payload$signal5.aborted) return;
|
|
256
|
+
const handled = errorHandler(e);
|
|
257
|
+
if (isFronteggApiError(handled)) {
|
|
258
|
+
const status = handled.statusCode;
|
|
259
|
+
// Identity: 400 = bad request / missing input; 410 = expired or consumed. Both use the same link-expired screen (invalid).
|
|
260
|
+
// 403/422 included if the API or gateway uses them for invalid tokens.
|
|
261
|
+
const tokenInvalid = status === 400 || status === 403 || status === 410 || status === 422;
|
|
262
|
+
const degradeToLegacyFlow = status === 401 || status === 404 || status >= 500;
|
|
263
|
+
if (tokenInvalid) {
|
|
264
|
+
setForgotPasswordState({
|
|
265
|
+
resetTokenValidationStatus: 'invalid',
|
|
266
|
+
error: undefined
|
|
267
|
+
});
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (degradeToLegacyFlow) {
|
|
271
|
+
setForgotPasswordState({
|
|
272
|
+
resetTokenValidationStatus: 'valid',
|
|
273
|
+
error: undefined
|
|
274
|
+
});
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
setForgotPasswordState({
|
|
279
|
+
resetTokenValidationStatus: 'valid',
|
|
280
|
+
error: undefined
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
};
|
|
221
284
|
return {
|
|
222
285
|
loadPasswordRecoveryStrategies,
|
|
223
286
|
setForgotPasswordState,
|
|
@@ -225,6 +288,7 @@ export default ((store, api, sharedActions) => {
|
|
|
225
288
|
forgotPassword,
|
|
226
289
|
resetPassword,
|
|
227
290
|
loadPasswordConfig,
|
|
291
|
+
validateResetPasswordToken,
|
|
228
292
|
determinePasswordRecoveryStrategy,
|
|
229
293
|
sendPasswordRecoveryEmail,
|
|
230
294
|
sendPasswordRecoverySms,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EIdentifierType, IForgotPassword, IResetPassword, IPasswordRecoveryStrategy } from '@frontegg/rest-api';
|
|
2
2
|
import type { WithCallback } from '../../interfaces';
|
|
3
|
+
export type ResetTokenValidationStatus = 'idle' | 'pending' | 'valid' | 'invalid';
|
|
3
4
|
export declare enum ForgotPasswordStep {
|
|
4
5
|
'forgotPassword' = "forgotPassword",
|
|
5
6
|
'resetPasswordViaSms' = "resetPasswordViaSms",
|
|
@@ -26,6 +27,7 @@ export interface ForgotPasswordState {
|
|
|
26
27
|
token?: string;
|
|
27
28
|
error?: any;
|
|
28
29
|
activeStrategies?: IPasswordRecoveryStrategy[];
|
|
30
|
+
resetTokenValidationStatus: ResetTokenValidationStatus;
|
|
29
31
|
}
|
|
30
32
|
export interface IForgotPasswordPayload extends WithCallback<IForgotPassword> {
|
|
31
33
|
recaptchaToken?: string;
|
package/index.js
CHANGED
|
@@ -6,7 +6,15 @@ declare const _default: (store: FronteggState, api: RestApi, actions: SharedActi
|
|
|
6
6
|
resetForgotPasswordState: () => void;
|
|
7
7
|
forgotPassword: (payload: import("../..").IForgotPasswordPayload) => Promise<void>;
|
|
8
8
|
resetPassword: (payload: import("../..").IResetPasswordPayload) => Promise<void>;
|
|
9
|
-
loadPasswordConfig: (payload?: IGetUserPasswordConfig
|
|
9
|
+
loadPasswordConfig: (payload?: IGetUserPasswordConfig & {
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}) => Promise<void>;
|
|
12
|
+
validateResetPasswordToken: (payload: {
|
|
13
|
+
userId: string;
|
|
14
|
+
token: string;
|
|
15
|
+
skipValidation?: boolean;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
}) => Promise<void>;
|
|
10
18
|
determinePasswordRecoveryStrategy: (payload: import("../..").IDeterminePasswordRecoveryStrategyPayload) => Promise<void>;
|
|
11
19
|
sendPasswordRecoveryEmail: () => Promise<void>;
|
|
12
20
|
sendPasswordRecoverySms: () => Promise<void>;
|
|
@@ -26,5 +26,19 @@ export default ((store, api, actions) => {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
|
+
mockedActions.validateResetPasswordToken = async payload => {
|
|
30
|
+
if (payload.skipValidation) {
|
|
31
|
+
mockedActions.setForgotPasswordState({
|
|
32
|
+
resetTokenValidationStatus: 'valid'
|
|
33
|
+
});
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
mockedActions.setForgotPasswordState({
|
|
37
|
+
resetTokenValidationStatus: 'pending'
|
|
38
|
+
});
|
|
39
|
+
mockedActions.setForgotPasswordState({
|
|
40
|
+
resetTokenValidationStatus: 'valid'
|
|
41
|
+
});
|
|
42
|
+
};
|
|
29
43
|
return mockedActions;
|
|
30
44
|
});
|
|
@@ -213,18 +213,81 @@ var _default = (store, api, sharedActions) => {
|
|
|
213
213
|
loading: true
|
|
214
214
|
});
|
|
215
215
|
try {
|
|
216
|
-
|
|
216
|
+
var _payload$signal;
|
|
217
|
+
const passwordConfig = await api.auth.loadPasswordConfig(payload ? {
|
|
218
|
+
userId: payload.userId
|
|
219
|
+
} : undefined);
|
|
220
|
+
if (payload != null && (_payload$signal = payload.signal) != null && _payload$signal.aborted) return;
|
|
217
221
|
setForgotPasswordState({
|
|
218
222
|
loading: false,
|
|
219
223
|
passwordConfig
|
|
220
224
|
});
|
|
221
225
|
} catch (e) {
|
|
226
|
+
var _payload$signal2;
|
|
227
|
+
if (payload != null && (_payload$signal2 = payload.signal) != null && _payload$signal2.aborted) return;
|
|
222
228
|
setForgotPasswordState({
|
|
223
229
|
loading: false,
|
|
224
230
|
error: (0, _helpers.errorHandler)(e)
|
|
225
231
|
});
|
|
226
232
|
}
|
|
227
233
|
};
|
|
234
|
+
const validateResetPasswordToken = async payload => {
|
|
235
|
+
if (payload.skipValidation) {
|
|
236
|
+
var _payload$signal3;
|
|
237
|
+
if (!((_payload$signal3 = payload.signal) != null && _payload$signal3.aborted)) {
|
|
238
|
+
setForgotPasswordState({
|
|
239
|
+
resetTokenValidationStatus: 'valid',
|
|
240
|
+
error: undefined
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
setForgotPasswordState({
|
|
246
|
+
resetTokenValidationStatus: 'pending',
|
|
247
|
+
error: undefined
|
|
248
|
+
});
|
|
249
|
+
try {
|
|
250
|
+
var _payload$signal4;
|
|
251
|
+
await api.auth.validateResetPasswordToken({
|
|
252
|
+
userId: payload.userId,
|
|
253
|
+
token: payload.token
|
|
254
|
+
});
|
|
255
|
+
if ((_payload$signal4 = payload.signal) != null && _payload$signal4.aborted) return;
|
|
256
|
+
setForgotPasswordState({
|
|
257
|
+
resetTokenValidationStatus: 'valid',
|
|
258
|
+
error: undefined
|
|
259
|
+
});
|
|
260
|
+
} catch (e) {
|
|
261
|
+
var _payload$signal5;
|
|
262
|
+
if ((_payload$signal5 = payload.signal) != null && _payload$signal5.aborted) return;
|
|
263
|
+
const handled = (0, _helpers.errorHandler)(e);
|
|
264
|
+
if ((0, _helpers.isFronteggApiError)(handled)) {
|
|
265
|
+
const status = handled.statusCode;
|
|
266
|
+
// Identity: 400 = bad request / missing input; 410 = expired or consumed. Both use the same link-expired screen (invalid).
|
|
267
|
+
// 403/422 included if the API or gateway uses them for invalid tokens.
|
|
268
|
+
const tokenInvalid = status === 400 || status === 403 || status === 410 || status === 422;
|
|
269
|
+
const degradeToLegacyFlow = status === 401 || status === 404 || status >= 500;
|
|
270
|
+
if (tokenInvalid) {
|
|
271
|
+
setForgotPasswordState({
|
|
272
|
+
resetTokenValidationStatus: 'invalid',
|
|
273
|
+
error: undefined
|
|
274
|
+
});
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (degradeToLegacyFlow) {
|
|
278
|
+
setForgotPasswordState({
|
|
279
|
+
resetTokenValidationStatus: 'valid',
|
|
280
|
+
error: undefined
|
|
281
|
+
});
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
setForgotPasswordState({
|
|
286
|
+
resetTokenValidationStatus: 'valid',
|
|
287
|
+
error: undefined
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
};
|
|
228
291
|
return {
|
|
229
292
|
loadPasswordRecoveryStrategies,
|
|
230
293
|
setForgotPasswordState,
|
|
@@ -232,6 +295,7 @@ var _default = (store, api, sharedActions) => {
|
|
|
232
295
|
forgotPassword,
|
|
233
296
|
resetPassword,
|
|
234
297
|
loadPasswordConfig,
|
|
298
|
+
validateResetPasswordToken,
|
|
235
299
|
determinePasswordRecoveryStrategy,
|
|
236
300
|
sendPasswordRecoveryEmail,
|
|
237
301
|
sendPasswordRecoverySms,
|
|
@@ -15,7 +15,8 @@ const initialState = {
|
|
|
15
15
|
sessionId: '',
|
|
16
16
|
userId: '',
|
|
17
17
|
token: '',
|
|
18
|
-
passwordConfig: null
|
|
18
|
+
passwordConfig: null,
|
|
19
|
+
resetTokenValidationStatus: 'idle'
|
|
19
20
|
};
|
|
20
21
|
exports.initialState = initialState;
|
|
21
22
|
var _default = overrideState => (0, _proxy.createProxy)(initialState, overrideState);
|
package/node/index.js
CHANGED
|
@@ -32,6 +32,20 @@ var _default = (store, api, actions) => {
|
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
+
mockedActions.validateResetPasswordToken = async payload => {
|
|
36
|
+
if (payload.skipValidation) {
|
|
37
|
+
mockedActions.setForgotPasswordState({
|
|
38
|
+
resetTokenValidationStatus: 'valid'
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
mockedActions.setForgotPasswordState({
|
|
43
|
+
resetTokenValidationStatus: 'pending'
|
|
44
|
+
});
|
|
45
|
+
mockedActions.setForgotPasswordState({
|
|
46
|
+
resetTokenValidationStatus: 'valid'
|
|
47
|
+
});
|
|
48
|
+
};
|
|
35
49
|
return mockedActions;
|
|
36
50
|
};
|
|
37
51
|
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontegg/redux-store",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.104.0-alpha.1",
|
|
4
4
|
"main": "./node/index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Frontegg LTD",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@babel/runtime": "^7.18.6",
|
|
9
9
|
"@frontegg/entitlements-javascript-commons": "1.1.2",
|
|
10
|
-
"@frontegg/rest-api": "7.
|
|
10
|
+
"@frontegg/rest-api": "7.104.0-alpha.1",
|
|
11
11
|
"fast-deep-equal": "3.1.3",
|
|
12
12
|
"get-value": "^3.0.1",
|
|
13
13
|
"proxy-compare": "^3.0.0",
|