Completed
Push — master ( b98811...509992 )
by Maxence
06:02 queued 02:51
created

CirclesReport::obfuscateMember()   B

Complexity

Conditions 8
Paths 64

Size

Total Lines 46

Duplication

Lines 7
Ratio 15.22 %

Importance

Changes 0
Metric Value
dl 7
loc 46
rs 7.9337
c 0
b 0
f 0
cc 8
nc 64
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\Command;
33
34
use daita\MySmallPhpTools\Console\Nextcloud\nc22\NC22InteractiveShell;
35
use daita\MySmallPhpTools\Exceptions\InvalidItemException;
36
use daita\MySmallPhpTools\IInteractiveShellClient;
37
use daita\MySmallPhpTools\Model\Nextcloud\nc22\NC22InteractiveShellSession;
38
use daita\MySmallPhpTools\Model\SimpleDataStore;
39
use daita\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Deserialize;
40
use daita\MySmallPhpTools\Traits\TArrayTools;
41
use OC\Core\Command\Base;
42
use OCA\Circles\Exceptions\InitiatorNotFoundException;
43
use OCA\Circles\Model\Circle;
44
use OCA\Circles\Model\Federated\RemoteInstance;
45
use OCA\Circles\Model\FederatedUser;
46
use OCA\Circles\Model\Member;
47
use OCA\Circles\Model\Membership;
48
use OCA\Circles\Model\Report;
49
use OCA\Circles\Service\CircleService;
50
use OCA\Circles\Service\ConfigService;
51
use OCA\Circles\Service\FederatedUserService;
52
use OCA\Circles\Service\MemberService;
53
use Symfony\Component\Console\Input\InputInterface;
54
use Symfony\Component\Console\Input\InputOption;
55
use Symfony\Component\Console\Output\ConsoleOutput;
56
use Symfony\Component\Console\Output\OutputInterface;
57
58
59
/**
60
 * Class CirclesReport
61
 *
62
 * @package OCA\Circles\Command
63
 */
64
class CirclesReport extends Base implements IInteractiveShellClient {
65
66
67
	use TNC22Deserialize;
68
	use TArrayTools;
69
70
71
	/** @var FederatedUserService */
72
	private $federatedUserService;
73
74
	/** @var CircleService */
75
	private $circleService;
76
77
	/** @var MemberService */
78
	private $memberService;
79
80
	/** @var ConfigService */
81
	private $configService;
82
83
84
	/** @var OutputInterface */
85
	private $output;
86
87
	/** @var Report */
88
	private $report;
89
90
91
	/**
92
	 * CirclesReport constructor.
93
	 *
94
	 * @param FederatedUserService $federatedUserService
95
	 * @param CircleService $circleService
96
	 * @param MemberService $memberService
97
	 * @param ConfigService $configService
98
	 */
99 View Code Duplication
	public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100
		FederatedUserService $federatedUserService,
101
		CircleService $circleService,
102
		MemberService $memberService,
103
		ConfigService $configService
104
	) {
105
		parent::__construct();
106
107
		$this->federatedUserService = $federatedUserService;
108
		$this->circleService = $circleService;
109
		$this->memberService = $memberService;
110
		$this->configService = $configService;
111
	}
112
113
114
	/**
115
	 *
116
	 */
117
	protected function configure() {
118
		parent::configure();
119
		$this->setName('circles:report')
120
			 ->setDescription('Read and write obfuscated report')
121
			 ->addOption('local', '', InputOption::VALUE_NONE, 'Use local report')
122
			 ->addOption('read', '', InputOption::VALUE_REQUIRED, 'File containing the report to read', '');
123
	}
124
125
126
	/**
127
	 * @param InputInterface $input
128
	 * @param OutputInterface $output
129
	 *
130
	 * @return int
131
	 * @throws InvalidItemException
132
	 * @throws InitiatorNotFoundException
133
	 */
