Passed
Push — master ( 3e5dae...8d4e4c )
by Simon
12:37
created
includes/ConsoleTasks/RegenerateStylesheetsTask.php 1 patch
Indentation   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -13,27 +13,27 @@
 block discarded – undo
13 13
 
14 14
 class RegenerateStylesheetsTask extends ConsoleTaskBase
15 15
 {
16
-    const RESOURCES_GENERATED = 'resources/generated';
16
+	const RESOURCES_GENERATED = 'resources/generated';
17 17
 
18
-    public function execute()
19
-    {
20
-        $scss = new Compiler();
21
-        $scss->setImportPaths('resources/scss');
18
+	public function execute()
19
+	{
20
+		$scss = new Compiler();
21
+		$scss->setImportPaths('resources/scss');
22 22
 
23
-        if (!$this->getSiteConfiguration()->getDebuggingTraceEnabled()) {
24
-            $scss->setOutputStyle(\ScssPhp\ScssPhp\OutputStyle::COMPRESSED);
25
-            $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE);
26
-        }
23
+		if (!$this->getSiteConfiguration()->getDebuggingTraceEnabled()) {
24
+			$scss->setOutputStyle(\ScssPhp\ScssPhp\OutputStyle::COMPRESSED);
25
+			$scss->setSourceMap(Compiler::SOURCE_MAP_INLINE);
26
+		}
27 27
 
28
-        if (!is_dir(self::RESOURCES_GENERATED)) {
29
-            mkdir(self::RESOURCES_GENERATED);
30
-        }
28
+		if (!is_dir(self::RESOURCES_GENERATED)) {
29
+			mkdir(self::RESOURCES_GENERATED);
30
+		}
31 31
 
32
-        foreach (['bootstrap-main', 'bootstrap-alt', 'bootstrap-auto'] as $file) {
33
-            file_put_contents(
34
-                self::RESOURCES_GENERATED . '/' . $file . '.css',
35
-                $scss->compileString('/*! Do not edit this auto-generated file! */ @import "' . $file . '";')->getCss()
36
-            );
37
-        }
38
-    }
32
+		foreach (['bootstrap-main', 'bootstrap-alt', 'bootstrap-auto'] as $file) {
33
+			file_put_contents(
34
+				self::RESOURCES_GENERATED . '/' . $file . '.css',
35
+				$scss->compileString('/*! Do not edit this auto-generated file! */ @import "' . $file . '";')->getCss()
36
+			);
37
+		}
38
+	}
39 39
 }
Please login to merge, or discard this patch.
includes/ConsoleStart.php 1 patch
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -15,66 +15,66 @@
 block discarded – undo
15 15
 
16 16
 class ConsoleStart extends ApplicationBase
17 17
 {
18
-    /**
19
-     * @var ConsoleTaskBase
20
-     */
21
-    private $consoleTask;
18
+	/**
19
+	 * @var ConsoleTaskBase
20
+	 */
21
+	private $consoleTask;
22 22
 
23
-    /**
24
-     * ConsoleStart constructor.
25
-     *
26
-     * @param SiteConfiguration $configuration
27
-     * @param ConsoleTaskBase   $consoleTask
28
-     */
29
-    public function __construct(SiteConfiguration $configuration, ConsoleTaskBase $consoleTask)
30
-    {
31
-        parent::__construct($configuration);
32
-        $this->consoleTask = $consoleTask;
33
-    }
23
+	/**
24
+	 * ConsoleStart constructor.
25
+	 *
26
+	 * @param SiteConfiguration $configuration
27
+	 * @param ConsoleTaskBase   $consoleTask
28
+	 */
29
+	public function __construct(SiteConfiguration $configuration, ConsoleTaskBase $consoleTask)
30
+	{
31
+		parent::__construct($configuration);
32
+		$this->consoleTask = $consoleTask;
33
+	}
34 34
 
35
-    protected function setupEnvironment()
36
-    {
37
-        // initialise super-global providers
38
-        WebRequest::setGlobalStateProvider(new FakeGlobalStateProvider());
35
+	protected function setupEnvironment()
36
+	{
37
+		// initialise super-global providers
38
+		WebRequest::setGlobalStateProvider(new FakeGlobalStateProvider());
39 39
 
40
-        if (WebRequest::method() !== null) {
41
-            throw new EnvironmentException('This is a console task, which cannot be executed via the web.');
42
-        }
40
+		if (WebRequest::method() !== null) {
41
+			throw new EnvironmentException('This is a console task, which cannot be executed via the web.');
42
+		}
43 43
 
44
-        return parent::setupEnvironment();
45
-    }
44
+		return parent::setupEnvironment();
45
+	}
46 46
 
47
-    protected function cleanupEnvironment()
48
-    {
49
-    }
47
+	protected function cleanupEnvironment()
48
+	{
49
+	}
50 50
 
51
-    /**
52
-     * Main application logic
53
-     */
54
-    protected function main()
55
-    {
56
-        $database = PdoDatabase::getDatabaseConnection('acc');
51
+	/**
52
+	 * Main application logic
53
+	 */
54
+	protected function main()
55
+	{
56
+		$database = PdoDatabase::getDatabaseConnection('acc');
57 57
 
58
-        $this->setupHelpers($this->consoleTask, $this->getConfiguration(), $database);
58
+		$this->setupHelpers($this->consoleTask, $this->getConfiguration(), $database);
59 59
 
60
-        // initialise a database transaction
61
-        if (!$database->beginTransaction()) {
62
-            throw new Exception('Failed to start transaction on primary database.');
63
-        }
60
+		// initialise a database transaction
61
+		if (!$database->beginTransaction()) {
62
+			throw new Exception('Failed to start transaction on primary database.');
63
+		}
64 64
 
65
-        try {
66
-            // run the task
67
-            $this->consoleTask->execute();
65
+		try {
66
+			// run the task
67
+			$this->consoleTask->execute();
68 68
 
69
-            if ($database->hasActiveTransaction()) {
70
-                $database->commit();
71
-            }
72
-        }
73
-        finally {
74
-            // Catch any hanging on transactions
75
-            if ($database->hasActiveTransaction()) {
76
-                $database->rollBack();
77
-            }
78
-        }
79
-    }
69
+			if ($database->hasActiveTransaction()) {
70
+				$database->commit();
71
+			}
72
+		}
73
+		finally {
74
+			// Catch any hanging on transactions
75
+			if ($database->hasActiveTransaction()) {
76
+				$database->rollBack();
77
+			}
78
+		}
79
+	}
80 80
 }
81 81
\ No newline at end of file
Please login to merge, or discard this patch.
includes/IdentificationVerifier.php 1 patch
Indentation   +161 added lines, -161 removed lines patch added patch discarded remove patch
@@ -26,133 +26,133 @@  discard block
 block discarded – undo
26 26
  */
27 27
 class IdentificationVerifier
