Skip to content

Commit cd742aa

Browse files
committed
feat: add support for sensitive Declarative settings values encryption
Signed-off-by: Andrey Borysenko <andrey18106x@gmail.com>
1 parent 68b2a62 commit cd742aa

File tree

13 files changed

+597
-45
lines changed

13 files changed

+597
-45
lines changed

apps/settings/appinfo/routes.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
],
6868
'ocs' => [
6969
['name' => 'DeclarativeSettings#setValue', 'url' => '/settings/api/declarative/value', 'verb' => 'POST', 'root' => ''],
70+
['name' => 'DeclarativeSettings#setSensitiveValue', 'url' => '/settings/api/declarative/value-sensitive', 'verb' => 'POST', 'root' => ''],
7071
['name' => 'DeclarativeSettings#getForms', 'url' => '/settings/api/declarative/forms', 'verb' => 'GET', 'root' => ''],
7172
],
7273
];

apps/settings/lib/Controller/CommonSettingsTrait.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@ private function getIndexResponse(string $type, string $section): TemplateRespon
144144
$this->declarativeSettingsManager->loadSchemas();
145145
$declarativeSettings = $this->declarativeSettingsManager->getFormsWithValues($user, $type, $section);
146146

147+
foreach ($declarativeSettings as &$form) {
148+
foreach ($form['fields'] as &$field) {
149+
if (isset($field['sensitive']) && $field['sensitive'] === true && !empty($field['value'])) {
150+
$field['value'] = 'dummySecret';
151+
}
152+
}
153+
}
154+
147155
if ($type === 'personal') {
148156
$settings = array_values($this->settingsManager->getPersonalSettings($section));
149157
if ($section === 'theming') {

apps/settings/lib/Controller/DeclarativeSettingsController.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use OCA\Settings\ResponseDefinitions;
1616
use OCP\AppFramework\Http;
1717
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
18+
use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
1819
use OCP\AppFramework\Http\DataResponse;
1920
use OCP\AppFramework\OCS\OCSBadRequestException;
2021
use OCP\AppFramework\OCSController;
@@ -53,6 +54,45 @@ public function __construct(
5354
*/
5455
#[NoAdminRequired]
5556
public function setValue(string $app, string $formId, string $fieldId, mixed $value): DataResponse {
57+
return $this->saveValue($app, $formId, $fieldId, $value);
58+
}
59+
60+
/**
61+
* Sets a declarative settings value.
62+
* Password confirmation is required for sensitive values.
63+
*
64+
* @param string $app ID of the app
65+
* @param string $formId ID of the form
66+
* @param string $fieldId ID of the field
67+
* @param mixed $value Value to be saved
68+
* @return DataResponse<Http::STATUS_OK, null, array{}>
69+
* @throws NotLoggedInException Not logged in or not an admin user
70+
* @throws NotAdminException Not logged in or not an admin user
71+
* @throws OCSBadRequestException Invalid arguments to save value
72+
*
73+
* 200: Value set successfully
74+
*/
75+
#[NoAdminRequired]
76+
#[PasswordConfirmationRequired]
77+
public function setSensitiveValue(string $app, string $formId, string $fieldId, mixed $value): DataResponse {
78+
return $this->saveValue($app, $formId, $fieldId, $value);
79+
}
80+
81+
/**
82+
* Sets a declarative settings value.
83+
*
84+
* @param string $app ID of the app
85+
* @param string $formId ID of the form
86+
* @param string $fieldId ID of the field
87+
* @param mixed $value Value to be saved
88+
* @return DataResponse<Http::STATUS_OK, null, array{}>
89+
* @throws NotLoggedInException Not logged in or not an admin user
90+
* @throws NotAdminException Not logged in or not an admin user
91+
* @throws OCSBadRequestException Invalid arguments to save value
92+
*
93+
* 200: Value set successfully
94+
*/
95+
private function saveValue(string $app, string $formId, string $fieldId, mixed $value): DataResponse {
5696
$user = $this->userSession->getUser();
5797
if ($user === null) {
5898
throw new NotLoggedInException();

apps/settings/lib/ResponseDefinitions.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* default: mixed,
2121
* options?: list<string|array{name: string, value: mixed}>,
2222
* value: string|int|float|bool|list<string>,
23+
* sensitive?: boolean,
2324
* }
2425
*
2526
* @psalm-type SettingsDeclarativeForm = array{

apps/settings/openapi-full.json

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@
169169
}
170170
}
171171
]
172+
},
173+
"sensitive": {
174+
"type": "boolean"
172175
}
173176
}
174177
},
@@ -343,7 +346,141 @@
343346
}
344347
},
345348
"400": {
346-
"description": "Invalid arguments to save value",
349+
"description": "Invalid arguments to save value\r",
350+
"content": {
351+
"application/json": {
352+
"schema": {
353+
"type": "object",
354+
"required": [
355+
"ocs"
356+
],
357+
"properties": {
358+
"ocs": {
359+
"type": "object",
360+
"required": [
361+
"meta",
362+
"data"
363+
],
364+
"properties": {
365+
"meta": {
366+
"$ref": "#/components/schemas/OCSMeta"
367+
},
368+
"data": {}
369+
}
370+
}
371+
}
372+
}
373+
}
374+
}
375+
}
376+
}
377+
}
378+
},
379+
"/ocs/v2.php/settings/api/declarative/value-sensitive": {
380+
"post": {
381+
"operationId": "declarative_settings-set-sensitive-value",
382+
"summary": "Sets a declarative settings value. Password confirmation is required for sensitive values.",
383+
"description": "This endpoint requires password confirmation",
384+
"tags": [
385+
"declarative_settings"
386+
],
387+
"security": [
388+
{
389+
"bearer_auth": []
390+
},
391+
{
392+
"basic_auth": []
393+
}
394+
],
395+
"requestBody": {
396+
"required": true,
397+
"content": {
398+
"application/json": {
399+
"schema": {
400+
"type": "object",
401+
"required": [
402+
"app",
403+
"formId",
404+
"fieldId",
405+
"value"
406+
],
407+
"properties": {
408+
"app": {
409+
"type": "string",
410+
"description": "ID of the app"
411+
},
412+
"formId": {
413+
"type": "string",
414+
"description": "ID of the form"
415+
},
416+
"fieldId": {
417+
"type": "string",
418+
"description": "ID of the field"
419+
},
420+
"value": {
421+
"type": "object",
422+
"description": "Value to be saved"
423+
}
424+
}
425+
}
426+
}
427+
}
428+
},
429+
"parameters": [
430+
{
431+
"name": "OCS-APIRequest",
432+
"in": "header",
433+
"description": "Required to be true for the API request to pass",
434+
"required": true,
435+
"schema": {
436+
"type": "boolean",
437+
"default": true
438+
}
439+
}
440+
],
441+
"responses": {
442+
"200": {
443+
"description": "Value set successfully",
444+
"content": {
445+
"application/json": {
446+
"schema": {
447+
"type": "object",
448+
"required": [
449+
"ocs"
450+
],
451+
"properties": {
452+
"ocs": {
453+
"type": "object",
454+
"required": [
455+
"meta",
456+
"data"
457+
],
458+
"properties": {
459+
"meta": {
460+
"$ref": "#/components/schemas/OCSMeta"
461+
},
462+
"data": {
463+
"nullable": true
464+
}
465+
}
466+
}
467+
}
468+
}
469+
}
470+
}
471+
},
472+
"500": {
473+
"description": "Not logged in or not an admin user",
474+
"content": {
475+
"text/plain": {
476+
"schema": {
477+
"type": "string"
478+
}
479+
}
480+
}
481+
},
482+
"400": {
483+
"description": "Invalid arguments to save value\r",
347484
"content": {
348485
"application/json": {
349486
"schema": {

apps/settings/openapi.json

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@
169169
}
170170
}
171171
]
172+
},
173+
"sensitive": {
174+
"type": "boolean"
172175
}
173176
}
174177
},
@@ -302,7 +305,141 @@
302305
}
303306
},
304307
"400": {
305-
"description": "Invalid arguments to save value",
308+
"description": "Invalid arguments to save value\r",
309+
"content": {
310+
"application/json": {
311+
"schema": {
312+
"type": "object",
313+
"required": [
314+
"ocs"
315+
],
316+
"properties": {
317+
"ocs": {
318+
"type": "object",
319+
"required": [
320+
"meta",
321+
"data"
322+
],
323+
"properties": {
324+
"meta": {
325+
"$ref": "#/components/schemas/OCSMeta"
326+
},
327+
"data": {}
328+
}
329+
}
330+
}
331+
}
332+
}
333+
}
334+
}
335+
}
336+
}
337+
},
338+
"/ocs/v2.php/settings/api/declarative/value-sensitive": {
339+
"post": {
340+
"operationId": "declarative_settings-set-sensitive-value",
341+
"summary": "Sets a declarative settings value. Password confirmation is required for sensitive values.",
342+
"description": "This endpoint requires password confirmation",
343+
"tags": [
344+
"declarative_settings"
345+
],
346+
"security": [
347+
{
348+
"bearer_auth": []
349+
},
350+
{
351+
"basic_auth": []
352+
}
353+
],
354+
"requestBody": {
355+
"required": true,
356+
"content": {
357+
"application/json": {
358+
"schema": {
359+
"type": "object",
360+
"required": [
361+
"app",
362+
"formId",
363+
"fieldId",
364+
"value"
365+
],
366+
"properties": {
367+
"app": {
368+
"type": "string",
369+
"description": "ID of the app"
370+
},
371+
"formId": {
372+
"type": "string",
373+
"description": "ID of the form"
374+
},
375+
"fieldId": {
376+
"type": "string",
377+
"description": "ID of the field"
378+
},
379+
"value": {
380+
"type": "object",
381+
"description": "Value to be saved"
382+
}
383+
}
384+
}
385+
}
386+
}
387+
},
388+
"parameters": [
389+
{
390+
"name": "OCS-APIRequest",
391+
"in": "header",
392+
"description": "Required to be true for the API request to pass",
393+
"required": true,
394+
"schema": {
395+
"type": "boolean",
396+
"default": true
397+
}
398+
}
399+
],
400+
"responses": {
401+
"200": {
402+
"description": "Value set successfully",
403+
"content": {
404+
"application/json": {
405+
"schema": {
406+
"type": "object",
407+
"required": [
408+
"ocs"
409+
],
410+
"properties": {
411+
"ocs": {
412+
"type": "object",
413+
"required": [
414+
"meta",
415+
"data"
416+
],
417+
"properties": {
418+
"meta": {
419+
"$ref": "#/components/schemas/OCSMeta"
420+
},
421+
"data": {
422+
"nullable": true
423+
}
424+
}
425+
}
426+
}
427+
}
428+
}
429+
}
430+
},
431+
"500": {
432+
"description": "Not logged in or not an admin user",
433+
"content": {
434+
"text/plain": {
435+
"schema": {
436+
"type": "string"
437+
}
438+
}
439+
}
440+
},
441+
"400": {
442+
"description": "Invalid arguments to save value\r",
306443
"content": {
307444
"application/json": {
308445
"schema": {

0 commit comments

Comments
 (0)