Completed
Pull Request — master (#490)
by Maxence
02:09
created

ConfigService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
rs 9.9666
cc 1
nc 1
nop 5
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
use daita\MySmallPhpTools\Model\Nextcloud\NC19Request;
30
use OCA\Circles\Exceptions\GSStatusException;
31
use OCA\Circles\Model\Circle;
32
use OCP\IConfig;
33
use OCP\IRequest;
34
use OCP\PreConditionNotMetException;
35
use OCP\Util;
36
37
class ConfigService {
38
39
	const CIRCLES_ALLOW_CIRCLES = 'allow_circles';
40
	const CIRCLES_CONTACT_BACKEND = 'contact_backend';
41
	const CIRCLES_STILL_FRONTEND = 'still_frontend';
42
	const CIRCLES_SWAP_TO_TEAMS = 'swap_to_teams';
43
	const CIRCLES_ALLOW_FEDERATED_CIRCLES = 'allow_federated';
44
	const CIRCLES_GS_ENABLED = 'gs_enabled';
45
	const CIRCLES_MEMBERS_LIMIT = 'members_limit';
46
	const CIRCLES_ACCOUNTS_ONLY = 'accounts_only';
47
	const CIRCLES_ALLOW_LINKED_GROUPS = 'allow_linked_groups';
48
	const CIRCLES_ALLOW_NON_SSL_LINKS = 'allow_non_ssl_links';
49
	const CIRCLES_NON_SSL_LOCAL = 'local_is_non_ssl';
50
	const CIRCLES_SELF_SIGNED = 'self_signed_cert';
51
	const LOCAL_CLOUD_ID = 'local_cloud_id';
52
	const CIRCLES_ACTIVITY_ON_CREATION = 'creation_activity';
53
	const CIRCLES_SKIP_INVITATION_STEP = 'skip_invitation_to_closed_circles';
54
	const CIRCLES_SEARCH_FROM_COLLABORATOR = 'search_from_collaborator';
55
	const CIRCLES_TEST_ASYNC_LOCK = 'test_async_lock';
56
	const CIRCLES_TEST_ASYNC_INIT = 'test_async_init';
57
	const CIRCLES_TEST_ASYNC_HAND = 'test_async_hand';
58
	const CIRCLES_TEST_ASYNC_COUNT = 'test_async_count';
59
60
	const GS_ENABLED = 'enabled';
61
	const GS_MODE = 'mode';
62
	const GS_KEY = 'key';
63
	const GS_LOOKUP = 'lookup';
64
65
	const GS_LOOKUP_INSTANCES = '/instances';
66
67
68
	private $defaults = [
69
		self::CIRCLES_ALLOW_CIRCLES            => Circle::CIRCLES_ALL,
70
		self::CIRCLES_CONTACT_BACKEND          => '0',
71
		self::CIRCLES_STILL_FRONTEND           => '0',
72
		self::CIRCLES_TEST_ASYNC_INIT          => '0',
73
		self::CIRCLES_SWAP_TO_TEAMS            => '0',
74
		self::CIRCLES_ACCOUNTS_ONLY            => '0',
75
		self::CIRCLES_MEMBERS_LIMIT            => '50',
76
		self::CIRCLES_ALLOW_LINKED_GROUPS      => '0',
77
		self::CIRCLES_ALLOW_FEDERATED_CIRCLES  => '0',
78
		self::CIRCLES_GS_ENABLED               => '0',
79
		self::CIRCLES_ALLOW_NON_SSL_LINKS      => '0',
80
		self::CIRCLES_NON_SSL_LOCAL            => '0',
81
		self::CIRCLES_SELF_SIGNED              => '0',
82
		self::LOCAL_CLOUD_ID                   => '',
83
		self::CIRCLES_ACTIVITY_ON_CREATION     => '1',
84
		self::CIRCLES_SKIP_INVITATION_STEP     => '0',
85
		self::CIRCLES_SEARCH_FROM_COLLABORATOR => '0'
86
	];
87
88
	/** @var string */
89
	private $appName;
90
91
	/** @var IConfig */
92
	private $config;
93
94
	/** @var string */
95
	private $userId;
96
97
	/** @var IRequest */
98
	private $request;
99
100
	/** @var MiscService */
101
	private $miscService;
102
103
	/** @var int */
104
	private $allowedCircle = -1;
105
106
	/** @var int */
107
	private $allowedLinkedGroups = -1;
108
109
	/** @var int */
110
	private $allowedFederatedCircles = -1;
111
112
	/** @var int */
113
	private $allowedNonSSLLinks = -1;
114
115
	/** @var int */
116
	private $localNonSSL = -1;
117
118
	/**
119
	 * ConfigService constructor.
120
	 *
121
	 * @param string $appName
122
	 * @param IConfig $config
123
	 * @param IRequest $request
124
	 * @param string $userId
125
	 * @param MiscService $miscService
126
	 */
127
	public function __construct(
128
		$appName, IConfig $config, IRequest $request, $userId, MiscService $miscService
129
	) {
130
		$this->appName = $appName;
131
		$this->config = $config;
132
		$this->request = $request;
133
		$this->userId = $userId;
134
		$this->miscService = $miscService;
135
	}
136
137
138
	public function getLocalAddress() {
139
		return (($this->isLocalNonSSL()) ? 'http://' : '')
140
			   . $this->request->getServerHost();
141
	}
142
143
144
	/**
145
	 * returns if this type of circle is allowed by the current configuration.
146
	 *
147
	 * @param $type
148
	 *
149
	 * @return int
150
	 */
151
	public function isCircleAllowed($type) {
152
		if ($this->allowedCircle === -1) {
153
			$this->allowedCircle = (int)$this->getAppValue(self::CIRCLES_ALLOW_CIRCLES);
154
		}
155
156
		return ((int)$type & (int)$this->allowedCircle);
157
	}
158
159
160
	/**
161
	 * @return bool
162
	 * @throws GSStatusException
163
	 */
164
	public function isLinkedGroupsAllowed() {
165
		if ($this->allowedLinkedGroups === -1) {
166
			$allowed = ($this->getAppValue(self::CIRCLES_ALLOW_LINKED_GROUPS) === '1'
167
						&& !$this->getGSStatus(self::GS_ENABLED));
168
			$this->allowedLinkedGroups = ($allowed) ? 1 : 0;
169
		}
170
171
		return ($this->allowedLinkedGroups === 1);
172
	}
173
174
175
	/**
176
	 * @return bool
177
	 */
178
	public function isFederatedCirclesAllowed() {
179
		if ($this->allowedFederatedCircles === -1) {
180
			$this->allowedFederatedCircles =
181
				(int)$this->getAppValue(self::CIRCLES_ALLOW_FEDERATED_CIRCLES);
182
		}
183
184
		return ($this->allowedFederatedCircles === 1);
185
	}
186
187
	/**
188
	 * @return bool
189
	 */
190
	public function isInvitationSkipped() {
191
		return (int)$this->getAppValue(self::CIRCLES_SKIP_INVITATION_STEP) === 1;
192
	}
193
194
	/**
195
	 * @return bool
196
	 */
197
	public function isLocalNonSSL() {
198
		if ($this->localNonSSL === -1) {
199
			$this->localNonSSL =
200
				(int)$this->getAppValue(self::CIRCLES_NON_SSL_LOCAL);
201
		}
202
203
		return ($this->localNonSSL === 1);
204
	}
205
206
207
	/**
208
	 * @return bool
209
	 */
210
	public function isNonSSLLinksAllowed() {
211
		if ($this->allowedNonSSLLinks === -1) {
212
			$this->allowedNonSSLLinks =
213
				(int)$this->getAppValue(self::CIRCLES_ALLOW_NON_SSL_LINKS);
214
		}
215
216
		return ($this->allowedNonSSLLinks === 1);
217
	}
218
219
220
	/**
221
	 * @param string $remote
222
	 *
223
	 * @return string
224
	 */
225
	public function generateRemoteHost($remote) {
226
		if ((!$this->isNonSSLLinksAllowed() || strpos($remote, 'http://') !== 0)
227
			&& strpos($remote, 'https://') !== 0
228
		) {
229
			$remote = 'https://' . $remote;
230
		}
231
232
		return rtrim($remote, '/');
233
	}
234
235
236
	/**
237
	 * Get a value by key
238
	 *
239
	 * @param string $key
240
	 *
241
	 * @return string
242
	 */
243
	public function getCoreValue($key) {
244
		$defaultValue = null;
245
246
		return $this->config->getAppValue('core', $key, $defaultValue);
247
	}
248
249
	/**
250
	 * Get a value by key
251
	 *
252
	 * @param string $key
253
	 *
254
	 * @return string
255
	 */
256
	public function getSystemValue($key) {
257
		$defaultValue = null;
258
259
		return $this->config->getSystemValue($key, $defaultValue);
260
	}
261
262
263
	/**
264
	 * Get available hosts
265
	 *
266
	 * @return array
267
	 */
268
	public function getAvailableHosts(): array {
269
		return $this->config->getSystemValue('trusted_domains', []);
270
	}
271
272
273
	/**
274
	 * Get a value by key
275
	 *
276
	 * @param string $key
277
	 *
278
	 * @return string
279
	 */
280
	public function getAppValue($key) {
281
		$defaultValue = null;
282
283
		if (array_key_exists($key, $this->defaults)) {
284
			$defaultValue = $this->defaults[$key];
285
		}
286
287
		return $this->config->getAppValue($this->appName, $key, $defaultValue);
288
	}
289
290
	/**
291
	 * Set a value by key
292
	 *
293
	 * @param string $key
294
	 * @param string $value
295
	 *
296
	 * @return void
297
	 */
298
	public function setAppValue($key, $value) {
299
		$this->config->setAppValue($this->appName, $key, $value);
300
	}
301
302
	/**
303
	 * remove a key
304
	 *
305
	 * @param string $key
306
	 *
307
	 * @return string
308
	 */
309
	public function deleteAppValue($key) {
310
		return $this->config->deleteAppValue($this->appName, $key);
311
	}
312
313
	/**
314
	 * Get a user value by key
315
	 *
316
	 * @param string $key
317
	 *
318
	 * @return string
319
	 */
320
	public function getUserValue($key) {
321
		return $this->config->getUserValue($this->userId, $this->appName, $key);
322
	}
323
324
	/**
325
	 * Set a user value by key
326
	 *
327
	 * @param string $key
328
	 * @param string $value
329
	 *
330
	 * @return string
331
	 * @throws PreConditionNotMetException
332
	 */
333
	public function setUserValue($key, $value) {
334
		return $this->config->setUserValue($this->userId, $this->appName, $key, $value);
335
	}
336
337
338
	/**
339
	 * Get a user value by key and user
340
	 *
341
	 * @param string $userId
342
	 * @param string $key
343
	 *
344
	 * @param string $default
345
	 *
346
	 * @return string
347
	 */
348
	public function getCoreValueForUser($userId, $key, $default = '') {
349
		return $this->config->getUserValue($userId, 'core', $key, $default);
350
	}
351
352
353
	/**
354
	 * Get a user value by key and user
355
	 *
356
	 * @param string $userId
357
	 * @param string $key
358
	 *
359
	 * @return string
360
	 */
361
	public function getValueForUser($userId, $key) {
362
		return $this->config->getUserValue($userId, $this->appName, $key);
363
	}
364
365
	/**
366
	 * Set a user value by key
367
	 *
368
	 * @param string $userId
369
	 * @param string $key
370
	 * @param string $value
371
	 *
372
	 * @return string
373
	 * @throws PreConditionNotMetException
374
	 */
375
	public function setValueForUser($userId, $key, $value) {
376
		return $this->config->setUserValue($userId, $this->appName, $key, $value);
377
	}
378
379
	/**
380
	 * return the cloud version.
381
	 * if $complete is true, return a string x.y.z
382
	 *
383
	 * @param boolean $complete
384
	 *
385
	 * @return string|integer
386
	 */
387
	public function getCloudVersion($complete = false) {
388
		$ver = Util::getVersion();
389
390
		if ($complete) {
391
			return implode('.', $ver);
392
		}
393
394
		return $ver[0];
395
	}
396
397
398
	/**
399
	 * @return bool
400
	 */
401
	public function isAccountOnly() {
402
		return ($this->getAppValue(self::CIRCLES_ACCOUNTS_ONLY) === '1');
403
	}
404
405
406
	/**
407
	 * @return bool
408
	 */
409
	public function isContactsBackend(): bool {
410
		return ($this->getAppValue(ConfigService::CIRCLES_CONTACT_BACKEND) !== '0');
411
	}
412
413
414
	public function contactsBackendType(): int {
415
		return (int)$this->getAppValue(ConfigService::CIRCLES_CONTACT_BACKEND);
416
	}
417
418
419
	/**
420
	 * @return bool
421
	 */
422
	public function stillFrontEnd(): bool {
423
		if ($this->getAppValue(self::CIRCLES_CONTACT_BACKEND) !== '1') {
424
			return true;
425
		}
426
427
		if ($this->getAppValue(self::CIRCLES_STILL_FRONTEND) === '1') {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return $this->getAppValu...TILL_FRONTEND) === '1';.
Loading history...
428
			return true;
429
		}
430
431
		return false;
432
	}
433
434
435
	/**
436
	 * should the password for a mail share be send to the recipient
437
	 *
438
	 * @return bool
439
	 */
440
	public function sendPasswordByMail() {
441
		if ($this->getAppValue(self::CIRCLES_CONTACT_BACKEND) === '1') {
442
			return false;
443
		}
444
445
		return ($this->config->getAppValue('sharebymail', 'sendpasswordmail', 'yes') === 'yes');
446
	}
447
448
	/**
449
	 * do we require a share by mail to be password protected
450
	 *
451
	 * @param Circle $circle
452
	 *
453
	 * @return bool
454
	 */
455
	public function enforcePasswordProtection(Circle $circle) {
456
		if ($this->getAppValue(self::CIRCLES_CONTACT_BACKEND) === '1') {
457
			return false;
458
		}
459
460
		if ($circle->getSetting('password_enforcement') === 'true') {
461
			return true;
462
		}
463
464
		return ($this->config->getAppValue('sharebymail', 'enforcePasswordProtection', 'no') === 'yes');
465
	}
466
467
468
	/**
469
	 * @param string $type
470
	 *
471
	 * @return array|bool|mixed
472
	 * @throws GSStatusException
473
	 */
474
	public function getGSStatus(string $type = '') {
475
		$enabled = $this->config->getSystemValueBool('gs.enabled', false);
476
		$lookup = $this->config->getSystemValue('lookup_server', '');
477
478
		if ($lookup === '' || !$enabled) {
479
			if ($type === self::GS_ENABLED) {
480
				return false;
481
			}
482
483
			throw new GSStatusException('GS and lookup are not configured : ' . $lookup . ', ' . $enabled);
484
		}
485
486
		$clef = $this->config->getSystemValue('gss.jwt.key', '');
487
		$mode = $this->config->getSystemValue('gss.mode', '');
488
489
		switch ($type) {
490
			case self::GS_ENABLED:
491
				return $enabled;
492
493
			case self::GS_MODE:
494
				return $mode;
495
496
			case self::GS_KEY:
497
				return $clef;
498
499
			case self::GS_LOOKUP:
500
				return $lookup;
501
		}
502
503
		return [
504
			self::GS_ENABLED => $enabled,
505
			self::GS_LOOKUP  => $lookup,
506
			self::GS_MODE    => $clef,
507
			self::GS_KEY     => $mode,
508
		];
509
	}
510
511
512
	/**
513
	 * @return array
514
	 */
515
	public function getTrustedDomains(): array {
516
		$domains = [];
517
		foreach ($this->config->getSystemValue('trusted_domains', []) as $v) {
518
			$domains[] = $v;
519
		}
520
521
		return $domains;
522
	}
523
524
525
	/**
526
	 * @return string
527
	 */
528
	public function getLocalCloudId(): string {
529
		$localCloudId = $this->getAppValue(self::LOCAL_CLOUD_ID);
530
		if ($localCloudId === '') {
531
			return $this->getTrustedDomains()[0];
532
		}
533
534
		return $localCloudId;
535
	}
536
537
538
	/**
539
	 * @return mixed
540
	 */
541
	public function getInstanceId() {
542
		return $this->config->getSystemValue('instanceid');
543
	}
544
545
546
	/**
547
	 * @param NC19Request $request
548
	 */
549
	public function configureRequest(NC19Request $request) {
550
		if ($this->getAppValue(ConfigService::CIRCLES_SELF_SIGNED) === '1') {
551
			$request->setVerifyPeer(false);
552
		}
553
554
//		if ($this->getAppValue(ConfigService::CIRCLES_NON_SSL_LOCAL) === '1') {
555
			$request->setLocalAddressAllowed(true);
556
//		}
557
	}
558
559
}
560
561