Skip to content

Commit

Permalink
Trim passwords input (fedimint#589)
Browse files Browse the repository at this point in the history
* feat: trim whitespace in verification codes

* feat: trim leading/trailing whitespace in verification codes/rebase

* feat: trim whitespace from password confirmation input
  • Loading branch information
kleysc authored Jan 6, 2025
1 parent 886a376 commit 6e3c4c1
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React from 'react';
import {
Alert,
AlertDescription,
Expand All @@ -21,6 +21,7 @@ import {
} from '@chakra-ui/react';
import { useTranslation } from '@fedimint/utils';
import { ReactComponent as WarningIcon } from '../../../../assets/svgs/warning.svg';
import { useTrimmedInput } from '../../../../../hooks';

interface ConfirmPasswordModalProps {
password: string;
Expand All @@ -38,8 +39,8 @@ export const ConfirmPasswordModal: React.FC<ConfirmPasswordModalProps> = ({
guardianName,
}) => {
const { t } = useTranslation();
const [confirmPassword, setConfirmPassword] = useState('');
const [confirmGuardianName, setConfirmGuardianName] = useState('');
const [confirmPassword, setConfirmPassword] = useTrimmedInput('');
const [confirmGuardianName, setConfirmGuardianName] = useTrimmedInput('');

const confirmed =
confirmPassword === password && confirmGuardianName === guardianName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
useConsensusPolling,
useGuardianSetupApi,
useGuardianSetupContext,
useTrimmedInputArray,
} from '../../../../../hooks';

interface PeerWithHash {
Expand All @@ -63,7 +64,9 @@ export const VerifyGuardians: React.FC<Props> = ({ next }) => {
const isHost = role === GuardianRole.Host;
const [myHash, setMyHash] = useState('');
const [peersWithHash, setPeersWithHash] = useState<PeerWithHash[]>();
const [enteredHashes, setEnteredHashes] = useState<string[]>([]);
const [enteredHashes, handleHashChange] = useTrimmedInputArray(
peersWithHash ? peersWithHash.map(() => '') : []
);
const [verifiedConfigs, setVerifiedConfigs] = useState<boolean>(false);
const [isStarting, setIsStarting] = useState(false);
const [error, setError] = useState<string>();
Expand All @@ -74,14 +77,6 @@ export const VerifyGuardians: React.FC<Props> = ({ next }) => {
useConsensusPolling();

useEffect(() => {
if (
peers.every(
(peer) => peer.status === GuardianServerStatus.VerifiedConfigs
)
) {
setVerifiedConfigs(true);
}

async function assembleHashInfo() {
if (peers.length === 0) {
return setError(t('verify-guardians.error'));
Expand All @@ -97,7 +92,6 @@ export const VerifyGuardians: React.FC<Props> = ({ next }) => {

try {
const hashes = await api.getVerifyConfigHash();

setMyHash(hashes[ourCurrentId]);
setPeersWithHash(
Object.entries(peers)
Expand All @@ -109,23 +103,23 @@ export const VerifyGuardians: React.FC<Props> = ({ next }) => {
.filter((peer) => peer.id !== ourCurrentId.toString())
);

// If we're already at the VerifiedConfigs state, prefill all the other hashes with the correct values
// Prefill hashes if already verified
if (
peers[ourCurrentId].status === GuardianServerStatus.VerifiedConfigs
) {
const otherPeers = Object.entries(peers).filter(
([id]) => id !== ourCurrentId.toString()
);
setEnteredHashes(
otherPeers.map(([id]) => hashes[id as unknown as number])
);
otherPeers.forEach(([id], idx) => {
handleHashChange(idx, hashes[id as unknown as number]);
});
}
} catch (err) {
setError(formatApiErrorMessage(err));
}
}
assembleHashInfo();
}, [api, peers, ourCurrentId, t]);
}, [api, peers, ourCurrentId, t, handleHashChange]);

useEffect(() => {
// If we're the only guardian, skip this verify other guardians step.
Expand Down Expand Up @@ -207,14 +201,6 @@ export const VerifyGuardians: React.FC<Props> = ({ next }) => {
sm: 'row',
}) as StackDirection | undefined;

const handleChangeHash = useCallback((value: string, index: number) => {
setEnteredHashes((hashes) => {
const newHashes = [...hashes];
newHashes[index] = value;
return newHashes;
});
}, []);

const tableRows = useMemo(() => {
if (!peersWithHash) return [];
return peersWithHash.map(({ peer, hash }, idx) => {
Expand All @@ -239,14 +225,14 @@ export const VerifyGuardians: React.FC<Props> = ({ next }) => {
variant='filled'
value={value}
placeholder={`${t('verify-guardians.verified-placeholder')}`}
onChange={(ev) => handleChangeHash(ev.currentTarget.value, idx)}
onChange={(ev) => handleHashChange(idx, ev.currentTarget.value)}
readOnly={isValid}
/>
</FormControl>
),
};
});
}, [peersWithHash, enteredHashes, handleChangeHash, t]);
}, [peersWithHash, enteredHashes, handleHashChange, t]);

if (error) {
return (
Expand Down Expand Up @@ -344,7 +330,7 @@ export const VerifyGuardians: React.FC<Props> = ({ next }) => {
'verify-guardians.verified-placeholder'
)}`}
onChange={(ev) =>
handleChangeHash(ev.currentTarget.value, idx)
handleHashChange(idx, ev.currentTarget.value)
}
readOnly={isValid}
/>
Expand Down
27 changes: 27 additions & 0 deletions apps/router/src/hooks/custom/useTrimmedInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useState } from 'react';

const cleanInput = (value: string) => value.trim();

export const useTrimmedInput = (initialValue = '') => {
const [value, setValue] = useState(initialValue);

const handleChange = (newValue: string) => {
setValue(cleanInput(newValue));
};

return [value, handleChange] as const;
};

export const useTrimmedInputArray = (initialValues: string[]) => {
const [values, setValues] = useState<string[]>(initialValues);

const handleChange = (index: number, newValue: string) => {
setValues((prev) => {
const newValues = [...prev];
newValues[index] = cleanInput(newValue);
return newValues;
});
};

return [values, handleChange] as const;
};
1 change: 1 addition & 0 deletions apps/router/src/hooks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useLocation } from 'react-router-dom';
export * from './guardian/useGuardian';
export * from './guardian/useGuardianSetup';
export * from './gateway/useGateway';
export * from './custom/useTrimmedInput';

import { useContext } from 'react';
import { AppContext, AppContextValue } from '../context/AppContext';
Expand Down

0 comments on commit 6e3c4c1

Please sign in to comment.