summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Evans <grknight@gentoo.org>2020-10-02 15:01:38 -0400
committerBrian Evans <grknight@gentoo.org>2020-10-02 15:01:38 -0400
commit30182d5bb3887c68648a069679abdbdc3a59f191 (patch)
treeaba120486e186bb9dba8a5457300468d426f7a65
parentUpdate CommentStreams to 1.35 (diff)
downloadextensions-30182d5bb3887c68648a069679abdbdc3a59f191.tar.gz
extensions-30182d5bb3887c68648a069679abdbdc3a59f191.tar.bz2
extensions-30182d5bb3887c68648a069679abdbdc3a59f191.zip
Update OpenIDConnect to 1.35
Signed-off-by: Brian Evans <grknight@gentoo.org>
-rw-r--r--OpenIDConnect/.gitignore1
-rw-r--r--OpenIDConnect/.phpcs.xml6
-rw-r--r--OpenIDConnect/CODE_OF_CONDUCT.md2
-rw-r--r--OpenIDConnect/composer.json27
-rw-r--r--OpenIDConnect/extension.json6
-rw-r--r--OpenIDConnect/gitinfo.json1
-rw-r--r--OpenIDConnect/i18n/SelectOpenIDConnectIssuer.alias.php1
-rw-r--r--OpenIDConnect/i18n/ar.json9
-rw-r--r--OpenIDConnect/i18n/el.json8
-rw-r--r--OpenIDConnect/i18n/sh.json9
-rw-r--r--OpenIDConnect/i18n/tr.json9
-rw-r--r--OpenIDConnect/i18n/zh-hk.json9
-rw-r--r--OpenIDConnect/maintenance/MigrateOIDCSubjectAndIssuerFromUserTable.php96
-rw-r--r--OpenIDConnect/package-lock.json891
-rw-r--r--OpenIDConnect/package.json18
-rw-r--r--OpenIDConnect/sql/AddIssuer.sql1
-rw-r--r--OpenIDConnect/sql/AddSubject.sql1
-rw-r--r--OpenIDConnect/sql/mysql/AddTable.sql6
-rw-r--r--OpenIDConnect/sql/mysql/DropColumnsFromUserTable.sql1
-rw-r--r--OpenIDConnect/sql/postgres/AddTable.sql6
-rw-r--r--OpenIDConnect/sql/postgres/DropColumnsFromUserTable.sql1
-rw-r--r--OpenIDConnect/src/OpenIDConnect.php341
-rw-r--r--OpenIDConnect/src/SelectOpenIDConnectIssuer.php5
-rw-r--r--OpenIDConnect/version4
24 files changed, 1308 insertions, 151 deletions
diff --git a/OpenIDConnect/.gitignore b/OpenIDConnect/.gitignore
index 6574e829..47e36d52 100644
--- a/OpenIDConnect/.gitignore
+++ b/OpenIDConnect/.gitignore
@@ -1,4 +1,3 @@
/node_modules/
/vendor/
/composer.lock
-/package-lock.json
diff --git a/OpenIDConnect/.phpcs.xml b/OpenIDConnect/.phpcs.xml
index 95b1ff23..35799936 100644
--- a/OpenIDConnect/.phpcs.xml
+++ b/OpenIDConnect/.phpcs.xml
@@ -1,8 +1,10 @@
<?xml version="1.0"?>
<ruleset>
- <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki" />
+ <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPrivate" />
+ <exclude name="PSR12.Properties.ConstantVisibility.NotFound" />
+ </rule>
<file>.</file>
<arg name="extensions" value="php,php5,inc" />
<arg name="encoding" value="utf8" />
- <exclude-pattern>vendor</exclude-pattern>
</ruleset>
diff --git a/OpenIDConnect/CODE_OF_CONDUCT.md b/OpenIDConnect/CODE_OF_CONDUCT.md
index d8e5d087..498acf76 100644
--- a/OpenIDConnect/CODE_OF_CONDUCT.md
+++ b/OpenIDConnect/CODE_OF_CONDUCT.md
@@ -1 +1 @@
-The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Code_of_Conduct).
+The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Special:MyLanguage/Code_of_Conduct).
diff --git a/OpenIDConnect/composer.json b/OpenIDConnect/composer.json
index 692e24e4..f971f014 100644
--- a/OpenIDConnect/composer.json
+++ b/OpenIDConnect/composer.json
@@ -1,5 +1,6 @@
{
- "name": "mediawiki/OpenIDConnect",
+ "name": "mediawiki/openidconnect",
+ "type": "mediawiki-extension",
"description": "Provides authentication using OpenID Connect in conjunction with PluggableAuth",
"license": "MIT",
"authors": [
@@ -8,20 +9,15 @@
"email": "cicalese@mitre.org"
}
],
- "repositories": [
- {
- "url": "https://github.com/jumbojett/OpenID-Connect-PHP.git",
- "type": "git"
- }
- ],
"require": {
- "jumbojett/openid-connect-php": "0.5.0"
+ "jumbojett/openid-connect-php": "0.5.0",
+ "composer/installers": "~1.0"
},
"require-dev": {
- "jakub-onderka/php-parallel-lint": "1.0.0",
- "mediawiki/mediawiki-codesniffer": "18.0.0",
- "jakub-onderka/php-console-highlighter": "0.3.2",
- "mediawiki/minus-x": "0.3.1"
+ "mediawiki/mediawiki-codesniffer": "31.0.0",
+ "mediawiki/minus-x": "1.1.0",
+ "php-parallel-lint/php-console-highlighter": "0.5.0",
+ "php-parallel-lint/php-parallel-lint": "1.2.0"
},
"scripts": {
"test": [
@@ -30,8 +26,11 @@
"minus-x check ."
],
"fix": [
- "phpcbf",
- "minus-x fix ."
+ "minus-x fix .",
+ "phpcbf"
]
+ },
+ "extra": {
+ "installer-name": "OpenIDConnect"
}
}
diff --git a/OpenIDConnect/extension.json b/OpenIDConnect/extension.json
index de2bac84..1aa32359 100644
--- a/OpenIDConnect/extension.json
+++ b/OpenIDConnect/extension.json
@@ -1,6 +1,6 @@
{
"name": "OpenID Connect",
- "version": "4.1",
+ "version": "5.3",
"author": [
"[https://www.mediawiki.org/wiki/User:Cindy.cicalese Cindy Cicalese]"
],
@@ -25,7 +25,9 @@
},
"AutoloadClasses": {
"OpenIDConnect": "src/OpenIDConnect.php",
- "SelectOpenIDConnectIssuer": "src/SelectOpenIDConnectIssuer.php"
+ "SelectOpenIDConnectIssuer": "src/SelectOpenIDConnectIssuer.php",
+ "MigrateOIDCSubjectAndIssuerFromUserTable":
+ "maintenance/MigrateOIDCSubjectAndIssuerFromUserTable.php"
},
"Hooks": {
"LoadExtensionSchemaUpdates": "OpenIDConnect::loadExtensionSchemaUpdates"
diff --git a/OpenIDConnect/gitinfo.json b/OpenIDConnect/gitinfo.json
deleted file mode 100644
index ad2b408c..00000000
--- a/OpenIDConnect/gitinfo.json
+++ /dev/null
@@ -1 +0,0 @@
-{"branch": "baea47f52e4b86ee09a01a6e26d1699bd31b6ea8\n", "headSHA1": "baea47f52e4b86ee09a01a6e26d1699bd31b6ea8\n", "remoteURL": "https://gerrit-replica.wikimedia.org/r/mediawiki/extensions/OpenIDConnect", "headCommitDate": "1523681260", "head": "baea47f52e4b86ee09a01a6e26d1699bd31b6ea8\n"} \ No newline at end of file
diff --git a/OpenIDConnect/i18n/SelectOpenIDConnectIssuer.alias.php b/OpenIDConnect/i18n/SelectOpenIDConnectIssuer.alias.php
index 353ed4d5..e30385bb 100644
--- a/OpenIDConnect/i18n/SelectOpenIDConnectIssuer.alias.php
+++ b/OpenIDConnect/i18n/SelectOpenIDConnectIssuer.alias.php
@@ -21,7 +21,6 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-// @codingStandardsIgnoreFile
$specialPageAliases = [];
diff --git a/OpenIDConnect/i18n/ar.json b/OpenIDConnect/i18n/ar.json
new file mode 100644
index 00000000..f1bad33d
--- /dev/null
+++ b/OpenIDConnect/i18n/ar.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "ديفيد"
+ ]
+ },
+ "openidconnect-desc": "يوفر المصادقة باستخدام OpenID Connect بالاقتران مع PluggableAuth",
+ "selectopenidconnectissuer": "حدد مصدر المصادقة"
+}
diff --git a/OpenIDConnect/i18n/el.json b/OpenIDConnect/i18n/el.json
new file mode 100644
index 00000000..25d98138
--- /dev/null
+++ b/OpenIDConnect/i18n/el.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Nikosgranturismogt"
+ ]
+ },
+ "selectopenidconnectissuer": "Επιλογή εκδότη επαλήθευσης"
+}
diff --git a/OpenIDConnect/i18n/sh.json b/OpenIDConnect/i18n/sh.json
new file mode 100644
index 00000000..38e5f1f2
--- /dev/null
+++ b/OpenIDConnect/i18n/sh.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Vlad5250"
+ ]
+ },
+ "openidconnect-desc": "Omogućuje potvdu identiteta s OpenID Connect koja radi zajedno s PluggableAuth",
+ "selectopenidconnectissuer": "Izaberite izdatelja potvrde identiteta"
+}
diff --git a/OpenIDConnect/i18n/tr.json b/OpenIDConnect/i18n/tr.json
new file mode 100644
index 00000000..0d20717f
--- /dev/null
+++ b/OpenIDConnect/i18n/tr.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "BaRaN6161 TURK"
+ ]
+ },
+ "openidconnect-desc": "PluIDableAuth ile birlikte OpenID Connect kullanarak kimlik doğrulama sağlar",
+ "selectopenidconnectissuer": "Kimlik Doğrulayıcıyı Seçin"
+}
diff --git a/OpenIDConnect/i18n/zh-hk.json b/OpenIDConnect/i18n/zh-hk.json
new file mode 100644
index 00000000..c226a2ea
--- /dev/null
+++ b/OpenIDConnect/i18n/zh-hk.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "C933103"
+ ]
+ },
+ "openidconnect-desc": "與PluggableAuth共同提供OpenID Connect認證",
+ "selectopenidconnectissuer": "選擇認證發行者"
+}
diff --git a/OpenIDConnect/maintenance/MigrateOIDCSubjectAndIssuerFromUserTable.php b/OpenIDConnect/maintenance/MigrateOIDCSubjectAndIssuerFromUserTable.php
new file mode 100644
index 00000000..d7b77b93
--- /dev/null
+++ b/OpenIDConnect/maintenance/MigrateOIDCSubjectAndIssuerFromUserTable.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Migrate subject and issuer columns from the user table to the openid_connect
+ * table.
+ *
+ * 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 Maintenance
+ */
+
+if ( getenv( 'MW_INSTALL_PATH' ) ) {
+ require_once getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php';
+} else {
+ require_once __DIR__ . '/../../../maintenance/Maintenance.php';
+}
+
+/**
+ * Maintenance script that migrates data in the subject and issuer columns
+ * from the user table to the openid_connect table.
+ *
+ * @ingroup Maintenance
+ */
+class MigrateOIDCSubjectAndIssuerFromUserTable extends LoggedUpdateMaintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->addDescription( 'Migrates data from user table (for upgrade to 5.X+' );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getUpdateKey() {
+ return __CLASS__;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function doDBUpdates() {
+ $dbw = $this->getDB( DB_MASTER );
+
+ if ( !$dbw->fieldExists(
+ 'user',
+ 'subject',
+ __METHOD__
+ ) ) {
+ $this->output( 'No subject column found in user table.' . PHP_EOL );
+ return true;
+ }
+
+ if ( !$dbw->fieldExists(
+ 'user',
+ 'issuer',
+ __METHOD__
+ ) ) {
+ $this->output( 'No issuer column found in user table.' . PHP_EOL );
+ return true;
+ }
+
+ $dbw->insertSelect(
+ 'openid_connect',
+ 'user',
+ [
+ 'oidc_user' => 'user_id',
+ 'oidc_subject' => 'subject',
+ 'oidc_issuer' => 'issuer'
+ ],
+ [
+ 'subject IS NOT NULL',
+ 'issuer IS NOT NULL'
+ ],
+ __METHOD__
+ );
+ $this->output( 'Migrated data from user table to openid_connect table.' .
+ PHP_EOL );
+
+ return true;
+ }
+}
+
+$maintClass = MigrateOIDCSubjectAndIssuerFromUserTable::class;
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/OpenIDConnect/package-lock.json b/OpenIDConnect/package-lock.json
new file mode 100644
index 00000000..16a67e43
--- /dev/null
+++ b/OpenIDConnect/package-lock.json
@@ -0,0 +1,891 @@
+{
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "JSV": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz",
+ "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=",
+ "dev": true
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ },
+ "dependencies": {
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ }
+ }
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ },
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^2.0.0",
+ "map-obj": "^1.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "coffeescript": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz",
+ "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "^1.0.1"
+ }
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1",
+ "meow": "^3.3.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "eventemitter2": {
+ "version": "0.4.14",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
+ "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=",
+ "dev": true
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "findup-sync": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz",
+ "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
+ "dev": true,
+ "requires": {
+ "glob": "~5.0.0"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dev": true,
+ "requires": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "getobject": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
+ "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.2",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
+ "dev": true
+ },
+ "grunt": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.1.0.tgz",
+ "integrity": "sha512-+NGod0grmviZ7Nzdi9am7vuRS/h76PcWDsV635mEXF0PEQMUV6Kb+OjTdsVxbi0PZmfQOjCMKb3w8CVZcqsn1g==",
+ "dev": true,
+ "requires": {
+ "coffeescript": "~1.10.0",
+ "dateformat": "~1.0.12",
+ "eventemitter2": "~0.4.13",
+ "exit": "~0.1.1",
+ "findup-sync": "~0.3.0",
+ "glob": "~7.0.0",
+ "grunt-cli": "~1.2.0",
+ "grunt-known-options": "~1.1.0",
+ "grunt-legacy-log": "~2.0.0",
+ "grunt-legacy-util": "~1.1.1",
+ "iconv-lite": "~0.4.13",
+ "js-yaml": "~3.13.1",
+ "minimatch": "~3.0.2",
+ "mkdirp": "~1.0.3",
+ "nopt": "~3.0.6",
+ "path-is-absolute": "~1.0.0",
+ "rimraf": "~2.6.2"
+ },
+ "dependencies": {
+ "grunt-cli": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz",
+ "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=",
+ "dev": true,
+ "requires": {
+ "findup-sync": "~0.3.0",
+ "grunt-known-options": "~1.1.0",
+ "nopt": "~3.0.6",
+ "resolve": "~1.1.0"
+ }
+ },
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-banana-checker": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/grunt-banana-checker/-/grunt-banana-checker-0.9.0.tgz",
+ "integrity": "sha512-SqPiB6OazWqR8USL0NymtuT5Br3mD9WBBsM1rHC/3wIi2SrZNM6/+j9CIeuEM5oCn+AtO2Y0+rzzFyOdC9afAg==",
+ "dev": true
+ },
+ "grunt-jsonlint": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/grunt-jsonlint/-/grunt-jsonlint-1.0.7.tgz",
+ "integrity": "sha1-BDPzpYVSy1twkgW/1uJ11ECoCWU=",
+ "dev": true,
+ "requires": {
+ "jsonlint": "1.6.2",
+ "strip-json-comments": "^2.0.0"
+ }
+ },
+ "grunt-known-options": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz",
+ "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==",
+ "dev": true
+ },
+ "grunt-legacy-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz",
+ "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==",
+ "dev": true,
+ "requires": {
+ "colors": "~1.1.2",
+ "grunt-legacy-log-utils": "~2.0.0",
+ "hooker": "~0.2.3",
+ "lodash": "~4.17.5"
+ }
+ },
+ "grunt-legacy-log-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz",
+ "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==",
+ "dev": true,
+ "requires": {
+ "chalk": "~2.4.1",
+ "lodash": "~4.17.10"
+ }
+ },
+ "grunt-legacy-util": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz",
+ "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==",
+ "dev": true,
+ "requires": {
+ "async": "~1.5.2",
+ "exit": "~0.1.1",
+ "getobject": "~0.1.0",
+ "hooker": "~0.2.3",
+ "lodash": "~4.17.10",
+ "underscore.string": "~3.3.4",
+ "which": "~1.3.0"
+ }
+ },
+ "has-color": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz",
+ "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "hooker": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
+ "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
+ "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
+ "dev": true
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsonlint": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.2.tgz",
+ "integrity": "sha1-VzcEUIX1XrRVxosf9OvAG9UOiDA=",
+ "dev": true,
+ "requires": {
+ "JSV": ">= 4.0.x",
+ "nomnom": ">= 1.5.x"
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "strip-bom": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "^0.4.1",
+ "signal-exit": "^3.0.0"
+ }
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "^2.0.0",
+ "decamelize": "^1.1.2",
+ "loud-rejection": "^1.0.0",
+ "map-obj": "^1.0.1",
+ "minimist": "^1.1.3",
+ "normalize-package-data": "^2.3.4",
+ "object-assign": "^4.0.1",
+ "read-pkg-up": "^1.0.1",
+ "redent": "^1.0.0",
+ "trim-newlines": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.3.tgz",
+ "integrity": "sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==",
+ "dev": true
+ },
+ "nomnom": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz",
+ "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=",
+ "dev": true,
+ "requires": {
+ "chalk": "~0.4.0",
+ "underscore": "~1.6.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz",
+ "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz",
+ "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "~1.0.0",
+ "has-color": "~0.1.0",
+ "strip-ansi": "~0.1.0"
+ }
+ }
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "dev": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^1.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^1.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "^1.0.0",
+ "read-pkg": "^1.0.0"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "^2.1.0",
+ "strip-indent": "^1.0.1"
+ }
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "resolve": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
+ "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "sprintf-js": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz",
+ "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ },
+ "underscore": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
+ "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
+ "dev": true
+ },
+ "underscore.string": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz",
+ "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "^1.0.3",
+ "util-deprecate": "^1.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ }
+ }
+}
diff --git a/OpenIDConnect/package.json b/OpenIDConnect/package.json
index 3b4b5f0c..1bfa2182 100644
--- a/OpenIDConnect/package.json
+++ b/OpenIDConnect/package.json
@@ -1,11 +1,11 @@
{
- "private": true,
- "scripts": {
- "test": "grunt test"
- },
- "devDependencies": {
- "grunt": "1.0.1",
- "grunt-banana-checker": "0.4.0",
- "grunt-jsonlint": "1.0.7"
- }
+ "private": true,
+ "scripts": {
+ "test": "grunt test"
+ },
+ "devDependencies": {
+ "grunt": "1.1.0",
+ "grunt-banana-checker": "0.9.0",
+ "grunt-jsonlint": "1.0.7"
+ }
}
diff --git a/OpenIDConnect/sql/AddIssuer.sql b/OpenIDConnect/sql/AddIssuer.sql
deleted file mode 100644
index 4b18a376..00000000
--- a/OpenIDConnect/sql/AddIssuer.sql
+++ /dev/null
@@ -1 +0,0 @@
-ALTER TABLE /*_*/user ADD issuer TINYBLOB;
diff --git a/OpenIDConnect/sql/AddSubject.sql b/OpenIDConnect/sql/AddSubject.sql
deleted file mode 100644
index 76ff53d8..00000000
--- a/OpenIDConnect/sql/AddSubject.sql
+++ /dev/null
@@ -1 +0,0 @@
-ALTER TABLE /*_*/user ADD subject TINYBLOB;
diff --git a/OpenIDConnect/sql/mysql/AddTable.sql b/OpenIDConnect/sql/mysql/AddTable.sql
new file mode 100644
index 00000000..873cbef4
--- /dev/null
+++ b/OpenIDConnect/sql/mysql/AddTable.sql
@@ -0,0 +1,6 @@
+CREATE TABLE /*_*/openid_connect (
+ oidc_user int unsigned PRIMARY KEY NOT NULL,
+ oidc_subject TINYBLOB NOT NULL,
+ oidc_issuer TINYBLOB NOT NULL
+) /*$wgDBTableOptions*/;
+CREATE INDEX /*i*/openid_connect_subject ON /*_*/openid_connect (oidc_subject(50),oidc_issuer(50));
diff --git a/OpenIDConnect/sql/mysql/DropColumnsFromUserTable.sql b/OpenIDConnect/sql/mysql/DropColumnsFromUserTable.sql
new file mode 100644
index 00000000..43f18fce
--- /dev/null
+++ b/OpenIDConnect/sql/mysql/DropColumnsFromUserTable.sql
@@ -0,0 +1 @@
+ALTER TABLE /*_*/user DROP COLUMN subject, DROP COLUMN issuer;
diff --git a/OpenIDConnect/sql/postgres/AddTable.sql b/OpenIDConnect/sql/postgres/AddTable.sql
new file mode 100644
index 00000000..209794fe
--- /dev/null
+++ b/OpenIDConnect/sql/postgres/AddTable.sql
@@ -0,0 +1,6 @@
+CREATE TABLE openid_connect (
+ oidc_user INTEGER NOT NULL PRIMARY KEY,
+ oidc_subject VARCHAR(255) NOT NULL,
+ oidc_issuer VARCHAR(255) NOT NULL
+);
+CREATE INDEX openid_connect_subject ON openid_connect (oidc_subject,oidc_issuer);
diff --git a/OpenIDConnect/sql/postgres/DropColumnsFromUserTable.sql b/OpenIDConnect/sql/postgres/DropColumnsFromUserTable.sql
new file mode 100644
index 00000000..8db8403e
--- /dev/null
+++ b/OpenIDConnect/sql/postgres/DropColumnsFromUserTable.sql
@@ -0,0 +1 @@
+ALTER TABLE mwuser DROP COLUMN subject, DROP COLUMN issuer;
diff --git a/OpenIDConnect/src/OpenIDConnect.php b/OpenIDConnect/src/OpenIDConnect.php
index 869c1555..481f5c26 100644
--- a/OpenIDConnect/src/OpenIDConnect.php
+++ b/OpenIDConnect/src/OpenIDConnect.php
@@ -22,9 +22,10 @@
* DEALINGS IN THE SOFTWARE.
*/
-use \MediaWiki\Session\SessionManager;
-use \MediaWiki\Auth\AuthManager;
-use \Jumbojett\OpenIDConnectClient;
+use Jumbojett\OpenIDConnectClient;
+use MediaWiki\Auth\AuthManager;
+use MediaWiki\MediaWikiServices;
+use MediaWiki\Session\SessionManager;
class OpenIDConnect extends PluggableAuth {
@@ -47,12 +48,14 @@ class OpenIDConnect extends PluggableAuth {
public function authenticate( &$id, &$username, &$realname, &$email,
&$errorMessage ) {
if ( !array_key_exists( 'SERVER_PORT', $_SERVER ) ) {
- wfDebug( "in authenticate, server port not set" . PHP_EOL );
+ wfDebugLog( 'OpenID Connect', 'in authenticate, server port not set' .
+ PHP_EOL );
return false;
}
if ( !isset( $GLOBALS['wgOpenIDConnect_Config'] ) ) {
- wfDebug( "wgOpenIDConnect_Config not set" . PHP_EOL );
+ wfDebugLog( 'OpenID Connect', 'wgOpenIDConnect_Config not set' .
+ PHP_EOL );
return false;
}
@@ -62,7 +65,7 @@ class OpenIDConnect extends PluggableAuth {
$iss = $session->get( 'iss' );
- if ( !is_null( $iss ) ) {
+ if ( $iss !== null ) {
if ( isset( $_REQUEST['code'] ) && isset( $_REQUEST['status'] ) ) {
$session->remove( 'iss' );
@@ -74,19 +77,21 @@ class OpenIDConnect extends PluggableAuth {
if ( !isset( $config['clientID'] ) ||
!isset( $config['clientsecret'] ) ) {
- wfDebug( "OpenID Connect: clientID or clientsecret not set for " . $iss );
+ wfDebugLog( 'OpenID Connect',
+ 'OpenID Connect: clientID or clientsecret not set for ' . $iss .
+ '.' . PHP_EOL );
$params = [
- "uri" => urlencode( $_SERVER['REQUEST_URI'] ),
- "query" => urlencode( $_SERVER['QUERY_STRING'] )
+ 'uri' => urlencode( $_SERVER['REQUEST_URI'] ),
+ 'query' => urlencode( $_SERVER['QUERY_STRING'] )
];
- self::redirect( "Special:SelectOpenIDConnectIssuer",
+ self::redirect( 'Special:SelectOpenIDConnectIssuer',
$params, true );
return false;
}
} else {
- wfDebug( 'Issuer ' . $iss .
- ' does not exist in wgOpeIDConnect_Config'. PHP_EOL );
+ wfDebugLog( 'OpenID Connect', 'Issuer ' . $iss .
+ ' does not exist in wgOpeIDConnect_Config.' . PHP_EOL );
return false;
}
@@ -108,18 +113,19 @@ class OpenIDConnect extends PluggableAuth {
if ( !isset( $config['clientID'] ) ||
!isset( $config['clientsecret'] ) ) {
- wfDebug( "OpenID Connect: clientID or clientsecret not set for " .
- $iss );
+ wfDebugLog( 'OpenID Connect',
+ 'OpenID Connect: clientID or clientsecret not set for ' .
+ $iss . '.' . PHP_EOL );
return false;
}
} else {
$params = [
- "uri" => urlencode( $_SERVER['REQUEST_URI'] ),
- "query" => urlencode( $_SERVER['QUERY_STRING'] )
+ 'uri' => urlencode( $_SERVER['REQUEST_URI'] ),
+ 'query' => urlencode( $_SERVER['QUERY_STRING'] )
];
- self::redirect( "Special:SelectOpenIDConnectIssuer",
+ self::redirect( 'Special:SelectOpenIDConnectIssuer',
$params, true );
return false;
}
@@ -149,57 +155,89 @@ class OpenIDConnect extends PluggableAuth {
if ( isset( $config['proxy'] ) ) {
$oidc->setHttpProxy( $config['proxy'] );
}
+ if ( isset( $config['verifyHost'] ) ) {
+ $oidc->setVerifyHost( $config['verifyHost'] );
+ }
+ if ( isset( $config['verifyPeer'] ) ) {
+ $oidc->setVerifyPeer( $config['verifyPeer'] );
+ }
+ $redirectURL =
+ SpecialPage::getTitleFor( 'PluggableAuthLogin' )->getFullURL();
+ $oidc->setRedirectURL( $redirectURL );
+ wfDebugLog( 'OpenID Connect', 'Redirect URL: ' . $redirectURL );
if ( $oidc->authenticate() ) {
- $preferred_username =
- $oidc->requestUserInfo(
- isset( $config['preferred_username'] ) ?
- $config['preferred_username'] :
- "preferred_username"
- );
- $realname = $oidc->requestUserInfo( "name" );
- $email = $oidc->requestUserInfo( "email" );
+ $realname = $oidc->requestUserInfo( 'name' );
+ $email = $oidc->requestUserInfo( 'email' );
$this->subject = $oidc->requestUserInfo( 'sub' );
$this->issuer = $oidc->getProviderURL();
-
- $username = $this->getName( $this->subject, $this->issuer );
- if ( !is_null( $username ) ) {
+ wfDebugLog( 'OpenID Connect', 'Real name: ' . $realname .
+ ', Email: ' . $email . ', Subject: ' . $this->subject .
+ ', Issuer: ' . $this->issuer );
+
+ list( $id, $username ) =
+ $this->findUser( $this->subject, $this->issuer );
+ if ( $id !== null ) {
+ wfDebugLog( 'OpenID Connect',
+ 'Found user with matching subject and issuer.' . PHP_EOL );
return true;
}
+ wfDebugLog( 'OpenID Connect',
+ 'No user found with matching subject and issuer.' . PHP_EOL );
+
if ( $GLOBALS['wgOpenIDConnect_MigrateUsersByEmail'] === true ) {
+ wfDebugLog( 'OpenID Connect', 'Checking for email migration.' .
+ PHP_EOL );
list( $id, $username ) = $this->getMigratedIdByEmail( $email );
- if ( !is_null( $id ) ) {
+ if ( $id !== null ) {
$this->saveExtraAttributes( $id );
- wfDebug( "Migrated user " . $username . " by email: " . $email );
+ wfDebugLog( 'OpenID Connect', 'Migrated user ' . $username .
+ ' by email: ' . $email . '.' . PHP_EOL );
return true;
}
- } elseif ( $GLOBALS['wgOpenIDConnect_MigrateUsersByUserName'] === true ) {
+ }
+
+ $preferred_username = $this->getPreferredUsername( $config, $oidc,
+ $realname, $email );
+ wfDebugLog( 'OpenID Connect', 'Preferred username: ' .
+ $preferred_username . PHP_EOL );
+
+ if ( $GLOBALS['wgOpenIDConnect_MigrateUsersByUserName'] === true ) {
+ wfDebugLog( 'OpenID Connect', 'Checking for username migration.' .
+ PHP_EOL );
$id = $this->getMigratedIdByUserName( $preferred_username );
- if ( !is_null( $id ) ) {
+ if ( $id !== null ) {
$this->saveExtraAttributes( $id );
- wfDebug( "Migrated user by username: " . $preferred_username );
+ wfDebugLog( 'OpenID Connect', 'Migrated user by username: ' .
+ $preferred_username . '.' . PHP_EOL );
$username = $preferred_username;
return true;
}
}
$username = self::getAvailableUsername( $preferred_username,
- $realname, $email, $this->subject );
+ $realname, $email );
+
+ wfDebugLog( 'OpenID Connect', 'Available username: ' .
+ $username . PHP_EOL );
- $authManager = Authmanager::singleton();
+ if ( method_exists( MediaWikiServices::class, 'getAuthManager' ) ) {
+ // MediaWiki 1.35+
+ $authManager = MediaWikiServices::getInstance()->getAuthManager();
+ } else {
+ $authManager = AuthManager::singleton();
+ }
$authManager->setAuthenticationSessionData(
self::OIDC_SUBJECT_SESSION_KEY, $this->subject );
$authManager->setAuthenticationSessionData(
self::OIDC_ISSUER_SESSION_KEY, $this->issuer );
return true;
-
- } else {
- $session->clear();
- return false;
}
+
} catch ( Exception $e ) {
- wfDebug( $e->__toString() . PHP_EOL );
+ wfDebugLog( 'OpenID Connect', $e->__toString() . PHP_EOL );
+ $errorMessage = $e->__toString();
$session->clear();
return false;
}
@@ -224,138 +262,192 @@ class OpenIDConnect extends PluggableAuth {
* @param int $id user id
*/
public function saveExtraAttributes( $id ) {
- $authManager = Authmanager::singleton();
- if ( is_null( $this->subject ) ) {
+ if ( method_exists( MediaWikiServices::class, 'getAuthManager' ) ) {
+ // MediaWiki 1.35+
+ $authManager = MediaWikiServices::getInstance()->getAuthManager();
+ } else {
+ $authManager = AuthManager::singleton();
+ }
+ if ( $this->subject === null ) {
$this->subject = $authManager->getAuthenticationSessionData(
self::OIDC_SUBJECT_SESSION_KEY );
$authManager->removeAuthenticationSessionData(
self::OIDC_SUBJECT_SESSION_KEY );
}
- if ( is_null( $this->issuer ) ) {
+ if ( $this->issuer === null ) {
$this->issuer = $authManager->getAuthenticationSessionData(
self::OIDC_ISSUER_SESSION_KEY );
$authManager->removeAuthenticationSessionData(
self::OIDC_ISSUER_SESSION_KEY );
}
$dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'user',
+ $dbw->upsert(
+ 'openid_connect',
+ [
+ 'oidc_user' => $id,
+ 'oidc_subject' => $this->subject,
+ 'oidc_issuer' => $this->issuer
+ ],
+ [
+ [ 'oidc_user' ]
+ ],
[
- 'subject' => $this->subject,
- 'issuer' => $this->issuer
- ], [
- 'user_id' => $id
- ], __METHOD__
+ 'oidc_subject' => $this->subject,
+ 'oidc_issuer' => $this->issuer
+ ],
+ __METHOD__
);
}
- private static function getName( $subject, $issuer ) {
+ private static function findUser( $subject, $issuer ) {
$dbr = wfGetDB( DB_REPLICA );
- $row = $dbr->selectRow( 'user',
- [ 'user_name' ],
+ $row = $dbr->selectRow(
[
- 'subject' => $subject,
- 'issuer' => $issuer
- ], __METHOD__
+ 'user',
+ 'openid_connect'
+ ],
+ [
+ 'user_id',
+ 'user_name'
+ ],
+ [
+ 'oidc_subject' => $subject,
+ 'oidc_issuer' => $issuer
+ ],
+ __METHOD__,
+ [],
+ [
+ 'openid_connect' => [ 'JOIN', [ 'user_id=oidc_user' ] ]
+ ]
);
if ( $row === false ) {
- return null;
+ return [ null, null ];
+ } else {
+ return [ $row->user_id, $row->user_name ];
+ }
+ }
+
+ private static function getPreferredUsername( $config, $oidc, $realname,
+ $email ) {
+ if ( isset( $config['preferred_username'] ) ) {
+ wfDebugLog( 'OpenID Connect', 'Using ' . $config['preferred_username'] .
+ ' attribute for preferred username.' . PHP_EOL );
+ $preferred_username =
+ $oidc->requestUserInfo( $config['preferred_username'] );
+ } else {
+ $preferred_username = $oidc->requestUserInfo( 'preferred_username' );
+ }
+ if ( strlen( $preferred_username ) > 0 ) {
+ // do nothing
+ } elseif ( strlen( $realname ) > 0 &&
+ $GLOBALS['wgOpenIDConnect_UseRealNameAsUserName'] === true ) {
+ $preferred_username = $realname;
+ } elseif ( strlen( $email ) > 0 &&
+ $GLOBALS['wgOpenIDConnect_UseEmailNameAsUserName'] === true ) {
+ $pos = strpos( $email, '@' );
+ if ( $pos !== false && $pos > 0 ) {
+ $preferred_username = substr( $email, 0, $pos );
+ } else {
+ $preferred_username = $email;
+ }
} else {
- return $row->user_name;
+ return null;
}
+ $nt = Title::makeTitleSafe( NS_USER, $preferred_username );
+ if ( $nt === null ) {
+ return null;
+ }
+ return $nt->getText();
}
private static function getMigratedIdByUserName( $username ) {
$nt = Title::makeTitleSafe( NS_USER, $username );
- if ( is_null( $nt ) ) {
+ if ( $nt === null ) {
+ wfDebugLog( 'OpenID Connect',
+ 'Invalid preferred username for migration: ' . $username . '.' .
+ PHP_EOL );
return null;
}
$username = $nt->getText();
$dbr = wfGetDB( DB_REPLICA );
- $row = $dbr->selectRow( 'user',
- [ 'user_id' ],
+ $row = $dbr->selectRow(
+ [
+ 'user',
+ 'openid_connect'
+ ],
+ [
+ 'user_id'
+ ],
[
'user_name' => $username,
- 'subject' => null,
- 'issuer' => null
+ 'oidc_user' => null
],
- __METHOD__
+ __METHOD__,
+ [],
+ [
+ 'openid_connect' => [ 'LEFT JOIN', [ 'user_id=oidc_user' ] ]
+ ]
);
- if ( $row === false ) {
- return null;
- } else {
+ if ( $row !== false ) {
return $row->user_id;
}
+ return null;
}
private static function getMigratedIdByEmail( $email ) {
- wfDebug( "Matching user to email " . $email );
+ wfDebugLog( 'OpenID Connect', 'Matching user to email ' . $email . '.' .
+ PHP_EOL );
$dbr = wfGetDB( DB_REPLICA );
- $row = $dbr->selectRow( 'user',
+ $row = $dbr->selectRow(
+ [
+ 'user',
+ 'openid_connect'
+ ],
[
'user_id',
- 'user_name'
+ 'user_name',
+ 'oidc_user'
],
[
- 'user_email' => $email,
- 'subject' => null,
- 'issuer' => null
+ 'user_email' => $email
],
__METHOD__,
[
// if multiple matching accounts, use the oldest one
- 'ORDER BY' => 'user_registration',
- 'LIMIT' => 1
+ 'ORDER BY' => 'user_registration'
+ ],
+ [
+ 'openid_connect' => [ 'LEFT JOIN', [ 'user_id=oidc_user' ] ]
]
);
- if ( $row === false ) {
- return [ null, null ];
- } else {
+ if ( $row !== false && $row->oidc_user === null ) {
return [ $row->user_id, $row->user_name ];
}
+ return [ null, null ];
}
- private static function getAvailableUsername( $preferred_username,
- $realname, $email, $subject ) {
- if ( strlen( $preferred_username ) > 0 ) {
- $name = $preferred_username;
- } elseif ( strlen( $realname ) > 0 &&
- $GLOBALS['wgOpenIDConnect_UseRealNameAsUserName'] === true ) {
- $name = $realname;
- } elseif ( strlen( $email ) > 0 &&
- $GLOBALS['wgOpenIDConnect_UseEmailNameAsUserName'] === true ) {
- $pos = strpos( $email, '@' );
- if ( $pos !== false && $pos > 0 ) {
- $name = substr( $email, 0, $pos );
- } else {
- $name = $email;
- }
+ private static function getAvailableUsername( $preferred_username ) {
+ if ( $preferred_username === null ) {
+ $preferred_username = 'User';
}
- $nt = Title::makeTitleSafe( NS_USER, $name );
- if ( is_null( $nt ) ) {
- $name = "User";
- } elseif ( is_null( User::idFromName( $name ) ) ) {
- return $nt->getText();
- } else {
- $name = $nt->getText();
+
+ if ( User::idFromName( $preferred_username ) === null ) {
+ return $preferred_username;
}
+
$count = 1;
- while ( !is_null( User::idFromName( $name . $count ) ) ) {
+ while ( User::idFromName( $preferred_username . $count ) !== null ) {
$count++;
}
- return $name . $count;
+ return $preferred_username . $count;
}
- private static function redirect( $page, $params = null, $doExit = false ) {
+ private static function redirect( $page, $params = [], $doExit = false ) {
$title = Title::newFromText( $page );
- if ( is_null( $title ) ) {
+ if ( $title === null ) {
$title = Title::newMainPage();
}
- $url = $title->getFullURL();
- if ( is_array( $params ) && count( $params ) > 0 ) {
- foreach ( $params as $key => $value ) {
- $url = wfAppendQuery( $url, $key . '=' . $value );
- }
- }
+ $url = $title->getFullURL( $params );
header( 'Location: ' . $url );
if ( $doExit ) {
exit;
@@ -369,7 +461,34 @@ class OpenIDConnect extends PluggableAuth {
*/
public static function loadExtensionSchemaUpdates( $updater ) {
$dir = $GLOBALS['wgExtensionDirectory'] . '/OpenIDConnect/sql/';
- $updater->addExtensionField( 'user', 'subject', $dir . '/AddSubject.sql' );
- $updater->addExtensionField( 'user', 'issuer', $dir . '/AddIssuer.sql' );
+ $type = $updater->getDB()->getType();
+ $updater->addExtensionTable( 'openid_connect',
+ $dir . $type . '/AddTable.sql' );
+ $updater->addExtensionUpdate( [ [ __CLASS__, 'migrateSubjectAndIssuer' ],
+ $updater ] );
+ }
+
+ /**
+ * Migrate subject and issuer columns from user table to openid_connect
+ * table.
+ *
+ * @param DatabaseUpdater $updater
+ */
+ public static function migrateSubjectAndIssuer( $updater ) {
+ if ( $updater->getDB()->fieldExists( 'user', 'subject', __METHOD__ ) &&
+ $updater->getDB()->fieldExists( 'user', 'issuer', __METHOD__ ) ) {
+ $maintenance = new FakeMaintenance();
+ $task = $maintenance->runChild(
+ 'MigrateOIDCSubjectAndIssuerFromUserTable' );
+ if ( $task->execute() ) {
+ $dir = $GLOBALS['wgExtensionDirectory'] . '/OpenIDConnect/sql/';
+ $type = $updater->getDB()->getType();
+ $patch = $dir . $type . '/DropColumnsFromUserTable.sql';
+ $updater->modifyField( 'user', 'subject', $patch, true );
+ }
+ } else {
+ $updater->output(
+ '...user table does not have subject and issuer columns.' . PHP_EOL );
+ }
}
}
diff --git a/OpenIDConnect/src/SelectOpenIDConnectIssuer.php b/OpenIDConnect/src/SelectOpenIDConnectIssuer.php
index 62199215..b31f02fd 100644
--- a/OpenIDConnect/src/SelectOpenIDConnectIssuer.php
+++ b/OpenIDConnect/src/SelectOpenIDConnectIssuer.php
@@ -40,9 +40,8 @@ class SelectOpenIDConnectIssuer extends UnlistedSpecialPage {
if ( strlen( $_REQUEST['query'] ) > 0 ) {
$url .= "?" . urldecode( $_REQUEST['query'] );
}
- if ( session_id() == '' ) {
- wfSetupSession();
- }
+ $this->getRequest()->getSession()->persist();
+
$_SESSION['iss'] = $_REQUEST['iss'];
$GLOBALS['wgOut']->redirect( $url );
} else {
diff --git a/OpenIDConnect/version b/OpenIDConnect/version
deleted file mode 100644
index a25699de..00000000
--- a/OpenIDConnect/version
+++ /dev/null
@@ -1,4 +0,0 @@
-OpenIDConnect: REL1_31
-2020-05-25T18:25:51
-
-baea47f