Completed
Pull Request — master (#362)
by Maxence
02:25
created

GSUpstreamService::getInstances()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 9.472
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php declare(strict_types=1);
2
3
4
/**
5
 * Circles - Bring cloud-users closer together.
6
 *
7
 * This file is licensed under the Affero General Public License version 3 or
8
 * later. See the COPYING file.
9
 *
10
 * @author Maxence Lange <[email protected]>
11
 * @copyright 2017
12
 * @license GNU AGPL version 3 or any later version
13
 *
14
 * This program is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License as
16
 * published by the Free Software Foundation, either version 3 of the
17
 * License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License
25
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26
 *
27
 */
28
29
30
namespace OCA\Circles\Service;
31
32
33
use daita\MySmallPhpTools\Exceptions\RequestContentException;
34
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
35
use daita\MySmallPhpTools\Exceptions\RequestResultNotJsonException;
36
use daita\MySmallPhpTools\Exceptions\RequestResultSizeException;
37
use daita\MySmallPhpTools\Exceptions\RequestServerException;
38
use daita\MySmallPhpTools\Model\Request;
39
use daita\MySmallPhpTools\Traits\TArrayTools;
40
use daita\MySmallPhpTools\Traits\TRequest;
41
use Exception;
42
use OCA\Circles\Db\CirclesRequest;
43
use OCA\Circles\Db\GSEventsRequest;
44
use OCA\Circles\Exceptions\GlobalScaleEventException;
45
use OCA\Circles\Exceptions\GSStatusException;
46
use OCA\Circles\Exceptions\JsonException;
47
use OCA\Circles\Exceptions\ModelException;
48
use OCA\Circles\Exceptions\TokenDoesNotExistException;
49
use OCA\Circles\Model\GlobalScale\GSEvent;
50
use OCA\Circles\Model\GlobalScale\GSWrapper;
51
use OCP\IURLGenerator;
52
53
54
/**
55
 * Class GSUpstreamService
56
 *
57
 * @package OCA\Circles\Service
58
 */
59
class GSUpstreamService {
60
61
62
	use TRequest;
63
	use TArrayTools;
64
65
66
	/** @var string */
67
	private $userId = '';
68
69
	/** @var IURLGenerator */
70
	private $urlGenerator;
71
72
	/** @var GSEventsRequest */
73
	private $gsEventsRequest;
74
75
	/** @var CirclesRequest */
76
	private $circlesRequest;
77
78
	/** @var GlobalScaleService */
79
	private $globalScaleService;
80
81
	/** @var ConfigService */
82
	private $configService;
83
84
	/** @var MiscService */
85
	private $miscService;
86
87
88
	/**
89
	 * GSUpstreamService constructor.
90
	 *
91
	 * @param $userId
92
	 * @param IURLGenerator $urlGenerator
93
	 * @param GSEventsRequest $gsEventsRequest
94
	 * @param CirclesRequest $circlesRequest
95
	 * @param GlobalScaleService $globalScaleService
96
	 * @param ConfigService $configService
97
	 * @param MiscService $miscService
98
	 */
99
	public function __construct(
100
		$userId,
101
		IURLGenerator $urlGenerator,
102
		GSEventsRequest $gsEventsRequest,
103
		CirclesRequest $circlesRequest,
104
		GlobalScaleService $globalScaleService,
105
		ConfigService $configService,
106
		MiscService $miscService
107
	) {
108
		$this->userId = $userId;
109
		$this->urlGenerator = $urlGenerator;
110
		$this->gsEventsRequest = $gsEventsRequest;
111
		$this->circlesRequest = $circlesRequest;
112
		$this->globalScaleService = $globalScaleService;
113
		$this->configService = $configService;
114
		$this->miscService = $miscService;
115
	}
116
117
118
	/**
119
	 * @param GSEvent $event
120
	 *
121
	 * @throws Exception
122
	 */
123
	public function newEvent(GSEvent $event) {
124
		try {
125
			$gs = $this->globalScaleService->getGlobalScaleEvent($event);
126
//		if (!$this->configService->getGSStatus(ConfigService::GS_ENABLED)) {
127
//			return true;
128
//		}
129
130
			$this->fillEvent($event);
131
			if ($this->isLocalEvent($event)) {
132
				$gs->verify($event, true);
133
				$gs->manage($event);
134
135
				$this->globalScaleService->asyncBroadcast($event);
136
			} else {
137
				$gs->verify($event);
138
				$this->confirmEvent($event);
139
				$gs->manage($event);
140
			}
141
		} catch (Exception $e) {
142
			$this->miscService->log(
143
				get_class($e) . ' on new event: ' . $e->getMessage() . ' - ' . json_encode($event), 1
144
			);
145
			throw $e;
146
		}
147
	}
148
149
150
	/**
151
	 * @param string $protocol
152
	 * @param GSEvent $event
153
	 *
154
	 * @throws GSStatusException
155
	 */
156
	public function broadcastEvent(string $protocol, GSEvent $event): void {
157
		$this->signEvent($event);
158
159
		$path = $this->urlGenerator->linkToRoute('circles.GlobalScale.broadcast');
160
		$request = new Request($path, Request::TYPE_POST);
161
		$request->setProtocol($protocol);
162
		$request->setDataSerialize($event);
163
164
		foreach ($this->getInstances($protocol) as $instance) {
165
			$request->setAddress($instance);
166
167
			try {
168
				$this->doRequest($request);
169
			} catch (RequestContentException | RequestNetworkException | RequestResultSizeException | RequestServerException $e) {
170
				// TODO: queue request
171
			}
172
		}
173
174
	}
175
176
177
	/**
178
	 * @param GSEvent $event
179
	 *
180
	 * @throws RequestContentException
181
	 * @throws RequestNetworkException
182
	 * @throws RequestResultSizeException
183
	 * @throws RequestServerException
184
	 * @throws RequestResultNotJsonException
185
	 * @throws GlobalScaleEventException
186
	 */
187
	public function confirmEvent(GSEvent $event): void {
188
		$this->signEvent($event);
189
190
		$circle = $event->getCircle();
191
		$owner = $circle->getOwner();
192
//$instance = $this->configService->getLocalCloudId();
193
//$instance = $owner->getInstance();
194
//$instance = ($instance === '') ?
195
		$path = $this->urlGenerator->linkToRoute('circles.GlobalScale.event');
196
197
		$request = new Request($path, Request::TYPE_POST);
198
		$request->setProtocol($_SERVER['REQUEST_SCHEME']);
199
		$request->setAddressFromUrl($owner->getInstance());
200
		$request->setDataSerialize($event);
201
202
		$result = $this->retrieveJson($request);
203
		$this->miscService->log('result ' . json_encode($result));
204
		if ($this->getInt('status', $result) === 0) {
205
			throw new GlobalScaleEventException($this->get('error', $result));
206
		}
207
	}
208
209
210
	/**
211
	 * @param GSEvent $event
212
	 *
213
	 * @throws GSStatusException
214
	 */
215
	private function fillEvent(GSEvent $event): void {
216
		if (!$this->configService->getGSStatus(ConfigService::GS_ENABLED)) {
217
			return;
218
		}
219
220
		$event->setSource($this->configService->getLocalCloudId());
221
	}
222
223
	/**
224
	 * @param string $protocol
225
	 * @param bool $all
226
	 *
227
	 * @return array
228
	 * @throws GSStatusException
229
	 */
230
	public function getInstances(string $protocol, bool $all = false): array {
231
		/** @var string $lookup */
232
		$lookup = $this->configService->getGSStatus(ConfigService::GS_LOOKUP);
233
234
		$request = new Request('/instances', Request::TYPE_GET);
235
		$request->setProtocol($protocol);
236
		$request->setAddressFromUrl($lookup);
237
238
		try {
239
			$instances = $this->retrieveJson($request);
240
		} catch (
241
		RequestContentException |
242
		RequestNetworkException |
243
		RequestResultSizeException |
244
		RequestServerException |
245
		RequestResultNotJsonException $e
246
		) {
247
			$this->miscService->log('Issue while retrieving instances from lookup: ' . $e->getMessage());
248
249
			return [];
250
		}
251
252
		if ($all) {
253
			return $instances;
254
		}
255
256
		return array_diff($instances, $this->configService->getTrustedDomains());
257
	}
258
259
260
	/**
261
	 * @param GSEvent $event
262
	 */
263
	private function signEvent(GSevent $event) {
264
		$event->setKey($this->globalScaleService->getKey());
265
	}
266
267
268
	/**
269
	 * @param GSEvent $event
270
	 *asyncBroadcast
271
	 *
272
	 * @return bool
273
	 */
274
	private function isLocalEvent(GSEvent $event): bool {
275
		if ($event->isLocal()) {
276
			return true;
277
		}
278
279
		$circle = $event->getCircle();
280
		$owner = $circle->getOwner();
281
		if ($owner->getInstance() === ''
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return $owner->getInstan...->getTrustedDomains());.
Loading history...
282
			|| in_array(
283
				$owner->getInstance(), $this->configService->getTrustedDomains()
284
			)) {
285
			return true;
286
		}
287
288
		return false;
289
	}
290
291
292
	/**
293
	 * @param string $token
294
	 *
295
	 * @return GSWrapper
296
	 * @throws JsonException
297
	 * @throws ModelException
298
	 * @throws TokenDoesNotExistException
299
	 */
300
	public function getEventByToken(string $token): GSWrapper {
301
		return $this->gsEventsRequest->getByToken($token);
302
	}
303
304
}
305
306