Completed
Pull Request — master (#32767)
by Sujith
13:11
created

CreateUser   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 164
Duplicated Lines 7.93 %

Coupling/Cohesion

Components 1
Dependencies 17

Importance

Changes 0
Metric Value
dl 13
loc 164
rs 10
c 0
b 0
f 0
wmc 27
lcom 1
cbo 17

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 1
F createUser() 0 92 23
A isAdmin() 13 13 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 OC\User\User;
25
use OCP\IGroupManager;
26
use OCP\ILogger;
27
use OCP\IUserManager;
28
use OCP\IUserSession;
29
use OCP\Mail\IMailer;
30
use OCP\Security\ISecureRandom;
31
use OCP\User\Exceptions\CannotCreateUserException;
32
use OCP\User\Exceptions\InvalidEmailException;
33
use OCP\User\Exceptions\UserAlreadyExistsException;
34
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
35
use Symfony\Component\EventDispatcher\GenericEvent;
36
37
class CreateUser {
38
	/** @var IUserSession  */
39
	private $userSession;
40
	/** @var IGroupManager  */
41
	private $groupManager;
42
	/** @var IUserManager  */
43
	private $userManager;
44
	/** @var IMailer  */
45
	private $mailer;
46
	/** @var ISecureRandom  */
47
	private $secureRandom;
48
	/** @var EventDispatcherInterface  */
49
	private $eventDispatcher;
50
	/** @var ILogger  */
51
	private $logger;
52
	/** @var UserSendMail  */
53
	private $userSendMail;
54
55
	/**
56
	 * CreateUser constructor.
57
	 *
58
	 * @param IUserSession $userSession
59
	 * @param IGroupManager $groupManager
60
	 * @param IUserManager $userManager
61
	 * @param IMailer $mailer
62
	 * @param ISecureRandom $secureRandom
63
	 * @param EventDispatcherInterface $eventDispatcher
64
	 * @param ILogger $logger
65
	 * @param UserSendMail $userSendMail
66
	 */
67
	public function __construct(IUserSession $userSession,
68
								IGroupManager $groupManager,
69
								IUserManager $userManager,
70
								IMailer $mailer,
71
								ISecureRandom $secureRandom,
72
								EventDispatcherInterface $eventDispatcher,
73
								ILogger $logger, UserSendMail $userSendMail) {
74
		$this->userSession = $userSession;
75
		$this->groupManager = $groupManager;
76
		$this->userManager = $userManager;
77
		$this->mailer = $mailer;
78
		$this->secureRandom = $secureRandom;
79
		$this->eventDispatcher = $eventDispatcher;
80
		$this->logger = $logger;
81
		$this->userSendMail = $userSendMail;
82
	}
83
84
	/**
85
	 * @param $username
86
	 * @param $password
87
	 * @param array $groups
88
	 * @param string $email
89
	 * @return bool|\OCP\IUser
90
	 * @throws CannotCreateUserException
91
	 * @throws InvalidEmailException
92
	 * @throws UserAlreadyExistsException
93
	 */
94
	public function createUser($username, $password, array $groups= [], $email='') {
95
		if ($email !== '' && !$this->mailer->validateMailAddress($email)) {
96
			throw new InvalidEmailException("Invalid mail address");
97
		}
98
99
		$currentUser = $this->userSession->getUser();
100
101
		if (!$this->isAdmin()) {
102
			if (!empty($groups)) {
103
				foreach ($groups as $key => $group) {
104
					$groupObject = $this->groupManager->get($group);
105
					if ($groupObject === null) {
106
						unset($groups[$key]);
107
						continue;
108
					}
109
110
					if (!$this->groupManager->getSubAdmin()->isSubAdminofGroup($currentUser, $groupObject)) {
0 ignored issues
show
Bug introduced by
It seems like $currentUser defined by $this->userSession->getUser() on line 99 can be null; however, OCP\ISubAdminManager::isSubAdminofGroup() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
111
						unset($groups[$key]);
112
					}
113
				}
114
			}
115
116
			if (empty($groups)) {
117
				$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($currentUser);
0 ignored issues
show
Bug introduced by
It seems like $currentUser defined by $this->userSession->getUser() on line 99 can be null; however, OCP\ISubAdminManager::getSubAdminsGroups() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
118
				// New class returns IGroup[] so convert back
119
				$gids = [];
120
				foreach ($groups as $group) {
121
					$gids[] = $group->getGID();
122
				}
123
				$groups = $gids;
124
			}
125
		}
126
127
		if ($this->userManager->userExists($username)) {
128
			throw new UserAlreadyExistsException('A user with that name already exists.');
129
		}
130
131
		try {
132
			if (($password === '') && ($email !== '')) {
133
				/**
134
				 * Generate a random password as we are going to have this
135
				 * use one time. The new user has to reset it using the link
136
				 * from email.
137
				 */
138
				$event = new GenericEvent();
139
				$this->eventDispatcher->dispatch('OCP\User::createPassword', $event);
140
				if ($event->hasArgument('password')) {
141
					$password = $event->getArgument('password');
142
				} else {
143
					$password = $this->secureRandom->generate(20);
144
				}
145
			}
146
			$user = $this->userManager->createUser($username, $password);
147
		} catch (\Exception $exception) {
148
			$message = $exception->getMessage();
149
			if (!$message) {
150
				$message = 'Unable to create user.';
151
			}
152
			throw new CannotCreateUserException($message);
153
		}
154
155
		if ($user instanceof User) {
156
			if ($groups !== null) {
157
				foreach ($groups as $groupName) {
158
					if ($groupName !== null) {
159
						$group = $this->groupManager->get($groupName);
160
161
						if (empty($group)) {
162
							$group = $this->groupManager->createGroup($groupName);
163
						}
164
						$group->addUser($user);
165
						$this->logger->info('Added userid ' . $user->getUID() . ' to group ' . $group->getGID());
166
					}
167
				}
168
			}
169
			/**
170
			 * Send new user mail only if a mail is set
171
			 */
172
			if ($email !== '') {
173
				$user->setEMailAddress($email);
174
				try {
175
					$this->userSendMail->generateTokenAndSendMail($username, $email);
176
				} catch (\Exception $e) {
177
					$this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), ['app' => 'settings']);
178
				}
179
			}
180
181
			return $user;
182
		}
183
184
		throw new CannotCreateUserException('Unable to create user.');
185
	}
186
187 View Code Duplication
	private function isAdmin() {
188
		// Check if current user (active and not in incognito mode)
189
		// is an admin
190
		$activeUser = $this->userSession->getUser();
191
		if ($activeUser !== null) {
192
			return $this->groupManager->isAdmin($activeUser->getUID());
193
		}
194
		// Check if it is triggered from command line
195
		if (\OC::$CLI) {
196
			return true;
197
		}
198
		return false;
199
	}
200
}