Skip to content

Commit

Permalink
Merge pull request #4171 from LiskHQ/4169-no-error-providing-second-p…
Browse files Browse the repository at this point in the history
…assphrase

Disable send button for an incorrect second passphrase - Closes #4169
  • Loading branch information
reyraa authored Feb 23, 2022
2 parents 45a2b90 + 8bd7fac commit 569e7c2
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 5 deletions.
11 changes: 7 additions & 4 deletions src/components/shared/transactionSummary/footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import React, { useEffect, useState } from 'react';
import { PrimaryButton, SecondaryButton, TertiaryButton } from '@toolbox/buttons';
import PassphraseInput from '@toolbox/passphraseInput';
import useSecondPassphrase from '@src/hooks/setSecondPassphrase';
import BoxFooter from '@toolbox/box/footer';
import styles from './transactionSummary.css';

Expand All @@ -23,7 +24,7 @@ const Actions = ({
)}
<PrimaryButton
className="confirm-button"
disabled={confirmButton.disabled || inputStatus === 'visible'}
disabled={confirmButton.disabled || inputStatus === 'visible' || inputStatus === 'invalid'}
onClick={confirmButton.onClick}
>
{isMultisignature ? t('Sign') : confirmButton.label}
Expand All @@ -34,12 +35,14 @@ const Actions = ({
const SecondPassInput = ({
t, secondPassphraseStored, inputStatus, setInputStatus,
}) => {
const [secondPass, set2ndPass] = useState('');
const [secondPass, set2ndPass] = useSecondPassphrase();

useEffect(() => {
if (secondPass) {
secondPassphraseStored(secondPass);
if (secondPass.error === 0) {
secondPassphraseStored(secondPass.data);
setInputStatus('valid');
} else if (secondPass.error > 0) {
setInputStatus('invalid');
}
}, [secondPass]);

Expand Down
46 changes: 46 additions & 0 deletions src/hooks/setSecondPassphrase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useState } from 'react';
import { useSelector } from 'react-redux';
import { selectActiveTokenAccount } from '@store/selectors';
import { extractPublicKey } from '@utils/account';

const empty2ndPass = {
data: '',
error: -1,
feedback: [],
};

const setSecondPassphrase = () => {
const [secondPass, set2ndPass] = useState(empty2ndPass);
const account = useSelector(selectActiveTokenAccount);

const validate2ndPass = (data, error) => {
const messages = [];
if (error) {
messages.push(messages);
return messages;
}

const secondPublicKey = account.keys.mandatoryKeys
.filter(item => item !== account.summary.publicKey);
const publicKey = extractPublicKey(data);

// compare them
if (!secondPublicKey.length || publicKey !== secondPublicKey[0]) {
messages.push('This passphrase does not belong to your account.');
}
return messages;
};

const setter = (data, error) => {
const feedback = validate2ndPass(data, error);
set2ndPass({
data,
error: data === '' ? -1 : feedback.length,
feedback,
});
};

return [secondPass, setter];
};

export default setSecondPassphrase;
41 changes: 41 additions & 0 deletions src/hooks/setSecondPassphrase.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { renderHook, act } from '@testing-library/react-hooks';
import { useSelector } from 'react-redux';
import setSecondPassphrase from './setSecondPassphrase';
import accounts from '../../test/constants/accounts';

jest.mock('@store');

// const mockSelector = jest.fn();
useSelector.mockReturnValue(accounts.secondPass);

describe('setSecondPassphrase', () => {
it('Should return second passphrase with no error message', () => {
const result = renderHook(() => setSecondPassphrase());
const [state, setState] = result.result.current;
expect(state.error).toBe(-1);
act(() => {
setState(accounts.secondPass.secondPass);
});
expect(result.result.current[0].error).toBe(0);
});

it('Should return second passphrase with relevant error message', () => {
const result = renderHook(() => setSecondPassphrase());
const [state, setState] = result.result.current;
expect(state.error).toBe(-1);
act(() => {
setState(accounts.genesis.passphrase);
});
expect(result.result.current[0].error).toBe(1);
});

it('Should return second passphrase with an external error message, if provided', () => {
const result = renderHook(() => setSecondPassphrase());
const [state, setState] = result.result.current;
expect(state.error).toBe(-1);
act(() => {
setState('wrong_pass', 'The pass is invalid');
});
expect(result.result.current[0].error).toBe(1);
});
});
11 changes: 10 additions & 1 deletion src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ const selectBTCAddress = state =>
(state.account.info ? state.account.info.BTC.summary.address : undefined);
const selectPublicKey = state => state.account.info[state.settings.token.active].publicKey;
const selectTransactions = state => state.transactions;
const selectActiveTokenAccount = state => state.account.info[state.settings.token.active];
const selectActiveTokenAccount = (state) => {
if (!state.account.info) {
return {};
}
return {
...state.account.info[state.settings.token.active],
passphrase: state.passphrase,
hwInfo: state.hwInfo,
};
};
const selectAccountBalance = state => (
state.account.info ? state.account.info[state.settings.token.active].summary.balance : undefined);
const selectBookmarks = state => state.bookmarks[state.settings.token.active];
Expand Down

0 comments on commit 569e7c2

Please sign in to comment.