Completed
Push — federated-circles ( 25ee14...bb3cdd )
by Maxence
02:31
created

FederatedController   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 11
lcom 2
cbo 7
dl 0
loc 158
rs 10
c 1
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
B requestedLink() 0 33 6
A shareFederatedItem() 0 12 1
A asyncAndLeaveClientOutOfThis() 0 14 2
A federatedSuccess() 0 6 1
A federatedFail() 0 9 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\Controller;
28
29
use OC\AppFramework\Http;
30
use OCA\Circles\Model\FederatedLink;
31
use OCA\Circles\Service\FederatedService;
32
use OCA\Circles\Service\CirclesService;
33
use OCA\Circles\Service\ConfigService;
34
use OCA\Circles\Service\MembersService;
35
use OCA\Circles\Service\MiscService;
36
use OCA\Circles\Service\SharesService;
37
use OCP\AppFramework\Http\DataResponse;
38
use OCP\IL10N;
39
40
class FederatedController extends BaseController {
41
42
	/** @var string */
43
	protected $userId;
44
45
	/** @var IL10N */
46
	protected $l10n;
47
48
	/** @var ConfigService */
49
	protected $configService;
50
51
	/** @var CirclesService */
52
	protected $circlesService;
53
54
	/** @var MembersService */
55
	protected $membersService;
56
57
	/** @var SharesService */
58
	protected $sharesService;
59
60
	/** @var FederatedService */
61
	protected $federatedService;
62
63
	/** @var MiscService */
64
	protected $miscService;
65
66
67
	/**
68
	 * requestedLink()
69
	 *
70
	 * Called when a remote circle want to create a link.
71
	 * The function check if it is possible first; then create a link- object
72
	 * and sent it to be saved in the database.
73
	 *
74
	 * @PublicPage
75
	 * @NoCSRFRequired
76
	 *
77
	 * @param string $token
78
	 * @param string $uniqueId
79
	 * @param string $sourceName
80
	 * @param string $linkTo
81
	 * @param string $address
82
	 *
83
	 * @return DataResponse
84
	 */
85
	public function requestedLink($token, $uniqueId, $sourceName, $linkTo, $address) {
86
87
		if (!$this->configService->isFederatedAllowed()) {
88
			return $this->federatedFail('federated_not_allowed');
89
		}
90
91
		$circle = $this->circlesService->infoCircleByName($linkTo);
92
		if ($circle === null) {
93
			return $this->federatedFail('circle_does_not_exist');
94
		}
95
96
		if ($circle->getUniqueId() === $uniqueId) {
97
			return $this->federatedFail('duplicate_unique_id');
98
		}
99
100
		if ($this->federatedService->getLink($circle->getId(), $uniqueId) !== null) {
101
			return $this->federatedFail('duplicate_link');
102
		}
103
104
		$link = new FederatedLink();
105
		$link->setToken($token)
106
			 ->setUniqueId($uniqueId)
107
			 ->setRemoteCircleName($sourceName)
108
			 ->setAddress($address);
109
110
		if ($this->federatedService->initiateLink($circle, $link)) {
111
			return $this->federatedSuccess(
112
				['status' => $link->getStatus(), 'uniqueId' => $circle->getUniqueId()], $link
113
			);
114
		} else {
115
			return $this->federatedFail('link_failed');
116
		}
117
	}
118
119
120
	/**
121
	 * shareFederatedItem()
122
	 *
123
	 * Note: this function will close the request mid-run from the client but will still
124
	 * running its process.
125
	 * Called by a remote circle to broadcast a Share item, the function will save the item
126
	 * in the database and broadcast it locally. A status response is sent to the remote to free
127
	 * the remote process before starting to broadcast the item to other federated links.
128
	 *
129
	 * @PublicPage
130
	 * @NoCSRFRequired
131
	 */
132
	public function shareFederatedItem() {
133
134
		$this->miscService->log("BroadItem start");
135
136
		// We don't want to keep the connection with the client up and running
137
		// as he might have others things to do
138
		$this->asyncAndLeaveClientOutOfThis('done');
139
140
		sleep(15);
141
		$this->miscService->log("BroadItem end");
142
		exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method shareFederatedItem() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
143
	}
144
145
	/**
146
	 * Hacky way to async the rest of the process without keeping client on hold.
147
	 *
148
	 * @param string $result
149
	 */
150
	private function asyncAndLeaveClientOutOfThis($result = '') {
151
		if (ob_get_contents() !== false) {
152
			ob_end_clean();
153
		}
154
155
		header("Connection: close");
156
		ignore_user_abort();
157
		ob_start();
158
		echo($result);
159
		$size = ob_get_length();
160
		header("Content-Length: $size");
161
		ob_end_flush();
162
		flush();
163
	}
164
165
	/**
166
	 * send a positive response to a request with an array of data, and confirm
167
	 * the identity of the link with a token
168
	 *
169
	 * @param array $data
170
	 * @param FederatedLink $link
171
	 *
172
	 * @return DataResponse
173
	 */
174
	private function federatedSuccess($data, $link) {
175
		return new DataResponse(
176
			array_merge($data, ['token' => $link->getToken()]), Http::STATUS_OK
177
		);
178
179
	}
180
181
	/**
182
	 * send a negative response to a request, with a reason of the failure.
183
	 *
184
	 * @param string $reason
185
	 *
186
	 * @return DataResponse
187
	 */
188
	private function federatedFail($reason) {
189
		return new DataResponse(
190
			[
191
				'status' => FederatedLink::STATUS_ERROR,
192
				'reason' => $reason
193
			],
194
			Http::STATUS_OK
195
		);
196
	}
197
}