jenkins-bot has submitted this change and it was merged. Change subject: ForeignApi: Allow posting for anonymous users ......................................................................
ForeignApi: Allow posting for anonymous users When a user is logged out, get a CSRF token from the remote wiki and make a POST request using it. Bug: T95960 Change-Id: Ic5afa3a78c91fd374278aa28296e5560db29f85a --- M resources/mobile.foreignApi/ForeignApi.js A tests/qunit/modules/test_ForeignApi.js 2 files changed, 76 insertions(+), 10 deletions(-) Approvals: Phuedx: Looks good to me, approved jenkins-bot: Verified diff --git a/resources/mobile.foreignApi/ForeignApi.js b/resources/mobile.foreignApi/ForeignApi.js index 62a7680..2e762b3 100644 --- a/resources/mobile.foreignApi/ForeignApi.js +++ b/resources/mobile.foreignApi/ForeignApi.js @@ -46,6 +46,7 @@ }, /** * Post to API with support for central auth tokens + * If the user is anonymous, then post using the csrftoken received from the remote wiki. * @param {String} tokenType Ignored. `'csrf'` is always used * @param {Object} data Data to be preprocessed and added to options * @param {Object} options Parameters passed to $.ajax() @@ -56,27 +57,51 @@ d = $.Deferred(); options = options || {}; + options.xhrFields = { + withCredentials: true + }; + // In case it is a file upload we need to append origin to query string. + options.url = self.apiUrl + '?origin=' + self.getOrigin(); + + data.origin = self.getOrigin(); + // first let's sort out the token self.getCentralAuthToken().done( function ( centralAuthTokenOne ) { self.getToken( tokenType, centralAuthTokenOne ).done( function ( token ) { self.getCentralAuthToken().done( function ( centralAuthTokenTwo ) { - data.format = 'json'; data.centralauthtoken = centralAuthTokenTwo; data.token = token; - data.origin = self.getOrigin(); - - options.xhrFields = { - withCredentials: true - }; - // In case it is a file upload we need to append origin to query string. - options.url = self.apiUrl + '?origin=' + self.getOrigin(); - Api.prototype.post.call( self, data, options ).done( function ( resp ) { d.resolve( resp ); } ).fail( $.proxy( d, 'reject' ) ); } ).fail( $.proxy( d, 'reject' ) ); } ).fail( $.proxy( d, 'reject' ) ); - } ).fail( $.proxy( d, 'reject' ) ); + } ).fail( function ( code ) { + if ( code !== 'notloggedin' ) { + d.reject(); + return; + } + // So the user is not logged in locally. + // Get the remote CSRF token + Api.prototype.ajax.call( + self, { + action: 'query', + meta: 'tokens', + type: 'csrf' + }, { + url: options.url + } + ).done( function ( resp ) { + if ( resp.query && resp.query.tokens && resp.query.tokens.csrftoken ) { + data.token = resp.query.tokens.csrftoken; + Api.prototype.post.call( self, data, options ).done( function ( resp ) { + d.resolve( resp ); + } ).fail( $.proxy( d, 'reject' ) ); + } else { + d.reject(); + } + } ).fail( $.proxy( d, 'reject' ) ); + } ); return d; }, /** @inheritdoc */ diff --git a/tests/qunit/modules/test_ForeignApi.js b/tests/qunit/modules/test_ForeignApi.js new file mode 100644 index 0000000..65904a9 --- /dev/null +++ b/tests/qunit/modules/test_ForeignApi.js @@ -0,0 +1,41 @@ +( function ( M, $ ) { + var ForeignApi = M.require( 'modules/ForeignApi' ), + api = M.require( 'api' ); + + QUnit.module( 'MobileFrontend ForeignApi' ); + + // Test whether postWithToken() works when the user is logged out + QUnit.test( '#postWithToken - anon', 1, function ( assert ) { + var self = this, + foreignApi = new ForeignApi(), + editToken = mw.user.tokens.get( 'editToken' ), + spy = this.sandbox.spy( api.Api.prototype, 'post' ); + + // Make sure the central auth token cannot be received + this.stub( foreignApi, 'getCentralAuthToken' ).returns( + $.Deferred().rejectWith( self, [ 'notloggedin' ] ) + ); + + // And ajax must return the csrftoken + this.stub( api.Api.prototype, 'ajax' ).returns( + $.Deferred().resolveWith( self, [ { + query: { + tokens: { + csrftoken: editToken + } + } + } ] ) + ); + + // Now, let's post some data + foreignApi.postWithToken( 'csrf', { some: 'data' }, {} ); + + // POST must be called with the editToken, and not with the centralAuthToken + assert.ok( spy.calledWith( { + origin: foreignApi.getOrigin(), + some: 'data', + token: editToken + } ), 'Posting to ForeignApi with token when the user is logged out works!' ); + } ); + +}( mw.mobileFrontend, jQuery ) ); -- To view, visit https://gerrit.wikimedia.org/r/211884 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ic5afa3a78c91fd374278aa28296e5560db29f85a Gerrit-PatchSet: 7 Gerrit-Project: mediawiki/extensions/MobileFrontend Gerrit-Branch: master Gerrit-Owner: Bmansurov <bmansu...@wikimedia.org> Gerrit-Reviewer: Anomie <bjor...@wikimedia.org> Gerrit-Reviewer: Bmansurov <bmansu...@wikimedia.org> Gerrit-Reviewer: Jdlrobson <jrob...@wikimedia.org> Gerrit-Reviewer: Kaldari <rkald...@wikimedia.org> Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com> Gerrit-Reviewer: Phuedx <g...@samsmith.io> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits