Completed
Pull Request — master (#9834)
by John
35:12 queued 15:13
created
settings/Controller/AppSettingsController.php 1 patch
Indentation   +484 added lines, -484 removed lines patch added patch discarded remove patch
@@ -58,489 +58,489 @@
 block discarded – undo
58 58
  */
59 59
 class AppSettingsController extends Controller {
60 60
 
61
-	/** @var \OCP\IL10N */
62
-	private $l10n;
63
-	/** @var IConfig */
64
-	private $config;
65
-	/** @var INavigationManager */
66
-	private $navigationManager;
67
-	/** @var IAppManager */
68
-	private $appManager;
69
-	/** @var CategoryFetcher */
70
-	private $categoryFetcher;
71
-	/** @var AppFetcher */
72
-	private $appFetcher;
73
-	/** @var IFactory */
74
-	private $l10nFactory;
75
-	/** @var BundleFetcher */
76
-	private $bundleFetcher;
77
-	/** @var Installer */
78
-	private $installer;
79
-	/** @var IURLGenerator */
80
-	private $urlGenerator;
81
-	/** @var ILogger */
82
-	private $logger;
83
-
84
-	/** @var array */
85
-	private $allApps = [];
86
-
87
-	/**
88
-	 * @param string $appName
89
-	 * @param IRequest $request
90
-	 * @param IL10N $l10n
91
-	 * @param IConfig $config
92
-	 * @param INavigationManager $navigationManager
93
-	 * @param IAppManager $appManager
94
-	 * @param CategoryFetcher $categoryFetcher
95
-	 * @param AppFetcher $appFetcher
96
-	 * @param IFactory $l10nFactory
97
-	 * @param BundleFetcher $bundleFetcher
98
-	 * @param Installer $installer
99
-	 * @param IURLGenerator $urlGenerator
100
-	 * @param ILogger $logger
101
-	 */
102
-	public function __construct(string $appName,
103
-								IRequest $request,
104
-								IL10N $l10n,
105
-								IConfig $config,
106
-								INavigationManager $navigationManager,
107
-								IAppManager $appManager,
108
-								CategoryFetcher $categoryFetcher,
109
-								AppFetcher $appFetcher,
110
-								IFactory $l10nFactory,
111
-								BundleFetcher $bundleFetcher,
112
-								Installer $installer,
113
-								IURLGenerator $urlGenerator,
114
-								ILogger $logger) {
115
-		parent::__construct($appName, $request);
116
-		$this->l10n = $l10n;
117
-		$this->config = $config;
118
-		$this->navigationManager = $navigationManager;
119
-		$this->appManager = $appManager;
120
-		$this->categoryFetcher = $categoryFetcher;
121
-		$this->appFetcher = $appFetcher;
122
-		$this->l10nFactory = $l10nFactory;
123
-		$this->bundleFetcher = $bundleFetcher;
124
-		$this->installer = $installer;
125
-		$this->urlGenerator = $urlGenerator;
126
-		$this->logger = $logger;
127
-	}
128
-
129
-	/**
130
-	 * @NoCSRFRequired
131
-	 *
132
-	 * @return TemplateResponse
133
-	 */
134
-	public function viewApps(): TemplateResponse {
135
-		\OC_Util::addScript('settings', 'apps');
136
-		\OC_Util::addVendorScript('core', 'marked/marked.min');
137
-		$params = [];
138
-		$params['appstoreEnabled'] = $this->config->getSystemValue('appstoreenabled', true) === true;
139
-		$params['updateCount'] = count($this->getAppsWithUpdates());
140
-		$params['developerDocumentation'] = $this->urlGenerator->linkToDocs('developer-manual');
141
-		$params['bundles'] = $this->getBundles();
142
-		$this->navigationManager->setActiveEntry('core_apps');
143
-
144
-		$templateResponse = new TemplateResponse('settings', 'settings-vue', ['serverData' => $params]);
145
-		$policy = new ContentSecurityPolicy();
146
-		$policy->addAllowedImageDomain('https://usercontent.apps.nextcloud.com');
147
-		$templateResponse->setContentSecurityPolicy($policy);
148
-
149
-		return $templateResponse;
150
-	}
151
-
152
-	private function getAppsWithUpdates() {
153
-		$appClass = new \OC_App();
154
-		$apps = $appClass->listAllApps();
155
-		foreach($apps as $key => $app) {
156
-			$newVersion = $this->installer->isUpdateAvailable($app['id']);
157
-			if($newVersion === false) {
158
-				unset($apps[$key]);
159
-			}
160
-		}
161
-		return $apps;
162
-	}
163
-
164
-	private function getBundles() {
165
-		$result = [];
166
-		$bundles = $this->bundleFetcher->getBundles();
167
-		foreach ($bundles as $bundle) {
168
-			$result[] = [
169
-				'name' => $bundle->getName(),
170
-				'id' => $bundle->getIdentifier(),
171
-				'appIdentifiers' => $bundle->getAppIdentifiers()
172
-			];
173
-		}
174
-		return $result;
175
-
176
-	}
177
-
178
-	/**
179
-	 * Get all available categories
180
-	 *
181
-	 * @return JSONResponse
182
-	 */
183
-	public function listCategories(): JSONResponse {
184
-		return new JSONResponse($this->getAllCategories());
185
-	}
186
-
187
-	private function getAllCategories() {
188
-		$currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2);
189
-
190
-		$formattedCategories = [];
191
-		$categories = $this->categoryFetcher->get();
192
-		foreach($categories as $category) {
193
-			$formattedCategories[] = [
194
-				'id' => $category['id'],
195
-				'ident' => $category['id'],
196
-				'displayName' => isset($category['translations'][$currentLanguage]['name']) ? $category['translations'][$currentLanguage]['name'] : $category['translations']['en']['name'],
197
-			];
198
-		}
199
-
200
-		return $formattedCategories;
201
-	}
202
-
203
-	private function fetchApps() {
204
-		$appClass = new \OC_App();
205
-		$apps = $appClass->listAllApps();
206
-		foreach ($apps as $app) {
207
-			$app['installed'] = true;
208
-			$this->allApps[$app['id']] = $app;
209
-		}
210
-
211
-		$apps = $this->getAppsForCategory('');
212
-		foreach ($apps as $app) {
213
-			$app['appstore'] = true;
214
-			if (!array_key_exists($app['id'], $this->allApps)) {
215
-				$this->allApps[$app['id']] = $app;
216
-			} else {
217
-				$this->allApps[$app['id']] = array_merge($this->allApps[$app['id']], $app);
218
-			}
219
-		}
220
-
221
-		// add bundle information
222
-		$bundles = $this->bundleFetcher->getBundles();
223
-		foreach($bundles as $bundle) {
224
-			foreach($bundle->getAppIdentifiers() as $identifier) {
225
-				foreach($this->allApps as &$app) {
226
-					if($app['id'] === $identifier) {
227
-						$app['bundleId'] = $bundle->getIdentifier();
228
-						continue;
229
-					}
230
-				}
231
-			}
232
-		}
233
-	}
234
-
235
-	private function getAllApps() {
236
-		return $this->allApps;
237
-	}
238
-	/**
239
-	 * Get all available apps in a category
240
-	 *
241
-	 * @param string $category
242
-	 * @return JSONResponse
243
-	 * @throws \Exception
244
-	 */
245
-	public function listApps(): JSONResponse {
246
-
247
-		$this->fetchApps();
248
-		$apps = $this->getAllApps();
249
-
250
-		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($this->config), $this->l10n);
251
-
252
-		// Extend existing app details
253
-		$apps = array_map(function($appData) use ($dependencyAnalyzer) {
254
-			$appstoreData = $appData['appstoreData'];
255
-			$appData['screenshot'] = isset($appstoreData['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/'.base64_encode($appstoreData['screenshots'][0]['url']) : '';
256
-			$appData['category'] = $appstoreData['categories'];
257
-
258
-			$newVersion = $this->installer->isUpdateAvailable($appData['id']);
259
-			if($newVersion && $this->appManager->isInstalled($appData['id'])) {
260
-				$appData['update'] = $newVersion;
261
-			}
262
-
263
-			// fix groups to be an array
264
-			$groups = array();
265
-			if (is_string($appData['groups'])) {
266
-				$groups = json_decode($appData['groups']);
267
-			}
268
-			$appData['groups'] = $groups;
269
-			$appData['canUnInstall'] = !$appData['active'] && $appData['removable'];
270
-
271
-			// fix licence vs license
272
-			if (isset($appData['license']) && !isset($appData['licence'])) {
273
-				$appData['licence'] = $appData['license'];
274
-			}
275
-
276
-			// analyse dependencies
277
-			$missing = $dependencyAnalyzer->analyze($appData);
278
-			$appData['canInstall'] = empty($missing);
279
-			$appData['missingDependencies'] = $missing;
280
-
281
-			$appData['missingMinOwnCloudVersion'] = !isset($appData['dependencies']['nextcloud']['@attributes']['min-version']);
282
-			$appData['missingMaxOwnCloudVersion'] = !isset($appData['dependencies']['nextcloud']['@attributes']['max-version']);
283
-
284
-			return $appData;
285
-		}, $apps);
286
-
287
-		usort($apps, [$this, 'sortApps']);
288
-
289
-		return new JSONResponse(['apps' => $apps, 'status' => 'success']);
290
-	}
291
-
292
-	/**
293
-	 * Get all apps for a category from the app store
294
-	 *
295
-	 * @param string $requestedCategory
296
-	 * @return array
297
-	 * @throws \Exception
298
-	 */
299
-	private function getAppsForCategory($requestedCategory = ''): array {
300
-		$versionParser = new VersionParser();
301
-		$formattedApps = [];
302
-		$apps = $this->appFetcher->get();
303
-		foreach($apps as $app) {
304
-			// Skip all apps not in the requested category
305
-			if ($requestedCategory !== '') {
306
-				$isInCategory = false;
307
-				foreach($app['categories'] as $category) {
308
-					if($category === $requestedCategory) {
309
-						$isInCategory = true;
310
-					}
311
-				}
312
-				if(!$isInCategory) {
313
-					continue;
314
-				}
315
-			}
316
-
317
-			$nextCloudVersion = $versionParser->getVersion($app['releases'][0]['rawPlatformVersionSpec']);
318
-			$nextCloudVersionDependencies = [];
319
-			if($nextCloudVersion->getMinimumVersion() !== '') {
320
-				$nextCloudVersionDependencies['nextcloud']['@attributes']['min-version'] = $nextCloudVersion->getMinimumVersion();
321
-			}
322
-			if($nextCloudVersion->getMaximumVersion() !== '') {
323
-				$nextCloudVersionDependencies['nextcloud']['@attributes']['max-version'] = $nextCloudVersion->getMaximumVersion();
324
-			}
325
-			$phpVersion = $versionParser->getVersion($app['releases'][0]['rawPhpVersionSpec']);
326
-			$existsLocally = \OC_App::getAppPath($app['id']) !== false;
327
-			$phpDependencies = [];
328
-			if($phpVersion->getMinimumVersion() !== '') {
329
-				$phpDependencies['php']['@attributes']['min-version'] = $phpVersion->getMinimumVersion();
330
-			}
331
-			if($phpVersion->getMaximumVersion() !== '') {
332
-				$phpDependencies['php']['@attributes']['max-version'] = $phpVersion->getMaximumVersion();
333
-			}
334
-			if(isset($app['releases'][0]['minIntSize'])) {
335
-				$phpDependencies['php']['@attributes']['min-int-size'] = $app['releases'][0]['minIntSize'];
336
-			}
337
-			$authors = '';
338
-			foreach($app['authors'] as $key => $author) {
339
-				$authors .= $author['name'];
340
-				if($key !== count($app['authors']) - 1) {
341
-					$authors .= ', ';
342
-				}
343
-			}
344
-
345
-			$currentLanguage = substr(\OC::$server->getL10NFactory()->findLanguage(), 0, 2);
346
-			$enabledValue = $this->config->getAppValue($app['id'], 'enabled', 'no');
347
-			$groups = null;
348
-			if($enabledValue !== 'no' && $enabledValue !== 'yes') {
349
-				$groups = $enabledValue;
350
-			}
351
-
352
-			$currentVersion = '';
353
-			if($this->appManager->isInstalled($app['id'])) {
354
-				$currentVersion = $this->appManager->getAppVersion($app['id']);
355
-			} else {
356
-				$currentLanguage = $app['releases'][0]['version'];
357
-			}
358
-
359
-			$formattedApps[] = [
360
-				'id' => $app['id'],
361
-				'name' => isset($app['translations'][$currentLanguage]['name']) ? $app['translations'][$currentLanguage]['name'] : $app['translations']['en']['name'],
362
-				'description' => isset($app['translations'][$currentLanguage]['description']) ? $app['translations'][$currentLanguage]['description'] : $app['translations']['en']['description'],
363
-				'summary' => isset($app['translations'][$currentLanguage]['summary']) ? $app['translations'][$currentLanguage]['summary'] : $app['translations']['en']['summary'],
364
-				'license' => $app['releases'][0]['licenses'],
365
-				'author' => $authors,
366
-				'shipped' => false,
367
-				'version' => $currentVersion,
368
-				'default_enable' => '',
369
-				'types' => [],
370
-				'documentation' => [
371
-					'admin' => $app['adminDocs'],
372
-					'user' => $app['userDocs'],
373
-					'developer' => $app['developerDocs']
374
-				],
375
-				'website' => $app['website'],
376
-				'bugs' => $app['issueTracker'],
377
-				'detailpage' => $app['website'],
378
-				'dependencies' => array_merge(
379
-					$nextCloudVersionDependencies,
380
-					$phpDependencies
381
-				),
382
-				'level' => ($app['isFeatured'] === true) ? 200 : 100,
383
-				'missingMaxOwnCloudVersion' => false,
384
-				'missingMinOwnCloudVersion' => false,
385
-				'canInstall' => true,
386
-				'screenshot' => isset($app['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/'.base64_encode($app['screenshots'][0]['url']) : '',
387
-				'score' => $app['ratingOverall'],
388
-				'ratingNumOverall' => $app['ratingNumOverall'],
389
-				'ratingNumThresholdReached' => $app['ratingNumOverall'] > 5,
390
-				'removable' => $existsLocally,
391
-				'active' => $this->appManager->isEnabledForUser($app['id']),
392
-				'needsDownload' => !$existsLocally,
393
-				'groups' => $groups,
394
-				'fromAppStore' => true,
395
-				'appstoreData' => $app,
396
-			];
397
-		}
398
-
399
-		return $formattedApps;
400
-	}
401
-
402
-	/**
403
-	 * @PasswordConfirmationRequired
404
-	 *
405
-	 * @param string $appId
406
-	 * @param array $groups
407
-	 * @return JSONResponse
408
-	 */
409
-	public function enableApp(string $appId, array $groups = []): JSONResponse {
410
-		return $this->enableApps([$appId], $groups);
411
-	}
412
-
413
-	/**
414
-	 * Enable one or more apps
415
-	 *
416
-	 * apps will be enabled for specific groups only if $groups is defined
417
-	 *
418
-	 * @PasswordConfirmationRequired
419
-	 * @param array $appIds
420
-	 * @param array $groups
421
-	 * @return JSONResponse
422
-	 */
423
-	public function enableApps(array $appIds, array $groups = []): JSONResponse {
424
-		try {
425
-			$updateRequired = false;
426
-
427
-			foreach ($appIds as $appId) {
428
-				$appId = OC_App::cleanAppId($appId);
429
-
430
-				// Check if app is already downloaded
431
-				/** @var Installer $installer */
432
-				$installer = \OC::$server->query(Installer::class);
433
-				$isDownloaded = $installer->isDownloaded($appId);
434
-
435
-				if(!$isDownloaded) {
436
-					$installer->downloadApp($appId);
437
-				}
438
-
439
-				$installer->installApp($appId);
440
-
441
-				if (count($groups) > 0) {
442
-					$this->appManager->enableAppForGroups($appId, $this->getGroupList($groups));
443
-				} else {
444
-					$this->appManager->enableApp($appId);
445
-				}
446
-				if (\OC_App::shouldUpgrade($appId)) {
447
-					$updateRequired = true;
448
-				}
449
-			}
450
-			return new JSONResponse(['data' => ['update_required' => $updateRequired]]);
451
-
452
-		} catch (\Exception $e) {
453
-			$this->logger->logException($e);
454
-			return new JSONResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR);
455
-		}
456
-	}
457
-
458
-	private function getGroupList(array $groups) {
459
-		$groupManager = \OC::$server->getGroupManager();
460
-		$groupsList = [];
461
-		foreach ($groups as $group) {
462
-			$groupItem = $groupManager->get($group);
463
-			if ($groupItem instanceof \OCP\IGroup) {
464
-				$groupsList[] = $groupManager->get($group);
465
-			}
466
-		}
467
-		return $groupsList;
468
-	}
469
-
470
-	/**
471
-	 * @PasswordConfirmationRequired
472
-	 *
473
-	 * @param string $appId
474
-	 * @return JSONResponse
475
-	 */
476
-	public function disableApp(string $appId): JSONResponse {
477
-		return $this->disableApps([$appId]);
478
-	}
479
-
480
-	/**
481
-	 * @PasswordConfirmationRequired
482
-	 *
483
-	 * @param array $appIds
484
-	 * @return JSONResponse
485
-	 */
486
-	public function disableApps(array $appIds): JSONResponse {
487
-		try {
488
-			foreach ($appIds as $appId) {
489
-				$appId = OC_App::cleanAppId($appId);
490
-				$this->appManager->disableApp($appId);
491
-			}
492
-			return new JSONResponse([]);
493
-		} catch (\Exception $e) {
494
-			$this->logger->logException($e);
495
-			return new JSONResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR);
496
-		}
497
-	}
498
-
499
-	/**
500
-	 * @PasswordConfirmationRequired
501
-	 *
502
-	 * @param string $appId
503
-	 * @return JSONResponse
504
-	 */
505
-	public function uninstallApp(string $appId): JSONResponse {
506
-		$appId = OC_App::cleanAppId($appId);
507
-		$result = $this->installer->removeApp($appId);
508
-		if($result !== false) {
509
-			$this->appManager->clearAppsCache();
510
-			return new JSONResponse(['data' => ['appid' => $appId]]);
511
-		}
512
-		return new JSONResponse(['data' => ['message' => $this->l10n->t('Couldn\'t remove app.')]], Http::STATUS_INTERNAL_SERVER_ERROR);
513
-	}
514
-
515
-	/**
516
-	 * @param string $appId
517
-	 * @return JSONResponse
518
-	 */
519
-	public function updateApp(string $appId): JSONResponse {
520
-		$appId = OC_App::cleanAppId($appId);
521
-
522
-		$this->config->setSystemValue('maintenance', true);
523
-		try {
524
-			$result = $this->installer->updateAppstoreApp($appId);
525
-			$this->config->setSystemValue('maintenance', false);
526
-		} catch (\Exception $ex) {
527
-			$this->config->setSystemValue('maintenance', false);
528
-			return new JSONResponse(['data' => ['message' => $ex->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR);
529
-		}
530
-
531
-		if ($result !== false) {
532
-			return new JSONResponse(['data' => ['appid' => $appId]]);
533
-		}
534
-		return new JSONResponse(['data' => ['message' => $this->l10n->t('Couldn\'t update app.')]], Http::STATUS_INTERNAL_SERVER_ERROR);
535
-	}
536
-
537
-	private function sortApps($a, $b) {
538
-		$a = (string)$a['name'];
539
-		$b = (string)$b['name'];
540
-		if ($a === $b) {
541
-			return 0;
542
-		}
543
-		return ($a < $b) ? -1 : 1;
544
-	}
61
+    /** @var \OCP\IL10N */
62
+    private $l10n;
63
+    /** @var IConfig */
64
+    private $config;
65
+    /** @var INavigationManager */
66
+    private $navigationManager;
67
+    /** @var IAppManager */
68
+    private $appManager;
69
+    /** @var CategoryFetcher */
70
+    private $categoryFetcher;
71
+    /** @var AppFetcher */
72
+    private $appFetcher;
73
+    /** @var IFactory */
74
+    private $l10nFactory;
75
+    /** @var BundleFetcher */
76
+    private $bundleFetcher;
77
+    /** @var Installer */
78
+    private $installer;
79
+    /** @var IURLGenerator */
80
+    private $urlGenerator;
81
+    /** @var ILogger */
82
+    private $logger;
83
+
84
+    /** @var array */
85
+    private $allApps = [];
86
+
87
+    /**
88
+     * @param string $appName
89
+     * @param IRequest $request
90
+     * @param IL10N $l10n
91
+     * @param IConfig $config
92
+     * @param INavigationManager $navigationManager
93
+     * @param IAppManager $appManager
94
+     * @param CategoryFetcher $categoryFetcher
95
+     * @param AppFetcher $appFetcher
96
+     * @param IFactory $l10nFactory
97
+     * @param BundleFetcher $bundleFetcher
98
+     * @param Installer $installer
99
+     * @param IURLGenerator $urlGenerator
100
+     * @param ILogger $logger
101
+     */
102
+    public function __construct(string $appName,
103
+                                IRequest $request,
104
+                                IL10N $l10n,
105
+                                IConfig $config,
106
+                                INavigationManager $navigationManager,
107
+                                IAppManager $appManager,
108
+                                CategoryFetcher $categoryFetcher,
109
+                                AppFetcher $appFetcher,
110
+                                IFactory $l10nFactory,
111
+                                BundleFetcher $bundleFetcher,
112
+                                Installer $installer,
113
+                                IURLGenerator $urlGenerator,
114
+                                ILogger $logger) {
115
+        parent::__construct($appName, $request);
116
+        $this->l10n = $l10n;
117
+        $this->config = $config;
118
+        $this->navigationManager = $navigationManager;
119
+        $this->appManager = $appManager;
120
+        $this->categoryFetcher = $categoryFetcher;
121
+        $this->appFetcher = $appFetcher;
122
+        $this->l10nFactory = $l10nFactory;
123
+        $this->bundleFetcher = $bundleFetcher;
124
+        $this->installer = $installer;
125
+        $this->urlGenerator = $urlGenerator;
126
+        $this->logger = $logger;
127
+    }
128
+
129
+    /**
130
+     * @NoCSRFRequired
131
+     *
132
+     * @return TemplateResponse
133
+     */
134
+    public function viewApps(): TemplateResponse {
135
+        \OC_Util::addScript('settings', 'apps');
136
+        \OC_Util::addVendorScript('core', 'marked/marked.min');
137
+        $params = [];
138
+        $params['appstoreEnabled'] = $this->config->getSystemValue('appstoreenabled', true) === true;
139
+        $params['updateCount'] = count($this->getAppsWithUpdates());
140
+        $params['developerDocumentation'] = $this->urlGenerator->linkToDocs('developer-manual');
141
+        $params['bundles'] = $this->getBundles();
142
+        $this->navigationManager->setActiveEntry('core_apps');
143
+
144
+        $templateResponse = new TemplateResponse('settings', 'settings-vue', ['serverData' => $params]);
145
+        $policy = new ContentSecurityPolicy();
146
+        $policy->addAllowedImageDomain('https://usercontent.apps.nextcloud.com');
147
+        $templateResponse->setContentSecurityPolicy($policy);
148
+
149
+        return $templateResponse;
150
+    }
151
+
152
+    private function getAppsWithUpdates() {
153
+        $appClass = new \OC_App();
154
+        $apps = $appClass->listAllApps();
155
+        foreach($apps as $key => $app) {
156
+            $newVersion = $this->installer->isUpdateAvailable($app['id']);
157
+            if($newVersion === false) {
158
+                unset($apps[$key]);
159
+            }
160
+        }
161
+        return $apps;
162
+    }
163
+
164
+    private function getBundles() {
165
+        $result = [];
166
+        $bundles = $this->bundleFetcher->getBundles();
167
+        foreach ($bundles as $bundle) {
168
+            $result[] = [
169
+                'name' => $bundle->getName(),
170
+                'id' => $bundle->getIdentifier(),
171
+                'appIdentifiers' => $bundle->getAppIdentifiers()
172
+            ];
173
+        }
174
+        return $result;
175
+
176
+    }
177
+
178
+    /**
179
+     * Get all available categories
180
+     *
181
+     * @return JSONResponse
182
+     */
183
+    public function listCategories(): JSONResponse {
184
+        return new JSONResponse($this->getAllCategories());
185
+    }
186
+
187
+    private function getAllCategories() {
188
+        $currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2);
189
+
190
+        $formattedCategories = [];
191
+        $categories = $this->categoryFetcher->get();
192
+        foreach($categories as $category) {
193
+            $formattedCategories[] = [
194
+                'id' => $category['id'],
195
+                'ident' => $category['id'],
196
+                'displayName' => isset($category['translations'][$currentLanguage]['name']) ? $category['translations'][$currentLanguage]['name'] : $category['translations']['en']['name'],
197
+            ];
198
+        }
199
+
200
+        return $formattedCategories;
201
+    }
202
+
203
+    private function fetchApps() {
204
+        $appClass = new \OC_App();
205
+        $apps = $appClass->listAllApps();
206
+        foreach ($apps as $app) {
207
+            $app['installed'] = true;
208
+            $this->allApps[$app['id']] = $app;
209
+        }
210
+
211
+        $apps = $this->getAppsForCategory('');
212
+        foreach ($apps as $app) {
213
+            $app['appstore'] = true;
214
+            if (!array_key_exists($app['id'], $this->allApps)) {
215
+                $this->allApps[$app['id']] = $app;
216
+            } else {
217
+                $this->allApps[$app['id']] = array_merge($this->allApps[$app['id']], $app);
218
+            }
219
+        }
220
+
221
+        // add bundle information
222
+        $bundles = $this->bundleFetcher->getBundles();
223
+        foreach($bundles as $bundle) {
224
+            foreach($bundle->getAppIdentifiers() as $identifier) {
225
+                foreach($this->allApps as &$app) {
226
+                    if($app['id'] === $identifier) {
227
+                        $app['bundleId'] = $bundle->getIdentifier();
228
+                        continue;
229
+                    }
230
+                }
231
+            }
232
+        }
233
+    }
234
+
235
+    private function getAllApps() {
236
+        return $this->allApps;
237
+    }
238
+    /**
239
+     * Get all available apps in a category
240
+     *
241
+     * @param string $category
242
+     * @return JSONResponse
243
+     * @throws \Exception
244
+     */
245
+    public function listApps(): JSONResponse {
246
+
247
+        $this->fetchApps();
248
+        $apps = $this->getAllApps();
249
+
250
+        $dependencyAnalyzer = new DependencyAnalyzer(new Platform($this->config), $this->l10n);
251
+
252
+        // Extend existing app details
253
+        $apps = array_map(function($appData) use ($dependencyAnalyzer) {
254
+            $appstoreData = $appData['appstoreData'];
255
+            $appData['screenshot'] = isset($appstoreData['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/'.base64_encode($appstoreData['screenshots'][0]['url']) : '';
256
+            $appData['category'] = $appstoreData['categories'];
257
+
258
+            $newVersion = $this->installer->isUpdateAvailable($appData['id']);
259
+            if($newVersion && $this->appManager->isInstalled($appData['id'])) {
260
+                $appData['update'] = $newVersion;
261
+            }
262
+
263
+            // fix groups to be an array
264
+            $groups = array();
265
+            if (is_string($appData['groups'])) {
266
+                $groups = json_decode($appData['groups']);
267
+            }
268
+            $appData['groups'] = $groups;
269
+            $appData['canUnInstall'] = !$appData['active'] && $appData['removable'];
270
+
271
+            // fix licence vs license
272
+            if (isset($appData['license']) && !isset($appData['licence'])) {
273
+                $appData['licence'] = $appData['license'];
274
+            }
275
+
276
+            // analyse dependencies
277
+            $missing = $dependencyAnalyzer->analyze($appData);
278
+            $appData['canInstall'] = empty($missing);
279
+            $appData['missingDependencies'] = $missing;
280
+
281
+            $appData['missingMinOwnCloudVersion'] = !isset($appData['dependencies']['nextcloud']['@attributes']['min-version']);
282
+            $appData['missingMaxOwnCloudVersion'] = !isset($appData['dependencies']['nextcloud']['@attributes']['max-version']);
283
+
284
+            return $appData;
285
+        }, $apps);
286
+
287
+        usort($apps, [$this, 'sortApps']);
288
+
289
+        return new JSONResponse(['apps' => $apps, 'status' => 'success']);
290
+    }
291
+
292
+    /**
293
+     * Get all apps for a category from the app store
294
+     *
295
+     * @param string $requestedCategory
296
+     * @return array
297
+     * @throws \Exception
298
+     */
299
+    private function getAppsForCategory($requestedCategory = ''): array {
300
+        $versionParser = new VersionParser();
301
+        $formattedApps = [];
302
+        $apps = $this->appFetcher->get();
303
+        foreach($apps as $app) {
304
+            // Skip all apps not in the requested category
305
+            if ($requestedCategory !== '') {
306
+                $isInCategory = false;
307
+                foreach($app['categories'] as $category) {
308
+                    if($category === $requestedCategory) {
309
+                        $isInCategory = true;
310
+                    }
311
+                }
312
+                if(!$isInCategory) {
313
+                    continue;
314
+                }
315
+            }
316
+
317
+            $nextCloudVersion = $versionParser->getVersion($app['releases'][0]['rawPlatformVersionSpec']);
318
+            $nextCloudVersionDependencies = [];
319
+            if($nextCloudVersion->getMinimumVersion() !== '') {
320
+                $nextCloudVersionDependencies['nextcloud']['@attributes']['min-version'] = $nextCloudVersion->getMinimumVersion();
321
+            }
322
+            if($nextCloudVersion->getMaximumVersion() !== '') {
323
+                $nextCloudVersionDependencies['nextcloud']['@attributes']['max-version'] = $nextCloudVersion->getMaximumVersion();
324
+            }
325
+            $phpVersion = $versionParser->getVersion($app['releases'][0]['rawPhpVersionSpec']);
326
+            $existsLocally = \OC_App::getAppPath($app['id']) !== false;
327
+            $phpDependencies = [];
328
+            if($phpVersion->getMinimumVersion() !== '') {
329
+                $phpDependencies['php']['@attributes']['min-version'] = $phpVersion->getMinimumVersion();
330
+            }
331
+            if($phpVersion->getMaximumVersion() !== '') {
332
+                $phpDependencies['php']['@attributes']['max-version'] = $phpVersion->getMaximumVersion();
333
+            }
334
+            if(isset($app['releases'][0]['minIntSize'])) {
335
+                $phpDependencies['php']['@attributes']['min-int-size'] = $app['releases'][0]['minIntSize'];
336
+            }
337
+            $authors = '';
338
+            foreach($app['authors'] as $key => $author) {
339
+                $authors .= $author['name'];
340
+                if($key !== count($app['authors']) - 1) {
341
+                    $authors .= ', ';
342
+                }
343
+            }
344
+
345
+            $currentLanguage = substr(\OC::$server->getL10NFactory()->findLanguage(), 0, 2);
346
+            $enabledValue = $this->config->getAppValue($app['id'], 'enabled', 'no');
347
+            $groups = null;
348
+            if($enabledValue !== 'no' && $enabledValue !== 'yes') {
349
+                $groups = $enabledValue;
350
+            }
351
+
352
+            $currentVersion = '';
353
+            if($this->appManager->isInstalled($app['id'])) {
354
+                $currentVersion = $this->appManager->getAppVersion($app['id']);
355
+            } else {
356
+                $currentLanguage = $app['releases'][0]['version'];
357
+            }
358
+
359
+            $formattedApps[] = [
360
+                'id' => $app['id'],
361
+                'name' => isset($app['translations'][$currentLanguage]['name']) ? $app['translations'][$currentLanguage]['name'] : $app['translations']['en']['name'],
362
+                'description' => isset($app['translations'][$currentLanguage]['description']) ? $app['translations'][$currentLanguage]['description'] : $app['translations']['en']['description'],
363
+                'summary' => isset($app['translations'][$currentLanguage]['summary']) ? $app['translations'][$currentLanguage]['summary'] : $app['translations']['en']['summary'],
364
+                'license' => $app['releases'][0]['licenses'],
365
+                'author' => $authors,
366
+                'shipped' => false,
367
+                'version' => $currentVersion,
368
+                'default_enable' => '',
369
+                'types' => [],
370
+                'documentation' => [
371
+                    'admin' => $app['adminDocs'],
372
+                    'user' => $app['userDocs'],
373
+                    'developer' => $app['developerDocs']
374
+                ],
375
+                'website' => $app['website'],
376
+                'bugs' => $app['issueTracker'],
377
+                'detailpage' => $app['website'],
378
+                'dependencies' => array_merge(
379
+                    $nextCloudVersionDependencies,
380
+                    $phpDependencies
381
+                ),
382
+                'level' => ($app['isFeatured'] === true) ? 200 : 100,
383
+                'missingMaxOwnCloudVersion' => false,
384
+                'missingMinOwnCloudVersion' => false,
385
+                'canInstall' => true,
386
+                'screenshot' => isset($app['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/'.base64_encode($app['screenshots'][0]['url']) : '',
387
+                'score' => $app['ratingOverall'],
388
+                'ratingNumOverall' => $app['ratingNumOverall'],
389
+                'ratingNumThresholdReached' => $app['ratingNumOverall'] > 5,
390
+                'removable' => $existsLocally,
391
+                'active' => $this->appManager->isEnabledForUser($app['id']),
392
+                'needsDownload' => !$existsLocally,
393
+                'groups' => $groups,
394
+                'fromAppStore' => true,
395
+                'appstoreData' => $app,
396
+            ];
397
+        }
398
+
399
+        return $formattedApps;
400
+    }
401
+
402
+    /**
403
+     * @PasswordConfirmationRequired
404
+     *
405
+     * @param string $appId
406
+     * @param array $groups
407
+     * @return JSONResponse
408
+     */
409
+    public function enableApp(string $appId, array $groups = []): JSONResponse {
410
+        return $this->enableApps([$appId], $groups);
411
+    }
412
+
413
+    /**
414
+     * Enable one or more apps
415
+     *
416
+     * apps will be enabled for specific groups only if $groups is defined
417
+     *
418
+     * @PasswordConfirmationRequired
419
+     * @param array $appIds
420
+     * @param array $groups
421
+     * @return JSONResponse
422
+     */
423
+    public function enableApps(array $appIds, array $groups = []): JSONResponse {
424
+        try {
425
+            $updateRequired = false;
426
+
427
+            foreach ($appIds as $appId) {
428
+                $appId = OC_App::cleanAppId($appId);
429
+
430
+                // Check if app is already downloaded
431
+                /** @var Installer $installer */
432
+                $installer = \OC::$server->query(Installer::class);
433
+                $isDownloaded = $installer->isDownloaded($appId);
434
+
435
+                if(!$isDownloaded) {
436
+                    $installer->downloadApp($appId);
437
+                }
438
+
439
+                $installer->installApp($appId);
440
+
441
+                if (count($groups) > 0) {
442
+                    $this->appManager->enableAppForGroups($appId, $this->getGroupList($groups));
443
+                } else {
444
+                    $this->appManager->enableApp($appId);
445
+                }
446
+                if (\OC_App::shouldUpgrade($appId)) {
447
+                    $updateRequired = true;
448
+                }
449
+            }
450
+            return new JSONResponse(['data' => ['update_required' => $updateRequired]]);
451
+
452
+        } catch (\Exception $e) {
453
+            $this->logger->logException($e);
454
+            return new JSONResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR);
455
+        }
456
+    }
457
+
458
+    private function getGroupList(array $groups) {
459
+        $groupManager = \OC::$server->getGroupManager();
460
+        $groupsList = [];
461
+        foreach ($groups as $group) {
462
+            $groupItem = $groupManager->get($group);
463
+            if ($groupItem instanceof \OCP\IGroup) {
464
+                $groupsList[] = $groupManager->get($group);
465
+            }
466
+        }
467
+        return $groupsList;
468
+    }
469
+
470
+    /**
471
+     * @PasswordConfirmationRequired
472
+     *
473
+     * @param string $appId
474
+     * @return JSONResponse
475
+     */
476
+    public function disableApp(string $appId): JSONResponse {
477
+        return $this->disableApps([$appId]);
478
+    }
479
+
480
+    /**
481
+     * @PasswordConfirmationRequired
482
+     *
483
+     * @param array $appIds
484
+     * @return JSONResponse
485
+     */
486
+    public function disableApps(array $appIds): JSONResponse {
487
+        try {
488
+            foreach ($appIds as $appId) {
489
+                $appId = OC_App::cleanAppId($appId);
490
+                $this->appManager->disableApp($appId);
491
+            }
492
+            return new JSONResponse([]);
493
+        } catch (\Exception $e) {
494
+            $this->logger->logException($e);
495
+            return new JSONResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR);
496
+        }
497
+    }
498
+
499
+    /**
500
+     * @PasswordConfirmationRequired
501
+     *
502
+     * @param string $appId
503
+     * @return JSONResponse
504
+     */
505
+    public function uninstallApp(string $appId): JSONResponse {
506
+        $appId = OC_App::cleanAppId($appId);
507
+        $result = $this->installer->removeApp($appId);
508
+        if($result !== false) {
509
+            $this->appManager->clearAppsCache();
510
+            return new JSONResponse(['data' => ['appid' => $appId]]);
511
+        }
512
+        return new JSONResponse(['data' => ['message' => $this->l10n->t('Couldn\'t remove app.')]], Http::STATUS_INTERNAL_SERVER_ERROR);
513
+    }
514
+
515
+    /**
516
+     * @param string $appId
517
+     * @return JSONResponse
518
+     */
519
+    public function updateApp(string $appId): JSONResponse {
520
+        $appId = OC_App::cleanAppId($appId);
521
+
522
+        $this->config->setSystemValue('maintenance', true);
523
+        try {
524
+            $result = $this->installer->updateAppstoreApp($appId);
525
+            $this->config->setSystemValue('maintenance', false);
526
+        } catch (\Exception $ex) {
527
+            $this->config->setSystemValue('maintenance', false);
528
+            return new JSONResponse(['data' => ['message' => $ex->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR);
529
+        }
530
+
531
+        if ($result !== false) {
532
+            return new JSONResponse(['data' => ['appid' => $appId]]);
533
+        }
534
+        return new JSONResponse(['data' => ['message' => $this->l10n->t('Couldn\'t update app.')]], Http::STATUS_INTERNAL_SERVER_ERROR);
535
+    }
536
+
537
+    private function sortApps($a, $b) {
538
+        $a = (string)$a['name'];
539
+        $b = (string)$b['name'];
540
+        if ($a === $b) {
541
+            return 0;
542
+        }
543
+        return ($a < $b) ? -1 : 1;
544
+    }
545 545
 
546 546
 }
Please login to merge, or discard this patch.
settings/Controller/UsersController.php 1 patch
Indentation   +368 added lines, -368 removed lines patch added patch discarded remove patch
@@ -65,402 +65,402 @@
 block discarded – undo
65 65
  * @package OC\Settings\Controller
66 66
  */
67 67
 class UsersController extends Controller {
68
-	/** @var IUserManager */
69
-	private $userManager;
70
-	/** @var IGroupManager */
71
-	private $groupManager;
72
-	/** @var IUserSession */
73
-	private $userSession;
74
-	/** @var IConfig */
75
-	private $config;
76
-	/** @var bool */
77
-	private $isAdmin;
78
-	/** @var IL10N */
79
-	private $l10n;
80
-	/** @var IMailer */
81
-	private $mailer;
82
-	/** @var IFactory */
83
-	private $l10nFactory;
84
-	/** @var IAppManager */
85
-	private $appManager;
86
-	/** @var AccountManager */
87
-	private $accountManager;
88
-	/** @var Manager */
89
-	private $keyManager;
90
-	/** @var IJobList */
91
-	private $jobList;
92
-	/** @var IManager */
93
-	private $encryptionManager;
68
+    /** @var IUserManager */
69
+    private $userManager;
70
+    /** @var IGroupManager */
71
+    private $groupManager;
72
+    /** @var IUserSession */
73
+    private $userSession;
74
+    /** @var IConfig */
75
+    private $config;
76
+    /** @var bool */
77
+    private $isAdmin;
78
+    /** @var IL10N */
79
+    private $l10n;
80
+    /** @var IMailer */
81
+    private $mailer;
82
+    /** @var IFactory */
83
+    private $l10nFactory;
84
+    /** @var IAppManager */
85
+    private $appManager;
86
+    /** @var AccountManager */
87
+    private $accountManager;
88
+    /** @var Manager */
89
+    private $keyManager;
90
+    /** @var IJobList */
91
+    private $jobList;
92
+    /** @var IManager */
93
+    private $encryptionManager;
94 94
 
95 95
 
96
-	public function __construct(string $appName,
97
-								IRequest $request,
98
-								IUserManager $userManager,
99
-								IGroupManager $groupManager,
100
-								IUserSession $userSession,
101
-								IConfig $config,
102
-								bool $isAdmin,
103
-								IL10N $l10n,
104
-								IMailer $mailer,
105
-								IFactory $l10nFactory,
106
-								IAppManager $appManager,
107
-								AccountManager $accountManager,
108
-								Manager $keyManager,
109
-								IJobList $jobList,
110
-								IManager $encryptionManager) {
111
-		parent::__construct($appName, $request);
112
-		$this->userManager = $userManager;
113
-		$this->groupManager = $groupManager;
114
-		$this->userSession = $userSession;
115
-		$this->config = $config;
116
-		$this->isAdmin = $isAdmin;
117
-		$this->l10n = $l10n;
118
-		$this->mailer = $mailer;
119
-		$this->l10nFactory = $l10nFactory;
120
-		$this->appManager = $appManager;
121
-		$this->accountManager = $accountManager;
122
-		$this->keyManager = $keyManager;
123
-		$this->jobList = $jobList;
124
-		$this->encryptionManager = $encryptionManager;
125
-	}
96
+    public function __construct(string $appName,
97
+                                IRequest $request,
98
+                                IUserManager $userManager,
99
+                                IGroupManager $groupManager,
100
+                                IUserSession $userSession,
101
+                                IConfig $config,
102
+                                bool $isAdmin,
103
+                                IL10N $l10n,
104
+                                IMailer $mailer,
105
+                                IFactory $l10nFactory,
106
+                                IAppManager $appManager,
107
+                                AccountManager $accountManager,
108
+                                Manager $keyManager,
109
+                                IJobList $jobList,
110
+                                IManager $encryptionManager) {
111
+        parent::__construct($appName, $request);
112
+        $this->userManager = $userManager;
113
+        $this->groupManager = $groupManager;
114
+        $this->userSession = $userSession;
115
+        $this->config = $config;
116
+        $this->isAdmin = $isAdmin;
117
+        $this->l10n = $l10n;
118
+        $this->mailer = $mailer;
119
+        $this->l10nFactory = $l10nFactory;
120
+        $this->appManager = $appManager;
121
+        $this->accountManager = $accountManager;
122
+        $this->keyManager = $keyManager;
123
+        $this->jobList = $jobList;
124
+        $this->encryptionManager = $encryptionManager;
125
+    }
126 126
 
127 127
 
128
-	/**
129
-	 * @NoCSRFRequired
130
-	 * @NoAdminRequired
131
-	 * 
132
-	 * Display users list template
133
-	 * 
134
-	 * @return TemplateResponse
135
-	 */
136
-	public function usersListByGroup() {
137
-		return $this->usersList();
138
-	}
128
+    /**
129
+     * @NoCSRFRequired
130
+     * @NoAdminRequired
131
+     * 
132
+     * Display users list template
133
+     * 
134
+     * @return TemplateResponse
135
+     */
136
+    public function usersListByGroup() {
137
+        return $this->usersList();
138
+    }
139 139
 
140
-	/**
141
-	 * @NoCSRFRequired
142
-	 * @NoAdminRequired
143
-	 * 
144
-	 * Display users list template
145
-	 * 
146
-	 * @return TemplateResponse
147
-	 */
148
-	public function usersList() {
149
-		$user = $this->userSession->getUser();
150
-		$uid = $user->getUID();
140
+    /**
141
+     * @NoCSRFRequired
142
+     * @NoAdminRequired
143
+     * 
144
+     * Display users list template
145
+     * 
146
+     * @return TemplateResponse
147
+     */
148
+    public function usersList() {
149
+        $user = $this->userSession->getUser();
150
+        $uid = $user->getUID();
151 151
 
152
-		\OC::$server->getNavigationManager()->setActiveEntry('core_users');
152
+        \OC::$server->getNavigationManager()->setActiveEntry('core_users');
153 153
 				
154
-		/* SORT OPTION: SORT_USERCOUNT or SORT_GROUPNAME */
155
-		$sortGroupsBy = \OC\Group\MetaData::SORT_USERCOUNT;
156
-		if ($this->config->getSystemValue('sort_groups_by_name', false)) {
157
-			$sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
158
-		} else {
159
-			$isLDAPUsed = false;
160
-			if ($this->appManager->isEnabledForUser('user_ldap')) {
161
-				$isLDAPUsed =
162
-					$this->groupManager->isBackendUsed('\OCA\User_LDAP\Group_LDAP')
163
-					|| $this->groupManager->isBackendUsed('\OCA\User_LDAP\Group_Proxy');
164
-				if ($isLDAPUsed) {
165
-					// LDAP user count can be slow, so we sort by group name here
166
-					$sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
167
-				}
168
-			}
169
-		}
154
+        /* SORT OPTION: SORT_USERCOUNT or SORT_GROUPNAME */
155
+        $sortGroupsBy = \OC\Group\MetaData::SORT_USERCOUNT;
156
+        if ($this->config->getSystemValue('sort_groups_by_name', false)) {
157
+            $sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
158
+        } else {
159
+            $isLDAPUsed = false;
160
+            if ($this->appManager->isEnabledForUser('user_ldap')) {
161
+                $isLDAPUsed =
162
+                    $this->groupManager->isBackendUsed('\OCA\User_LDAP\Group_LDAP')
163
+                    || $this->groupManager->isBackendUsed('\OCA\User_LDAP\Group_Proxy');
164
+                if ($isLDAPUsed) {
165
+                    // LDAP user count can be slow, so we sort by group name here
166
+                    $sortGroupsBy = \OC\Group\MetaData::SORT_GROUPNAME;
167
+                }
168
+            }
169
+        }
170 170
 		
171
-		/* ENCRYPTION CONFIG */
172
-		$isEncryptionEnabled = $this->encryptionManager->isEnabled();
173
-		$useMasterKey = $this->config->getAppValue('encryption', 'useMasterKey', true);
174
-		// If masterKey enabled, then you can change password. This is to avoid data loss!
175
-		$canChangePassword = ($isEncryptionEnabled && $useMasterKey) || $useMasterKey;
171
+        /* ENCRYPTION CONFIG */
172
+        $isEncryptionEnabled = $this->encryptionManager->isEnabled();
173
+        $useMasterKey = $this->config->getAppValue('encryption', 'useMasterKey', true);
174
+        // If masterKey enabled, then you can change password. This is to avoid data loss!
175
+        $canChangePassword = ($isEncryptionEnabled && $useMasterKey) || $useMasterKey;
176 176
 		
177 177
 		
178
-		/* GROUPS */		
179
-		$groupsInfo = new \OC\Group\MetaData(
180
-			$uid,
181
-			$this->isAdmin,
182
-			$this->groupManager,
183
-			$this->userSession
184
-		);
178
+        /* GROUPS */		
179
+        $groupsInfo = new \OC\Group\MetaData(
180
+            $uid,
181
+            $this->isAdmin,
182
+            $this->groupManager,
183
+            $this->userSession
184
+        );
185 185
 		
186
-		$groupsInfo->setSorting($sortGroupsBy);
187
-		list($adminGroup, $groups) = $groupsInfo->get();
186
+        $groupsInfo->setSorting($sortGroupsBy);
187
+        list($adminGroup, $groups) = $groupsInfo->get();
188 188
 		
189
-		if ($this->isAdmin) {
190
-			$disabledUsers = $isLDAPUsed ? 0 : $this->userManager->countDisabledUsers();
191
-			$userCount = array_reduce($this->userManager->countUsers(), function($v, $w) {
192
-				return $v + (int)$w;
193
-			}, 0);
194
-		} else {
195
-			// User is subadmin !
196
-			// Map group list to names to retrieve the countDisabledUsersOfGroups
197
-			$userGroups = $this->groupManager->getUserGroups($user);
198
-			$groupsNames = [];
199
-			$userCount = 0;
189
+        if ($this->isAdmin) {
190
+            $disabledUsers = $isLDAPUsed ? 0 : $this->userManager->countDisabledUsers();
191
+            $userCount = array_reduce($this->userManager->countUsers(), function($v, $w) {
192
+                return $v + (int)$w;
193
+            }, 0);
194
+        } else {
195
+            // User is subadmin !
196
+            // Map group list to names to retrieve the countDisabledUsersOfGroups
197
+            $userGroups = $this->groupManager->getUserGroups($user);
198
+            $groupsNames = [];
199
+            $userCount = 0;
200 200
 
201
-			foreach($groups as $key => $group) {
202
-				// $userCount += (int)$group['usercount'];
203
-				array_push($groupsNames, $group['name']);
204
-				// we prevent subadmins from looking up themselves
205
-				// so we lower the count of the groups he belongs to
206
-				if (array_key_exists($group['id'], $userGroups)) {
207
-					$groups[$key]['usercount']--;
208
-					$userCount = -1; // we also lower from one the total count
209
-				}
210
-			};
211
-			$userCount += $this->userManager->countUsersOfGroups($groupsInfo->getGroups());
212
-			$disabledUsers = $isLDAPUsed ? 0 : $this->userManager->countDisabledUsersOfGroups($groupsNames);
213
-		}
214
-		$disabledUsersGroup = [
215
-			'id' => 'disabled',
216
-			'name' => 'Disabled users',
217
-			'usercount' => $disabledUsers
218
-		];
201
+            foreach($groups as $key => $group) {
202
+                // $userCount += (int)$group['usercount'];
203
+                array_push($groupsNames, $group['name']);
204
+                // we prevent subadmins from looking up themselves
205
+                // so we lower the count of the groups he belongs to
206
+                if (array_key_exists($group['id'], $userGroups)) {
207
+                    $groups[$key]['usercount']--;
208
+                    $userCount = -1; // we also lower from one the total count
209
+                }
210
+            };
211
+            $userCount += $this->userManager->countUsersOfGroups($groupsInfo->getGroups());
212
+            $disabledUsers = $isLDAPUsed ? 0 : $this->userManager->countDisabledUsersOfGroups($groupsNames);
213
+        }
214
+        $disabledUsersGroup = [
215
+            'id' => 'disabled',
216
+            'name' => 'Disabled users',
217
+            'usercount' => $disabledUsers
218
+        ];
219 219
 		
220
-		/* QUOTAS PRESETS */
221
-		$quotaPreset = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
222
-		$quotaPreset = explode(',', $quotaPreset);
223
-		foreach ($quotaPreset as &$preset) {
224
-			$preset = trim($preset);
225
-		}
226
-		$quotaPreset = array_diff($quotaPreset, array('default', 'none'));
227
-		$defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
220
+        /* QUOTAS PRESETS */
221
+        $quotaPreset = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
222
+        $quotaPreset = explode(',', $quotaPreset);
223
+        foreach ($quotaPreset as &$preset) {
224
+            $preset = trim($preset);
225
+        }
226
+        $quotaPreset = array_diff($quotaPreset, array('default', 'none'));
227
+        $defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
228 228
 		
229
-		\OC::$server->getEventDispatcher()->dispatch('OC\Settings\Users::loadAdditionalScripts');
229
+        \OC::$server->getEventDispatcher()->dispatch('OC\Settings\Users::loadAdditionalScripts');
230 230
 		
231
-		/* LANGUAGES */
232
-		$languages = $this->l10nFactory->getLanguages();
231
+        /* LANGUAGES */
232
+        $languages = $this->l10nFactory->getLanguages();
233 233
 		
234
-		/* FINAL DATA */
235
-		$serverData = array();
236
-		// groups
237
-		$serverData['groups'] = array_merge_recursive($adminGroup, [$disabledUsersGroup], $groups);
238
-		// Various data
239
-		$serverData['isAdmin'] = $this->isAdmin;
240
-		$serverData['sortGroups'] = $sortGroupsBy;
241
-		$serverData['quotaPreset'] = $quotaPreset;
242
-		$serverData['userCount'] = $userCount - $disabledUsers;
243
-		$serverData['languages'] = $languages;
244
-		$serverData['defaultLanguage'] = $this->config->getSystemValue('default_language', 'en');
245
-		// Settings
246
-		$serverData['defaultQuota'] = $defaultQuota;
247
-		$serverData['canChangePassword'] = $canChangePassword;
234
+        /* FINAL DATA */
235
+        $serverData = array();
236
+        // groups
237
+        $serverData['groups'] = array_merge_recursive($adminGroup, [$disabledUsersGroup], $groups);
238
+        // Various data
239
+        $serverData['isAdmin'] = $this->isAdmin;
240
+        $serverData['sortGroups'] = $sortGroupsBy;
241
+        $serverData['quotaPreset'] = $quotaPreset;
242
+        $serverData['userCount'] = $userCount - $disabledUsers;
243
+        $serverData['languages'] = $languages;
244
+        $serverData['defaultLanguage'] = $this->config->getSystemValue('default_language', 'en');
245
+        // Settings
246
+        $serverData['defaultQuota'] = $defaultQuota;
247
+        $serverData['canChangePassword'] = $canChangePassword;
248 248
 
249
-		return new TemplateResponse('settings', 'settings-vue', ['serverData' => $serverData]);
250
-	}
249
+        return new TemplateResponse('settings', 'settings-vue', ['serverData' => $serverData]);
250
+    }
251 251
 
252
-	/**
253
-	 * @NoAdminRequired
254
-	 * @NoSubadminRequired
255
-	 * @PasswordConfirmationRequired
256
-	 *
257
-	 * @param string $avatarScope
258
-	 * @param string $displayname
259
-	 * @param string $displaynameScope
260
-	 * @param string $phone
261
-	 * @param string $phoneScope
262
-	 * @param string $email
263
-	 * @param string $emailScope
264
-	 * @param string $website
265
-	 * @param string $websiteScope
266
-	 * @param string $address
267
-	 * @param string $addressScope
268
-	 * @param string $twitter
269
-	 * @param string $twitterScope
270
-	 * @return DataResponse
271
-	 */
272
-	public function setUserSettings($avatarScope,
273
-									$displayname,
274
-									$displaynameScope,
275
-									$phone,
276
-									$phoneScope,
277
-									$email,
278
-									$emailScope,
279
-									$website,
280
-									$websiteScope,
281
-									$address,
282
-									$addressScope,
283
-									$twitter,
284
-									$twitterScope
285
-	) {
286
-		if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
287
-			return new DataResponse(
288
-				[
289
-					'status' => 'error',
290
-					'data' => [
291
-						'message' => $this->l10n->t('Invalid mail address')
292
-					]
293
-				],
294
-				Http::STATUS_UNPROCESSABLE_ENTITY
295
-			);
296
-		}
297
-		$user = $this->userSession->getUser();
298
-		$data = $this->accountManager->getUser($user);
299
-		$data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
300
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
301
-			$data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
302
-			$data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
303
-		}
304
-		if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
305
-			$federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
306
-			$shareProvider = $federatedFileSharing->getFederatedShareProvider();
307
-			if ($shareProvider->isLookupServerUploadEnabled()) {
308
-				$data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
309
-				$data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
310
-				$data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
311
-				$data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
312
-			}
313
-		}
314
-		try {
315
-			$this->saveUserSettings($user, $data);
316
-			return new DataResponse(
317
-				[
318
-					'status' => 'success',
319
-					'data' => [
320
-						'userId' => $user->getUID(),
321
-						'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
322
-						'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
323
-						'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
324
-						'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
325
-						'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
326
-						'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
327
-						'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
328
-						'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
329
-						'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
330
-						'message' => $this->l10n->t('Settings saved')
331
-					]
332
-				],
333
-				Http::STATUS_OK
334
-			);
335
-		} catch (ForbiddenException $e) {
336
-			return new DataResponse([
337
-				'status' => 'error',
338
-				'data' => [
339
-					'message' => $e->getMessage()
340
-				],
341
-			]);
342
-		}
343
-	}
344
-	/**
345
-	 * update account manager with new user data
346
-	 *
347
-	 * @param IUser $user
348
-	 * @param array $data
349
-	 * @throws ForbiddenException
350
-	 */
351
-	protected function saveUserSettings(IUser $user, array $data) {
352
-		// keep the user back-end up-to-date with the latest display name and email
353
-		// address
354
-		$oldDisplayName = $user->getDisplayName();
355
-		$oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
356
-		if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
357
-			&& $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
358
-		) {
359
-			$result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
360
-			if ($result === false) {
361
-				throw new ForbiddenException($this->l10n->t('Unable to change full name'));
362
-			}
363
-		}
364
-		$oldEmailAddress = $user->getEMailAddress();
365
-		$oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
366
-		if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
367
-			&& $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
368
-		) {
369
-			// this is the only permission a backend provides and is also used
370
-			// for the permission of setting a email address
371
-			if (!$user->canChangeDisplayName()) {
372
-				throw new ForbiddenException($this->l10n->t('Unable to change email address'));
373
-			}
374
-			$user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
375
-		}
376
-		$this->accountManager->updateUser($user, $data);
377
-	}
252
+    /**
253
+     * @NoAdminRequired
254
+     * @NoSubadminRequired
255
+     * @PasswordConfirmationRequired
256
+     *
257
+     * @param string $avatarScope
258
+     * @param string $displayname
259
+     * @param string $displaynameScope
260
+     * @param string $phone
261
+     * @param string $phoneScope
262
+     * @param string $email
263
+     * @param string $emailScope
264
+     * @param string $website
265
+     * @param string $websiteScope
266
+     * @param string $address
267
+     * @param string $addressScope
268
+     * @param string $twitter
269
+     * @param string $twitterScope
270
+     * @return DataResponse
271
+     */
272
+    public function setUserSettings($avatarScope,
273
+                                    $displayname,
274
+                                    $displaynameScope,
275
+                                    $phone,
276
+                                    $phoneScope,
277
+                                    $email,
278
+                                    $emailScope,
279
+                                    $website,
280
+                                    $websiteScope,
281
+                                    $address,
282
+                                    $addressScope,
283
+                                    $twitter,
284
+                                    $twitterScope
285
+    ) {
286
+        if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
287
+            return new DataResponse(
288
+                [
289
+                    'status' => 'error',
290
+                    'data' => [
291
+                        'message' => $this->l10n->t('Invalid mail address')
292
+                    ]
293
+                ],
294
+                Http::STATUS_UNPROCESSABLE_ENTITY
295
+            );
296
+        }
297
+        $user = $this->userSession->getUser();
298
+        $data = $this->accountManager->getUser($user);
299
+        $data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
300
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
301
+            $data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
302
+            $data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
303
+        }
304
+        if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
305
+            $federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
306
+            $shareProvider = $federatedFileSharing->getFederatedShareProvider();
307
+            if ($shareProvider->isLookupServerUploadEnabled()) {
308
+                $data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
309
+                $data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
310
+                $data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
311
+                $data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
312
+            }
313
+        }
314
+        try {
315
+            $this->saveUserSettings($user, $data);
316
+            return new DataResponse(
317
+                [
318
+                    'status' => 'success',
319
+                    'data' => [
320
+                        'userId' => $user->getUID(),
321
+                        'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
322
+                        'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
323
+                        'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
324
+                        'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
325
+                        'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
326
+                        'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
327
+                        'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
328
+                        'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
329
+                        'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
330
+                        'message' => $this->l10n->t('Settings saved')
331
+                    ]
332
+                ],
333
+                Http::STATUS_OK
334
+            );
335
+        } catch (ForbiddenException $e) {
336
+            return new DataResponse([
337
+                'status' => 'error',
338
+                'data' => [
339
+                    'message' => $e->getMessage()
340
+                ],
341
+            ]);
342
+        }
343
+    }
344
+    /**
345
+     * update account manager with new user data
346
+     *
347
+     * @param IUser $user
348
+     * @param array $data
349
+     * @throws ForbiddenException
350
+     */
351
+    protected function saveUserSettings(IUser $user, array $data) {
352
+        // keep the user back-end up-to-date with the latest display name and email
353
+        // address
354
+        $oldDisplayName = $user->getDisplayName();
355
+        $oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
356
+        if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
357
+            && $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
358
+        ) {
359
+            $result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
360
+            if ($result === false) {
361
+                throw new ForbiddenException($this->l10n->t('Unable to change full name'));
362
+            }
363
+        }
364
+        $oldEmailAddress = $user->getEMailAddress();
365
+        $oldEmailAddress = is_null($oldEmailAddress) ? '' : $oldEmailAddress;
366
+        if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
367
+            && $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
368
+        ) {
369
+            // this is the only permission a backend provides and is also used
370
+            // for the permission of setting a email address
371
+            if (!$user->canChangeDisplayName()) {
372
+                throw new ForbiddenException($this->l10n->t('Unable to change email address'));
373
+            }
374
+            $user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
375
+        }
376
+        $this->accountManager->updateUser($user, $data);
377
+    }
378 378
 