28 28
 {
29
-    /**
30
-     * This field is an array of parameters, in key => value format, that should be appended to the Meta Wikimedia
31
-     * Web Service Endpoint URL to query if a user is listed on the Identification Noticeboard.  Note that URL encoding
32
-     * of these values is *not* necessary; this is done automatically.
33
-     *
34
-     * @var string[]
35
-     * @category Security-Critical
36
-     */
37
-    private static $apiQueryParameters = array(
38
-        'action'   => 'query',
39
-        'format'   => 'json',
40
-        'prop'     => 'links',
41
-        // Populated from SiteConfiguration->getIdentificationNoticeboardPage
42
-        'titles'   => '',
43
-        // Username of the user to be checked, with User: prefix, goes here!  Set in isIdentifiedOnWiki()
44
-        'pltitles' => '',
45
-    );
46
-    /** @var HttpHelper */
47
-    private $httpHelper;
48
-    /** @var SiteConfiguration */
49
-    private $siteConfiguration;
50
-    /** @var PdoDatabase */
51
-    private $dbObject;
52
-
53
-    /**
54
-     * IdentificationVerifier constructor.
55
-     *
56
-     * @param HttpHelper        $httpHelper
57
-     * @param SiteConfiguration $siteConfiguration
58
-     * @param PdoDatabase       $dbObject
59
-     */
60
-    public function __construct(HttpHelper $httpHelper, SiteConfiguration $siteConfiguration, PdoDatabase $dbObject)
61
-    {
62
-        $this->httpHelper = $httpHelper;
63
-        $this->siteConfiguration = $siteConfiguration;
64
-        $this->dbObject = $dbObject;
65
-    }
66
-
67
-    /**
68
-     * Checks if the given user is identified to the Wikimedia Foundation.
69
-     *
70
-     * @param string $onWikiName The Wikipedia username of the user
71
-     *
72
-     * @return bool
73
-     * @category Security-Critical
74
-     * @throws EnvironmentException
75
-     */
76
-    public function isUserIdentified($onWikiName)
77
-    {
78
-        if ($this->checkIdentificationCache($onWikiName)) {
79
-            return true;
80
-        }
81
-        else {
82
-            if ($this->isIdentifiedOnWiki($onWikiName)) {
83
-                $this->cacheIdentificationStatus($onWikiName);
84
-
85
-                return true;
86
-            }
87
-            else {
88
-                return false;
89
-            }
90
-        }
91
-    }
92
-
93
-    /**
94
-     * Checks if the given user has a valid entry in the idcache table.
95
-     *
96
-     * @param string $onWikiName The Wikipedia username of the user
97
-     *
98
-     * @return bool
99
-     * @category Security-Critical
100
-     */
101
-    private function checkIdentificationCache($onWikiName)
102
-    {
103
-        $interval = $this->siteConfiguration->getIdentificationCacheExpiry();
104
-
105
-        $query = <<<SQL
29
+	/**
30
+	 * This field is an array of parameters, in key => value format, that should be appended to the Meta Wikimedia
31
+	 * Web Service Endpoint URL to query if a user is listed on the Identification Noticeboard.  Note that URL encoding
32
+	 * of these values is *not* necessary; this is done automatically.
33
+	 *
34
+	 * @var string[]
35
+	 * @category Security-Critical
36
+	 */
37
+	private static $apiQueryParameters = array(
38
+		'action'   => 'query',
39
+		'format'   => 'json',
40
+		'prop'     => 'links',
41
+		// Populated from SiteConfiguration->getIdentificationNoticeboardPage
42
+		'titles'   => '',
43
+		// Username of the user to be checked, with User: prefix, goes here!  Set in isIdentifiedOnWiki()
44
+		'pltitles' => '',
45
+	);
46
+	/** @var HttpHelper */
47
+	private $httpHelper;
48
+	/** @var SiteConfiguration */
49
+	private $siteConfiguration;
50
+	/** @var PdoDatabase */
51
+	private $dbObject;
52
+
53
+	/**
54
+	 * IdentificationVerifier constructor.
55
+	 *
56
+	 * @param HttpHelper        $httpHelper
57
+	 * @param SiteConfiguration $siteConfiguration
58
+	 * @param PdoDatabase       $dbObject
59
+	 */
60
+	public function __construct(HttpHelper $httpHelper, SiteConfiguration $siteConfiguration, PdoDatabase $dbObject)
61
+	{
62
+		$this->httpHelper = $httpHelper;
63
+		$this->siteConfiguration = $siteConfiguration;
64
+		$this->dbObject = $dbObject;
65
+	}
66
+
67
+	/**
68
+	 * Checks if the given user is identified to the Wikimedia Foundation.
69
+	 *
70
+	 * @param string $onWikiName The Wikipedia username of the user
71
+	 *
72
+	 * @return bool
73
+	 * @category Security-Critical
74
+	 * @throws EnvironmentException
75
+	 */
76
+	public function isUserIdentified($onWikiName)
77
+	{
78
+		if ($this->checkIdentificationCache($onWikiName)) {
79
+			return true;
80
+		}
81
+		else {
82
+			if ($this->isIdentifiedOnWiki($onWikiName)) {
83
+				$this->cacheIdentificationStatus($onWikiName);
84
+
85
+				return true;
86
+			}
87
+			else {
88
+				return false;
89
+			}
90
+		}
91
+	}
92
+
93
+	/**
94
+	 * Checks if the given user has a valid entry in the idcache table.
95
+	 *
96
+	 * @param string $onWikiName The Wikipedia username of the user
97
+	 *
98
+	 * @return bool
99
+	 * @category Security-Critical
100
+	 */
101
+	private function checkIdentificationCache($onWikiName)
102
+	{
103
+		$interval = $this->siteConfiguration->getIdentificationCacheExpiry();
104
+
105
+		$query = <<<SQL
106 106
 			SELECT COUNT(`id`)
107 107
 			FROM `idcache`
108 108
 			WHERE `onwikiusername` = :onwikiname
109 109
 				AND DATE_ADD(`checktime`, INTERVAL {$interval}) >= NOW();
110 110
 SQL;
111
-        $stmt = $this->dbObject->prepare($query);
112
-        $stmt->bindValue(':onwikiname', $onWikiName, PDO::PARAM_STR);
113
-        $stmt->execute();
114
-
115
-        // Guaranteed by the query to only return a single row with a single column
116
-        $results = $stmt->fetch(PDO::FETCH_NUM);
117
-
118
-        // I don't expect this to ever be a value other than 0 or 1 since the `onwikiusername` column is declared as a
119
-        // unique key - but meh.
120
-        return $results[0] != 0;
121
-    }
122
-
123
-    /**
124
-     * Does pretty much exactly what it says on the label - this method will clear all expired idcache entries from the
125
-     * idcache table.  Meant to be called periodically by a maintenance script.
126
-     *
127
-     * @param SiteConfiguration $siteConfiguration
128
-     * @param PdoDatabase       $dbObject
129
-     *
130
-     * @return void
131
-     */
132
-    public static function clearExpiredCacheEntries(SiteConfiguration $siteConfiguration, PdoDatabase $dbObject)
133
-    {
134
-        $interval = $siteConfiguration->getIdentificationCacheExpiry();
135
-
136
-        $query = <<<SQL
111
+		$stmt = $this->dbObject->prepare($query);
112
+		$stmt->bindValue(':onwikiname', $onWikiName, PDO::PARAM_STR);
113
+		$stmt->execute();
114
+
115
+		// Guaranteed by the query to only return a single row with a single column
116
+		$results = $stmt->fetch(PDO::FETCH_NUM);
117
+
118
+		// I don't expect this to ever be a value other than 0 or 1 since the `onwikiusername` column is declared as a
119
+		// unique key - but meh.
120
+		return $results[0] != 0;
121
+	}
122
+
123
+	/**
124
+	 * Does pretty much exactly what it says on the label - this method will clear all expired idcache entries from the
125
+	 * idcache table.  Meant to be called periodically by a maintenance script.
126
+	 *
127
+	 * @param SiteConfiguration $siteConfiguration
128
+	 * @param PdoDatabase       $dbObject
129
+	 *
130
+	 * @return void
131
+	 */
132
+	public static function clearExpiredCacheEntries(SiteConfiguration $siteConfiguration, PdoDatabase $dbObject)
133
+	{
134
+		$interval = $siteConfiguration->getIdentificationCacheExpiry();
135
+
136
+		$query = <<<SQL
137 137
 			DELETE FROM `idcache`
138 138
 			WHERE DATE_ADD(`checktime`, INTERVAL {$interval}) < NOW();
139 139
 SQL;
140
-        $dbObject->prepare($query)->execute();
141
-    }
142
-
143
-    /**
144
-     * This method will add an entry to the idcache that the given Wikipedia user has been verified as identified.  This
145
-     * is so we don't have to hit the API every single time we check.  The cache entry is valid for as long as specified
146
-     * in the ACC configuration (validity enforced by checkIdentificationCache() and clearExpiredCacheEntries()).
147
-     *
148
-     * @param string $onWikiName The Wikipedia username of the user
149
-     *
150
-     * @return void
151
-     * @category Security-Critical
152
-     */
153
-    private function cacheIdentificationStatus($onWikiName)
154
-    {
155
-        $query = <<<SQL
140
+		$dbObject->prepare($query)->execute();
141
+	}
142
+
143
+	/**
144
+	 * This method will add an entry to the idcache that the given Wikipedia user has been verified as identified.  This
145
+	 * is so we don't have to hit the API every single time we check.  The cache entry is valid for as long as specified
146
+	 * in the ACC configuration (validity enforced by checkIdentificationCache() and clearExpiredCacheEntries()).
147
+	 *
148
+	 * @param string $onWikiName The Wikipedia username of the user
149
+	 *
150
+	 * @return void
151
+	 * @category Security-Critical
152
+	 */
153
+	private function cacheIdentificationStatus($onWikiName)
154
+	{
155
+		$query = <<<SQL
156 156
 			INSERT INTO `idcache`
157 157
 				(`onwikiusername`)
158 158
 			VALUES
@@ -161,46 +161,46 @@  discard block
 block discarded – undo
161 161
 				`onwikiusername` = VALUES(`onwikiusername`),
162 162
 				`checktime` = CURRENT_TIMESTAMP;
163 163
 SQL;
164
-        $stmt = $this->dbObject->prepare($query);
165
-        $stmt->bindValue(':onwikiname', $onWikiName, PDO::PARAM_STR);
166
-        $stmt->execute();
167
-    }
168
-
169
-    /**
170
-     * Queries the Wikimedia API to determine if the specified user is listed on the identification noticeboard.
171
-     *
172
-     * @param string $onWikiName The Wikipedia username of the user
173
-     *
174
-     * @return bool
175
-     * @throws EnvironmentException
176
-     * @category Security-Critical
177
-     */
178
-    private function isIdentifiedOnWiki($onWikiName)
179
-    {
180
-        $strings = new StringFunctions();
181
-
182
-        // First character of Wikipedia usernames is always capitalized.
183
-        $onWikiName = $strings->upperCaseFirst($onWikiName);
184
-
185
-        $parameters = self::$apiQueryParameters;
186
-        $parameters['pltitles'] = "User:" . $onWikiName;
187
-        $parameters['titles'] = $this->siteConfiguration->getIdentificationNoticeboardPage();
188
-
189
-        try {
190
-            $endpoint = $this->siteConfiguration->getMetaWikimediaWebServiceEndpoint();
191
-            $response = $this->httpHelper->get($endpoint, $parameters);
192
-            $response = json_decode($response, true);
193
-        }
194
-        catch (CurlException $ex) {
195
-            // failed getting identification status, so throw a nicer error.
196
-            $message = 'Could not contact metawiki API to determine user\' identification status. '
197
-                . 'This is probably a transient error, so please try again.';
198
-
199
-            throw new EnvironmentException($message);
200
-        }
201
-
202
-        $page = @array_pop($response['query']['pages']);
203
-
204
-        return @$page['links'][0]['title'] === "User:" . $onWikiName;
205
-    }
164
+		$stmt = $this->dbObject->prepare($query);
165
+		$stmt->bindValue(':onwikiname', $onWikiName, PDO::PARAM_STR);
166
+		$stmt->execute();
167
+	}
168
+
169
+	/**
170
+	 * Queries the Wikimedia API to determine if the specified user is listed on the identification noticeboard.
171
+	 *
172
+	 * @param string $onWikiName The Wikipedia username of the user
173
+	 *
174
+	 * @return bool
175
+	 * @throws EnvironmentException
176
+	 * @category Security-Critical
177
+	 */
178
+	private function isIdentifiedOnWiki($onWikiName)
179
+	{
180
+		$strings = new StringFunctions();
181
+
182
+		// First character of Wikipedia usernames is always capitalized.
183
+		$onWikiName = $strings->upperCaseFirst($onWikiName);
184
+
185
+		$parameters = self::$apiQueryParameters;
186
+		$parameters['pltitles'] = "User:" . $onWikiName;
187
+		$parameters['titles'] = $this->siteConfiguration->getIdentificationNoticeboardPage();
188
+
189
+		try {
190
+			$endpoint = $this->siteConfiguration->getMetaWikimediaWebServiceEndpoint();
191
+			$response = $this->httpHelper->get($endpoint, $parameters);
192
+			$response = json_decode($response, true);
193
+		}
194
+		catch (CurlException $ex) {
195
+			// failed getting identification status, so throw a nicer error.
196
+			$message = 'Could not contact metawiki API to determine user\' identification status. '
197
+				. 'This is probably a transient error, so please try again.';
198
+
199
+			throw new EnvironmentException($message);
200
+		}
201
+
202
+		$page = @array_pop($response['query']['pages']);
203
+
204
+		return @$page['links'][0]['title'] === "User:" . $onWikiName;
205
+	}
206 206
 }
Please login to merge, or discard this patch.
includes/Security/RoleConfiguration.php 1 patch
Indentation   +441 added lines, -441 removed lines patch added patch discarded remove patch
@@ -55,471 +55,471 @@
 block discarded – undo
55 55
 
56 56
 class RoleConfiguration
