mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-24 02:38:40 +00:00
mw.ViewPageTarget: Refetch token if session expired
* Rephrased visualeditor-savedialog-error-badtoken to emphasise that it is the old session that become invalid, not the one the user started browsing with since in a different window. * If the session changed, the user will be asked whether they agree to save with this new session instead. * We explictly update mw.config so that future save attempts in the same window compare against the correct environment. Without this there are two problems when saving and then making a second edit in the same window and saving that: - It will bring up the same question again (user A -> user B), which is annoying. - If the user logged back in again (new session, but for user A again) it would silently try with that new token without asking, thus saving as user A when the user still thinks it switched to user B. It switching back automatically is not obvious since we asked them from A->B, so we should also ask the other way around. This can be reproduced by opending ve-edit logged-in, then logging out in a new window, save, confirm anon, save, open edit again, log back in in a new window, save open edit in the old window, confirm new logged-in, save. Bug: 50424 Change-Id: Id055eca1886f85aeaf615f645de29898afc0373c
This commit is contained in:
parent
71504c3d15
commit
45c79f8c23
|
@ -141,7 +141,9 @@ $messages['en'] = array(
|
|||
'visualeditor-reference-search-reuse' => 'Use an existing source',
|
||||
'visualeditor-referencelist-isempty' => 'There are no references with the group "$1" on this page.',
|
||||
'visualeditor-referencelist-missingref' => 'This reference is defined in a template or other generated block, and for now can only be edited in source mode.',
|
||||
'visualeditor-savedialog-error-badtoken' => 'We could not process your edit because your session has expired.',
|
||||
'visualeditor-savedialog-error-badtoken' => 'We could not process your edit because the session was no longer valid.',
|
||||
'visualeditor-savedialog-identify-anon' => "Do you want to save this page as an anonymous user instead? Your IP address will be recorded in this page's edit history.",
|
||||
'visualeditor-savedialog-identify-user' => 'You are now logged in as [[User:$1|$1]]. Your edit will be associated with this account if you save this edit.',
|
||||
'visualeditor-savedialog-label-create' => 'Create page',
|
||||
'visualeditor-savedialog-label-error' => 'Error',
|
||||
'visualeditor-savedialog-label-report' => 'Report problem',
|
||||
|
@ -426,15 +428,22 @@ See also:
|
|||
'visualeditor-reference-search-reuse' => 'Label for section heading in results list for using an existing reference.
|
||||
|
||||
See also:
|
||||
* {{msg-mw|Visualeditor-reference-search-create}}',
|
||||
* {{msg-mw|visualeditor-reference-search-create}}',
|
||||
'visualeditor-referencelist-isempty' => 'Message that appears in the references list when there are no references on the page of that group.',
|
||||
'visualeditor-referencelist-missingref' => 'Message that appears in the references list, and as a tooltip on the reference itself, for references that are generated by a template or are otherwise uneditable.
|
||||
|
||||
See also:
|
||||
* {{msg-mw|Visualeditor-dialog-meta-languages-readonlynote}}',
|
||||
* {{msg-mw|visualeditor-dialog-meta-languages-readonlynote}}',
|
||||
'visualeditor-savedialog-error-badtoken' => 'Error displayed in the save dialog if saving the edit failed due to an invalid edit token (likely due to the user having logged out in a separate window, or logged in again)',
|
||||
'visualeditor-savedialog-label-create' => 'Label text for save button when the user is creating a new page.
|
||||
{{Identical|Create page}}',
|
||||
'visualeditor-savedialog-identify-anon' => 'Displayed in the save dialog if saving failed because the session expired and the session is now an anonymous user. Warning about IP address being recorded is based on {{mw-msg|anoneditwarning}}
|
||||
|
||||
{{format|jquerymsg}}',
|
||||
'visualeditor-savedialog-identify-user' => 'Displayed in the save dialog if saving failed because the session expired and the session is now for a different user account.
|
||||
|
||||
{{format|jquerymsg}}',
|
||||
'visualeditor-savedialog-label-create' => 'Label text for save button when the user is creating a new page',
|
||||
'visualeditor-savedialog-label-error' => 'Label in front of a save dialog error sentence, separated by {{msg-mw|colon-separator}}.
|
||||
{{Identical|Error}}',
|
||||
'visualeditor-savedialog-label-report' => 'Label for button to trigger report',
|
||||
|
|
|
@ -204,6 +204,7 @@ $wgResourceModules += array(
|
|||
'jquery.client',
|
||||
'jquery.placeholder',
|
||||
'jquery.visibleText',
|
||||
'mediawiki.api',
|
||||
'mediawiki.feedback',
|
||||
'mediawiki.jqueryMsg',
|
||||
'mediawiki.notify',
|
||||
|
@ -224,6 +225,8 @@ $wgResourceModules += array(
|
|||
'visualeditor-notification-created',
|
||||
'visualeditor-notification-restored',
|
||||
'visualeditor-notification-saved',
|
||||
'visualeditor-savedialog-identify-anon',
|
||||
'visualeditor-savedialog-identify-user',
|
||||
),
|
||||
),
|
||||
'ext.visualEditor.base' => $wgVisualEditorResourceTemplate + array(
|
||||
|
|
|
@ -432,7 +432,9 @@ ve.init.mw.ViewPageTarget.prototype.onSave = function ( html, newid ) {
|
|||
* @param {Object|null} data API response data
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.onSaveError = function ( jqXHR, status, data ) {
|
||||
var editApi;
|
||||
var api, editApi,
|
||||
viewPage = this;
|
||||
|
||||
this.saveDialogSaveButton.setDisabled( false );
|
||||
this.$saveDialogLoadingIcon.hide();
|
||||
|
||||
|
@ -487,14 +489,91 @@ ve.init.mw.ViewPageTarget.prototype.onSaveError = function ( jqXHR, status, data
|
|||
|
||||
// Handle token errors
|
||||
if ( data.error && data.error.code === 'badtoken' ) {
|
||||
this.showMessage(
|
||||
'api-save-error',
|
||||
document.createTextNode( mw.msg( 'visualeditor-savedialog-error-badtoken' ) ),
|
||||
{
|
||||
wrap: 'error'
|
||||
}
|
||||
);
|
||||
this.saveDialogSaveButton.setDisabled( true );
|
||||
api = new mw.Api();
|
||||
viewPage.saveDialogSaveButton.setDisabled( true );
|
||||
viewPage.$saveDialogLoadingIcon.show();
|
||||
api.get( {
|
||||
// action=query&meta=userinfo and action=tokens&type=edit can't be combined
|
||||
// but action=query&meta=userinfo and action=query&prop=info can, however
|
||||
// that means we have to give it titles and deal with page ids.
|
||||
'action': 'query',
|
||||
'meta': 'userinfo',
|
||||
'prop': 'info',
|
||||
// Try to send the normalised form so that it is less likely we get extra data like
|
||||
// data.normalised back that we don't need.
|
||||
'titles': new mw.Title( viewPage.pageName ).toText(),
|
||||
'indexpageids': '',
|
||||
'intoken': 'edit'
|
||||
} )
|
||||
.always( function () {
|
||||
viewPage.$saveDialogLoadingIcon.hide();
|
||||
} )
|
||||
.done( function ( data ) {
|
||||
var badTokenText, userMsg,
|
||||
userInfo = data.query && data.query.userinfo,
|
||||
pageInfo = data.query && data.query.pages && data.query.pageids &&
|
||||
data.query.pageids[0] && data.query.pages[ data.query.pageids[0] ],
|
||||
editToken = pageInfo && pageInfo.edittoken;
|
||||
|
||||
if ( userInfo && editToken ) {
|
||||
viewPage.editToken = editToken;
|
||||
|
||||
if (
|
||||
( mw.user.isAnon() && userInfo.anon !== undefined ) ||
|
||||
// Comparing id instead of name to pretect against possible
|
||||
// normalisation and against case where the user got renamed.
|
||||
mw.config.get( 'wgUserId' ) === userInfo.id
|
||||
) {
|
||||
// New session is the same user still
|
||||
viewPage.saveDocument();
|
||||
} else {
|
||||
// The now current session is a different user
|
||||
viewPage.saveDialogSaveButton.setDisabled( false );
|
||||
|
||||
// Trailing space is to separate from the other message.
|
||||
badTokenText = document.createTextNode( mw.msg( 'visualeditor-savedialog-error-badtoken' ) + ' ' );
|
||||
|
||||
if ( userInfo.anon !== undefined ) {
|
||||
// New session is an anonymous user
|
||||
mw.config.set( {
|
||||
// wgUserId is unset for anonymous users, not set to null
|
||||
'wgUserId': undefined,
|
||||
// wgUserName is explicitly set to null for anonymous users,
|
||||
// functions like mw.user.isAnon rely on this.
|
||||
'wgUserName': null
|
||||
} );
|
||||
|
||||
viewPage.showMessage(
|
||||
'api-save-error',
|
||||
$( badTokenText ).add(
|
||||
$.parseHTML( mw.message( 'visualeditor-savedialog-identify-anon' ).parse() )
|
||||
),
|
||||
{ wrap: 'warning' }
|
||||
);
|
||||
} else {
|
||||
// New session is a different user
|
||||
mw.config.set( { 'wgUserId': userInfo.id, 'wgUserName': userInfo.name } );
|
||||
|
||||
// mediawiki.jqueryMsg has a bug with [[User:$1|$1]] (bug 51388)
|
||||
userMsg = 'visualeditor-savedialog-identify-user---' + userInfo.name;
|
||||
mw.messages.set(
|
||||
userMsg,
|
||||
mw.messages.get( 'visualeditor-savedialog-identify-user' )
|
||||
.replace( /\$1/g, userInfo.name )
|
||||
);
|
||||
|
||||
viewPage.showMessage(
|
||||
'api-save-error',
|
||||
$( badTokenText ).add(
|
||||
$.parseHTML( mw.message( userMsg ).parse() )
|
||||
),
|
||||
{ wrap: 'warning' }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -767,6 +846,13 @@ ve.init.mw.ViewPageTarget.prototype.onSaveDialogReviewButtonClick = function ()
|
|||
* @method
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.onSaveDialogSaveButtonClick = function () {
|
||||
this.saveDocument();
|
||||
};
|
||||
|
||||
/**
|
||||
* Try to save the current document.
|
||||
*/
|
||||
ve.init.mw.ViewPageTarget.prototype.saveDocument = function () {
|
||||
var doc = this.surface.getModel().getDocument(),
|
||||
saveOptions = this.getSaveOptions();
|
||||
|
||||
|
|
Loading…
Reference in a new issue