379
-	/**
380
-	 * Set the mail address of a user
381
-	 *
382
-	 * @NoAdminRequired
383
-	 * @NoSubadminRequired
384
-	 * @PasswordConfirmationRequired
385
-	 *
386
-	 * @param string $account
387
-	 * @param bool $onlyVerificationCode only return verification code without updating the data
388
-	 * @return DataResponse
389
-	 */
390
-	public function getVerificationCode(string $account, bool $onlyVerificationCode): DataResponse {
379
+    /**
380
+     * Set the mail address of a user
381
+     *
382
+     * @NoAdminRequired
383
+     * @NoSubadminRequired
384
+     * @PasswordConfirmationRequired
385
+     *
386
+     * @param string $account
387
+     * @param bool $onlyVerificationCode only return verification code without updating the data
388
+     * @return DataResponse
389
+     */
390
+    public function getVerificationCode(string $account, bool $onlyVerificationCode): DataResponse {
391 391
 
392
-		$user = $this->userSession->getUser();
392
+        $user = $this->userSession->getUser();
393 393
 
394
-		if ($user === null) {
395
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
396
-		}
394
+        if ($user === null) {
395
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
396
+        }
397 397
 
398
-		$accountData = $this->accountManager->getUser($user);
399
-		$cloudId = $user->getCloudId();
400
-		$message = 'Use my Federated Cloud ID to share with me: ' . $cloudId;
401
-		$signature = $this->signMessage($user, $message);
398
+        $accountData = $this->accountManager->getUser($user);
399
+        $cloudId = $user->getCloudId();
400
+        $message = 'Use my Federated Cloud ID to share with me: ' . $cloudId;
401
+        $signature = $this->signMessage($user, $message);
402 402
 
403
-		$code = $message . ' ' . $signature;
404
-		$codeMd5 = $message . ' ' . md5($signature);
403
+        $code = $message . ' ' . $signature;
404
+        $codeMd5 = $message . ' ' . md5($signature);
405 405
 
406
-		switch ($account) {
407
-			case 'verify-twitter':
408
-				$accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
409
-				$msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
410
-				$code = $codeMd5;
411
-				$type = AccountManager::PROPERTY_TWITTER;
412
-				$data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
413
-				$accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
414
-				break;
415
-			case 'verify-website':
416
-				$accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
417
-				$msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
418
-				$type = AccountManager::PROPERTY_WEBSITE;
419
-				$data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
420
-				$accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
421
-				break;
422
-			default:
423
-				return new DataResponse([], Http::STATUS_BAD_REQUEST);
424
-		}
406
+        switch ($account) {
407
+            case 'verify-twitter':
408
+                $accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
409
+                $msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
410
+                $code = $codeMd5;
411
+                $type = AccountManager::PROPERTY_TWITTER;
412
+                $data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
413
+                $accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
414
+                break;
415
+            case 'verify-website':
416
+                $accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
417
+                $msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
418
+                $type = AccountManager::PROPERTY_WEBSITE;
419
+                $data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
420
+                $accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
421
+                break;
422
+            default:
423
+                return new DataResponse([], Http::STATUS_BAD_REQUEST);
424
+        }
425 425
 
426
-		if ($onlyVerificationCode === false) {
427
-			$this->accountManager->updateUser($user, $accountData);
426
+        if ($onlyVerificationCode === false) {
427
+            $this->accountManager->updateUser($user, $accountData);
428 428
 
429
-			$this->jobList->add(VerifyUserData::class,
430
-				[
431
-					'verificationCode' => $code,
432
-					'data' => $data,
433
-					'type' => $type,
434
-					'uid' => $user->getUID(),
435
-					'try' => 0,
436
-					'lastRun' => $this->getCurrentTime()
437
-				]
438
-			);
439
-		}
429
+            $this->jobList->add(VerifyUserData::class,
430
+                [
431
+                    'verificationCode' => $code,
432
+                    'data' => $data,
433
+                    'type' => $type,
434
+                    'uid' => $user->getUID(),
435
+                    'try' => 0,
436
+                    'lastRun' => $this->getCurrentTime()
437
+                ]
438
+            );
439
+        }
440 440
 
441
-		return new DataResponse(['msg' => $msg, 'code' => $code]);
442
-	}
441
+        return new DataResponse(['msg' => $msg, 'code' => $code]);
442
+    }
443 443
 
