From a3eed49638ef7d3086dfc8257228ca466c114237 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Thu, 24 Apr 2025 13:54:42 -0700 Subject: [PATCH] Use password and select config fields --- .../admin/config/config.component.html | 1 + .../admin/config/config.component.ts | 2 + .../input/password/password.component.html | 35 ++++++++----- src-ui/src/app/data/paperless-config.ts | 11 +++- src/documents/tests/test_api_app_config.py | 52 +++++++++---------- src/paperless/serialisers.py | 4 ++ 6 files changed, 62 insertions(+), 43 deletions(-) diff --git a/src-ui/src/app/components/admin/config/config.component.html b/src-ui/src/app/components/admin/config/config.component.html index 0f74339fb..ca1cc9e44 100644 --- a/src-ui/src/app/components/admin/config/config.component.html +++ b/src-ui/src/app/components/admin/config/config.component.html @@ -35,6 +35,7 @@ @case (ConfigOptionType.String) { } @case (ConfigOptionType.JSON) { } @case (ConfigOptionType.File) { } + @case (ConfigOptionType.Password) { } } diff --git a/src-ui/src/app/components/admin/config/config.component.ts b/src-ui/src/app/components/admin/config/config.component.ts index 76f6b8795..767c084b1 100644 --- a/src-ui/src/app/components/admin/config/config.component.ts +++ b/src-ui/src/app/components/admin/config/config.component.ts @@ -29,6 +29,7 @@ import { SettingsService } from 'src/app/services/settings.service' import { ToastService } from 'src/app/services/toast.service' import { FileComponent } from '../../common/input/file/file.component' import { NumberComponent } from '../../common/input/number/number.component' +import { PasswordComponent } from '../../common/input/password/password.component' import { SelectComponent } from '../../common/input/select/select.component' import { SwitchComponent } from '../../common/input/switch/switch.component' import { TextComponent } from '../../common/input/text/text.component' @@ -46,6 +47,7 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading TextComponent, NumberComponent, FileComponent, + PasswordComponent, AsyncPipe, NgbNavModule, FormsModule, diff --git a/src-ui/src/app/components/common/input/password/password.component.html b/src-ui/src/app/components/common/input/password/password.component.html index 1a70ff4f6..6b8ae75cd 100644 --- a/src-ui/src/app/components/common/input/password/password.component.html +++ b/src-ui/src/app/components/common/input/password/password.component.html @@ -1,17 +1,24 @@ -
- -
- - @if (showReveal) { - +
+
+
+ @if (title) { + + } +
+
+
+ + @if (showReveal) { + + } +
+
+ {{error}} +
+ @if (hint) { + }
-
- {{error}} -
- @if (hint) { - - }
diff --git a/src-ui/src/app/data/paperless-config.ts b/src-ui/src/app/data/paperless-config.ts index 0c309c7d2..96e4da924 100644 --- a/src-ui/src/app/data/paperless-config.ts +++ b/src-ui/src/app/data/paperless-config.ts @@ -44,6 +44,7 @@ export enum ConfigOptionType { Boolean = 'boolean', JSON = 'json', File = 'file', + Password = 'password', } export const ConfigCategory = { @@ -52,6 +53,11 @@ export const ConfigCategory = { AI: $localize`AI Settings`, } +export const LLMBackendConfig = { + OPENAI: 'openai', + OLLAMA: 'ollama', +} + export interface ConfigOption { key: string title: string @@ -191,7 +197,8 @@ export const PaperlessConfigOptions: ConfigOption[] = [ { key: 'llm_backend', title: $localize`LLM Backend`, - type: ConfigOptionType.String, + type: ConfigOptionType.Select, + choices: mapToItems(LLMBackendConfig), config_key: 'PAPERLESS_LLM_BACKEND', category: ConfigCategory.AI, }, @@ -205,7 +212,7 @@ export const PaperlessConfigOptions: ConfigOption[] = [ { key: 'llm_api_key', title: $localize`LLM API Key`, - type: ConfigOptionType.String, + type: ConfigOptionType.Password, config_key: 'PAPERLESS_LLM_API_KEY', category: ConfigCategory.AI, }, diff --git a/src/documents/tests/test_api_app_config.py b/src/documents/tests/test_api_app_config.py index 0e298545c..25d18e140 100644 --- a/src/documents/tests/test_api_app_config.py +++ b/src/documents/tests/test_api_app_config.py @@ -32,33 +32,31 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) self.maxDiff = None - self.assertEqual( - json.dumps(response.data[0]), - json.dumps( - { - "id": 1, - "user_args": None, - "output_type": None, - "pages": None, - "language": None, - "mode": None, - "skip_archive_file": None, - "image_dpi": None, - "unpaper_clean": None, - "deskew": None, - "rotate_pages": None, - "rotate_pages_threshold": None, - "max_image_pixels": None, - "color_conversion_strategy": None, - "app_title": None, - "app_logo": None, - "ai_enabled": False, - "llm_backend": None, - "llm_model": None, - "llm_api_key": None, - "llm_url": None, - }, - ), + self.assertDictEqual( + response.data[0], + { + "id": 1, + "user_args": None, + "output_type": None, + "pages": None, + "language": None, + "mode": None, + "skip_archive_file": None, + "image_dpi": None, + "unpaper_clean": None, + "deskew": None, + "rotate_pages": None, + "rotate_pages_threshold": None, + "max_image_pixels": None, + "color_conversion_strategy": None, + "app_title": None, + "app_logo": None, + "ai_enabled": False, + "llm_backend": None, + "llm_model": None, + "llm_api_key": None, + "llm_url": None, + }, ) def test_api_get_ui_settings_with_config(self): diff --git a/src/paperless/serialisers.py b/src/paperless/serialisers.py index 461eef587..4ff9ceb46 100644 --- a/src/paperless/serialisers.py +++ b/src/paperless/serialisers.py @@ -185,6 +185,10 @@ class ProfileSerializer(serializers.ModelSerializer): class ApplicationConfigurationSerializer(serializers.ModelSerializer): user_args = serializers.JSONField(binary=True, allow_null=True) + llm_api_key = ObfuscatedPasswordField( + required=False, + allow_null=True, + ) def run_validation(self, data): # Empty strings treated as None to avoid unexpected behavior