diff --git a/settings/src/components/account-status.js b/settings/src/components/account-status.js index b6694873..816a6b9c 100644 --- a/settings/src/components/account-status.js +++ b/settings/src/components/account-status.js @@ -15,26 +15,31 @@ import ScreenLink from './screen-link'; * Render the Account Status. */ export default function AccountStatus() { - const { userRecord } = useContext( GlobalContext ); - const { record } = userRecord; - const emailStatus = record.pending_email ? 'pending' : 'ok'; - const totpEnabled = record[ '2fa_available_providers' ].includes( 'Two_Factor_Totp' ); - const webAuthnEnabled = record[ '2fa_available_providers' ].includes( - 'TwoFactor_Provider_WebAuthn' - ); - const primaryProviderEnabled = totpEnabled || webAuthnEnabled; - const backupCodesEnabled = - record[ '2fa_available_providers' ].includes( 'Two_Factor_Backup_Codes' ); + const { + user: { + userRecord: { + record: { + '2fa_available_providers': availableProviders, + email, + pending_email: pendingEmail, + }, + }, + hasPrimaryProvider, + }, + } = useContext( GlobalContext ); + const emailStatus = pendingEmail ? 'pending' : 'ok'; + const totpEnabled = availableProviders.includes( 'Two_Factor_Totp' ); + const backupCodesEnabled = availableProviders.includes( 'Two_Factor_Backup_Codes' ); const backupBodyText = - ! backupCodesEnabled && ! primaryProviderEnabled + ! backupCodesEnabled && ! hasPrimaryProvider ? 'Please enable Two-Factor Authentication before enabling backup codes.' : `You have ${ backupCodesEnabled ? '' : 'not' } verified your backup codes for two-factor authentication.`; return ( - <> +
@@ -72,7 +77,7 @@ export default function AccountStatus() { bodyText={ backupBodyText } disabled={ ! backupCodesEnabled } /> - +
); } diff --git a/settings/src/components/backup-codes.js b/settings/src/components/backup-codes.js index 66319616..d14dd37c 100644 --- a/settings/src/components/backup-codes.js +++ b/settings/src/components/backup-codes.js @@ -16,7 +16,9 @@ import { refreshRecord } from '../utilities'; * Setup and manage backup codes. */ export default function BackupCodes() { - const { userRecord } = useContext( GlobalContext ); + const { + user: { userRecord }, + } = useContext( GlobalContext ); const [ regenerating, setRegenerating ] = useState( false ); const backupCodesEnabled = @@ -35,7 +37,10 @@ export default function BackupCodes() { * @param props.setRegenerating */ function Setup( { setRegenerating } ) { - const { setGlobalNotice, userRecord } = useContext( GlobalContext ); + const { + setGlobalNotice, + user: { userRecord }, + } = useContext( GlobalContext ); const [ backupCodes, setBackupCodes ] = useState( [] ); const [ hasPrinted, setHasPrinted ] = useState( false ); @@ -142,8 +147,12 @@ function CodeList( { codes } ) { * @param props.setRegenerating */ function Manage( { setRegenerating } ) { - const { userRecord } = useContext( GlobalContext ); - const remaining = userRecord.record[ '2fa_backup_codes_remaining' ]; + const { + user: { + userRecord: { record }, + }, + } = useContext( GlobalContext ); + const remaining = record[ '2fa_backup_codes_remaining' ]; return ( <> diff --git a/settings/src/components/email-address.js b/settings/src/components/email-address.js index 3e7d566e..4bf1569b 100644 --- a/settings/src/components/email-address.js +++ b/settings/src/components/email-address.js @@ -14,8 +14,12 @@ import { GlobalContext } from '../script'; * Render the Email setting. */ export default function EmailAddress() { - const { userRecord } = useContext( GlobalContext ); - const { record, edit, save, editedRecord, hasEdits, isSaving } = userRecord; + const { + user: { + userRecord: { record, edit, save, editedRecord, hasEdits }, + isSaving, + }, + } = useContext( GlobalContext ); const [ emailError, setEmailError ] = useState( '' ); const [ justChangedEmail, setJustChangedEmail ] = useState( false ); diff --git a/settings/src/components/password.js b/settings/src/components/password.js index f6cfcafa..b704aa64 100644 --- a/settings/src/components/password.js +++ b/settings/src/components/password.js @@ -25,29 +25,35 @@ import { GlobalContext } from '../script'; * Render the Password setting. */ export default function Password() { - const { setGlobalNotice, userRecord } = useContext( GlobalContext ); + const { + setGlobalNotice, + user: { + userRecord: { hasEdits, editedRecord, record, edit, save }, + isSaving, + }, + } = useContext( GlobalContext ); const [ inputType, setInputType ] = useState( 'password' ); const [ hasAttemptedSave, setHasAttemptedSave ] = useState( false ); let passwordStrong = true; // Saved passwords have already passed the test. - if ( userRecord.hasEdits ) { - passwordStrong = isPasswordStrong( userRecord.editedRecord.password, userRecord.record ); + if ( hasEdits ) { + passwordStrong = isPasswordStrong( editedRecord.password, record ); } // Clear the "saved password" notice when password is being changed. useEffect( () => { - if ( ! userRecord.hasEdits ) { + if ( ! hasEdits ) { return; } setGlobalNotice( '' ); - }, [ userRecord.hasEdits ] ); + }, [ hasEdits ] ); /** * Handle clicking the `Generate Password` button. */ const handlePasswordGenerate = useCallback( async () => { - userRecord.edit( { password: generatePassword( 24, true, true ) } ); + edit( { password: generatePassword( 24, true, true ) } ); setInputType( 'text' ); }, [] ); @@ -58,11 +64,11 @@ export default function Password() { setHasAttemptedSave( true ); - if ( ! passwordStrong || userRecord.isSaving ) { + if ( ! passwordStrong || isSaving ) { return; } - await userRecord.save(); + await save(); // Changing the password resets the nonce, which causes subsequent API requests to fail. `apiFetch()` will // retry them automatically, but that results in an extra XHR request and a console error. @@ -74,10 +80,10 @@ export default function Password() { setGlobalNotice( 'New password saved.' ); }, - [ passwordStrong, userRecord.isSaving ] + [ passwordStrong, isSaving ] ); - const handlePasswordChange = useCallback( ( password ) => userRecord.edit( { password } ), [] ); + const handlePasswordChange = useCallback( ( password ) => edit( { password } ), [] ); const handlePasswordToggle = useCallback( () => setInputType( inputType === 'password' ? 'text' : 'password' ), @@ -109,7 +115,7 @@ export default function Password() { help="The generate button will create a secure, random password." label="New Password" size="62" - value={ userRecord.editedRecord.password ?? '' } + value={ editedRecord.password ?? '' } placeholder="Enter New Password..." onChange={ handlePasswordChange } /> @@ -124,27 +130,24 @@ export default function Password() { - { userRecord.hasEdits && passwordStrong && ( + { hasEdits && passwordStrong && ( Your password is strong enough to be saved. ) } - { userRecord.hasEdits && - userRecord.editedRecord.password && - hasAttemptedSave && - ! passwordStrong && ( - - - That password is too easy to compromise. Please make it longer and/or add - random numbers/symbols. - - ) } + { hasEdits && editedRecord.password && hasAttemptedSave && ! passwordStrong && ( + + + That password is too easy to compromise. Please make it longer and/or add random + numbers/symbols. + + ) }

- { window.crypto?.getRandomValues && ( diff --git a/settings/src/components/revalidate-modal.js b/settings/src/components/revalidate-modal.js index 774165f1..d735bb1b 100644 --- a/settings/src/components/revalidate-modal.js +++ b/settings/src/components/revalidate-modal.js @@ -26,7 +26,11 @@ export default function RevalidateModal() { } function RevalidateIframe() { - const { setGlobalNotice, userRecord } = useContext( GlobalContext ); + const { + setGlobalNotice, + user: { userRecord }, + } = useContext( GlobalContext ); + const { record } = userRecord; const ref = useRef(); useEffect( () => { @@ -39,7 +43,7 @@ function RevalidateIframe() { // Pretend that the expires_at is in the future (+1hr), this provides a 'faster' UI. // This intentionally doesn't use `edit()` to prevent it attempting to update it on the server. - userRecord.record[ '2fa_revalidation' ].expires_at = new Date().getTime() / 1000 + 3600; + record[ '2fa_revalidation' ].expires_at = new Date().getTime() / 1000 + 3600; // Refresh the user record, to fetch the correct 2fa_revalidation data. refreshRecord( userRecord ); @@ -56,7 +60,7 @@ function RevalidateIframe() {