Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move inline JS to external scripts #562

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions js/admin-backup-codes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
(function(){
const backupCodes = document.getElementById( 'two-factor-backup-codes' ),
generateCodesButton = backupCodes.querySelector( '.button-two-factor-backup-codes-generate' ),
userId = backupCodes.dataset.userid || 0;

// Backup Codes generation
generateCodesButton.addEventListener( 'click', function(e) {
const codesCountDiv = backupCodes.querySelector( '.two-factor-backup-codes-count' ),
codeWrapper = backupCodes.querySelector( '.two-factor-backup-codes-wrapper' ),
codeList = backupCodes.querySelector( '.two-factor-backup-codes-unused-codes' ),
downloadButton = backupCodes.querySelector( '.button-two-factor-backup-codes-download' );

wp.apiRequest( {
method: 'POST',
path: 'two-factor/1.0/generate-backup-codes',
data: {
user_id: userId
}
} ).then( function( response ) {
codeList.innerHTML = '';

// Append the codes.
for ( i = 0; i < response.codes.length; i++ ) {
codeList.innerHTML += '<li>' + response.codes[ i ] + '</li>';
}

// Display the section.
codeWrapper.style.display = 'block';

// Update counter.
codesCountDiv.innerHTML = response.i18n.count;

// Update link.
downloadButton.href = response.download_link;
} );
} );

})();
90 changes: 90 additions & 0 deletions js/admin-totp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
(function(){
const totpSetup = document.getElementById( 'two-factor-totp-options' ),
userId = totpSetup.dataset.userid || 0;

// TOTP QR Setup
const renderQRCode = function() {
var link = document.querySelector( '#two-factor-qr-code a' );
if ( ! link ) {
return;
}

/*
* 0 = Automatically select the version, to avoid going over the limit of URL
* length.
* L = Least amount of error correction, because it's not needed when scanning
* on a monitor, and it lowers the image size.
*/
var qr = qrcode( 0, 'L' );

qr.addData( link.href );
qr.make();

link.innerHTML = qr.createSvgTag( 5 );
};

// TOTP Setup
const totpSetupHandler = function( e ) {
e.preventDefault();

const totpKey = document.getElementById( 'two-factor-totp-key' ).value,
totpCodeInput = document.getElementById( 'two-factor-totp-authcode' ),
totpSetupSubmit = totpSetup.querySelector( '.totp-submit' );

wp.apiRequest( {
method: 'POST',
path: 'two-factor/1.0/totp',
data: {
user_id: userId,
key: totpKey,
code: totpCodeInput.value,
}
} ).fail( function( response, status ) {
let errorMessage = response.responseJSON.message || status,
errorDiv = totpSetup.querySelector( '.totp-setup-error' );

if ( ! errorDiv ) {
totpSetupSubmit.outerHTML += '<div class="totp-setup-error error"><p></p></div>';
errorDiv = totpSetup.querySelector( '.totp-setup-error' );
}

errorDiv.querySelector( 'p' ).textContent = errorMessage;
totpCodeInput.value = '';
} ).then( function( response ) {
totpSetup.innerHTML = response.html;
} );
};

const totpResetHandler = function( e ) {
e.preventDefault();

wp.apiRequest( {
method: 'DELETE',
path: 'two-factor/1.0/totp',
data: {
user_id: userId,
}
} ).then( function( response ) {
totpSetup.innerHTML = response.html;

// And render the QR.
renderQRCode();
} );
};

// Render the QR now if the document is loaded, otherwise on DOMContentLoaded.
if ( document.readyState === 'complete' ) {
renderQRCode();
} else {
window.addEventListener( 'DOMContentLoaded', renderQRCode );
}

// Add the Click handlers.
totpSetup.addEventListener( 'click', function( e ) {
if ( e.target.closest( '.totp-submit' ) ) {
totpSetupHandler( e );
} else if ( e.target.closest( '.reset-totp-key' ) ) {
totpResetHandler( e );
}
} );
})();
63 changes: 28 additions & 35 deletions providers/class-two-factor-backup-codes.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ protected function __construct() {
add_action( 'two_factor_user_options_' . __CLASS__, array( $this, 'user_options' ) );
add_action( 'admin_notices', array( $this, 'admin_notices' ) );

add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );

return parent::__construct();
}

Expand Down Expand Up @@ -130,6 +133,21 @@ public function get_alternative_provider_label() {
return __( 'Use a recovery code', 'two-factor' );
}

