LoginController::showLoginForm()   F
last analyzed

Complexity

Conditions 22
Paths 1281

Size

Total Lines 77

Duplication

Lines 14
Ratio 18.18 %

Importance

Changes 0
Metric Value
cc 22
nc 1281
nop 3
dl 14
loc 77
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Christoph Wurst <[email protected]>
4
 * @author Joas Schilling <[email protected]>
5
 * @author Lukas Reschke <[email protected]>
6
 * @author Semih Serhat Karakaya <[email protected]>
7
 * @author Thomas Müller <[email protected]>
8
 *
9
 * @copyright Copyright (c) 2018, ownCloud GmbH
10
 * @license AGPL-3.0
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
26
namespace OC\Core\Controller;
27
28
use OC\Authentication\TwoFactorAuth\Manager;
29
use OC\User\Session;
30
use OC_App;
31
use OC_Util;
32
use OCP\AppFramework\Controller;
33
use OCP\AppFramework\Http\RedirectResponse;
34
use OCP\AppFramework\Http\TemplateResponse;
35
use OCP\IConfig;
36
use OCP\IRequest;
37
use OCP\ISession;
38
use OCP\IURLGenerator;
39
use OCP\IUser;
40
use OCP\IUserManager;
41
42
class LoginController extends Controller {
43
44
	/** @var IUserManager */
45
	private $userManager;
46
47
	/** @var IConfig */
48
	private $config;
49
50
	/** @var ISession */
51
	private $session;
52
53
	/** @var Session */
54
	private $userSession;
55
56
	/** @var IURLGenerator */
57
	private $urlGenerator;
58
59
	/** @var Manager */
60
	private $twoFactorManager;
61
62
	/**
63
	 * @param string $appName
64
	 * @param IRequest $request
65
	 * @param IUserManager $userManager
66
	 * @param IConfig $config
67
	 * @param ISession $session
68
	 * @param Session $userSession
69
	 * @param IURLGenerator $urlGenerator
70
	 * @param Manager $twoFactorManager
71
	 */
72
	public function __construct($appName, IRequest $request, IUserManager $userManager, IConfig $config, ISession $session,
73
		Session $userSession, IURLGenerator $urlGenerator, Manager $twoFactorManager) {
74
		parent::__construct($appName, $request);
75
		$this->userManager = $userManager;
76
		$this->config = $config;
77
		$this->session = $session;
78
		$this->userSession = $userSession;
79
		$this->urlGenerator = $urlGenerator;
80
		$this->twoFactorManager = $twoFactorManager;
81
	}
82
83
	/**
84
	 * @NoAdminRequired
85
	 * @UseSession
86
	 *
87
	 * @return RedirectResponse
88
	 */
89 View Code Duplication
	public function logout() {
90
		$loginToken = $this->request->getCookie('oc_token');
91
		if ($loginToken !== null) {
92
			$this->config->deleteUserValue($this->userSession->getUser()->getUID(), 'login_token', $loginToken);
93
		}
94
		$this->userSession->logout();
95
96
		return new RedirectResponse($this->urlGenerator->linkToRouteAbsolute('core.login.showLoginForm'));
97
	}
98
99
	/**
100
	 * @PublicPage
101
	 * @NoCSRFRequired
102
	 * @UseSession
103
	 *
104
	 * @param string $user
105
	 * @param string $redirect_url
106
	 * @param string $remember_login
107
	 *
108
	 * @return TemplateResponse|RedirectResponse
109
	 */
110
	public function showLoginForm($user, $redirect_url, $remember_login) {
111
		if (\OC_User::handleApacheAuth() || $this->userSession->isLoggedIn()) {
112
			return new RedirectResponse($this->getDefaultUrl());
113
		}
114
115
		$parameters = [];
116
		$loginMessages = $this->session->get('loginMessages');
117
		$errors = [];
118
		$messages = [];
119
		if (\is_array($loginMessages)) {
120
			list($errors, $messages) = $loginMessages;
121
		}
122
		$this->session->remove('loginMessages');
123
		foreach ($errors as $value) {
124
			$parameters[$value] = true;
125
		}
126
127
		$parameters['messages'] = $messages;
128 View Code Duplication
		if ($user !== null && $user !== '') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
			$parameters['loginName'] = $user;
130
			$parameters['user_autofocus'] = false;
131
		} else {
132
			$parameters['loginName'] = '';
133
			$parameters['user_autofocus'] = true;
134
		}
135
		if (!empty($redirect_url)) {
136
			$parameters['redirect_url'] = $redirect_url;
137
		}
138
139
		$parameters['canResetPassword'] = true;
140
		$parameters['resetPasswordLink'] = $this->config->getSystemValue('lost_password_link', '');
141
		if (!$parameters['resetPasswordLink']) {
142
			if ($user !== null && $user !== '') {
143
				$userObj = $this->userManager->get($user);
144
				if ($userObj instanceof IUser) {
145
					$parameters['canResetPassword'] = $userObj->canChangePassword();
146
				}
147
			}
148
		} elseif ($parameters['resetPasswordLink'] === 'disabled') {
149
			$parameters['canResetPassword'] = false;
150
		}
151
152
		$altLogins = OC_App::getAlternativeLogIns();
153
		$altLogins2 = $this->config->getSystemValue('login.alternatives');
154
		if (\is_array($altLogins2) && !empty($altLogins2)) {
155
			$altLogins = \array_merge($altLogins, $altLogins2);
156
		}
157
		$parameters['alt_login'] = $altLogins;
158
		$parameters['rememberLoginAllowed'] = OC_Util::rememberLoginAllowed();
159
		$parameters['rememberLoginState'] = !empty($remember_login) ? $remember_login : 0;
160
161 View Code Duplication
		if ($user !== null && $user !== '') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
162
			$parameters['loginName'] = $user;
163
			$parameters['user_autofocus'] = false;
164
		} else {
165
			$parameters['loginName'] = '';
166
			$parameters['user_autofocus'] = true;
167
		}
