Skip to content

Commit 4ac2375

Browse files
provokateurinandrey18106
authored andcommitted
feat: Add declarative settings
Signed-off-by: jld3103 <jld3103yt@gmail.com> Signed-off-by: Julien Veyssier <julien-nc@posteo.net> Signed-off-by: Andrey Borysenko <andrey18106x@gmail.com>
1 parent c423973 commit 4ac2375

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+3215
-52
lines changed

apps/settings/appinfo/routes.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,9 @@
8181
['name' => 'WebAuthn#deleteRegistration', 'url' => '/settings/api/personal/webauthn/registration/{id}', 'verb' => 'DELETE' , 'root' => ''],
8282

8383
['name' => 'Reasons#getPdf', 'url' => '/settings/download/reasons', 'verb' => 'GET', 'root' => ''],
84-
]
84+
],
85+
'ocs' => [
86+
['name' => 'DeclarativeSettings#setValue', 'url' => '/settings/api/declarative/value', 'verb' => 'POST', 'root' => ''],
87+
['name' => 'DeclarativeSettings#getForms', 'url' => '/settings/api/declarative/forms', 'verb' => 'GET', 'root' => ''],
88+
],
8589
];

apps/settings/composer/composer/autoload_classmap.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
'OCA\\Settings\\Controller\\ChangePasswordController' => $baseDir . '/../lib/Controller/ChangePasswordController.php',
2828
'OCA\\Settings\\Controller\\CheckSetupController' => $baseDir . '/../lib/Controller/CheckSetupController.php',
2929
'OCA\\Settings\\Controller\\CommonSettingsTrait' => $baseDir . '/../lib/Controller/CommonSettingsTrait.php',
30+
'OCA\\Settings\\Controller\\DeclarativeSettingsController' => $baseDir . '/../lib/Controller/DeclarativeSettingsController.php',
3031
'OCA\\Settings\\Controller\\HelpController' => $baseDir . '/../lib/Controller/HelpController.php',
3132
'OCA\\Settings\\Controller\\LogSettingsController' => $baseDir . '/../lib/Controller/LogSettingsController.php',
3233
'OCA\\Settings\\Controller\\MailSettingsController' => $baseDir . '/../lib/Controller/MailSettingsController.php',
@@ -43,6 +44,7 @@
4344
'OCA\\Settings\\Listener\\UserRemovedFromGroupActivityListener' => $baseDir . '/../lib/Listener/UserRemovedFromGroupActivityListener.php',
4445
'OCA\\Settings\\Mailer\\NewUserMailHelper' => $baseDir . '/../lib/Mailer/NewUserMailHelper.php',
4546
'OCA\\Settings\\Middleware\\SubadminMiddleware' => $baseDir . '/../lib/Middleware/SubadminMiddleware.php',
47+
'OCA\\Settings\\ResponseDefinitions' => $baseDir . '/../lib/ResponseDefinitions.php',
4648
'OCA\\Settings\\Search\\AppSearch' => $baseDir . '/../lib/Search/AppSearch.php',
4749
'OCA\\Settings\\Search\\SectionSearch' => $baseDir . '/../lib/Search/SectionSearch.php',
4850
'OCA\\Settings\\Search\\UserSearch' => $baseDir . '/../lib/Search/UserSearch.php',