/**
* Enqueue scripts
*
* @codeCoverageIgnore
*/
public function enqueue_assets( $hook_suffix ) {
wp_register_script(
'two-factor-backup-codes',
plugins_url( 'js/admin-backup-codes.js', __DIR__ ),
array( 'wp-api-request' ),
TWO_FACTOR_VERSION,
true
);
}

/**
* Whether this Two Factor provider is configured and codes are available for the user specified.
*
Expand All @@ -154,9 +172,11 @@ public function is_available_for_user( $user ) {
* @param WP_User $user WP_User object of the logged-in user.
*/
public function user_options( $user ) {
wp_enqueue_script( 'two-factor-backup-codes' );

$count = self::codes_remaining_for_user( $user );
?>
<p id="two-factor-backup-codes">
<div id="two-factor-backup-codes" data-userid="<?php echo esc_attr( $user->ID ); ?>">
<p class="two-factor-backup-codes-count">
<?php
echo esc_html(
Expand All @@ -173,41 +193,14 @@ public function user_options( $user ) {
<?php esc_html_e( 'Generate new recovery codes', 'two-factor' ); ?>
</button>
</p>
</p>
<div class="two-factor-backup-codes-wrapper" style="display:none;">
<ol class="two-factor-backup-codes-unused-codes"></ol>
<p class="description"><?php esc_html_e( 'Write these down! Once you navigate away from this page, you will not be able to view these codes again.', 'two-factor' ); ?></p>
<p>
<a class="button button-two-factor-backup-codes-download button-secondary hide-if-no-js" href="javascript:void(0);" id="two-factor-backup-codes-download-link" download="two-factor-backup-codes.txt"><?php esc_html_e( 'Download Codes', 'two-factor' ); ?></a>
<p>
<div class="two-factor-backup-codes-wrapper" style="display:none;">
<ol class="two-factor-backup-codes-unused-codes"></ol>
<p class="description"><?php esc_html_e( 'Write these down! Once you navigate away from this page, you will not be able to view these codes again.', 'two-factor' ); ?></p>
<p>
<a class="button button-two-factor-backup-codes-download button-secondary hide-if-no-js" download="two-factor-backup-codes.txt"><?php esc_html_e( 'Download Codes', 'two-factor' ); ?></a>
<p>
</div>
</div>
<script type="text/javascript">
( function( $ ) {
$( '.button-two-factor-backup-codes-generate' ).click( function() {
wp.apiRequest( {
method: 'POST',
path: <?php echo wp_json_encode( Two_Factor_Core::REST_NAMESPACE . '/generate-backup-codes' ); ?>,
data: {
user_id: <?php echo wp_json_encode( $user->ID ); ?>
}
} ).then( function( response ) {
var $codesList = $( '.two-factor-backup-codes-unused-codes' );

$( '.two-factor-backup-codes-wrapper' ).show();
$codesList.html( '' );

// Append the codes.
for ( i = 0; i < response.codes.length; i++ ) {
$codesList.append( '<li>' + response.codes[ i ] + '</li>' );
}

// Update counter.
$( '.two-factor-backup-codes-count' ).html( response.i18n.count );
$( '#two-factor-backup-codes-download-link' ).attr( 'href', response.download_link );
} );
} );
} )( jQuery );
</script>
<?php
}

Expand Down
92 changes: 12 additions & 80 deletions providers/class-two-factor-totp.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ public function enqueue_assets( $hook_suffix ) {
TWO_FACTOR_VERSION,
true
);

wp_register_script(
'two-factor-totp',
plugins_url( 'js/admin-totp.js', __DIR__ ),
array( 'two-factor-qr-code-generator', 'wp-api-request' ),
TWO_FACTOR_VERSION,
true
);
}

/**
Expand Down Expand Up @@ -271,10 +279,10 @@ public function user_two_factor_options( $user ) {

$key = $this->get_user_totp_key( $user->ID );

wp_enqueue_script( 'two-factor-qr-code-generator' );
wp_enqueue_script( 'two-factor-totp' );

?>
<div id="two-factor-totp-options">
<div id="two-factor-totp-options" data-userid="<?php echo esc_attr( $user->ID ); ?>">
<?php
if ( empty( $key ) ) :

Expand All @@ -288,7 +296,7 @@ public function user_two_factor_options( $user ) {
</p>
<p id="two-factor-qr-code">
<a href="<?php echo $totp_url; ?>">
Loading...
<?php esc_html_e( 'Loading...', 'two-factor' ); ?>
<img src="<?php echo esc_url( admin_url( 'images/spinner.gif' ) ); ?>" alt="" />
</a>
</p>
Expand All @@ -301,32 +309,6 @@ public function user_two_factor_options( $user ) {
}
</style>

<script>
(function(){
var qr_generator = function() {
/*
* 0 = Automatically select the version, to avoid going over the limit of URL
* length.
* L = Least amount of error correction, because it's not needed when scanning
* on a monitor, and it lowers the image size.
*/
var qr = qrcode( 0, 'L' );

qr.addData( <?php echo wp_json_encode( $totp_url ); ?> );
qr.make();

document.querySelector( '#two-factor-qr-code a' ).innerHTML = qr.createSvgTag( 5 );
};

