Failed Conditions
Push — newinternal-releasecandidate ( a30d14...06bb07 )
by Simon
08:31
created
includes/Pages/PageSearch.php 1 patch
Indentation   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -20,155 +20,155 @@
 block discarded – undo
20 20
 
21 21
 class PageSearch extends InternalPageBase
22 22
 {
23
-    /**
24
-     * Main function for this page, when no specific actions are called.
25
-     */
26
-    protected function main()
27
-    {
28
-        $this->setHtmlTitle('Search');
29
-
30
-        // Dual-mode page
31
-        if (WebRequest::wasPosted()) {
32
-            $this->validateCSRFToken();
33
-
34
-            $searchType = WebRequest::postString('type');
35
-            $searchTerm = WebRequest::postString('term');
36
-
37
-            $validationError = "";
38
-            if (!$this->validateSearchParameters($searchType, $searchTerm, $validationError)) {
39
-                SessionAlert::error($validationError, "Search error");
40
-                $this->redirect("search");
41
-
42
-                return;
43
-            }
44
-
45
-            $results = array();
46
-
47
-            switch ($searchType) {
48
-                case 'name':
49
-                    $results = $this->getNameSearchResults($searchTerm);
50
-                    break;
51
-                case 'email':
52
-                    $results = $this->getEmailSearchResults($searchTerm);
53
-                    break;
54
-                case 'ip':
55
-                    $results = $this->getIpSearchResults($searchTerm);
56
-                    break;
57
-            }
58
-
59
-            // deal with results
60
-            $this->assign('requests', $results);
61
-            $this->assign('term', $searchTerm);
62
-            $this->assign('target', $searchType);
63
-
64
-            $userIds = array_map(
65
-                function(Request $entry) {
66
-                    return $entry->getReserved();
67
-                },
68
-                $results);
69
-            $userList = UserSearchHelper::get($this->getDatabase())->inIds($userIds)->fetchMap('username');
70
-            $this->assign('userlist', $userList);
71
-
72
-            $currentUser = User::getCurrent($this->getDatabase());
73
-            $this->assign('canBan', $this->barrierTest('set', $currentUser, PageBan::class));
74
-            $this->assign('canBreakReservation', $this->barrierTest('force', $currentUser, PageBreakReservation::class));
75
-
76
-            $this->assignCSRFToken();
77
-            $this->setTemplate('search/searchResult.tpl');
78
-        }
79
-        else {
80
-            $this->assignCSRFToken();
81
-            $this->setTemplate('search/searchForm.tpl');
82
-        }
83
-    }
84
-
85
-    /**
86
-     * Gets search results by name
87
-     *
88
-     * @param string $searchTerm
89
-     *
90
-     * @returns Request[]
91
-     */
92
-    private function getNameSearchResults($searchTerm)
93
-    {
94
-        $padded = '%' . $searchTerm . '%';
95
-
96
-        /** @var Request[] $requests */
97
-        $requests = RequestSearchHelper::get($this->getDatabase())
98
-            ->byName($padded)
99
-            ->fetch();
100
-
101
-        return $requests;
102
-    }
103
-
104
-    /**
105
-     * Gets search results by email
106
-     *
107
-     * @param string $searchTerm
108
-     *
109
-     * @return Request[]
110
-     * @throws ApplicationLogicException
111
-     */
112
-    private function getEmailSearchResults($searchTerm)
113
-    {
114
-        if ($searchTerm === "@") {
115
-            throw new ApplicationLogicException('The search term "@" is not valid for email address searches!');
116
-        }
117
-
118
-        $padded = '%' . $searchTerm . '%';
119
-
120
-        /** @var Request[] $requests */
121
-        $requests = RequestSearchHelper::get($this->getDatabase())
122
-            ->byEmailAddress($padded)
123
-            ->excludingPurgedData($this->getSiteConfiguration())
124
-            ->fetch();
125
-
126
-        return $requests;
127
-    }
128
-
129
-    /**
130
-     * Gets search results by IP address or XFF IP address
131
-     *
132
-     * @param string $searchTerm
133
-     *
134
-     * @returns Request[]
135
-     */
136
-    private function getIpSearchResults($searchTerm)
137
-    {
138
-        /** @var Request[] $requests */
139
-        $requests = RequestSearchHelper::get($this->getDatabase())
140
-            ->byIp($searchTerm)
141
-            ->excludingPurgedData($this->getSiteConfiguration())
142
-            ->fetch();
143
-
144
-        return $requests;
145
-    }
146
-
147
-    /**
148
-     * @param string $searchType
149
-     * @param string $searchTerm
150
-     *
151
-     * @param string $errorMessage
152
-     *
153
-     * @return bool true if parameters are valid
154
-     * @throws ApplicationLogicException
155
-     */
156
-    protected function validateSearchParameters($searchType, $searchTerm, &$errorMessage)
157
-    {
158
-        if (!in_array($searchType, array('name', 'email', 'ip'))) {
159
-            $errorMessage = 'Unknown search type';
160
-
161
-            return false;
162
-        }
163
-
164
-        if ($searchTerm === '%' || $searchTerm === '' || $searchTerm === null) {
165
-            $errorMessage = 'No search term specified entered';
166
-
167
-            return false;
168
-        }
169
-
170
-        $errorMessage = "";
171
-
172
-        return true;
173
-    }
23
+	/**
24
+	 * Main function for this page, when no specific actions are called.
25
+	 */
26
+	protected function main()
27
+	{
28
+		$this->setHtmlTitle('Search');
29
+
30
+		// Dual-mode page
31
+		if (WebRequest::wasPosted()) {
32
+			$this->validateCSRFToken();
33
+
34
+			$searchType = WebRequest::postString('type');
35
+			$searchTerm = WebRequest::postString('term');
36
+
37
+			$validationError = "";
38
+			if (!$this->validateSearchParameters($searchType, $searchTerm, $validationError)) {
39
+				SessionAlert::error($validationError, "Search error");
40
+				$this->redirect("search");
41
+
42
+				return;
43
+			}
44
+
45
+			$results = array();
46
+
47
+			switch ($searchType) {
48
+				case 'name':
49
+					$results = $this->getNameSearchResults($searchTerm);
50
+					break;
51
+				case 'email':
52
+					$results = $this->getEmailSearchResults($searchTerm);
53
+					break;
54
+				case 'ip':
55
+					$results = $this->getIpSearchResults($searchTerm);
56
+					break;
57
+			}
58
+
59
+			// deal with results
60
+			$this->assign('requests', $results);
61
+			$this->assign('term', $searchTerm);
62
+			$this->assign('target', $searchType);
63
+
64
+			$userIds = array_map(
65
+				function(Request $entry) {
66
+					return $entry->getReserved();
67
+				},
68
+				$results);
69
+			$userList = UserSearchHelper::get($this->getDatabase())->inIds($userIds)->fetchMap('username');
70
+			$this->assign('userlist', $userList);
71
+
72
+			$currentUser = User::getCurrent($this->getDatabase());
73
+			$this->assign('canBan', $this->barrierTest('set', $currentUser, PageBan::class));
74
+			$this->assign('canBreakReservation', $this->barrierTest('force', $currentUser, PageBreakReservation::class));
75
+
76
+			$this->assignCSRFToken();
77
+			$this->setTemplate('search/searchResult.tpl');
78
+		}
79
+		else {
80
+			$this->assignCSRFToken();
81
+			$this->setTemplate('search/searchForm.tpl');
82
+		}
83
+	}
84
+
85
+	/**
86
+	 * Gets search results by name
87
+	 *
88
+	 * @param string $searchTerm
89
+	 *
90
+	 * @returns Request[]
91
+	 */
92
+	private function getNameSearchResults($searchTerm)
93
+	{
94
+		$padded = '%' . $searchTerm . '%';
95
+
96
+		/** @var Request[] $requests */
97
+		$requests = RequestSearchHelper::get($this->getDatabase())
98
+			->byName($padded)
99
+			->fetch();
100
+
101
+		return $requests;
102
+	}
103
+
104
+	/**
105
+	 * Gets search results by email
106
+	 *
107
+	 * @param string $searchTerm
108
+	 *
109
+	 * @return Request[]
110
+	 * @throws ApplicationLogicException
111
+	 */
112
+	private function getEmailSearchResults($searchTerm)
113
+	{
114
+		if ($searchTerm === "@") {
115
+			throw new ApplicationLogicException('The search term "@" is not valid for email address searches!');
116
+		}
117
+
118
+		$padded = '%' . $searchTerm . '%';
119
+
120
+		/** @var Request[] $requests */
121
+		$requests = RequestSearchHelper::get($this->getDatabase())
122
+			->byEmailAddress($padded)
123
+			->excludingPurgedData($this->getSiteConfiguration())
124
+			->fetch();
125
+
126
+		return $requests;
127
+	}
128
+
129
+	/**
130
+	 * Gets search results by IP address or XFF IP address
131
+	 *
132
+	 * @param string $searchTerm
133
+	 *
134
+	 * @returns Request[]
135
+	 */
136
+	private function getIpSearchResults($searchTerm)
137
+	{
138
+		/** @var Request[] $requests */
139
+		$requests = RequestSearchHelper::get($this->getDatabase())
140
+			->byIp($searchTerm)
141
+			->excludingPurgedData($this->getSiteConfiguration())
142
+			->fetch();
143
+
144
+		return $requests;
145
+	}
146
+
147
+	/**
148
+	 * @param string $searchType
149
+	 * @param string $searchTerm
150
+	 *
151
+	 * @param string $errorMessage
152
+	 *
153
+	 * @return bool true if parameters are valid
154
+	 * @throws ApplicationLogicException
155
+	 */
156
+	protected function validateSearchParameters($searchType, $searchTerm, &$errorMessage)
157
+	{
158
+		if (!in_array($searchType, array('name', 'email', 'ip'))) {
159
+			$errorMessage = 'Unknown search type';
160
+
161
+			return false;
162
+		}
163
+
164
+		if ($searchTerm === '%' || $searchTerm === '' || $searchTerm === null) {
165
+			$errorMessage = 'No search term specified entered';
166
+
167
+			return false;
168
+		}
169
+
170
+		$errorMessage = "";
171
+
172
+		return true;
173
+	}
174 174
 }
