jenkins-bot has submitted this change and it was merged.

Change subject: Send authorization header to cxserver
......................................................................


Send authorization header to cxserver

Also see https://gerrit.wikimedia.org/r/#/c/221857/

Bug: T97113
Change-Id: If349547fe072b3e7ef5a226afd34373a2199eb95
---
A api/ApiContentTranslationToken.php
M composer.json
M extension.json
M i18n/en.json
M i18n/qqq.json
M modules/tools/ext.cx.tools.mt.js
6 files changed, 132 insertions(+), 7 deletions(-)

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



diff --git a/api/ApiContentTranslationToken.php 
b/api/ApiContentTranslationToken.php
new file mode 100644
index 0000000..f7b47b3
--- /dev/null
+++ b/api/ApiContentTranslationToken.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Module that provides JWT tokens to authenticate with cxserver.
+ *
+ * @file
+ * @copyright See AUTHORS.txt
+ * @license GPL-2.0+
+ */
+class ApiContentTranslationToken extends ApiBase {
+       public function execute() {
+               $user = $this->getUser();
+
+               if ( $user->isBlocked() ) {
+                       $this->dieUsageMsg( 'blockedtext' );
+               }
+
+               if ( !$user->isLoggedIn() ) {
+                       $this->dieUsage( 'Must be logged in', 
'token-impossible' );
+               }
+
+               // Do not fatal out
+               if ( !class_exists( 'JWT' ) ) {
+                       $this->dieUsage( 'JWT missing', 'token-impossible' );
+               }
+
+               $config = $this->getConfig()->get( 
'ContentTranslationCXServerAuth' );
+               $algorithm = $config['algorithm'];
+               $key = $config['key'];
+
+               if ( $key === '' ) {
+                       $this->dieUsage( 'Key not configured', 
'token-impossible' );
+               }
+
+               $exp = time() + $config['age'];
+
+               $token = array(
+                       'sub' => $user->getName(),
+                       'iat' => time(),
+                       'exp' => $exp,
+               );
+
+               $jwt = JWT::encode( $token, $key, $algorithm );
+
+               $this->getResult()->addValue( null, 'jwt', $jwt );
+               $this->getResult()->addValue( null, 'exp', $exp );
+       }
+
+       public function needsToken() {
+               return 'csrf';
+       }
+
+       protected function getExamplesMessages() {
+               return array(
+                       'action=cxtoken&token=123ABC' => 
'apihelp-cxtoken-example-1'
+               );
+       }
+}
diff --git a/composer.json b/composer.json
index 2f22485..aa2dacd 100644
--- a/composer.json
+++ b/composer.json
@@ -17,7 +17,8 @@
        },
        "require": {
                "php": ">=5.3.0",
-               "composer/installers": ">=1.0.1"
+               "composer/installers": ">=1.0.1",
+               "firebase/php-jwt": "~2.1.0"
        },
        "require-dev": {
                "jakub-onderka/php-parallel-lint": "0.9",
diff --git a/extension.json b/extension.json
index 0d09ca0..fc6f936 100644
--- a/extension.json
+++ b/extension.json
@@ -37,7 +37,8 @@
        "APIModules": {
                "cxpublish": "ApiContentTranslationPublish",
                "cxdelete": "ApiContentTranslationDelete",
-               "cxconfiguration": "ApiContentTranslationConfiguration"
+               "cxconfiguration": "ApiContentTranslationConfiguration",
+               "cxtoken": "ApiContentTranslationToken"
        },
        "APIListModules": {
                "contenttranslation": "ApiQueryContentTranslation",
@@ -54,11 +55,12 @@
        },
        "AutoloadClasses": {
                "ApiContentTranslationConfiguration": 
"api/ApiContentTranslationConfiguration.php",
-               "ApiContentTranslationPublish": 
"api/ApiContentTranslationPublish.php",
                "ApiContentTranslationDelete": 
"api/ApiContentTranslationDelete.php",
+               "ApiContentTranslationPublish": 
"api/ApiContentTranslationPublish.php",
+               "ApiContentTranslationToken": 
"api/ApiContentTranslationToken.php",
                "ApiQueryContentTranslation": 
"api/ApiQueryContentTranslation.php",
-               "ApiQueryContentTranslationStats": 
"api/ApiQueryContentTranslationStats.php",
                "ApiQueryContentTranslationLanguageTrend": 
"api/ApiQueryContentTranslationLanguageTrend.php",
+               "ApiQueryContentTranslationStats": 
"api/ApiQueryContentTranslationStats.php",
                "ApiQueryPublishedTranslations": 
"api/ApiQueryPublishedTranslations.php",
                "ContentTranslationHooks": "ContentTranslation.hooks.php",
                "ContentTranslation\\Database": "includes/Database.php",
@@ -104,6 +106,11 @@
                "ContentTranslationUseMagnusTool": true,
                "ContentTranslationBrowserBlacklist": {
                        "msie": [ [ "<", 10 ] ]
+               },
+               "ContentTranslationCXServerAuth": {
+                       "algorithm": "HS256",
+                       "key": "",
+                       "age": "3600"
                }
        },
        "ResourceModules": {
diff --git a/i18n/en.json b/i18n/en.json
index 9bf3d3b..e94229f 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -139,6 +139,7 @@
        "apihelp-query+contenttranslationlangtrend-param-interval": "The 
interval for calculating the trend. Can be 'week' or 'month'.",
        "apihelp-query+contenttranslationlangtrend-example-1": "Fetch the 
publishing trend for the language pair es-ca with weekly intervals",
        "apihelp-query+contenttranslationlangtrend-example-2": "Fetch the 
publishing trend for all languages",
+       "apihelp-cxtoken-example-1": "Fetch the authentication token for 
cxserver",
        "cx-save-draft-save-success": "Saved {{PLURAL:$1|a minute ago|$1 
minutes ago|0=just now}}",
        "cx-save-draft-saving": "Saving...",
        "cx-save-draft-tooltip": "Translation drafts are saved automatically",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 7a03aa7..7983e0c 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -144,6 +144,7 @@
        "apihelp-query+contenttranslationlangtrend-param-interval": 