// Run now if the document is loaded, otherwise on DOMContentLoaded.
if ( document.readyState === 'complete' ) {
qr_generator();
} else {
window.addEventListener( 'DOMContentLoaded', qr_generator );
}
})();
</script>

<p>
<code><?php echo esc_html( $key ); ?></code>
</p>
Expand All @@ -340,42 +322,9 @@ public function user_two_factor_options( $user ) {
?>
<input type="tel" name="two-factor-totp-authcode" id="two-factor-totp-authcode" class="input" value="" size="20" pattern="[0-9 ]*" placeholder="<?php echo esc_attr( $placeholder ); ?>" />
</label>
<input type="submit" class="button totp-submit" name="two-factor-totp-submit" value="<?php esc_attr_e( 'Submit', 'two-factor' ); ?>" />
<input type="submit" class="button totp-submit" value="<?php esc_attr_e( 'Submit', 'two-factor' ); ?>" />
</p>

<script>
(function($){
$('.totp-submit').click( function( e ) {
e.preventDefault();
var key = $('#two-factor-totp-key').val(),
code = $('#two-factor-totp-authcode').val();

wp.apiRequest( {
method: 'POST',
path: <?php echo wp_json_encode( Two_Factor_Core::REST_NAMESPACE . '/totp' ); ?>,
data: {
user_id: <?php echo wp_json_encode( $user->ID ); ?>,
key: key,
code: code,
}
} ).fail( function( response, status ) {
var errorMessage = response.responseJSON.message || status,
$error = $( '#totp-setup-error' );

if ( ! $error.length ) {
$error = $('<div class="error" id="totp-setup-error"><p></p></div>').insertAfter( $('.totp-submit') );
}

$error.find('p').text( errorMessage );

$('#two-factor-totp-authcode').val('');
} ).then( function( response ) {
$( '#two-factor-totp-options' ).html( response.html );
} );
} );
})(jQuery);
</script>

<?php else : ?>
<p class="success">
<?php esc_html_e( 'An authenticator app is currently configured. You will need to re-scan the QR code on all devices if reset.', 'two-factor' ); ?>
Expand All @@ -384,23 +333,6 @@ public function user_two_factor_options( $user ) {
<button type="button" class="button button-secondary reset-totp-key hide-if-no-js">
<?php esc_html_e( 'Reset authenticator app', 'two-factor' ); ?>
</button>
<script>
( function( $ ) {
$( '.button.reset-totp-key' ).click( function( e ) {
e.preventDefault();

wp.apiRequest( {
method: 'DELETE',
path: <?php echo wp_json_encode( Two_Factor_Core::REST_NAMESPACE . '/totp' ); ?>,
data: {
user_id: <?php echo wp_json_encode( $user->ID ); ?>,
}
} ).then( function( response ) {
$( '#two-factor-totp-options' ).html( response.html );
} );
} );
} )( jQuery );
</script>
</p>
<?php endif; ?>
</div>
Expand Down
4 changes: 2 additions & 2 deletions tests/providers/class-two-factor-backup-codes.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ public function test_user_options() {
$this->provider->user_options( $user );
$buffer = ob_get_clean();

$this->assertStringContainsString( '<p id="two-factor-backup-codes">', $buffer );
$this->assertStringContainsString( '<div id="two-factor-backup-codes"', $buffer );
$this->assertStringContainsString( '<div class="two-factor-backup-codes-wrapper" style="display:none;">', $buffer );
$this->assertStringContainsString( "user_id: {$user->ID}", $buffer );
$this->assertStringContainsString( "data-userid=\"{$user->ID}\"", $buffer );
}

/**
Expand Down