Completed
Pull Request — master (#551)
by Maxence
01:55
created

FederatedUserService::bypassCurrentUserCondition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
6
/**
7
 * Circles - Bring cloud-users closer together.
8
 *
9
 * This file is licensed under the Affero General Public License version 3 or
10
 * later. See the COPYING file.
11
 *
12
 * @author Maxence Lange <[email protected]>
13
 * @copyright 2021
14
 * @license GNU AGPL version 3 or any later version
15
 *
16
 * This program is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License as
18
 * published by the Free Software Foundation, either version 3 of the
19
 * License, or (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
28
 *
29
 */
30
31
32
namespace OCA\Circles\Service;
33
34
35
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Logger;
36
use daita\MySmallPhpTools\Traits\TArrayTools;
37
use daita\MySmallPhpTools\Traits\TStringTools;
38
use OC\User\NoUserException;
39
use OCA\Circles\Db\CircleRequest;
40
use OCA\Circles\Db\MemberRequest;
41
use OCA\Circles\Db\MembershipRequest;
42
use OCA\Circles\Exceptions\CircleNotFoundException;
43
use OCA\Circles\Exceptions\InitiatorNotFoundException;
44
use OCA\Circles\Exceptions\OwnerNotFoundException;
45
use OCA\Circles\Exceptions\UserTypeNotFoundException;
46
use OCA\Circles\IFederatedUser;
47
use OCA\Circles\Model\Circle;
48
use OCA\Circles\Model\FederatedUser;
49
use OCA\Circles\Model\ManagedModel;
50
use OCA\Circles\Model\Member;
51
use OCA\Circles\Model\Membership;
52
use OCP\IUserManager;
53
54
55
/**
56
 * Class FederatedUserService
57
 *
58
 * @package OCA\Circles\Service
59
 */
60
class FederatedUserService {
61
62
63
	use TArrayTools;
64
	use TStringTools;
65
	use TNC21Logger;
66
67
68
	/** @var IUserManager */
69
	private $userManager;
70
71
	/** @var MembershipRequest */
72
	private $membershipRequest;
73
74
	/** @var CircleRequest */
75
	private $circleRequest;
76
77
	/** @var MemberRequest */
78
	private $memberRequest;
79
80
	/** @var ConfigService */
81
	private $configService;
82
83
84
	/** @var FederatedUser */
85
	private $currentUser = null;
86
87
	/** @var bool */
88
	private $bypass = false;
89
90
91
	/**
92
	 * FederatedUserService constructor.
93
	 *
94
	 * @param IUserManager $userManager
95
	 * @param MembershipRequest $membershipRequest
96
	 * @param CircleRequest $circleRequest
97
	 * @param MemberRequest $memberRequest
98
	 * @param ConfigService $configService
99
	 */
100
	public function __construct(
101
		IUserManager $userManager, MembershipRequest $membershipRequest, CircleRequest $circleRequest,
102
		MemberRequest $memberRequest, ConfigService $configService
103
	) {
104
		$this->userManager = $userManager;
105
		$this->membershipRequest = $membershipRequest;
106
		$this->circleRequest = $circleRequest;
107
		$this->memberRequest = $memberRequest;
108
		$this->configService = $configService;
109
	}
110
111
112
	/**
113
	 * @param string $userId
114
	 *
115
	 * @throws CircleNotFoundException
116
	 * @throws NoUserException
117
	 */
118
	public function setLocalInitiator(string $userId): void {
119
		$this->currentUser = $this->createLocalFederatedUser($userId);
120
	}
121
122
	/**
123
	 * @param IFederatedUser $federatedUser
124
	 *
125
	 * @throws CircleNotFoundException
126
	 */
127
	public function setCurrentUser(IFederatedUser $federatedUser): void {
128
		if (!($federatedUser instanceof FederatedUser)) {
129
			$tmp = new FederatedUser();
130
			$tmp->importFromIFederatedUser($federatedUser);
131
			$federatedUser = $tmp;
132
		}
133
134
		$this->fillSingleCircleId($federatedUser);
135
		$this->currentUser = $federatedUser;
136
	}
137
138
	/**
139
	 * @return FederatedUser|null
140
	 */
141
	public function getCurrentUser(): ?FederatedUser {
142
		return $this->currentUser;
143
	}
144
145
	/**
146
	 * @return bool
147
	 */
148
	public function hasCurrentUser(): bool {
149
		return ($this->currentUser !== null);
150
	}
151
152
	/**
153
	 * @throws InitiatorNotFoundException
154
	 */
155
	public function mustHaveCurrentUser(): void {
156
		if ($this->bypass) {
157
			return;
158
		}
159
		if (!$this->hasCurrentUser()) {
160
			throw new InitiatorNotFoundException();
161
		}
162
	}
163
164
	/**
165
	 * @param bool $bypass
166
	 */
167
	public function bypassCurrentUserCondition(bool $bypass): void {
168
		$this->bypass = $bypass;
169
	}
170
171
172
	/**
173
	 * @param string $userId
174
	 *
175
	 * @return FederatedUser
176
	 * @throws CircleNotFoundException
177
	 * @throws NoUserException
178
	 */
179
	public function createLocalFederatedUser(string $userId): FederatedUser {
180
		$user = $this->userManager->get($userId);
181
		if ($user === null) {
182
			throw new NoUserException('user ' . $userId . ' not found');
183
		}
184
185
		$federatedUser = new FederatedUser();
186
		$federatedUser->set($user->getUID());
187
		$this->fillSingleCircleId($federatedUser);
188
189
		return $federatedUser;
190
	}
191
192
193
	/**
194
	 * @param string $federatedId
195
	 * @param int $userType
196
	 *
197
	 * @return FederatedUser
198
	 * @throws CircleNotFoundException
199
	 * @throws NoUserException
200
	 * @throws UserTypeNotFoundException
201
	 */
202
	public function createFederatedUser(string $federatedId, int $userType = Member::TYPE_USER
203
	): FederatedUser {
204
		switch ($userType) {
205
			case Member::TYPE_USER:
206
				return $this->createFederatedUserTypeUser($federatedId);
207
		}
208
209
		throw new UserTypeNotFoundException();
210
	}
211
212
	/**
213
	 * @param string $userId
214
	 *
215
	 * @return FederatedUser
216
	 * @throws CircleNotFoundException
217
	 * @throws NoUserException
218
	 */
219
	public function createFederatedUserTypeUser(string $userId): FederatedUser {
220
		$userId = trim($userId, '@');
221
		if (strpos($userId, '@') === false) {
222
			$instance = $this->configService->getLocalInstance();
223
		} else {
224
			list($userId, $instance) = explode('@', $userId);
225
		}
226
227
		if ($this->configService->isLocalInstance($instance)) {
228
			return $this->createLocalFederatedUser($userId);
229
		} else {
230
			$federatedUser = new FederatedUser();
231
			$federatedUser->set($userId, $instance, Member::TYPE_USER);
232
233
			return $federatedUser;
234
		}
235
	}
236
237
238
	/**
239
	 * some ./occ commands allows to add an Initiator
240
	 * TODO: manage non-user type
241
	 *
242
	 * @param string $userId
243
	 * @param string $circleId
244
	 * @param bool $bypass
245
	 *
246
	 * @throws CircleNotFoundException
247
	 * @throws NoUserException
248
	 * @throws OwnerNotFoundException
249
	 */
250
	public function commandLineInitiator(string $userId, string $circleId = '', bool $bypass = false) {
251
		if ($userId !== '') {
252
			$this->setCurrentUser($this->createFederatedUserTypeUser($userId));
253
254
			return;
255
		}
256
257
		if ($circleId !== '') {
258
			$localCircle = $this->circleRequest->getCircle($circleId);
259
			if ($this->configService->isLocalInstance($localCircle->getInstance())) {
260
				// TODO: manage NO_OWNER circles
261
				$this->setCurrentUser($localCircle->getOwner());
262
263
				return;
264
			}
265
		}
266
267
		if (!$bypass) {
268
			throw new CircleNotFoundException(
269
				'This Circle is not managed from this instance, please use --initiator'
270
			);
271
		}
272
273
		$this->bypassCurrentUserCondition($bypass);
274
	}
275
276
277
	/**
278
	 * TODO: Is it needed outside of CirclesList ?
279
	 *
280
	 * @param string $userId
281
	 * @param int $level
282
	 *
283
	 * @return Member
284
	 * @throws CircleNotFoundException
285
	 * @throws NoUserException
286
	 */
287
	public function createFilterMember(string $userId, int $level = Member::LEVEL_MEMBER): Member {
288
		$userId = trim($userId, ',');
289
		if (strpos($userId, ',') !== false) {
290
			list($userId, $level) = explode(',', $userId);
291
		}
292
293
		$federatedUser = $this->createFederatedUserTypeUser($userId);
294
		$member = new Member();
295
		$member->importFromIFederatedUser($federatedUser);
296
		$member->setLevel((int)$level);
297
298
		return $member;
299
	}
300
301
302
	/**
303
	 * @param FederatedUser $federatedUser
304
	 *
305
	 * @throws CircleNotFoundException
306
	 */
307
	private function fillSingleCircleId(FederatedUser $federatedUser): void {
308
		if ($federatedUser->getSingleId() !== '') {
309
			return;
310
		}
311
312
		// only if currentUser is from LocalInstance
313
		if ($this->configService->isLocalInstance($federatedUser->getInstance())) {
314
			$circle = $this->getSingleCircle($federatedUser);
315
			$federatedUser->setSingleId($circle->getId());
316
		}
317
	}
318
319
320
	/**
321
	 * @param FederatedUser $federatedUser
322
	 *
323
	 * @return Circle
324
	 * @throws CircleNotFoundException
325
	 */
326
	public function getSingleCircle(FederatedUser $federatedUser): Circle {
327
		try {
328
			return $this->circleRequest->getInitiatorCircle($federatedUser);
329
		} catch (CircleNotFoundException $e) {
330
			$circle = new Circle();
331
			$id = $this->token(ManagedModel::ID_LENGTH);
332
333
			$circle->setName('single:' . $federatedUser->getUserId() . ':' . $id)
334
				   ->setId($id)
335
				   ->setConfig(Circle::CFG_SINGLE);
336
			$this->circleRequest->save($circle);
337
338
			$owner = new Member();
339
			$owner->importFromIFederatedUser($federatedUser);
340
			$owner->setLevel(Member::LEVEL_OWNER)
341
				  ->setCircleId($id)
342
				  ->setId($id)
343
				  ->setCachedName($owner->getUserId())
344
				  ->setStatus('Member');
345
			$this->memberRequest->save($owner);
346
		}
347
348
		return $this->circleRequest->getInitiatorCircle($federatedUser);
349
	}
350
351
352
	/**
353
	 * @param FederatedUser $federatedUser
354
	 *
355
	 * @return Membership[]
356
	 */
357
	public function generateMemberships(FederatedUser $federatedUser): array {
358
		$circles = $this->circleRequest->getCircles(null, $federatedUser);
359
		$memberships = [];
360
		foreach ($circles as $circle) {
361
			$initiator = $circle->getInitiator();
362
			if (!$initiator->isMember()) {
363
				continue;
364
			}
365
366
			$memberships[] = new Membership(
367
				$initiator->getId(), $circle->getId(), $federatedUser->getSingleId(), $initiator->getLevel()
368
			);
369
370
//			$newUser = new CurrentUser($circle->getId(), Member::TYPE_CIRCLE, '');
371
//			$circles = $this->circleRequest->getCircles(null, $currentUser);
372
		}
373
374
		return $memberships;
375
	}
376
377
378
	/**
379
	 * @param FederatedUser|null $federatedUser
380
	 */
381
	public function updateMemberships(?FederatedUser $federatedUser = null) {
382
		if (is_null($federatedUser)) {
383
			$federatedUser = $this->getCurrentUser();
384
		} else {
385
			$federatedUser->setMemberships($this->membershipRequest->getMemberships($federatedUser));
0 ignored issues
show
Documentation introduced by
$federatedUser is of type object<OCA\Circles\Model\FederatedUser>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
386
		}
387
388
		if (is_null($federatedUser)) {
389
			return;
390
		}
391
392
		$last = $this->generateMemberships($federatedUser);
393
394
		echo 'known: ' . json_encode($federatedUser->getMemberships()) . "\n";
395
		echo 'last: ' . json_encode($last) . "\n";
396
397
//
398
//		$circles = $this->circleRequest->getCircles(null, $viewer);
399
//		foreach ($circles as $circle) {
400
//			$viewer = $circle->getViewer();
401
//			if (!$viewer->isMember()) {
402
//				continue;
403
//			}
404
//
405
//			echo 'new member: ' . json_encode($viewer) . "\n";
406
////			$this->federatedUserService->updateMembership($circle);
407
//		}
408
409
410
	}
411
412
}
413
414