Completed
Pull Request — master (#551)
by Maxence
02:15
created

RemoteController   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 277
Duplicated Lines 11.55 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 12
dl 32
loc 277
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 1
A event() 0 22 5
A incoming() 0 11 2
A test() 0 5 1
A circles() 0 15 1
A circle() 0 18 3
A members() 16 16 2
A member() 16 16 2
A confirmRemoteInstance() 0 19 4
A extractEventFromRequest() 0 10 1

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
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 2020
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\Controller;
33
34
use daita\MySmallPhpTools\Exceptions\InvalidItemException;
35
use daita\MySmallPhpTools\Exceptions\InvalidOriginException;
36
use daita\MySmallPhpTools\Exceptions\MalformedArrayException;
37
use daita\MySmallPhpTools\Exceptions\SignatoryException;
38
use daita\MySmallPhpTools\Exceptions\SignatureException;
39
use daita\MySmallPhpTools\Model\Nextcloud\nc21\NC21SignedRequest;
40
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Controller;
41
use Exception;
42
use OCA\Circles\Db\CircleRequest;
43
use OCA\Circles\Exceptions\CircleNotFoundException;
44
use OCA\Circles\Exceptions\FederatedEventDSyncException;
45
use OCA\Circles\Exceptions\FederatedItemException;
46
use OCA\Circles\Model\Federated\FederatedEvent;
47
use OCA\Circles\Model\Federated\RemoteInstance;
48
use OCA\Circles\Service\CircleService;
49
use OCA\Circles\Service\ConfigService;
50
use OCA\Circles\Service\FederatedUserService;
51
use OCA\Circles\Service\MemberService;
52
use OCA\Circles\Service\RemoteDownstreamService;
53
use OCA\Circles\Service\RemoteStreamService;
54
use OCP\AppFramework\Controller;
55
use OCP\AppFramework\Http;
56
use OCP\AppFramework\Http\DataResponse;
57
use OCP\IRequest;
58
59
60
/**
61
 * Class RemoteController
62
 *
63
 * @package OCA\Circles\Controller
64
 */
65
class RemoteController extends Controller {
66
67
68
	use TNC21Controller;
69
70
71
	/** @var CircleRequest */
72
	private $circleRequest;
73
74
	/** @var RemoteStreamService */
75
	private $remoteStreamService;
76
77
	/** @var RemoteDownstreamService */
78
	private $remoteDownstreamService;
79
80
	/** @var FederatedUserService */
81
	private $federatedUserService;
82
83
	/** @var CircleService */
84
	private $circleService;
85
86
	/** @var MemberService */
87
	private $memberService;
88
89
	/** @var ConfigService */
90
	private $configService;
91
92
93
	/**
94
	 * RemoteController constructor.
95
	 *
96
	 * @param string $appName
97
	 * @param IRequest $request
98
	 * @param CircleRequest $circleRequest
99
	 * @param RemoteStreamService $remoteStreamService
100
	 * @param RemoteDownstreamService $remoteDownstreamService
101
	 * @param FederatedUserService $federatedUserService
102
	 * @param CircleService $circleService
103
	 * @param MemberService $memberService
104
	 * @param ConfigService $configService
105
	 */
106
	public function __construct(
107
		string $appName, IRequest $request, CircleRequest $circleRequest,
108
		RemoteStreamService $remoteStreamService,
109
		RemoteDownstreamService $remoteDownstreamService, FederatedUserService $federatedUserService,
110
		CircleService $circleService, MemberService $memberService, ConfigService $configService
111
	) {
112
		parent::__construct($appName, $request);
113
		$this->circleRequest = $circleRequest;
114
		$this->remoteStreamService = $remoteStreamService;
115
		$this->remoteDownstreamService = $remoteDownstreamService;
116
		$this->federatedUserService = $federatedUserService;
117
		$this->circleService = $circleService;
118
		$this->memberService = $memberService;
119
		$this->configService = $configService;
120
121
		$this->setup('app', 'circles');
122
	}
123
124
125
	/**
126
	 * @PublicPage
127
	 * @NoCSRFRequired
128
	 *
129
	 * @return DataResponse
130
	 */
131
	public function event(): DataResponse {
132
		try {
133
			$event = $this->extractEventFromRequest();
134
		} catch (Exception $e) {
135
			return $this->fail($e, [], Http::STATUS_BAD_REQUEST);
136
		}
137
138
		try {
139
			$this->remoteDownstreamService->requestedEvent($event);
140
		} catch (FederatedItemException $e) {
141
			$this->e($e, ['event' => $event]);
142
			$event->setReadingOutcome($e->getMessage(), $e->getParams(), true);
143
		} catch (FederatedEventDSyncException $e) {
144
			return $this->fail($e, [], Http::STATUS_CONFLICT);
145
		} catch (Exception $e) {
146
			$this->e($e);
147
148
			return $this->fail($e, [], Http::STATUS_BAD_REQUEST);
149
		}
150
151
		return $this->successObj($event->getOutcome());
152
	}
153
154
155
	/**
156
	 * @PublicPage
157
	 * @NoCSRFRequired
158
	 *
159
	 * @return DataResponse
160
	 */
161
	public function incoming(): DataResponse {
162
		try {
163
			$event = $this->extractEventFromRequest();
164
165
			$result = $this->remoteDownstreamService->incomingEvent($event);
166
167
			return $this->success($result);
168
		} catch (Exception $e) {
169
			return $this->fail($e);
170
		}
171
	}
172
173
174
	/**
175
	 * @PublicPage
176
	 * @NoCSRFRequired
177
	 *
178
	 * @return DataResponse
179
	 * @throws InvalidOriginException
180
	 * @throws MalformedArrayException
181
	 * @throws SignatoryException
182
	 * @throws SignatureException
183
	 */
184
	public function test(): DataResponse {
185
		$test = $this->remoteStreamService->incomingSignedRequest($this->configService->getLocalInstance());
186
187
		return $this->successObj($test);
188
	}
189
190
191
	/**
192
	 * @PublicPage
193
	 * @NoCSRFRequired
194
	 *
195
	 * @return DataResponse
196
	 */
197
	public function circles(): DataResponse {
198
//		$circles = $this->circleRequest->getFederated();
199
//
200
//		try {
201
//			/** @var Circle $circle */
202
//			$circle = $this->extractItemFromRequest(Circle::class, $signed);
203
////			$event->setIncomingOrigin($signed->getOrigin());
204
//
205
//			//$result = $this->remoteDownstreamService->incomingEvent($event);
206
//
207
//			return $this->successObj($circle);
208
//		} catch (Exception $e) {
209
//			return $this->fail($e);
210
//		}
211
	}
212
213
214
	/**
215
	 * @PublicPage
216
	 * @NoCSRFRequired
217
	 *
218
	 * @param string $circleId
219
	 *
220
	 * @return DataResponse
221
	 */
222
	public function circle(string $circleId): DataResponse {
223
		try {
224
			$signed =
225
				$this->remoteStreamService->incomingSignedRequest($this->configService->getLocalInstance());
226
			$remoteInstance = $this->confirmRemoteInstance($signed);
227
228
			$this->federatedUserService->setRemoteInstance($remoteInstance);
229
			$this->federatedUserService->bypassCurrentUserCondition(true);
230
231
			$circle = $this->circleService->getCircle($circleId);
232
233
			return $this->successObj($circle);
234
		} catch (CircleNotFoundException $e) {
235
			return $this->success([], false);
236
		} catch (Exception $e) {
237
			return $this->fail($e);
238
		}
239
	}
240
241
242
	/**
243
	 * @PublicPage
244
	 * @NoCSRFRequired
245
	 *
246
	 * @param string $circleId
247
	 *
248
	 * @return DataResponse
249
	 */
250 View Code Duplication
	public function members(string $circleId): DataResponse {
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...
251
		try {
252
			$signed =
253
				$this->remoteStreamService->incomingSignedRequest($this->configService->getLocalInstance());
254
			$remoteInstance = $this->confirmRemoteInstance($signed);
0 ignored issues
show
Unused Code introduced by
$remoteInstance is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
255
256
//			$this->federatedUserService->setRemoteInstance($remoteInstance);
257
//			$this->federatedUserService->bypassCurrentUserCondition(true);
258
259
			$members = $this->memberService->getMembers($circleId);
260
261
			return $this->success($members, false);
262
		} catch (Exception $e) {
263
			return $this->fail($e);
264
		}
265
	}
266
267
268
	/**
269
	 * @PublicPage
270
	 * @NoCSRFRequired
271
	 *
272
	 * @param string $type
273
	 * @param string $userId
274
	 *
275
	 * @return DataResponse
276
	 */
277 View Code Duplication
	public function member(string $type, string $userId): DataResponse {
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...
278
		try {
279
			$signed =
280
				$this->remoteStreamService->incomingSignedRequest($this->configService->getLocalInstance());
281
			$remoteInstance = $this->confirmRemoteInstance($signed);
0 ignored issues
show
Unused Code introduced by
$remoteInstance is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
282
283
//			$this->federatedUserService->setRemoteInstance($remoteInstance);
284
//			$this->federatedUserService->bypassCurrentUserCondition(true);
285
286
			$federatedUser = $this->federatedUserService->createLocalFederatedUser($userId);
287
288
			return $this->successObj($federatedUser);
289
		} catch (Exception $e) {
290
			return $this->fail($e);
291
		}
292
	}
293
294
295
	/**
296
	 * @param NC21SignedRequest $signedRequest
297
	 *
298
	 * @return RemoteInstance
299
	 * @throws SignatoryException
300
	 */
301
	private function confirmRemoteInstance(NC21SignedRequest $signedRequest): RemoteInstance {
302
		/** @var RemoteInstance $signatory */
303
		$signatory = $signedRequest->getSignatory();
304
305
		if (!$signatory instanceof RemoteInstance) {
306
			$this->debug('Signatory is not a known RemoteInstance', ['signedRequest' => $signedRequest]);
307
			throw new SignatoryException('Could not confirm identity');
308
		}
309
310
		\OC::$server->getLogger()->log(3, '###' . get_class($signatory));
311
		// TODO: confirm local istance is safe ?
312
		if (!$this->configService->isLocalInstance($signedRequest->getOrigin())
313
			&& $signatory->getType() === RemoteInstance::TYPE_UNKNOWN) {
314
			$this->debug('Could not confirm identity', ['signedRequest' => $signedRequest]);
315
			throw new SignatoryException('Could not confirm identity');
316
		}
317
318
		return $signatory;
319
	}
320
321
322
	/**
323
	 * @return FederatedEvent
324
	 * @throws InvalidOriginException
325
	 * @throws MalformedArrayException
326
	 * @throws SignatoryException
327
	 * @throws SignatureException
328
	 * @throws InvalidItemException
329
	 */
330
	private function extractEventFromRequest(): FederatedEvent {
331
		$signed = $this->remoteStreamService->incomingSignedRequest($this->configService->getLocalInstance());
332
		$this->confirmRemoteInstance($signed);
333
334
		$event = new FederatedEvent();
335
		$event->import(json_decode($signed->getBody(), true));
336
		$event->setIncomingOrigin($signed->getOrigin());
337
338
		return $event;
339
	}
340
341
}
342
343