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 2021 |
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\Model\Federated; |
33
|
|
|
|
34
|
|
|
|
35
|
|
|
use daita\MySmallPhpTools\Db\Nextcloud\nc22\INC22QueryRow; |
36
|
|
|
use daita\MySmallPhpTools\Model\Nextcloud\nc22\NC22Signatory; |
37
|
|
|
use daita\MySmallPhpTools\Traits\TArrayTools; |
38
|
|
|
use JsonSerializable; |
39
|
|
|
use OCA\Circles\Exceptions\RemoteNotFoundException; |
40
|
|
|
use OCA\Circles\Exceptions\RemoteUidException; |
41
|
|
|
|
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Class AppService |
45
|
|
|
* |
46
|
|
|
* @package OCA\Circles\Model |
47
|
|
|
*/ |
48
|
|
|
class RemoteInstance extends NC22Signatory implements INC22QueryRow, JsonSerializable { |
49
|
|
|
|
50
|
|
|
|
51
|
|
|
use TArrayTools; |
52
|
|
|
|
53
|
|
|
const TYPE_UNKNOWN = 'Unknown'; // not trusted |
54
|
|
|
const TYPE_PASSIVE = 'Passive'; // Minimum information about Federated Circles are broadcasted if a member belongs to the circle. |
55
|
|
|
const TYPE_EXTERNAL = 'External'; // info about Federated Circles and their members are broadcasted if a member belongs to the circle. |
56
|
|
|
const TYPE_TRUSTED = 'Trusted'; // everything about Federated Circles are broadcasted. |
57
|
|
|
const TYPE_GLOBALSCALE = 'GlobalScale'; // every Circle is broadcasted, |
58
|
|
|
|
59
|
|
|
public static $LIST_TYPE = [ |
60
|
|
|
self::TYPE_UNKNOWN, |
61
|
|
|
self::TYPE_PASSIVE, |
62
|
|
|
self::TYPE_EXTERNAL, |
63
|
|
|
self::TYPE_TRUSTED, |
64
|
|
|
self::TYPE_GLOBALSCALE |
65
|
|
|
]; |
66
|
|
|
|
67
|
|
|
const TEST = 'test'; |
68
|
|
|
const INCOMING = 'incoming'; |
69
|
|
|
const EVENT = 'event'; |
70
|
|
|
const CIRCLES = 'circles'; |
71
|
|
|
const CIRCLE = 'circle'; |
72
|
|
|
const MEMBERS = 'members'; |
73
|
|
|
const MEMBER = 'member'; |
74
|
|
|
|
75
|
|
|
|
76
|
|
|
/** @var int */ |
77
|
|
|
private $dbId = 0; |
78
|
|
|
|
79
|
|
|
/** @var string */ |
80
|
|
|
private $type = self::TYPE_UNKNOWN; |
81
|
|
|
|
82
|
|
|
/** @var int */ |
83
|
|
|
private $interface = 0; |
84
|
|
|
|
85
|
|
|
/** @var string */ |
86
|
|
|
private $test = ''; |
87
|
|
|
|
88
|
|
|
/** @var array */ |
89
|
|
|
private $aliases = []; |
90
|
|
|
|
91
|
|
|
/** @var string */ |
92
|
|
|
private $incoming = ''; |
93
|
|
|
|
94
|
|
|
/** @var string */ |
95
|
|
|
private $root = ''; |
96
|
|
|
|
97
|
|
|
/** @var string */ |
98
|
|
|
private $event = ''; |
99
|
|
|
|
100
|
|
|
/** @var string */ |
101
|
|
|
private $circles = ''; |
102
|
|
|
|
103
|
|
|
/** @var string */ |
104
|
|
|
private $circle = ''; |
105
|
|
|
|
106
|
|
|
/** @var string */ |
107
|
|
|
private $members = ''; |
108
|
|
|
|
109
|
|
|
/** @var string */ |
110
|
|
|
private $member = ''; |
111
|
|
|
|
112
|
|
|
/** @var string */ |
113
|
|
|
private $uid = ''; |
114
|
|
|
|
115
|
|
|
/** @var string */ |
116
|
|
|
private $authSigned = ''; |
117
|
|
|
|
118
|
|
|
/** @var bool */ |
119
|
|
|
private $identityAuthed = false; |
120
|
|
|
|
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @param int $dbId |
124
|
|
|
* |
125
|
|
|
* @return self |
126
|
|
|
*/ |
127
|
|
|
public function setDbId(int $dbId): self { |
128
|
|
|
$this->dbId = $dbId; |
129
|
|
|
|
130
|
|
|
return $this; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* @return int |
135
|
|
|
*/ |
136
|
|
|
public function getDbId(): int { |
137
|
|
|
return $this->dbId; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* @param string $type |
143
|
|
|
* |
144
|
|
|
* @return $this |
145
|
|
|
*/ |
146
|
|
|
public function setType(string $type): self { |
147
|
|
|
$this->type = $type; |
148
|
|
|
|
149
|
|
|
return $this; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* @return string |
154
|
|
|
*/ |
155
|
|
|
public function getType(): string { |
156
|
|
|
return $this->type; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* @param int $interface |
162
|
|
|
* |
163
|
|
|
* @return RemoteInstance |
164
|
|
|
*/ |
165
|
|
|
public function setInterface(int $interface): self { |
166
|
|
|
$this->interface = $interface; |
167
|
|
|
|
168
|
|
|
return $this; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* @return int |
173
|
|
|
*/ |
174
|
|
|
public function getInterface(): int { |
175
|
|
|
return $this->interface; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* @param array $aliases |
181
|
|
|
* |
182
|
|
|
* @return RemoteInstance |
183
|
|
|
*/ |
184
|
|
|
public function setAliases(array $aliases): self { |
185
|
|
|
$this->aliases = $aliases; |
186
|
|
|
|
187
|
|
|
return $this; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* @return array |
192
|
|
|
*/ |
193
|
|
|
public function getAliases(): array { |
194
|
|
|
return $this->aliases; |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* @return string |
200
|
|
|
*/ |
201
|
|
|
public function getIncoming(): string { |
202
|
|
|
return $this->incoming; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* @param string $incoming |
207
|
|
|
* |
208
|
|
|
* @return self |
209
|
|
|
*/ |
210
|
|
|
public function setIncoming(string $incoming): self { |
211
|
|
|
$this->incoming = $incoming; |
212
|
|
|
|
213
|
|
|
return $this; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @return string |
219
|
|
|
*/ |
220
|
|
|
public function getRoot(): string { |
221
|
|
|
return $this->root; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* @param string $root |
226
|
|
|
* |
227
|
|
|
* @return $this |
228
|
|
|
*/ |
229
|
|
|
public function setRoot(string $root): self { |
230
|
|
|
$this->root = $root; |
231
|
|
|
|
232
|
|
|
return $this; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* @return string |
238
|
|
|
*/ |
239
|
|
|
public function getEvent(): string { |
240
|
|
|
return $this->event; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* @param string $event |
245
|
|
|
* |
246
|
|
|
* @return self |
247
|
|
|
*/ |
248
|
|
|
public function setEvent(string $event): self { |
249
|
|
|
$this->event = $event; |
250
|
|
|
|
251
|
|
|
return $this; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* @param string $test |
257
|
|
|
* |
258
|
|
|
* @return RemoteInstance |
259
|
|
|
*/ |
260
|
|
|
public function setTest(string $test): self { |
261
|
|
|
$this->test = $test; |
262
|
|
|
|
263
|
|
|
return $this; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* @return string |
268
|
|
|
*/ |
269
|
|
|
public function getTest(): string { |
270
|
|
|
return $this->test; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* @return string |
276
|
|
|
*/ |
277
|
|
|
public function getCircles(): string { |
278
|
|
|
return $this->circles; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* @param string $circles |
283
|
|
|
* |
284
|
|
|
* @return self |
285
|
|
|
*/ |
286
|
|
|
public function setCircles(string $circles): self { |
287
|
|
|
$this->circles = $circles; |
288
|
|
|
|
289
|
|
|
return $this; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* @return string |
295
|
|
|
*/ |
296
|
|
|
public function getCircle(): string { |
297
|
|
|
return $this->circle; |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* @param string $circle |
302
|
|
|
* |
303
|
|
|
* @return self |
304
|
|
|
*/ |
305
|
|
|
public function setCircle(string $circle): self { |
306
|
|
|
$this->circle = $circle; |
307
|
|
|
|
308
|
|
|
return $this; |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* @return string |
314
|
|
|
*/ |
315
|
|
|
public function getMembers(): string { |
316
|
|
|
return $this->members; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* @param string $members |
321
|
|
|
* |
322
|
|
|
* @return self |
323
|
|
|
*/ |
324
|
|
|
public function setMembers(string $members): self { |
325
|
|
|
$this->members = $members; |
326
|
|
|
|
327
|
|
|
return $this; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* @return string |
333
|
|
|
*/ |
334
|
|
|
public function getMember(): string { |
335
|
|
|
return $this->member; |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
/** |
339
|
|
|
* @param string $member |
340
|
|
|
* |
341
|
|
|
* @return self |
342
|
|
|
*/ |
343
|
|
|
public function setMember(string $member): self { |
344
|
|
|
$this->member = $member; |
345
|
|
|
|
346
|
|
|
return $this; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* @return $this |
352
|
|
|
*/ |
353
|
|
|
public function setUidFromKey(): self { |
354
|
|
|
$this->setUid(hash('sha512', $this->getPublicKey())); |
355
|
|
|
|
356
|
|
|
return $this; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* @param string $uid |
361
|
|
|
* |
362
|
|
|
* @return RemoteInstance |
363
|
|
|
*/ |
364
|
|
|
public function setUid(string $uid): self { |
365
|
|
|
$this->uid = $uid; |
366
|
|
|
|
367
|
|
|
return $this; |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* @param bool $shorten |
372
|
|
|
* |
373
|
|
|
* @return string |
374
|
|
|
*/ |
375
|
|
|
public function getUid(bool $shorten = false): string { |
376
|
|
|
if ($shorten) { |
377
|
|
|
return substr($this->uid, 0, 18); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
return $this->uid; |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* @param string $authSigned |
386
|
|
|
* |
387
|
|
|
* @return RemoteInstance |
388
|
|
|
*/ |
389
|
|
|
public function setAuthSigned(string $authSigned): self { |
390
|
|
|
$this->authSigned = $authSigned; |
391
|
|
|
|
392
|
|
|
return $this; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* @return string |
397
|
|
|
*/ |
398
|
|
|
public function getAuthSigned(): string { |
399
|
|
|
return $this->authSigned; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
|
403
|
|
|
/** |
404
|
|
|
* @param bool $identityAuthed |
405
|
|
|
* |
406
|
|
|
* @return RemoteInstance |
407
|
|
|
*/ |
408
|
|
|
public function setIdentityAuthed(bool $identityAuthed): self { |
409
|
|
|
$this->identityAuthed = $identityAuthed; |
410
|
|
|
|
411
|
|
|
return $this; |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
/** |
415
|
|
|
* @return bool |
416
|
|
|
*/ |
417
|
|
|
public function isIdentityAuthed(): bool { |
418
|
|
|
return $this->identityAuthed; |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
/** |
422
|
|
|
* @throws RemoteUidException |
423
|
|
|
*/ |
424
|
|
|
public function mustBeIdentityAuthed(): void { |
425
|
|
|
if (!$this->isIdentityAuthed()) { |
426
|
|
|
throw new RemoteUidException('identity not authed'); |
427
|
|
|
} |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
|
431
|
|
|
/** |
432
|
|
|
* @param array $data |
433
|
|
|
* |
434
|
|
|
* @return NC22Signatory |
435
|
|
|
*/ |
436
|
|
|
public function import(array $data): NC22Signatory { |
437
|
|
|
parent::import($data); |
438
|
|
|
|
439
|
|
|
$this->setTest($this->get('test', $data)) |
440
|
|
|
->setAliases($this->getArray('aliases', $data)) |
441
|
|
|
->setEvent($this->get('event', $data)) |
442
|
|
|
->setRoot($this->get('root', $data)) |
443
|
|
|
->setIncoming($this->get('incoming', $data)) |
444
|
|
|
->setCircles($this->get('circles', $data)) |
445
|
|
|
->setCircle($this->get('circle', $data)) |
446
|
|
|
->setMembers($this->get('members', $data)) |
447
|
|
|
->setMember($this->get('member', $data)) |
448
|
|
|
->setUid($this->get('uid', $data)); |
449
|
|
|
|
450
|
|
|
$algo = ''; |
451
|
|
|
$authSigned = trim($this->get('auth-signed', $data), ':'); |
452
|
|
|
if (strpos($authSigned, ':') > 0) { |
453
|
|
|
list($algo, $authSigned) = explode(':', $authSigned); |
454
|
|
|
} |
455
|
|
|
|
456
|
|
|
$this->setAuthSigned($authSigned) |
457
|
|
|
->setAlgorithm($algo); |
458
|
|
|
|
459
|
|
|
return $this; |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
|
463
|
|
|
/** |
464
|
|
|
* @return array |
465
|
|
|
*/ |
466
|
|
|
public function jsonSerialize(): array { |
467
|
|
|
$data = [ |
468
|
|
|
'uid' => $this->getUid(true), |
469
|
|
|
'root' => $this->getRoot(), |
470
|
|
|
'event' => $this->getEvent(), |
471
|
|
|
'incoming' => $this->getIncoming(), |
472
|
|
|
'test' => $this->getTest(), |
473
|
|
|
'circles' => $this->getCircles(), |
474
|
|
|
'circle' => $this->getCircle(), |
475
|
|
|
'members' => $this->getMembers(), |
476
|
|
|
'member' => $this->getMember(), |
477
|
|
|
]; |
478
|
|
|
|
479
|
|
|
if ($this->getAuthSigned() !== '') { |
480
|
|
|
$data['auth-signed'] = $this->getAlgorithm() . ':' . $this->getAuthSigned(); |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
if (!empty($this->getAliases())) { |
484
|
|
|
$data['aliases'] = $this->getAliases(); |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
return array_filter(array_merge($data, parent::jsonSerialize())); |
488
|
|
|
} |
489
|
|
|
|
490
|
|
|
|
491
|
|
|
/** |
492
|
|
|
* @param array $data |
493
|
|
|
* @param string $prefix |
494
|
|
|
* |
495
|
|
|
* @return self |
496
|
|
|
* @throws RemoteNotFoundException |
497
|
|
|
*/ |
498
|
|
|
public function importFromDatabase(array $data, string $prefix = ''): INC22QueryRow { |
499
|
|
|
if ($this->getInt($prefix . 'id', $data) === 0) { |
500
|
|
|
throw new RemoteNotFoundException(); |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
$this->setDbId($this->getInt($prefix . 'id', $data)); |
504
|
|
|
$this->import($this->getArray($prefix . 'item', $data)); |
505
|
|
|
$this->setOrigData($this->getArray($prefix . 'item', $data)); |
506
|
|
|
$this->setType($this->get($prefix . 'type', $data)); |
507
|
|
|
$this->setInterface($this->getInt($prefix . 'interface', $data)); |
508
|
|
|
$this->setInstance($this->get($prefix . 'instance', $data)); |
509
|
|
|
$this->setId($this->get($prefix . 'href', $data)); |
510
|
|
|
|
511
|
|
|
return $this; |
|
|
|
|
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.