Completed
Push — master ( 462815...ee89ff )
by Maxence
03:04
created

SharesService::generatePayloadDeliveryURL()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 3
rs 10
c 1
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * Circles - Bring cloud-users closer together.
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2017
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
namespace OCA\Circles\Service;
28
29
30
use Exception;
31
use OC\Http\Client\ClientService;
32
use OCA\Circles\Api\v1\Circles;
33
use OCA\Circles\AppInfo\Application;
34
use OCA\Circles\Db\CirclesRequest;
35
use OCA\Circles\Exceptions\CircleDoesNotExistException;
36
use OCA\Circles\Exceptions\MemberDoesNotExistException;
37
use OCA\Circles\Exceptions\PayloadDeliveryException;
38
use OCA\Circles\Exceptions\SharingFrameAlreadyDeliveredException;
39
use OCA\Circles\Exceptions\SharingFrameAlreadyExistException;
40
use OCA\Circles\Exceptions\SharingFrameDoesNotExistException;
41
use OCA\Circles\Model\Circle;
42
use OCA\Circles\Model\FederatedLink;
43
use OCA\Circles\Model\SharingFrame;
44
45
46
class SharesService {
47
48
	/** @var string */
49
	private $userId;
50
51
	/** @var ConfigService */
52
	private $configService;
53
54
	/** @var CirclesRequest */
55
	private $circlesRequest;
56
57
	/** @var BroadcastService */
58
	private $broadcastService;
59
60
	/** @var FederatedLinkService */
61
	private $federatedLinkService;
62
63
	/** @var ClientService */
64
	private $clientService;
65
66
	/** @var MiscService */
67
	private $miscService;
68
69
70
	/**
71
	 * SharesService constructor.
72
	 *
73
	 * @param string $userId
74
	 * @param ConfigService $configService
75
	 * @param CirclesRequest $circlesRequest
76
	 * @param BroadcastService $broadcastService
77
	 * @param FederatedLinkService $federatedLinkService
78
	 * @param ClientService $clientService
79
	 * @param MiscService $miscService
80
	 */
81
	public function __construct(
82
		$userId,
83
		ConfigService $configService,
84
		CirclesRequest $circlesRequest,
85
		BroadcastService $broadcastService,
86
		FederatedLinkService $federatedLinkService,
87
		ClientService $clientService,
88
		MiscService $miscService
89
	) {
90
		$this->userId = (string)$userId;
91
		$this->configService = $configService;
92
		$this->circlesRequest = $circlesRequest;
93
		$this->broadcastService = $broadcastService;
94
		$this->federatedLinkService = $federatedLinkService;
95
		$this->clientService = $clientService;
96
		$this->miscService = $miscService;
97
	}
98
99
100
	/**
101
	 * createFrame()
102
	 *
103
	 * Save the Frame containing the Payload.
104
	 * The Payload will be shared locally, and spread it live if a Broadcaster is set.
105
	 * Function will also initiate the federated broadcast to linked circles.
106
	 *
107
	 * @param string $circleUniqueId
108
	 * @param SharingFrame $frame
109
	 * @param string|null $broadcast
110
	 *
111
	 * @throws Exception
112
	 * @throws MemberDoesNotExistException
113
	 */
114 View Code Duplication
	public function createFrame($circleUniqueId, SharingFrame $frame, $broadcast = null) {
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...
115
116
		try {
117
			$circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId);
118
			$circle->getHigherViewer()
119
				   ->hasToBeMember();
120
121
			$frame->setCircle($circle);
122
123
			$this->generateHeaders($frame, $circle, $broadcast);
124
			$this->circlesRequest->saveFrame($frame);
125
126
			$this->initiateShare($circle->getUniqueId(), $frame->getUniqueId());
127
		} catch (Exception $e) {
128
			throw $e;
129
		}
130
	}
131
132
133
	/**
134
	 * Generate Headers and few more thing like UniqueId and Author.
135
	 * Check if the source is NOT Circles.
136
	 *
137
	 * @param SharingFrame $frame
138
	 * @param Circle $circle
139
	 * @param $broadcast
140
	 */
141
	private function generateHeaders(SharingFrame $frame, Circle $circle, $broadcast) {
142
143
		try {
144
			$frame->cannotBeFromCircles();
145
146
			$frame->setAuthor($this->userId);
147
			$frame->setHeader('author', $this->userId);
148
			$frame->setHeader('circleName', $circle->getName());
149
			$frame->setHeader('circleUniqueId', $circle->getUniqueId());
150
			$frame->setHeader('broadcast', (string)$broadcast);
151
			$frame->generateUniqueId();
152
153
		} catch (Exception $e) {
154
			throw new $e;
155
		}
156
	}
157
158
	/**
159
	 * @param string $circleUniqueId
160
	 * @param string $frameUniqueId
161
	 *
162
	 * @return null|SharingFrame
163
	 * @throws SharingFrameAlreadyDeliveredException
164
	 * @throws SharingFrameDoesNotExistException
165
	 */