168
169
		/**
170
		 * If redirect_url is not empty and remember_login is null and
171
		 * user not logged in and check if the string
172
		 * webroot+"/index.php/f/" is in redirect_url then
173
		 * user is trying to access files for which he needs to login.
174
		 */
175
176
		if (!empty($redirect_url) && ($remember_login === null) &&
177
			($this->userSession->isLoggedIn() === false) &&
178
			(\strpos($this->urlGenerator->getAbsoluteURL(\urldecode($redirect_url)),
179
				$this->urlGenerator->getAbsoluteURL('/index.php/f/')) !== false)) {
180
			$parameters['accessLink'] = true;
181
		}
182
183
		return new TemplateResponse(
184
			$this->appName, 'login', $parameters, 'guest'
185
		);
186
	}
187
188
	/**
189
	 * @PublicPage
190
	 * @UseSession
191
	 *
192
	 * @param string $user
193
	 * @param string $password
194
	 * @param string $redirect_url
195
	 * @param string $timezone
196
	 * @return RedirectResponse
197
	 * @throws \OCP\PreConditionNotMetException
198
	 * @throws \OC\User\LoginException
199
	 */
200
	public function tryLogin($user, $password, $redirect_url, $timezone = null) {
201
		$originalUser = $user;
202
		// TODO: Add all the insane error handling
203
		$loginResult = $this->userSession->login($user, $password);
204
		if ($loginResult !== true) {
205
			$users = $this->userManager->getByEmail($user);
206
			// we only allow login by email if unique
207
			if (\count($users) === 1) {
208
				$user = $users[0]->getUID();
209
				$loginResult = $this->userSession->login($user, $password);
210
			}
211
		}
212
		if ($loginResult !== true) {
213
			$this->session->set('loginMessages', [
214
				['invalidpassword'], []
215
			]);
216
			$args = [];
217
			// Read current user and append if possible - we need to return the unmodified user otherwise we will leak the login name
218
			if ($user !== null) {
219
				$args['user'] = $originalUser;
220
			}
221
			// keep the redirect url
222
			if (!empty($redirect_url)) {
223
				$args['redirect_url'] = $redirect_url;
224
			}
225
			return new RedirectResponse($this->urlGenerator->linkToRoute('core.login.showLoginForm', $args));
226
		}
227
		/* @var $userObject IUser */
228
		$userObject = $this->userSession->getUser();
229
		// TODO: remove password checks from above and let the user session handle failures
230
		// requires https://github.com/owncloud/core/pull/24616
231
		$this->userSession->createSessionToken($this->request, $userObject->getUID(), $user, $password);
232
233
		// User has successfully logged in, now remove the password reset link, when it is available
234
		$this->config->deleteUserValue($userObject->getUID(), 'owncloud', 'lostpassword');
235
236
		// Save the timezone
237
		if ($timezone !== null) {
238
			$this->config->setUserValue($userObject->getUID(), 'core', 'timezone', $timezone);
239
		}
240
241
		if ($this->twoFactorManager->isTwoFactorAuthenticated($userObject)) {
242
			$this->twoFactorManager->prepareTwoFactorLogin($userObject);
243
			if ($redirect_url !== null) {
244
				return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge', [
245
					'redirect_url' => $redirect_url
246
				]));
247
			}
248
			return new RedirectResponse($this->urlGenerator->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
249
		}
250
251
		if ($redirect_url !== null && $this->userSession->isLoggedIn()) {
252
			$location = $this->urlGenerator->getAbsoluteURL(\urldecode($redirect_url));
253
			// Deny the redirect if the URL contains a @
254
			// This prevents unvalidated redirects like ?redirect_url=:[email protected]
255
			if (\strpos($location, '@') === false) {
256
				return new RedirectResponse($location);
257
			}
258
		}
259
260
		return new RedirectResponse($this->getDefaultUrl());
261
	}
262
263
	/**
264
	 * @return string
265
	 */
266
	protected function getDefaultUrl() {
267
		return OC_Util::getDefaultPageUrl();
268
	}
269
270
	/**
271
	 * @return ISession
272
	 */
273
	public function getSession() {
274
		return $this->session;
275
	}
276
}
277