Florianschmidtwelzow has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/358081 )

Change subject: Add backend services and functions for allowed domains in the 
database
......................................................................

Add backend services and functions for allowed domains in the database

Instead of requiring the users of this extension to manage the list of allowed
domains, from which the users can login with Google, in an array in the Local-
Settings.php file, this change implements to store this list in the database
in a new database table.

To allow different backends for the list of allowed domains, a new interface,
AllowedDomainsStore, is created, which allows different implementations for
the puprose of checking, if a specific domain is allowed or not (no matter where
the list of allowed domains is stored or comes from). There're three 
implementations,
which are inspired by the SiteStore implementations. One for the currently
used global array, one for a list out of the database and one which uses a 
BagOStuff
cache and another AllowedDomainsStore as a backend.

There's currently no api or user interface to manage the list of allowed 
domains,
therefore it has to be done in the database directly. There will be changes in
the future to allow to manage the list through an api and/or through a user
interface. The list, when the database is used, will be cached for up to 1 hour,
so changes will not take effect immediately at the moment.

Bug: T166423
Change-Id: I629534b97b0eddbc195c87b9a86d015c2e07a694
---
M extension.json
A includes/Constants.php
M includes/GoogleLogin.body.php
M includes/GoogleLogin.hooks.php
A includes/ServiceWiring.php
A includes/alloweddomains/AllowedDomainsStore.php
A includes/alloweddomains/ArrayAllowedDomainsStore.php
A includes/alloweddomains/CachedAllowedDomainsStore.php
A includes/alloweddomains/DBAllowedDomainsStore.php
A includes/alloweddomains/MutableAllowedDomainsStore.php
A includes/sql/googlelogin_allowed_domains.sql
11 files changed, 314 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/GoogleLogin 
refs/changes/81/358081/1

diff --git a/extension.json b/extension.json
index 5a0349e..2843a81 100644
--- a/extension.json
+++ b/extension.json
@@ -49,12 +49,17 @@
                "GoogleLogin\\Specials\\SpecialManageGoogleLogin": 
"includes/specials/SpecialManageGoogleLogin.php",
                "GoogleLogin\\GoogleLoginHooks": 
"includes/GoogleLogin.hooks.php",
                "GoogleLogin\\GoogleUser": "includes/GoogleUser.php",
+               "GoogleLogin\\Constants": "includes/Constants.php",
                "GoogleLogin\\Auth\\GooglePrimaryAuthenticationProvider": 
"includes/auth/GooglePrimaryAuthenticationProvider.php",
                "GoogleLogin\\Auth\\GoogleServerAuthenticationRequest": 
"includes/auth/GoogleServerAuthenticationRequest.php",
                "GoogleLogin\\Auth\\GoogleAuthenticationRequest": 
"includes/auth/GoogleAuthenticationRequest.php",
                "GoogleLogin\\Auth\\GoogleRemoveAuthenticationRequest": 
"includes/auth/GoogleRemoveAuthenticationRequest.php",
                "GoogleLogin\\Auth\\GoogleUserInfoAuthenticationRequest": 
"includes/auth/GoogleUserInfoAuthenticationRequest.php",
                "GoogleLogin\\AllowedDomains\\AllowedDomainsStore": 
"includes/alloweddomains/AllowedDomainsStore.php",
+               "GoogleLogin\\AllowedDomains\\MutableAllowedDomainsStore": 
"includes/alloweddomains/MutableAllowedDomainsStore.php",
+               "GoogleLogin\\AllowedDomains\\ArrayAllowedDomainsStore": 
"includes/alloweddomains/ArrayAllowedDomainsStore.php",
+               "GoogleLogin\\AllowedDomains\\DBAllowedDomainsStore": 
"includes/alloweddomains/DBAllowedDomainsStore.php",
+               "GoogleLogin\\AllowedDomains\\CachedAllowedDomainsStore": 
"includes/alloweddomains/CachedAllowedDomainsStore.php",
                "GoogleLogin\\AllowedDomains\\EmailDomain": 
"includes/alloweddomains/EmailDomain.php",
                "ApiGoogleLoginInfo": "includes/api/ApiGoogleLoginInfo.php"
        },
@@ -150,9 +155,13 @@
                "GLAppId": "",
                "GLAllowedDomains": "",
                "GLAllowedDomainsStrict": false,
+               "GLAllowedDomainsDB": false,
                "GLAPIKey": "",
                "GLEnableEchoEvents": true
        },
+       "ServiceWiringFiles": [
+               "includes/ServiceWiring.php"
+       ],
        "load_composer_autoloader": true,
        "manifest_version": 1
 }