57 57
 {
58
-    const ACCESS_ALLOW = 1;
59
-    const ACCESS_DENY = -1;
60
-    const ACCESS_DEFAULT = 0;
61
-    const MAIN = 'main';
62
-    const ALL = '*';
63
-    /**
64
-     * A map of roles to rights
65
-     *
66
-     * For example:
67
-     *
68
-     * array(
69
-     *   'myrole' => array(
70
-     *       PageMyPage::class => array(
71
-     *           'edit' => self::ACCESS_ALLOW,
72
-     *           'create' => self::ACCESS_DENY,
73
-     *       )
74
-     *   )
75
-     * )
76
-     *
77
-     * Note that DENY takes precedence over everything else when roles are combined, followed by ALLOW, followed by
78
-     * DEFAULT. Thus, if you have the following ([A]llow, [D]eny, [-] (default)) grants in different roles, this should
79
-     * be the expected result:
80
-     *
81
-     * - (-,-,-) = - (default because nothing to explicitly say allowed or denied equates to a denial)
82
-     * - (A,-,-) = A
83
-     * - (D,-,-) = D
84
-     * - (A,D,-) = D (deny takes precedence over allow)
85
-     * - (A,A,A) = A (repetition has no effect)
86
-     *
87
-     * The public role is special, and is applied to all users automatically. Avoid using deny on this role.
88
-     *
89
-     * @var array
90
-     */
91
-    private $roleConfig = array(
92
-        'public'            => array(
93
-            /*
58
+	const ACCESS_ALLOW = 1;
59
+	const ACCESS_DENY = -1;
60
+	const ACCESS_DEFAULT = 0;
61
+	const MAIN = 'main';
62
+	const ALL = '*';
63
+	/**
64
+	 * A map of roles to rights
65
+	 *
66
+	 * For example:
67
+	 *
68
+	 * array(
69
+	 *   'myrole' => array(
70
+	 *       PageMyPage::class => array(
71
+	 *           'edit' => self::ACCESS_ALLOW,
72
+	 *           'create' => self::ACCESS_DENY,
73
+	 *       )
74
+	 *   )
75
+	 * )
76
+	 *
77
+	 * Note that DENY takes precedence over everything else when roles are combined, followed by ALLOW, followed by
78
+	 * DEFAULT. Thus, if you have the following ([A]llow, [D]eny, [-] (default)) grants in different roles, this should
79
+	 * be the expected result:
80
+	 *
81
+	 * - (-,-,-) = - (default because nothing to explicitly say allowed or denied equates to a denial)
82
+	 * - (A,-,-) = A
83
+	 * - (D,-,-) = D
84
+	 * - (A,D,-) = D (deny takes precedence over allow)
85
+	 * - (A,A,A) = A (repetition has no effect)
86
+	 *
87
+	 * The public role is special, and is applied to all users automatically. Avoid using deny on this role.
88
+	 *
89
+	 * @var array
90
+	 */
91
+	private $roleConfig = array(
92
+		'public'            => array(
93
+			/*
94 94
              * THIS ROLE IS GRANTED TO ALL LOGGED *OUT* USERS IMPLICITLY.
95 95
              *
96 96
              * USERS IN THIS ROLE DO NOT HAVE TO BE IDENTIFIED TO GET THE RIGHTS CONFERRED HERE.
97 97
              * DO NOT ADD ANY SECURITY-SENSITIVE RIGHTS HERE.
98 98
              */
99
-            '_childRoles'   => array(
100
-                'publicStats',
101
-            ),
102
-            PageTeam::class => array(
103
-                self::MAIN => self::ACCESS_ALLOW,
104
-            ),
105
-            PageXffDemo::class        => array(
106
-                self::MAIN  => self::ACCESS_ALLOW,
107
-            )
108
-        ),
109
-        'loggedIn'          => array(
110
-            /*
99
+			'_childRoles'   => array(
100
+				'publicStats',
101
+			),
102
+			PageTeam::class => array(
103
+				self::MAIN => self::ACCESS_ALLOW,
104
+			),
105
+			PageXffDemo::class        => array(
106
+				self::MAIN  => self::ACCESS_ALLOW,
107
+			)
108
+		),
109
+		'loggedIn'          => array(
110
+			/*
111 111
              * THIS ROLE IS GRANTED TO ALL LOGGED IN USERS IMPLICITLY.
112 112
              *
113 113
              * USERS IN THIS ROLE DO NOT HAVE TO BE IDENTIFIED TO GET THE RIGHTS CONFERRED HERE.
114 114
              * DO NOT ADD ANY SECURITY-SENSITIVE RIGHTS HERE.
115 115
              */
116
-            '_childRoles'             => array(
117
-                'public',
118
-            ),
119
-            PagePreferences::class    => array(
120
-                self::MAIN => self::ACCESS_ALLOW,
121
-                'refreshOAuth' => self::ACCESS_ALLOW,
122
-            ),
123
-            PageChangePassword::class => array(
124
-                self::MAIN => self::ACCESS_ALLOW,
125
-            ),
126
-            PageMultiFactor::class    => array(
127
-                self::MAIN          => self::ACCESS_ALLOW,
128
-                'scratch'           => self::ACCESS_ALLOW,
129
-                'enableYubikeyOtp'  => self::ACCESS_ALLOW,
130
-                'disableYubikeyOtp' => self::ACCESS_ALLOW,
131
-                'enableTotp'        => self::ACCESS_ALLOW,
132
-                'disableTotp'       => self::ACCESS_ALLOW,
133
-            ),
134
-            PageOAuth::class          => array(
135
-                'attach' => self::ACCESS_ALLOW,
136
-                'detach' => self::ACCESS_ALLOW,
137
-            ),
138
-            PageDomainSwitch::class   => array(
139
-                self::MAIN => self::ACCESS_ALLOW
140
-            )
141
-        ),
142
-        'user'              => array(
143
-            '_description'                       => 'A standard tool user.',
144
-            '_editableBy'                        => array('admin', 'toolRoot'),
145
-            '_childRoles'                        => array(
146
-                'internalStats',
147
-            ),
148
-            PageMain::class                      => array(
149
-                self::MAIN => self::ACCESS_ALLOW,
150
-            ),
151
-            PageBan::class                       => array(
152
-                self::MAIN => self::ACCESS_ALLOW,
153
-                'show'     => self::ACCESS_ALLOW,
154
-            ),
155
-            'BanVisibility'             => array(
156
-                'user' => self::ACCESS_ALLOW,
157
-            ),
158
-            'BanType'                   => array(
159
-                'ip' => self::ACCESS_ALLOW,
160
-                'name' => self::ACCESS_ALLOW,
161
-            ),
162
-            PageEditComment::class               => array(
163
-                self::MAIN => self::ACCESS_ALLOW,
164
-            ),
165
-            PageEmailManagement::class           => array(
166
-                self::MAIN => self::ACCESS_ALLOW,
167
-                'view'     => self::ACCESS_ALLOW,
168
-            ),
169
-            PageExpandedRequestList::class       => array(
170
-                self::MAIN => self::ACCESS_ALLOW,
171
-            ),
172
-            PageLog::class                       => array(
173
-                self::MAIN => self::ACCESS_ALLOW,
174
-            ),
175
-            PageSearch::class                    => array(
176
-                self::MAIN => self::ACCESS_ALLOW,
177
-                'byName'   => self::ACCESS_ALLOW,
178
-                'byEmail'  => self::ACCESS_ALLOW,
179
-                'byIp'     => self::ACCESS_ALLOW,
180
-                'allowNonConfirmed' => self::ACCESS_ALLOW,
181
-            ),
182
-            PageWelcomeTemplateManagement::class => array(
183
-                self::MAIN => self::ACCESS_ALLOW,
184
-                'select'   => self::ACCESS_ALLOW,
185
-                'view'     => self::ACCESS_ALLOW,
186
-            ),
187
-            PageViewRequest::class               => array(
188
-                self::MAIN       => self::ACCESS_ALLOW,
189
-                'seeAllRequests' => self::ACCESS_ALLOW,
190
-            ),
191
-            'RequestData'                        => array(
192
-                'seePrivateDataWhenReserved' => self::ACCESS_ALLOW,
193
-                'seePrivateDataWithHash'     => self::ACCESS_ALLOW,
194
-                'seeRelatedRequests'         => self::ACCESS_ALLOW,
195
-            ),
196
-            PageCustomClose::class               => array(
197
-                self::MAIN => self::ACCESS_ALLOW,
198
-            ),
199
-            PageComment::class                   => array(
200
-                self::MAIN => self::ACCESS_ALLOW,
201
-            ),
202
-            PageFlagComment::class               => array(
203
-                self::MAIN => self::ACCESS_ALLOW,
204
-            ),
205
-            PageCloseRequest::class              => array(
206
-                self::MAIN => self::ACCESS_ALLOW,
207
-            ),
208
-            PageCreateRequest::class             => array(
209
-                self::MAIN => self::ACCESS_ALLOW,
210
-            ),
211
-            PageDeferRequest::class              => array(
212
-                self::MAIN => self::ACCESS_ALLOW,
213
-            ),
214
-            PageDropRequest::class               => array(
215
-                self::MAIN => self::ACCESS_ALLOW,
216
-            ),
217
-            PageReservation::class               => array(
218
-                self::MAIN => self::ACCESS_ALLOW,
219
-            ),
220
-            PageSendToUser::class                => array(
221
-                self::MAIN => self::ACCESS_ALLOW,
222
-            ),
223
-            PageBreakReservation::class          => array(
224
-                self::MAIN => self::ACCESS_ALLOW,
225
-            ),
226
-            PageJobQueue::class                  => array(
227
-                self::MAIN    => self::ACCESS_ALLOW,
228
-                'view'        => self::ACCESS_ALLOW,
229
-                'all'         => self::ACCESS_ALLOW,
230
-                'acknowledge' => self::ACCESS_ALLOW,
231
-                'cancel'      => self::ACCESS_ALLOW
232
-            ),
233
-            PageDomainManagement::class          => array(
234
-                self::MAIN => self::ACCESS_ALLOW,
235
-            ),
236
-            PageRequestFormManagement::class     => array(
237
-                self::MAIN => self::ACCESS_ALLOW,
238
-                'view'     => self::ACCESS_ALLOW,
239
-                'preview'  => self::ACCESS_ALLOW,
240
-            ),
241
-            'RequestCreation'                    => array(
242
-                User::CREATION_MANUAL => self::ACCESS_ALLOW,
243
-                User::CREATION_OAUTH  => self::ACCESS_ALLOW,
244
-            ),
245
-            'GlobalInfo'                         => array(
246
-                'viewSiteNotice' => self::ACCESS_ALLOW,
247
-                'viewOnlineUsers' => self::ACCESS_ALLOW,
248
-            ),
249
-        ),
250
-        'admin'             => array(
251
-            '_description'                       => 'A tool administrator.',
252
-            '_editableBy'                        => array('admin', 'toolRoot'),
253
-            '_childRoles'                        => array(
254
-                'user',
255
-                'requestAdminTools',
256
-            ),
257
-            PageEmailManagement::class           => array(
258
-                'edit'   => self::ACCESS_ALLOW,
259
-                'create' => self::ACCESS_ALLOW,
260
-            ),
261
-            PageSiteNotice::class                => array(
262
-                self::MAIN => self::ACCESS_ALLOW,
263
-            ),
264
-            PageUserManagement::class            => array(
265
-                self::MAIN  => self::ACCESS_ALLOW,
266
-                'approve'   => self::ACCESS_ALLOW,
267
-                'decline'   => self::ACCESS_ALLOW,
268
-                'rename'    => self::ACCESS_ALLOW,
269
-                'editUser'  => self::ACCESS_ALLOW,
270
-                'suspend'   => self::ACCESS_ALLOW,
271
-                'editRoles' => self::ACCESS_ALLOW,
272
-            ),
273
-            PageSearch::class                    => array(
274
-                'byComment' => self::ACCESS_ALLOW,
275
-            ),
276
-            PageManuallyConfirm::class               => array(
277
-                self::MAIN => self::ACCESS_ALLOW,
278
-            ),
279
-            PageWelcomeTemplateManagement::class => array(
280
-                'edit'   => self::ACCESS_ALLOW,
281
-                'delete' => self::ACCESS_ALLOW,
282
-                'add'    => self::ACCESS_ALLOW,
283
-            ),
284
-            PageJobQueue::class                  => array(
285
-                'acknowledge' => self::ACCESS_ALLOW,
286
-                'requeue'     => self::ACCESS_ALLOW,
287
-                'cancel'      => self::ACCESS_ALLOW,
288
-            ),
289
-            'RequestData'               => array(
290
-                'reopenClearedRequest'  => self::ACCESS_ALLOW,
291
-            ),
292
-            PageQueueManagement::class           => array(
293
-                self::MAIN => self::ACCESS_ALLOW,
294
-                'edit'     => self::ACCESS_ALLOW,
295
-                'create'   => self::ACCESS_ALLOW,
296
-            ),
297
-            PageRequestFormManagement::class     => array(
298
-                'edit'     => self::ACCESS_ALLOW,
299
-                'create'   => self::ACCESS_ALLOW,
300
-            ),
301
-            PageDomainManagement::class          => array(
302
-                'edit'     => self::ACCESS_ALLOW,
303
-            ),
304
-        ),
305
-        'checkuser'         => array(
306
-            '_description'            => 'A user with CheckUser access',
307
-            '_editableBy'             => array('checkuser', 'toolRoot'),
308
-            '_childRoles'             => array(
309
-                'user',
310
-                'requestAdminTools',
311
-            ),
312
-            PageUserManagement::class => array(
313
-                self::MAIN  => self::ACCESS_ALLOW,
314
-                'suspend'   => self::ACCESS_ALLOW,
315
-                'editRoles' => self::ACCESS_ALLOW,
316
-            ),
317
-            'RequestData'             => array(
318
-                'seeUserAgentData'      => self::ACCESS_ALLOW,
319
-                'seeCheckuserComments'  => self::ACCESS_ALLOW,
320
-                'createLocalAccount'    => self::ACCESS_ALLOW,
321
-            ),
322
-            'BanType'                   => array(
323
-                'useragent' => self::ACCESS_ALLOW,
324
-            ),
325
-            'BanVisibility'             => array(
326
-                'checkuser' => self::ACCESS_ALLOW,
327
-            ),
328
-        ),
329
-        'toolRoot'          => array(
330
-            '_description' => 'A user with shell access to the servers running the tool',
331
-            '_editableBy'  => array('toolRoot'),
332
-            '_childRoles'  => array(
333
-                'admin',
334
-            ),
335
-            'BanType'                   => array(
336
-                'ip-largerange' => self::ACCESS_ALLOW,
337
-            ),
338
-            PageMultiFactor::class => array(
339
-                'enableU2F'         => self::ACCESS_ALLOW,
340
-                'disableU2F'        => self::ACCESS_ALLOW,
341
-            ),
342
-            PageDomainManagement::class => array(
343
-                self::MAIN => self::ACCESS_ALLOW,
344
-                'editAll'  => self::ACCESS_ALLOW,
345
-                'edit'     => self::ACCESS_ALLOW,
346
-                'create'   => self::ACCESS_ALLOW,
347
-            ),
348
-            PageErrorLogViewer::class => array(
349
-                self::MAIN      => self::ACCESS_ALLOW,
350
-                'view'          => self::ACCESS_ALLOW,
351
-                'remove'        => self::ACCESS_ALLOW,
352
-            ),
353
-        ),
354
-        'botCreation'       => array(
355
-            '_description'    => 'A user allowed to use the bot to perform account creations',
356
-            '_editableBy'     => array('admin', 'toolRoot'),
357
-            '_childRoles'     => array(),
358
-            'RequestCreation' => array(
359
-                User::CREATION_BOT => self::ACCESS_ALLOW,
360
-            ),
361
-        ),
116
+			'_childRoles'             => array(
117
+				'public',
118
+			),
119
+			PagePreferences::class    => array(
120
+				self::MAIN => self::ACCESS_ALLOW,
121
+				'refreshOAuth' => self::ACCESS_ALLOW,
122
+			),
123
+			PageChangePassword::class => array(
124
+				self::MAIN => self::ACCESS_ALLOW,
125
+			),
126
+			PageMultiFactor::class    => array(
127
+				self::MAIN          => self::ACCESS_ALLOW,
128
+				'scratch'           => self::ACCESS_ALLOW,
129
+				'enableYubikeyOtp'  => self::ACCESS_ALLOW,
130
+				'disableYubikeyOtp' => self::ACCESS_ALLOW,
131
+				'enableTotp'        => self::ACCESS_ALLOW,
132
+				'disableTotp'       => self::ACCESS_ALLOW,
133
+			),
134
+			PageOAuth::class          => array(
135
+				'attach' => self::ACCESS_ALLOW,
136
+				'detach' => self::ACCESS_ALLOW,
137
+			),
138
+			PageDomainSwitch::class   => array(
139
+				self::MAIN => self::ACCESS_ALLOW
140
+			)
141
+		),
142
+		'user'              => array(
143
+			'_description'                       => 'A standard tool user.',
144
+			'_editableBy'                        => array('admin', 'toolRoot'),
145
+			'_childRoles'                        => array(
146
+				'internalStats',
147
+			),
148
+			PageMain::class                      => array(
149
+				self::MAIN => self::ACCESS_ALLOW,
150
+			),
151
+			PageBan::class                       => array(
152
+				self::MAIN => self::ACCESS_ALLOW,
153
+				'show'     => self::ACCESS_ALLOW,
154
+			),
155
+			'BanVisibility'             => array(
156
+				'user' => self::ACCESS_ALLOW,
157
+			),
158
+			'BanType'                   => array(
159
+				'ip' => self::ACCESS_ALLOW,
160
+				'name' => self::ACCESS_ALLOW,
161
+			),
162
+			PageEditComment::class               => array(
163
+				self::MAIN => self::ACCESS_ALLOW,
164
+			),
165
+			PageEmailManagement::class           => array(
166
+				self::MAIN => self::ACCESS_ALLOW,
167
+				'view'     => self::ACCESS_ALLOW,
168
+			),
169
+			PageExpandedRequestList::class       => array(
170
+				self::MAIN => self::ACCESS_ALLOW,
171
+			),
172
+			PageLog::class                       => array(
173
+				self::MAIN => self::ACCESS_ALLOW,
174
+			),
175
+			PageSearch::class                    => array(
176
+				self::MAIN => self::ACCESS_ALLOW,
177
+				'byName'   => self::ACCESS_ALLOW,
178
+				'byEmail'  => self::ACCESS_ALLOW,
179
+				'byIp'     => self::ACCESS_ALLOW,
180
+				'allowNonConfirmed' => self::ACCESS_ALLOW,
181
+			),
182
+			PageWelcomeTemplateManagement::class => array(
183
+				self::MAIN => self::ACCESS_ALLOW,
184
+				'select'   => self::ACCESS_ALLOW,
185
+				'view'     => self::ACCESS_ALLOW,
186
+			),
187
+			PageViewRequest::class               => array(
188
+				self::MAIN       => self::ACCESS_ALLOW,
189
+				'seeAllRequests' => self::ACCESS_ALLOW,
190
+			),
191
+			'RequestData'                        => array(
192
+				'seePrivateDataWhenReserved' => self::ACCESS_ALLOW,
193
+				'seePrivateDataWithHash'     => self::ACCESS_ALLOW,
194
+				'seeRelatedRequests'         => self::ACCESS_ALLOW,
195
+			),
196
+			PageCustomClose::class               => array(
197
+				self::MAIN => self::ACCESS_ALLOW,
198
+			),
199
+			PageComment::class                   => array(
200
+				self::MAIN => self::ACCESS_ALLOW,
201
+			),
202
+			PageFlagComment::class               => array(
203
+				self::MAIN => self::ACCESS_ALLOW,
204
+			),
205
+			PageCloseRequest::class              => array(
206
+				self::MAIN => self::ACCESS_ALLOW,
207
+			),
208
+			PageCreateRequest::class             => array(
209
+				self::MAIN => self::ACCESS_ALLOW,
210
+			),
211
+			PageDeferRequest::class              => array(
212
+				self::MAIN => self::ACCESS_ALLOW,
213
+			),
214
+			PageDropRequest::class               => array(
215
+				self::MAIN => self::ACCESS_ALLOW,
216
+			),
217
+			PageReservation::class               => array(
218
+				self::MAIN => self::ACCESS_ALLOW,
219
+			),
220
+			PageSendToUser::class                => array(
221
+				self::MAIN => self::ACCESS_ALLOW,
222
+			),
223
+			PageBreakReservation::class          => array(
224
+				self::MAIN => self::ACCESS_ALLOW,
225
+			),
226
+			PageJobQueue::class                  => array(
227
+				self::MAIN    => self::ACCESS_ALLOW,
228
+				'view'        => self::ACCESS_ALLOW,
229
+				'all'         => self::ACCESS_ALLOW,
230
+				'acknowledge' => self::ACCESS_ALLOW,
231
+				'cancel'      => self::ACCESS_ALLOW
232
+			),
233
+			PageDomainManagement::class          => array(
234
+				self::MAIN => self::ACCESS_ALLOW,
235
+			),
236
+			PageRequestFormManagement::class     => array(
237
+				self::MAIN => self::ACCESS_ALLOW,
238
+				'view'     => self::ACCESS_ALLOW,
239
+				'preview'  => self::ACCESS_ALLOW,
240
+			),
241
+			'RequestCreation'                    => array(
242
+				User::CREATION_MANUAL => self::ACCESS_ALLOW,
243
+				User::CREATION_OAUTH  => self::ACCESS_ALLOW,
244
+			),
245
+			'GlobalInfo'                         => array(
246
+				'viewSiteNotice' => self::ACCESS_ALLOW,
247
+				'viewOnlineUsers' => self::ACCESS_ALLOW,
248
+			),
249
+		),
250
+		'admin'             => array(
251
+			'_description'                       => 'A tool administrator.',
252
+			'_editableBy'                        => array('admin', 'toolRoot'),
253
+			'_childRoles'                        => array(
254
+				'user',
255
+				'requestAdminTools',
256
+			),
257
+			PageEmailManagement::class           => array(
258
+				'edit'   => self::ACCESS_ALLOW,
259
+				'create' => self::ACCESS_ALLOW,
260
+			),
261
+			PageSiteNotice::class                => array(
262
+				self::MAIN => self::ACCESS_ALLOW,
263
+			),
264
+			PageUserManagement::class            => array(
265
+				self::MAIN  => self::ACCESS_ALLOW,
266
+				'approve'   => self::ACCESS_ALLOW,
267
+				'decline'   => self::ACCESS_ALLOW,
268
+				'rename'    => self::ACCESS_ALLOW,
269
+				'editUser'  => self::ACCESS_ALLOW,
270
+				'suspend'   => self::ACCESS_ALLOW,
271
+				'editRoles' => self::ACCESS_ALLOW,
272
+			),
273
+			PageSearch::class                    => array(
274
+				'byComment' => self::ACCESS_ALLOW,
275
+			),
276
+			PageManuallyConfirm::class               => array(
277
+				self::MAIN => self::ACCESS_ALLOW,
278
+			),
279
+			PageWelcomeTemplateManagement::class => array(
280
+				'edit'   => self::ACCESS_ALLOW,
281
+				'delete' => self::ACCESS_ALLOW,
282
+				'add'    => self::ACCESS_ALLOW,
283
+			),
284
+			PageJobQueue::class                  => array(
285
+				'acknowledge' => self::ACCESS_ALLOW,
286
+				'requeue'     => self::ACCESS_ALLOW,
287
+				'cancel'      => self::ACCESS_ALLOW,
288
+			),
289
+			'RequestData'               => array(
290
+				'reopenClearedRequest'  => self::ACCESS_ALLOW,
291
+			),
292
+			PageQueueManagement::class           => array(
293
+				self::MAIN => self::ACCESS_ALLOW,
294
+				'edit'     => self::ACCESS_ALLOW,
295
+				'create'   => self::ACCESS_ALLOW,
296
+			),
297
+			PageRequestFormManagement::class     => array(
298
+				'edit'     => self::ACCESS_ALLOW,
299
+				'create'   => self::ACCESS_ALLOW,
300
+			),
301
+			PageDomainManagement::class          => array(
302
+				'edit'     => self::ACCESS_ALLOW,
303
+			),
304
+		),
305
+		'checkuser'         => array(
306
+			'_description'            => 'A user with CheckUser access',
307
+			'_editableBy'             => array('checkuser', 'toolRoot'),
308
+			'_childRoles'             => array(
309
+				'user',
310
+				'requestAdminTools',
311
+			),
312
+			PageUserManagement::class => array(
313
+				self::MAIN  => self::ACCESS_ALLOW,
314
+				'suspend'   => self::ACCESS_ALLOW,
315
+				'editRoles' => self::ACCESS_ALLOW,
316
+			),
317
+			'RequestData'             => array(
318
+				'seeUserAgentData'      => self::ACCESS_ALLOW,
319
+				'seeCheckuserComments'  => self::ACCESS_ALLOW,
320
+				'createLocalAccount'    => self::ACCESS_ALLOW,
321
+			),
322
+			'BanType'                   => array(
323
+				'useragent' => self::ACCESS_ALLOW,
324
+			),
325
+			'BanVisibility'             => array(
326
+				'checkuser' => self::ACCESS_ALLOW,
327
+			),
328
+		),
329
+		'toolRoot'          => array(
330
+			'_description' => 'A user with shell access to the servers running the tool',
331
+			'_editableBy'  => array('toolRoot'),
332
+			'_childRoles'  => array(
333
+				'admin',
334
+			),
335
+			'BanType'                   => array(
336
+				'ip-largerange' => self::ACCESS_ALLOW,
337
+			),
338
+			PageMultiFactor::class => array(
339
+				'enableU2F'         => self::ACCESS_ALLOW,
340
+				'disableU2F'        => self::ACCESS_ALLOW,
341
+			),
342
+			PageDomainManagement::class => array(
343
+				self::MAIN => self::ACCESS_ALLOW,
344
+				'editAll'  => self::ACCESS_ALLOW,
345
+				'edit'     => self::ACCESS_ALLOW,
346
+				'create'   => self::ACCESS_ALLOW,
347
+			),
348
+			PageErrorLogViewer::class => array(
349
+				self::MAIN      => self::ACCESS_ALLOW,
350
+				'view'          => self::ACCESS_ALLOW,
351
+				'remove'        => self::ACCESS_ALLOW,
352
+			),
353
+		),
354
+		'botCreation'       => array(
355
+			'_description'    => 'A user allowed to use the bot to perform account creations',
356
+			'_editableBy'     => array('admin', 'toolRoot'),
357
+			'_childRoles'     => array(),
358
+			'RequestCreation' => array(
359
+				User::CREATION_BOT => self::ACCESS_ALLOW,
360
+			),
361
+		),
362 362
 
363
-        // Child roles go below this point
364
-        'publicStats'       => array(
365
-            '_hidden'               => true,
366
-            StatsUsers::class       => array(
367
-                self::MAIN => self::ACCESS_ALLOW,
368
-                'detail'   => self::ACCESS_ALLOW,
369
-            ),
370
-            StatsTopCreators::class => array(
371
-                self::MAIN => self::ACCESS_ALLOW,
372
-            ),
373
-            StatsMonthlyStats::class     => array(
374
-                self::MAIN => self::ACCESS_ALLOW,
375
-            ),
376
-        ),
377
-        'internalStats'     => array(
378
-            '_hidden'                    => true,
379
-            StatsMain::class             => array(
380
-                self::MAIN => self::ACCESS_ALLOW,
381
-            ),
382
-            StatsFastCloses::class       => array(
383
-                self::MAIN => self::ACCESS_ALLOW,
384
-            ),
385
-            StatsInactiveUsers::class    => array(
386
-                self::MAIN => self::ACCESS_ALLOW,
387
-            ),
388
-            StatsReservedRequests::class => array(
389
-                self::MAIN => self::ACCESS_ALLOW,
390
-            ),
391
-            StatsTemplateStats::class    => array(
392
-                self::MAIN => self::ACCESS_ALLOW,
393
-            ),
394
-        ),
395
-        'requestAdminTools' => array(
396
-            '_hidden'                   => true,
397
-            PageBan::class              => array(
398
-                self::MAIN => self::ACCESS_ALLOW,
399
-                'set'      => self::ACCESS_ALLOW,
400
-                'remove'   => self::ACCESS_ALLOW,
401
-            ),
402
-            'BanType'                   => array(
403
-                'ip' => self::ACCESS_ALLOW,
404
-                'email' => self::ACCESS_ALLOW,
405
-                'name' => self::ACCESS_ALLOW,
406
-            ),
407
-            'BanVisibility'             => array(
408
-                'user' => self::ACCESS_ALLOW,
409
-                'admin' => self::ACCESS_ALLOW,
410
-            ),
411
-            PageEditComment::class      => array(
412
-                'editOthers' => self::ACCESS_ALLOW,
413
-            ),
414
-            PageBreakReservation::class => array(
415
-                'force' => self::ACCESS_ALLOW,
416
-            ),
417
-            PageCustomClose::class      => array(
418
-                'skipCcMailingList' => self::ACCESS_ALLOW,
419
-            ),
420
-            PageFlagComment::class      => array(
421
-                'unflag'   => self::ACCESS_ALLOW,
422
-            ),
423
-            PageListFlaggedComments::class => array(
424
-                self::MAIN => self::ACCESS_ALLOW,
425
-            ),
426
-            'RequestData'               => array(
427
-                'reopenOldRequest'      => self::ACCESS_ALLOW,
428
-                'alwaysSeePrivateData'  => self::ACCESS_ALLOW,
429
-                'alwaysSeeHash'         => self::ACCESS_ALLOW,
430
-                'seeRestrictedComments' => self::ACCESS_ALLOW,
431
-            ),
432
-        ),
433
-    );
434
-    /** @var array
435
-     * List of roles which are *exempt* from the identification requirements
436
-     *
437
-     * Think twice about adding roles to this list.
438
-     *
439
-     * @category Security-Critical
440
-     */
441
-    private $identificationExempt = array('public', 'loggedIn');
363
+		// Child roles go below this point
364
+		'publicStats'       => array(
365
+			'_hidden'               => true,
366
+			StatsUsers::class       => array(
367
+				self::MAIN => self::ACCESS_ALLOW,
368
+				'detail'   => self::ACCESS_ALLOW,
369
+			),
370
+			StatsTopCreators::class => array(
371
+				self::MAIN => self::ACCESS_ALLOW,
372
+			),
373
+			StatsMonthlyStats::class     => array(
374
+				self::MAIN => self::ACCESS_ALLOW,
375
+			),
376
+		),
377
+		'internalStats'     => array(
378
+			'_hidden'                    => true,
379
+			StatsMain::class             => array(
380
+				self::MAIN => self::ACCESS_ALLOW,
381
+			),
382
+			StatsFastCloses::class       => array(
383
+				self::MAIN => self::ACCESS_ALLOW,
384
+			),
385
+			StatsInactiveUsers::class    => array(
386
+				self::MAIN => self::ACCESS_ALLOW,
387
+			),
388
+			StatsReservedRequests::class => array(
389
+				self::MAIN => self::ACCESS_ALLOW,
390
+			),
391
+			StatsTemplateStats::class    => array(
392
+				self::MAIN => self::ACCESS_ALLOW,
393
+			),
394
+		),
395
+		'requestAdminTools' => array(
396
+			'_hidden'                   => true,
397
+			PageBan::class              => array(
398
+				self::MAIN => self::ACCESS_ALLOW,
399
+				'set'      => self::ACCESS_ALLOW,
400
+				'remove'   => self::ACCESS_ALLOW,
401
+			),
402
+			'BanType'                   => array(
403
+				'ip' => self::ACCESS_ALLOW,
404
+				'email' => self::ACCESS_ALLOW,
405
+				'name' => self::ACCESS_ALLOW,
406
+			),
407
+			'BanVisibility'             => array(
408
+				'user' => self::ACCESS_ALLOW,
409
+				'admin' => self::ACCESS_ALLOW,
410
+			),
411
+			PageEditComment::class      => array(
412
+				'editOthers' => self::ACCESS_ALLOW,
413
+			),
414
+			PageBreakReservation::class => array(
415
+				'force' => self::ACCESS_ALLOW,
416
+			),
417
+			PageCustomClose::class      => array(
418
+				'skipCcMailingList' => self::ACCESS_ALLOW,
419
+			),
420
+			PageFlagComment::class      => array(
421
+				'unflag'   => self::ACCESS_ALLOW,
422
+			),
423
+			PageListFlaggedComments::class => array(
424
+				self::MAIN => self::ACCESS_ALLOW,
425
+			),
426
+			'RequestData'               => array(
427
+				'reopenOldRequest'      => self::ACCESS_ALLOW,
428
+				'alwaysSeePrivateData'  => self::ACCESS_ALLOW,
429
+				'alwaysSeeHash'         => self::ACCESS_ALLOW,
430
+				'seeRestrictedComments' => self::ACCESS_ALLOW,
431
+			),
432
+		),
433
+	);
434
+	/** @var array
435
+	 * List of roles which are *exempt* from the identification requirements
436
+	 *
437
+	 * Think twice about adding roles to this list.
438
+	 *
439
+	 * @category Security-Critical
440
+	 */
441
+	private $identificationExempt = array('public', 'loggedIn');
442 442
 
443
-    /**
444
-     * RoleConfiguration constructor.
445
-     *
446
-     * @param array $roleConfig           Set to non-null to override the default configuration.
447
-     * @param array $identificationExempt Set to non-null to override the default configuration.
448
-     */
449
-    public function __construct(array $roleConfig = null, array $identificationExempt = null)
450
-    {
451
-        if ($roleConfig !== null) {
452
-            $this->roleConfig = $roleConfig;
453
-        }
443
+	/**
444
+	 * RoleConfiguration constructor.
445
+	 *
446
+	 * @param array $roleConfig           Set to non-null to override the default configuration.
447
+	 * @param array $identificationExempt Set to non-null to override the default configuration.
448
+	 */
449
+	public function __construct(array $roleConfig = null, array $identificationExempt = null)
450
+	{
451
+		if ($roleConfig !== null) {
452
+			$this->roleConfig = $roleConfig;
453
+		}
454 454
 
455
-        if ($identificationExempt !== null) {
456
-            $this->identificationExempt = $identificationExempt;
457
-        }
458
-    }
455
+		if ($identificationExempt !== null) {
456
+			$this->identificationExempt = $identificationExempt;
457
+		}
458
+	}
459 459
 
460
-    /**
461
-     * @param array $roles The roles to check
462
-     *
463
-     * @return array
464
-     */
465
-    public function getApplicableRoles(array $roles)
466
-    {
467
-        $available = array();
460
+	/**
461
+	 * @param array $roles The roles to check
462
+	 *
463
+	 * @return array
464
+	 */
465
+	public function getApplicableRoles(array $roles)
466
+	{
467
+		$available = array();
468 468
 
469
-        foreach ($roles as $role) {
470
-            if (!isset($this->roleConfig[$role])) {
471
-                // wat
472
-                continue;
473
-            }
469
+		foreach ($roles as $role) {
470
+			if (!isset($this->roleConfig[$role])) {
471
+				// wat
472
+				continue;
473
+			}
474 474
 
475
-            $available[$role] = $this->roleConfig[$role];
475
+			$available[$role] = $this->roleConfig[$role];
476 476
 
477
-            if (isset($available[$role]['_childRoles'])) {
478
-                $childRoles = $this->getApplicableRoles($available[$role]['_childRoles']);
479
-                $available = array_merge($available, $childRoles);
477
+			if (isset($available[$role]['_childRoles'])) {
478
+				$childRoles = $this->getApplicableRoles($available[$role]['_childRoles']);
479
+				$available = array_merge($available, $childRoles);
480 480
 
481
-                unset($available[$role]['_childRoles']);
482
-            }
481
+				unset($available[$role]['_childRoles']);
482
+			}
483 483
 
484
-            foreach (array('_hidden', '_editableBy', '_description') as $item) {
485
-                if (isset($available[$role][$item])) {
486
-                    unset($available[$role][$item]);
487
-                }
488
-            }
489
-        }
484
+			foreach (array('_hidden', '_editableBy', '_description') as $item) {
485
+				if (isset($available[$role][$item])) {
486
+					unset($available[$role][$item]);
487
+				}
488
+			}
489
+		}
490 490
 
491
-        return $available;
492
-    }
491
+		return $available;
492
+	}
493 493
 
494
-    public function getAvailableRoles()
495
-    {
496
-        $possible = array_diff(array_keys($this->roleConfig), array('public', 'loggedIn'));
494
+	public function getAvailableRoles()
495
+	{
496
+		$possible = array_diff(array_keys($this->roleConfig), array('public', 'loggedIn'));
497 497
 
498
-        $actual = array();
498
+		$actual = array();
499 499
 
500
-        foreach ($possible as $role) {
501
-            if (!isset($this->roleConfig[$role]['_hidden'])) {
502
-                $actual[$role] = array(
503
-                    'description' => $this->roleConfig[$role]['_description'],
504
-                    'editableBy'  => $this->roleConfig[$role]['_editableBy'],
505
-                );
506
-            }
507
-        }
500
+		foreach ($possible as $role) {
501
+			if (!isset($this->roleConfig[$role]['_hidden'])) {
502
+				$actual[$role] = array(
503
+					'description' => $this->roleConfig[$role]['_description'],
504
+					'editableBy'  => $this->roleConfig[$role]['_editableBy'],
505
+				);
506
+			}
507
+		}
508 508
 
509
-        return $actual;
510
-    }
509
+		return $actual;
510
+	}
511 511
 
512
-    /**
513
-     * @param string $role
514
-     *
515
-     * @return bool
516
-     */
517
-    public function roleNeedsIdentification($role)
518
-    {
519
-        if (in_array($role, $this->identificationExempt)) {
520
-            return false;
521
-        }
512
+	/**
513
+	 * @param string $role
514
+	 *
515
+	 * @return bool
516
+	 */
517
+	public function roleNeedsIdentification($role)
518
+	{
519
+		if (in_array($role, $this->identificationExempt)) {
520
+			return false;
521
+		}
522 522
 
523
-        return true;
524
-    }
523
+		return true;
524
+	}
525 525
 }
Please login to merge, or discard this patch.
includes/Security/SecurityManager.php 1 patch
Indentation   +214 added lines, -214 removed lines patch added patch discarded remove patch
@@ -14,218 +14,218 @@
 block discarded – undo
14 14
 
15 15
 final class SecurityManager
16 16
 {
17
-    const ALLOWED = 1;
18
-    const ERROR_NOT_IDENTIFIED = 2;
19
-    const ERROR_DENIED = 3;
20
-    /** @var IdentificationVerifier */
21
-    private $identificationVerifier;
22
-    /**
23
-     * @var RoleConfiguration
24
-     */
25
-    private $roleConfiguration;
26
-
27
-    private $cache = [];
28
-
29
-    /**
30
-     * SecurityManager constructor.
31
-     *
32
-     * @param IdentificationVerifier $identificationVerifier
33
-     * @param RoleConfiguration      $roleConfiguration
34
-     */
35
-    public function __construct(
36
-        IdentificationVerifier $identificationVerifier,
37
-        RoleConfiguration $roleConfiguration
38
-    ) {
39
-        $this->identificationVerifier = $identificationVerifier;
40
-        $this->roleConfiguration = $roleConfiguration;
41
-    }
42
-
43
-    /**
44
-     * Tests if a user is allowed to perform an action.
45
-     *
46
-     * This method should form a hard, deterministic security barrier, and only return true if it is absolutely sure
47
-     * that a user should have access to something.
48
-     *
49
-     * @param string $page
50
-     * @param string $route
51
-     * @param User   $user
52
-     *
53
-     * @return int
54
-     *
55
-     * @category Security-Critical
56
-     */
57
-    public function allows($page, $route, User $user)
58
-    {
59
-        $this->getCachedActiveRoles($user, $activeRoles, $inactiveRoles);
60
-
61
-        $availableRights = $this->flattenRoles($activeRoles);
62
-        $testResult = $this->findResult($availableRights, $page, $route);
63
-
64
-        if ($testResult !== null) {
65
-            // We got a firm result here, so just return it.
66
-            return $testResult;
67
-        }
68
-
69
-        // No firm result yet, so continue testing the inactive roles so we can give a better error.
70
-        $inactiveRights = $this->flattenRoles($inactiveRoles);
71
-        $testResult = $this->findResult($inactiveRights, $page, $route);
72
-
73
-        if ($testResult === self::ALLOWED) {
74
-            // The user is allowed to access this, but their role is inactive.
75
-            return self::ERROR_NOT_IDENTIFIED;
76
-        }
77
-
78
-        // Other options from the secondary test are denied and inconclusive, which at this point defaults to denied.
79
-        return self::ERROR_DENIED;
80
-    }
81
-
82
-    /**
83
-     * @param array  $pseudoRole The role (flattened) to check
84
-     * @param string $page       The page class to check
85
-     * @param string $route      The page route to check
86
-     *
87
-     * @return int|null
88
-     */
89
-    private function findResult($pseudoRole, $page, $route)
90
-    {
91
-        if (isset($pseudoRole[$page])) {
92
-            // check for deny on catch-all route
93
-            if (isset($pseudoRole[$page][RoleConfiguration::ALL])) {
94
-                if ($pseudoRole[$page][RoleConfiguration::ALL] === RoleConfiguration::ACCESS_DENY) {
95
-                    return self::ERROR_DENIED;
96
-                }
97
-            }
98
-
99
-            // check normal route
100
-            if (isset($pseudoRole[$page][$route])) {
101
-                if ($pseudoRole[$page][$route] === RoleConfiguration::ACCESS_DENY) {
102
-                    return self::ERROR_DENIED;
103
-                }
104
-
105
-                if ($pseudoRole[$page][$route] === RoleConfiguration::ACCESS_ALLOW) {
106
-                    return self::ALLOWED;
107
-                }
108
-            }
109
-
110
-            // check for allowed on catch-all route
111
-            if (isset($pseudoRole[$page][RoleConfiguration::ALL])) {
112
-                if ($pseudoRole[$page][RoleConfiguration::ALL] === RoleConfiguration::ACCESS_ALLOW) {
113
-                    return self::ALLOWED;
114
-                }
115
-            }
116
-        }
117
-
118
-        // return indeterminate result
119
-        return null;
120
-    }
121
-
122
-    /**
123
-     * Takes an array of roles and flattens the values to a single set.
124
-     *
125
-     * @param array $activeRoles
126
-     *
127
-     * @return array
128
-     */
129
-    private function flattenRoles($activeRoles)
130
-    {
131
-        $result = array();
132
-
133
-        $roleConfig = $this->roleConfiguration->getApplicableRoles($activeRoles);
134
-
135
-        // Iterate over every page in every role
136
-        foreach ($roleConfig as $role) {
137
-            foreach ($role as $page => $pageRights) {
138
-                // Create holder in result for this page
139
-                if (!isset($result[$page])) {
140
-                    $result[$page] = array();
141
-                }
142
-
143
-                foreach ($pageRights as $action => $permission) {
144
-                    // Deny takes precedence, so if it's set, don't change it.
145
-                    if (isset($result[$page][$action])) {
146
-                        if ($result[$page][$action] === RoleConfiguration::ACCESS_DENY) {
147
-                            continue;
148
-                        }
149
-                    }
150
-
151
-                    if ($permission === RoleConfiguration::ACCESS_DEFAULT) {
152
-                        // Configured to do precisely nothing.
153
-                        continue;
154
-                    }
155
-
156
-                    $result[$page][$action] = $permission;
157
-                }
158
-            }
159
-        }
160
-
161
-        return $result;
162
-    }
163
-
164
-    /**
165
-     * @param User  $user
166
-     * @param array $activeRoles
167
-     * @param array $inactiveRoles
168
-     */
169
-    public function getActiveRoles(User $user, &$activeRoles, &$inactiveRoles)
170
-    {
171
-        // Default to the community user here, because the main user is logged out
172
-        $identified = false;
173
-        $userRoles = array('public');
174
-
175
-        // if we're not the community user, get our real rights.
176
-        if (!$user->isCommunityUser()) {
177
-            // Check the user's status - only active users are allowed the effects of roles
178
-
179
-            $userRoles[] = 'loggedIn';
180
-
181
-            if ($user->isActive()) {
182
-                $ur = UserRole::getForUser($user->getId(), $user->getDatabase());
183
-
184
-                // NOTE: public is still in this array.
185
-                foreach ($ur as $r) {
186
-                    $userRoles[] = $r->getRole();
187
-                }
188
-
189
-                $identified = $user->isIdentified($this->identificationVerifier);
190
-            }
191
-        }
192
-
193
-        $activeRoles = array();
194
-        $inactiveRoles = array();
195
-
196
-        foreach ($userRoles as $v) {
197
-            if ($this->roleConfiguration->roleNeedsIdentification($v)) {
198
-                if ($identified) {
199
-                    $activeRoles[] = $v;
200
-                }
201
-                else {
202
-                    $inactiveRoles[] = $v;
203
-                }
204
-            }
205
-            else {
206
-                $activeRoles[] = $v;
207
-            }
208
-        }
209
-    }
210
-
211
-    /**
212
-     * @param User  $user
213
-     * @param array $activeRoles
214
-     * @param array $inactiveRoles
215
-     */
216
-    public function getCachedActiveRoles(User $user, &$activeRoles, &$inactiveRoles)
217
-    {
218
-        if (!array_key_exists($user->getId(), $this->cache)) {
219
-            $this->getActiveRoles($user, $retrievedActiveRoles, $retrievedInactiveRoles);
220
-            $this->cache[$user->getId()] = ['active' => $retrievedActiveRoles, 'inactive' => $retrievedInactiveRoles];
221
-        }
222
-
223
-        $activeRoles = $this->cache[$user->getId()]['active'];
224
-        $inactiveRoles = $this->cache[$user->getId()]['inactive'];
225
-    }
226
-
227
-    public function getRoleConfiguration()
228
-    {
229
-        return $this->roleConfiguration;
230
-    }
17
+	const ALLOWED = 1;
18
+	const ERROR_NOT_IDENTIFIED = 2;
19
+	const ERROR_DENIED = 3;
20
+	/** @var IdentificationVerifier */
21
+	private $identificationVerifier;
22
+	/**
23
+	 * @var RoleConfiguration
24
+	 */
25
+	private $roleConfiguration;
26
+
27
+	private $cache = [];
28
+
29
+	/**
30
+	 * SecurityManager constructor.
31
+	 *
32
+	 * @param IdentificationVerifier $identificationVerifier
33
+	 * @param RoleConfiguration      $roleConfiguration
34
+	 */
35
+	public function __construct(
36
+		IdentificationVerifier $identificationVerifier,
37
+		RoleConfiguration $roleConfiguration
38
+	) {
39
+		$this->identificationVerifier = $identificationVerifier;
40
+		$this->roleConfiguration = $roleConfiguration;
41
+	}
42
+
43
+	/**
44
+	 * Tests if a user is allowed to perform an action.
45
+	 *
46
+	 * This method should form a hard, deterministic security barrier, and only return true if it is absolutely sure
47
+	 * that a user should have access to something.
48
+	 *
49
+	 * @param string $page
50
+	 * @param string $route
51
+	 * @param User   $user
52
+	 *
53
+	 * @return int
54
+	 *
55
+	 * @category Security-Critical
56
+	 */
57
+	public function allows($page, $route, User $user)
58
+	{
59
+		$this->getCachedActiveRoles($user, $activeRoles, $inactiveRoles);
60
+
61
+		$availableRights = $this->flattenRoles($activeRoles);
62
+		$testResult = $this->findResult($availableRights, $page, $route);
63
+
64
+		if ($testResult !== null) {
65
+			// We got a firm result here, so just return it.
66
+			return $testResult;
67
+		}
68
+
69
+		// No firm result yet, so continue testing the inactive roles so we can give a better error.
70
+		$inactiveRights = $this->flattenRoles($inactiveRoles);
71
+		$testResult = $this->findResult($inactiveRights, $page, $route);
72
+
73
+		if ($testResult === self::ALLOWED) {
74
+			// The user is allowed to access this, but their role is inactive.
75
+			return self::ERROR_NOT_IDENTIFIED;
76
+		}
77
+
78
+		// Other options from the secondary test are denied and inconclusive, which at this point defaults to denied.
79
+		return self::ERROR_DENIED;
80
+	}
81
+
82
+	/**
83
+	 * @param array  $pseudoRole The role (flattened) to check
84
+	 * @param string $page       The page class to check
85
+	 * @param string $route      The page route to check
86
+	 *
87
+	 * @return int|null
88
+	 */
89
+	private function findResult($pseudoRole, $page, $route)
90
+	{
91
+		if (isset($pseudoRole[$page])) {
92
+			// check for deny on catch-all route
93
+			if (isset($pseudoRole[$page][RoleConfiguration::ALL])) {
94
+				if ($pseudoRole[$page][RoleConfiguration::ALL] === RoleConfiguration::ACCESS_DENY) {
95
+					return self::ERROR_DENIED;
96
+				}
97
+			}
98
+
99
+			// check normal route
100
+			if (isset($pseudoRole[$page][$route])) {
101
+				if ($pseudoRole[$page][$route] === RoleConfiguration::ACCESS_DENY) {
102
+					return self::ERROR_DENIED;
103
+				}
104
+
105
+				if ($pseudoRole[$page][$route] === RoleConfiguration::ACCESS_ALLOW) {
106
+					return self::ALLOWED;
107
+				}
108
+			}
109
+
110
+			// check for allowed on catch-all route
111
+			if (isset($pseudoRole[$page][RoleConfiguration::ALL])) {
112
+				if ($pseudoRole[$page][RoleConfiguration::ALL] === RoleConfiguration::ACCESS_ALLOW) {
113
+					return self::ALLOWED;
114
+				}
115
+			}
116
+		}
117
+
118
+		// return indeterminate result
119
+		return null;
120
+	}
121
+
122
+	/**
123
+	 * Takes an array of roles and flattens the values to a single set.
124
+	 *
125
+	 * @param array $activeRoles
126
+	 *
127
+	 * @return array
128
+	 */
129
+	private function flattenRoles($activeRoles)
130
+	{
131
+		$result = array();
132
+
133
+		$roleConfig = $this->roleConfiguration->getApplicableRoles($activeRoles);
134
+
135
+		// Iterate over every page in every role
136
+		foreach ($roleConfig as $role) {
137
+			foreach ($role as $page => $pageRights) {
138
+				// Create holder in result for this page
139
+				if (!isset($result[$page])) {
140
+					$result[$page] = array();
141
+				}
142
+
143
+				foreach ($pageRights as $action => $permission) {
144
+					// Deny takes precedence, so if it's set, don't change it.
145
+					if (isset($result[$page][$action])) {
146
+						if ($result[$page][$action] === RoleConfiguration::ACCESS_DENY) {
147
+							continue;
148
+						}
149
+					}
150
+
151
+					if ($permission === RoleConfiguration::ACCESS_DEFAULT) {
152
+						// Configured to do precisely nothing.
153
+						continue;
154
+					}
155
+
156
+					$result[$page][$action] = $permission;
157
+				}
158
+			}
159
+		}
160
+
161
+		return $result;
162
+	}
163
+
164
+	/**
165
+	 * @param User  $user
166
+	 * @param array $activeRoles
167
+	 * @param array $inactiveRoles
168
+	 */
169
+	public function getActiveRoles(User $user, &$activeRoles, &$inactiveRoles)
170
+	{
171
+		// Default to the community user here, because the main user is logged out
172
+		$identified = false;
173
+		$userRoles = array('public');
174
+
175
+		// if we're not the community user, get our real rights.
176
+		if (!$user->isCommunityUser()) {
177
+			// Check the user's status - only active users are allowed the effects of roles
178
+
179
+			$userRoles[] = 'loggedIn';
180
+
181
+			if ($user->isActive()) {
182
+				$ur = UserRole::getForUser($user->getId(), $user->getDatabase());
183
+
184
+				// NOTE: public is still in this array.
185
+				foreach ($ur as $r) {
186
+					$userRoles[] = $r->getRole();
187
+				}
188
+
189
+				$identified = $user->isIdentified($this->identificationVerifier);
190
+			}
191
+		}
192
+
193
+		$activeRoles = array();
194
+		$inactiveRoles = array();
195
+
196
+		foreach ($userRoles as $v) {
197
+			if ($this->roleConfiguration->roleNeedsIdentification($v)) {
198
+				if ($identified) {
199
+					$activeRoles[] = $v;
200
+				}
201
+				else {
202
+					$inactiveRoles[] = $v;
203
+				}
204
+			}
205
+			else {
206
+				$activeRoles[] = $v;
207
+			}
208
+		}
209
+	}
210
+
211
+	/**
212
+	 * @param User  $user
213
+	 * @param array $activeRoles
214
+	 * @param array $inactiveRoles
215
+	 */
216
+	public function getCachedActiveRoles(User $user, &$activeRoles, &$inactiveRoles)
217
+	{
218
+		if (!array_key_exists($user->getId(), $this->cache)) {
219
+			$this->getActiveRoles($user, $retrievedActiveRoles, $retrievedInactiveRoles);
220
+			$this->cache[$user->getId()] = ['active' => $retrievedActiveRoles, 'inactive' => $retrievedInactiveRoles];
221
+		}
222
+
223
+		$activeRoles = $this->cache[$user->getId()]['active'];
224
+		$inactiveRoles = $this->cache[$user->getId()]['inactive'];
225
+	}
226
+
227
+	public function getRoleConfiguration()
228
+	{
229
+		return $this->roleConfiguration;
230
+	}
231 231
 }
Please login to merge, or discard this patch.
includes/Security/DomainAccessManager.php 1 patch
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -16,61 +16,61 @@
 block discarded – undo
16 16
 
17 17
 class DomainAccessManager
18 18
 {
19
-    /**
20
-     * @var SecurityManager
21
-     */
22
-    private $securityManager;
19
+	/**
20
+	 * @var SecurityManager
21
+	 */
22
+	private $securityManager;
23 23
 
24
-    public function __construct(SecurityManager $securityManager)
25
-    {
26
-        $this->securityManager = $securityManager;
27
-    }
24
+	public function __construct(SecurityManager $securityManager)
25
+	{
26
+		$this->securityManager = $securityManager;
27
+	}
28 28
 
29
-    /**
30
-     * @param User $user
31
-     *
32
-     * @return Domain[]
33
-     */
34
-    public function getAllowedDomains(User $user): array
35
-    {
36
-        if ($user->isCommunityUser()) {
37
-            return [];
38
-        }
29
+	/**
30
+	 * @param User $user
31
+	 *
32
+	 * @return Domain[]
33
+	 */
34
+	public function getAllowedDomains(User $user): array
35
+	{
36
+		if ($user->isCommunityUser()) {
37
+			return [];
38
+		}
39 39
 
40
-        return Domain::getDomainByUser($user->getDatabase(), $user, true);
41
-    }
40
+		return Domain::getDomainByUser($user->getDatabase(), $user, true);
41
+	}
42 42
 
43
-    public function switchDomain(User $user, Domain $newDomain): void
44
-    {
45
-        $mapToId = function(DataObject $object) {
46
-            return $object->getId();
47
-        };
43
+	public function switchDomain(User $user, Domain $newDomain): void
44
+	{
45
+		$mapToId = function(DataObject $object) {
46
+			return $object->getId();
47
+		};
48 48
 
49
-        $allowed = in_array($newDomain->getId(), array_map($mapToId, self::getAllowedDomains($user)));
49
+		$allowed = in_array($newDomain->getId(), array_map($mapToId, self::getAllowedDomains($user)));
50 50
 
51
-        if ($allowed) {
52
-            WebRequest::setActiveDomain($newDomain);
53
-        }
54
-        else {
55
-            throw new AccessDeniedException($this->securityManager, $this);
56
-        }
57
-    }
51
+		if ($allowed) {
52
+			WebRequest::setActiveDomain($newDomain);
53
+		}
54
+		else {
55
+			throw new AccessDeniedException($this->securityManager, $this);
56
+		}
57
+	}
58 58
 
59
-    /**
60
-     * Not a very smart way of doing this - just set the user's current domain to the first one in the list.
61
-     *
62
-     * We may wish to allow the user to configure a default domain, but I don't expect this to be needed by many people,
63
-     * so for now they can suffer until someone complains.
64
-     *
65
-     * @param User $user
66
-     *
67
-     * @return void
68
-     */
69
-    public function switchToDefaultDomain(User $user): void
70
-    {
71
-        $domains = $this->getAllowedDomains($user);
72
-        if (count($domains) > 0) {
73
-            WebRequest::setActiveDomain($domains[0]);
74
-        }
75
-    }
59
+	/**
60
+	 * Not a very smart way of doing this - just set the user's current domain to the first one in the list.
61
+	 *
62
+	 * We may wish to allow the user to configure a default domain, but I don't expect this to be needed by many people,
63
+	 * so for now they can suffer until someone complains.
64
+	 *
65
+	 * @param User $user
66
+	 *
67
+	 * @return void
68
+	 */
69
+	public function switchToDefaultDomain(User $user): void
70
+	{
71
+		$domains = $this->getAllowedDomains($user);
72
+		if (count($domains) > 0) {
73
+			WebRequest::setActiveDomain($domains[0]);
74
+		}
75
+	}
76 76
 }
77 77
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/ContentSecurityPolicyManager.php 1 patch
Indentation   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -12,101 +12,101 @@
 block discarded – undo
12 12
 
13 13
 class ContentSecurityPolicyManager
14 14
 {
15
-    private $policy = [
16
-        'default-src'     => [],
17
-        'script-src'      => ['self', 'nonce'],
18
-        'script-src-elem' => ['self', 'nonce'],
19
-        'script-src-attr' => [],
20
-        'connect-src'     => ['self'],
21
-        'style-src'       => ['self'],
22
-        'style-src-elem'  => ['self'],
23
-        'style-src-attr'  => [],
24
-        'img-src'         => ['self', 'data:', 'https://upload.wikimedia.org', 'https://accounts-dev.wmflabs.org/'],
25
-        'font-src'        => ['self'],
26
-        'form-action'     => ['self', 'oauth'],
27
-        'frame-ancestors' => ['self'],
28
-        'frame-src'       => ['self'],
29
-    ];
30
-    private $nonce = null;
31
-    private $reportOnly = false;
32
-    /**
33
-     * @var SiteConfiguration
34
-     */
35
-    private $configuration;
15
+	private $policy = [
16
+		'default-src'     => [],
17
+		'script-src'      => ['self', 'nonce'],
18
+		'script-src-elem' => ['self', 'nonce'],
19
+		'script-src-attr' => [],
20
+		'connect-src'     => ['self'],
21
+		'style-src'       => ['self'],
22
+		'style-src-elem'  => ['self'],
23
+		'style-src-attr'  => [],
24
+		'img-src'         => ['self', 'data:', 'https://upload.wikimedia.org', 'https://accounts-dev.wmflabs.org/'],
25
+		'font-src'        => ['self'],
26
+		'form-action'     => ['self', 'oauth'],
27
+		'frame-ancestors' => ['self'],
28
+		'frame-src'       => ['self'],
29
+	];
30
+	private $nonce = null;
31
+	private $reportOnly = false;
32
+	/**
33
+	 * @var SiteConfiguration
34
+	 */
35
+	private $configuration;
36 36
 
37
-    /**
38
-     * ContentSecurityPolicyManager constructor.
39
-     *
40
-     * @param SiteConfiguration $configuration
41
-     */
42
-    public function __construct(SiteConfiguration $configuration)
43
-    {
44
-        $this->configuration = $configuration;
45
-    }
37
+	/**
38
+	 * ContentSecurityPolicyManager constructor.
39
+	 *
40
+	 * @param SiteConfiguration $configuration
41
+	 */
42
+	public function __construct(SiteConfiguration $configuration)
43
+	{
44
+		$this->configuration = $configuration;
45
+	}
46 46
 
47
-    public function getNonce()
48
-    {
49
-        if ($this->nonce === null) {
50
-            $this->nonce = base64_encode(openssl_random_pseudo_bytes(32));
51
-        }
47
+	public function getNonce()
48
+	{
49
+		if ($this->nonce === null) {
50
+			$this->nonce = base64_encode(openssl_random_pseudo_bytes(32));
51
+		}
52 52
 
53
-        return $this->nonce;
54
-    }
53
+		return $this->nonce;
54
+	}
55 55
 
56
-    public function getHeader(): string
57
-    {
58
-        $reportOnly = '';
59
-        if ($this->reportOnly) {
60
-            $reportOnly = '-Report-Only';
61
-        }
56
+	public function getHeader(): string
57
+	{
58
+		$reportOnly = '';
59
+		if ($this->reportOnly) {
60
+			$reportOnly = '-Report-Only';
61
+		}
62 62
 
63
-        $constructedPolicy = "Content-Security-Policy{$reportOnly}: ";
63
+		$constructedPolicy = "Content-Security-Policy{$reportOnly}: ";
64 64
 
65
-        foreach ($this->policy as $item => $values) {
66
-            $constructedPolicy .= $item . ' ';
67
-            $policyIsSet = false;
65
+		foreach ($this->policy as $item => $values) {
66
+			$constructedPolicy .= $item . ' ';
67
+			$policyIsSet = false;
68 68
 
69
-            if (count($values) > 0) {
70
-                foreach ($values as $value) {
71
-                    switch ($value) {
72
-                        case 'none':
73
-                        case 'self':
74
-                        case 'strict-dynamic':
75
-                            $policyIsSet = true;
76
-                            $constructedPolicy .= "'{$value}' ";
77
-                            break;
78
-                        case 'nonce':
79
-                            if ($this->nonce !== null) {
80
-                                $policyIsSet = true;
81
-                                $constructedPolicy .= "'nonce-{$this->nonce}' ";
82
-                            }
83
-                            break;
84
-                        case 'oauth':
85
-                            $policyIsSet = true;
86
-                            $constructedPolicy .= "{$this->configuration->getOauthMediaWikiCanonicalServer()} ";
87
-                            break;
88
-                        default:
89
-                            $policyIsSet = true;
90
-                            $constructedPolicy .= $value . ' ';
91
-                            break;
92
-                    }
93
-                }
69
+			if (count($values) > 0) {
70
+				foreach ($values as $value) {
71
+					switch ($value) {
72
+						case 'none':
73
+						case 'self':
74
+						case 'strict-dynamic':
75
+							$policyIsSet = true;
76
+							$constructedPolicy .= "'{$value}' ";
77
+							break;
78
+						case 'nonce':
79
+							if ($this->nonce !== null) {
80
+								$policyIsSet = true;
81
+								$constructedPolicy .= "'nonce-{$this->nonce}' ";
82
+							}
83
+							break;
84
+						case 'oauth':
85
+							$policyIsSet = true;
86
+							$constructedPolicy .= "{$this->configuration->getOauthMediaWikiCanonicalServer()} ";
87
+							break;
88
+						default:
89
+							$policyIsSet = true;
90
+							$constructedPolicy .= $value . ' ';
91
+							break;
92
+					}
93
+				}
94 94
 
95
-                if (!$policyIsSet) {
96
-                    $constructedPolicy .= "'none' ";
97
-                }
98
-            }
99
-            else {
100
-                $constructedPolicy .= "'none' ";
101
-            }
95
+				if (!$policyIsSet) {
96
+					$constructedPolicy .= "'none' ";
97
+				}
98
+			}
99
+			else {
100
+				$constructedPolicy .= "'none' ";
101
+			}
102 102
 
103
-            $constructedPolicy .= '; ';
104
-        }
103
+			$constructedPolicy .= '; ';
104
+		}
105 105
 
106
-        if ($this->configuration->getCspReportUri() !== null) {
107
-            $constructedPolicy .= 'report-uri ' . $this->configuration->getCspReportUri();
108
-        }
106
+		if ($this->configuration->getCspReportUri() !== null) {
107
+			$constructedPolicy .= 'report-uri ' . $this->configuration->getCspReportUri();
108
+		}
109 109
 
110
-        return $constructedPolicy;
111
-    }
110
+		return $constructedPolicy;
111
+	}
112 112
 }
Please login to merge, or discard this patch.
includes/PdoDatabase.php 1 patch
Indentation   +130 added lines, -130 removed lines patch added patch discarded remove patch
@@ -15,134 +15,134 @@
 block discarded – undo
15 15
 
16 16
 class PdoDatabase extends PDO
17 17
 {
18
-    public const ISOLATION_SERIALIZABLE = 'SERIALIZABLE';
19
-    public const ISOLATION_READ_COMMITTED = 'READ COMMITTED';
20
-    public const ISOLATION_READ_ONLY = 'READ ONLY';
21
-
22
-    /**
23
-     * @var PdoDatabase[]
24
-     */
25
-    private static $connections = array();
26
-    /**
27
-     * @var bool True if a transaction is active
28
-     */
29
-    protected $hasActiveTransaction = false;
30
-
31
-    /**
32
-     * Unless you're doing low-level work, this is not the function you want.
33
-     *
34
-     * @param string $connectionName
35
-     *
36
-     * @return PdoDatabase
37
-     * @throws Exception
38
-     */
39
-    public static function getDatabaseConnection($connectionName)
40
-    {
41
-        if (!isset(self::$connections[$connectionName])) {
42
-            global $cDatabaseConfig;
43
-
44
-            if (!array_key_exists($connectionName, $cDatabaseConfig)) {
45
-                throw new Exception("Database configuration not found for alias $connectionName");
46
-            }
47
-
48
-            try {
49
-                $databaseObject = new PdoDatabase(
50
-                    $cDatabaseConfig[$connectionName]["dsrcname"],
51
-                    $cDatabaseConfig[$connectionName]["username"],
52
-                    $cDatabaseConfig[$connectionName]["password"],
53
-                    $cDatabaseConfig[$connectionName]["options"]
54
-                );
55
-            }
56
-            catch (PDOException $ex) {
57
-                // wrap around any potential stack traces which may include passwords
58
-                throw new EnvironmentException("Error connecting to database '$connectionName': " . $ex->getMessage());
59
-            }
60
-
61
-            $databaseObject->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
62
-
63
-            // emulating prepared statements gives a performance boost on MySQL.
64
-            //
65
-            // however, our version of PDO doesn't seem to understand parameter types when emulating
66
-            // the prepared statements, so we're forced to turn this off for now.
67
-            // -- stw 2014-02-11
68
-            $databaseObject->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
69
-
70
-            // Set the default transaction mode
71
-            $databaseObject->exec("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;");
72
-
73
-            self::$connections[$connectionName] = $databaseObject;
74
-        }
75
-
76
-        return self::$connections[$connectionName];
77
-    }
78
-
79
-    /**
80
-     * Determines if this connection has a transaction in progress or not
81
-     * @return boolean true if there is a transaction in progress.
82
-     */
83
-    public function hasActiveTransaction()
84
-    {
85
-        return $this->hasActiveTransaction;
86
-    }
87
-
88
-    /**
89
-     * Summary of beginTransaction
90
-     * @return bool
91
-     */
92
-    public function beginTransaction(string $isolationLevel = self::ISOLATION_READ_COMMITTED)
93
-    {
94
-        // Override the pre-existing method, which doesn't stop you from
95
-        // starting transactions within transactions - which doesn't work and
96
-        // will throw an exception. This eliminates the need to catch exceptions
97
-        // all over the rest of the code
98
-        if ($this->hasActiveTransaction) {
99
-            return false;
100
-        }
101
-        else {
102
-            $accessMode = 'READ WRITE';
103
-
104
-            switch ($isolationLevel) {
105
-                case self::ISOLATION_SERIALIZABLE:
106
-                case self::ISOLATION_READ_COMMITTED:
107
-                    break;
108
-                case self::ISOLATION_READ_ONLY:
109
-                    $isolationLevel = self::ISOLATION_READ_COMMITTED;
110
-                    $accessMode = 'READ ONLY';
111
-                    break;
112
-                default:
113
-                    throw new Exception("Invalid transaction isolation level");
114
-            }
115
-
116
-            // set the transaction isolation level for every transaction.
117
-            // string substitution is safe here; values can only be one of the above constants
118
-            parent::exec("SET TRANSACTION ISOLATION LEVEL ${isolationLevel}, ${accessMode};");
119
-
120
-            // start a new transaction, and return whether the start was successful
121
-            $this->hasActiveTransaction = parent::beginTransaction();
122
-
123
-            return $this->hasActiveTransaction;
124
-        }
125
-    }
126
-
127
-    /**
128
-     * Commits the active transaction
129
-     */
130
-    public function commit()
131
-    {
132
-        if ($this->hasActiveTransaction) {
133
-            parent::commit();
134
-            $this->hasActiveTransaction = false;
135
-        }
136
-    }
137
-
138
-    /**
139
-     * Rolls back a transaction
140
-     */
141
-    public function rollBack()
142
-    {
143
-        if ($this->hasActiveTransaction) {
144
-            parent::rollback();
145
-            $this->hasActiveTransaction = false;
146
-        }
147
-    }
18
+	public const ISOLATION_SERIALIZABLE = 'SERIALIZABLE';
19
+	public const ISOLATION_READ_COMMITTED = 'READ COMMITTED';
20
+	public const ISOLATION_READ_ONLY = 'READ ONLY';
21
+
22
+	/**
23
+	 * @var PdoDatabase[]
24
+	 */
25
+	private static $connections = array();
26
+	/**
27
+	 * @var bool True if a transaction is active
28
+	 */
29
+	protected $hasActiveTransaction = false;
30
+
31
+	/**
32
+	 * Unless you're doing low-level work, this is not the function you want.
33
+	 *
34
+	 * @param string $connectionName
35
+	 *
36
+	 * @return PdoDatabase
37
+	 * @throws Exception
38
+	 */
39
+	public static function getDatabaseConnection($connectionName)
40
+	{
41
+		if (!isset(self::$connections[$connectionName])) {
42
+			global $cDatabaseConfig;
43
+
44
+			if (!array_key_exists($connectionName, $cDatabaseConfig)) {
45
+				throw new Exception("Database configuration not found for alias $connectionName");
46
+			}
47
+
48
+			try {
49
+				$databaseObject = new PdoDatabase(
50
+					$cDatabaseConfig[$connectionName]["dsrcname"],
51
+					$cDatabaseConfig[$connectionName]["username"],
52
+					$cDatabaseConfig[$connectionName]["password"],
53
+					$cDatabaseConfig[$connectionName]["options"]
54
+				);
55
+			}
56
+			catch (PDOException $ex) {
57
+				// wrap around any potential stack traces which may include passwords
58
+				throw new EnvironmentException("Error connecting to database '$connectionName': " . $ex->getMessage());
59
+			}
60
+
61
+			$databaseObject->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
62
+
63
+			// emulating prepared statements gives a performance boost on MySQL.
64
+			//
65
+			// however, our version of PDO doesn't seem to understand parameter types when emulating
66
+			// the prepared statements, so we're forced to turn this off for now.
67
+			// -- stw 2014-02-11
68
+			$databaseObject->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
69
+
70
+			// Set the default transaction mode
71
+			$databaseObject->exec("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;");
72
+
73
+			self::$connections[$connectionName] = $databaseObject;
74
+		}
75
+
76
+		return self::$connections[$connectionName];
77
+	}
78
+
79
+	/**
80
+	 * Determines if this connection has a transaction in progress or not
81
+	 * @return boolean true if there is a transaction in progress.
82
+	 */
83
+	public function hasActiveTransaction()
84
+	{
85
+		return $this->hasActiveTransaction;
86
+	}
87
+
88
+	/**
89
+	 * Summary of beginTransaction
90
+	 * @return bool
91
+	 */
92
+	public function beginTransaction(string $isolationLevel = self::ISOLATION_READ_COMMITTED)
93
+	{
94
+		// Override the pre-existing method, which doesn't stop you from
95
+		// starting transactions within transactions - which doesn't work and
96
+		// will throw an exception. This eliminates the need to catch exceptions
97
+		// all over the rest of the code
98
+		if ($this->hasActiveTransaction) {
99
+			return false;
100
+		}
101
+		else {
102
+			$accessMode = 'READ WRITE';
103
+
104
+			switch ($isolationLevel) {
105
+				case self::ISOLATION_SERIALIZABLE:
106
+				case self::ISOLATION_READ_COMMITTED:
107
+					break;
108
+				case self::ISOLATION_READ_ONLY:
109
+					$isolationLevel = self::ISOLATION_READ_COMMITTED;
110
+					$accessMode = 'READ ONLY';
111
+					break;
112
+				default:
113
+					throw new Exception("Invalid transaction isolation level");
114
+			}
115
+
116
+			// set the transaction isolation level for every transaction.
117
+			// string substitution is safe here; values can only be one of the above constants
118
+			parent::exec("SET TRANSACTION ISOLATION LEVEL ${isolationLevel}, ${accessMode};");
119
+
120
+			// start a new transaction, and return whether the start was successful
121
+			$this->hasActiveTransaction = parent::beginTransaction();
122
+
123
+			return $this->hasActiveTransaction;
124
+		}
125
+	}
126
+
127
+	/**
128
+	 * Commits the active transaction
129
+	 */
130
+	public function commit()
131
+	{
132
+		if ($this->hasActiveTransaction) {
133
+			parent::commit();
134
+			$this->hasActiveTransaction = false;
135
+		}
136
+	}
137
+
138
+	/**
139
+	 * Rolls back a transaction
140
+	 */
141
+	public function rollBack()
142
+	{
143
+		if ($this->hasActiveTransaction) {
144
+			parent::rollback();
145
+			$this->hasActiveTransaction = false;
146
+		}
147
+	}
148 148
 }
Please login to merge, or discard this patch.
includes/Offline.php 1 patch
Indentation   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -17,60 +17,60 @@
 block discarded – undo
17 17
  */
18 18
 class Offline
19 19
 {
20
-    /**
21
-     * Determines if the tool is offline
22
-     * @return bool
23
-     */
24
-    public static function isOffline()
25
-    {
26
-        global $dontUseDb;
20
+	/**
21
+	 * Determines if the tool is offline
22
+	 * @return bool
23
+	 */
24
+	public static function isOffline()
25
+	{
26
+		global $dontUseDb;
27 27
 
28
-        return (bool)$dontUseDb;
29
-    }
28
+		return (bool)$dontUseDb;
29
+	}
30 30
 
31
-    /**
32
-     * Gets the offline message
33
-     *
34
-     * @param bool        $external
35
-     * @param null|string $message
36
-     *
37
-     * @return string
38
-     * @throws SmartyException
39
-     */
40
-    public static function getOfflineMessage($external, $message = null)
41
-    {
42
-        global $dontUseDbCulprit, $dontUseDbReason, $baseurl;
31
+	/**
32
+	 * Gets the offline message
33
+	 *
34
+	 * @param bool        $external
35
+	 * @param null|string $message
36
+	 *
37
+	 * @return string
38
+	 * @throws SmartyException
39
+	 */
40
+	public static function getOfflineMessage($external, $message = null)
41
+	{
42
+		global $dontUseDbCulprit, $dontUseDbReason, $baseurl;
43 43
 
44
-        $smarty = new Smarty();
45
-        $smarty->assign("baseurl", $baseurl);
46
-        $smarty->assign("resourceCacheEpoch", 0);
47
-        $smarty->assign("alerts", []);
48
-        $smarty->assign("toolversion", Environment::getToolVersion());
44
+		$smarty = new Smarty();
45
+		$smarty->assign("baseurl", $baseurl);
46
+		$smarty->assign("resourceCacheEpoch", 0);
47
+		$smarty->assign("alerts", []);
48
+		$smarty->assign("toolversion", Environment::getToolVersion());
49 49
 
50
-        if (!headers_sent()) {
51
-            header("HTTP/1.1 503 Service Unavailable");
52
-        }
50
+		if (!headers_sent()) {
51
+			header("HTTP/1.1 503 Service Unavailable");
52
+		}
53 53
 
54
-        if ($external) {
55
-            return $smarty->fetch("offline/external.tpl");
56
-        }
57
-        else {
58
-            $hideCulprit = true;
54
+		if ($external) {
55
+			return $smarty->fetch("offline/external.tpl");
56
+		}
57
+		else {
58
+			$hideCulprit = true;
59 59
 
60
-            // Use the provided message if possible
61
-            if ($message === null) {
62
-                $hideCulprit = false;
63
-                $message = $dontUseDbReason;
64
-            }
60
+			// Use the provided message if possible
61
+			if ($message === null) {
62
+				$hideCulprit = false;
63
+				$message = $dontUseDbReason;
64
+			}
65 65
 
66
-            $smarty->assign("hideCulprit", $hideCulprit);
67
-            $smarty->assign("dontUseDbCulprit", $dontUseDbCulprit);
68
-            $smarty->assign("dontUseDbReason", $message);
69
-            $smarty->assign("alerts", array());
70
-            $smarty->assign('currentUser', User::getCommunity());
71
-            $smarty->assign('currentDomain', null);
66
+			$smarty->assign("hideCulprit", $hideCulprit);
67
+			$smarty->assign("dontUseDbCulprit", $dontUseDbCulprit);
68
+			$smarty->assign("dontUseDbReason", $message);
69
+			$smarty->assign("alerts", array());
70
+			$smarty->assign('currentUser', User::getCommunity());
71
+			$smarty->assign('currentDomain', null);
72 72
 
73
-            return $smarty->fetch("offline/internal.tpl");
74
-        }
75
-    }
73
+			return $smarty->fetch("offline/internal.tpl");
74
+		}
75
+	}
76 76
 }
Please login to merge, or discard this patch.