Skip to content

Commit 874e8aa

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

3 files changed

Lines changed: 58 additions & 6 deletions

File tree

lib/Db/UI/SettingsForm.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ public function __construct(array $params = []) {
4747
}
4848
}
4949

50+
public function getSchemaField(string $fieldId): ?array {
51+
$scheme = $this->getScheme();
52+
foreach ($scheme['fields'] as $field) {
53+
if ($field['id'] === $fieldId) {
54+
return $field;
55+
}
56+
}
57+
return null;
58+
}
59+
5060
public function jsonSerialize(): array {
5161
return [
5262
'id' => $this->getId(),

lib/Listener/DeclarativeSettings/GetValueListener.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,21 @@
1414
use OCA\AppAPI\Service\UI\SettingsService;
1515
use OCP\EventDispatcher\Event;
1616
use OCP\EventDispatcher\IEventListener;
17+
use OCP\Security\ICrypto;
1718
use OCP\Settings\DeclarativeSettingsTypes;
1819
use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
20+
use Psr\Log\LoggerInterface;
1921

2022
/**
2123
* @template-implements IEventListener<Event>
2224
*/
2325
class GetValueListener implements IEventListener {
2426
public function __construct(
25-
private readonly SettingsService $service,
27+
private readonly SettingsService $service,
2628
private readonly ExAppPreferenceService $preferenceService,
27-
private readonly ExAppConfigService $configService,
29+
private readonly ExAppConfigService $configService,
30+
private readonly ICrypto $crypto,
31+
private readonly LoggerInterface $logger,
2832
) {
2933
}
3034

@@ -38,9 +42,19 @@ public function handle(Event $event): void {
3842
return;
3943
}
4044
$formSchema = $settingsForm->getScheme();
45+
$field = $settingsForm->getSchemaField($event->getFieldId());
46+
$isSensitive = isset($field['sensitive']) && $field['sensitive'] === true;
4147
if ($formSchema['section_type'] === DeclarativeSettingsTypes::SECTION_TYPE_ADMIN) {
4248
$existingValue = $this->configService->getAppConfig($event->getApp(), $event->getFieldId());
4349
if (!empty($existingValue)) {
50+
if ($isSensitive) {
51+
try {
52+
$encryptedValue = $this->crypto->decrypt($existingValue->getConfigvalue());
53+
$existingValue->setConfigvalue($encryptedValue);
54+
} catch (\Exception $e) {
55+
$existingValue->setConfigvalue('');
56+
}
57+
}
4458
$event->setValue($existingValue->getConfigvalue());
4559
return;
4660
}
@@ -51,6 +65,15 @@ public function handle(Event $event): void {
5165
[$event->getFieldId()],
5266
);
5367
if (!empty($existingValue)) {
68+
if ($isSensitive) {
69+
try {
70+
$encryptedValue = $this->crypto->decrypt($existingValue[0]['configvalue']);
71+
$existingValue[0]['configvalue'] = $encryptedValue;
72+
} catch (\Exception $e) {
73+
$this->logger->warning('Failed to decrypt declarative setting.', ['exception' => $e]);
74+
$existingValue[0]['configvalue'] = '';
75+
}
76+
}
5477
$event->setValue($existingValue[0]['configvalue']);
5578
return;
5679
}

lib/Listener/DeclarativeSettings/SetValueListener.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,21 @@
1414
use OCA\AppAPI\Service\UI\SettingsService;
1515
use OCP\EventDispatcher\Event;
1616
use OCP\EventDispatcher\IEventListener;
17+
use OCP\Security\ICrypto;
1718
use OCP\Settings\DeclarativeSettingsTypes;
1819
use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
20+
use Psr\Log\LoggerInterface;
1921

2022
/**
2123
* @template-implements IEventListener<Event>
2224
*/
2325
class SetValueListener implements IEventListener {
2426
public function __construct(
25-
private readonly SettingsService $service,
27+
private readonly SettingsService $service,
2628
private readonly ExAppPreferenceService $preferenceService,
27-
private readonly ExAppConfigService $configService,
29+
private readonly ExAppConfigService $configService,
30+
private readonly ICrypto $crypto,
31+
private readonly LoggerInterface $logger,
2832
) {
2933
}
3034

@@ -38,11 +42,26 @@ public function handle(Event $event): void {
3842
return;
3943
}
4044
$formSchema = $settingsForm->getScheme();
45+
$field = $settingsForm->getSchemaField($event->getFieldId());
46+
$isSensitive = isset($field['sensitive']) && $field['sensitive'] === true;
47+
$value = $event->getValue();
48+
if ($isSensitive) {
49+
try {
50+
$encryptedValue = $this->crypto->encrypt($value);
51+
$value = $encryptedValue;
52+
} catch (\Exception $e) {
53+
$this->logger->warning(
54+
sprintf('Failed to encrypt sensitive value for app %s, field %s', $event->getApp(), $event->getFieldId()),
55+
['exception' => $e, 'app' => $event->getApp()]
56+
);
57+
return;
58+
}
59+
}
4160
if ($formSchema['section_type'] === DeclarativeSettingsTypes::SECTION_TYPE_ADMIN) {
42-
$this->configService->setAppConfigValue($event->getApp(), $event->getFieldId(), $event->getValue());
61+
$this->configService->setAppConfigValue($event->getApp(), $event->getFieldId(), $value);
4362
} else {
4463
$this->preferenceService->setUserConfigValue(
45-
$event->getUser()->getUID(), $event->getApp(), $event->getFieldId(), $event->getValue()
64+
$event->getUser()->getUID(), $event->getApp(), $event->getFieldId(), $value
4665
);
4766
}
4867
}

0 commit comments

Comments
 (0)