Skip to content

Commit

Permalink
Add modal for confirmation of disabling security keys
Browse files Browse the repository at this point in the history
  • Loading branch information
adamwoodnz committed Aug 9, 2023
1 parent e8abd7b commit e7e3203
Showing 1 changed file with 87 additions and 40 deletions.
127 changes: 87 additions & 40 deletions settings/src/components/webauthn/webauthn.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
import { Button, Notice, Spinner } from '@wordpress/components';
import { Button, Notice, Spinner, Modal } from '@wordpress/components';
import { useCallback, useContext, useState } from '@wordpress/element';
import { Icon, cancelCircleFilled } from '@wordpress/icons';
import apiFetch from '@wordpress/api-fetch';
Expand All @@ -17,7 +17,6 @@ import RegisterKey from './register-key';
/**
* Global dependencies
*/
const confirm = window.confirm;
const alert = window.alert;

/**
Expand All @@ -37,27 +36,14 @@ export default function WebAuthn() {
const [ flow, setFlow ] = useState( 'manage' );
const [ statusError, setStatusError ] = useState( '' );
const [ statusWaiting, setStatusWaiting ] = useState( false );

/**
* Handle post-registration prcessing.
*/
const onRegisterSuccess = useCallback( async () => {
if ( ! webAuthnEnabled ) {
await enableProvider();
}

if ( ! backupCodesEnabled ) {
// TODO maybe redirect to backup codes, pending discussion.
alert( 'redirect to backup codes' );
} else {
setFlow( 'manage' );
}
}, [ webAuthnEnabled, backupCodesEnabled ] );
const [ confirmingDisable, setConfirmingDisable ] = useState( false );

/**
* Enable the WebAuthn provider.
*/
const enableProvider = useCallback( async () => {
const toggleProvider = useCallback( async () => {
const status = webAuthnEnabled ? 'disable' : 'enable';

try {
setStatusError( '' );
setStatusWaiting( true );
Expand All @@ -68,40 +54,48 @@ export default function WebAuthn() {
data: {
user_id: record.id,
provider: 'TwoFactor_Provider_WebAuthn',
status: 'enable',
status,
},
} );

await refreshRecord( userRecord );
setGlobalNotice( 'Successfully enabled Security Keys.' );
setGlobalNotice( `Successfully ${ status }d Security Keys.` );
} catch ( error ) {
setStatusError( error?.message || error?.responseJSON?.data || error );
} finally {
setStatusWaiting( false );
}
}, [] );
}, [ record, setGlobalNotice, userRecord, webAuthnEnabled ] );

/**
* Disable the WebAuthn provider.
* Handle post-registration processing.
*/
const disableProvider = useCallback( () => {
// TODO this will be done in a separate PR
// Also pending outcome of https://github.com/WordPress/wporg-two-factor/issues/194#issuecomment-1564930700

// return early if already disabled?
// this shouldn't be called in the first place if that's the case, maybe the button should be disabled or not even shown
//
// call api to disable provider
// handle failure

confirm(
'TODO Modal H4 Disable Security Keys? p Are you sure you want to disable Security Keys? Button Cancel Button Disable'
);
const onRegisterSuccess = useCallback( async () => {
if ( ! webAuthnEnabled ) {
await toggleProvider();
}

// refresuserRecord should result in this screen re-rendering with the enable button visible instead of the disable button
if ( ! backupCodesEnabled ) {
// TODO maybe redirect to backup codes, pending discussion.
alert( 'redirect to backup codes' );
} else {
setFlow( 'manage' );
}
}, [ webAuthnEnabled, backupCodesEnabled, toggleProvider ] );

// maybe refactor to use some of enableProvider() b/c they're calling the same endpoint, just with a different `status` value
}, [] ); // todo any dependencies?
/**
* Display the modal to confirm disabling the WebAuthn provider.
*/
const showConfirmDisableModal = useCallback( () => {
setConfirmingDisable( true );
}, [] );

/**
* Hide te modal to confirm disabling the WebAuthn provider.
*/
const hideConfirmDisableModal = useCallback( () => {
setConfirmingDisable( false );
}, [] );

if ( 'register' === flow ) {
return (
Expand Down Expand Up @@ -134,7 +128,7 @@ export default function WebAuthn() {
{ keys.length > 0 && (
<Button
variant="secondary"
onClick={ webAuthnEnabled ? disableProvider : enableProvider }
onClick={ webAuthnEnabled ? showConfirmDisableModal : toggleProvider }
disabled={ statusWaiting }
>
{ webAuthnEnabled ? 'Disable security keys' : 'Enable security keys' }
Expand All @@ -154,6 +148,59 @@ export default function WebAuthn() {
{ statusError }
</Notice>
) }

{ confirmingDisable && (
<ConfirmDisableKeys
error={ statusError }
disabling={ statusWaiting }
onClose={ hideConfirmDisableModal }
onConfirm={ toggleProvider }
/>
) }
</>
);
}

/**
* Prompt the user to confirm they want to disable security keys.
*
* @param {Object} props
* @param {Function} props.onConfirm
* @param {Function} props.onClose
* @param {string} props.error
* @param {boolean} props.disabling
*/
function ConfirmDisableKeys( { onConfirm, onClose, disabling, error } ) {
if ( !! error ) {
onClose();
return null;
}

return (
<Modal
title={ `Disable security keys` }
className="wporg-2fa__confirm-disable-keys"
onRequestClose={ onClose }
>
<p className="wporg-2fa__screen-intro">
Are you sure you want to disable security keys?
</p>

<div className="wporg-2fa__submit-actions">
<Button variant="primary" onClick={ onConfirm }>
Disable
</Button>

<Button variant="secondary" onClick={ onClose }>
Cancel
</Button>
</div>

{ disabling && (
<p className="wporg-2fa__webauthn-register-key-status">
<Spinner />
</p>
) }
</Modal>
);
}

0 comments on commit e7e3203

Please sign in to comment.