166
	public function getFrameFromUniqueId($circleUniqueId, $frameUniqueId) {
167
		if ($frameUniqueId === null || $frameUniqueId === '') {
168
			throw new SharingFrameDoesNotExistException('unknown_share');
169
		}
170
171
		try {
172
			$frame = $this->circlesRequest->getFrame($circleUniqueId, $frameUniqueId);
173
			if ($frame->getCloudId() !== null) {
174
				throw new SharingFrameAlreadyDeliveredException('share_already_delivered');
175
			}
176
		} catch (SharingFrameDoesNotExistException $e) {
177
			throw new SharingFrameDoesNotExistException('unknown_share');
178
		}
179
180
		return $frame;
181
	}
182
183
184
	/**
185
	 * @param string $token
186
	 * @param string $uniqueId
187
	 * @param SharingFrame $frame
188
	 *
189
	 * @return bool
190
	 * @throws Exception
191
	 */
192
	public function receiveFrame($token, $uniqueId, SharingFrame &$frame) {
193
		try {
194
			$link = $this->circlesRequest->getLinkFromToken((string)$token, (string)$uniqueId);
195
		} catch (Exception $e) {
196
			throw $e;
197
		}
198
199
		try {
200
			$this->circlesRequest->getFrame($link->getCircleId(), $frame->getUniqueId());
201
			throw new SharingFrameAlreadyExistException('shares_is_already_known');
202
		} catch (SharingFrameDoesNotExistException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
203
		}
204
205
		try {
206
			$circle = $this->circlesRequest->forceGetCircle($link->getCircleId());
207
		} catch (CircleDoesNotExistException $e) {
208
			throw new CircleDoesNotExistException('unknown_circle');
209
		}
210
211
		$frame->setCircle($circle);
212
		$this->circlesRequest->saveFrame($frame);
213
214
		return true;
215
	}
216
217
218
	/**
219
	 * @param string $circleUniqueId
220
	 * @param string $frameUniqueId
221
	 *
222
	 * @return bool
223
	 * @throws Exception
224
	 */
225
	public function initiateShare($circleUniqueId, $frameUniqueId) {
226
		$args = [
227
			'circleId' => $circleUniqueId,
228
			'frameId'  => $frameUniqueId
229
		];
230
231
		$client = $this->clientService->newClient();
232
		try {
233
			$client->post(
234
				$this->generatePayloadDeliveryURL($this->configService->getLocalAddress()), [
235
																							  'body'            => $args,
236
																							  'timeout'         => 10,
237
																							  'connect_timeout' => 10,
238
																						  ]
239
			);
240
241
			return true;
242
		} catch (Exception $e) {
243
			throw $e;
244
		}
245
	}
246
247
248
	/**
249
	 * @param string $remote
250
	 *
251
	 * @return string
252
	 */
253
	private function generatePayloadDeliveryURL($remote) {
254
		return $this->configService->generateRemoteHost($remote) . Application::REMOTE_URL_PAYLOAD;
255
	}
256
257
258
	/**
259
	 * @param SharingFrame $frame
260
	 *
261
	 * @throws Exception
262
	 */
263
	public function forwardSharingFrame(SharingFrame $frame) {
264
265
		try {
266
			$circle = $this->circlesRequest->forceGetCircle(
267
				$frame->getCircle()
268
					  ->getUniqueId()
269
			);
270
		} catch (CircleDoesNotExistException $e) {
271
			throw new CircleDoesNotExistException('unknown_circle');
272
		}
273
274
		$links = $this->federatedLinkService->getLinksFromCircle(
275
			$frame->getCircle()
276
				  ->getUniqueId()
277
		);
278
279
		$this->forwardSharingFrameToFederatedLinks($circle, $frame, $links);
280
	}
281
282
283
	/**
284
	 * @param Circle $circle
285
	 * @param SharingFrame $frame
286
	 * @param FederatedLink[] $links
287
	 */
288
	private function forwardSharingFrameToFederatedLinks(Circle $circle, SharingFrame $frame, $links) {
289
290
		$args = [
291
			'apiVersion' => Circles::version(),
292
			'uniqueId'   => $circle->getUniqueId(true),
293
			'item'       => json_encode($frame)
294
		];
295
296
		foreach ($links AS $link) {
297
			$args['token'] = $link->getToken(true);
298
			$this->deliverSharingFrameToLink($link, $args);
299
		}
300
	}
301
302
303
	/**
304
	 * sendRemoteShareToLinks();
305
	 *
306
	 * @param FederatedLink $link
307
	 * @param array $args
308
	 */
309
	private function deliverSharingFrameToLink($link, $args) {
310
311
		$client = $this->clientService->newClient();
312
		try {
313
			$request = $client->put(
314
				$this->generatePayloadDeliveryURL($link->getAddress()), [
315
																		  'body'            => $args,
316
																		  'timeout'         => 10,
317
																		  'connect_timeout' => 10,
318
																	  ]
319
			);
320
321
			$result = json_decode($request->getBody(), true);
322
			if ($result['status'] === -1) {
323
				throw new PayloadDeliveryException($result['reason']);
324
			}
325
326
		} catch (Exception $e) {
327
			$this->miscService->log(
328
				'fail to send frame to ' . $link->getAddress() . ' - ' . $e->getMessage()
329
			);
330
		}
331
	}
332
333
334
	/**
335
	 * @param SharingFrame $frame
336
	 */
337
	public function updateFrameWithCloudId(SharingFrame $frame) {
338
		$frame->setCloudId($this->configService->getLocalAddress());
339
		$this->circlesRequest->updateFrame($frame);
340
	}
341
342
343
}