134
	protected function execute(InputInterface $input, OutputInterface $output): int {
135
		$filename = $input->getOption('read');
136
		$local = $input->getOption('local');
137
		$this->output = $output;
138
139
		$report = null;
140
		if ($filename === '' || $local) {
141
			$report = $this->generateReport();
142
			if (!$local) {
143
				$this->output->writeln(json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
144
145
				return 0;
146
			}
147
		}
148
149
		if ($filename !== '') {
150
			/** @var Report $report */
151
			$data = file_get_contents($filename);
152
			$report = $this->deserialize(json_decode($data, true), Report::class);
153
		}
154
155
		if (!is_null($report)) {
156
			$this->readReport($input, $report);
157
		}
158
159
		return 0;
160
	}
161
162
163
	/**
164
	 * @throws InitiatorNotFoundException
165
	 */
166
	private function generateReport(): Report {
167
		$report = new Report();
168
		$report->setSource($this->configService->getLocalInstance());
0 ignored issues
show
Bug introduced by
The method getLocalInstance() does not seem to exist on object<OCA\Circles\Service\ConfigService>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
169
		$this->federatedUserService->bypassCurrentUserCondition(true);
170
171
		$raw = $this->circleService->getCircles(
172
			null,
173
			null,
174
			new SimpleDataStore(['includeSystemCircles' => true])
175
		);
176
177
		$circles = [];
178
		foreach ($raw as $circle) {
179
			$circle->getMembers();
180
181
			$circles[] = $this->obfuscateCircle($circle);
182
		}
183
184
		$report->setCircles($circles);
185
186
		return $report;
187
	}
188
189
190
	/**
191
	 * @param InputInterface $input
192
	 * @param Report $report
193
	 */
194
	private function readReport(InputInterface $input, Report $report) {
195
		$output = new ConsoleOutput();
196
		$this->output = $output->section();
197
		$this->report = $report;
198
199
		$interactiveShell = new NC22InteractiveShell($this, $input, $this);
200
		$commands = [
201
			'circles.list',
202
			'circles.delete.#circleId',
203
			'members.list.#circleId',
204
			'members.details.#memberId',
205
			'remoteInstance.list'
206
		];
207
208
		$interactiveShell->setCommands($commands);
209
210
		$interactiveShell->run();
211
	}
212
213
214
	/**
215
	 * @param string $source
216
	 * @param string $field
217
	 *
218
	 * @return string[]
219
	 */
220
	public function fillCommandList(string $source, string $field): array {
221
		echo $source . ' ' . $field . "\n";
222
223
		return ['abcd', 'abdde', 'erfg'];
224
	}
225
226
227
	/**
228
	 * @param string $command
229
	 */
230
	public function manageCommand(string $command): void {
231
//		echo $command . "\n";
232
	}
233
234
235
	/**
236
	 * @param Circle $circle
237
	 *
238
	 * @return Circle
239
	 */
240
	private function obfuscateCircle(Circle $circle): Circle {
241
		$singleId = $this->obfuscateId($circle->getSingleId());
242
		$circle->setSingleId($singleId)
243
			   ->setName($singleId)
244
			   ->setDisplayName($singleId)
245
			   ->setDescription('')
246
			   ->setCreation(0);
247
248
		if ($circle->hasOwner()) {
249
			$circle->setOwner($this->obfuscateMember($circle->getOwner()));
250
		}
251
252
		if ($circle->hasInitiator()) {
253
			$circle->setInitiator($this->obfuscateMember($circle->getInitiator()));
254
		}
255
256
		if ($circle->hasMembers()) {
257
			$members = [];
258
			foreach ($circle->getMembers() as $member) {
259
				$members[] = $this->obfuscateMember($member);
260
			}
261
			$circle->setMembers($members);
262
		}
263
264 View Code Duplication
		if ($circle->hasMemberships()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
265
			$memberships = [];
266
			foreach ($circle->getMemberships() as $membership) {
267
				$memberships[] = $this->obfuscateMembership($membership);
268
			}
269
			$circle->setMemberships($memberships);
270
		}
271
272
273
		return $circle;
274
	}
275
276
277
	/**
278
	 * @param Member $member
279
	 *
280
	 * @return Member
281
	 */
282
	private function obfuscateMember(Member $member): Member {
283
		$memberId = $this->obfuscateId($member->getId());
284
		$singleId = $this->obfuscateId($member->getSingleId());
285
		$circleId = $this->obfuscateId($member->getCircleId());
286
287
		$member->setSingleId($singleId)
288
			   ->setCircleId($circleId)
289
			   ->setId($memberId)
290
			   ->setUserId($singleId)
291
			   ->setDisplayName($singleId)
292
			   ->setDisplayUpdate(0)
293
			   ->setNote('')
294
			   ->setContactId('')
295
			   ->setContactMeta('')
296
			   ->setJoined(0);
297
298
		if ($member->hasCircle()) {
299
			$member->setCircle($this->obfuscateCircle($member->getCircle()));
300
		}
301
302
		if ($member->hasBasedOn()) {
303
			$member->setBasedOn($this->obfuscateCircle($member->getBasedOn()));
304
		}
305
306
		if ($member->hasInheritedBy()) {
307
			$member->setInheritedBy($this->obfuscateFederatedUser($member->getInheritedBy()));
308
		}
309
310
		if ($member->hasInheritanceFrom()) {
311
			$member->setInheritanceFrom($this->obfuscateMember($member->getInheritanceFrom()));
312
		}
313
314
		if ($member->hasRemoteInstance()) {
315
			$member->setRemoteInstance($this->obfuscateRemoteInstance($member->getRemoteInstance()));
316
		}
317
318 View Code Duplication
		if ($member->hasMemberships()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
319
			$memberships = [];
320
			foreach ($member->getMemberships() as $membership) {
321
				$memberships[] = $this->obfuscateMembership($membership);
322
			}
323
			$member->setMemberships($memberships);
324
		}
325
326
		return $member;
327
	}
328
329
330
	/**
331
	 * @param FederatedUser $federatedUser
332
	 *
333
	 * @return FederatedUser
334
	 */
335
	private function obfuscateFederatedUser(FederatedUser $federatedUser): FederatedUser {
336
		$singleId = $this->obfuscateId($federatedUser->getSingleId());
337
		$federatedUser->setSingleId($singleId)
338
					  ->setUserId($singleId);
339
340
		if ($federatedUser->hasBasedOn()) {
341
			$federatedUser->setBasedOn($this->obfuscateCircle($federatedUser->getBasedOn()));
342
		}
343
344
		if ($federatedUser->hasLink()) {
345
			$federatedUser->setLink($this->obfuscateMembership($federatedUser->getLink()));
346
		}
347
348 View Code Duplication
		if ($federatedUser->hasMemberships()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
349
			$memberships = [];
350
			foreach ($federatedUser->getMemberships() as $membership) {
351
				$memberships[] = $this->obfuscateMembership($membership);
352
			}
353
			$federatedUser->setMemberships($memberships);
354
		}
355
356
		return $federatedUser;
357
	}
358
359
360
	/**
361
	 * @param Membership $membership
362
	 *
363
	 * @return Membership
364
	 */
365
	private function obfuscateMembership(Membership $membership): Membership {
366
		$membership->setSingleId($this->obfuscateId($membership->getSingleId()));
367
		$membership->setCircleId($this->obfuscateId($membership->getCircleId()));
368
		$membership->setInheritanceFirst($this->obfuscateId($membership->getInheritanceFirst()));
369
		$membership->setInheritanceLast($this->obfuscateId($membership->getInheritanceLast()));
370
371
		$path = [];
372
		foreach ($membership->getInheritancePath() as $item) {
373
			$path[] = $this->obfuscateId($item);
374
		}
375
		$membership->setInheritancePath($path);
376
377
		return $membership;
378
	}
379
380
381
	/**
382
	 * @param RemoteInstance $remoteInstance
383
	 *
384
	 * @return RemoteInstance
385
	 */
386
	private function obfuscateRemoteInstance(RemoteInstance $remoteInstance): RemoteInstance {
387
		return $remoteInstance;
388
	}
389
390
391
	/**
392
	 * @param string $id
393
	 *
394
	 * @return string
395
	 */
396
	private function obfuscateId(string $id): string {
397
		return substr($id, 0, 5) . '.' . md5(substr($id, 5));
398
	}
399
400
401
	/**
402
	 * @param NC22InteractiveShellSession $session
403
	 */
404
	public function onNewPrompt(NC22InteractiveShellSession $session): void {
405
		$prompt =
406
			'Circles Report [<info>' . $this->report->getSource() . '</info>]:<comment>%PATH%</comment>';
407
408
		$commands = [];
409
		if ($session->getData()->g('currentStatus') === 'write') {
410
			$commands[] = 'cancel';
411
			$commands[] = 'write';
412
			$prompt .= '<error>#</error> ';
413
		} else {
414
			$commands[] = 'edit';
415
			$prompt .= '$ ';
416
		}
417
418
		$session->setGlobalCommands($commands)
419
				->setPrompt($prompt);
420
	}
421
422
423
	/**
424
	 * @param NC22InteractiveShellSession $session
425
	 * @param $command
426
	 */
427
	public function onNewCommand(NC22InteractiveShellSession $session, $command): void {
428
		echo $session->getPath();
429
	}
430
431
432
}
433
434