Password hidden field for api keys (username) (#630)

* feat: add username hidden field to api keys * fix: do not read api_keys from backend and only save new * feat: treat api_key filds as plaintext --------- Co-authored-by: Rafael Uzarowski <uzarowski.rafael@proton.me>

ehl0wr0ld committed Aug 7, 2025 at 14:31 UTC b4e42481496702efc4373ce6da0ab2450b2ed5a6
2 files changed +14 -4
python/helpers/settings.py
+11 -3
@@ -143,6 +143,7 @@ class SettingsOutput(TypedDict):
143
144
145 PASSWORD_PLACEHOLDER = "****PSWD****"
146 +API_KEY_PLACEHOLDER = "************"
147
148 SETTINGS_FILE = files.get_abs_path("tmp/settings.json")
149 _settings: Settings | None = None
@@ -1138,11 +1139,12 @@ def convert_out(settings: Settings) -> SettingsOutput:
1139
1140 def _get_api_key_field(settings: Settings, provider: str, title: str) -> SettingsField:
1141 key = settings["api_keys"].get(provider, models.get_api_key(provider))
1142 + # For API keys, use simple asterisk placeholder for existing keys
1143 return {
1144 "id": f"api_key_{provider}",
1145 "title": title,
1144 - "type": "password",
1145 - "value": (PASSWORD_PLACEHOLDER if key and key != "None" else ""),
1146 + "type": "text",
1147 + "value": (API_KEY_PLACEHOLDER if key and key != "None" else ""),
1148 }
1149
1150
@@ -1151,7 +1153,13 @@ def convert_in(settings: dict) -> Settings:
1153 for section in settings["sections"]:
1154 if "fields" in section:
1155 for field in section["fields"]:
1154 - if field["value"] != PASSWORD_PLACEHOLDER:
1156 + # Skip saving if value is a placeholder
1157 + should_skip = (
1158 + field["value"] == PASSWORD_PLACEHOLDER or
1159 + field["value"] == API_KEY_PLACEHOLDER
1160 + )
1161 +
1162 + if not should_skip:
1163 if field["id"].endswith("_kwargs"):
1164 current[field["id"]] = _env_to_dict(field["value"])
1165 elif field["id"].startswith("api_key_"):
webui/index.html
+3 -1
@@ -622,10 +622,12 @@
622 </template>
623
624
625 - <!-- Password field -->
625 + <!-- Password field -->
626 <template x-if="field.type === 'password'">
627 <input type="password" :class="field.classes" :value="field.value"
628 :readonly="field.readonly === true"
629 + :id="field.id"
630 + autocomplete="off"
631 @input="field.value = $event.target.value">
632 </template>
633