summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Magorsch <arzano@gentoo.org>2020-05-27 02:30:01 +0200
committerMax Magorsch <arzano@gentoo.org>2020-05-27 02:30:01 +0200
commit881c1e396ad9ace944b022394fdda1d1d95d3b51 (patch)
treece22601f07aa36fb5ee31a28d9075c6163887153
parentAdd OpenIDConnect extension for Gentoo SSO (diff)
downloadextensions-881c1e396ad9ace944b022394fdda1d1d95d3b51.tar.gz
extensions-881c1e396ad9ace944b022394fdda1d1d95d3b51.tar.bz2
extensions-881c1e396ad9ace944b022394fdda1d1d95d3b51.zip
Add PluggableAuth extension for OpenID Connect
Signed-off-by: Max Magorsch <arzano@gentoo.org>
-rw-r--r--PluggableAuth/.dir-locals.el88
-rw-r--r--PluggableAuth/.gitignore23
-rw-r--r--PluggableAuth/.gitreview6
-rw-r--r--PluggableAuth/.phpcs.xml7
-rw-r--r--PluggableAuth/.phpmd.xml29
-rw-r--r--PluggableAuth/CODE_OF_CONDUCT.md1
-rw-r--r--PluggableAuth/COPYING19
-rw-r--r--PluggableAuth/Gruntfile.js21
-rw-r--r--PluggableAuth/composer.json41
-rw-r--r--PluggableAuth/extension.json57
-rw-r--r--PluggableAuth/gitinfo.json1
-rw-r--r--PluggableAuth/i18n/ast.json13
-rw-r--r--PluggableAuth/i18n/be-tarask.json13
-rw-r--r--PluggableAuth/i18n/de.json13
-rw-r--r--PluggableAuth/i18n/el.json8
-rw-r--r--PluggableAuth/i18n/en.json13
-rw-r--r--PluggableAuth/i18n/es.json10
-rw-r--r--PluggableAuth/i18n/fi.json12
-rw-r--r--PluggableAuth/i18n/fr.json15
-rw-r--r--PluggableAuth/i18n/gl.json13
-rw-r--r--PluggableAuth/i18n/it.json10
-rw-r--r--PluggableAuth/i18n/ko.json12
-rw-r--r--PluggableAuth/i18n/ksh.json9
-rw-r--r--PluggableAuth/i18n/lb.json11
-rw-r--r--PluggableAuth/i18n/lv.json8
-rw-r--r--PluggableAuth/i18n/mk.json13
-rw-r--r--PluggableAuth/i18n/ms.json8
-rw-r--r--PluggableAuth/i18n/nl.json9
-rw-r--r--PluggableAuth/i18n/oc.json8
-rw-r--r--PluggableAuth/i18n/pl.json8
-rw-r--r--PluggableAuth/i18n/pt-br.json13
-rw-r--r--PluggableAuth/i18n/pt.json14
-rw-r--r--PluggableAuth/i18n/qqq.json15
-rw-r--r--PluggableAuth/i18n/roa-tara.json9
-rw-r--r--PluggableAuth/i18n/ru.json8
-rw-r--r--PluggableAuth/i18n/sv.json10
-rw-r--r--PluggableAuth/i18n/tl.json8
-rw-r--r--PluggableAuth/i18n/uk.json14
-rw-r--r--PluggableAuth/i18n/zh-hans.json13
-rw-r--r--PluggableAuth/i18n/zh-hant.json14
-rw-r--r--PluggableAuth/includes/PluggableAuth.alias.php16
-rw-r--r--PluggableAuth/includes/PluggableAuth.php54
-rw-r--r--PluggableAuth/includes/PluggableAuthBeginAuthenticationRequest.php35
-rw-r--r--PluggableAuth/includes/PluggableAuthContinueAuthenticationRequest.php33
-rw-r--r--PluggableAuth/includes/PluggableAuthHooks.php161
-rw-r--r--PluggableAuth/includes/PluggableAuthLogin.php83
-rw-r--r--PluggableAuth/includes/PluggableAuthPrimaryAuthenticationProvider.php182
-rw-r--r--PluggableAuth/package.json11
-rw-r--r--PluggableAuth/version4
49 files changed, 1196 insertions, 0 deletions
diff --git a/PluggableAuth/.dir-locals.el b/PluggableAuth/.dir-locals.el
new file mode 100644
index 00000000..22804955
--- /dev/null
+++ b/PluggableAuth/.dir-locals.el
@@ -0,0 +1,88 @@
+((nil . ((mode . flycheck)
+ (mode . company)
+ (mode . edep)
+ (mode . subword)
+ (tab-width . 4)
+ (c-basic-offset . 4)
+ (indent-tabs-mode . t)
+ (eval . (progn (when (fboundp 'delete-trailing-whitespace)
+ (delete-trailing-whitespace))
+ (tabify (point-min) (point-max))))
+ (c-hanging-braces-alist
+ (defun-open after)
+ (block-open after)
+ (defun-close))
+ (c-offsets-alist . (
+ (access-label . -)
+ (annotation-top-cont . 0)
+ (annotation-var-cont . +)
+ (arglist-close . php-lineup-arglist-close)
+ (arglist-cont-nonempty first
+ php-lineup-cascaded-calls
+ c-lineup-arglist)
+ (arglist-intro . php-lineup-arglist-intro)
+ (block-close . 0)
+ (block-open . 0)
+ (brace-entry-open . 0)
+ (brace-list-close . 0)
+ (brace-list-entry . 0)
+ (brace-list-intro . +)
+ (brace-list-open . 0)
+ (c . c-lineup-C-comments)
+ (case-label . 0)
+ (catch-clause . 0)
+ (class-close . 0)
+ (comment-intro . 0)
+ (composition-close . 0)
+ (composition-open . 0)
+ (cpp-define-intro c-lineup-cpp-define +)
+ (cpp-macro . [0])
+ (cpp-macro-cont . +)
+ (defun-block-intro . +)
+ (defun-close . 0)
+ (defun-open . 0)
+ (do-while-closure . 0)
+ (else-clause . 0)
+ (extern-lang-close . 0)
+ (extern-lang-open . 0)
+ (friend . 0)
+ (func-decl-cont . +)
+ (inclass . +)
+ (incomposition . +)
+ (inexpr-class . +)
+ (inexpr-statement . +)
+ (inextern-lang . +)
+ (inher-cont . c-lineup-multi-inher)
+ (inher-intro . +)
+ (inlambda . 0)
+ (inline-close . 0)
+ (inline-open . 0)
+ (inmodule . +)
+ (innamespace . +)
+ (knr-argdecl . 0)
+ (knr-argdecl-intro . +)
+ (label . +)
+ (lambda-intro-cont . +)
+ (member-init-cont . c-lineup-multi-inher)
+ (member-init-intro . +)
+ (module-close . 0)
+ (module-open . 0)
+ (namespace-close . 0)
+ (namespace-open . 0)
+ (statement . 0)
+ (statement-block-intro . +)
+ (statement-case-intro . +)
+ (statement-case-open . 0)
+ (statement-cont first
+ php-lineup-cascaded-calls
+ php-lineup-string-cont +)
+ (stream-op . c-lineup-streamop)
+ (string . c-lineup-dont-change)
+ (substatement . +)
+ (substatement-label . 2)
+ (substatement-open . 0)
+ (template-args-cont c-lineup-template-args +)
+ (topmost-intro . 0)
+ (topmost-intro-cont first php-lineup-cascaded-calls +)
+ ))
+ )))
diff --git a/PluggableAuth/.gitignore b/PluggableAuth/.gitignore
new file mode 100644
index 00000000..8aa2a07f
--- /dev/null
+++ b/PluggableAuth/.gitignore
@@ -0,0 +1,23 @@
+node_modules/
+vendor/
+composer.lock
+
+# Editors
+*.kate-swp
+*~
+\#*#
+.#*
+.*.swp
+.project
+.buildpath
+.classpath
+.settings
+cscope.files
+cscope.out
+*.orig
+## NetBeans
+nbproject*
+project.index
+## Sublime
+sublime-*
+sftp-config.json
diff --git a/PluggableAuth/.gitreview b/PluggableAuth/.gitreview
new file mode 100644
index 00000000..5376489b
--- /dev/null
+++ b/PluggableAuth/.gitreview
@@ -0,0 +1,6 @@
+[gerrit]
+host=gerrit.wikimedia.org
+port=29418
+project=mediawiki/extensions/PluggableAuth.git
+track=1
+defaultrebase=0
diff --git a/PluggableAuth/.phpcs.xml b/PluggableAuth/.phpcs.xml
new file mode 100644
index 00000000..b915cf83
--- /dev/null
+++ b/PluggableAuth/.phpcs.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<ruleset>
+ <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki" />
+ <file>.</file>
+ <arg name="extensions" value="php"/>
+ <arg name="encoding" value="UTF-8"/>
+</ruleset>
diff --git a/PluggableAuth/.phpmd.xml b/PluggableAuth/.phpmd.xml
new file mode 100644
index 00000000..2c2ab34c
--- /dev/null
+++ b/PluggableAuth/.phpmd.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<ruleset xmlns="http://pmd.sf.net/ruleset/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
+ xsi:noNamespaceSchemaLocation=" http://pmd.sf.net/ruleset_xml_schema.xsd">
+
+ <rule ref="rulesets/codesize.xml">
+ <exclude name="TooManyMethods" />
+ <exclude name="ExcessiveClassComplexity" />
+ </rule>
+ <rule ref="rulesets/codesize.xml/TooManyMethods">
+ <properties>
+ <property name="maxmethods" value="20" />
+ </properties>
+ </rule>
+
+ <!-- todo: exclude the camel case method rule for the tests -->
+ <rule ref="rulesets/controversial.xml" />
+
+ <rule ref="rulesets/design.xml" />
+
+ <rule ref="rulesets/naming.xml">
+ <exclude name="ShortVariable" />
+ </rule>
+
+ <rule ref="rulesets/unusedcode.xml">
+ <exclude name="UnusedLocalVariable" />
+ </rule>
+</ruleset>
diff --git a/PluggableAuth/CODE_OF_CONDUCT.md b/PluggableAuth/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..d8e5d087
--- /dev/null
+++ b/PluggableAuth/CODE_OF_CONDUCT.md
@@ -0,0 +1 @@
+The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Code_of_Conduct).
diff --git a/PluggableAuth/COPYING b/PluggableAuth/COPYING
new file mode 100644
index 00000000..69cbaabb
--- /dev/null
+++ b/PluggableAuth/COPYING
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2017 The MITRE Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/PluggableAuth/Gruntfile.js b/PluggableAuth/Gruntfile.js
new file mode 100644
index 00000000..a45071e1
--- /dev/null
+++ b/PluggableAuth/Gruntfile.js
@@ -0,0 +1,21 @@
+/*jshint node:true */
+module.exports = function ( grunt ) {
+ grunt.loadNpmTasks( 'grunt-jsonlint' );
+ grunt.loadNpmTasks( 'grunt-banana-checker' );
+
+ grunt.initConfig( {
+ banana: {
+ all: 'i18n/'
+ },
+ jsonlint: {
+ all: [
+ '**/*.json',
+ '!node_modules/**',
+ '!vendor/**'
+ ]
+ }
+ } );
+
+ grunt.registerTask( 'test', [ 'jsonlint', 'banana' ] );
+ grunt.registerTask( 'default', 'test' );
+};
diff --git a/PluggableAuth/composer.json b/PluggableAuth/composer.json
new file mode 100644
index 00000000..0e7c221d
--- /dev/null
+++ b/PluggableAuth/composer.json
@@ -0,0 +1,41 @@
+{
+ "name": "mediawiki/pluggable-auth",
+ "license": "MIT",
+ "type": "mediawiki-extension",
+ "homepage": "https://www.mediawiki.org/wiki/Extension:PluggableAuth",
+ "description": "An authentication framework for MediaWiki",
+ "keywords": [
+ "extension",
+ "wiki",
+ "mediawiki",
+ "authentication"
+ ],
+ "authors": [
+ {
+ "name": "Cindy Cicalese",
+ "email": "cindom@gmail.com",
+ "role": "Contributor"
+ }
+ ],
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "1.0.0",
+ "jakub-onderka/php-console-highlighter": "0.3.2",
+ "mediawiki/minus-x": "0.3.1",
+ "mediawiki/mediawiki-codesniffer": "18.0.0",
+ "phpmd/phpmd": "~2.1"
+ },
+ "scripts": {
+ "phpunit": "php $MW_INSTALL_PATH/tests/phpunit/phpunit.php -c .phpunit.xml.dist",
+ "phpdbg": "phpdbg -qrr $MW_INSTALL_PATH/tests/phpunit/phpunit.php -c .phpunit.xml.dist",
+ "test": [
+ "parallel-lint . --exclude vendor --exclude node_modules",
+ "minus-x check .",
+ "phpmd includes text .phpmd.xml || :",
+ "phpcs -p -s"
+ ],
+ "fix": [
+ "minus-x fix .",
+ "phpcbf"
+ ]
+ }
+}
diff --git a/PluggableAuth/extension.json b/PluggableAuth/extension.json
new file mode 100644
index 00000000..39667cdd
--- /dev/null
+++ b/PluggableAuth/extension.json
@@ -0,0 +1,57 @@
+{
+ "name": "PluggableAuth",
+ "version": "5.4",
+ "author": [
+ "[https://www.mediawiki.org/wiki/User:Cindy.cicalese Cindy Cicalese]"
+ ],
+ "url": "https://www.mediawiki.org/wiki/Extension:PluggableAuth",
+ "descriptionmsg": "pluggableauth-desc",
+ "type": "other",
+ "SpecialPages": {
+ "PluggableAuthLogin": "PluggableAuthLogin"
+ },
+ "MessagesDirs": {
+ "PluggableAuth": [
+ "i18n"
+ ]
+ },
+ "ExtensionMessagesFiles": {
+ "PluggableAuthAlias": "includes/PluggableAuth.alias.php"
+ },
+ "AutoloadClasses": {
+ "PluggableAuth": "includes/PluggableAuth.php",
+ "PluggableAuthHooks": "includes/PluggableAuthHooks.php",
+ "PluggableAuthPrimaryAuthenticationProvider": "includes/PluggableAuthPrimaryAuthenticationProvider.php",
+ "PluggableAuthBeginAuthenticationRequest": "includes/PluggableAuthBeginAuthenticationRequest.php",
+ "PluggableAuthContinueAuthenticationRequest": "includes/PluggableAuthContinueAuthenticationRequest.php",
+ "PluggableAuthLogin": "includes/PluggableAuthLogin.php"
+ },
+ "callback": "PluggableAuthHooks::onRegistration",
+ "Hooks": {
+ "TitleReadWhitelist": "PluggableAuthHooks::onTitleReadWhitelist",
+ "UserLogoutComplete": "PluggableAuthHooks::deauthenticate",
+ "AuthChangeFormFields": "PluggableAuthHooks::onAuthChangeFormFields",
+ "PersonalUrls": "PluggableAuthHooks::modifyLoginURLs",
+ "BeforeInitialize": "PluggableAuthHooks::doBeforeInitialize"
+ },
+ "AuthManagerAutoConfig": {
+ "primaryauth": {
+ "PluggableAuthPrimaryAuthenticationProvider": {
+ "class": "PluggableAuthPrimaryAuthenticationProvider",
+ "sort": 0
+ }
+ }
+ },
+ "PluggableAuthLoginSpecialPages": [
+ "PluggableAuthLogin",
+ "Userlogin"
+ ],
+ "config": {
+ "PluggableAuth_EnableAutoLogin": false,
+ "PluggableAuth_EnableLocalLogin": false,
+ "PluggableAuth_EnableLocalProperties": false,
+ "PluggableAuth_ButtonLabel": null,
+ "PluggableAuth_ExtraLoginFields": []
+ },
+ "manifest_version": 1
+}
diff --git a/PluggableAuth/gitinfo.json b/PluggableAuth/gitinfo.json
new file mode 100644
index 00000000..c7656a1e
--- /dev/null
+++ b/PluggableAuth/gitinfo.json
@@ -0,0 +1 @@
+{"branch": "300ac44dde702b9f36fab06c7d75f943d89c510c\n", "headSHA1": "300ac44dde702b9f36fab06c7d75f943d89c510c\n", "remoteURL": "https://gerrit-replica.wikimedia.org/r/mediawiki/extensions/PluggableAuth", "headCommitDate": "1523683714", "head": "300ac44dde702b9f36fab06c7d75f943d89c510c\n"} \ No newline at end of file
diff --git a/PluggableAuth/i18n/ast.json b/PluggableAuth/i18n/ast.json
new file mode 100644
index 00000000..0c7e1a82
--- /dev/null
+++ b/PluggableAuth/i18n/ast.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Xuacu"
+ ]
+ },
+ "pluggableauth-desc": "Ufre un marcu p'autenticación y autorización coneutable",
+ "pluggableauth-not-authorized": "{{GENDER:$1|L'usuariu|La usuaria}} $1 nun ta {{GENDER:$1|autorizáu|autorizada}}.",
+ "pluggableauth-authentication-failure": "Fallu n'autenticación o autorización.",
+ "pluggableauth-authentication-workflow-failure": "Fallu nel procesu d'autenticación.",
+ "pluggableauth-loginbutton-label": "Aniciar sesión con PluggableAuth",
+ "pluggableauth-loginbutton-help": "Autentícate con PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/be-tarask.json b/PluggableAuth/i18n/be-tarask.json
new file mode 100644
index 00000000..c8507ea1
--- /dev/null
+++ b/PluggableAuth/i18n/be-tarask.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Red Winged Duck"
+ ]
+ },
+ "pluggableauth-desc": "Забясьпечвае структуру для зьменнай аўтэнтыфікацыі і аўтарызацыі",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Удзельнік|Удзельніца}} $1 не {{GENDER:$1|аўтарызаваны|аўтарызаваная}}.",
+ "pluggableauth-authentication-failure": "Удзельнік ня можа быць аўтэнтыфікаваны.",
+ "pluggableauth-authentication-workflow-failure": "Памылка працэсу аўтэнтыфікацыі.",
+ "pluggableauth-loginbutton-label": "Увайсьці ў сыстэму з дапамогай PluggableAuth",
+ "pluggableauth-loginbutton-help": "Аўтэнтыфікуе вас з дапамогай PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/de.json b/PluggableAuth/i18n/de.json
new file mode 100644
index 00000000..f3723e5c
--- /dev/null
+++ b/PluggableAuth/i18n/de.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Metalhead64"
+ ]
+ },
+ "pluggableauth-desc": "Ergänzt ein Framework zur Authentifikation und Autorisierung",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Der Benutzer|Die Benutzerin}} $1 ist nicht berechtigt.",
+ "pluggableauth-authentication-failure": "Der Benutzer konnte nicht authentifiziert werden.",
+ "pluggableauth-authentication-workflow-failure": "Authentifikations-Workflow-Fehler.",
+ "pluggableauth-loginbutton-label": "Mit PluggableAuth anmelden",
+ "pluggableauth-loginbutton-help": "Authentifiziert dich mit PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/el.json b/PluggableAuth/i18n/el.json
new file mode 100644
index 00000000..5ebbcbb3
--- /dev/null
+++ b/PluggableAuth/i18n/el.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Nikosgranturismogt"
+ ]
+ },
+ "pluggableauth-loginbutton-label": "Συνδεθείτε με το PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/en.json b/PluggableAuth/i18n/en.json
new file mode 100644
index 00000000..575186c3
--- /dev/null
+++ b/PluggableAuth/i18n/en.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "cicalese"
+ ]
+ },
+ "pluggableauth-desc": "Provides framework for pluggable authentication and authorization",
+ "pluggableauth-not-authorized": "{{GENDER:$1|User}} $1 not authorized.",
+ "pluggableauth-authentication-failure": "User cannot be authenticated.",
+ "pluggableauth-authentication-workflow-failure": "Authentication workflow failure.",
+ "pluggableauth-loginbutton-label": "Log in with PluggableAuth",
+ "pluggableauth-loginbutton-help": "Authenticates you with PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/es.json b/PluggableAuth/i18n/es.json
new file mode 100644
index 00000000..8d9b4ff9
--- /dev/null
+++ b/PluggableAuth/i18n/es.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Macofe"
+ ]
+ },
+ "pluggableauth-desc": "Proporciona el marco para anexar autenticación y autorización",
+ "pluggableauth-not-authorized": "{{GENDER:$1|El usuario|La usuaria}} $1 no está {{GENDER:$1|autorizado|autorizada}}.",
+ "pluggableauth-authentication-failure": "El usuario no puede autenticarse."
+}
diff --git a/PluggableAuth/i18n/fi.json b/PluggableAuth/i18n/fi.json
new file mode 100644
index 00000000..2e3edf3f
--- /dev/null
+++ b/PluggableAuth/i18n/fi.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Nike",
+ "Olkitu"
+ ]
+ },
+ "pluggableauth-not-authorized": "{{GENDER:$1|Käyttäjää}} $1 ei ole valtuutettu.",
+ "pluggableauth-authentication-failure": "Kirjautuminen epäonnistui.",
+ "pluggableauth-loginbutton-label": "Kirjaudu PluggableAuth:lla.",
+ "pluggableauth-loginbutton-help": "Kirjauduttu PluggableAuth avulla."
+}
diff --git a/PluggableAuth/i18n/fr.json b/PluggableAuth/i18n/fr.json
new file mode 100644
index 00000000..faeac847
--- /dev/null
+++ b/PluggableAuth/i18n/fr.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Wladek92",
+ "Gomoko",
+ "Urhixidur"
+ ]
+ },
+ "pluggableauth-desc": "Fournit le cadre d’application pour les greffons d’authentication et d’autorisation",
+ "pluggableauth-not-authorized": "Utilisat{{GENDER:$1|eur|rice}} $1 non autorisé{{GENDER:$1||e}}.",
+ "pluggableauth-authentication-failure": "L’utilisateur n’a pas pu être authentifié.",
+ "pluggableauth-authentication-workflow-failure": "Échec du processus d’authentification.",
+ "pluggableauth-loginbutton-label": "Se connecter avec PluggableAuth",
+ "pluggableauth-loginbutton-help": "Vous authentifie avec PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/gl.json b/PluggableAuth/i18n/gl.json
new file mode 100644
index 00000000..8a54011b
--- /dev/null
+++ b/PluggableAuth/i18n/gl.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Elisardojm"
+ ]
+ },
+ "pluggableauth-desc": "Proporciona o marco para anexar autenticación e autorización",
+ "pluggableauth-not-authorized": "{{GENDER:$1|O usuario|A usuaria}} $1 non está {{GENDER:$1|autorizado|autorizada}}.",
+ "pluggableauth-authentication-failure": "O usuario non pode autenticarse.",
+ "pluggableauth-authentication-workflow-failure": "Fallo no proceso de autenticación.",
+ "pluggableauth-loginbutton-label": "Conectarse con PluggableAuth",
+ "pluggableauth-loginbutton-help": "Autentícao con PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/it.json b/PluggableAuth/i18n/it.json
new file mode 100644
index 00000000..bdde8193
--- /dev/null
+++ b/PluggableAuth/i18n/it.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beta16"
+ ]
+ },
+ "pluggableauth-not-authorized": "Utente $1 non {{GENDER:$1|autorizzato|autorizzata|autorizzato/a}}.",
+ "pluggableauth-loginbutton-label": "Accedi con PluggableAuth",
+ "pluggableauth-loginbutton-help": "Autenticati con PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/ko.json b/PluggableAuth/i18n/ko.json
new file mode 100644
index 00000000..96e670f1
--- /dev/null
+++ b/PluggableAuth/i18n/ko.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Revi",
+ "Ykhwong"
+ ]
+ },
+ "pluggableauth-desc": "플러그 가능한 식별과 인증을 위한 프레임워크 제공",
+ "pluggableauth-not-authorized": "$1 {{GENDER:$1|사용자}}가 인증되지 않았습니다.",
+ "pluggableauth-authentication-failure": "사용자를 인증할 수 없습니다.",
+ "pluggableauth-loginbutton-label": "PluggableAuth로 로그인"
+}
diff --git a/PluggableAuth/i18n/ksh.json b/PluggableAuth/i18n/ksh.json
new file mode 100644
index 00000000..ae7b2344
--- /dev/null
+++ b/PluggableAuth/i18n/ksh.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Purodha"
+ ]
+ },
+ "pluggableauth-desc": "Brängk ene Rahme för ußtuuschbahre Ongerprojramme för et Aanmällde un esu.",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} es nit berääschtesch."
+}
diff --git a/PluggableAuth/i18n/lb.json b/PluggableAuth/i18n/lb.json
new file mode 100644
index 00000000..96cc722f
--- /dev/null
+++ b/PluggableAuth/i18n/lb.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robby"
+ ]
+ },
+ "pluggableauth-not-authorized": "{{GENDER:$1|De Benotzer}} $1 ass net autoriséiert.",
+ "pluggableauth-authentication-failure": "Benotzer kann net authentifizéiert ginn.",
+ "pluggableauth-loginbutton-label": "Mat PluggableAuth aloggen",
+ "pluggableauth-loginbutton-help": "Authentifizéiert Iech mat PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/lv.json b/PluggableAuth/i18n/lv.json
new file mode 100644
index 00000000..c11b2504
--- /dev/null
+++ b/PluggableAuth/i18n/lv.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Papuass"
+ ]
+ },
+ "pluggableauth-authentication-failure": "Lietotāju nevar autentificēt."
+}
diff --git a/PluggableAuth/i18n/mk.json b/PluggableAuth/i18n/mk.json
new file mode 100644
index 00000000..efed3479
--- /dev/null
+++ b/PluggableAuth/i18n/mk.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06"
+ ]
+ },
+ "pluggableauth-desc": "Дава рамка за приклучна заверка и овластување",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Корисникот}} $1 не е овластен.",
+ "pluggableauth-authentication-failure": "Неуспешна заверка или овластување.",
+ "pluggableauth-authentication-workflow-failure": "Неупех во работниот тек на заверката.",
+ "pluggableauth-loginbutton-label": "Најава со PluggableAuth",
+ "pluggableauth-loginbutton-help": "Ве заверува со PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/ms.json b/PluggableAuth/i18n/ms.json
new file mode 100644
index 00000000..713aeb97
--- /dev/null
+++ b/PluggableAuth/i18n/ms.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia"
+ ]
+ },
+ "pluggableauth-not-authorized": "{{GENDER:$1|Pengguna}} $1 tidak diizinkan."
+}
diff --git a/PluggableAuth/i18n/nl.json b/PluggableAuth/i18n/nl.json
new file mode 100644
index 00000000..3551e265
--- /dev/null
+++ b/PluggableAuth/i18n/nl.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Esketti"
+ ]
+ },
+ "pluggableauth-desc": "Biedt een kader voor pluggable authenticatie en autorisatie",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Gebruikers}} $1 niet toegestaan."
+}
diff --git a/PluggableAuth/i18n/oc.json b/PluggableAuth/i18n/oc.json
new file mode 100644
index 00000000..f2bac0b7
--- /dev/null
+++ b/PluggableAuth/i18n/oc.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31"
+ ]
+ },
+ "pluggableauth-not-authorized": "{{GENDER:$1|Utilizaire|Utilizaira}} $1 pas {{GENDER:$1|autorizat|autorizada}}."
+}
diff --git a/PluggableAuth/i18n/pl.json b/PluggableAuth/i18n/pl.json
new file mode 100644
index 00000000..5b5cd688
--- /dev/null
+++ b/PluggableAuth/i18n/pl.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chrumps"
+ ]
+ },
+ "pluggableauth-authentication-failure": "Użytkownik nie może być uwierzytelniony."
+}
diff --git a/PluggableAuth/i18n/pt-br.json b/PluggableAuth/i18n/pt-br.json
new file mode 100644
index 00000000..7f113da3
--- /dev/null
+++ b/PluggableAuth/i18n/pt-br.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Eduardo Addad de Oliveira"
+ ]
+ },
+ "pluggableauth-desc": "Fornece uma estrutura para autenticação e autorização modulares",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Usuário $1 não autorizado|Usuária $1 não autorizada}}.",
+ "pluggableauth-authentication-failure": "O usuário não pode ser autenticado.",
+ "pluggableauth-authentication-workflow-failure": "Falha no processo de autenticação.",
+ "pluggableauth-loginbutton-label": "Iniciar sessão com PluggableAuth",
+ "pluggableauth-loginbutton-help": "Faz a sua autenticação com PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/pt.json b/PluggableAuth/i18n/pt.json
new file mode 100644
index 00000000..80bfa88a
--- /dev/null
+++ b/PluggableAuth/i18n/pt.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Vitorvicentevalente",
+ "Hamilton Abreu"
+ ]
+ },
+ "pluggableauth-desc": "Fornece uma estrutura para autenticação e autorização modulares",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Utilizador $1 não autorizado|Utilizadora $1 não autorizada}}.",
+ "pluggableauth-authentication-failure": "Não foi possível autenticar o utilizador.",
+ "pluggableauth-authentication-workflow-failure": "Falha no processo de autenticação.",
+ "pluggableauth-loginbutton-label": "Iniciar sessão com PluggableAuth",
+ "pluggableauth-loginbutton-help": "Faz a sua autenticação com PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/qqq.json b/PluggableAuth/i18n/qqq.json
new file mode 100644
index 00000000..c6f0b658
--- /dev/null
+++ b/PluggableAuth/i18n/qqq.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "cicalese",
+ "Liuxinyu970226",
+ "Umherirrender"
+ ]
+ },
+ "pluggableauth-desc": "{{desc|name=Pluggable Auth|url=https://www.mediawiki.org/wiki/Extension:PluggableAuth}}",
+ "pluggableauth-not-authorized": "Text to display when an authorization plugin indicates that the user is not authorized to log in. Parameters:\n* $1 - a username with GENDER support.",
+ "pluggableauth-authentication-failure": "Failure message when there is an authentication or authorization failure (e.g. User not authorized).",
+ "pluggableauth-authentication-workflow-failure": "Failure message when there is an error in authentication workflow, such as an AuthenticationRequest being received in the wrong action.",
+ "pluggableauth-loginbutton-label": "Used as label for the button shown in [[Special:UserLogin]].",
+ "pluggableauth-loginbutton-help": "Help message used for the Login with PluggableAuth button on [[Special:UserLogin]]."
+}
diff --git a/PluggableAuth/i18n/roa-tara.json b/PluggableAuth/i18n/roa-tara.json
new file mode 100644
index 00000000..0ec95f29
--- /dev/null
+++ b/PluggableAuth/i18n/roa-tara.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joetaras"
+ ]
+ },
+ "pluggableauth-desc": "Dèje 'nu framework pe attaccà autendicaziune e autorizzazziune",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Utende}} $1 none autorizzate."
+}
diff --git a/PluggableAuth/i18n/ru.json b/PluggableAuth/i18n/ru.json
new file mode 100644
index 00000000..9a4bda29
--- /dev/null
+++ b/PluggableAuth/i18n/ru.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kareyac"
+ ]
+ },
+ "pluggableauth-authentication-failure": "Пользователь не может быть аутентифицирован."
+}
diff --git a/PluggableAuth/i18n/sv.json b/PluggableAuth/i18n/sv.json
new file mode 100644
index 00000000..6f5efb70
--- /dev/null
+++ b/PluggableAuth/i18n/sv.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lokal Profil",
+ "WikiPhoenix"
+ ]
+ },
+ "pluggableauth-not-authorized": "{{GENDER:$1|Användare}} $1 är inte auktoriserad.",
+ "pluggableauth-loginbutton-label": "Logga in med PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/tl.json b/PluggableAuth/i18n/tl.json
new file mode 100644
index 00000000..2a498ac5
--- /dev/null
+++ b/PluggableAuth/i18n/tl.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Emem.calist"
+ ]
+ },
+ "pluggableauth-loginbutton-label": "Mag-Log in gamit ang 'PluggableAuth'"
+}
diff --git a/PluggableAuth/i18n/uk.json b/PluggableAuth/i18n/uk.json
new file mode 100644
index 00000000..3ab0b638
--- /dev/null
+++ b/PluggableAuth/i18n/uk.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ата",
+ "Piramidion"
+ ]
+ },
+ "pluggableauth-desc": "Забезпечує основу для змінної автентифікації та авторизації",
+ "pluggableauth-not-authorized": "{{GENDER:$1|Користувач $1 не авторизований|Користувачка $1 не авторизована}}.",
+ "pluggableauth-authentication-failure": "Автентифікація користувача неможлива.",
+ "pluggableauth-authentication-workflow-failure": "Помилка процесу автентифікації.",
+ "pluggableauth-loginbutton-label": "Увійти в систему за допомогою PluggableAuth",
+ "pluggableauth-loginbutton-help": "Автентифікує Вас через PluggableAuth"
+}
diff --git a/PluggableAuth/i18n/zh-hans.json b/PluggableAuth/i18n/zh-hans.json
new file mode 100644
index 00000000..2fa466db
--- /dev/null
+++ b/PluggableAuth/i18n/zh-hans.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Liuxinyu970226"
+ ]
+ },
+ "pluggableauth-desc": "提供框架用于插接式身份认证和授权",
+ "pluggableauth-not-authorized": "{{GENDER:$1|用户}}$1未获授权。",
+ "pluggableauth-authentication-failure": "用户身份不能被验证。",
+ "pluggableauth-authentication-workflow-failure": "身份验证工作流失败。",
+ "pluggableauth-loginbutton-label": "通过PluggableAuth登录",
+ "pluggableauth-loginbutton-help": "使用PluggableAuth验证您的身份"
+}
diff --git a/PluggableAuth/i18n/zh-hant.json b/PluggableAuth/i18n/zh-hant.json
new file mode 100644
index 00000000..09481355
--- /dev/null
+++ b/PluggableAuth/i18n/zh-hant.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Liuxinyu970226",
+ "Kly"
+ ]
+ },
+ "pluggableauth-desc": "提供可插入式的驗證與授權框架",
+ "pluggableauth-not-authorized": "{{GENDER:$1|使用者}} $1 沒有取得授權。",
+ "pluggableauth-authentication-failure": "使用者無法被驗證。",
+ "pluggableauth-authentication-workflow-failure": "驗證流程失敗。",
+ "pluggableauth-loginbutton-label": "以 PluggableAuth 登入",
+ "pluggableauth-loginbutton-help": "以 PluggableAuth 來驗證您的身份"
+}
diff --git a/PluggableAuth/includes/PluggableAuth.alias.php b/PluggableAuth/includes/PluggableAuth.alias.php
new file mode 100644
index 00000000..df3accfa
--- /dev/null
+++ b/PluggableAuth/includes/PluggableAuth.alias.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * Aliases for special pages
+ *
+ * @file
+ * @ingroup Extensions
+ */
+// @codingStandardsIgnoreFile
+
+$specialPageAliases = [];
+
+/** English (English) */
+$specialPageAliases['en'] = [
+ 'PluggableAuthLogin' => ['PluggableAuthLogin'],
+];
diff --git a/PluggableAuth/includes/PluggableAuth.php b/PluggableAuth/includes/PluggableAuth.php
new file mode 100644
index 00000000..8ecf4e40
--- /dev/null
+++ b/PluggableAuth/includes/PluggableAuth.php
@@ -0,0 +1,54 @@
+<?php
+
+abstract class PluggableAuth {
+
+ /**
+ * @since 1.0
+ *
+ * @param int &$id The user's user ID
+ * @param string &$username The user's user name
+ * @param string &$realname The user's real name
+ * @param string &$email The user's email address
+ * @param string &$errorMessage Returns a descritive message if
+ * there's an error
+ */
+ abstract public function authenticate( &$id, &$username, &$realname,
+ &$email, &$errorMessage );
+
+ /**
+ * @since 1.0
+ *
+ * @param User &$user The user
+ */
+ abstract public function deauthenticate( User &$user );
+
+ /**
+ * @since 1.0
+ *
+ * @param int $id The user's user ID
+ */
+ abstract public function saveExtraAttributes( $id );
+
+ private static $instance = null;
+
+ /**
+ * @since 2.0
+ * @return PluggableAuth a PluggableAuth object
+ */
+ public static function singleton() {
+ wfDebugLog( 'PluggableAuth', 'Getting PluggableAuth singleton' );
+ wfDebugLog( 'PluggableAuth', 'Class name: ' . $GLOBALS['wgPluggableAuth_Class'] );
+ if ( !is_null( self::$instance ) ) {
+ wfDebugLog( 'PluggableAuth', 'Singleton already exists' );
+ return self::$instance;
+ } elseif ( isset( $GLOBALS['wgPluggableAuth_Class'] ) &&
+ class_exists( $GLOBALS['wgPluggableAuth_Class'] ) &&
+ is_subclass_of( $GLOBALS['wgPluggableAuth_Class'],
+ 'PluggableAuth' ) ) {
+ self::$instance = new $GLOBALS['wgPluggableAuth_Class'];
+ return self::$instance;
+ }
+ wfDebugLog( 'PluggableAuth', 'Could not get authentication plugin instance.' );
+ return false;
+ }
+}
diff --git a/PluggableAuth/includes/PluggableAuthBeginAuthenticationRequest.php b/PluggableAuth/includes/PluggableAuthBeginAuthenticationRequest.php
new file mode 100644
index 00000000..04831fb8
--- /dev/null
+++ b/PluggableAuth/includes/PluggableAuthBeginAuthenticationRequest.php
@@ -0,0 +1,35 @@
+<?php
+
+use \MediaWiki\Auth\ButtonAuthenticationRequest;
+use \MediaWiki\Auth\AuthManager;
+
+class PluggableAuthBeginAuthenticationRequest extends
+ ButtonAuthenticationRequest {
+
+ public function __construct() {
+ if ( isset( $GLOBALS['wgPluggableAuth_ButtonLabelMessage'] ) ) {
+ $label = wfMessage( $GLOBALS['wgPluggableAuth_ButtonLabelMessage'] );
+ } elseif ( $GLOBALS['wgPluggableAuth_ButtonLabel'] ) {
+ $label = new RawMessage( $GLOBALS['wgPluggableAuth_ButtonLabel'] );
+ } else {
+ $label = wfMessage( 'pluggableauth-loginbutton-label' );
+ }
+ parent::__construct(
+ 'pluggableauthlogin',
+ $label,
+ wfMessage( 'pluggableauth-loginbutton-help' ),
+ true );
+ }
+
+ /**
+ * Returns field information.
+ * @return array field information
+ */
+ public function getFieldInfo() {
+ if ( $this->action !== AuthManager::ACTION_LOGIN ) {
+ return [];
+ }
+ return array_merge( $GLOBALS['wgPluggableAuth_ExtraLoginFields'],
+ parent::getFieldInfo() );
+ }
+}
diff --git a/PluggableAuth/includes/PluggableAuthContinueAuthenticationRequest.php b/PluggableAuth/includes/PluggableAuthContinueAuthenticationRequest.php
new file mode 100644
index 00000000..a08bba6e
--- /dev/null
+++ b/PluggableAuth/includes/PluggableAuthContinueAuthenticationRequest.php
@@ -0,0 +1,33 @@
+<?php
+
+use \MediaWiki\Auth\AuthenticationRequest;
+use \MediaWiki\Auth\AuthManager;
+
+class PluggableAuthContinueAuthenticationRequest extends AuthenticationRequest {
+
+ /**
+ * Returns field information.
+ * @return array field information
+ */
+ public function getFieldInfo() {
+ return [];
+ }
+
+ /**
+ * Load from submission.
+ * @param array $data data (ignored)
+ * @return bool success
+ */
+ public function loadFromSubmission( array $data ) {
+ $authManager = AuthManager::singleton();
+ $error = $authManager->getAuthenticationSessionData(
+ PluggableAuthLogin::ERROR_SESSION_KEY );
+ if ( is_null( $error ) ) {
+ $this->username = $authManager->getAuthenticationSessionData(
+ PluggableAuthLogin::USERNAME_SESSION_KEY );
+ $authManager->removeAuthenticationSessionData(
+ PluggableAuthLogin::USERNAME_SESSION_KEY );
+ }
+ return true;
+ }
+}
diff --git a/PluggableAuth/includes/PluggableAuthHooks.php b/PluggableAuth/includes/PluggableAuthHooks.php
new file mode 100644
index 00000000..ee1e9777
--- /dev/null
+++ b/PluggableAuth/includes/PluggableAuthHooks.php
@@ -0,0 +1,161 @@
+<?php
+
+class PluggableAuthHooks {
+
+ /**
+ * Implements extension registration callback.
+ * See https://www.mediawiki.org/wiki/Manual:Extension_registration#Customizing_registration
+ * Removes password providers if local login is not enabled.
+ *
+ * @since 2.0
+ *
+ */
+ public static function onRegistration() {
+ if ( $GLOBALS['wgPluggableAuth_EnableLocalLogin'] ) {
+ return;
+ }
+ $passwordProviders = [
+ 'MediaWiki\Auth\LocalPasswordPrimaryAuthenticationProvider',
+ 'MediaWiki\Auth\TemporaryPasswordPrimaryAuthenticationProvider'
+ ];
+ $providers = $GLOBALS['wgAuthManagerAutoConfig'];
+ if ( isset( $providers['primaryauth'] ) ) {
+ $primaries = $providers['primaryauth'];
+ foreach ( $primaries as $key => $provider ) {
+ if ( in_array( $provider['class'], $passwordProviders ) ) {
+ unset( $GLOBALS['wgAuthManagerAutoConfig']['primaryauth'][$key] );
+ }
+ }
+ }
+ }
+
+ /**
+ * Implements TitleReadWhitelist hook.
+ * See https://www.mediawiki.org/wiki/Manual:Hooks/TitleReadWhitelist
+ * Adds PluggableAuth login special pages to whitelist.
+ *
+ * @since 2.0
+ * @param Title $title being checked
+ * @param User $user Current user
+ * @param bool &$whitelisted whether this title is whitelisted
+ */
+ public static function onTitleReadWhitelist(
+ Title $title, User $user, &$whitelisted
+ ) {
+ $loginSpecialPages = ExtensionRegistry::getInstance()->getAttribute(
+ 'PluggableAuthLoginSpecialPages' );
+ foreach ( $loginSpecialPages as $page ) {
+ if ( $title->isSpecial( $page ) ) {
+ $whitelisted = true;
+ return;
+ }
+ }
+ }
+
+ /**
+ * Implements AuthChangeFormFields hook.
+ * See https://www.mediawiki.org/wiki/Manual:Hooks/AuthChangeFormFields
+ * Moves login button to bottom of form.
+ *
+ * @since 2.0
+ * @param array $requests AuthenticationRequests the fields are created from
+ * @param array $fieldInfo union of AuthenticationRequest::getFieldInfo()
+ * @param HTMLForm &$formDescriptor The special key weight can be set to
+ * change the order of the fields.
+ * @param int $action one of the AuthManager::ACTION_* constants.
+ */
+ public static function onAuthChangeFormFields(
+ array $requests, array $fieldInfo, array &$formDescriptor, $action
+ ) {
+ if ( isset( $formDescriptor['pluggableauthlogin'] ) ) {
+ $formDescriptor['pluggableauthlogin']['weight'] = 101;
+ }
+ }
+
+ /**
+ * Implements UserLogoutComplete hook.
+ * See https://www.mediawiki.org/wiki/Manual:Hooks/UserLogoutComplete
+ * Calls deauthenticate hook in authentication plugin.
+ *
+ * @since 2.0
+ * @param User $user User after logout (won't have name, ID, etc.)
+ * @param string $inject_html Any HTML to inject after the logout message.
+ * @param string $old_name The text of the username that just logged out.
+ */
+ public static function deauthenticate(
+ User $user, $inject_html, $old_name
+ ) {
+ $old_user = User::newFromName( $old_name );
+ if ( $old_user === false ) {
+ return;
+ }
+ wfDebugLog( 'PluggableAuth', 'Deauthenticating ' . $old_name );
+ $pluggableauth = PluggableAuth::singleton();
+ if ( $pluggableauth ) {
+ $pluggableauth->deauthenticate( $old_user );
+ }
+ wfDebugLog( 'PluggableAuth', 'Deauthenticated ' . $old_name );
+ }
+
+ /**
+ * Grab the page request early
+ * See https://www.mediawiki.org/wiki/Manual:Hooks/BeforeInitialize
+ * Redirects ASAP to login
+ * @param Title &$title being used for request
+ * @param null $article unused
+ * @param OutputPage $out object
+ * @param User $user current user
+ * @param WebRequest $request why we're here
+ * @param MediaWiki $mw object
+ *
+ * Note that $title has to be passed by ref so we can replace it.
+ */
+ public static function doBeforeInitialize(
+ Title &$title, $article, OutputPage $out, User $user,
+ WebRequest $request, MediaWiki $mw
+ ) {
+ if ( !$GLOBALS['wgPluggableAuth_EnableAutoLogin'] ) {
+ return;
+ }
+ if ( !$out->getUser()->isAnon() ) {
+ return;
+ }
+ if ( !User::isEveryoneAllowed( 'read' ) && $title->userCan( 'read' ) ) {
+ return;
+ }
+ $loginSpecialPages = ExtensionRegistry::getInstance()->getAttribute(
+ 'PluggableAuthLoginSpecialPages'
+ );
+ foreach ( $loginSpecialPages as $page ) {
+ if ( $title->isSpecial( $page ) ) {
+ return;
+ }
+ }
+
+ $oldTitle = $title;
+ $title = Title::newFromText( "UserLogin", NS_SPECIAL );
+ $out->redirect( $title->getFullURL( [
+ 'returnto' => urlencode( $oldTitle ),
+ 'returntoquery' => $request->getRawQueryString()
+ ] ) );
+ }
+
+ /**
+ * Implements PersonalUrls hook.
+ * See https://www.mediawiki.org/wiki/Manual:Hooks/PersonalUrls
+ * Removes logout link from skin if auto login is enabled.
+ *
+ * @since 1.0
+ *
+ * @param array &$personal_urls urls sto modify
+ * @param Title $title current title
+ * @param SkinTemplate $skin template for vars
+ */
+ public static function modifyLoginURLs(
+ array &$personal_urls, Title $title = null, SkinTemplate $skin = null
+ ) {
+ if ( $GLOBALS['wgPluggableAuth_EnableAutoLogin'] ) {
+ unset( $personal_urls['logout'] );
+ }
+ }
+}
diff --git a/PluggableAuth/includes/PluggableAuthLogin.php b/PluggableAuth/includes/PluggableAuthLogin.php
new file mode 100644
index 00000000..c27e6a6b
--- /dev/null
+++ b/PluggableAuth/includes/PluggableAuthLogin.php
@@ -0,0 +1,83 @@
+<?php
+
+use \MediaWiki\Auth\AuthManager;
+
+class PluggableAuthLogin extends UnlistedSpecialPage {
+
+ const RETURNTOURL_SESSION_KEY = 'PluggableAuthLoginReturnToUrl';
+ const RETURNTOPAGE_SESSION_KEY = 'PluggableAuthLoginReturnToPage';
+ const RETURNTOQUERY_SESSION_KEY = 'PluggableAuthLoginReturnToQuery';
+ const EXTRALOGINFIELDS_SESSION_KEY = 'PluggableAuthLoginExtraLoginFields';
+ const USERNAME_SESSION_KEY = 'PluggableAuthLoginUsername';
+ const REALNAME_SESSION_KEY = 'PluggableAuthLoginRealname';
+ const EMAIL_SESSION_KEY = 'PluggableAuthLoginEmail';
+ const ERROR_SESSION_KEY = 'PluggableAuthLoginError';
+
+ public function __construct() {
+ parent::__construct( 'PluggableAuthLogin' );
+ }
+
+ /**
+ * @param string|null $param parameters (ignored)
+ */
+ public function execute( $param ) {
+ wfDebugLog( 'PluggableAuth', 'In execute()' );
+ $authManager = AuthManager::singleton();
+ $user = $this->getUser();
+ $pluggableauth = PluggableAuth::singleton();
+ $error = null;
+ if ( $pluggableauth ) {
+ if ( $pluggableauth->authenticate( $id, $username, $realname, $email,
+ $error ) ) {
+ if ( is_null( $id ) ) {
+ $user->loadDefaults( $username );
+ $user->mName = $username;
+ $user->mRealName = $realname;
+ $user->mEmail = $email;
+ $user->mEmailAuthenticated = wfTimestamp();
+ $user->mTouched = wfTimestamp();
+ wfDebugLog( 'PluggableAuth', 'Authenticated new user: ' . $username );
+ } else {
+ $user->mId = $id;
+ $user->loadFromId();
+ wfDebugLog( 'PluggableAuth', 'Authenticated existing user: ' . $user->mName );
+ }
+ $authorized = true;
+ Hooks::run( 'PluggableAuthUserAuthorization', [ $user, &$authorized ] );
+ if ( $authorized ) {
+ $authManager->setAuthenticationSessionData(
+ self::USERNAME_SESSION_KEY, $username );
+ $authManager->setAuthenticationSessionData(
+ self::REALNAME_SESSION_KEY, $realname );
+ $authManager->setAuthenticationSessionData(
+ self::EMAIL_SESSION_KEY, $email );
+ wfDebugLog( 'PluggableAuth', 'User is authorized.' );
+ } else {
+ wfDebugLog( 'PluggableAuth', 'Authorization failure.' );
+ $error = wfMessage( 'pluggableauth-not-authorized', $username )->text();
+ }
+ } else {
+ wfDebugLog( 'PluggableAuth', 'Authentication failure.' );
+ if ( is_null( $error ) ) {
+ $error = wfMessage( 'pluggableauth-authentication-failure' )->text();
+ } else {
+ if ( !is_string( $error ) ) {
+ $error = strval( $error );
+ }
+ wfDebugLog( 'PluggableAuth', 'ERROR: ' . $error );
+ }
+ }
+ }
+ if ( !is_null( $error ) ) {
+ $authManager->setAuthenticationSessionData( self::ERROR_SESSION_KEY,
+ $error );
+ }
+ $returnToUrl = $authManager->getAuthenticationSessionData(
+ self::RETURNTOURL_SESSION_KEY );
+ if ( is_null( $returnToUrl ) || count( $returnToUrl ) === 0 ) {
+ wfDebugLog( 'PluggableAuth', 'ERROR: return to URL is null or empty' );
+ } else {
+ $this->getOutput()->redirect( $returnToUrl );
+ }
+ }
+}
diff --git a/PluggableAuth/includes/PluggableAuthPrimaryAuthenticationProvider.php b/PluggableAuth/includes/PluggableAuthPrimaryAuthenticationProvider.php
new file mode 100644
index 00000000..2fda5db0
--- /dev/null
+++ b/PluggableAuth/includes/PluggableAuthPrimaryAuthenticationProvider.php
@@ -0,0 +1,182 @@
+<?php
+
+use \MediaWiki\Auth\AuthenticationRequest;
+use \MediaWiki\Auth\ButtonAuthenticationRequest;
+use \MediaWiki\Auth\AbstractPrimaryAuthenticationProvider;
+use \MediaWiki\Auth\AuthManager;
+use \MediaWiki\Auth\AuthenticationResponse;
+
+class PluggableAuthPrimaryAuthenticationProvider extends
+ AbstractPrimaryAuthenticationProvider {
+
+ /**
+ * Start an authentication flow
+ * @inheritDoc
+ */
+ public function beginPrimaryAuthentication( array $reqs ) {
+ $request = ButtonAuthenticationRequest::getRequestByName( $reqs,
+ 'pluggableauthlogin' );
+ if ( !$request ) {
+ return AuthenticationResponse::newAbstain();
+ }
+ $extraLoginFields = [];
+ foreach ( $GLOBALS['wgPluggableAuth_ExtraLoginFields'] as $key => $value ) {
+ if ( isset( $request, $key ) ) {
+ $extraLoginFields[$key] = $request->$key;
+ }
+ }
+ $url = Title::newFromText( 'Special:PluggableAuthLogin' )->getFullURL();
+ $this->manager->setAuthenticationSessionData(
+ PluggableAuthLogin::RETURNTOURL_SESSION_KEY, $request->returnToUrl );
+ $this->manager->setAuthenticationSessionData(
+ PluggableAuthLogin::EXTRALOGINFIELDS_SESSION_KEY, $extraLoginFields );
+ // @codingStandardsIgnoreStart
+ if ( isset( $_GET['returnto'] ) ) {
+ $returnto = $_GET['returnto'];
+ } else {
+ $returnto = '';
+ }
+ $this->manager->setAuthenticationSessionData(
+ PluggableAuthLogin::RETURNTOPAGE_SESSION_KEY, $returnto );
+ if ( isset( $_GET['returntoquery'] ) ) {
+ $returntoquery = $_GET['returntoquery'];
+ } else {
+ $returntoquery = '';
+ }
+ // @codingStandardsIgnoreEnd
+ $this->manager->setAuthenticationSessionData(
+ PluggableAuthLogin::RETURNTOQUERY_SESSION_KEY, $returntoquery );
+
+ return AuthenticationResponse::newRedirect( [
+ new PluggableAuthContinueAuthenticationRequest()
+ ], $url );
+ }
+
+ /**
+ * Continue an authentication flow
+ * @inheritDoc
+ */
+ public function continuePrimaryAuthentication( array $reqs ) {
+ $request = AuthenticationRequest::getRequestByClass( $reqs,
+ PluggableAuthContinueAuthenticationRequest::class );
+ if ( !$request ) {
+ return AuthenticationResponse::newFail(
+ wfMessage( 'pluggableauth-authentication-workflow-failure' ) );
+ }
+ $error = $this->manager->getAuthenticationSessionData(
+ PluggableAuthLogin::ERROR_SESSION_KEY );
+ if ( !is_null( $error ) ) {
+ $this->manager->removeAuthenticationSessionData(
+ PluggableAuthLogin::ERROR_SESSION_KEY );
+ return AuthenticationResponse::newFail( new RawMessage( $error ) );
+ }
+ $username = $request->username;
+ $user = User::newFromName( $username );
+ if ( $user && $user->getId() !== 0 ) {
+ $this->updateUserRealnameAndEmail( $user );
+ Hooks::run( 'PluggableAuthPopulateGroups', [ $user ] );
+ }
+ return AuthenticationResponse::newPass( $username );
+ }
+
+ /**
+ * Determine whether a property can change
+ * @inheritDoc
+ */
+ public function providerAllowsPropertyChange( $property ) {
+ return $GLOBALS['wgPluggableAuth_EnableLocalProperties'];
+ }
+
+ private function updateUserRealNameAndEmail( $user, $force = false ) {
+ $realname = $this->manager->getAuthenticationSessionData(
+ PluggableAuthLogin::REALNAME_SESSION_KEY );
+ $this->manager->removeAuthenticationSessionData(
+ PluggableAuthLogin::REALNAME_SESSION_KEY );
+ $email = $this->manager->getAuthenticationSessionData(
+ PluggableAuthLogin::EMAIL_SESSION_KEY );
+ $this->manager->removeAuthenticationSessionData(
+ PluggableAuthLogin::EMAIL_SESSION_KEY );
+ if ( $user->mRealName != $realname || $user->mEmail != $email ) {
+ if ( $GLOBALS['wgPluggableAuth_EnableLocalProperties'] && !$force ) {
+ wfDebugLog( 'PluggableAuth', 'Local properties enabled.' );
+ wfDebugLog( 'PluggableAuth', 'Did not save updated real name and email address.' );
+ } else {
+ wfDebugLog( 'PluggableAuth', 'Local properties disabled or has just been created.' );
+ $user->mRealName = $realname;
+ if ( $email && Sanitizer::validateEmail( $email ) ) {
+ $user->mEmail = $email;
+ $user->confirmEmail();
+ }
+ $user->saveSettings();
+ wfDebugLog( 'PluggableAuth', 'Saved updated real name and email address.' );
+ }
+ } else {
+ wfDebugLog( 'PluggableAuth', 'Real name and email address did not change.' );
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function autoCreatedAccount( $user, $source ) {
+ $this->updateUserRealNameAndEmail( $user, true );
+ $pluggableauth = PluggableAuth::singleton();
+ if ( $pluggableauth ) {
+ $pluggableauth->saveExtraAttributes( $user->mId );
+ }
+ }
+
+ /**
+ * Test whether the named user exists
+ * @inheritDoc
+ */
+ public function testUserExists( $username, $flags = User::READ_NORMAL ) {
+ return false;
+ }
+
+ /**
+ * Validate a change of authentication data (e.g. passwords)
+ * @inheritDoc
+ */
+ public function providerAllowsAuthenticationDataChange(
+ AuthenticationRequest $req, $checkData = true ) {
+ return StatusValue::newGood( 'ignored' );
+ }
+
+ /**
+ * Fetch the account-creation type
+ * @inheritDoc
+ */
+ public function accountCreationType() {
+ return self::TYPE_LINK;
+ }
+
+ /**
+ * Start an account creation flow
+ * @inheritDoc
+ */
+ public function beginPrimaryAccountCreation( $user, $creator, array $reqs ) {
+ return AuthenticationResponse::newAbstain();
+ }
+
+ /**
+ * Change or remove authentication data (e.g. passwords)
+ * @inheritDoc
+ */
+ public function providerChangeAuthenticationData( AuthenticationRequest $req ) {
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getAuthenticationRequests( $action, array $options ) {
+ switch ( $action ) {
+ case AuthManager::ACTION_LOGIN:
+ return [
+ new PluggableAuthBeginAuthenticationRequest()
+ ];
+ default:
+ return [];
+ }
+ }
+}
diff --git a/PluggableAuth/package.json b/PluggableAuth/package.json
new file mode 100644
index 00000000..bcf5b133
--- /dev/null
+++ b/PluggableAuth/package.json
@@ -0,0 +1,11 @@
+{
+ "private": true,
+ "scripts": {
+ "test": "grunt test"
+ },
+ "devDependencies": {
+ "grunt": "1.0.1",
+ "grunt-banana-checker": "0.5.0",
+ "grunt-jsonlint": "1.1.0"
+ }
+}
diff --git a/PluggableAuth/version b/PluggableAuth/version
new file mode 100644
index 00000000..9f74e3a2
--- /dev/null
+++ b/PluggableAuth/version
@@ -0,0 +1,4 @@
+PluggableAuth: REL1_31
+2020-05-25T18:28:00
+
+300ac44