"{{doc-apihelp-param|query+cxpublishedtranslations|interval}}",
        "apihelp-query+contenttranslationlangtrend-example-1": 
"{{doc-apihelp-example|query+contenttranslationlangtrend}}",
        "apihelp-query+contenttranslationlangtrend-example-2": 
"{{doc-apihelp-example|query+contenttranslationlangtrend}}",
+       "apihelp-cxtoken-example-1": "{{doc-apihelp-example|cxtoken}}",
        "cx-save-draft-save-success": "\"Saved\" refers to a draft of a 
translated page that was saved recently.",
        "cx-save-draft-saving": "Label of button to save the translation as 
draft while saving is in progress\n{{Identical|Saving}}",
        "cx-save-draft-tooltip": "Tooltip text shown for the save status 
indicator text in the header of [[Special:ContentTranslation]].\n\nParameters: 
\n* $1 - the number of minutes ago the translation was saved.",
diff --git a/modules/tools/ext.cx.tools.mt.js b/modules/tools/ext.cx.tools.mt.js
index 29e69c1..6773c10 100644
--- a/modules/tools/ext.cx.tools.mt.js
+++ b/modules/tools/ext.cx.tools.mt.js
@@ -11,11 +11,62 @@
 ( function ( $, mw ) {
        'use strict';
 
-       var cache = {}, // MT requests cache
+       var
+               cxserverToken = {
+                       expires: undefined,
+                       jwt: undefined,
+                       promise: undefined
+               },
+               cache = {}, // MT requests cache
                providerIdPrefix = 'cx-provider-',
                disableMT = 'disable-mt',
                noMT = 'no-mt',
                sourceMT = 'source-mt';
+
+       /**
+        * Fetch token for authentication with cxserver.
+        *
+        * @return {jQuery.Promise}
+        */
+       function getCXServerToken() {
+               var now = Math.floor( Date.now() / 1000 );
+
+               // If request in progress, wait for it
+               if ( cxserverToken.promise ) {
+                       return cxserverToken.promise;
+               }
+
+               // Return cached token if fresh and not expiring soon.
+               // And hope that client clock is at correct time.
+               if (
+                       cxserverToken.expires !== undefined &&
+                       cxserverToken.expires + 5 < now
+               ) {
+                       return $.Deferred().resolve( cxserverToken.jwt );
+               }
+
+               // (Re-)fetch cxserver token
+               cxserverToken.promise = (new mw.Api())
+                       .postWithToken( 'edit', { action: 'cxtoken' } )
+                       .always( function () {
+                               cxserverToken.promise = undefined;
+                       } )
+                       .then(
+                               function ( response ) {
+                                       cxserverToken.jwt = response.jwt;
+                                       cxserverToken.expires = response.exp;
+
+                                       return response.jwt;
+                               },
+                               // Not all MT services require token, so let 
the caller try
+                               // with empty token to see if it fails.
+                               function () {
+                                       return $.Deferred().resolve( '' );
+                               }
+                       );
+
+               return cxserverToken.promise;
+       }
 
        /**
         * Get the registry of machine translation providers
@@ -80,8 +131,15 @@
                        $provider: MTControlCard.provider
                } );
 
-               return $.post( mtURL, sourceHtml ).then( null, function () {
-                       return $.Deferred().reject( 'service-failure', 
arguments ).promise();
+               return getCXServerToken().then( function ( token ) {
+                       return $.ajax( {
+                               type: 'post',
+                               url: mtURL,
+                               data: sourceHtml,
+                               headers: { Authorization: token }
+                       } ).then( null, function () {
+                               return $.Deferred().reject( 'service-failure', 
arguments ).promise();
+                       } );
                } );
        }
 

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

Gerrit-MessageType: merged
Gerrit-Change-Id: If349547fe072b3e7ef5a226afd34373a2199eb95
Gerrit-PatchSet: 12
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Nikerabbit <[email protected]>
Gerrit-Reviewer: Amire80 <[email protected]>
Gerrit-Reviewer: CSteipp <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Nikerabbit <[email protected]>
Gerrit-Reviewer: Santhosh <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to