Please login to merge, or discard this patch.
includes/Pages/UserAuth/PageForgotPassword.php 1 patch
Indentation   +204 added lines, -204 removed lines patch added patch discarded remove patch
@@ -22,208 +22,208 @@
 block discarded – undo
22 22
 
23 23
 class PageForgotPassword extends InternalPageBase
24 24
 {
25
-    /**
26
-     * Main function for this page, when no specific actions are called.
27
-     *
28
-     * This is the forgotten password reset form
29
-     * @category Security-Critical
30
-     */
31
-    protected function main()
32
-    {
33
-        if (WebRequest::wasPosted()) {
34
-            $this->validateCSRFToken();
35
-            $username = WebRequest::postString('username');
36
-            $email = WebRequest::postEmail('email');
37
-            $database = $this->getDatabase();
38
-
39
-            if ($username === null || trim($username) === "" || $email === null || trim($email) === "") {
40
-                throw new ApplicationLogicException("Both username and email address must be specified!");
41
-            }
42
-
43
-            $user = User::getByUsername($username, $database);
44
-            $this->sendResetMail($user, $email);
45
-
46
-            SessionAlert::success('<strong>Your password reset request has been completed.</strong> If the details you have provided match our records, you should receive an email shortly.');
47
-
48
-            $this->redirect('login');
49
-        }
50
-        else {
51
-            $this->assignCSRFToken();
52
-            $this->setTemplate('forgot-password/forgotpw.tpl');
53
-        }
54
-    }
55
-
56
-    /**
57
-     * Sends a reset email if the user is authenticated
58
-     *
59
-     * @param User|boolean $user  The user located from the database, or false. Doesn't really matter, since we do the
60
-     *                            check anyway within this method and silently skip if we don't have a user.
61
-     * @param string       $email The provided email address
62
-     */
63
-    private function sendResetMail($user, $email)
64
-    {
65
-        // If the user isn't found, or the email address is wrong, skip sending the details silently.
66
-        if (!$user instanceof User) {
67
-            return;
68
-        }
69
-
70
-        if (strtolower($user->getEmail()) === strtolower($email)) {
71
-            $clientIp = $this->getXffTrustProvider()
72
-                ->getTrustedClientIp(WebRequest::remoteAddress(), WebRequest::forwardedAddress());
73
-
74
-            $this->cleanExistingTokens($user);
75
-
76
-            $hash = Base32::encode(openssl_random_pseudo_bytes(30));
77
-
78
-            $encryptionHelper = new EncryptionHelper($this->getSiteConfiguration());
79
-
80
-            $cred = new Credential();
81
-            $cred->setDatabase($this->getDatabase());
82
-            $cred->setFactor(-1);
83
-            $cred->setUserId($user->getId());
84
-            $cred->setType('reset');
85
-            $cred->setData($encryptionHelper->encryptData($hash));
86
-            $cred->setVersion(0);
87
-            $cred->setDisabled(0);
88
-            $cred->setTimeout(new DateTimeImmutable('+ 1 hour'));
89
-            $cred->setPriority(9);
90
-            $cred->save();
91
-
92
-            $this->assign("user", $user);
93
-            $this->assign("hash", $hash);
94
-            $this->assign("remoteAddress", $clientIp);
95
-
96
-            $emailContent = $this->fetchTemplate('forgot-password/reset-mail.tpl');
97
-
98
-            $this->getEmailHelper()->sendMail($user->getEmail(), "WP:ACC password reset", $emailContent);
99
-        }
100
-    }
101
-
102
-    /**
103
-     * Entry point for the reset action
104
-     *
105
-     * This is the reset password part of the form.
106
-     * @category Security-Critical
107
-     */
108
-    protected function reset()
109
-    {
110
-        $si = WebRequest::getString('si');
111
-        $id = WebRequest::getString('id');
112
-
113
-        if ($si === null || trim($si) === "" || $id === null || trim($id) === "") {
114
-            throw new ApplicationLogicException("Link not valid, please ensure it has copied correctly");
115
-        }
116
-
117
-        $database = $this->getDatabase();
118
-        $user = $this->getResettingUser($id, $database, $si);
119
-
120
-        // Dual mode
121
-        if (WebRequest::wasPosted()) {
122
-            $this->validateCSRFToken();
123
-            try {
124
-                $this->doReset($user);
125
-                $this->cleanExistingTokens($user);
126
-            }
127
-            catch (ApplicationLogicException $ex) {
128
-                SessionAlert::error($ex->getMessage());
129
-                $this->redirect('forgotPassword', 'reset', array('si' => $si, 'id' => $id));
130
-
131
-                return;
132
-            }
133
-        }
134
-        else {
135
-            $this->assignCSRFToken();
136
-            $this->assign('user', $user);
137
-            $this->setTemplate('forgot-password/forgotpwreset.tpl');
138
-        }
139
-    }
140
-
141
-    /**
142
-     * Gets the user resetting their password from the database, or throwing an exception if that is not possible.
143
-     *
144
-     * @param integer     $id       The ID of the user to retrieve
145
-     * @param PdoDatabase $database The database object to use
146
-     * @param string      $si       The reset hash provided
147
-     *
148
-     * @return User
149
-     * @throws ApplicationLogicException
150
-     */
151
-    private function getResettingUser($id, $database, $si)
152
-    {
153
-        $user = User::getById($id, $database);
154
-
155
-        if ($user === false ||  $user->isCommunityUser()) {
156
-            throw new ApplicationLogicException("Password reset failed. Please try again.");
157
-        }
158
-
159
-        $statement = $database->prepare("SELECT * FROM credential WHERE type = 'reset' AND user = :user;");
160
-        $statement->execute([':user' => $user->getId()]);
161
-
162
-        /** @var Credential $credential */
163
-        $credential = $statement->fetchObject(Credential::class);
164
-
165
-        $statement->closeCursor();
166
-
167
-        if ($credential === false) {
168
-            throw new ApplicationLogicException("Password reset failed. Please try again.");
169
-        }
170
-
171
-        $credential->setDatabase($database);
172
-
173
-        $encryptionHelper = new EncryptionHelper($this->getSiteConfiguration());
174
-        if ($encryptionHelper->decryptData($credential->getData()) != $si) {
175
-            throw new ApplicationLogicException("Password reset failed. Please try again.");
176
-        }
177
-
178
-        if ($credential->getTimeout() < new DateTimeImmutable()) {
179
-            $credential->delete();
180
-            throw new ApplicationLogicException("Password reset token expired. Please try again.");
181
-        }
182
-
183
-        return $user;
184
-    }
185
-
186
-    /**
187
-     * Performs the setting of the new password
188
-     *
189
-     * @param User $user The user to set the password for
190
-     *
191
-     * @throws ApplicationLogicException
192
-     */
193
-    private function doReset(User $user)
194
-    {
195
-        $pw = WebRequest::postString('pw');
196
-        $pw2 = WebRequest::postString('pw2');
197
-
198
-        if ($pw !== $pw2) {
199
-            throw new ApplicationLogicException('Passwords do not match!');
200
-        }
201
-
202
-        $passwordCredentialProvider = new PasswordCredentialProvider($user->getDatabase(), $this->getSiteConfiguration());
203
-        $passwordCredentialProvider->setCredential($user, 1, $pw);
204
-
205
-        SessionAlert::success('You may now log in!');
206
-        $this->redirect('login');
207
-    }
208
-
209
-    protected function isProtectedPage()
210
-    {
211
-        return false;
212
-    }
213
-
214
-    /**
215
-     * @param $user
216
-     */
217
-    private function cleanExistingTokens($user): void
218
-    {
219
-        // clean out existing reset tokens
220
-        $statement = $this->getDatabase()->prepare("SELECT * FROM credential WHERE type = 'reset' AND user = :user;");
221
-        $statement->execute([':user' => $user->getId()]);
222
-        $existing = $statement->fetchAll(PdoDatabase::FETCH_CLASS, Credential::class);
223
-
224
-        foreach ($existing as $c) {
225
-            $c->setDatabase($this->getDatabase());
226
-            $c->delete();
227
-        }
228
-    }
25
+	/**
26
+	 * Main function for this page, when no specific actions are called.
27
+	 *
28
+	 * This is the forgotten password reset form
29
+	 * @category Security-Critical
30
+	 */
31
+	protected function main()
32
+	{
33
+		if (WebRequest::wasPosted()) {
34
+			$this->validateCSRFToken();
35
+			$username = WebRequest::postString('username');
36
+			$email = WebRequest::postEmail('email');
37
+			$database = $this->getDatabase();
38
+
39
+			if ($username === null || trim($username) === "" || $email === null || trim($email) === "") {
40
+				throw new ApplicationLogicException("Both username and email address must be specified!");
41
+			}
42
+
43
+			$user = User::getByUsername($username, $database);
44
+			$this->sendResetMail($user, $email);
45
+
46
+			SessionAlert::success('<strong>Your password reset request has been completed.</strong> If the details you have provided match our records, you should receive an email shortly.');
47
+
48
+			$this->redirect('login');
49
+		}
50
+		else {
51
+			$this->assignCSRFToken();
52
+			$this->setTemplate('forgot-password/forgotpw.tpl');
53
+		}
54
+	}
55
+
56
+	/**
57
+	 * Sends a reset email if the user is authenticated
58
+	 *
59
+	 * @param User|boolean $user  The user located from the database, or false. Doesn't really matter, since we do the
60
+	 *                            check anyway within this method and silently skip if we don't have a user.
61
+	 * @param string       $email The provided email address
62
+	 */
63
+	private function sendResetMail($user, $email)
64
+	{
65
+		// If the user isn't found, or the email address is wrong, skip sending the details silently.
66
+		if (!$user instanceof User) {
67
+			return;
68
+		}
69
+
70
+		if (strtolower($user->getEmail()) === strtolower($email)) {
71
+			$clientIp = $this->getXffTrustProvider()
72
+				->getTrustedClientIp(WebRequest::remoteAddress(), WebRequest::forwardedAddress());
73
+
74
+			$this->cleanExistingTokens($user);
75
+
76
+			$hash = Base32::encode(openssl_random_pseudo_bytes(30));
77
+
78
+			$encryptionHelper = new EncryptionHelper($this->getSiteConfiguration());
79
+
80
+			$cred = new Credential();
81
+			$cred->setDatabase($this->getDatabase());
82
+			$cred->setFactor(-1);
83
+			$cred->setUserId($user->getId());
84
+			$cred->setType('reset');
85
+			$cred->setData($encryptionHelper->encryptData($hash));
86
+			$cred->setVersion(0);
87
+			$cred->setDisabled(0);
88
+			$cred->setTimeout(new DateTimeImmutable('+ 1 hour'));
89
+			$cred->setPriority(9);
90
+			$cred->save();
91
+
92
+			$this->assign("user", $user);
93
+			$this->assign("hash", $hash);
94
+			$this->assign("remoteAddress", $clientIp);
95
+
96
+			$emailContent = $this->fetchTemplate('forgot-password/reset-mail.tpl');
97
+
98
+			$this->getEmailHelper()->sendMail($user->getEmail(), "WP:ACC password reset", $emailContent);
99
+		}
100
+	}
101
+
102
+	/**
103
+	 * Entry point for the reset action
104
+	 *
105
+	 * This is the reset password part of the form.
106
+	 * @category Security-Critical
107
+	 */
108
+	protected function reset()
109
+	{
110
+		$si = WebRequest::getString('si');
111
+		$id = WebRequest::getString('id');
112
+
113
+		if ($si === null || trim($si) === "" || $id === null || trim($id) === "") {
114
+			throw new ApplicationLogicException("Link not valid, please ensure it has copied correctly");
115
+		}
116
+
117
+		$database = $this->getDatabase();
118
+		$user = $this->getResettingUser($id, $database, $si);
119
+
120
+		// Dual mode
121
+		if (WebRequest::wasPosted()) {
122
+			$this->validateCSRFToken();
123
+			try {
124
+				$this->doReset($user);
125
+				$this->cleanExistingTokens($user);
126
+			}
127
+			catch (ApplicationLogicException $ex) {
128
+				SessionAlert::error($ex->getMessage());
129
+				$this->redirect('forgotPassword', 'reset', array('si' => $si, 'id' => $id));
130
+
131
+				return;
132
+			}
133
+		}
134
+		else {
135
+			$this->assignCSRFToken();
136
+			$this->assign('user', $user);
137
+			$this->setTemplate('forgot-password/forgotpwreset.tpl');
138
+		}
139
+	}
140
+
141
+	/**
142
+	 * Gets the user resetting their password from the database, or throwing an exception if that is not possible.
143
+	 *
144
+	 * @param integer     $id       The ID of the user to retrieve
145
+	 * @param PdoDatabase $database The database object to use
146
+	 * @param string      $si       The reset hash provided
147
+	 *
148
+	 * @return User
149
+	 * @throws ApplicationLogicException
150
+	 */
151
+	private function getResettingUser($id, $database, $si)
152
+	{
153
+		$user = User::getById($id, $database);
154
+
155
+		if ($user === false ||  $user->isCommunityUser()) {
156
+			throw new ApplicationLogicException("Password reset failed. Please try again.");
157
+		}
158
+
159
+		$statement = $database->prepare("SELECT * FROM credential WHERE type = 'reset' AND user = :user;");
160
+		$statement->execute([':user' => $user->getId()]);
161
+
162
+		/** @var Credential $credential */
163
+		$credential = $statement->fetchObject(Credential::class);
164
+
165
+		$statement->closeCursor();
166
+
167
+		if ($credential === false) {
168
+			throw new ApplicationLogicException("Password reset failed. Please try again.");
169
+		}
170
+
171
+		$credential->setDatabase($database);
172
+
173
+		$encryptionHelper = new EncryptionHelper($this->getSiteConfiguration());
174
+		if ($encryptionHelper->decryptData($credential->getData()) != $si) {
175
+			throw new ApplicationLogicException("Password reset failed. Please try again.");
176
+		}
177
+
178
+		if ($credential->getTimeout() < new DateTimeImmutable()) {
179
+			$credential->delete();
180
+			throw new ApplicationLogicException("Password reset token expired. Please try again.");
181
+		}
182
+
183
+		return $user;
184
+	}
185
+
186
+	/**
187
+	 * Performs the setting of the new password
188
+	 *
189
+	 * @param User $user The user to set the password for
190
+	 *
191
+	 * @throws ApplicationLogicException
192
+	 */
193
+	private function doReset(User $user)
194
+	{
195
+		$pw = WebRequest::postString('pw');
196
+		$pw2 = WebRequest::postString('pw2');
197
+
198
+		if ($pw !== $pw2) {
199
+			throw new ApplicationLogicException('Passwords do not match!');
200
+		}
201
+
202
+		$passwordCredentialProvider = new PasswordCredentialProvider($user->getDatabase(), $this->getSiteConfiguration());
203
+		$passwordCredentialProvider->setCredential($user, 1, $pw);
204
+
205
+		SessionAlert::success('You may now log in!');
206
+		$this->redirect('login');
207
+	}
208
+
209
+	protected function isProtectedPage()
210
+	{
211
+		return false;
212
+	}
213
+
214
+	/**
215
+	 * @param $user
216
+	 */
217
+	private function cleanExistingTokens($user): void
218
+	{
219
+		// clean out existing reset tokens
220
+		$statement = $this->getDatabase()->prepare("SELECT * FROM credential WHERE type = 'reset' AND user = :user;");
221
+		$statement->execute([':user' => $user->getId()]);
222
+		$existing = $statement->fetchAll(PdoDatabase::FETCH_CLASS, Credential::class);
223
+
224
+		foreach ($existing as $c) {
225
+			$c->setDatabase($this->getDatabase());
226
+			$c->delete();
227
+		}
228
+	}
229 229
 }
Please login to merge, or discard this patch.