Updates to the 'Log out everywhere' implementation.

* Include a message and a disabled button when you're only logged in at one location.
 * Avoid leaking the session token in HTML.
 * Simplify, simplify, simplify.

see #30264.

Built from https://develop.svn.wordpress.org/trunk@30888


git-svn-id: http://core.svn.wordpress.org/trunk@30878 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Andrew Nacin 2014-12-16 09:15:23 +00:00
parent 6abad25e05
commit 23f4b0f62f
9 changed files with 45 additions and 67 deletions

View File

@ -1265,7 +1265,8 @@ div.error {
.notice p,
div.updated p,
div.error p {
div.error p,
.form-table td .notice p {
margin: 0.5em 0;
padding: 2px;
}

View File

@ -1265,7 +1265,8 @@ div.error {
.notice p,
div.updated p,
div.error p {
div.error p,
.form-table td .notice p {
margin: 0.5em 0;
padding: 2px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2771,42 +2771,25 @@ function wp_ajax_parse_media_shortcode() {
*/
function wp_ajax_destroy_sessions() {
if ( empty( $_POST['user_id'] ) ) {
$user = new WP_Error();
} else {
$user = new WP_User( absint( $_POST['user_id'] ) );
if ( ! $user->exists() ) {
$user = new WP_Error();
} elseif ( ! current_user_can( 'edit_user', $user->ID ) ) {
$user = new WP_Error();
} elseif ( ! check_ajax_referer( sprintf( 'destroy_sessions_%d', $user->ID ), false, false ) ) {
$user = new WP_Error();
$user = get_userdata( (int) $_POST['user_id'] );
if ( $user ) {
if ( ! current_user_can( 'edit_user', $user->ID ) ) {
$user = false;
} elseif ( ! wp_verify_nonce( $_POST['nonce'], 'update-user_' . $user->ID ) ) {
$user = false;
}
}
if ( is_wp_error( $user ) ) {
if ( ! $user ) {
wp_send_json_error( array(
'message' => __( 'Could not log out user sessions. Please try again.' ),
) );
}
// 'token' is only set if the initiating user is viewing their own profile-editing screen.
if ( isset( $_POST['token'] ) ) {
$keep = wp_unslash( $_POST['token'] );
} else {
$keep = null;
}
$sessions = WP_Session_Tokens::get_instance( $user->ID );
/*
* If $keep is a string, then the current user is destroying all of their own sessions
* except the current one. If $keep is not a string, the current user is destroying all
* of another user's sessions with no exceptions.
*/
if ( is_string( $keep ) ) {
$sessions->destroy_others( $keep );
if ( $user->ID === get_current_user_id() ) {
$sessions->destroy_others( wp_get_session_token() );
$message = __( 'You are now logged out everywhere else.' );
} else {
$sessions->destroy_all();
@ -2814,8 +2797,5 @@ function wp_ajax_destroy_sessions() {
$message = sprintf( __( '%s has been logged out.' ), $user->display_name );
}
wp_send_json_success( array(
'message' => $message
) );
wp_send_json_success( array( 'message' => $message ) );
}

View File

@ -1,4 +1,4 @@
/* global ajaxurl, pwsL10n, _wpSessionMangager */
/* global ajaxurl, pwsL10n */
(function($){
function check_pass_strength() {
@ -125,25 +125,19 @@
});
$( '#destroy-sessions' ).on( 'click', function( e ) {
var $this = $(this);
var data = {
action : 'destroy-sessions',
_ajax_nonce : _wpSessionMangager.nonce,
user_id : _wpSessionMangager.user_id,
token : $(this).data('token')
};
$.post( ajaxurl, data, function( response ) {
if ( response.success ) {
$this.prop( 'disabled', true );
$this.before( '<div class="updated inline"><p>' + response.data.message + '</p></div>' );
} else {
$this.before( '<div class="error inline"><p>' + response.data.message + '</p></div>' );
}
}, 'json' );
wp.ajax.post( 'destroy-sessions', {
nonce: $( '#_wpnonce' ).val(),
user_id: $( '#user_id' ).val()
}).done( function( response ) {
$this.prop( 'disabled', true );
$this.siblings( '.notice' ).remove();
$this.before( '<div class="notice notice-success inline"><p>' + response.message + '</p></div>' );
}).fail( function( response ) {
$this.siblings( '.notice' ).remove();
$this.before( '<div class="notice notice-error inline"><p>' + response.message + '</p></div>' );
});
e.preventDefault();
});

View File

@ -1 +1 @@
!function(a){function b(){var b,c=a("#pass1").val(),d=a("#pass2").val();if(a("#pass-strength-result").removeClass("short bad good strong"),!c)return void a("#pass-strength-result").html(pwsL10n.empty);switch(b=wp.passwordStrength.meter(c,wp.passwordStrength.userInputBlacklist(),d)){case 2:a("#pass-strength-result").addClass("bad").html(pwsL10n.bad);break;case 3:a("#pass-strength-result").addClass("good").html(pwsL10n.good);break;case 4:a("#pass-strength-result").addClass("strong").html(pwsL10n.strong);break;case 5:a("#pass-strength-result").addClass("short").html(pwsL10n.mismatch);break;default:a("#pass-strength-result").addClass("short").html(pwsL10n["short"])}}a(document).ready(function(){var c,d,e,f,g=a("#display_name");a("#pass1").val("").keyup(b),a("#pass2").val("").keyup(b),a("#pass-strength-result").show(),a(".color-palette").click(function(){a(this).siblings('input[name="admin_color"]').prop("checked",!0)}),g.length&&a("#first_name, #last_name, #nickname").bind("blur.user_profile",function(){var b=[],c={display_nickname:a("#nickname").val()||"",display_username:a("#user_login").val()||"",display_firstname:a("#first_name").val()||"",display_lastname:a("#last_name").val()||""};c.display_firstname&&c.display_lastname&&(c.display_firstlast=c.display_firstname+" "+c.display_lastname,c.display_lastfirst=c.display_lastname+" "+c.display_firstname),a.each(a("option",g),function(a,c){b.push(c.value)}),a.each(c,function(d,e){if(e){var f=e.replace(/<\/?[a-z][^>]*>/gi,"");c[d].length&&-1===a.inArray(f,b)&&(b.push(f),a("<option />",{text:f}).appendTo(g))}})}),c=a("#color-picker"),d=a("#colors-css"),e=a("input#user_id").val(),f=a('input[name="checkuser_id"]').val(),c.on("click.colorpicker",".color-option",function(){var b,c=a(this);if(!c.hasClass("selected")&&(c.siblings(".selected").removeClass("selected"),c.addClass("selected").find('input[type="radio"]').prop("checked",!0),e===f)){if(0===d.length&&(d=a('<link rel="stylesheet" />').appendTo("head")),d.attr("href",c.children(".css_url").val()),"undefined"!=typeof wp&&wp.svgPainter){try{b=a.parseJSON(c.children(".icon_colors").val())}catch(g){}b&&(wp.svgPainter.setColors(b),wp.svgPainter.paint())}a.post(ajaxurl,{action:"save-user-color-scheme",color_scheme:c.children('input[name="admin_color"]').val(),nonce:a("#color-nonce").val()})}})}),a("#destroy-sessions").on("click",function(b){var c=a(this),d={action:"destroy-sessions",_ajax_nonce:_wpSessionMangager.nonce,user_id:_wpSessionMangager.user_id,token:a(this).data("token")};a.post(ajaxurl,d,function(a){a.success?(c.prop("disabled",!0),c.before('<div class="updated inline"><p>'+a.data.message+"</p></div>")):c.before('<div class="error inline"><p>'+a.data.message+"</p></div>")},"json"),b.preventDefault()})}(jQuery);
!function(a){function b(){var b,c=a("#pass1").val(),d=a("#pass2").val();if(a("#pass-strength-result").removeClass("short bad good strong"),!c)return void a("#pass-strength-result").html(pwsL10n.empty);switch(b=wp.passwordStrength.meter(c,wp.passwordStrength.userInputBlacklist(),d)){case 2:a("#pass-strength-result").addClass("bad").html(pwsL10n.bad);break;case 3:a("#pass-strength-result").addClass("good").html(pwsL10n.good);break;case 4:a("#pass-strength-result").addClass("strong").html(pwsL10n.strong);break;case 5:a("#pass-strength-result").addClass("short").html(pwsL10n.mismatch);break;default:a("#pass-strength-result").addClass("short").html(pwsL10n["short"])}}a(document).ready(function(){var c,d,e,f,g=a("#display_name");a("#pass1").val("").keyup(b),a("#pass2").val("").keyup(b),a("#pass-strength-result").show(),a(".color-palette").click(function(){a(this).siblings('input[name="admin_color"]').prop("checked",!0)}),g.length&&a("#first_name, #last_name, #nickname").bind("blur.user_profile",function(){var b=[],c={display_nickname:a("#nickname").val()||"",display_username:a("#user_login").val()||"",display_firstname:a("#first_name").val()||"",display_lastname:a("#last_name").val()||""};c.display_firstname&&c.display_lastname&&(c.display_firstlast=c.display_firstname+" "+c.display_lastname,c.display_lastfirst=c.display_lastname+" "+c.display_firstname),a.each(a("option",g),function(a,c){b.push(c.value)}),a.each(c,function(d,e){if(e){var f=e.replace(/<\/?[a-z][^>]*>/gi,"");c[d].length&&-1===a.inArray(f,b)&&(b.push(f),a("<option />",{text:f}).appendTo(g))}})}),c=a("#color-picker"),d=a("#colors-css"),e=a("input#user_id").val(),f=a('input[name="checkuser_id"]').val(),c.on("click.colorpicker",".color-option",function(){var b,c=a(this);if(!c.hasClass("selected")&&(c.siblings(".selected").removeClass("selected"),c.addClass("selected").find('input[type="radio"]').prop("checked",!0),e===f)){if(0===d.length&&(d=a('<link rel="stylesheet" />').appendTo("head")),d.attr("href",c.children(".css_url").val()),"undefined"!=typeof wp&&wp.svgPainter){try{b=a.parseJSON(c.children(".icon_colors").val())}catch(g){}b&&(wp.svgPainter.setColors(b),wp.svgPainter.paint())}a.post(ajaxurl,{action:"save-user-color-scheme",color_scheme:c.children('input[name="admin_color"]').val(),nonce:a("#color-nonce").val()})}})}),a("#destroy-sessions").on("click",function(b){var c=a(this);wp.ajax.post("destroy-sessions",{nonce:a("#_wpnonce").val(),user_id:a("#user_id").val()}).done(function(a){c.prop("disabled",!0),c.siblings(".notice").remove(),c.before('<div class="notice notice-success inline"><p>'+a.message+"</p></div>")}).fail(function(a){c.siblings(".notice").remove(),c.before('<div class="notice notice-error inline"><p>'+a.message+"</p></div>")}),b.preventDefault()})}(jQuery);

View File

@ -25,15 +25,6 @@ elseif ( ! get_userdata( $user_id ) )
wp_enqueue_script('user-profile');
wp_localize_script(
'user-profile',
'_wpSessionMangager',
array(
'user_id' => $user_id,
'nonce' => wp_create_nonce( sprintf( 'destroy_sessions_%d', $user_id ) ),
)
);
$title = IS_PROFILE_PAGE ? __('Profile') : __('Edit User');
if ( current_user_can('edit_users') && !IS_PROFILE_PAGE )
$submenu_file = 'users.php';
@ -493,17 +484,28 @@ if ( $show_password_fields ) :
</tr>
<?php endif; ?>
<?php if ( IS_PROFILE_PAGE && ( count( $sessions->get_all() ) > 1 ) ) { ?>
<?php
if ( IS_PROFILE_PAGE && count( $sessions->get_all() ) === 1 ) : ?>
<tr class="user-sessions-wrap hide-if-no-js">
<th>&nbsp;</th>
<td aria-live="assertive">
<div class="destroy-sessions"><button class="button button-secondary" id="destroy-sessions" data-token="<?php echo esc_attr( wp_get_session_token() ); ?>"><?php _e( 'Log Out of All Other Sessions' ); ?></button></div>
<div class="destroy-sessions"><button disabled class="button button-secondary"><?php _e( 'Log Out of All Other Sessions' ); ?></button></div>
<p class="description">
<?php _e( 'You are only logged in at this location.' ); ?>
</p>
</td>
</tr>
<?php elseif ( IS_PROFILE_PAGE && count( $sessions->get_all() ) > 1 ) : ?>
<tr class="user-sessions-wrap hide-if-no-js">
<th>&nbsp;</th>
<td aria-live="assertive">
<div class="destroy-sessions"><button class="button button-secondary" id="destroy-sessions"><?php _e( 'Log Out of All Other Sessions' ); ?></button></div>
<p class="description">
<?php _e( 'Left your account logged in at a public computer? Lost your phone? This will log you out everywhere except your current browser.' ); ?>
</p>
</td>
</tr>
<?php } else if ( ! IS_PROFILE_PAGE && ( count( $sessions->get_all() ) > 0 ) ) { ?>
<?php elseif ( ! IS_PROFILE_PAGE && $sessions->get_all() ) : ?>
<tr class="user-sessions-wrap hide-if-no-js">
<th>&nbsp;</th>
<td>
@ -516,7 +518,7 @@ if ( $show_password_fields ) :
</p>
</td>
</tr>
<?php } ?>
<?php endif; ?>
</table>

View File

@ -349,7 +349,7 @@ function wp_default_scripts( &$scripts ) {
'mismatch' => __('Mismatch')
) );
$scripts->add( 'user-profile', "/wp-admin/js/user-profile$suffix.js", array( 'jquery', 'password-strength-meter' ), false, 1 );
$scripts->add( 'user-profile', "/wp-admin/js/user-profile$suffix.js", array( 'jquery', 'password-strength-meter', 'wp-util' ), false, 1 );
$scripts->add( 'language-chooser', "/wp-admin/js/language-chooser$suffix.js", array( 'jquery' ), false, 1 );
$scripts->add( 'user-suggest', "/wp-admin/js/user-suggest$suffix.js", array( 'jquery-ui-autocomplete' ), false, 1 );