Completed
Pull Request — master (#32767)
by Sujith
74:52 queued 26:28
created

UserSendMail::generateTokenAndSendMail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 29
rs 9.456
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Sujith Haridasan <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2018, ownCloud GmbH
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
namespace OC\User\Service;
23
24
use OCP\AppFramework\Http\TemplateResponse;
25
use OCP\AppFramework\Utility\ITimeFactory;
26
use OCP\IConfig;
27
use OCP\IL10N;
28
use OCP\IURLGenerator;
29
use OCP\IUser;
30
use OCP\Mail\IMailer;
31
use OCP\Security\ISecureRandom;
32
use OCP\User\Exceptions\InvalidUserTokenException;
33
use OCP\User\Exceptions\UserTokenExpiredException;
34
use OCP\User\Exceptions\UserTokenMismatchException;
35
use OCP\Util;
36
37
class UserSendMail {
38
	/** @var ISecureRandom  */
39
	private $secureRandom;
40
	/** @var IConfig  */
41
	private $config;
42
	/** @var IMailer  */
43
	private $mailer;
44
	/** @var IURLGenerator  */
45
	private $urlGenerator;
46
	/** @var \OC_Defaults  */
47
	private $defaults;
48
	/** @var ITimeFactory  */
49
	private $timeFactory;
50
	/** @var string  */
51
	private $fromMailAddress;
52
	/** @var IL10N  */
53
	private $l10n;
54
55
	/**
56
	 * UserSendMail constructor.
57
	 *
58
	 * @param ISecureRandom $secureRandom
59
	 * @param IConfig $config
60
	 * @param IMailer $mailer
61
	 * @param IURLGenerator $urlGenerator
62
	 * @param \OC_Defaults $defaults
63
	 * @param ITimeFactory $timeFactory
64
	 * @param IL10N $l10n
65
	 */
66 View Code Duplication
	public function __construct(ISecureRandom $secureRandom, IConfig $config,
67
								IMailer $mailer, IURLGenerator $urlGenerator,
68
								\OC_Defaults $defaults, ITimeFactory $timeFactory,
69
								IL10N $l10n) {
70
		$this->secureRandom = $secureRandom;
71
		$this->config = $config;
72
		$this->mailer = $mailer;
73
		$this->urlGenerator = $urlGenerator;
74
		$this->defaults = $defaults;
75
		$this->timeFactory = $timeFactory;
76
		$this->l10n = $l10n;
77
		$this->fromMailAddress = Util::getDefaultEmailAddress('no-reply');
78
	}
79
80
	/**
81
	 * @param string $userId
82
	 * @param string $email
83
	 * @return null
84
	 */
85
	public function generateTokenAndSendMail($userId, $email) {
86
		$token = $this->secureRandom->generate(21,
87
			ISecureRandom::CHAR_DIGITS,
88
			ISecureRandom::CHAR_LOWER, ISecureRandom::CHAR_UPPER);
0 ignored issues
show
Unused Code introduced by
The call to ISecureRandom::generate() has too many arguments starting with \OCP\Security\ISecureRandom::CHAR_LOWER.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
89
		$this->config->setUserValue($userId, 'owncloud',
90
			'lostpassword', $this->timeFactory->getTime() . ':' . $token);
91
92
		// data for the mail template
93
		$mailData = [
94
			'username' => $userId,
95
			'url' => $this->urlGenerator->linkToRouteAbsolute('core.user.setPasswordForm', ['userId' => $userId, 'token' => $token])
96
		];
97
98
		$mail = new TemplateResponse('core', 'new_user/email-html', $mailData, 'blank');
99
		$mailContent = $mail->render();
100
101
		$mail = new TemplateResponse('core', 'new_user/email-plain_text', $mailData, 'blank');
102
		$plainTextMailContent = $mail->render();
103
104
		$subject = $this->l10n->t('Your %s account was created', [$this->defaults->getName()]);
105
106
		$message = $this->mailer->createMessage();
107
		$message->setTo([$email => $userId]);
108
		$message->setSubject($subject);
109
		$message->setHtmlBody($mailContent);
0 ignored issues
show
Bug introduced by
It seems like $mailContent defined by $mail->render() on line 99 can also be of type boolean; however, OC\Mail\Message::setHtmlBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
110
		$message->setPlainBody($plainTextMailContent);
0 ignored issues
show
Bug introduced by
It seems like $plainTextMailContent defined by $mail->render() on line 102 can also be of type boolean; however, OC\Mail\Message::setPlainBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
111
		$message->setFrom([$this->fromMailAddress => $this->defaults->getName()]);
112
		$this->mailer->send($message);
113
	}
114
115
	/**
116
	 * @param string $token
117
	 * @param IUser $user
118
	 * @return null
119
	 * @throws InvalidUserTokenException
120
	 * @throws UserTokenExpiredException
121
	 * @throws UserTokenMismatchException
122
	 */
123
	public function checkPasswordSetToken($token, IUser $user) {
124
		$splittedToken = \explode(':', $this->config->getUserValue($user->getUID(), 'owncloud', 'lostpassword', null));
125
		if (\count($splittedToken) !== 2) {
126
			$this->config->deleteUserValue($user->getUID(), 'owncloud', 'lostpassword');
127
			throw new InvalidUserTokenException($this->l10n->t('The token provided is invalid.'));
128
		}
129
130
		//The value 43200 = 60*60*12 = 1/2 day
131
		if ($splittedToken[0] < ($this->timeFactory->getTime() - (int)$this->config->getAppValue('core', 'token_expire_time', '43200')) ||
132
			$user->getLastLogin() > $splittedToken[0]) {
133
			$this->config->deleteUserValue($user->getUID(), 'owncloud', 'lostpassword');
134
			throw new UserTokenExpiredException($this->l10n->t('The token provided had expired.'));
135
		}
136
137
		if (!\hash_equals($splittedToken[1], $token)) {
138
			throw new UserTokenMismatchException($this->l10n->t('The token provided is invalid.'));
139
		}
140
	}
141
142
	/**
143
	 * @param IUser $user
144
	 * @return null
145
	 * @throws \Exception
146
	 */
147
	public function sendNotificationMail($user) {
148
		$email = $user->getEMailAddress();
149
150
		if ($email !== '') {
151
			$tmpl = new \OC_Template('core', 'lostpassword/notify');
152
			$msg = $tmpl->fetchPage();
153
154
			$message = $this->mailer->createMessage();
155
			$message->setTo([$email => $user->getUID()]);
156
			$message->setSubject($this->l10n->t('%s password changed successfully', [$this->defaults->getName()]));
157
			$message->setPlainBody($msg);
0 ignored issues
show
Bug introduced by
It seems like $msg defined by $tmpl->fetchPage() on line 152 can also be of type boolean; however, OC\Mail\Message::setPlainBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
158
			$message->setFrom([$email => $this->defaults->getName()]);
159
			$this->mailer->send($message);
160
		}
161
	}
162
}
163