diff --git a/includes/Constants.php b/includes/Constants.php
new file mode 100644
index 0000000..e9e58d7
--- /dev/null
+++ b/includes/Constants.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: florian
+ * Date: 09.06.17
+ * Time: 19:40
+ */
+
+namespace GoogleLogin;
+
+
+class Constants {
+       const SERVICE_ALLOWED_DOMAINS_STORE = 'GoogleLogin.AllowedDomainsStore';
+}
\ No newline at end of file
diff --git a/includes/GoogleLogin.body.php b/includes/GoogleLogin.body.php
index 534e6f1..2e918cf 100755
--- a/includes/GoogleLogin.body.php
+++ b/includes/GoogleLogin.body.php
@@ -5,7 +5,11 @@
 use ConfigFactory;
 
 use Google_Client;
+use GoogleLogin\AllowedDomains\AllowedDomainsStore;
+use GoogleLogin\AllowedDomains\CachedAllowedDomainsStore;
 use GoogleLogin\AllowedDomains\EmailDomain;
+use GoogleLogin\AllowedDomains\MutableAllowedDomainsStore;
+use MediaWiki\MediaWikiServices;
 
 class GoogleLogin {
        /** @var $mGoogleClient Stores an instance of GoogleClient */
@@ -51,13 +55,13 @@
         */
        public static function isValidDomain( $mailDomain ) {
                $glConfig = self::getGLConfig();
-               if ( is_array( $glConfig->get( 'GLAllowedDomains' ) ) ) {
+               /** @var AllowedDomainsStore $allowedDomainsStore */
+               $allowedDomainsStore = MediaWikiServices::getInstance()
+                       ->getService( Constants::SERVICE_ALLOWED_DOMAINS_STORE 
);
+               if ( $allowedDomainsStore !== null ) {
                        $domain = new EmailDomain( $mailDomain, $glConfig->get( 
'GLAllowedDomainsStrict' ) );
                        if (
-                               in_array(
-                                       $domain->getHost(),
-                                       $glConfig->get( 'GLAllowedDomains' )
-                               )
+                               $allowedDomainsStore->contains( $domain )
                        ) {
                                return true;
                        }
diff --git a/includes/GoogleLogin.hooks.php b/includes/GoogleLogin.hooks.php
index ba5d01e..267107b 100644
--- a/includes/GoogleLogin.hooks.php
+++ b/includes/GoogleLogin.hooks.php
@@ -20,6 +20,7 @@
 
        public static function onLoadExtensionSchemaUpdates( \DatabaseUpdater 
$updater = null ) {
                $config = ConfigFactory::getDefaultInstance()->makeConfig( 
'main' );
+               $extConfig = GoogleLogin::getGLConfig();
                // Don't create tables on a shared database
                $sharedDB = $config->get( 'SharedDB' );
                if (
@@ -38,6 +39,11 @@
                                'user_id',
                                "$sql/user_google_user_user_id_index.sql" );
                }
+
+               if ( $extConfig->get( 'GLAllowedDomainsDB' ) ) {
+                       $schema = "$sql/googlelogin_allowed_domains.sql";
+                       $updater->addExtensionUpdate( [ 'addTable', 
'googlelogin_allowed_domains', $schema, true ] );
+               }
                return true;
        }
 
diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php
new file mode 100644
index 0000000..073229b
--- /dev/null
+++ b/includes/ServiceWiring.php
@@ -0,0 +1,26 @@
+<?php
+
+use MediaWiki\MediaWikiServices;
+use GoogleLogin\GoogleLogin;
+use GoogleLogin\AllowedDomains\CachedAllowedDomainsStore;
+use GoogleLogin\AllowedDomains\DBAllowedDomainsStore;
+use GoogleLogin\AllowedDomains\ArrayAllowedDomainsStore;
+use GoogleLogin\Constants;
+
+return [
+       Constants::SERVICE_ALLOWED_DOMAINS_STORE => function ( 
MediaWikiServices $services ) {
+               $glConfig = GoogleLogin::getGLConfig();
+               if (
+                       is_array( $glConfig->get( 'GLAllowedDomains' ) ) &&
+                       !$glConfig->get( 'GLAllowedDomainsDB' )
+               ) {
+                       return new ArrayAllowedDomainsStore( $glConfig->get( 
'GLAllowedDomains' ) );
+               } elseif ( $glConfig->get( 'GLAllowedDomainsDB' ) ) {
+                       $dbBackedStore = new DBAllowedDomainsStore( 
$services->getDBLoadBalancer() );
+                       $cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : 
CACHE_ANYTHING );
+
+                       return new CachedAllowedDomainsStore( $dbBackedStore, 
$cache );
+               }
+               return null;
+       }
+];
\ No newline at end of file
diff --git a/includes/alloweddomains/AllowedDomainsStore.php 
b/includes/alloweddomains/AllowedDomainsStore.php
new file mode 100644
index 0000000..5dc3a1c
--- /dev/null
+++ b/includes/alloweddomains/AllowedDomainsStore.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace GoogleLogin\AllowedDomains;
+
+/**
+ * Interface AllowedDomainsStore
+ *
+ * Defines, how a store should behave, which provides a list of allowed 
domains, which can be
+ * used to login with a Google account.
+ *
+ * @package GoogleLogin\AllowedDomains
+ */
+interface AllowedDomainsStore {
+
+       /**
+        * Checks, if the given EmailDomain is allowed to be used for login or 
not.
+        *
+        * @param EmailDomain $domain
+        * @return boolean
+        */
+       function contains( EmailDomain $domain );
+
+       /**
+        * Returns the complete list of allowed domains of this store as an 
array.
+        *
+        * @return array
+        */
+       function getAllowedDomains();
+}
\ No newline at end of file
diff --git a/includes/alloweddomains/ArrayAllowedDomainsStore.php 
b/includes/alloweddomains/ArrayAllowedDomainsStore.php
new file mode 100644
index 0000000..cf6f96c
--- /dev/null
+++ b/includes/alloweddomains/ArrayAllowedDomainsStore.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace GoogleLogin\AllowedDomains;
+
+use Config;
+
+/**
+ * Class GlobalAllowedDomainsStore
+ *
+ * An implementation of the AllowedDomainStore interface, which is backed by 
the an array passed
+ * to it, e.g. a configured array of allowed domains.
+ *
+ * @package GoogleLogin\AllowedDomains
+ */
+class ArrayAllowedDomainsStore implements AllowedDomainsStore {
+       private $allowedDomains;
+
+       public function __construct( array $allowedDomains ) {
+               $this->allowedDomains = $allowedDomains;
+       }
+
+       public function contains( EmailDomain $domain ) {
+               return in_array(
+                       $domain->getHost(),
+                       $this->allowedDomains
+               );
+       }
+
+       public function getAllowedDomains() {
+               return $this->allowedDomains;
+       }
+}
\ No newline at end of file
diff --git a/includes/alloweddomains/CachedAllowedDomainsStore.php 
b/includes/alloweddomains/CachedAllowedDomainsStore.php
new file mode 100644
index 0000000..60ac2ab
--- /dev/null
+++ b/includes/alloweddomains/CachedAllowedDomainsStore.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace GoogleLogin\AllowedDomains;
+
+use BagOStuff;
+
+class CachedAllowedDomainsStore implements AllowedDomainsStore, 
MutableAllowedDomainsStore {
+       /**
+        * @var AllowedDomainsStore
+        */
+       private $rawStore;
+       /**
+        * @var BagOStuff
+        */
+       private $cache;
+       /**
+        * @var string|null
+        */
+       private $cacheKey;
+       private $allowedDomains;
+
+       const CACHE_VERSION = '1';
+
+       public function __construct( AllowedDomainsStore $rawStore, BagOStuff 
$cache ) {
+               $this->cache = $cache;
+               $this->rawStore = $rawStore;
+       }
+
+       /**
+        * Constructs a cache key to use for caching the list of allowed 
domains.
+        *
+        * @return string The cache key.
+        */
+       private function getCacheKey() {
+               if ( $this->cacheKey === null ) {
+                       $type = 'CachedAllowedDomainsStore#' . 
self::CACHE_VERSION;
+                       $this->cacheKey = $this->cache->makeKey( 
"googlelogin/allowedDomains/$type" );
+               }
+               return $this->cacheKey;
+       }
+
+       /**
+        * @return array
+        */
+       public function getAllowedDomains() {
+               if ( $this->allowedDomains === null ) {
+                       $this->allowedDomains = $this->cache->get( 
$this->getCacheKey() );
+                       if ( !is_object( $this->allowedDomains ) ) {
+                               $this->allowedDomains = 
$this->rawStore->getAllowedDomains();
+                               $this->cache->set( $this->getCacheKey(), 
$this->allowedDomains, 3600 );
+                       }
+               }
+               return $this->allowedDomains;
+       }
+
+       public function contains( EmailDomain $domain ) {
+               return in_array( $domain->getHost(), $this->getAllowedDomains() 
);
+       }
+
+       public function add( EmailDomain $domain ) {
+               if ( !$this->rawStore instanceof MutableAllowedDomainsStore ) {
+                       throw new \InvalidArgumentException(
+                               'The backend domain store does not support to 
change the store data.' );
+               }
+               $this->rawStore->add( $domain );
+       }
+
+       public function clear() {
+               $this->cache->delete( $this->getCacheKey() );
+               $this->allowedDomains = null;
+       }
+}
\ No newline at end of file
diff --git a/includes/alloweddomains/DBAllowedDomainsStore.php 
b/includes/alloweddomains/DBAllowedDomainsStore.php
new file mode 100644
index 0000000..521e208
--- /dev/null
+++ b/includes/alloweddomains/DBAllowedDomainsStore.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace GoogleLogin\AllowedDomains;
+
+use Wikimedia\Rdbms\LoadBalancer;
+
+/**
+ * Class DBAllowedDomainsStore
+ *
+ * Implementation of the AllowedDomainsStore interface, which is backed by the 
database. The
+ * allowed domain list is stored and manageable in the database of MediaWiki. 
For performance
+ * reasons, you should use the CachedAllowedDomainsStore implementation and 
wrap an instance of
+ * this class into it.
+ *
+ * @package GoogleLogin\AllowedDomains
+ */
+class DBAllowedDomainsStore implements AllowedDomainsStore {
+       private $dbLoadBalancer;
+       private $allowedDomains;
+
+       public function __construct( LoadBalancer $dbLoadBalancer ) {
+               $this->dbLoadBalancer = $dbLoadBalancer;
+       }
+
+       private function loadDomains() {
+               if ( $this->allowedDomains !== null ) {
+                       return;
+               }
+               $dbr = $this->dbLoadBalancer->getConnection( DB_REPLICA );
+
+               $res = $dbr->select(
+                       'googlelogin_allowed_domains',
+                       [
+                               'gl_allowed_domain_id',
+                               'gl_allowed_domain',
+                       ],
+                       '',
+                       __METHOD__
+               );
+
+               foreach ( $res as $row ) {
+                       $this->allowedDomains[$row->gl_allowed_domain_id] = 
$row->gl_allowed_domain;
+               }
+       }
+
+       public function getAllowedDomains() {
+               $this->loadDomains();
+
+               return $this->allowedDomains;
+       }
+
+       public function contains( EmailDomain $domain ) {
+               $this->loadDomains();
+
+               return in_array( $domain->getHost(), $this->allowedDomains );
+       }
+
+       public function add( EmailDomain $domain ) {
+               if ( $this->contains( $domain ) ) {
+                       return -1;
+               }
+               $dbw = $this->dbLoadBalancer->getConnection( DB_MASTER );
+               $dbw->insert(
+                       'googlelogin_allowed_domains',
+                       [
+                               'gl_allowed_domain' => $domain->getHost()
+                       ],
+                       __METHOD__
+               );
+
+               return $dbw->insertId();
+       }
+
+       public function clear() {
+               $dbw = $this->dbLoadBalancer->getConnection( DB_MASTER );
+
+               $ok = $dbw->delete( 'googlelogin_allowed_domains', '*', 
__METHOD__ );
+               $this->allowedDomains = null;
+
+               return $ok;
+       }
+}
\ No newline at end of file
diff --git a/includes/alloweddomains/MutableAllowedDomainsStore.php 
b/includes/alloweddomains/MutableAllowedDomainsStore.php
new file mode 100644
index 0000000..c40bc92
--- /dev/null
+++ b/includes/alloweddomains/MutableAllowedDomainsStore.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace GoogleLogin\AllowedDomains;
+
+/**
+ * Interface MutableAllowedDomainsStore
+ *
+ * A domain store, which can be modified during runtime, where the changes 
persist between requests.
+ *
+ * @package GoogleLogin\AllowedDomains
+ */
+interface MutableAllowedDomainsStore {
+       /**
+        * Adds the host of the given EmailDomain to the store.
+        *
+        * @param EmailDomain $domain
+        * @return void
+        */
+       function add( EmailDomain $domain );
+
+       /**
+        * Cleans the store and deletes all entries from it.
+        *
+        * @return void
+        */
+       function clear();
+}
\ No newline at end of file
diff --git a/includes/sql/googlelogin_allowed_domains.sql 
b/includes/sql/googlelogin_allowed_domains.sql
new file mode 100644
index 0000000..50af8b2
--- /dev/null
+++ b/includes/sql/googlelogin_allowed_domains.sql
@@ -0,0 +1,8 @@
+--
+-- extension Google Login SQL schema
+--
+CREATE TABLE /*$wgDBprefix*/googlelogin_allowed_domains (
+  gl_allowed_domain_id int unsigned AUTO_INCREMENT NOT NULL PRIMARY KEY,
+  gl_allowed_domain varchar(255) NOT NULL,
+  KEY(gl_allowed_domain)
+) /*$wgDBTableOptions*/;

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I629534b97b0eddbc195c87b9a86d015c2e07a694
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/GoogleLogin
Gerrit-Branch: master
Gerrit-Owner: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com>

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

Reply via email to