Mobrovac has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/384994 )

Change subject: Create SpecialRunSingleJob.php
......................................................................


Create SpecialRunSingleJob.php

Bug: T175146
Change-Id: Id0f0857f62250b3341c3ca41fc05a9830a20735e
---
A SpecialRunSingleJob.php
M extension.json
2 files changed, 153 insertions(+), 1 deletion(-)

Approvals:
  Mobrovac: Verified; Looks good to me, approved
  jenkins-bot: Verified



diff --git a/SpecialRunSingleJob.php b/SpecialRunSingleJob.php
new file mode 100644
index 0000000..93e0b51
--- /dev/null
+++ b/SpecialRunSingleJob.php
@@ -0,0 +1,148 @@
+<?php
+/**
+ * Implements Special:RunSingleJob
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
+use Firebase\JWT\JWT;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Special page designed for running a single background task (internal use 
only)
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialRunSingleJob extends UnlistedSpecialPage {
+
+       /** @var LoggerInterface instance for all SpecialRunJobs instances */
+       private static $logger;
+
+       public function __construct() {
+               parent::__construct( 'RunSingleJob' );
+       }
+
+       public function doesWrites() {
+               return true;
+       }
+
+       public function execute( $par = '' ) {
+               $this->getOutput()->disable();
+
+               if ( wfReadOnly() ) {
+                       wfHttpError( 423, 'Locked', 'Wiki is in read-only 
mode.' );
+                       return;
+               }
+
+               // Validate request method
+               if ( !$this->getRequest()->wasPosted() ) {
+                       wfHttpError( 400, 'Bad Request', 'Request must be 
POSTed.' );
+                       return;
+               }
+
+               // get the info contained in the body
+               $event = null;
+               try {
+                       $event = FormatJson::decode( file_get_contents( 
"php://input" ), true );
+               } catch ( Exception $e ) {
+                       wfHttpError( 500, 'Server Error', 'Could not decode the 
event' );
+                       return;
+               }
+
+               // check that we have the needed components of the event
+               if ( !isset( $event['database'] )
+                        || !isset( $event['type'] )
+                        || !isset( $event['page_title'] )
+                        || !isset( $event['params'] )
+               ) {
+                       wfHttpError( 400, 'Bad Request', 'Invalid event 
received' );
+                       return;
+               }
+
+               if ( !isset( $event['mediawiki_signature'] ) ) {
+                       wfHttpError( 403, 'Forbidden', 'Missing mediawiki 
signature' );
+                       return;
+               }
+               $signature = $event['mediawiki_signature'];
+               unset( $event['mediawiki_signature'] );
+               $expected_signature = JWT::encode(
+                       $event,
+                       MediaWikiServices::getInstance()->getMainConfig()->get( 
'SecretKey' )
+               );
+               if ( !hash_equals( $expected_signature, $signature ) ) {
+                       wfHttpError( 403, 'Forbidden', 'Invalid mediawiki 
signature' );
+                       return;
+               }
+
+               // check if there are any base64-encoded parameters and if so 
decode them
+               foreach ( $event['params'] as $key => &$value ) {
+                       if ( !is_string( $value ) ) {
+                               continue;
+                       }
+                       if ( preg_match( 
'/^data:application/octet-stream;base64,([\s\S]+)$/', $value, $match ) ) {
+                               $value = base64_decode( $match[1], true );
+                               if ( $value === false ) {
+                                       wfHttpError(
+                                               500,
+                                               'Internal Server Error',
+                                               "base64_decode() failed for 
parameter {$key} ({$match[1]})"
+                                       );
+                                       return;
+                               }
+                       }
+               }
+               unset( $value );
+
+               $executor = new JobExecutor();
+
+               try {
+                       // execute the job
+                       $response = $executor->execute( $event );
+                       if ( $response['status'] === true ) {
+                               HttpStatus::header( 200 );
+                               return;
+                       } else {
+                               wfHttpError( 500, 'Internal Server Error', 
$response['message'] );
+                       }
+               } catch ( Exception $e ) {
+                       self::logger()->error(
+                               'Error running job ' . $event['meta']['id'] . ' 
of type ' . $event['type'],
+                               [
+                                       'exception' => $e
+                               ]
+                       );
+                       wfHttpError( 500, 'Internal Server Error', 
$e->getMessage() );
+               }
+       }
+
+       /**
+        * Returns a singleton logger instance for all JobExecutor instances.
+        * Use like: self::logger()->info( $mesage )
+        * We use this so we don't have to check if the logger has been created
+        * before attempting to log a message.
+        */
+       private static function logger() {
+               if ( !self::$logger ) {
+                       self::$logger = LoggerFactory::getInstance( 
'RunSingleJob' );
+               }
+               return self::$logger;
+       }
+}
diff --git a/extension.json b/extension.json
index f887d04..4a4dea8 100644
--- a/extension.json
+++ b/extension.json
@@ -22,7 +22,8 @@
                "EventBusRCFeedEngine": "EventBusRCFeedEngine.php",
                "EventBusRCFeedFormatter": "EventBusRCFeedFormatter.php",
                "JobQueueEventBus": "JobQueueEventBus.php",
-               "JobExecutor": "JobExecutor.php"
+               "JobExecutor": "JobExecutor.php",
+               "SpecialRunSingleJob": "SpecialRunSingleJob.php"
        },
        "MessagesDirs": {
                "EventBus": [
@@ -64,5 +65,8 @@
                        "EventBusHooks::onArticleProtectComplete"
                ]
        },
+       "SpecialPages": {
+               "RunSingleJob": "SpecialRunSingleJob"
+       },
        "manifest_version": 1
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/384994
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id0f0857f62250b3341c3ca41fc05a9830a20735e
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/extensions/EventBus
Gerrit-Branch: master
Gerrit-Owner: Ppchelko <ppche...@wikimedia.org>
Gerrit-Reviewer: Mobrovac <mobro...@wikimedia.org>
Gerrit-Reviewer: Ppchelko <ppche...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to