Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable10] Backport of resetpassword command supports send password r… #32500

Merged
merged 1 commit into from
Aug 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions core/Command/User/ResetPassword.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* @author Laurens Post <lkpost@scept.re>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Sujith Haridasan <sharidasan@owncloud.com>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
Expand All @@ -27,7 +28,16 @@

namespace OC\Core\Command\User;

use OC\Core\Controller\LostController;
use OC\Helper\EnvironmentHelper;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Mail\IMailer;
use OCP\Security\ISecureRandom;
use OCP\Util;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -39,9 +49,25 @@ class ResetPassword extends Command {

/** @var IUserManager */
protected $userManager;
/** @var IConfig */
private $config;
/** @var ITimeFactory */
private $timeFactory;
/** @var EnvironmentHelper */
private $environmentHelper;
/** @var LostController */
private $lostController;

public function __construct(IUserManager $userManager) {
public function __construct(IUserManager $userManager,
IConfig $config,
ITimeFactory $timeFactory,
EnvironmentHelper $environmentHelper,
LostController $lostController) {
$this->userManager = $userManager;
$this->config = $config;
$this->timeFactory = $timeFactory;
$this->environmentHelper = $environmentHelper;
$this->lostController = $lostController;
parent::__construct();
}

Expand All @@ -60,11 +86,25 @@ protected function configure() {
InputOption::VALUE_NONE,
'Read the password from the OC_PASS environment variable.'
)
->addOption(
'send-email',
null,
InputOption::VALUE_NONE,
'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.'
)
->addOption(
'output-link',
null,
InputOption::VALUE_NONE,
'The link to reset the password will be displayed.'
)
;
}

protected function execute(InputInterface $input, OutputInterface $output) {
$username = $input->getArgument('user');
$emailLink = $input->getOption('send-email');
$displayLink = $input->getOption('output-link');

/** @var $user \OCP\IUser */
$user = $this->userManager->get($username);
Expand All @@ -74,11 +114,32 @@ protected function execute(InputInterface $input, OutputInterface $output) {
}

if ($input->getOption('password-from-env')) {
$password = \getenv('OC_PASS');
$password = $this->environmentHelper->getEnvVar('OC_PASS');
if (!$password) {
$output->writeln('<error>--password-from-env given, but OC_PASS is empty!</error>');
return 1;
}
} elseif ($emailLink || $displayLink) {
$userId = $user->getUID();
list($link, $token) = $this->lostController->generateTokenAndLink($userId);

if ($emailLink && $user->getEMailAddress() !== null) {
try {
$this->config->deleteUserValue($userId, 'owncloud', 'lostpassword');
$this->lostController->sendEmail($userId, $token, $link);
} catch (\Exception $e) {
$output->writeln('<error>Can\'t send new user mail to ' . $user->getEMailAddress() . ': ' . $e->getMessage() . '</error>');
return 1;
}
} else {
if ($emailLink) {
$output->writeln('<error>Email address is not set for the user ' . $user->getUID() . '</error>');
return 1;
}
}
$this->config->setUserValue($userId, 'owncloud', 'lostpassword', $this->timeFactory->getTime() . ':' . $token);
$output->writeln('The password reset link is: ' . $link);
return 0;
} elseif ($input->isInteractive()) {
/** @var $dialog \Symfony\Component\Console\Helper\QuestionHelper */
$dialog = $this->getHelperSet()->get('question');
Expand Down
33 changes: 22 additions & 11 deletions core/Controller/LostController.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ private function success() {
public function email($user) {
// FIXME: use HTTP error codes
try {
$this->sendEmail($user);
list($link, $token) = $this->generateTokenAndLink($user);
$this->sendEmail($user, $token, $link);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
Expand Down Expand Up @@ -278,12 +279,28 @@ protected function sendNotificationMail($userId) {
}
}

/**
* @param string $userId
* @return array
*/
public function generateTokenAndLink($userId) {
$token = $this->secureRandom->generate(21,
ISecureRandom::CHAR_DIGITS .
ISecureRandom::CHAR_LOWER .
ISecureRandom::CHAR_UPPER);

$link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $userId, 'token' => $token]);
return [$link, $token];
}

/**
* @param string $user
* @param string $token
* @param string $link
* @throws \Exception
* @return boolean
*/
protected function sendEmail($user) {
public function sendEmail($user, $token, $link) {
if ($this->userManager->userExists($user)) {
$userObject = $this->userManager->get($user);
$email = $userObject->getEMailAddress();
Expand All @@ -310,23 +327,17 @@ protected function sendEmail($user) {
}
}

$token = $this->config->getUserValue($user, 'owncloud', 'lostpassword');
if ($token !== '') {
$splittedToken = \explode(':', $token);
$getToken = $this->config->getUserValue($user, 'owncloud', 'lostpassword');
if ($getToken !== '') {
$splittedToken = \explode(':', $getToken);
if ((\count($splittedToken)) === 2 && $splittedToken[0] > ($this->timeFactory->getTime() - 60 * 5)) {
$this->logger->alert('The email is not sent because a password reset email was sent recently.');
return false;
}
}

$token = $this->secureRandom->generate(21,
ISecureRandom::CHAR_DIGITS .
ISecureRandom::CHAR_LOWER .
ISecureRandom::CHAR_UPPER);
$this->config->setUserValue($user, 'owncloud', 'lostpassword', $this->timeFactory->getTime() . ':' . $token);

$link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $user, 'token' => $token]);

$tmpl = new \OC_Template('core', 'lostpassword/email');
$tmpl->assign('link', $link);
$msg = $tmpl->fetchPage();
Expand Down
7 changes: 6 additions & 1 deletion core/register_command.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,12 @@
$application->add(new OC\Core\Command\User\ListUsers(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\ListUserGroups(\OC::$server->getUserManager(), \OC::$server->getGroupManager()));
$application->add(new OC\Core\Command\User\Report(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\ResetPassword(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\ResetPassword(\OC::$server->getUserManager(), \OC::$server->getConfig(), \OC::$server->getTimeFactory(),
new \OC\Helper\EnvironmentHelper(), new \OC\Core\Controller\LostController('settings',
\OC::$server->getRequest(), \OC::$server->getURLGenerator(), \OC::$server->getUserManager(), new \OC_Defaults(),
\OC::$server->getL10N('settings'), \OC::$server->getConfig(), \OC::$server->getSecureRandom(),
\OCP\Util::getDefaultEmailAddress('lostpassword-noreply'), \OC::$server->getEncryptionManager()->isEnabled(),
\OC::$server->getMailer(), \OC::$server->getTimeFactory(), \OC::$server->getLogger(), \OC::$server->getUserSession())));
$application->add(new OC\Core\Command\User\Setting(\OC::$server->getUserManager(), \OC::$server->getConfig(), \OC::$server->getDatabaseConnection()));
$application->add(new OC\Core\Command\User\Modify(\OC::$server->getUserManager(), \OC::$server->getMailer()));
$application->add(new OC\Core\Command\User\SyncBackend(\OC::$server->getAccountMapper(), \OC::$server->getConfig(), \OC::$server->getUserManager(), \OC::$server->getLogger()));
Expand Down
Loading