apps/settings/composer/composer/autoload_static.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class ComposerStaticInitSettings
4242
'OCA\\Settings\\Controller\\ChangePasswordController' => __DIR__ . '/..' . '/../lib/Controller/ChangePasswordController.php',
4343
'OCA\\Settings\\Controller\\CheckSetupController' => __DIR__ . '/..' . '/../lib/Controller/CheckSetupController.php',
4444
'OCA\\Settings\\Controller\\CommonSettingsTrait' => __DIR__ . '/..' . '/../lib/Controller/CommonSettingsTrait.php',
45+
'OCA\\Settings\\Controller\\DeclarativeSettingsController' => __DIR__ . '/..' . '/../lib/Controller/DeclarativeSettingsController.php',
4546
'OCA\\Settings\\Controller\\HelpController' => __DIR__ . '/..' . '/../lib/Controller/HelpController.php',
4647
'OCA\\Settings\\Controller\\LogSettingsController' => __DIR__ . '/..' . '/../lib/Controller/LogSettingsController.php',
4748
'OCA\\Settings\\Controller\\MailSettingsController' => __DIR__ . '/..' . '/../lib/Controller/MailSettingsController.php',
@@ -58,6 +59,7 @@ class ComposerStaticInitSettings
5859
'OCA\\Settings\\Listener\\UserRemovedFromGroupActivityListener' => __DIR__ . '/..' . '/../lib/Listener/UserRemovedFromGroupActivityListener.php',
5960
'OCA\\Settings\\Mailer\\NewUserMailHelper' => __DIR__ . '/..' . '/../lib/Mailer/NewUserMailHelper.php',
6061
'OCA\\Settings\\Middleware\\SubadminMiddleware' => __DIR__ . '/..' . '/../lib/Middleware/SubadminMiddleware.php',
62+
'OCA\\Settings\\ResponseDefinitions' => __DIR__ . '/..' . '/../lib/ResponseDefinitions.php',
6163
'OCA\\Settings\\Search\\AppSearch' => __DIR__ . '/..' . '/../lib/Search/AppSearch.php',
6264
'OCA\\Settings\\Search\\SectionSearch' => __DIR__ . '/..' . '/../lib/Search/SectionSearch.php',
6365
'OCA\\Settings\\Search\\UserSearch' => __DIR__ . '/..' . '/../lib/Search/UserSearch.php',

