Alex Monk has submitted this change and it was merged. Change subject: Fix CAPTCHA on new editors ......................................................................
Fix CAPTCHA on new editors Previously, the CAPTCHA error showed the raw HTML, and also there was no way to submit the CAPTCHA. * Standardize on onEditorSaveContent * Pass specific i18n message related to the spam filter flag to the API response so we know which ones it's safe to treat as HTML. Bug: T109554 Change-Id: I5df07700540898c7997b9ad0d8c5f81f3b6af721 (cherry picked from commit 890bef9de619abd974cd617f5a96afd6b1486b89) --- M includes/Block/Block.php M modules/flow/dm/api/mw.flow.dm.APIHandler.js M modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js M modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js M modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js 5 files changed, 108 insertions(+), 24 deletions(-) Approvals: Alex Monk: Verified; Looks good to me, approved diff --git a/includes/Block/Block.php b/includes/Block/Block.php index ccc5740..9d47053 100644 --- a/includes/Block/Block.php +++ b/includes/Block/Block.php @@ -329,7 +329,8 @@ return true; } - $this->addError( 'spamfilter', $status->getMessage() ); + $message = $status->getMessage(); + $this->addError( 'spamfilter', $message, $message->getKey() ); return false; } diff --git a/modules/flow/dm/api/mw.flow.dm.APIHandler.js b/modules/flow/dm/api/mw.flow.dm.APIHandler.js index 71324bd..13b4bbc 100644 --- a/modules/flow/dm/api/mw.flow.dm.APIHandler.js +++ b/modules/flow/dm/api/mw.flow.dm.APIHandler.js @@ -112,16 +112,32 @@ }; /** + * Adds CAPTCHA to parameters if applicable + * + * @param {Object} captcha CAPTCHA object + * @param {string} id CAPTCHA ID + * @param {string} answer CAPTCHA answer (user-provided) + */ + mw.flow.dm.APIHandler.prototype.addCaptcha = function ( params, captcha ) { + // TODO: Find a better way to plug this in. + if ( captcha ) { + params.wpCaptchaId = captcha.id; + params.wpCaptchaWord = captcha.answer; + } + }; + + /** * Send an edit request to the API to save a reply. * * @param {string} topicId Topic Id * @param {string} replyTo The parent of this reply * @param {string} content Reply content * @param {string} format Reply content format + * @param {Object} [captcha] CAPTCHA information * @return {jQuery.Promise} Promise that is resolved with the id of the workflow * that this reply belongs to */ - mw.flow.dm.APIHandler.prototype.saveReply = function ( topicId, replyTo, content, format ) { + mw.flow.dm.APIHandler.prototype.saveReply = function ( topicId, replyTo, content, format, captcha ) { var params = { action: 'flow', submodule: 'reply', @@ -130,6 +146,8 @@ repcontent: content, repformat: format }; + + this.addCaptcha( params, captcha ); return ( new mw.Api() ).postWithToken( 'edit', params ) .then( function ( data ) { @@ -143,9 +161,10 @@ * @param {string} title Topic title * @param {string} content Topic content * @param {string} format Content format + * @param {Object} [captcha] CAPTCHA information * @return {jQuery.Promise} Promise that is resolved with the new topic id */ - mw.flow.dm.APIHandler.prototype.saveNewTopic = function ( title, content, format ) { + mw.flow.dm.APIHandler.prototype.saveNewTopic = function ( title, content, format, captcha ) { var params = { action: 'flow', submodule: 'new-topic', @@ -154,6 +173,8 @@ ntcontent: content, ntformat: format }; + + this.addCaptcha( params, captcha ); return ( new mw.Api() ).postWithToken( 'edit', params ) .then( function ( response ) { @@ -183,10 +204,11 @@ * Save header information. * * @param {string} content Header content - * @param {string} [format='fixed-html'] Content format for board description + * @param {string} format Content format for board description + * @param {string} [captcha] CAPTCHA information * @return {jQuery.Promise} Promise that is resolved with the saved header revision id */ - mw.flow.dm.APIHandler.prototype.saveDescription = function ( content, format ) { + mw.flow.dm.APIHandler.prototype.saveDescription = function ( content, format, captcha ) { var xhr, params = { page: this.page, @@ -195,6 +217,8 @@ ehprev_revision: this.currentRevision }; + this.addCaptcha( params, captcha ); + // return ( new mw.Api() ).postWithToken( 'edit', params ) xhr = this.postEdit( 'edit-header', params ) .then( function ( data ) { diff --git a/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js b/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js index be91978..185d7c7 100644 --- a/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js +++ b/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js @@ -160,10 +160,23 @@ * @param {string} contentFormat Format of content */ mw.flow.ui.BoardDescriptionWidget.prototype.onEditorSaveContent = function ( content, format ) { - var widget = this; + var widget = this, + $captchaField, captcha; this.editor.pushPending(); - this.api.saveDescription( content, format ) + + $captchaField = this.error.$label.find( '[name="wpCaptchaWord"]' ); + if ( $captchaField.length > 0 ) { + captcha = { + id: this.error.$label.find( '[name="wpCaptchaId"]' ).val(), + answer: $captchaField.val() + }; + } + + this.error.setLabel( '' ); + this.error.toggle( false ); + + this.api.saveDescription( content, format, captcha ) .then( function ( newRevisionId ) { // Update revisionId in the API widget.api.setCurrentRevision( newRevisionId ); @@ -177,8 +190,15 @@ widget.showContent( true ); } ) .then( null, function ( errorCode, errorObj ) { - var $errorMessage = $( '<span>' ).text( errorObj.error && errorObj.error.info || errorObj.exception ); - widget.error.setLabel( $errorMessage ); + if ( /spamfilter$/.test( errorCode ) && errorObj.error.spamfilter === 'flow-spam-confirmedit-form' ) { + widget.error.setLabel( + // CAPTCHA form + new OO.ui.HtmlSnippet( errorObj.error.info ) + ); + } else { + widget.error.setLabel( errorObj.error && errorObj.error.info || errorObj.exception ); + } + widget.error.toggle( true ); } ) .always( function () { diff --git a/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js b/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js index adfa6b7..5c91f26 100644 --- a/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js +++ b/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js @@ -48,7 +48,7 @@ // Events this.editor.connect( this, { change: 'updateSaveButtonState', - saveContent: 'onEditorSave', + saveContent: 'onEditorSaveContent', cancel: 'onEditorCancel' } ); this.editor.once( 'switch', function ( promise ) { @@ -112,29 +112,50 @@ * @param {string} content Content * @param {string} format Content format */ - mw.flow.ui.NewTopicWidget.prototype.onEditorSave = function ( content, format ) { + mw.flow.ui.NewTopicWidget.prototype.onEditorSaveContent = function ( content, format ) { var widget = this, - title = this.title.getValue(); + title = this.title.getValue(), + $captchaField, + captcha; - this.error.toggle( false ); this.editor.pushPending(); this.title.pushPending(); this.title.setDisabled( true ); - this.api.saveNewTopic( title, content, format ) + + $captchaField = this.error.$label.find( '[name="wpCaptchaWord"]' ); + if ( $captchaField.length > 0 ) { + captcha = { + id: this.error.$label.find( '[name="wpCaptchaId"]' ).val(), + answer: $captchaField.val() + }; + } + + this.error.setLabel( '' ); + this.error.toggle( false ); + + this.api.saveNewTopic( title, content, format, captcha ) .then( function ( topicId ) { widget.toggleExpanded( false ); widget.emit( 'save', topicId ); } ) .then( null, function ( errorCode, errorObj ) { - var $errorMessage = $( '<span>' ).text( errorObj.error && errorObj.error.info || errorObj.exception ); - widget.error.setLabel( $errorMessage ); + if ( /spamfilter$/.test( errorCode ) && errorObj.error.spamfilter === 'flow-spam-confirmedit-form' ) { + widget.error.setLabel( + // CAPTCHA form + new OO.ui.HtmlSnippet( errorObj.error.info ) + ); + } else { + widget.error.setLabel( errorObj.error && errorObj.error.info || errorObj.exception ); + } + widget.error.toggle( true ); } ) .always( function () { widget.editor.popPending(); widget.title.popPending(); widget.title.setDisabled( false ); - + } ) + .done( function () { // Clear for next use widget.title.setValue( '' ); widget.editor.setContent( '', 'html' ); diff --git a/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js b/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js index 0aef4c7..33e6349 100644 --- a/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js +++ b/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js @@ -52,7 +52,7 @@ // Events this.editor.connect( this, { - saveContent: 'onEditorSave', + saveContent: 'onEditorSaveContent', cancel: 'onEditorCancel' } ); @@ -107,12 +107,23 @@ /** * Respond to editor save */ - mw.flow.ui.ReplyWidget.prototype.onEditorSave = function ( content, format ) { - var widget = this; + mw.flow.ui.ReplyWidget.prototype.onEditorSaveContent = function ( content, format ) { + var widget = this, + $captchaField, captcha; - this.error.toggle( false ); + $captchaField = this.error.$label.find( '[name="wpCaptchaWord"]' ); + if ( $captchaField.length > 0 ) { + captcha = { + id: this.error.$label.find( '[name="wpCaptchaId"]' ).val(), + answer: $captchaField.val() + }; + } + + this.error.setLabel( '' ); + this.error.toggle( false ) + ; this.editor.pushPending(); - this.api.saveReply( this.topicId, this.replyTo, content, format ) + this.api.saveReply( this.topicId, this.replyTo, content, format, captcha ) .then( function ( workflow ) { if ( widget.expandable ) { widget.triggerInput.toggle( true ); @@ -123,8 +134,15 @@ widget.emit( 'saveContent', workflow, content, format ); } ) .then( null, function ( errorCode, errorObj ) { - var $errorMessage = $( '<span>' ).text( errorObj.error && errorObj.error.info || errorObj.exception ); - widget.error.setLabel( $errorMessage ); + if ( /spamfilter$/.test( errorCode ) && errorObj.error.spamfilter === 'flow-spam-confirmedit-form' ) { + widget.error.setLabel( + // CAPTCHA form + new OO.ui.HtmlSnippet( errorObj.error.info ) + ); + } else { + widget.error.setLabel( errorObj.error && errorObj.error.info || errorObj.exception ); + } + widget.error.toggle( true ); } ) .always( function () { -- To view, visit https://gerrit.wikimedia.org/r/233718 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I5df07700540898c7997b9ad0d8c5f81f3b6af721 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Flow Gerrit-Branch: wmf/1.26wmf19 Gerrit-Owner: Mattflaschen <mflasc...@wikimedia.org> Gerrit-Reviewer: Alex Monk <kren...@gmail.com> Gerrit-Reviewer: Mattflaschen <mflasc...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits