Failed Conditions
Pull Request — newinternal (#527)
by Simon
17:20 queued 07:22
created
includes/AuthUtility.php 1 patch
Indentation   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -10,99 +10,99 @@
 block discarded – undo
10 10
 
11 11
 class AuthUtility
12 12
 {
13
-    /**
14
-     * Test the specified data against the specified credentials
15
-     *
16
-     * @param string $password
17
-     * @param string $credentials
18
-     *
19
-     * @return bool
20
-     * @deprecated
21
-     */
22
-    public static function testCredentials($password, $credentials)
23
-    {
24
-        global $minimumPasswordVersion;
13
+	/**
14
+	 * Test the specified data against the specified credentials
15
+	 *
16
+	 * @param string $password
17
+	 * @param string $credentials
18
+	 *
19
+	 * @return bool
20
+	 * @deprecated
21
+	 */
22
+	public static function testCredentials($password, $credentials)
23
+	{
24
+		global $minimumPasswordVersion;
25 25
 
26
-        if (substr($credentials, 0, 1) != ":") {
27
-            return false;
28
-        }
26
+		if (substr($credentials, 0, 1) != ":") {
27
+			return false;
28
+		}
29 29
 
30
-        // determine password version
31
-        $data = explode(':', substr($credentials, 1));
30
+		// determine password version
31
+		$data = explode(':', substr($credentials, 1));
32 32
 
33
-        // call the encryptVersion function for the version that this password actually is.
34
-        // syntax: :1:SALT:HASH
35
-        // syntax: :2:x:HASH
33
+		// call the encryptVersion function for the version that this password actually is.
34
+		// syntax: :1:SALT:HASH
35
+		// syntax: :2:x:HASH
36 36
 
37
-        // check the version is one of the allowed ones:
38
-        if ($minimumPasswordVersion > $data[0]) {
39
-            return false;
40
-        }
37
+		// check the version is one of the allowed ones:
38
+		if ($minimumPasswordVersion > $data[0]) {
39
+			return false;
40
+		}
41 41
 
42
-        if ($data[0] == 1) {
43
-            return $credentials == self::encryptVersion1($password, $data[1]);
44
-        }
42
+		if ($data[0] == 1) {
43
+			return $credentials == self::encryptVersion1($password, $data[1]);
44
+		}
45 45
 
46
-        if ($data[0] == 2) {
47
-            return self::verifyVersion2($password, $data[2]);
48
-        }
46
+		if ($data[0] == 2) {
47
+			return self::verifyVersion2($password, $data[2]);
48
+		}
49 49
 
50
-        return false;
51
-    }
50
+		return false;
51
+	}
52 52
 
53
-    /**
54
-     * @param string $credentials
55
-     *
56
-     * @return bool
57
-     * @deprecated
58
-     */
59
-    public static function isCredentialVersionLatest($credentials)
60
-    {
61
-        return substr($credentials, 0, 3) === ":2:";
62
-    }
53
+	/**
54
+	 * @param string $credentials
55
+	 *
56
+	 * @return bool
57
+	 * @deprecated
58
+	 */
59
+	public static function isCredentialVersionLatest($credentials)
60
+	{
61
+		return substr($credentials, 0, 3) === ":2:";
62
+	}
63 63
 
64
-    /**
65
-     * Encrypts a user's password with the latest version of the hash algorithm
66
-     *
67
-     * @param string $password
68
-     *
69
-     * @return string
70
-     * @deprecated
71
-     */
72
-    public static function encryptPassword($password)
73
-    {
74
-        return self::encryptVersion2($password);
75
-    }
64
+	/**
65
+	 * Encrypts a user's password with the latest version of the hash algorithm
66
+	 *
67
+	 * @param string $password
68
+	 *
69
+	 * @return string
70
+	 * @deprecated
71
+	 */
72
+	public static function encryptPassword($password)
73
+	{
74
+		return self::encryptVersion2($password);
75
+	}
76 76
 
77
-    /**
78
-     * @param string $password
79
-     * @param string $salt
80
-     *
81
-     * @return string
82
-     */
83
-    private static function encryptVersion1($password, $salt)
84
-    {
85
-        return ':1:' . $salt . ':' . md5($salt . '-' . md5($password));
86
-    }
77
+	/**
78
+	 * @param string $password
79
+	 * @param string $salt
80
+	 *
81
+	 * @return string
82
+	 */
83
+	private static function encryptVersion1($password, $salt)
84
+	{
85
+		return ':1:' . $salt . ':' . md5($salt . '-' . md5($password));
86
+	}
87 87
 
88
-    /**
89
-     * @param string $password
90
-     *
91
-     * @return string
92
-     */
93
-    private static function encryptVersion2($password)
94
-    {
95
-        return ':2:x:' . password_hash($password, PASSWORD_BCRYPT);
96
-    }
88
+	/**
89
+	 * @param string $password
90
+	 *
91
+	 * @return string
92
+	 */
93
+	private static function encryptVersion2($password)
94
+	{
95
+		return ':2:x:' . password_hash($password, PASSWORD_BCRYPT);
96
+	}
97 97
 
98
-    /**
99
-     * @param string $password
100
-     * @param string $hash
101
-     *
102
-     * @return bool
103
-     */
104
-    private static function verifyVersion2($password, $hash)
105
-    {
106
-        return password_verify($password, $hash);
107
-    }
98
+	/**
99
+	 * @param string $password
100
+	 * @param string $hash
101
+	 *
102
+	 * @return bool
103
+	 */
104
+	private static function verifyVersion2($password, $hash)
105
+	{
106
+		return password_verify($password, $hash);
107
+	}
108 108
 }
Please login to merge, or discard this patch.
includes/Security/AuthenticationManager.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -19,62 +19,62 @@
 block discarded – undo
19 19
 
20 20
 class AuthenticationManager
21 21
 {
22
-    const AUTH_OK = 1;
23
-    const AUTH_FAIL = 2;
24
-    const AUTH_REQUIRE_NEXT_STAGE = 3;
25
-    private $typeMap = array();
26
-    /**
27
-     * @var PdoDatabase
28
-     */
29
-    private $database;
22
+	const AUTH_OK = 1;
23
+	const AUTH_FAIL = 2;
24
+	const AUTH_REQUIRE_NEXT_STAGE = 3;
25
+	private $typeMap = array();
26
+	/**
27
+	 * @var PdoDatabase
28
+	 */
29
+	private $database;
30 30
 
31
-    /**
32
-     * AuthenticationManager constructor.
33
-     *
34
-     * @param PdoDatabase       $database
35
-     * @param SiteConfiguration $siteConfiguration
36
-     * @param HttpHelper        $httpHelper
37
-     */
38
-    public function __construct(PdoDatabase $database, SiteConfiguration $siteConfiguration, HttpHelper $httpHelper)
39
-    {
40
-        // setup providers
41
-        $this->typeMap['password'] = new PasswordCredentialProvider($database, $siteConfiguration);
42
-        $this->database = $database;
43
-    }
31
+	/**
32
+	 * AuthenticationManager constructor.
33
+	 *
34
+	 * @param PdoDatabase       $database
35
+	 * @param SiteConfiguration $siteConfiguration
36
+	 * @param HttpHelper        $httpHelper
37
+	 */
38
+	public function __construct(PdoDatabase $database, SiteConfiguration $siteConfiguration, HttpHelper $httpHelper)
39
+	{
40
+		// setup providers
41
+		$this->typeMap['password'] = new PasswordCredentialProvider($database, $siteConfiguration);
42
+		$this->database = $database;
43
+	}
44 44
 
45
-    public function authenticate(User $user, $data, $stage)
46
-    {
47
-        $sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage';
48
-        $statement = $this->database->prepare($sql);
49
-        $statement->execute(array(':user' => $user->getId(), ':stage' => $stage));
50
-        $options = $statement->fetchAll(PDO::FETCH_COLUMN);
45
+	public function authenticate(User $user, $data, $stage)
46
+	{
47
+		$sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage';
48
+		$statement = $this->database->prepare($sql);
49
+		$statement->execute(array(':user' => $user->getId(), ':stage' => $stage));
50
+		$options = $statement->fetchAll(PDO::FETCH_COLUMN);
51 51
 
52
-        $sql = 'SELECT count(DISTINCT factor) FROM credential WHERE user = :user AND factor > :stage';
53
-        $statement = $this->database->prepare($sql);
54
-        $statement->execute(array(':user' => $user->getId(), ':stage' => $stage));
55
-        $requiredFactors = $statement->fetchColumn();
52
+		$sql = 'SELECT count(DISTINCT factor) FROM credential WHERE user = :user AND factor > :stage';
53
+		$statement = $this->database->prepare($sql);
54
+		$statement->execute(array(':user' => $user->getId(), ':stage' => $stage));
55
+		$requiredFactors = $statement->fetchColumn();
56 56
 
57
-        // prep the correct OK response based on how many factors are ahead of this one
58
-        $success = self::AUTH_OK;
59
-        if ($requiredFactors > 0) {
60
-            $success = self::AUTH_REQUIRE_NEXT_STAGE;
61
-        }
57
+		// prep the correct OK response based on how many factors are ahead of this one
58
+		$success = self::AUTH_OK;
59
+		if ($requiredFactors > 0) {
60
+			$success = self::AUTH_REQUIRE_NEXT_STAGE;
61
+		}
62 62
 
63
-        foreach ($options as $type) {
64
-            if (!isset($this->typeMap[$type])) {
65
-                // does this type have a credentialProvider registered?
66
-                continue;
67
-            }
63
+		foreach ($options as $type) {
64
+			if (!isset($this->typeMap[$type])) {
65
+				// does this type have a credentialProvider registered?
66
+				continue;
67
+			}
68 68
 
69
-            /** @var ICredentialProvider $credentialProvider */
70
-            $credentialProvider = $this->typeMap[$type];
71
-            if ($credentialProvider->authenticate($user, $data)) {
72
-                return $success;
73
-            }
74
-        }
69
+			/** @var ICredentialProvider $credentialProvider */
70
+			$credentialProvider = $this->typeMap[$type];
71
+			if ($credentialProvider->authenticate($user, $data)) {
72
+				return $success;
73
+			}
74
+		}
75 75
 
76
-        // We've iterated over all the available providers for this stage.
77
-        // They all hate you.
78
-        return self::AUTH_FAIL;
79
-    }
76
+		// We've iterated over all the available providers for this stage.
77
+		// They all hate you.
78
+		return self::AUTH_FAIL;
79
+	}
80 80
 }
81 81
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/RoleConfiguration.php 1 patch
Indentation   +334 added lines, -334 removed lines patch added patch discarded remove patch
@@ -45,364 +45,364 @@
 block discarded – undo
45 45
 
46 46
 class RoleConfiguration
47 47
 {
48
-    const ACCESS_ALLOW = 1;
49
-    const ACCESS_DENY = -1;
50
-    const ACCESS_DEFAULT = 0;
51
-    const MAIN = 'main';
52
-    const ALL = '*';
53
-    /**
54
-     * A map of roles to rights
55
-     *
56
-     * For example:
57
-     *
58
-     * array(
59
-     *   'myrole' => array(
60
-     *       PageMyPage::class => array(
61
-     *           'edit' => self::ACCESS_ALLOW,
62
-     *           'create' => self::ACCESS_DENY,
63
-     *       )
64
-     *   )
65
-     * )
66
-     *
67
-     * Note that DENY takes precedence over everything else when roles are combined, followed by ALLOW, followed by
68
-     * DEFAULT. Thus, if you have the following ([A]llow, [D]eny, [-] (default)) grants in different roles, this should
69
-     * be the expected result:
70
-     *
71
-     * - (-,-,-) = - (default because nothing to explicitly say allowed or denied equates to a denial)
72
-     * - (A,-,-) = A
73
-     * - (D,-,-) = D
74
-     * - (A,D,-) = D (deny takes precedence over allow)
75
-     * - (A,A,A) = A (repetition has no effect)
76
-     *
77
-     * The public role is special, and is applied to all users automatically. Avoid using deny on this role.
78
-     *
79
-     * @var array
80
-     */
81
-    private $roleConfig = array(
82
-        'public'            => array(
83
-            /*
48
+	const ACCESS_ALLOW = 1;
49
+	const ACCESS_DENY = -1;
50
+	const ACCESS_DEFAULT = 0;
51
+	const MAIN = 'main';
52
+	const ALL = '*';
53
+	/**
54
+	 * A map of roles to rights
55
+	 *
56
+	 * For example:
57
+	 *
58
+	 * array(
59
+	 *   'myrole' => array(
60
+	 *       PageMyPage::class => array(
61
+	 *           'edit' => self::ACCESS_ALLOW,
62
+	 *           'create' => self::ACCESS_DENY,
63
+	 *       )
64
+	 *   )
65
+	 * )
66
+	 *
67
+	 * Note that DENY takes precedence over everything else when roles are combined, followed by ALLOW, followed by
68
+	 * DEFAULT. Thus, if you have the following ([A]llow, [D]eny, [-] (default)) grants in different roles, this should
69
+	 * be the expected result:
70
+	 *
71
+	 * - (-,-,-) = - (default because nothing to explicitly say allowed or denied equates to a denial)
72
+	 * - (A,-,-) = A
73
+	 * - (D,-,-) = D
74
+	 * - (A,D,-) = D (deny takes precedence over allow)
75
+	 * - (A,A,A) = A (repetition has no effect)
76
+	 *
77
+	 * The public role is special, and is applied to all users automatically. Avoid using deny on this role.
78
+	 *
79
+	 * @var array
80
+	 */
81
+	private $roleConfig = array(
82
+		'public'            => array(
83
+			/*
84 84
              * THIS ROLE IS GRANTED TO ALL LOGGED *OUT* USERS IMPLICITLY.
85 85
              *
86 86
              * USERS IN THIS ROLE DO NOT HAVE TO BE IDENTIFIED TO GET THE RIGHTS CONFERRED HERE.
87 87
              * DO NOT ADD ANY SECURITY-SENSITIVE RIGHTS HERE.
88 88
              */
89
-            '_childRoles'   => array(
90
-                'publicStats',
91
-            ),
92
-            PageTeam::class => array(
93
-                self::MAIN => self::ACCESS_ALLOW,
94
-            ),
95
-        ),
96
-        'loggedIn'          => array(
97
-            /*
89
+			'_childRoles'   => array(
90
+				'publicStats',
91
+			),
92
+			PageTeam::class => array(
93
+				self::MAIN => self::ACCESS_ALLOW,
94
+			),
95
+		),
96
+		'loggedIn'          => array(
97
+			/*
98 98
              * THIS ROLE IS GRANTED TO ALL LOGGED IN USERS IMPLICITLY.
99 99
              *
100 100
              * USERS IN THIS ROLE DO NOT HAVE TO BE IDENTIFIED TO GET THE RIGHTS CONFERRED HERE.
101 101
              * DO NOT ADD ANY SECURITY-SENSITIVE RIGHTS HERE.
102 102
              */
103
-            '_childRoles'             => array(
104
-                'public',
105
-            ),
106
-            PagePreferences::class    => array(
107
-                self::MAIN => self::ACCESS_ALLOW,
108
-            ),
109
-            PageChangePassword::class => array(
110
-                self::MAIN => self::ACCESS_ALLOW,
111
-            ),
112
-            PageOAuth::class          => array(
113
-                'attach' => self::ACCESS_ALLOW,
114
-                'detach' => self::ACCESS_ALLOW,
115
-            ),
116
-        ),
117
-        'user'              => array(
118
-            '_description'                       => 'A standard tool user.',
119
-            '_editableBy'                        => array('admin', 'toolRoot'),
120
-            '_childRoles'                        => array(
121
-                'internalStats',
122
-            ),
123
-            PageMain::class                      => array(
124
-                self::MAIN => self::ACCESS_ALLOW,
125
-            ),
126
-            PageBan::class                       => array(
127
-                self::MAIN => self::ACCESS_ALLOW,
128
-            ),
129
-            PageEditComment::class               => array(
130
-                self::MAIN => self::ACCESS_ALLOW,
131
-            ),
132
-            PageEmailManagement::class           => array(
133
-                self::MAIN => self::ACCESS_ALLOW,
134
-                'view'     => self::ACCESS_ALLOW,
135
-            ),
136
-            PageExpandedRequestList::class       => array(
137
-                self::MAIN => self::ACCESS_ALLOW,
138
-            ),
139
-            PageLog::class                       => array(
140
-                self::MAIN => self::ACCESS_ALLOW,
141
-            ),
142
-            PageSearch::class                    => array(
143
-                self::MAIN => self::ACCESS_ALLOW,
144
-            ),
145
-            PageWelcomeTemplateManagement::class => array(
146
-                self::MAIN => self::ACCESS_ALLOW,
147
-                'select'   => self::ACCESS_ALLOW,
148
-                'view'     => self::ACCESS_ALLOW,
149
-            ),
150
-            PageViewRequest::class               => array(
151
-                self::MAIN       => self::ACCESS_ALLOW,
152
-                'seeAllRequests' => self::ACCESS_ALLOW,
153
-            ),
154
-            'RequestData'                        => array(
155
-                'seePrivateDataWhenReserved' => self::ACCESS_ALLOW,
156
-                'seePrivateDataWithHash'     => self::ACCESS_ALLOW,
157
-            ),
158
-            PageCustomClose::class               => array(
159
-                self::MAIN => self::ACCESS_ALLOW,
160
-            ),
161
-            PageComment::class                   => array(
162
-                self::MAIN => self::ACCESS_ALLOW,
163
-            ),
164
-            PageCloseRequest::class              => array(
165
-                self::MAIN => self::ACCESS_ALLOW,
166
-            ),
167
-            PageCreateRequest::class             => array(
168
-                self::MAIN => self::ACCESS_ALLOW,
169
-            ),
170
-            PageDeferRequest::class              => array(
171
-                self::MAIN => self::ACCESS_ALLOW,
172
-            ),
173
-            PageDropRequest::class               => array(
174
-                self::MAIN => self::ACCESS_ALLOW,
175
-            ),
176
-            PageReservation::class               => array(
177
-                self::MAIN => self::ACCESS_ALLOW,
178
-            ),
179
-            PageSendToUser::class                => array(
180
-                self::MAIN => self::ACCESS_ALLOW,
181
-            ),
182
-            PageBreakReservation::class          => array(
183
-                self::MAIN => self::ACCESS_ALLOW,
184
-            ),
185
-            PageJobQueue::class                  => array(
186
-                self::MAIN => self::ACCESS_ALLOW,
187
-                'view'     => self::ACCESS_ALLOW,
188
-                'all'      => self::ACCESS_ALLOW,
189
-            ),
190
-            'RequestCreation'                    => array(
191
-                User::CREATION_MANUAL => self::ACCESS_ALLOW,
192
-                User::CREATION_OAUTH  => self::ACCESS_ALLOW,
193
-            ),
194
-        ),
195
-        'admin'             => array(
196
-            '_description'                       => 'A tool administrator.',
197
-            '_editableBy'                        => array('admin', 'toolRoot'),
198
-            '_childRoles'                        => array(
199
-                'user',
200
-                'requestAdminTools',
201
-            ),
202
-            PageEmailManagement::class           => array(
203
-                'edit'   => self::ACCESS_ALLOW,
204
-                'create' => self::ACCESS_ALLOW,
205
-            ),
206
-            PageSiteNotice::class                => array(
207
-                self::MAIN => self::ACCESS_ALLOW,
208
-            ),
209
-            PageUserManagement::class            => array(
210
-                self::MAIN  => self::ACCESS_ALLOW,
211
-                'approve'   => self::ACCESS_ALLOW,
212
-                'decline'   => self::ACCESS_ALLOW,
213
-                'rename'    => self::ACCESS_ALLOW,
214
-                'editUser'  => self::ACCESS_ALLOW,
215
-                'suspend'   => self::ACCESS_ALLOW,
216
-                'editRoles' => self::ACCESS_ALLOW,
217
-            ),
218
-            PageWelcomeTemplateManagement::class => array(
219
-                'edit'   => self::ACCESS_ALLOW,
220
-                'delete' => self::ACCESS_ALLOW,
221
-                'add'    => self::ACCESS_ALLOW,
222
-            ),
223
-            PageJobQueue::class                  => array(
224
-                'acknowledge' => self::ACCESS_ALLOW,
225
-                'requeue'     => self::ACCESS_ALLOW,
226
-            ),
227
-        ),
228
-        'checkuser'         => array(
229
-            '_description'            => 'A user with CheckUser access',
230
-            '_editableBy'             => array('checkuser', 'toolRoot'),
231
-            '_childRoles'             => array(
232
-                'user',
233
-                'requestAdminTools',
234
-            ),
235
-            PageUserManagement::class => array(
236
-                self::MAIN  => self::ACCESS_ALLOW,
237
-                'suspend'   => self::ACCESS_ALLOW,
238
-                'editRoles' => self::ACCESS_ALLOW,
239
-            ),
240
-            'RequestData'             => array(
241
-                'seeUserAgentData' => self::ACCESS_ALLOW,
242
-            ),
243
-        ),
244
-        'toolRoot'          => array(
245
-            '_description' => 'A user with shell access to the servers running the tool',
246
-            '_editableBy'  => array('toolRoot'),
247
-            '_childRoles'  => array(
248
-                'admin',
249
-                'checkuser',
250
-            ),
251
-        ),
252
-        'botCreation'       => array(
253
-            '_description'    => 'A user allowed to use the bot to perform account creations',
254
-            '_editableBy'     => array('admin', 'toolRoot'),
255
-            '_childRoles'     => array(),
256
-            'RequestCreation' => array(
257
-                User::CREATION_BOT => self::ACCESS_ALLOW,
258
-            ),
259
-        ),
103
+			'_childRoles'             => array(
104
+				'public',
105
+			),
106
+			PagePreferences::class    => array(
107
+				self::MAIN => self::ACCESS_ALLOW,
108
+			),
109
+			PageChangePassword::class => array(
110
+				self::MAIN => self::ACCESS_ALLOW,
111
+			),
112
+			PageOAuth::class          => array(
113
+				'attach' => self::ACCESS_ALLOW,
114
+				'detach' => self::ACCESS_ALLOW,
115
+			),
116
+		),
117
+		'user'              => array(
118
+			'_description'                       => 'A standard tool user.',
119
+			'_editableBy'                        => array('admin', 'toolRoot'),
120
+			'_childRoles'                        => array(
121
+				'internalStats',
122
+			),
123
+			PageMain::class                      => array(
124
+				self::MAIN => self::ACCESS_ALLOW,
125
+			),
126
+			PageBan::class                       => array(
127
+				self::MAIN => self::ACCESS_ALLOW,
128
+			),
129
+			PageEditComment::class               => array(
130
+				self::MAIN => self::ACCESS_ALLOW,
131
+			),
132
+			PageEmailManagement::class           => array(
133
+				self::MAIN => self::ACCESS_ALLOW,
134
+				'view'     => self::ACCESS_ALLOW,
135
+			),
136
+			PageExpandedRequestList::class       => array(
137
+				self::MAIN => self::ACCESS_ALLOW,
138
+			),
139
+			PageLog::class                       => array(
140
+				self::MAIN => self::ACCESS_ALLOW,
141
+			),
142
+			PageSearch::class                    => array(
143
+				self::MAIN => self::ACCESS_ALLOW,
144
+			),
145
+			PageWelcomeTemplateManagement::class => array(
146
+				self::MAIN => self::ACCESS_ALLOW,
147
+				'select'   => self::ACCESS_ALLOW,
148
+				'view'     => self::ACCESS_ALLOW,
149
+			),
150
+			PageViewRequest::class               => array(
151
+				self::MAIN       => self::ACCESS_ALLOW,
152
+				'seeAllRequests' => self::ACCESS_ALLOW,
153
+			),
154
+			'RequestData'                        => array(
155
+				'seePrivateDataWhenReserved' => self::ACCESS_ALLOW,
156
+				'seePrivateDataWithHash'     => self::ACCESS_ALLOW,
157
+			),
158
+			PageCustomClose::class               => array(
159
+				self::MAIN => self::ACCESS_ALLOW,
160
+			),
161
+			PageComment::class                   => array(
162
+				self::MAIN => self::ACCESS_ALLOW,
163
+			),
164
+			PageCloseRequest::class              => array(
165
+				self::MAIN => self::ACCESS_ALLOW,
166
+			),
167
+			PageCreateRequest::class             => array(
168
+				self::MAIN => self::ACCESS_ALLOW,
169
+			),
170
+			PageDeferRequest::class              => array(
171
+				self::MAIN => self::ACCESS_ALLOW,
172
+			),
173
+			PageDropRequest::class               => array(
174
+				self::MAIN => self::ACCESS_ALLOW,
175
+			),
176
+			PageReservation::class               => array(
177
+				self::MAIN => self::ACCESS_ALLOW,
178
+			),
179
+			PageSendToUser::class                => array(
180
+				self::MAIN => self::ACCESS_ALLOW,
181
+			),
182
+			PageBreakReservation::class          => array(
183
+				self::MAIN => self::ACCESS_ALLOW,
184
+			),
185
+			PageJobQueue::class                  => array(
186
+				self::MAIN => self::ACCESS_ALLOW,
187
+				'view'     => self::ACCESS_ALLOW,
188
+				'all'      => self::ACCESS_ALLOW,
189
+			),
190
+			'RequestCreation'                    => array(
191
+				User::CREATION_MANUAL => self::ACCESS_ALLOW,
192
+				User::CREATION_OAUTH  => self::ACCESS_ALLOW,
193
+			),
194
+		),
195
+		'admin'             => array(
196
+			'_description'                       => 'A tool administrator.',
197
+			'_editableBy'                        => array('admin', 'toolRoot'),
198
+			'_childRoles'                        => array(
199
+				'user',
200
+				'requestAdminTools',
201
+			),
202
+			PageEmailManagement::class           => array(
203
+				'edit'   => self::ACCESS_ALLOW,
204
+				'create' => self::ACCESS_ALLOW,
205
+			),
206
+			PageSiteNotice::class                => array(
207
+				self::MAIN => self::ACCESS_ALLOW,
208
+			),
209
+			PageUserManagement::class            => array(
210
+				self::MAIN  => self::ACCESS_ALLOW,
211
+				'approve'   => self::ACCESS_ALLOW,
212
+				'decline'   => self::ACCESS_ALLOW,
213
+				'rename'    => self::ACCESS_ALLOW,
214
+				'editUser'  => self::ACCESS_ALLOW,
215
+				'suspend'   => self::ACCESS_ALLOW,
216
+				'editRoles' => self::ACCESS_ALLOW,
217
+			),
218
+			PageWelcomeTemplateManagement::class => array(
219
+				'edit'   => self::ACCESS_ALLOW,
220
+				'delete' => self::ACCESS_ALLOW,
221
+				'add'    => self::ACCESS_ALLOW,
222
+			),
223
+			PageJobQueue::class                  => array(
224
+				'acknowledge' => self::ACCESS_ALLOW,
225
+				'requeue'     => self::ACCESS_ALLOW,
226
+			),
227
+		),
228
+		'checkuser'         => array(
229
+			'_description'            => 'A user with CheckUser access',
230
+			'_editableBy'             => array('checkuser', 'toolRoot'),
231
+			'_childRoles'             => array(
232
+				'user',
233
+				'requestAdminTools',
234
+			),
235
+			PageUserManagement::class => array(
236
+				self::MAIN  => self::ACCESS_ALLOW,
237
+				'suspend'   => self::ACCESS_ALLOW,
238
+				'editRoles' => self::ACCESS_ALLOW,
239
+			),
240
+			'RequestData'             => array(
241
+				'seeUserAgentData' => self::ACCESS_ALLOW,
242
+			),
243
+		),
244
+		'toolRoot'          => array(
245
+			'_description' => 'A user with shell access to the servers running the tool',
246
+			'_editableBy'  => array('toolRoot'),
247
+			'_childRoles'  => array(
248
+				'admin',
249
+				'checkuser',
250
+			),
251
+		),
252
+		'botCreation'       => array(
253
+			'_description'    => 'A user allowed to use the bot to perform account creations',
254
+			'_editableBy'     => array('admin', 'toolRoot'),
255
+			'_childRoles'     => array(),
256
+			'RequestCreation' => array(
257
+				User::CREATION_BOT => self::ACCESS_ALLOW,
258
+			),
259
+		),
260 260
 
261
-        // Child roles go below this point
262
-        'publicStats'       => array(
263
-            '_hidden'               => true,
264
-            StatsUsers::class       => array(
265
-                self::MAIN => self::ACCESS_ALLOW,
266
-                'detail'   => self::ACCESS_ALLOW,
267
-            ),
268
-            StatsTopCreators::class => array(
269
-                self::MAIN => self::ACCESS_ALLOW,
270
-            ),
271
-        ),
272
-        'internalStats'     => array(
273
-            '_hidden'                    => true,
274
-            StatsMain::class             => array(
275
-                self::MAIN => self::ACCESS_ALLOW,
276
-            ),
277
-            StatsFastCloses::class       => array(
278
-                self::MAIN => self::ACCESS_ALLOW,
279
-            ),
280
-            StatsInactiveUsers::class    => array(
281
-                self::MAIN => self::ACCESS_ALLOW,
282
-            ),
283
-            StatsMonthlyStats::class     => array(
284
-                self::MAIN => self::ACCESS_ALLOW,
285
-            ),
286
-            StatsReservedRequests::class => array(
287
-                self::MAIN => self::ACCESS_ALLOW,
288
-            ),
289
-            StatsTemplateStats::class    => array(
290
-                self::MAIN => self::ACCESS_ALLOW,
291
-            ),
292
-        ),
293
-        'requestAdminTools' => array(
294
-            '_hidden'                   => true,
295
-            PageBan::class              => array(
296
-                self::MAIN => self::ACCESS_ALLOW,
297
-                'set'      => self::ACCESS_ALLOW,
298
-                'remove'   => self::ACCESS_ALLOW,
299
-            ),
300
-            PageEditComment::class      => array(
301
-                'editOthers' => self::ACCESS_ALLOW,
302
-            ),
303
-            PageBreakReservation::class => array(
304
-                'force' => self::ACCESS_ALLOW,
305
-            ),
306
-            PageCustomClose::class      => array(
307
-                'skipCcMailingList' => self::ACCESS_ALLOW,
308
-            ),
309
-            'RequestData'               => array(
310
-                'reopenOldRequest'      => self::ACCESS_ALLOW,
311
-                'alwaysSeePrivateData'  => self::ACCESS_ALLOW,
312
-                'alwaysSeeHash'         => self::ACCESS_ALLOW,
313
-                'seeRestrictedComments' => self::ACCESS_ALLOW,
314
-            ),
315
-        ),
316
-    );
317
-    /** @var array
318
-     * List of roles which are *exempt* from the identification requirements
319
-     *
320
-     * Think twice about adding roles to this list.
321
-     *
322
-     * @category Security-Critical
323
-     */
324
-    private $identificationExempt = array('public', 'loggedIn');
261
+		// Child roles go below this point
262
+		'publicStats'       => array(
263
+			'_hidden'               => true,
264
+			StatsUsers::class       => array(
265
+				self::MAIN => self::ACCESS_ALLOW,
266
+				'detail'   => self::ACCESS_ALLOW,
267
+			),
268
+			StatsTopCreators::class => array(
269
+				self::MAIN => self::ACCESS_ALLOW,
270
+			),
271
+		),
272
+		'internalStats'     => array(
273
+			'_hidden'                    => true,
274
+			StatsMain::class             => array(
275
+				self::MAIN => self::ACCESS_ALLOW,
276
+			),
277
+			StatsFastCloses::class       => array(
278
+				self::MAIN => self::ACCESS_ALLOW,
279
+			),
280
+			StatsInactiveUsers::class    => array(
281
+				self::MAIN => self::ACCESS_ALLOW,
282
+			),
283
+			StatsMonthlyStats::class     => array(
284
+				self::MAIN => self::ACCESS_ALLOW,
285
+			),
286
+			StatsReservedRequests::class => array(
287
+				self::MAIN => self::ACCESS_ALLOW,
288
+			),
289
+			StatsTemplateStats::class    => array(
290
+				self::MAIN => self::ACCESS_ALLOW,
291
+			),
292
+		),
293
+		'requestAdminTools' => array(
294
+			'_hidden'                   => true,
295
+			PageBan::class              => array(
296
+				self::MAIN => self::ACCESS_ALLOW,
297
+				'set'      => self::ACCESS_ALLOW,
298
+				'remove'   => self::ACCESS_ALLOW,
299
+			),
300
+			PageEditComment::class      => array(
301
+				'editOthers' => self::ACCESS_ALLOW,
302
+			),
303
+			PageBreakReservation::class => array(
304
+				'force' => self::ACCESS_ALLOW,
305
+			),
306
+			PageCustomClose::class      => array(
307
+				'skipCcMailingList' => self::ACCESS_ALLOW,
308
+			),
309
+			'RequestData'               => array(
310
+				'reopenOldRequest'      => self::ACCESS_ALLOW,
311
+				'alwaysSeePrivateData'  => self::ACCESS_ALLOW,
312
+				'alwaysSeeHash'         => self::ACCESS_ALLOW,
313
+				'seeRestrictedComments' => self::ACCESS_ALLOW,
314
+			),
315
+		),
316
+	);
317
+	/** @var array
318
+	 * List of roles which are *exempt* from the identification requirements
319
+	 *
320
+	 * Think twice about adding roles to this list.
321
+	 *
322
+	 * @category Security-Critical
323
+	 */
324
+	private $identificationExempt = array('public', 'loggedIn');
325 325
 
326
-    /**
327
-     * RoleConfiguration constructor.
328
-     *
329
-     * @param array $roleConfig           Set to non-null to override the default configuration.
330
-     * @param array $identificationExempt Set to non-null to override the default configuration.
331
-     */
332
-    public function __construct(array $roleConfig = null, array $identificationExempt = null)
333
-    {
334
-        if ($roleConfig !== null) {
335
-            $this->roleConfig = $roleConfig;
336
-        }
326
+	/**
327
+	 * RoleConfiguration constructor.
328
+	 *
329
+	 * @param array $roleConfig           Set to non-null to override the default configuration.
330
+	 * @param array $identificationExempt Set to non-null to override the default configuration.
331
+	 */
332
+	public function __construct(array $roleConfig = null, array $identificationExempt = null)
333
+	{
334
+		if ($roleConfig !== null) {
335
+			$this->roleConfig = $roleConfig;
336
+		}
337 337
 
338
-        if ($identificationExempt !== null) {
339
-            $this->identificationExempt = $identificationExempt;
340
-        }
341
-    }
338
+		if ($identificationExempt !== null) {
339
+			$this->identificationExempt = $identificationExempt;
340
+		}
341
+	}
342 342
 
343
-    /**
344
-     * @param array $roles The roles to check
345
-     *
346
-     * @return array
347
-     */
348
-    public function getApplicableRoles(array $roles)
349
-    {
350
-        $available = array();
343
+	/**
344
+	 * @param array $roles The roles to check
345
+	 *
346
+	 * @return array
347
+	 */
348
+	public function getApplicableRoles(array $roles)
349
+	{
350
+		$available = array();
351 351
 
352
-        foreach ($roles as $role) {
353
-            if (!isset($this->roleConfig[$role])) {
354
-                // wat
355
-                continue;
356
-            }
352
+		foreach ($roles as $role) {
353
+			if (!isset($this->roleConfig[$role])) {
354
+				// wat
355
+				continue;
356
+			}
357 357
 
358
-            $available[$role] = $this->roleConfig[$role];
358
+			$available[$role] = $this->roleConfig[$role];
359 359
 
360
-            if (isset($available[$role]['_childRoles'])) {
361
-                $childRoles = self::getApplicableRoles($available[$role]['_childRoles']);
362
-                $available = array_merge($available, $childRoles);
360
+			if (isset($available[$role]['_childRoles'])) {
361
+				$childRoles = self::getApplicableRoles($available[$role]['_childRoles']);
362
+				$available = array_merge($available, $childRoles);
363 363
 
364
-                unset($available[$role]['_childRoles']);
365
-            }
364
+				unset($available[$role]['_childRoles']);
365
+			}
366 366
 
367
-            foreach (array('_hidden', '_editableBy', '_description') as $item) {
368
-                if (isset($available[$role][$item])) {
369
-                    unset($available[$role][$item]);
370
-                }
371
-            }
372
-        }
367
+			foreach (array('_hidden', '_editableBy', '_description') as $item) {
368
+				if (isset($available[$role][$item])) {
369
+					unset($available[$role][$item]);
370
+				}
371
+			}
372
+		}
373 373
 
374
-        return $available;
375
-    }
374
+		return $available;
375
+	}
376 376
 
377
-    public function getAvailableRoles()
378
-    {
379
-        $possible = array_diff(array_keys($this->roleConfig), array('public', 'loggedIn'));
377
+	public function getAvailableRoles()
378
+	{
379
+		$possible = array_diff(array_keys($this->roleConfig), array('public', 'loggedIn'));
380 380
 
381
-        $actual = array();
381
+		$actual = array();
382 382
 
383
-        foreach ($possible as $role) {
384
-            if (!isset($this->roleConfig[$role]['_hidden'])) {
385
-                $actual[$role] = array(
386
-                    'description' => $this->roleConfig[$role]['_description'],
387
-                    'editableBy'  => $this->roleConfig[$role]['_editableBy'],
388
-                );
389
-            }
390
-        }
383
+		foreach ($possible as $role) {
384
+			if (!isset($this->roleConfig[$role]['_hidden'])) {
385
+				$actual[$role] = array(
386
+					'description' => $this->roleConfig[$role]['_description'],
387
+					'editableBy'  => $this->roleConfig[$role]['_editableBy'],
388
+				);
389
+			}
390
+		}
391 391
 
392
-        return $actual;
393
-    }
392
+		return $actual;
393
+	}
394 394
 
395
-    /**
396
-     * @param string $role
397
-     *
398
-     * @return bool
399
-     */
400
-    public function roleNeedsIdentification($role)
401
-    {
402
-        if (in_array($role, $this->identificationExempt)) {
403
-            return false;
404
-        }
395
+	/**
396
+	 * @param string $role
397
+	 *
398
+	 * @return bool
399
+	 */
400
+	public function roleNeedsIdentification($role)
401
+	{
402
+		if (in_array($role, $this->identificationExempt)) {
403
+			return false;
404
+		}
405 405
 
406
-        return true;
407
-    }
406
+		return true;
407
+	}
408 408
 }
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/ICredentialProvider.php 1 patch
Indentation   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -12,20 +12,20 @@
 block discarded – undo
12 12
 
13 13
 interface ICredentialProvider
14 14
 {
15
-    /**
16
-     * Validates a user-provided credential
17
-     *
18
-     * @param User $user The user to test the authentication against
19
-     * @param string $data The raw credential data to be validated
20
-     *
21
-     * @return bool
22
-     */
23
-    public function authenticate(User $user, $data);
15
+	/**
16
+	 * Validates a user-provided credential
17
+	 *
18
+	 * @param User $user The user to test the authentication against
19
+	 * @param string $data The raw credential data to be validated
20
+	 *
21
+	 * @return bool
22
+	 */
23
+	public function authenticate(User $user, $data);
24 24
 
25
-    /**
26
-     * @param User $user The user the credential belongs to
27
-     * @param int $factor The factor this credential provides
28
-     * @param string $data
29
-     */
30
-    public function setCredential(User $user, $factor, $data);
25
+	/**
26
+	 * @param User $user The user the credential belongs to
27
+	 * @param int $factor The factor this credential provides
28
+	 * @param string $data
29
+	 */
30
+	public function setCredential(User $user, $factor, $data);
31 31
 }
32 32
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/PasswordCredentialProvider.php 1 patch
Indentation   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -14,50 +14,50 @@
 block discarded – undo
14 14
 
15 15
 class PasswordCredentialProvider extends CredentialProviderBase
16 16
 {
17
-    const PASSWORD_COST = 10;
18
-
19
-    public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
20
-    {
21
-        parent::__construct($database, $configuration, 'password');
22
-    }
23
-
24
-    public function authenticate(User $user, $data)
25
-    {
26
-        $storedData = $this->getCredentialData($user->getId());
27
-        if($storedData === null)
28
-        {
29
-            // No available credential matching these parameters
30
-            return false;
31
-        }
32
-
33
-        if($storedData->getVersion() !== 2) {
34
-            // Non-2 versions are not supported.
35
-            return false;
36
-        }
37
-
38
-        if(password_verify($data, $storedData->getData())) {
39
-            if(password_needs_rehash($storedData->getData(), PASSWORD_BCRYPT, array('cost' => self::PASSWORD_COST))){
40
-                $this->setCredential($user, $storedData->getFactor(), $data);
41
-            }
42
-
43
-            return true;
44
-        }
45
-
46
-        return false;
47
-    }
48
-
49
-    public function setCredential(User $user, $factor, $password)
50
-    {
51
-        $storedData = $this->getCredentialData($user->getId());
52
-
53
-        if($storedData === null){
54
-            $storedData = $this->createNewCredential($user);
55
-        }
56
-
57
-        $storedData->setData(password_hash($password, PASSWORD_BCRYPT, array('cost' => self::PASSWORD_COST)));
58
-        $storedData->setFactor($factor);
59
-        $storedData->setVersion(2);
60
-
61
-        $storedData->save();
62
-    }
17
+	const PASSWORD_COST = 10;
18
+
19
+	public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
20
+	{
21
+		parent::__construct($database, $configuration, 'password');
22
+	}
23
+
24
+	public function authenticate(User $user, $data)
25
+	{
26
+		$storedData = $this->getCredentialData($user->getId());
27
+		if($storedData === null)
28
+		{
29
+			// No available credential matching these parameters
30
+			return false;
31
+		}
32
+
33
+		if($storedData->getVersion() !== 2) {
34
+			// Non-2 versions are not supported.
35
+			return false;
36
+		}
37
+
38
+		if(password_verify($data, $storedData->getData())) {
39
+			if(password_needs_rehash($storedData->getData(), PASSWORD_BCRYPT, array('cost' => self::PASSWORD_COST))){
40
+				$this->setCredential($user, $storedData->getFactor(), $data);
41
+			}
42
+
43
+			return true;
44
+		}
45
+
46
+		return false;
47
+	}
48
+
49
+	public function setCredential(User $user, $factor, $password)
50
+	{
51
+		$storedData = $this->getCredentialData($user->getId());
52
+
53
+		if($storedData === null){
54
+			$storedData = $this->createNewCredential($user);
55
+		}
56
+
57
+		$storedData->setData(password_hash($password, PASSWORD_BCRYPT, array('cost' => self::PASSWORD_COST)));
58
+		$storedData->setFactor($factor);
59
+		$storedData->setVersion(2);
60
+
61
+		$storedData->save();
62
+	}
63 63
 }
64 64
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/CredentialProviderBase.php 1 patch
Indentation   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -15,85 +15,85 @@
 block discarded – undo
15 15
 
16 16
 abstract class CredentialProviderBase implements ICredentialProvider
17 17
 {
18
-    /**
19
-     * @var PdoDatabase
20
-     */
21
-    private $database;
22
-    /**
23
-     * @var SiteConfiguration
24
-     */
25
-    private $configuration;
26
-    /** @var string */
27
-    private $type;
18
+	/**
19
+	 * @var PdoDatabase
20
+	 */
21
+	private $database;
22
+	/**
23
+	 * @var SiteConfiguration
24
+	 */
25
+	private $configuration;
26
+	/** @var string */
27
+	private $type;
28 28
 
29
-    /**
30
-     * CredentialProviderBase constructor.
31
-     *
32
-     * @param PdoDatabase       $database
33
-     * @param SiteConfiguration $configuration
34
-     * @param string            $type
35
-     */
36
-    public function __construct(PdoDatabase $database, SiteConfiguration $configuration, $type)
37
-    {
38
-        $this->database = $database;
39
-        $this->configuration = $configuration;
40
-        $this->type = $type;
41
-    }
29
+	/**
30
+	 * CredentialProviderBase constructor.
31
+	 *
32
+	 * @param PdoDatabase       $database
33
+	 * @param SiteConfiguration $configuration
34
+	 * @param string            $type
35
+	 */
36
+	public function __construct(PdoDatabase $database, SiteConfiguration $configuration, $type)
37
+	{
38
+		$this->database = $database;
39
+		$this->configuration = $configuration;
40
+		$this->type = $type;
41
+	}
42 42
 
43
-    /**
44
-     * @param int $userId
45
-     *
46
-     * @return Credential
47
-     */
48
-    protected function getCredentialData($userId)
49
-    {
50
-        $sql = 'SELECT * FROM credential WHERE type = :t AND user = :u AND disabled = 0';
43
+	/**
44
+	 * @param int $userId
45
+	 *
46
+	 * @return Credential
47
+	 */
48
+	protected function getCredentialData($userId)
49
+	{
50
+		$sql = 'SELECT * FROM credential WHERE type = :t AND user = :u AND disabled = 0';
51 51
 
52
-        $statement = $this->database->prepare($sql);
53
-        $statement->execute(array(':u' => $userId, ':t' => $this->type));
52
+		$statement = $this->database->prepare($sql);
53
+		$statement->execute(array(':u' => $userId, ':t' => $this->type));
54 54
 
55
-        /** @var Credential $obj */
56
-        $obj = $statement->fetchObject(Credential::class);
55
+		/** @var Credential $obj */
56
+		$obj = $statement->fetchObject(Credential::class);
57 57
 
58
-        if ($obj === false) {
59
-            return null;
60
-        }
58
+		if ($obj === false) {
59
+			return null;
60
+		}
61 61
 
62
-        $obj->setDatabase($this->database);
62
+		$obj->setDatabase($this->database);
63 63
 
64
-        $statement->closeCursor();
64
+		$statement->closeCursor();
65 65
 
66
-        return $obj;
67
-    }
66
+		return $obj;
67
+	}
68 68
 
69
-    /**
70
-     * @return PdoDatabase
71
-     */
72
-    public function getDatabase()
73
-    {
74
-        return $this->database;
75
-    }
69
+	/**
70
+	 * @return PdoDatabase
71
+	 */
72
+	public function getDatabase()
73
+	{
74
+		return $this->database;
75
+	}
76 76
 
77
-    /**
78
-     * @return SiteConfiguration
79
-     */
80
-    public function getConfiguration()
81
-    {
82
-        return $this->configuration;
83
-    }
77
+	/**
78
+	 * @return SiteConfiguration
79
+	 */
80
+	public function getConfiguration()
81
+	{
82
+		return $this->configuration;
83
+	}
84 84
 
85
-    /**
86
-     * @param User $user
87
-     *
88
-     * @return Credential
89
-     */
90
-    protected function createNewCredential(User $user)
91
-    {
92
-        $credential = new Credential();
93
-        $credential->setDatabase($this->getDatabase());
94
-        $credential->setUserId($user->getId());
95
-        $credential->setType($this->type);
85
+	/**
86
+	 * @param User $user
87
+	 *
88
+	 * @return Credential
89
+	 */
90
+	protected function createNewCredential(User $user)
91
+	{
92
+		$credential = new Credential();
93
+		$credential->setDatabase($this->getDatabase());
94
+		$credential->setUserId($user->getId());
95
+		$credential->setType($this->type);
96 96
 
97
-        return $credential;
98
-    }
97
+		return $credential;
98
+	}
99 99
 }
100 100
\ No newline at end of file
Please login to merge, or discard this patch.
includes/API/Actions/StatsAction.php 1 patch
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -20,58 +20,58 @@
 block discarded – undo
20 20
  */
21 21
 class StatsAction extends ApiPageBase implements IApiAction
22 22
 {
23
-    /**
24
-     * The target user
25
-     * @var User $user
26
-     */
27
-    private $user;
23
+	/**
24
+	 * The target user
25
+	 * @var User $user
26
+	 */
27
+	private $user;
28 28
 
29
-    /**
30
-     * Summary of execute
31
-     *
32
-     * @param \DOMElement $apiDocument
33
-     *
34
-     * @return \DOMElement
35
-     * @throws ApiException
36
-     * @throws \Exception
37
-     */
38
-    public function executeApiAction(\DOMElement $apiDocument)
39
-    {
40
-        $username = WebRequest::getString('user');
41
-        $wikiusername = WebRequest::getString('wikiuser');
29
+	/**
30
+	 * Summary of execute
31
+	 *
32
+	 * @param \DOMElement $apiDocument
33
+	 *
34
+	 * @return \DOMElement
35
+	 * @throws ApiException
36
+	 * @throws \Exception
37
+	 */
38
+	public function executeApiAction(\DOMElement $apiDocument)
39
+	{
40
+		$username = WebRequest::getString('user');
41
+		$wikiusername = WebRequest::getString('wikiuser');
42 42
 
43
-        if ($username === null && $wikiusername === null) {
44
-            throw new ApiException("Please specify a username using either user or wikiuser parameters.");
45
-        }
43
+		if ($username === null && $wikiusername === null) {
44
+			throw new ApiException("Please specify a username using either user or wikiuser parameters.");
45
+		}
46 46
 
47
-        $userElement = $this->document->createElement("user");
48
-        $apiDocument->appendChild($userElement);
47
+		$userElement = $this->document->createElement("user");
48
+		$apiDocument->appendChild($userElement);
49 49
 
50
-        if ($username !== null) {
51
-            $user = User::getByUsername($username, $this->getDatabase());
52
-        }
53
-        else {
54
-            $user = User::getByOnWikiUsername($wikiusername, $this->getDatabase());
55
-        }
50
+		if ($username !== null) {
51
+			$user = User::getByUsername($username, $this->getDatabase());
52
+		}
53
+		else {
54
+			$user = User::getByOnWikiUsername($wikiusername, $this->getDatabase());
55
+		}
56 56
 
57
-        if ($user === false) {
58
-            $userElement->setAttribute("missing", "true");
57
+		if ($user === false) {
58
+			$userElement->setAttribute("missing", "true");
59 59
 
60
-            return $apiDocument;
61
-        }
60
+			return $apiDocument;
61
+		}
62 62
 
63
-        $this->user = $user;
63
+		$this->user = $user;
64 64
 
65
-        $oauth = new OAuthUserHelper($user, $this->getDatabase(), $this->getOAuthProtocolHelper(),
66
-            $this->getSiteConfiguration());
65
+		$oauth = new OAuthUserHelper($user, $this->getDatabase(), $this->getOAuthProtocolHelper(),
66
+			$this->getSiteConfiguration());
67 67
 
68
-        $userElement->setAttribute("username", $this->user->getUsername());
69
-        $userElement->setAttribute("status", $this->user->getStatus());
70
-        $userElement->setAttribute("lastactive", $this->user->getLastActive());
71
-        $userElement->setAttribute("welcome_template", $this->user->getWelcomeTemplate());
72
-        $userElement->setAttribute("onwikiname", $this->user->getOnWikiName());
73
-        $userElement->setAttribute("oauth", $oauth->isFullyLinked() ? "true" : "false");
68
+		$userElement->setAttribute("username", $this->user->getUsername());
69
+		$userElement->setAttribute("status", $this->user->getStatus());
70
+		$userElement->setAttribute("lastactive", $this->user->getLastActive());
71
+		$userElement->setAttribute("welcome_template", $this->user->getWelcomeTemplate());
72
+		$userElement->setAttribute("onwikiname", $this->user->getOnWikiName());
73
+		$userElement->setAttribute("oauth", $oauth->isFullyLinked() ? "true" : "false");
74 74
 
75
-        return $apiDocument;
76
-    }
75
+		return $apiDocument;
76
+	}
77 77
 }
Please login to merge, or discard this patch.
includes/Helpers/BotMediaWikiClient.php 1 patch
Indentation   +132 added lines, -132 removed lines patch added patch discarded remove patch
@@ -16,136 +16,136 @@
 block discarded – undo
16 16
 
17 17
 class BotMediaWikiClient implements IMediaWikiClient
18 18
 {
19
-    /**
20
-     * @var HttpHelper
21
-     */
22
-    private $httpHelper;
23
-    /** @var string */
24
-    private $mediawikiWebServiceEndpoint;
25
-    /** @var string */
26
-    private $creationBotUsername;
27
-    /** @var string */
28
-    private $creationBotPassword;
29
-    /** @var bool */
30
-    private $knownLoggedIn = false;
31
-
32
-    /**
33
-     * BotMediaWikiClient constructor.
34
-     *
35
-     * @param SiteConfiguration $siteConfiguration
36
-     */
37
-    public function __construct(SiteConfiguration $siteConfiguration)
38
-    {
39
-        $this->mediawikiWebServiceEndpoint = $siteConfiguration->getMediawikiWebServiceEndpoint();
40
-
41
-        $this->creationBotUsername = $siteConfiguration->getCreationBotUsername();
42
-        $this->creationBotPassword = $siteConfiguration->getCreationBotPassword();
43
-
44
-        $this->httpHelper = new HttpHelper(
45
-            $siteConfiguration->getUserAgent(),
46
-            $siteConfiguration->getCurlDisableVerifyPeer(),
47
-            $siteConfiguration->getCurlCookieJar()
48
-        );
49
-    }
50
-
51
-    function doApiCall($apiParams, $method = 'GET')
52
-    {
53
-        $this->ensureLoggedIn();
54
-        $apiParams['assert'] = 'user';
55
-
56
-        return $this->callApi($apiParams, $method);
57
-    }
58
-
59
-    private function ensureLoggedIn()
60
-    {
61
-        if ($this->knownLoggedIn) {
62
-            return;
63
-        }
64
-
65
-        $userinfoResult = $this->callApi(array('action' => 'query', 'meta' => 'userinfo'), 'GET');
66
-        if (isset($userinfoResult->query->userinfo->anon)) {
67
-            // not logged in.
68
-            $this->logIn();
69
-
70
-            // retest
71
-            $userinfoResult = $this->callApi(array('action' => 'query', 'meta' => 'userinfo'), 'GET');
72
-            if (isset($userinfoResult->query->userinfo->anon)) {
73
-                throw new MediaWikiApiException('Unable to log in.');
74
-            }
75
-            else {
76
-                $this->knownLoggedIn = true;
77
-            }
78
-        }
79
-        else {
80
-            $this->knownLoggedIn = true;
81
-        }
82
-    }
83
-
84
-    /**
85
-     * @param $apiParams
86
-     * @param $method
87
-     *
88
-     * @return mixed
89
-     * @throws ApplicationLogicException
90
-     * @throws CurlException
91
-     */
92
-    private function callApi($apiParams, $method)
93
-    {
94
-        $apiParams['format'] = 'json';
95
-
96
-        if ($method == 'GET') {
97
-            $data = $this->httpHelper->get($this->mediawikiWebServiceEndpoint, $apiParams);
98
-        }
99
-        elseif ($method == 'POST') {
100
-            $data = $this->httpHelper->post($this->mediawikiWebServiceEndpoint, $apiParams);
101
-        }
102
-        else {
103
-            throw new ApplicationLogicException('Unsupported HTTP Method');
104
-        }
105
-
106
-        if ($data === false) {
107
-            throw new CurlException('Curl error: ' . $this->httpHelper->getError());
108
-        }
109
-
110
-        $result = json_decode($data);
111
-
112
-        return $result;
113
-    }
114
-
115
-    private function logIn()
116
-    {
117
-        // get token
118
-        $tokenParams = array(
119
-            'action' => 'query',
120
-            'meta'   => 'tokens',
121
-            'type'   => 'login',
122
-        );
123
-
124
-        $response = $this->callApi($tokenParams, 'POST');
125
-
126
-        if (isset($response->error)) {
127
-            throw new MediaWikiApiException($response->error->code . ': ' . $response->error->info);
128
-        }
129
-
130
-        $token = $response->query->tokens->logintoken;
131
-
132
-        if ($token === null) {
133
-            throw new MediaWikiApiException('Edit token could not be acquired');
134
-        }
135
-
136
-        $params = array(
137
-            'action' => 'login',
138
-            'lgname' => $this->creationBotUsername,
139
-            'lgpassword' => $this->creationBotPassword,
140
-            'lgtoken' => $token,
141
-        );
142
-
143
-        $loginResponse = $this->callApi($params, 'POST');
144
-
145
-        if($loginResponse->login->result == 'Success'){
146
-            return;
147
-        }
148
-
149
-        throw new ApplicationLogicException(json_encode($loginResponse));
150
-    }
19
+	/**
20
+	 * @var HttpHelper
21
+	 */
22
+	private $httpHelper;
23
+	/** @var string */
24
+	private $mediawikiWebServiceEndpoint;
25
+	/** @var string */
26
+	private $creationBotUsername;
27
+	/** @var string */
28
+	private $creationBotPassword;
29
+	/** @var bool */
30
+	private $knownLoggedIn = false;
31
+
32
+	/**
33
+	 * BotMediaWikiClient constructor.
34
+	 *
35
+	 * @param SiteConfiguration $siteConfiguration
36
+	 */
37
+	public function __construct(SiteConfiguration $siteConfiguration)
38
+	{
39
+		$this->mediawikiWebServiceEndpoint = $siteConfiguration->getMediawikiWebServiceEndpoint();
40
+
41
+		$this->creationBotUsername = $siteConfiguration->getCreationBotUsername();
42
+		$this->creationBotPassword = $siteConfiguration->getCreationBotPassword();
43
+
44
+		$this->httpHelper = new HttpHelper(
45
+			$siteConfiguration->getUserAgent(),
46
+			$siteConfiguration->getCurlDisableVerifyPeer(),
47
+			$siteConfiguration->getCurlCookieJar()
48
+		);
49
+	}
50
+
51
+	function doApiCall($apiParams, $method = 'GET')
52
+	{
53
+		$this->ensureLoggedIn();
54
+		$apiParams['assert'] = 'user';
55
+
56
+		return $this->callApi($apiParams, $method);
57
+	}
58
+
59
+	private function ensureLoggedIn()
60
+	{
61
+		if ($this->knownLoggedIn) {
62
+			return;
63
+		}
64
+
65
+		$userinfoResult = $this->callApi(array('action' => 'query', 'meta' => 'userinfo'), 'GET');
66
+		if (isset($userinfoResult->query->userinfo->anon)) {
67
+			// not logged in.
68
+			$this->logIn();
69
+
70
+			// retest
71
+			$userinfoResult = $this->callApi(array('action' => 'query', 'meta' => 'userinfo'), 'GET');
72
+			if (isset($userinfoResult->query->userinfo->anon)) {
73
+				throw new MediaWikiApiException('Unable to log in.');
74
+			}
75
+			else {
76
+				$this->knownLoggedIn = true;
77
+			}
78
+		}
79
+		else {
80
+			$this->knownLoggedIn = true;
81
+		}
82
+	}
83
+
84
+	/**
85
+	 * @param $apiParams
86
+	 * @param $method
87
+	 *
88
+	 * @return mixed
89
+	 * @throws ApplicationLogicException
90
+	 * @throws CurlException
91
+	 */
92
+	private function callApi($apiParams, $method)
93
+	{
94
+		$apiParams['format'] = 'json';
95
+
96
+		if ($method == 'GET') {
97
+			$data = $this->httpHelper->get($this->mediawikiWebServiceEndpoint, $apiParams);
98
+		}
99
+		elseif ($method == 'POST') {
100
+			$data = $this->httpHelper->post($this->mediawikiWebServiceEndpoint, $apiParams);
101
+		}
102
+		else {
103
+			throw new ApplicationLogicException('Unsupported HTTP Method');
104
+		}
105
+
106
+		if ($data === false) {
107
+			throw new CurlException('Curl error: ' . $this->httpHelper->getError());
108
+		}
109
+
110
+		$result = json_decode($data);
111
+
112
+		return $result;
113
+	}
114
+
115
+	private function logIn()
116
+	{
117
+		// get token
118
+		$tokenParams = array(
119
+			'action' => 'query',
120
+			'meta'   => 'tokens',
121
+			'type'   => 'login',
122
+		);
123
+
124
+		$response = $this->callApi($tokenParams, 'POST');
125
+
126
+		if (isset($response->error)) {
127
+			throw new MediaWikiApiException($response->error->code . ': ' . $response->error->info);
128
+		}
129
+
130
+		$token = $response->query->tokens->logintoken;
131
+
132
+		if ($token === null) {
133
+			throw new MediaWikiApiException('Edit token could not be acquired');
134
+		}
135
+
136
+		$params = array(
137
+			'action' => 'login',
138
+			'lgname' => $this->creationBotUsername,
139
+			'lgpassword' => $this->creationBotPassword,
140
+			'lgtoken' => $token,
141
+		);
142
+
143
+		$loginResponse = $this->callApi($params, 'POST');
144
+
145
+		if($loginResponse->login->result == 'Success'){
146
+			return;
147
+		}
148
+
149
+		throw new ApplicationLogicException(json_encode($loginResponse));
150
+	}
151 151
 }
152 152
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Helpers/OAuthUserHelper.php 1 patch
Indentation   +403 added lines, -403 removed lines patch added patch discarded remove patch
@@ -22,411 +22,411 @@
 block discarded – undo
22 22
 
23 23
 class OAuthUserHelper implements IMediaWikiClient
24 24
 {
25
-    const TOKEN_REQUEST = 'request';
26
-    const TOKEN_ACCESS = 'access';
27
-    /** @var PDOStatement */
28
-    private static $tokenCountStatement = null;
29
-    /** @var PDOStatement */
30
-    private $getTokenStatement;
31
-    /**
32
-     * @var User
33
-     */
34
-    private $user;
35
-    /**
36
-     * @var PdoDatabase
37
-     */
38
-    private $database;
39
-    /**
40
-     * @var IOAuthProtocolHelper
41
-     */
42
-    private $oauthProtocolHelper;
43
-    /**
44
-     * @var bool|null Is the user linked to OAuth
45
-     */
46
-    private $linked;
47
-    private $partiallyLinked;
48
-    /** @var OAuthToken */
49
-    private $accessToken;
50
-    /** @var bool */
51
-    private $accessTokenLoaded = false;
52
-    /**
53
-     * @var OAuthIdentity
54
-     */
55
-    private $identity = null;
56
-    /**
57
-     * @var bool
58
-     */
59
-    private $identityLoaded = false;
60
-    /**
61
-     * @var SiteConfiguration
62
-     */
63
-    private $siteConfiguration;
64
-
65
-    #region Static methods
66
-    public static function findUserByRequestToken($requestToken, PdoDatabase $database)
67
-    {
68
-        $statement = $database->prepare(<<<'SQL'
25
+	const TOKEN_REQUEST = 'request';
26
+	const TOKEN_ACCESS = 'access';
27
+	/** @var PDOStatement */
28
+	private static $tokenCountStatement = null;
29
+	/** @var PDOStatement */
30
+	private $getTokenStatement;
31
+	/**
32
+	 * @var User
33
+	 */
34
+	private $user;
35
+	/**
36
+	 * @var PdoDatabase
37
+	 */
38
+	private $database;
39
+	/**
40
+	 * @var IOAuthProtocolHelper
41
+	 */
42
+	private $oauthProtocolHelper;
43
+	/**
44
+	 * @var bool|null Is the user linked to OAuth
45
+	 */
46
+	private $linked;
47
+	private $partiallyLinked;
48
+	/** @var OAuthToken */
49
+	private $accessToken;
50
+	/** @var bool */
51
+	private $accessTokenLoaded = false;
52
+	/**
53
+	 * @var OAuthIdentity
54
+	 */
55
+	private $identity = null;
56
+	/**
57
+	 * @var bool
58
+	 */
59
+	private $identityLoaded = false;
60
+	/**
61
+	 * @var SiteConfiguration
62
+	 */
63
+	private $siteConfiguration;
64
+
65
+	#region Static methods
66
+	public static function findUserByRequestToken($requestToken, PdoDatabase $database)
67
+	{
68
+		$statement = $database->prepare(<<<'SQL'
69 69
             SELECT u.* FROM user u 
70 70
             INNER JOIN oauthtoken t ON t.user = u.id 
71 71
             WHERE t.type = :type AND t.token = :token
72 72
 SQL
73
-        );
74
-        $statement->execute(array(':type' => self::TOKEN_REQUEST, ':token' => $requestToken));
75
-
76
-        /** @var User $user */
77
-        $user = $statement->fetchObject(User::class);
78
-        $statement->closeCursor();
79
-
80
-        if ($user === false) {
81
-            throw new ApplicationLogicException('Token not found in store, please try again');
82
-        }
83
-
84
-        $user->setDatabase($database);
85
-
86
-        return $user;
87
-    }
88
-
89
-    public static function userIsFullyLinked(User $user, PdoDatabase $database = null)
90
-    {
91
-        if (self::$tokenCountStatement === null && $database === null) {
92
-            throw new ApplicationLogicException('Static link request without initialised statement');
93
-        }
94
-
95
-        return self::runTokenCount($user->getId(), $database, self::TOKEN_ACCESS);
96
-    }
97
-
98
-    public static function userIsPartiallyLinked(User $user, PdoDatabase $database = null)
99
-    {
100
-        if (self::$tokenCountStatement === null && $database === null) {
101
-            throw new ApplicationLogicException('Static link request without initialised statement');
102
-        }
103
-
104
-        if (self::userIsFullyLinked($user, $database)) {
105
-            return false;
106
-        }
107
-
108
-        return self::runTokenCount($user->getId(), $database, self::TOKEN_REQUEST)
109
-            || $user->getOnWikiName() == null;
110
-    }
111
-
112
-    /**
113
-     * @param PdoDatabase $database
114
-     */
115
-    public static function prepareTokenCountStatement(PdoDatabase $database)
116
-    {
117
-        if (self::$tokenCountStatement === null) {
118
-            self::$tokenCountStatement = $database->prepare('SELECT COUNT(*) FROM oauthtoken WHERE user = :user AND type = :type');
119
-        }
120
-    }
121
-
122
-    private static function runTokenCount($userId, $database, $tokenType)
123
-    {
124
-        if (self::$tokenCountStatement === null) {
125
-            self::prepareTokenCountStatement($database);
126
-        }
127
-
128
-        self::$tokenCountStatement->execute(array(
129
-            ':user' => $userId,
130
-            ':type' => $tokenType,
131
-        ));
132
-
133
-        $tokenCount = self::$tokenCountStatement->fetchColumn();
134
-        $linked = $tokenCount > 0;
135
-        self::$tokenCountStatement->closeCursor();
136
-
137
-        return $linked;
138
-    }
139
-
140
-    #endregion Static methods
141
-
142
-    /**
143
-     * OAuthUserHelper constructor.
144
-     *
145
-     * @param User                 $user
146
-     * @param PdoDatabase          $database
147
-     * @param IOAuthProtocolHelper $oauthProtocolHelper
148
-     * @param SiteConfiguration    $siteConfiguration
149
-     */
150
-    public function __construct(
151
-        User $user,
152
-        PdoDatabase $database,
153
-        IOAuthProtocolHelper $oauthProtocolHelper,
154
-        SiteConfiguration $siteConfiguration
155
-    ) {
156
-        $this->user = $user;
157
-        $this->database = $database;
158
-        $this->oauthProtocolHelper = $oauthProtocolHelper;
159
-
160
-        $this->linked = null;
161
-        $this->partiallyLinked = null;
162
-        $this->siteConfiguration = $siteConfiguration;
163
-
164
-        self::prepareTokenCountStatement($database);
165
-        $this->getTokenStatement = $this->database->prepare('SELECT * FROM oauthtoken WHERE user = :user AND type = :type');
166
-    }
167
-
168
-    /**
169
-     * Determines if the user is fully connected to OAuth.
170
-     *
171
-     * @return bool
172
-     */
173
-    public function isFullyLinked()
174
-    {
175
-        if ($this->linked === null) {
176
-            $this->linked = self::userIsFullyLinked($this->user, $this->database);
177
-        }
178
-
179
-        return $this->linked;
180
-    }
181
-
182
-    /**
183
-     * Attempts to figure out if a user is partially linked to OAuth, and therefore needs to complete the OAuth
184
-     * procedure before configuring.
185
-     * @return bool
186
-     */
187
-    public function isPartiallyLinked()
188
-    {
189
-        if ($this->partiallyLinked === null) {
190
-            $this->partiallyLinked = self::userIsPartiallyLinked($this->user, $this->database);
191
-        }
192
-
193
-        return $this->partiallyLinked;
194
-    }
195
-
196
-    /**
197
-     * @throws OAuthException
198
-     */
199
-    public function refreshIdentity()
200
-    {
201
-        $this->loadIdentity();
202
-
203
-        if ($this->identity === null) {
204
-            $this->identity = new OAuthIdentity();
205
-            $this->identity->setUserId($this->user->getId());
206
-            $this->identity->setDatabase($this->database);
207
-        }
208
-
209
-        $token = $this->loadAccessToken();
210
-
211
-        $rawTicket = $this->oauthProtocolHelper->getIdentityTicket($token->getToken(), $token->getSecret());
212
-
213
-        $this->identity->populate($rawTicket);
214
-
215
-        if (!$this->identityIsValid()) {
216
-            throw new OAuthException('Identity ticket is not valid!');
217
-        }
218
-
219
-        $this->identity->save();
220
-
221
-        $this->user->setOnWikiName($this->identity->getUsername());
222
-        $this->user->save();
223
-    }
224
-
225
-    public function getRequestToken()
226
-    {
227
-        $token = $this->oauthProtocolHelper->getRequestToken();
228
-
229
-        $this->partiallyLinked = true;
230
-        $this->linked = false;
231
-
232
-        $this->database
233
-            ->prepare('DELETE FROM oauthtoken WHERE user = :user AND type = :type')
234
-            ->execute(array(':user' => $this->user->getId(), ':type' => self::TOKEN_REQUEST));
235
-
236
-        $this->database
237
-            ->prepare('INSERT INTO oauthtoken (user, type, token, secret, expiry) VALUES (:user, :type, :token, :secret, DATE_ADD(NOW(), INTERVAL 1 DAY))')
238
-            ->execute(array(
239
-                ':user'   => $this->user->getId(),
240
-                ':type'   => self::TOKEN_REQUEST,
241
-                ':token'  => $token->key,
242
-                ':secret' => $token->secret,
243
-            ));
244
-
245
-        return $this->oauthProtocolHelper->getAuthoriseUrl($token->key);
246
-    }
247
-
248
-    public function completeHandshake($verificationToken)
249
-    {
250
-        $this->getTokenStatement->execute(array(':user' => $this->user->getId(), ':type' => self::TOKEN_REQUEST));
251
-
252
-        /** @var OAuthToken $token */
253
-        $token = $this->getTokenStatement->fetchObject(OAuthToken::class);
254
-        $this->getTokenStatement->closeCursor();
255
-
256
-        if ($token === false) {
257
-            throw new ApplicationLogicException('Cannot find request token');
258
-        }
259
-
260
-        $token->setDatabase($this->database);
261
-
262
-        $accessToken = $this->oauthProtocolHelper->callbackCompleted($token->getToken(), $token->getSecret(),
263
-            $verificationToken);
264
-
265
-        $clearStatement = $this->database->prepare('DELETE FROM oauthtoken WHERE user = :u AND type = :t');
266
-        $clearStatement->execute(array(':u' => $this->user->getId(), ':t' => self::TOKEN_ACCESS));
267
-
268
-        $token->setToken($accessToken->key);
269
-        $token->setSecret($accessToken->secret);
270
-        $token->setType(self::TOKEN_ACCESS);
271
-        $token->setExpiry(null);
272
-        $token->save();
273
-
274
-        $this->partiallyLinked = false;
275
-        $this->linked = true;
276
-
277
-        $this->refreshIdentity();
278
-    }
279
-
280
-    public function detach()
281
-    {
282
-        $this->loadIdentity();
283
-
284
-        $this->identity->delete();
285
-        $statement = $this->database->prepare('DELETE FROM oauthtoken WHERE user = :user');
286
-        $statement->execute(array(':user' => $this->user->getId()));
287
-
288
-        $this->identity = null;
289
-        $this->linked = false;
290
-        $this->partiallyLinked = false;
291
-    }
292
-
293
-    /**
294
-     * @param bool $expiredOk
295
-     *
296
-     * @return OAuthIdentity
297
-     * @throws OAuthException
298
-     */
299
-    public function getIdentity($expiredOk = false)
300
-    {
301
-        $this->loadIdentity();
302
-
303
-        if (!$this->identityIsValid($expiredOk)) {
304
-            throw new OAuthException('Stored identity is not valid.');
305
-        }
306
-
307
-        return $this->identity;
308
-    }
309
-
310
-    public function doApiCall($params, $method)
311
-    {
312
-        // Ensure we're logged in
313
-        $params['assert'] = 'user';
314
-
315
-        $token = $this->loadAccessToken();
316
-        return $this->oauthProtocolHelper->apiCall($params, $token->getToken(), $token->getSecret(), $method);
317
-    }
318
-
319
-    /**
320
-     * @param bool $expiredOk
321
-     *
322
-     * @return bool
323
-     */
324
-    private function identityIsValid($expiredOk = false)
325
-    {
326
-        $this->loadIdentity();
327
-
328
-        if ($this->identity === null) {
329
-            return false;
330
-        }
331
-
332
-        if ($this->identity->getIssuedAtTime() === false
333
-            || $this->identity->getExpirationTime() === false
334
-            || $this->identity->getAudience() === false
335
-            || $this->identity->getIssuer() === false
336
-        ) {
337
-            // this isn't populated properly.
338
-            return false;
339
-        }
340
-
341
-        $issue = DateTimeImmutable::createFromFormat("U", $this->identity->getIssuedAtTime());
342
-        $now = new DateTimeImmutable();
343
-
344
-        if ($issue > $now) {
345
-            // wat.
346
-            return false;
347
-        }
348
-
349
-        if ($this->identityExpired() && !$expiredOk) {
350
-            // soz.
351
-            return false;
352
-        }
353
-
354
-        if ($this->identity->getAudience() !== $this->siteConfiguration->getOAuthConsumerToken()) {
355
-            // token not issued for us
356
-            return false;
357
-        }
358
-
359
-        if ($this->identity->getIssuer() !== $this->siteConfiguration->getOauthMediaWikiCanonicalServer()) {
360
-            // token not issued by the right person
361
-            return false;
362
-        }
363
-
364
-        // can't find a reason to not trust it
365
-        return true;
366
-    }
367
-
368
-    /**
369
-     * @return bool
370
-     */
371
-    public function identityExpired()
372
-    {
373
-        // allowed max age
374
-        $gracePeriod = $this->siteConfiguration->getOauthIdentityGraceTime();
375
-
376
-        $expiry = DateTimeImmutable::createFromFormat("U", $this->identity->getExpirationTime());
377
-        $graceExpiry = $expiry->modify($gracePeriod);
378
-        $now = new DateTimeImmutable();
379
-
380
-        return $graceExpiry < $now;
381
-    }
382
-
383
-    /**
384
-     * Loads the OAuth identity from the database for the current user.
385
-     */
386
-    private function loadIdentity()
387
-    {
388
-        if ($this->identityLoaded) {
389
-            return;
390
-        }
391
-
392
-        $statement = $this->database->prepare('SELECT * FROM oauthidentity WHERE user = :user');
393
-        $statement->execute(array(':user' => $this->user->getId()));
394
-        /** @var OAuthIdentity $obj */
395
-        $obj = $statement->fetchObject(OAuthIdentity::class);
396
-
397
-        if ($obj === false) {
398
-            // failed to load identity.
399
-            $this->identityLoaded = true;
400
-            $this->identity = null;
401
-
402
-            return;
403
-        }
404
-
405
-        $obj->setDatabase($this->database);
406
-        $this->identityLoaded = true;
407
-        $this->identity = $obj;
408
-    }
409
-
410
-    /**
411
-     * @return OAuthToken
412
-     * @throws OAuthException
413
-     */
414
-    private function loadAccessToken()
415
-    {
416
-        if (!$this->accessTokenLoaded) {
417
-            $this->getTokenStatement->execute(array(':user' => $this->user->getId(), ':type' => self::TOKEN_ACCESS));
418
-            /** @var OAuthToken $token */
419
-            $token = $this->getTokenStatement->fetchObject(OAuthToken::class);
420
-            $this->getTokenStatement->closeCursor();
421
-
422
-            if ($token === false) {
423
-                throw new OAuthException('Access token not found!');
424
-            }
425
-
426
-            $this->accessToken = $token;
427
-            $this->accessTokenLoaded = true;
428
-        }
429
-
430
-        return $this->accessToken;
431
-    }
73
+		);
74
+		$statement->execute(array(':type' => self::TOKEN_REQUEST, ':token' => $requestToken));
75
+
76
+		/** @var User $user */
77
+		$user = $statement->fetchObject(User::class);
78
+		$statement->closeCursor();
79
+
80
+		if ($user === false) {
81
+			throw new ApplicationLogicException('Token not found in store, please try again');
82
+		}
83
+
84
+		$user->setDatabase($database);
85
+
86
+		return $user;
87
+	}
88
+
89
+	public static function userIsFullyLinked(User $user, PdoDatabase $database = null)
90
+	{
91
+		if (self::$tokenCountStatement === null && $database === null) {
92
+			throw new ApplicationLogicException('Static link request without initialised statement');
93
+		}
94
+
95
+		return self::runTokenCount($user->getId(), $database, self::TOKEN_ACCESS);
96
+	}
97
+
98
+	public static function userIsPartiallyLinked(User $user, PdoDatabase $database = null)
99
+	{
100
+		if (self::$tokenCountStatement === null && $database === null) {
101
+			throw new ApplicationLogicException('Static link request without initialised statement');
102
+		}
103
+
104
+		if (self::userIsFullyLinked($user, $database)) {
105
+			return false;
106
+		}
107
+
108
+		return self::runTokenCount($user->getId(), $database, self::TOKEN_REQUEST)
109
+			|| $user->getOnWikiName() == null;
110
+	}
111
+
112
+	/**
113
+	 * @param PdoDatabase $database
114
+	 */
115
+	public static function prepareTokenCountStatement(PdoDatabase $database)
116
+	{
117
+		if (self::$tokenCountStatement === null) {
118
+			self::$tokenCountStatement = $database->prepare('SELECT COUNT(*) FROM oauthtoken WHERE user = :user AND type = :type');
119
+		}
120
+	}
121
+
122
+	private static function runTokenCount($userId, $database, $tokenType)
123
+	{
124
+		if (self::$tokenCountStatement === null) {
125
+			self::prepareTokenCountStatement($database);
126
+		}
127
+
128
+		self::$tokenCountStatement->execute(array(
129
+			':user' => $userId,
130
+			':type' => $tokenType,
131
+		));
132
+
133
+		$tokenCount = self::$tokenCountStatement->fetchColumn();
134
+		$linked = $tokenCount > 0;
135
+		self::$tokenCountStatement->closeCursor();
136
+
137
+		return $linked;
138
+	}
139
+
140
+	#endregion Static methods
141
+
142
+	/**
143
+	 * OAuthUserHelper constructor.
144
+	 *
145
+	 * @param User                 $user
146
+	 * @param PdoDatabase          $database
147
+	 * @param IOAuthProtocolHelper $oauthProtocolHelper
148
+	 * @param SiteConfiguration    $siteConfiguration
149
+	 */
150
+	public function __construct(
151
+		User $user,
152
+		PdoDatabase $database,
153
+		IOAuthProtocolHelper $oauthProtocolHelper,
154
+		SiteConfiguration $siteConfiguration
155
+	) {
156
+		$this->user = $user;
157
+		$this->database = $database;
158
+		$this->oauthProtocolHelper = $oauthProtocolHelper;
159
+
160
+		$this->linked = null;
161
+		$this->partiallyLinked = null;
162
+		$this->siteConfiguration = $siteConfiguration;
163
+
164
+		self::prepareTokenCountStatement($database);
165
+		$this->getTokenStatement = $this->database->prepare('SELECT * FROM oauthtoken WHERE user = :user AND type = :type');
166
+	}
167
+
168
+	/**
169
+	 * Determines if the user is fully connected to OAuth.
170
+	 *
171
+	 * @return bool
172
+	 */
173
+	public function isFullyLinked()
174
+	{
175
+		if ($this->linked === null) {
176
+			$this->linked = self::userIsFullyLinked($this->user, $this->database);
177
+		}
178
+
179
+		return $this->linked;
180
+	}
181
+
182
+	/**
183
+	 * Attempts to figure out if a user is partially linked to OAuth, and therefore needs to complete the OAuth
184
+	 * procedure before configuring.
185
+	 * @return bool
186
+	 */
187
+	public function isPartiallyLinked()
188
+	{
189
+		if ($this->partiallyLinked === null) {
190
+			$this->partiallyLinked = self::userIsPartiallyLinked($this->user, $this->database);
191
+		}
192
+
193
+		return $this->partiallyLinked;
194
+	}
195
+
196
+	/**
197
+	 * @throws OAuthException
198
+	 */
199
+	public function refreshIdentity()
200
+	{
201
+		$this->loadIdentity();
202
+
203
+		if ($this->identity === null) {
204
+			$this->identity = new OAuthIdentity();
205
+			$this->identity->setUserId($this->user->getId());
206
+			$this->identity->setDatabase($this->database);
207
+		}
208
+
209
+		$token = $this->loadAccessToken();
210
+
211
+		$rawTicket = $this->oauthProtocolHelper->getIdentityTicket($token->getToken(), $token->getSecret());
212
+
213
+		$this->identity->populate($rawTicket);
214
+
215
+		if (!$this->identityIsValid()) {
216
+			throw new OAuthException('Identity ticket is not valid!');
217
+		}
218
+
219
+		$this->identity->save();
220
+
221
+		$this->user->setOnWikiName($this->identity->getUsername());
222
+		$this->user->save();
223
+	}
224
+
225
+	public function getRequestToken()
226
+	{
227
+		$token = $this->oauthProtocolHelper->getRequestToken();
228
+
229
+		$this->partiallyLinked = true;
230
+		$this->linked = false;
231
+
232
+		$this->database
233
+			->prepare('DELETE FROM oauthtoken WHERE user = :user AND type = :type')
234
+			->execute(array(':user' => $this->user->getId(), ':type' => self::TOKEN_REQUEST));
235
+
236
+		$this->database
237
+			->prepare('INSERT INTO oauthtoken (user, type, token, secret, expiry) VALUES (:user, :type, :token, :secret, DATE_ADD(NOW(), INTERVAL 1 DAY))')
238
+			->execute(array(
239
+				':user'   => $this->user->getId(),
240
+				':type'   => self::TOKEN_REQUEST,
241
+				':token'  => $token->key,
242
+				':secret' => $token->secret,
243
+			));
244
+
245
+		return $this->oauthProtocolHelper->getAuthoriseUrl($token->key);
246
+	}
247
+
248
+	public function completeHandshake($verificationToken)
249
+	{
250
+		$this->getTokenStatement->execute(array(':user' => $this->user->getId(), ':type' => self::TOKEN_REQUEST));
251
+
252
+		/** @var OAuthToken $token */
253
+		$token = $this->getTokenStatement->fetchObject(OAuthToken::class);
254
+		$this->getTokenStatement->closeCursor();
255
+
256
+		if ($token === false) {
257
+			throw new ApplicationLogicException('Cannot find request token');
258
+		}
259
+
260
+		$token->setDatabase($this->database);
261
+
262
+		$accessToken = $this->oauthProtocolHelper->callbackCompleted($token->getToken(), $token->getSecret(),
263
+			$verificationToken);
264
+
265
+		$clearStatement = $this->database->prepare('DELETE FROM oauthtoken WHERE user = :u AND type = :t');
266
+		$clearStatement->execute(array(':u' => $this->user->getId(), ':t' => self::TOKEN_ACCESS));
267
+
268
+		$token->setToken($accessToken->key);
269
+		$token->setSecret($accessToken->secret);
270
+		$token->setType(self::TOKEN_ACCESS);
271
+		$token->setExpiry(null);
272
+		$token->save();
273
+
274
+		$this->partiallyLinked = false;
275
+		$this->linked = true;
276
+
277
+		$this->refreshIdentity();
278
+	}
279
+
280
+	public function detach()
281
+	{
282
+		$this->loadIdentity();
283
+
284
+		$this->identity->delete();
285
+		$statement = $this->database->prepare('DELETE FROM oauthtoken WHERE user = :user');
286
+		$statement->execute(array(':user' => $this->user->getId()));
287
+
288
+		$this->identity = null;
289
+		$this->linked = false;
290
+		$this->partiallyLinked = false;
291
+	}
292
+
293
+	/**
294
+	 * @param bool $expiredOk
295
+	 *
296
+	 * @return OAuthIdentity
297
+	 * @throws OAuthException
298
+	 */
299
+	public function getIdentity($expiredOk = false)
300
+	{
301
+		$this->loadIdentity();
302
+
303
+		if (!$this->identityIsValid($expiredOk)) {
304
+			throw new OAuthException('Stored identity is not valid.');
305
+		}
306
+
307
+		return $this->identity;
308
+	}
309
+
310
+	public function doApiCall($params, $method)
311
+	{
312
+		// Ensure we're logged in
313
+		$params['assert'] = 'user';
314
+
315
+		$token = $this->loadAccessToken();
316
+		return $this->oauthProtocolHelper->apiCall($params, $token->getToken(), $token->getSecret(), $method);
317
+	}
318
+
319
+	/**
320
+	 * @param bool $expiredOk
321
+	 *
322
+	 * @return bool
323
+	 */
324
+	private function identityIsValid($expiredOk = false)
325
+	{
326
+		$this->loadIdentity();
327
+
328
+		if ($this->identity === null) {
329
+			return false;
330
+		}
331
+
332
+		if ($this->identity->getIssuedAtTime() === false
333
+			|| $this->identity->getExpirationTime() === false
334
+			|| $this->identity->getAudience() === false
335
+			|| $this->identity->getIssuer() === false
336
+		) {
337
+			// this isn't populated properly.
338
+			return false;
339
+		}
340
+
341
+		$issue = DateTimeImmutable::createFromFormat("U", $this->identity->getIssuedAtTime());
342
+		$now = new DateTimeImmutable();
343
+
344
+		if ($issue > $now) {
345
+			// wat.
346
+			return false;
347
+		}
348
+
349
+		if ($this->identityExpired() && !$expiredOk) {
350
+			// soz.
351
+			return false;
352
+		}
353
+
354
+		if ($this->identity->getAudience() !== $this->siteConfiguration->getOAuthConsumerToken()) {
355
+			// token not issued for us
356
+			return false;
357
+		}
358
+
359
+		if ($this->identity->getIssuer() !== $this->siteConfiguration->getOauthMediaWikiCanonicalServer()) {
360
+			// token not issued by the right person
361
+			return false;
362
+		}
363
+
364
+		// can't find a reason to not trust it
365
+		return true;
366
+	}
367
+
368
+	/**
369
+	 * @return bool
370
+	 */
371
+	public function identityExpired()
372
+	{
373
+		// allowed max age
374
+		$gracePeriod = $this->siteConfiguration->getOauthIdentityGraceTime();
375
+
376
+		$expiry = DateTimeImmutable::createFromFormat("U", $this->identity->getExpirationTime());
377
+		$graceExpiry = $expiry->modify($gracePeriod);
378
+		$now = new DateTimeImmutable();
379
+
380
+		return $graceExpiry < $now;
381
+	}
382
+
383
+	/**
384
+	 * Loads the OAuth identity from the database for the current user.
385
+	 */
386
+	private function loadIdentity()
387
+	{
388
+		if ($this->identityLoaded) {
389
+			return;
390
+		}
391
+
392
+		$statement = $this->database->prepare('SELECT * FROM oauthidentity WHERE user = :user');
393
+		$statement->execute(array(':user' => $this->user->getId()));
394
+		/** @var OAuthIdentity $obj */
395
+		$obj = $statement->fetchObject(OAuthIdentity::class);
396
+
397
+		if ($obj === false) {
398
+			// failed to load identity.
399
+			$this->identityLoaded = true;
400
+			$this->identity = null;
401
+
402
+			return;
403
+		}
404
+
405
+		$obj->setDatabase($this->database);
406
+		$this->identityLoaded = true;
407
+		$this->identity = $obj;
408
+	}
409
+
410
+	/**
411
+	 * @return OAuthToken
412
+	 * @throws OAuthException
413
+	 */
414
+	private function loadAccessToken()
415
+	{
416
+		if (!$this->accessTokenLoaded) {
417
+			$this->getTokenStatement->execute(array(':user' => $this->user->getId(), ':type' => self::TOKEN_ACCESS));
418
+			/** @var OAuthToken $token */
419
+			$token = $this->getTokenStatement->fetchObject(OAuthToken::class);
420
+			$this->getTokenStatement->closeCursor();
421
+
422
+			if ($token === false) {
423
+				throw new OAuthException('Access token not found!');
424
+			}
425
+
426
+			$this->accessToken = $token;
427
+			$this->accessTokenLoaded = true;
428
+		}
429
+
430
+		return $this->accessToken;
431
+	}
432 432
 }
433 433
\ No newline at end of file
Please login to merge, or discard this patch.