Completed
Pull Request — master (#32767)
by Sujith
17:56 queued 07:59
created

CreateUser::isAdmin()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 14
rs 9.7998
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\IGroupManager;
25
use OCP\ILogger;
26
use OCP\IUserManager;
27
use OCP\IUserSession;
28
use OCP\Mail\IMailer;
29
use OCP\Security\ISecureRandom;
30
use OCP\User\Exceptions\CannotCreateUserException;
31
use OCP\User\Exceptions\InvalidEmailException;
32
use OCP\User\Exceptions\UserAlreadyExistsException;
33
34
class CreateUser {
35
	/** @var IUserSession */
36
	private $userSession;
37
	/** @var IGroupManager */
38
	private $groupManager;
39
	/** @var IUserManager */
40
	private $userManager;
41
	/** @var IMailer */
42
	private $mailer;
43
	/** @var ISecureRandom */
44
	private $secureRandom;
45
	/** @var ILogger */
46
	private $logger;
47
	/** @var UserSendMail */
48
	private $userSendMail;
49
	/** @var CreatePassword */
50
	private $createPassword;
51
52
	/**
53
	 * CreateUser constructor.
54
	 *
55
	 * @param IUserSession $userSession
56
	 * @param IGroupManager $groupManager
57
	 * @param IUserManager $userManager
58
	 * @param IMailer $mailer
59
	 * @param ISecureRandom $secureRandom
60
	 * @param ILogger $logger
61
	 * @param UserSendMail $userSendMail
62
	 * @param CreatePassword $createPassword
63
	 */
64
	public function __construct(IUserSession $userSession,
65
								IGroupManager $groupManager,
66
								IUserManager $userManager,
67
								IMailer $mailer,
68
								ISecureRandom $secureRandom,
69
								ILogger $logger,
70
								UserSendMail $userSendMail,
71
								CreatePassword $createPassword) {
72
		$this->userSession = $userSession;
73
		$this->groupManager = $groupManager;
74
		$this->userManager = $userManager;
75
		$this->mailer = $mailer;
76
		$this->secureRandom = $secureRandom;
77
		$this->logger = $logger;
78
		$this->userSendMail = $userSendMail;
79
		$this->createPassword = $createPassword;
80
	}
81
82
	/**
83
	 * @param $username
84
	 * @param $password
85
	 * @param array $groups
86
	 * @param string $email
87
	 * @return bool|\OCP\IUser
88
	 * @throws CannotCreateUserException
89
	 * @throws InvalidEmailException
90
	 * @throws UserAlreadyExistsException
91
	 */
92
	public function createUser($username, $password, array $groups= [], $email='') {
93
		if ($email !== '' && !$this->mailer->validateMailAddress($email)) {
94
			throw new InvalidEmailException("Invalid mail address");
95
		}
96
97
		$currentUser = $this->userSession->getUser();
98
99
		if (!$this->isAdmin()) {
100
			if (!empty($groups)) {
101
				foreach ($groups as $key => $group) {
102
					$groupObject = $this->groupManager->get($group);
103
					if ($groupObject === null) {
104
						unset($groups[$key]);
105
						continue;
106
					}
107
108
					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 97 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...
109
						unset($groups[$key]);
110
					}
111
				}
112
			}
113
114
			if (empty($groups)) {
115
				$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($currentUser);
0 ignored issues
show
Bug introduced by
It seems like $currentUser defined by $this->userSession->getUser() on line 97 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...
116
				// New class returns IGroup[] so convert back
117
				$gids = [];
118
				foreach ($groups as $group) {
119
					$gids[] = $group->getGID();
120
				}
121
				$groups = $gids;
122
			}
123
		}
124
125
		if ($this->userManager->userExists($username)) {
126
			throw new UserAlreadyExistsException('A user with that name already exists.');
127
		}
128
129
		try {
130
			if (($password === '') && ($email !== '')) {
131
				/**
132
				 * Generate a random password as we are going to have this
133
				 * use one time. The new user has to reset it using the link
134
				 * from email.
135
				 */
136
				$password = $this->createPassword->createPassword();
137
			}
138
			$user = $this->userManager->createUser($username, $password);
139
		} catch (\Exception $exception) {
140
			throw new CannotCreateUserException("Unable to create user due to exception: {$exception->getMessage()}");
141
		}
142
143
		if ($user === false) {
144
			throw new CannotCreateUserException('Unable to create user.');
145
		}
146
147
		if ($groups !== null) {
148
			foreach ($groups as $groupName) {
149
				if ($groupName !== null) {
150
					$group = $this->groupManager->get($groupName);
151
152
					if (empty($group)) {
153
						$group = $this->groupManager->createGroup($groupName);
154
					}
155
					$group->addUser($user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->userManager->crea...r($username, $password) on line 138 can also be of type boolean; however, OCP\IGroup::addUser() does only seem to accept object<OCP\IUser>, 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...
156
					$this->logger->info('Added userid ' . $user->getUID() . ' to group ' . $group->getGID());
157
				}
158
			}
159
		}
160
		/**
161
		 * Send new user mail only if a mail is set
162
		 */
163
		if ($email !== '') {
164
			$user->setEMailAddress($email);
165
			try {
166
				$this->userSendMail->generateTokenAndSendMail($username, $email);
167
			} catch (\Exception $e) {
168
				$this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), ['app' => 'settings']);
169
			}
170
		}
171
172
		return $user;
173
	}
174
175
	private function isAdmin() {
176
		// Check if current user (active and not in incognito mode)
177
		// is an admin
178
		$activeUser = $this->userSession->getUser();
179
		if ($activeUser !== null) {
180
			return $this->groupManager->isAdmin($activeUser->getUID());
181
		}
182
		// Check if it is triggered from command line
183
		$cli = $this->triggeredFromCommandLine();
184
		if ($cli === true) {
185
			return true;
186
		}
187
		return false;
188
	}
189
190
	/**
191
	 * Check if action is triggered from command line
192
	 * @return bool
193
	 */
194
	private function triggeredFromCommandLine() {
195
		return \OC::$CLI;
196
	}
197
}
198