apps/settings/composer/composer/installed.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
'name' => '__root__',
44
'pretty_version' => 'dev-master',
55
'version' => 'dev-master',
6-
'reference' => 'b1797842784b250fb01ed5e3bf130705eb94751b',
6+
'reference' => '4ff660ca2e0baa02440ba07296ed7e75fa544c0e',
77
'type' => 'library',
88
'install_path' => __DIR__ . '/../',
99
'aliases' => array(),
@@ -13,7 +13,7 @@
1313
'__root__' => array(
1414
'pretty_version' => 'dev-master',
1515
'version' => 'dev-master',
16-
'reference' => 'b1797842784b250fb01ed5e3bf130705eb94751b',
16+
'reference' => '4ff660ca2e0baa02440ba07296ed7e75fa544c0e',
1717
'type' => 'library',
1818
'install_path' => __DIR__ . '/../',
1919
'aliases' => array(),

apps/settings/lib/Controller/AdminSettingsController.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
use OCP\AppFramework\Controller;
3131
use OCP\AppFramework\Http\Attribute\OpenAPI;
3232
use OCP\AppFramework\Http\TemplateResponse;
33+
use OCP\AppFramework\Services\IInitialState;
3334
use OCP\Group\ISubAdmin;
3435
use OCP\IGroupManager;
3536
use OCP\INavigationManager;
3637
use OCP\IRequest;
3738
use OCP\IUser;
3839
use OCP\IUserSession;
40+
use OCP\Settings\IDeclarativeManager;
3941
use OCP\Settings\IManager as ISettingsManager;
4042
use OCP\Template;
4143

@@ -50,14 +52,18 @@ public function __construct(
5052
ISettingsManager $settingsManager,
5153
IUserSession $userSession,
5254
IGroupManager $groupManager,
53-
ISubAdmin $subAdmin
55+
ISubAdmin $subAdmin,
56+
IDeclarativeManager $declarativeSettingsManager,
57+
IInitialState $initialState,
5458
) {
5559
parent::__construct($appName, $request);
5660
$this->navigationManager = $navigationManager;
5761
$this->settingsManager = $settingsManager;
5862
$this->userSession = $userSession;
5963
$this->groupManager = $groupManager;
6064
$this->subAdmin = $subAdmin;
65+
$this->declarativeSettingsManager = $declarativeSettingsManager;
66+
$this->initialState = $initialState;
6167
}
6268

6369
/**
@@ -80,7 +86,8 @@ protected function getSettings($section) {
8086
$user = $this->userSession->getUser();
8187
$isSubAdmin = !$this->groupManager->isAdmin($user->getUID()) && $this->subAdmin->isSubAdmin($user);
8288
$settings = $this->settingsManager->getAllowedAdminSettings($section, $user);
83-
if (empty($settings)) {
89+
$declarativeFormIDs = $this->declarativeSettingsManager->getFormIDs($user, 'admin', $section);
90+
if (empty($settings) && empty($declarativeFormIDs)) {
8491
throw new NotAdminException("Logged in user doesn't have permission to access these settings.");
8592
}
8693
$formatted = $this->formatSettings($settings);

apps/settings/lib/Controller/CommonSettingsTrait.php

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,26 @@
2626
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2727
*
2828
*/
29+
2930
namespace OCA\Settings\Controller;
3031

32+
use OCA\Settings\AppInfo\Application;
3133
use OCP\AppFramework\Http\TemplateResponse;
34+
use OCP\AppFramework\Services\IInitialState;
3235
use OCP\Group\ISubAdmin;
3336
use OCP\IGroupManager;
3437
use OCP\INavigationManager;
3538
use OCP\IUserSession;
39+
use OCP\Settings\IDeclarativeManager;
40+
use OCP\Settings\IDeclarativeSettingsForm;
3641
use OCP\Settings\IIconSection;
3742
use OCP\Settings\IManager as ISettingsManager;
3843
use OCP\Settings\ISettings;
44+
use OCP\Util;
3945

46+
/**
47+
* @psalm-import-type DeclarativeSettingsFormField from IDeclarativeSettingsForm
48+
*/
4049
trait CommonSettingsTrait {
4150

4251
/** @var ISettingsManager */
@@ -54,28 +63,26 @@ trait CommonSettingsTrait {
5463
/** @var ISubAdmin */
5564
private $subAdmin;
5665

66+
private IDeclarativeManager $declarativeSettingsManager;
67+
68+
/** @var IInitialState */
69+
private $initialState;
70+
5771
/**
5872
* @return array{forms: array{personal: array, admin: array}}
5973
*/
6074
private function getNavigationParameters(string $currentType, string $currentSection): array {
61-
$templateParameters = [
62-
'personal' => $this->formatPersonalSections($currentType, $currentSection),
63-
'admin' => []
64-
];
65-
66-
$templateParameters['admin'] = $this->formatAdminSections(
67-
$currentType,
68-
$currentSection
69-
);
70-
7175
return [
72-
'forms' => $templateParameters
76+
'forms' => [
77+
'personal' => $this->formatPersonalSections($currentType, $currentSection),
78+
'admin' => $this->formatAdminSections($currentType, $currentSection),
79+
],
7380
];
7481
}
7582

7683
/**
7784
* @param IIconSection[][] $sections
78-
* @psam-param 'admin'|'personal' $type
85+
* @psalm-param 'admin'|'personal' $type
7986
* @return list<array{anchor: string, section-name: string, active: bool, icon: string}>
8087
*/
8188
protected function formatSections(array $sections, string $currentSection, string $type, string $currentType): array {
@@ -87,7 +94,11 @@ protected function formatSections(array $sections, string $currentSection, strin
8794
} elseif ($type === 'personal') {
8895
$settings = $this->settingsManager->getPersonalSettings($section->getID());
8996
}
90-
if (empty($settings) && !($section->getID() === 'additional' && count(\OC_App::getForms('admin')) > 0)) {
97+
98+
/** @psalm-suppress PossiblyNullArgument */
99+
$declarativeFormIDs = $this->declarativeSettingsManager->getFormIDs($this->userSession->getUser(), $type, $section->getID());
100+
101+
if (empty($settings) && empty($declarativeFormIDs) && !($section->getID() === 'additional' && count(\OC_App::getForms('admin')) > 0)) {
91102
continue;
92103
}
93104

@@ -107,14 +118,14 @@ protected function formatSections(array $sections, string $currentSection, strin
107118
return $templateParameters;
108119
}
109120

110-
protected function formatPersonalSections(string $currentType, string $currentSections): array {
121+
protected function formatPersonalSections(string $currentType, string $currentSection): array {
111122
$sections = $this->settingsManager->getPersonalSections();
112-
return $this->formatSections($sections, $currentSections, 'personal', $currentType);
123+
return $this->formatSections($sections, $currentSection, 'personal', $currentType);
113124
}
114125

115-
protected function formatAdminSections(string $currentType, string $currentSections): array {
126+
protected function formatAdminSections(string $currentType, string $currentSection): array {
116127
$sections = $this->settingsManager->getAdminSections();
117-
return $this->formatSections($sections, $currentSections, 'admin', $currentType);
128+
return $this->formatSections($sections, $currentSection, 'admin', $currentType);
118129
}
119130

120131
/**
@@ -133,6 +144,9 @@ private function formatSettings(array $settings): array {
133144
return ['content' => $html];
134145
}
135146

147+
/**
148+
* @psalm-param 'admin'|'personal' $type
149+
*/
136150
private function getIndexResponse(string $type, string $section): TemplateResponse {
137151
if ($type === 'personal') {
138152
if ($section === 'theming') {
@@ -144,9 +158,24 @@ private function getIndexResponse(string $type, string $section): TemplateRespon
144158
$this->navigationManager->setActiveEntry('admin_settings');
145159
}
146160

161+
$this->declarativeSettingsManager->loadSchemas();
162+
147163
$templateParams = [];
148164
$templateParams = array_merge($templateParams, $this->getNavigationParameters($type, $section));
149165
$templateParams = array_merge($templateParams, $this->getSettings($section));
166+
167+
/** @psalm-suppress PossiblyNullArgument */
168+
$declarativeFormIDs = $this->declarativeSettingsManager->getFormIDs($this->userSession->getUser(), $type, $section);
169+
if (!empty($declarativeFormIDs)) {
170+
foreach ($declarativeFormIDs as $app => $ids) {
171+
/** @psalm-suppress PossiblyUndefinedArrayOffset */
172+
$templateParams['content'] .= join(array_map(fn (string $id) => '<div id="' . $app . '_' . $id . '"></div>', $ids));
173+
}
174+
Util::addScript(Application::APP_ID, 'declarative-settings-forms');
175+
/** @psalm-suppress PossiblyNullArgument */
176+
$this->initialState->provideInitialState('declarative-settings-forms', $this->declarativeSettingsManager->getFormsWithValues($this->userSession->getUser(), $type, $section));
177+
}
178+
150179
$activeSection = $this->settingsManager->getSection($type, $section);
151180
if ($activeSection) {
152181
$templateParams['pageTitle'] = $activeSection->getName();
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
/**
3+
* @copyright Copyright (c) 2023 Kate Döen <kate.doeen@nextcloud.com>
4+
*
5+
* @author Kate Döen <kate.doeen@nextcloud.com>
6+
*
7+
* @license GNU AGPL version 3 or any later version
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Affero General Public License as
11+
* published by the Free Software Foundation, either version 3 of the
12+
* License, or (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Affero General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Affero General Public License
20+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
namespace OCA\Settings\Controller;
25+
26+
use Exception;
27+
use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException;
28+
use OC\AppFramework\Middleware\Security\Exceptions\NotLoggedInException;
29+
use OCA\Settings\ResponseDefinitions;
30+
use OCP\AppFramework\Http;
31+
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
32+
use OCP\AppFramework\Http\DataResponse;
33+
use OCP\AppFramework\OCS\OCSBadRequestException;
34+
use OCP\AppFramework\OCSController;
35+
use OCP\IRequest;
36+
use OCP\IUserSession;
37+
use OCP\Settings\IDeclarativeManager;
38+
use Psr\Log\LoggerInterface;
39+
40+
/**
41+
* @psalm-import-type SettingsDeclarativeForm from ResponseDefinitions
42+
*/
43+
class DeclarativeSettingsController extends OCSController {
44+
public function __construct(
45+
string $appName,
46+
IRequest $request,
47+
private IUserSession $userSession,
48+
private IDeclarativeManager $declarativeManager,
49+
private LoggerInterface $logger,
50+
) {
51+
parent::__construct($appName, $request);
52+
}
53+
54+
/**
55+
* Sets a declarative settings value
56+
*
57+
* @param string $app ID of the app
58+
* @param string $formId ID of the form
59+
* @param string $fieldId ID of the field
60+
* @param mixed $value Value to be saved
61+
* @return DataResponse<Http::STATUS_OK, null, array{}>
62+
* @throws NotLoggedInException Not logged in or not an admin user
63+
* @throws NotAdminException Not logged in or not an admin user
64+
* @throws OCSBadRequestException Invalid arguments to save value
65+
*
66+
* 200: Value set successfully
67+
*/
68+
#[NoAdminRequired]
69+
public function setValue(string $app, string $formId, string $fieldId, mixed $value): DataResponse {
70+
$user = $this->userSession->getUser();
71+
if ($user === null) {
72+
throw new NotLoggedInException();
73+
}
74+
75+
try {
76+
$this->declarativeManager->loadSchemas();
77+
$this->declarativeManager->setValue($user, $app, $formId, $fieldId, $value);
78+
return new DataResponse(null);
79+
} catch (NotAdminException $e) {
80+
throw $e;
81+
} catch (Exception $e) {
82+
$this->logger->error('Failed to set declarative settings value: ' . $e->getMessage());
83+
throw new OCSBadRequestException();
84+
}
85+
}
86+
87+
/**
88+
* Gets all declarative forms with the values prefilled.
89+
*
90+
* @return DataResponse<Http::STATUS_OK, list<SettingsDeclarativeForm>, array{}>
91+
* @throws NotLoggedInException
92+
* @NoSubAdminRequired
93+
*
94+
* 200: Forms returned
95+
*/
96+
#[NoAdminRequired]
97+
public function getForms(): DataResponse {
98+
$user = $this->userSession->getUser();
99+
if ($user === null) {
100+
throw new NotLoggedInException();
101+
}
102+
$this->declarativeManager->loadSchemas();
103+
return new DataResponse($this->declarativeManager->getFormsWithValues($user, null, null));
104+
}
105+
}

apps/settings/lib/Controller/PersonalSettingsController.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929
use OCP\AppFramework\Controller;
3030
use OCP\AppFramework\Http\Attribute\OpenAPI;
3131
use OCP\AppFramework\Http\TemplateResponse;
32+
use OCP\AppFramework\Services\IInitialState;
3233
use OCP\Group\ISubAdmin;
3334
use OCP\IGroupManager;
3435
use OCP\INavigationManager;
3536
use OCP\IRequest;
3637
use OCP\IUserSession;
38+
use OCP\Settings\IDeclarativeManager;
3739
use OCP\Settings\IManager as ISettingsManager;
3840
use OCP\Template;
3941

@@ -48,14 +50,18 @@ public function __construct(
4850
ISettingsManager $settingsManager,
4951
IUserSession $userSession,
5052
IGroupManager $groupManager,
51-
ISubAdmin $subAdmin
53+
ISubAdmin $subAdmin,
54+
IDeclarativeManager $declarativeSettingsManager,
55+
IInitialState $initialState,
5256
) {
5357
parent::__construct($appName, $request);
5458
$this->navigationManager = $navigationManager;
5559
$this->settingsManager = $settingsManager;
5660
$this->userSession = $userSession;
5761
$this->subAdmin = $subAdmin;
5862
$this->groupManager = $groupManager;
63+
$this->declarativeSettingsManager = $declarativeSettingsManager;
64+
$this->initialState = $initialState;
5965
}
6066

6167
/**

0 commit comments

Comments
 (0)