mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-12 09:09:25 +00:00
Clean up code related to token and bad token handling
Things I noticed while writing I37f8e89b6d92c419d1b6569891612256342f8139, but which felt too messy to include in that commit. * Use promise chaining * Update documentation * Remove redundant code * Split a method that now handles two different errors * Grumble about localisation messages Change-Id: I81e28a03af4f6c3452679ef6bbcaa89bb1235122
This commit is contained in:
parent
58757d4e3e
commit
8065fdf2b9
|
@ -784,22 +784,20 @@ ve.init.mw.ArticleTarget.prototype.saveErrorHookAborted = function ( data ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle assert error indicating another user is logged in, and token fetch errors.
|
* Handle assert error indicating another user is logged in.
|
||||||
*
|
*
|
||||||
* @param {string|null} username Name of newly logged-in user, or null if anonymous
|
* @param {string|null} username Name of newly logged-in user, or null if anonymous
|
||||||
* @param {boolean} [error=false] Whether this is a token fetch error
|
|
||||||
* @fires saveErrorBadToken
|
|
||||||
* @fires saveErrorNewUser
|
* @fires saveErrorNewUser
|
||||||
*/
|
*/
|
||||||
ve.init.mw.ArticleTarget.prototype.saveErrorBadTokenOrNewUser = function ( username, error ) {
|
ve.init.mw.ArticleTarget.prototype.saveErrorNewUser = function ( username ) {
|
||||||
var $msg = $( document.createTextNode( mw.msg( 'visualeditor-savedialog-error-badtoken' ) + ' ' ) );
|
var $msg;
|
||||||
|
|
||||||
if ( error ) {
|
|
||||||
this.emit( 'saveErrorBadToken', false );
|
|
||||||
$msg = $msg.add( document.createTextNode( mw.msg( 'visualeditor-savedialog-identify-trylogin' ) ) );
|
|
||||||
} else {
|
|
||||||
this.emit( 'saveErrorNewUser' );
|
this.emit( 'saveErrorNewUser' );
|
||||||
$msg = $msg.add(
|
|
||||||
|
// TODO: Improve this message, concatenating it this way is a bad practice.
|
||||||
|
// This should read more like 'session_fail_preview' in MediaWiki core
|
||||||
|
// (but with the caveat that we know already whether you're logged in or not).
|
||||||
|
$msg = $( document.createTextNode( mw.msg( 'visualeditor-savedialog-error-badtoken' ) + ' ' ) ).add(
|
||||||
mw.message(
|
mw.message(
|
||||||
username === null ?
|
username === null ?
|
||||||
'visualeditor-savedialog-identify-anon' :
|
'visualeditor-savedialog-identify-anon' :
|
||||||
|
@ -807,10 +805,27 @@ ve.init.mw.ArticleTarget.prototype.saveErrorBadTokenOrNewUser = function ( usern
|
||||||
username
|
username
|
||||||
).parseDom()
|
).parseDom()
|
||||||
);
|
);
|
||||||
}
|
|
||||||
this.showSaveError( $msg );
|
this.showSaveError( $msg );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle token fetch errors.
|
||||||
|
*
|
||||||
|
* @fires saveErrorBadToken
|
||||||
|
*/
|
||||||
|
ve.init.mw.ArticleTarget.prototype.saveErrorBadToken = function () {
|
||||||
|
this.emit( 'saveErrorBadToken', false );
|
||||||
|
|
||||||
|
// TODO: Improve this message, concatenating it this way is a bad practice.
|
||||||
|
// Also, it's not always true that you're "no longer logged in".
|
||||||
|
// This should read more like 'session_fail_preview' in MediaWiki core.
|
||||||
|
this.showSaveError(
|
||||||
|
mw.msg( 'visualeditor-savedialog-error-badtoken' ) + ' ' +
|
||||||
|
mw.msg( 'visualeditor-savedialog-identify-trylogin' )
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle unknown save error
|
* Handle unknown save error
|
||||||
*
|
*
|
||||||
|
@ -1264,10 +1279,8 @@ ve.init.mw.ArticleTarget.prototype.clearPreparedCacheKey = function () {
|
||||||
* HTML directly if there is no cache key present or pending, or if the request for the cache key
|
* HTML directly if there is no cache key present or pending, or if the request for the cache key
|
||||||
* fails, or if using the cache key fails with a badcachekey error.
|
* fails, or if using the cache key fails with a badcachekey error.
|
||||||
*
|
*
|
||||||
* If extraData.token is set, this function will use mw.Api#post and let the caller handle badtoken
|
* This function will use mw.Api#postWithToken to retry automatically when encountering a 'badtoken'
|
||||||
* errors. If extraData.token is not set, this function will use mw.Api#postWithToken which retries
|
* error.
|
||||||
* automatically when encountering a badtoken error. If you do not want the automatic retry behavior
|
|
||||||
* and want to control badtoken retries, you have to set extradata.token.
|
|
||||||
*
|
*
|
||||||
* @param {HTMLDocument|string} doc Document to submit or string in source mode
|
* @param {HTMLDocument|string} doc Document to submit or string in source mode
|
||||||
* @param {Object} extraData POST parameters to send. Do not include 'html', 'cachekey' or 'format'.
|
* @param {Object} extraData POST parameters to send. Do not include 'html', 'cachekey' or 'format'.
|
||||||
|
|
|
@ -461,28 +461,16 @@ ve.init.mw.Target.prototype.teardown = function () {
|
||||||
* @return {jQuery.Promise} Promise resolved with new username, or null if anonymous
|
* @return {jQuery.Promise} Promise resolved with new username, or null if anonymous
|
||||||
*/
|
*/
|
||||||
ve.init.mw.Target.prototype.refreshUser = function ( doc ) {
|
ve.init.mw.Target.prototype.refreshUser = function ( doc ) {
|
||||||
var api = this.getContentApi( doc ),
|
return this.getContentApi( doc ).get( {
|
||||||
deferred = ve.createDeferred();
|
|
||||||
api.get( {
|
|
||||||
action: 'query',
|
action: 'query',
|
||||||
meta: 'userinfo'
|
meta: 'userinfo'
|
||||||
} )
|
} ).then( function ( data ) {
|
||||||
.done( function ( data ) {
|
var userInfo = data.query && data.query.userinfo;
|
||||||
var
|
|
||||||
userInfo = data.query && data.query.userinfo,
|
if ( !userInfo ) {
|
||||||
isAnon = mw.user.isAnon();
|
return ve.createDeferred().reject();
|
||||||
|
}
|
||||||
|
|
||||||
if ( userInfo ) {
|
|
||||||
if (
|
|
||||||
( isAnon && userInfo.anon !== undefined ) ||
|
|
||||||
// Comparing id instead of name to protect against possible
|
|
||||||
// normalisation and against case where the user got renamed.
|
|
||||||
mw.config.get( 'wgUserId' ) === userInfo.id
|
|
||||||
) {
|
|
||||||
// New session is the same user still
|
|
||||||
deferred.resolve( mw.user.getName() );
|
|
||||||
} else {
|
|
||||||
// The now current session is a different user
|
|
||||||
if ( userInfo.anon !== undefined ) {
|
if ( userInfo.anon !== undefined ) {
|
||||||
// New session is an anonymous user
|
// New session is an anonymous user
|
||||||
mw.config.set( {
|
mw.config.set( {
|
||||||
|
@ -493,19 +481,15 @@ ve.init.mw.Target.prototype.refreshUser = function ( doc ) {
|
||||||
wgUserName: null
|
wgUserName: null
|
||||||
} );
|
} );
|
||||||
} else {
|
} else {
|
||||||
// New session is a different user
|
// New session is a logged in user
|
||||||
mw.config.set( { wgUserId: userInfo.id, wgUserName: userInfo.name } );
|
mw.config.set( {
|
||||||
}
|
wgUserId: userInfo.id,
|
||||||
deferred.resolve( mw.user.getName() );
|
wgUserName: userInfo.name
|
||||||
}
|
} );
|
||||||
} else {
|
}
|
||||||
deferred.reject();
|
|
||||||
}
|
return mw.user.getName();
|
||||||
} )
|
|
||||||
.fail( function () {
|
|
||||||
deferred.reject();
|
|
||||||
} );
|
} );
|
||||||
return deferred.promise();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -516,7 +500,7 @@ ve.init.mw.Target.prototype.refreshUser = function ( doc ) {
|
||||||
* @return {jQuery.Promise} Abortable promise which resolves with a wikitext string
|
* @return {jQuery.Promise} Abortable promise which resolves with a wikitext string
|
||||||
*/
|
*/
|
||||||
ve.init.mw.Target.prototype.getWikitextFragment = function ( doc, useRevision ) {
|
ve.init.mw.Target.prototype.getWikitextFragment = function ( doc, useRevision ) {
|
||||||
var promise, xhr,
|
var xhr,
|
||||||
params = {
|
params = {
|
||||||
action: 'visualeditoredit',
|
action: 'visualeditoredit',
|
||||||
paction: 'serialize',
|
paction: 'serialize',
|
||||||
|
@ -539,18 +523,12 @@ ve.init.mw.Target.prototype.getWikitextFragment = function ( doc, useRevision )
|
||||||
{ contentType: 'multipart/form-data' }
|
{ contentType: 'multipart/form-data' }
|
||||||
);
|
);
|
||||||
|
|
||||||
promise = xhr.then( function ( response ) {
|
return xhr.then( function ( response ) {
|
||||||
if ( response.visualeditoredit ) {
|
if ( response.visualeditoredit ) {
|
||||||
return response.visualeditoredit.content;
|
return response.visualeditoredit.content;
|
||||||
}
|
}
|
||||||
return ve.createDeferred().reject();
|
return ve.createDeferred().reject();
|
||||||
} );
|
} ).promise( { abort: xhr.abort } );
|
||||||
|
|
||||||
promise.abort = function () {
|
|
||||||
xhr.abort();
|
|
||||||
};
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -195,7 +195,8 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post content to the API.
|
* Post content to the API, using mw.Api#postWithToken to retry automatically when encountering
|
||||||
|
* a 'badtoken' error.
|
||||||
*
|
*
|
||||||
* By default uses action=visualeditoredit, paction=save.
|
* By default uses action=visualeditoredit, paction=save.
|
||||||
*
|
*
|
||||||
|
@ -230,11 +231,8 @@
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( data.token ) {
|
|
||||||
request = api.post( data, { contentType: 'multipart/form-data' } );
|
|
||||||
} else {
|
|
||||||
request = api.postWithToken( 'csrf', data, { contentType: 'multipart/form-data' } );
|
request = api.postWithToken( 'csrf', data, { contentType: 'multipart/form-data' } );
|
||||||
}
|
|
||||||
return request.then(
|
return request.then(
|
||||||
function ( response, jqxhr ) {
|
function ( response, jqxhr ) {
|
||||||
var eventData, fullEventName, error,
|
var eventData, fullEventName, error,
|
||||||
|
|
Loading…
Reference in a new issue