Completed
Push — master ( 53fcb4...50b7c9 )
by Maxence
02:56
created

FederatedService::allowNonSSLLink()   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
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
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\Db\CirclesRequest;
34
use OCA\Circles\Db\FederatedLinksRequest;
35
use OCA\Circles\Exceptions\FederatedCircleLinkFormatException;
36
use OCA\Circles\Exceptions\FederatedCircleNotAllowaedException;
37
use OCA\Circles\Exceptions\CircleTypeNotValid;
38
use OCA\Circles\Exceptions\FederatedLinkDoesNotExistException;
39
use OCA\Circles\Exceptions\FederatedRemoteCircleDoesNotExistException;
40
use OCA\Circles\Exceptions\FederatedRemoteDoesNotAllowException;
41
use OCA\Circles\Exceptions\FrameAlreadyExistException;
42
use OCA\Circles\Exceptions\LinkCreationException;
43
use OCA\Circles\Exceptions\MemberIsNotAdminException;
44
use OCA\Circles\Model\Circle;
45
use OCA\Circles\Model\FederatedLink;
46
use OCA\Circles\Model\SharingFrame;
47
use OCP\IL10N;
48
49
class FederatedService {
50
51
52
	/** @var string */
53
	private $userId;
54
55
	/** @var IL10N */
56
	private $l10n;
57
58
	/** @var CirclesRequest */
59
	private $circlesRequest;
60
61
	/** @var ConfigService */
62
	private $configService;
63
64
	/** @var CirclesService */
65
	private $circlesService;
66
67
	/** @var BroadcastService */
68
	private $broadcastService;
69
70
	/** @var FederatedLinksRequest */
71
	private $federatedLinksRequest;
72
73
	/** @var string */
74
	private $serverHost;
75
76
	/** @var ClientService */
77
	private $clientService;
78
79
	/** @var MiscService */
80
	private $miscService;
81
82
	/** @var bool */
83
	private $localTest = false;
84
85
	/**
86
	 * CirclesService constructor.
87
	 *
88
	 * @param $userId
89
	 * @param IL10N $l10n
90
	 * @param CirclesRequest $circlesRequest
91
	 * @param ConfigService $configService
92
	 * @param CirclesService $circlesService
93
	 * @param BroadcastService $broadcastService
94
	 * @param FederatedLinksRequest $federatedLinksRequest
95
	 * @param string $serverHost
96
	 * @param ClientService $clientService
97
	 * @param MiscService $miscService
98
	 */
99
	public function __construct(
100
		$userId,
101
		IL10N $l10n,
102
		CirclesRequest $circlesRequest,
103
		ConfigService $configService,
104
		CirclesService $circlesService,
105
		BroadcastService $broadcastService,
106
		FederatedLinksRequest $federatedLinksRequest,
107
		$serverHost,
108
		ClientService $clientService,
109
		MiscService $miscService
110
	) {
111
		$this->userId = $userId;
112
		$this->l10n = $l10n;
113
		$this->circlesRequest = $circlesRequest;
114
		$this->configService = $configService;
115
		$this->circlesService = $circlesService;
116
		$this->broadcastService = $broadcastService;
117
		$this->federatedLinksRequest = $federatedLinksRequest;
118
		$this->serverHost = (string)$serverHost;
119
		$this->clientService = $clientService;
120
		$this->miscService = $miscService;
121
	}
122
123
124
	/**
125
	 * linkCircle()
126
	 *
127
	 * link to a circle.
128
	 * Function will check if settings allow Federated links between circles, and the format of
129
	 * the link ($remote). If no exception, a request to the remote circle will be initiated
130
	 * using requestLinkWithCircle()
131
	 *
132
	 * $remote format: <circle_name>@<remote_host>
133
	 *
134
	 * @param int $circleId
135
	 * @param string $remote
136
	 *
137
	 * @throws Exception
138
	 * @throws FederatedCircleLinkFormatException
139
	 * @throws CircleTypeNotValid
140
	 * @throws MemberIsNotAdminException
141
	 *
142
	 * @return FederatedLink
143
	 */
144
	public function linkCircle($circleId, $remote) {
145
146
		if (!$this->configService->isFederatedAllowed()) {
147
			throw new FederatedCircleNotAllowedException(
148
				$this->l10n->t("Federated circles are not allowed on this Nextcloud")
149
			);
150
		}
151
152
		if (strpos($remote, '@') === false) {
153
			throw new FederatedCircleLinkFormatException(
154
				$this->l10n->t("Federated link does not have a valid format")
155
			);
156
		}
157
158
		try {
159
			return $this->requestLinkWithCircle($circleId, $remote);
160
		} catch (Exception $e) {
161
			throw $e;
162
		}
163
	}
164
165
166
	/**
167
	 * linkStatus()
168
	 *
169
	 * Update the status of a link.
170
	 * Function will check if user can edit the status, will update it and send the update to
171
	 * remote
172
	 *
173
	 * @param int $linkId
174
	 * @param int $status
175
	 *
176
	 * @throws Exception
177
	 * @throws FederatedCircleLinkFormatException
178
	 * @throws CircleTypeNotValid
179
	 * @throws MemberIsNotAdminException
180
	 *
181
	 * @return FederatedLink[]
182
	 */
183
	public function linkStatus($linkId, $status) {
184
185
		if (!$this->configService->isFederatedAllowed()) {
186
			throw new FederatedCircleNotAllowedException(
187
				$this->l10n->t("Federated circles are not allowed on this Nextcloud")
188
			);
189
		}
190
191
		$link = null;
192
		try {
193
194
			$link = $this->circlesRequest->getLinkFromId($linkId);
195
			$circle = $this->circlesRequest->getCircleFromId($link->getCircleId(), $this->userId);
196
			$circle->hasToBeFederated();
197
198
			$link->hasToBeValidStatusUpdate($status);
199
			$link->setStatus($status);
200
201
			$this->federatedLinksRequest->update($link);
0 ignored issues
show
Bug introduced by
It seems like $link defined by $this->circlesRequest->getLinkFromId($linkId) on line 194 can be null; however, OCA\Circles\Db\FederatedLinksRequest::update() 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...
202
203
			$link->setUniqueId($circle->getUniqueId());
204
			$this->updateLinkRemote($link);
0 ignored issues
show
Bug introduced by
It seems like $link defined by $this->circlesRequest->getLinkFromId($linkId) on line 194 can be null; however, OCA\Circles\Service\Fede...ice::updateLinkRemote() 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...
205
206
			return $this->circlesRequest->getLinksFromCircle($circle->getId());
207
		} catch (Exception $e) {
208
			throw $e;
209
		}
210
211
	}
212
213
214
	/**
215
	 * requestLinkWithCircle()
216
	 *
217
	 * Using CircleId, function will get more infos from the database.
218
	 * Will check if author is at least admin and initiate a FederatedLink, save it
219
	 * in the database and send a request to the remote circle using requestLink()
220
	 * If any issue, entry is removed from the database.
221
	 *
222
	 * @param integer $circleId
223
	 * @param string $remote
224
	 *
225
	 * @return FederatedLink
226
	 * @throws Exception
227
	 */
228
	private function requestLinkWithCircle($circleId, $remote) {
229
230
		$link = null;
231
		try {
232
			list($remoteCircle, $remoteAddress) = explode('@', $remote, 2);
233
234
			$circle = $this->circlesService->detailsCircle($circleId);
235
			$circle->getUser()
236
				   ->hasToBeAdmin();
237
			$circle->hasToBeFederated();
238
			$circle->cantBePersonal();
239
240
			$link = new FederatedLink();
241
			$link->setCircleId($circleId)
242
				 ->setLocalAddress($this->serverHost)
243
				 ->setAddress($remoteAddress)
244
				 ->setRemoteCircleName($remoteCircle)
245
				 ->setStatus(FederatedLink::STATUS_LINK_SETUP)
246
				 ->generateToken();
247
248
			$this->federatedLinksRequest->create($link);
249
			$this->requestLink($circle, $link);
250
251
		} catch (Exception $e) {
252
			if ($link !== null) {
253
				$this->federatedLinksRequest->delete($link);
254
			}
255
			throw $e;
256
		}
257
258
		return $link;
259
	}
260
261
262
	/**
263
	 * @param string $remote
264
	 *
265
	 * @return string
266
	 */
267 View Code Duplication
	private function generateLinkRemoteURL($remote) {
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...
268
		if ($this->localTest === false && strpos($remote, 'https') !== 0) {
269
			$remote = 'https://' . $remote;
270
		}
271
272
		return rtrim($remote, '/') . '/index.php/apps/circles/v1/link';
273
	}
274
275
276
	/**
277
	 * @param string $remote
278
	 *
279
	 * @return string
280
	 */
281 View Code Duplication
	private function generatePayloadDeliveryURL($remote) {
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...
282
		if ($this->localTest === false && strpos($remote, 'https') !== 0) {
283
			$remote = 'https://' . $remote;
284
		}
285
286
		return rtrim($remote, '/') . '/index.php/apps/circles/v1/payload';
287
	}
288
289
290
	public function allowNonSSLLink() {
291
		$this->localTest = true;
292
	}
293
294
295
	/**
296
	 * requestLink()
297
	 *
298
	 *
299
	 * @param Circle $circle
300
	 * @param FederatedLink $link
301
	 *
302
	 * @return boolean
303
	 * @throws Exception
304
	 */
305
	private function requestLink(Circle $circle, FederatedLink & $link) {
306
		$args = [
307
			'apiVersion' => Circles::API_VERSION,
308
			'token'      => $link->getToken(),
309
			'uniqueId'   => $circle->getUniqueId(),
310
			'sourceName' => $circle->getName(),
311
			'linkTo'     => $link->getRemoteCircleName(),
312
			'address'    => $link->getLocalAddress()
313
		];
314
315
		$client = $this->clientService->newClient();
316
		//$this->allowNonSSLLink();
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
317
318
		try {
319
			$request = $client->put(
320
				$this->generateLinkRemoteURL($link->getAddress()), [
321
																	 'body'            => $args,
322
																	 'timeout'         => 10,
323
																	 'connect_timeout' => 10,
324
																 ]
325
			);
326
327
			$result = json_decode($request->getBody(), true);
328
329
			if ($result['status'] === FederatedLink::STATUS_LINK_UP) {
330
				$link->setStatus(FederatedLink::STATUS_LINK_UP);
331
			} else if ($result['status'] === FederatedLink::STATUS_LINK_REQUESTED) {
332
				$link->setStatus(FederatedLink::STATUS_REQUEST_SENT);
333
			} else {
334
				$this->parsingRequestLinkResult($result);
335
			}
336
337
			$link->setUniqueId($result['uniqueId']);
338
			$this->federatedLinksRequest->uniqueness($link);
339
			$this->federatedLinksRequest->update($link);
340
341
			return true;
342
		} catch (Exception $e) {
343
			throw $e;
344
		}
345
	}
346
347
348
	/**
349
	 * @param $token
350
	 * @param $uniqueId
351
	 * @param $status
352
	 *
353
	 * @return FederatedLink
0 ignored issues
show
Documentation introduced by
Should the return type not be FederatedLink|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
354
	 * @throws Exception
355
	 */
356
	public function updateLinkLocal($token, $uniqueId, $status) {
357
		try {
358
			$link = $this->circlesRequest->getLinkFromToken($token, $uniqueId);
359
			$link->setStatus($status);
360
			$this->federatedLinksRequest->update($link);
0 ignored issues
show
Bug introduced by
It seems like $link defined by $this->circlesRequest->g...oken($token, $uniqueId) on line 358 can be null; however, OCA\Circles\Db\FederatedLinksRequest::update() 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...
361
362
			return $link;
363
		} catch (Exception $e) {
364
			throw $e;
365
		}
366
	}
367
368
369
	/**
370
	 * updateLinkRemote()
371
	 *
372
	 * Send a request to the remote of the link to update its status.
373
	 *
374
	 * @param FederatedLink $link
375
	 *
376
	 * @return boolean
377
	 * @throws Exception
378
	 */
379
	public function updateLinkRemote(FederatedLink & $link) {
380
		$args = [
381
			'apiVersion' => Circles::API_VERSION,
382
			'token'      => $link->getToken(),
383
			'uniqueId'   => $link->getUniqueId(),
384
			'status'     => $link->getStatus()
385
		];
386
387
		$client = $this->clientService->newClient();
388
		//$this->allowNonSSLLink();
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
389
390
		try {
391
			$request = $client->post(
0 ignored issues
show
Unused Code introduced by
$request 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...
392
				$this->generateLinkRemoteURL($link->getAddress()), [
393
																	 'body'            => $args,
394
																	 'timeout'         => 10,
395
																	 'connect_timeout' => 10,
396
																 ]
397
			);
398
399
//			$result = json_decode($request->getBody(), true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
400
401
//			if ($result['status'] === FederatedLink::STATUS_LINK_UP) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
402
//				$link->setStatus(FederatedLink::STATUS_LINK_UP);
403
//			} else if ($result['status'] === FederatedLink::STATUS_LINK_REQUESTED) {
404
//				$link->setStatus(FederatedLink::STATUS_REQUEST_SENT);
405
//			} else {
406
//				$this->parsingRequestLinkResult($result);
407
//			}
408
//
409
//			$link->setUniqueId($result['uniqueId']);
410
//			$this->federatedLinksRequest->uniqueness($link);
411
//			$this->federatedLinksRequest->update($link);
412
413
			return true;
414
		} catch (Exception $e) {
415
			throw $e;
416
		}
417
	}
418
419
420
	private function parsingRequestLinkResult($result) {
421
422
		if ($result['reason'] === 'federated_not_allowed') {
423
			throw new FederatedRemoteDoesNotAllowException(
424
				$this->l10n->t('Federated circles are not allowed on the remote Nextcloud')
425
			);
426
		}
427
428
		if ($result['reason'] === 'circle_links_disable') {
429
			throw new FederatedRemoteDoesNotAllowException(
430
				$this->l10n->t('The remote circle does not accept Federated Links')
431
			);
432
		}
433
434
		if ($result['reason'] === 'duplicate_unique_id') {
435
			throw new FederatedRemoteDoesNotAllowException(
436
				$this->l10n->t('It seems that you are trying to link a circle to itself')
437
			);
438
		}
439
440
		if ($result['reason'] === 'duplicate_link') {
441
			throw new FederatedRemoteDoesNotAllowException(
442
				$this->l10n->t('This link exists already')
443
			);
444
		}
445
446
		if ($result['reason'] === 'circle_does_not_exist') {
447
			throw new FederatedRemoteCircleDoesNotExistException(
448
				$this->l10n->t('The requested remote circle does not exist')
449
			);
450
		}
451
452
		throw new Exception($result['reason']);
453
	}
454
455
456
	/**
457
	 * Create a new link into database and assign the correct status.
458
	 *
459
	 * @param Circle $circle
460
	 * @param FederatedLink $link
461
	 *
462
	 * @throws Exception
463
	 */
464
	public function initiateLink(Circle $circle, FederatedLink & $link) {
465
466
		try {
467
			$this->checkLinkRequestValidity($circle, $link);
468
			$link->setCircleId($circle->getId());
469
470
			if ($circle->getSetting('allow_links_auto') === 'true') {
471
				$link->setStatus(FederatedLink::STATUS_LINK_UP);
472
			} else {
473
				$link->setStatus(FederatedLink::STATUS_LINK_REQUESTED);
474
			}
475
476
			$this->federatedLinksRequest->create($link);
477
		} catch (Exception $e) {
478
			throw $e;
479
		}
480
	}
481
482
483
	/**
484
	 * @param Circle $circle
485
	 * @param FederatedLink $link
486
	 *
487
	 * @throws LinkCreationException
488
	 */
489
	private function checkLinkRequestValidity($circle, $link) {
490
		if ($circle->getUniqueId() === $link->getUniqueId()) {
491
			throw new LinkCreationException('duplicate_unique_id');
492
		}
493
494
		if ($this->getLink($circle->getId(), $link->getUniqueId()) !== null) {
495
			throw new LinkCreationException('duplicate_link');
496
		}
497
498
		if ($circle->getSetting('allow_links') !== 'true') {
499
			throw new LinkCreationException('circle_links_disable');
500
		}
501
	}
502
503
504
	/**
505
	 * @param string $token
506
	 * @param string $uniqueId
507
	 * @param SharingFrame $frame
508
	 *
509
	 * @return bool
510
	 * @throws Exception
511
	 */
512
	public function receiveFrame($token, $uniqueId, SharingFrame & $frame) {
513
514
		$link = $this->circlesRequest->getLinkFromToken((string)$token, (string)$uniqueId);
515
		if ($link === null) {
516
			throw new FederatedLinkDoesNotExistException('unknown_link');
517
		}
518
519
		if ($this->circlesRequest->getFrame($link->getCircleId(), $frame->getUniqueId())) {
520
			$this->miscService->log("Frame already exist");
521
			throw new FrameAlreadyExistException('shares_is_already_known');
522
		}
523
524
		$circle = $this->circlesRequest->getCircleFromId($link->getCircleId());
525
		if ($circle === null) {
526
			throw new Exception('unknown_circle');
527
		}
528
529
		$frame->setCircleId($link->getCircleId());
530
		$frame->setCircleName($circle->getName());
531
532
		$this->circlesRequest->saveFrame($frame);
533
		$this->broadcastService->broadcastFrame($frame->getHeader('broadcast'), $frame);
534
535
		return true;
536
	}
537
538
	/**
539
	 * @param integer $circleId
540
	 * @param string $uniqueId
541
	 *
542
	 * @return FederatedLink
0 ignored issues
show
Documentation introduced by
Should the return type not be FederatedLink|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
543
	 */
544
	public function getLink($circleId, $uniqueId) {
545
		return $this->federatedLinksRequest->getFromUniqueId($circleId, $uniqueId);
546
	}
547
548
549
	/**
550
	 * @param integer $circleId
551
	 *
552
	 * @return FederatedLink[]
553
	 */
554
	public function getLinks($circleId) {
555
		return $this->federatedLinksRequest->getLinked($circleId);
556
	}
557
558
559
	/**
560
	 * @param int $circleId
561
	 * @param string $uniqueId
562
	 *
563
	 * @return bool
564
	 * @throws Exception
565
	 */
566
	public function initiateRemoteShare($circleId, $uniqueId) {
567
		$args = [
568
			'apiVersion' => Circles::API_VERSION,
569
			'circleId'   => (int)$circleId,
570
			'uniqueId'   => (string)$uniqueId
571
		];
572
573
		$client = $this->clientService->newClient();
574
		try {
575
			$request = $client->post(
576
				$this->generatePayloadDeliveryURL($this->serverHost), [
577
																		'body'            => $args,
578
																		'timeout'         => 10,
579
																		'connect_timeout' => 10,
580
																	]
581
			);
582
583
			$result = json_decode($request->getBody(), true);
584
			$this->miscService->log(
585
				"initiateRemoteShare result: " . $uniqueId . '  ----  ' . var_export($result, true)
586
			);
587
588
			return true;
589
		} catch (Exception $e) {
590
			throw $e;
591
		}
592
	}
593
594
595
	/**
596
	 * @param SharingFrame $frame
597
	 *
598
	 * @throws Exception
599
	 */
600
	public function sendRemoteShare(SharingFrame $frame) {
601
602
		$circle = $this->circlesRequest->getCircleFromId($frame->getCircleId());
603
		if ($circle === null) {
604
			throw new Exception('unknown_circle');
605
		}
606
607
		$links = $this->getLinks($frame->getCircleId());
608
		foreach ($links AS $link) {
609
610
			$args = [
611
				'apiVersion' => Circles::API_VERSION,
612
				'token'      => $link->getToken(),
613
				'uniqueId'   => $circle->getUniqueId(),
614
				'item'       => json_encode($frame)
615
			];
616
617
			$client = $this->clientService->newClient();
618
			try {
619
				$client->put(
620
					$this->generatePayloadDeliveryURL($link->getAddress()), [
621
																			  'body'            => $args,
622
																			  'timeout'         => 10,
623
																			  'connect_timeout' => 10,
624
																		  ]
625
				);
626
			} catch (Exception $e) {
627
				throw $e;
628
			}
629
		}
630
	}
631
632
633
	/**
634
	 * generateHeaders()
635
	 *
636
	 * Generate new headers for the current Payload, and save them in the SharingFrame.
637
	 *
638
	 * @param SharingFrame $frame
639
	 */
640
	public function updateFrameWithCloudId(SharingFrame $frame) {
641
		$frame->setCloudId($this->serverHost);
642
		$this->circlesRequest->updateFrame($frame);
643
	}
644
645
}