mirror of
https://github.com/trezor/trezor-wallet
synced 2025-03-21 02:26:13 +00:00
fix: setInitialUrl - race condition
- Do not set initialUrl if it is landingPage - Block "RouterAction.selectDevice" if currently selected device is in auth process - Move WalletActions.observe() before DiscoveryActions.restore() in "WalletSerivce"
This commit is contained in:
parent
241e59dc98
commit
585c79a738
@ -430,29 +430,42 @@ export const setInitialUrl = (): PayloadAction<boolean> => (
|
||||
getState: GetState
|
||||
): boolean => {
|
||||
const { initialPathname } = getState().wallet;
|
||||
if (typeof initialPathname === 'string' && !dispatch(isLandingPageUrl(initialPathname, true))) {
|
||||
const valid = dispatch(
|
||||
getValidUrl({
|
||||
type: LOCATION_CHANGE,
|
||||
payload: {
|
||||
location: {
|
||||
pathname: initialPathname,
|
||||
hash: '',
|
||||
search: '',
|
||||
state: {},
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
if (typeof initialPathname !== 'string') return false;
|
||||
|
||||
if (valid === initialPathname) {
|
||||
// reset initial url
|
||||
dispatch({
|
||||
type: SET_INITIAL_URL,
|
||||
});
|
||||
dispatch(goto(valid));
|
||||
return true;
|
||||
}
|
||||
// DEVICE.CONNECT race condition, "selectDevice" method was called but currently selectedDevice is in getState (auth) process
|
||||
// if so, consume this action (return true) to break "selectDevice" process
|
||||
// "setInitialUrl" will be called again after AUTH_DEVICE action
|
||||
const { selectedDevice } = getState().wallet;
|
||||
if (
|
||||
selectedDevice &&
|
||||
selectedDevice.type === 'acquired' &&
|
||||
!selectedDevice.features.passphrase_protection &&
|
||||
!selectedDevice.state
|
||||
)
|
||||
return true;
|
||||
|
||||
const valid = dispatch(
|
||||
getValidUrl({
|
||||
type: LOCATION_CHANGE,
|
||||
payload: {
|
||||
location: {
|
||||
pathname: initialPathname,
|
||||
hash: '',
|
||||
search: '',
|
||||
state: {},
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
if (valid === initialPathname) {
|
||||
// reset initial url
|
||||
dispatch({
|
||||
type: SET_INITIAL_URL,
|
||||
});
|
||||
dispatch(goto(valid));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
@ -29,11 +29,16 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa
|
||||
api.dispatch(WalletActions.init());
|
||||
// set initial url
|
||||
// TODO: validate if initial url is potentially correct
|
||||
api.dispatch({
|
||||
type: WALLET.SET_INITIAL_URL,
|
||||
pathname: action.payload.location.pathname,
|
||||
state: {},
|
||||
});
|
||||
// exclude landing page url
|
||||
const { pathname } = action.payload.location;
|
||||
const isValidPath = !api.dispatch(RouterActions.isLandingPageUrl(pathname, true));
|
||||
if (isValidPath) {
|
||||
api.dispatch({
|
||||
type: WALLET.SET_INITIAL_URL,
|
||||
pathname: action.payload.location.pathname,
|
||||
state: {},
|
||||
});
|
||||
}
|
||||
// pass action and break process
|
||||
return next(action);
|
||||
}
|
||||
@ -63,6 +68,29 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa
|
||||
// update common values ONLY if application is ready
|
||||
if (!api.getState().wallet.ready) return action;
|
||||
|
||||
// observe common values in WallerReducer
|
||||
if (!(await api.dispatch(WalletActions.observe(prevState, action)))) {
|
||||
// if "selectedDevice" didn't change observe common values in SelectedAccountReducer
|
||||
if (!(await api.dispatch(SelectedAccountActions.observe(prevState, action)))) {
|
||||
// if "selectedAccount" didn't change observe send form props changes
|
||||
api.dispatch(SendFormActions.observe(prevState, action));
|
||||
}
|
||||
} else {
|
||||
// no changes in common values
|
||||
if (action.type === CONNECT.RECEIVE_WALLET_TYPE) {
|
||||
if (action.device.state) {
|
||||
// redirect to root view (Dashboard) if device was authenticated before
|
||||
api.dispatch(RouterActions.selectFirstAvailableDevice(true));
|
||||
}
|
||||
api.dispatch(TrezorConnectActions.authorizeDevice());
|
||||
}
|
||||
if (action.type === CONNECT.AUTH_DEVICE) {
|
||||
// selected device did changed
|
||||
// try to restore discovery after device authentication
|
||||
api.dispatch(DiscoveryActions.restore());
|
||||
}
|
||||
}
|
||||
|
||||
// double verification needed
|
||||
// Corner case: LOCATION_CHANGE was called but pathname didn't changed (redirection from RouterService)
|
||||
const prevLocation = prevState.router.location;
|
||||
@ -96,29 +124,6 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa
|
||||
api.dispatch(NotificationActions.clear(prevLocation.state, currentLocation.state));
|
||||
}
|
||||
|
||||
// observe common values in WallerReducer
|
||||
if (!(await api.dispatch(WalletActions.observe(prevState, action)))) {
|
||||
// if "selectedDevice" didn't change observe common values in SelectedAccountReducer
|
||||
if (!(await api.dispatch(SelectedAccountActions.observe(prevState, action)))) {
|
||||
// if "selectedAccount" didn't change observe send form props changes
|
||||
api.dispatch(SendFormActions.observe(prevState, action));
|
||||
}
|
||||
} else {
|
||||
// no changes in common values
|
||||
if (action.type === CONNECT.RECEIVE_WALLET_TYPE) {
|
||||
if (action.device.state) {
|
||||
// redirect to root view (Dashboard) if device was authenticated before
|
||||
api.dispatch(RouterActions.selectFirstAvailableDevice(true));
|
||||
}
|
||||
api.dispatch(TrezorConnectActions.authorizeDevice());
|
||||
}
|
||||
if (action.type === CONNECT.AUTH_DEVICE) {
|
||||
// selected device did changed
|
||||
// try to restore discovery after device authentication
|
||||
api.dispatch(DiscoveryActions.restore());
|
||||
}
|
||||
}
|
||||
|
||||
// even if "selectedDevice" didn't change because it was updated on DEVICE.CHANGED before DEVICE.CONNECT action
|
||||
// try to restore discovery
|
||||
if (action.type === DEVICE.CONNECT) {
|
||||
|
Loading…
Reference in New Issue
Block a user