444
-	/**
445
-	 * get current timestamp
446
-	 *
447
-	 * @return int
448
-	 */
449
-	protected function getCurrentTime(): int {
450
-		return time();
451
-	}
444
+    /**
445
+     * get current timestamp
446
+     *
447
+     * @return int
448
+     */
449
+    protected function getCurrentTime(): int {
450
+        return time();
451
+    }
452 452
 
453
-	/**
454
-	 * sign message with users private key
455
-	 *
456
-	 * @param IUser $user
457
-	 * @param string $message
458
-	 *
459
-	 * @return string base64 encoded signature
460
-	 */
461
-	protected function signMessage(IUser $user, string $message): string {
462
-		$privateKey = $this->keyManager->getKey($user)->getPrivate();
463
-		openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
464
-		return base64_encode($signature);
465
-	}
453
+    /**
454
+     * sign message with users private key
455
+     *
456
+     * @param IUser $user
457
+     * @param string $message
458
+     *
459
+     * @return string base64 encoded signature
460
+     */
461
+    protected function signMessage(IUser $user, string $message): string {
462
+        $privateKey = $this->keyManager->getKey($user)->getPrivate();
463
+        openssl_sign(json_encode($message), $signature, $privateKey, OPENSSL_ALGO_SHA512);
464
+        return base64_encode($signature);
465
+    }
466 466
 }
Please login to merge, or discard this patch.
settings/templates/settings-vue.php 1 patch
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -25,7 +25,7 @@
 block discarded – undo
25 25
 style('settings', 'settings');
26 26
 
27 27
 // Do we have some data to inject ?
28
-if(is_array($_['serverData'])) {
28
+if (is_array($_['serverData'])) {
29 29
 ?>
30
-<span id="serverData" data-server="<?php p(json_encode($_['serverData']));?>"></span>
30
+<span id="serverData" data-server="<?php p(json_encode($_['serverData'])); ?>"></span>
31 31
 <?php } ?>
Please login to merge, or discard this patch.