Completed
Push — master ( b04a4a...6281d7 )
by Sujith
32s
created

ResetPassword::execute()   D

Complexity

Conditions 16
Paths 19

Size

Total Lines 81

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
nc 19
nop 2
dl 0
loc 81
rs 4.8678
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 Andreas Fischer <[email protected]>
4
 * @author Christopher Schäpers <[email protected]>
5
 * @author Clark Tomlinson <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Laurens Post <[email protected]>
8
 * @author Morris Jobke <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 * @author Sujith Haridasan <[email protected]>
11
 *
12
 * @copyright Copyright (c) 2018, ownCloud GmbH
13
 * @license AGPL-3.0
14
 *
15
 * This code is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License, version 3,
17
 * as published by the Free Software Foundation.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License, version 3,
25
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
26
 *
27
 */
28
29
namespace OC\Core\Command\User;
30
31
use OC\Core\Controller\LostController;
32
use OC\Helper\EnvironmentHelper;
33
use OCP\AppFramework\Utility\ITimeFactory;
34
use OCP\IConfig;
35
use OCP\IL10N;
36
use OCP\IURLGenerator;
37
use OCP\IUserManager;
38
use OCP\Mail\IMailer;
39
use OCP\Security\ISecureRandom;
40
use OCP\Util;
41
use Symfony\Component\Console\Command\Command;
42
use Symfony\Component\Console\Input\InputInterface;
43
use Symfony\Component\Console\Input\InputArgument;
44
use Symfony\Component\Console\Input\InputOption;
45
use Symfony\Component\Console\Output\OutputInterface;
46
use Symfony\Component\Console\Question\Question;
47
48
class ResetPassword extends Command {
49
50
	/** @var IUserManager */
51
	protected $userManager;
52
	/** @var IConfig  */
53
	private $config;
54
	/** @var ITimeFactory */
55
	private $timeFactory;
56
	/** @var EnvironmentHelper  */
57
	private $environmentHelper;
58
	/** @var LostController */
59
	private $lostController;
60
61
	public function __construct(IUserManager $userManager,
62
						IConfig $config,
63
						ITimeFactory $timeFactory,
64
						EnvironmentHelper $environmentHelper,
65
						LostController $lostController) {
66
		$this->userManager = $userManager;
67
		$this->config = $config;
68
		$this->timeFactory = $timeFactory;
69
		$this->environmentHelper = $environmentHelper;
70
		$this->lostController = $lostController;
71
		parent::__construct();
72
	}
73
74
	protected function configure() {
75
		$this
76
			->setName('user:resetpassword')
77
			->setDescription('Resets the password of the named user.')
78
			->addArgument(
79
				'user',
80
				InputArgument::REQUIRED,
81
				'The user\'s name.'
82
			)
83
			->addOption(
84
				'password-from-env',
85
				null,
86
				InputOption::VALUE_NONE,
87
				'Read the password from the OC_PASS environment variable.'
88
			)
89
			->addOption(
90
				'send-email',
91
				null,
92
				InputOption::VALUE_NONE,
93
				'The email-id set while creating the user, will be used to send link for password reset. This option will also display the link sent to user.'
94
			)
95
			->addOption(
96
				'output-link',
97
				null,
98
				InputOption::VALUE_NONE,
99
				'The link to reset the password will be displayed.'
100
			)
101
		;
102
	}
103
104
	protected function execute(InputInterface $input, OutputInterface $output) {
105
		$username = $input->getArgument('user');
106
		$emailLink = $input->getOption('send-email');
107
		$displayLink = $input->getOption('output-link');
108
109
		/** @var $user \OCP\IUser */
110
		$user = $this->userManager->get($username);
111
		if ($user === null) {
112
			$output->writeln('<error>User does not exist</error>');
113
			return 1;
114
		}
115
116
		if ($input->getOption('password-from-env')) {
117
			$password = $this->environmentHelper->getEnvVar('OC_PASS');
118
			if (!$password) {
119
				$output->writeln('<error>--password-from-env given, but OC_PASS is empty!</error>');
120
				return 1;
121
			}
122
		} elseif ($emailLink || $displayLink) {
123
			$userId = $user->getUID();
124
			list($link, $token) = $this->lostController->generateTokenAndLink($userId);
125
126
			if ($emailLink && $user->getEMailAddress() !== null) {
127
				try {
128
					$this->config->deleteUserValue($userId, 'owncloud', 'lostpassword');
129
					$this->lostController->sendEmail($userId, $token, $link);
130
				} catch (\Exception $e) {
131
					$output->writeln('<error>Can\'t send new user mail to ' . $user->getEMailAddress() . ': ' . $e->getMessage() . '</error>');
132
					return 1;
133
				}
134
			} else {
135
				if ($emailLink) {
136
					$output->writeln('<error>Email address is not set for the user ' . $user->getUID() . '</error>');
137
					return 1;
138
				}
139
			}
140
			$this->config->setUserValue($userId, 'owncloud', 'lostpassword', $this->timeFactory->getTime() . ':' . $token);
141
			$output->writeln('The password reset link is: ' . $link);
142
			return 0;
143
		} elseif ($input->isInteractive()) {
144
			/** @var $dialog \Symfony\Component\Console\Helper\QuestionHelper */
145
			$dialog = $this->getHelperSet()->get('question');
146
147
			if (\OCP\App::isEnabled('encryption')) {
148
				$output->writeln(
149
					'<error>Warning: Resetting the password when using encryption will result in data loss!</error>'
150
				);
151
				if (!$dialog->ask($input, $output, new Question('<question>Do you want to continue?</question>', true))) {
152
					return 1;
153
				}
154
			}
155
156
			$q = new Question('<question>Enter a new password: </question>', false);
157
			$q->setHidden(true);
158
			$password = $dialog->ask($input, $output, $q);
159
			if ($password === false) {
160
				// When user presses RETURN key or no password characters are entered,
161
				// $password gets a boolean value false.
162
				$output->writeln("<error>Password cannot be empty!</error>");
163
				return 1;
164
			}
165
			$q = new Question('<question>Confirm the new password: </question>', false);
166
			$q->setHidden(true);
167
			$confirm = $dialog->ask($input, $output, $q);
168
			if ($password !== $confirm) {
169
				$output->writeln("<error>Passwords did not match!</error>");
170
				return 1;
171
			}
172
		} else {
173
			$output->writeln("<error>Interactive input or --password-from-env is needed for entering a new password!</error>");
174
			return 1;
175
		}
176
177
		$success = $user->setPassword($password);
178
		if ($success) {
179
			$output->writeln("<info>Successfully reset password for " . $username . "</info>");
180
		} else {
181
			$output->writeln("<error>Error while resetting password!</error>");
182
			return 1;
183
		}
184
	}
185
}
186