04/24 Migrated info which stored in .ini to database and keyring

This commit is contained in:
2026-04-24 15:37:58 -04:00
parent f2a8d3f15b
commit 5d6ca5a039
9 changed files with 479 additions and 299 deletions
+24 -15
View File
@@ -1,13 +1,12 @@
"""
views/settings_view.py — Database connection settings dialog.
Shown automatically on first run (no config.ini) and accessible
Shown automatically on first run (no stored credentials) and accessible
via the admin sidebar Settings nav item at any time.
Writes connection details to config.ini via config.save_config().
Does NOT store the password in plaintext beyond what config.ini holds
(which is acceptable for a locally-run desktop tool; operators should
restrict file-system access to config.ini in production).
Credentials are saved to the OS native keychain (Windows Credential Manager,
macOS Keychain, or Linux Secret Service) via the keyring library.
No config.ini or local file is written — the app is fully portable.
"""
import tkinter as tk
@@ -42,7 +41,7 @@ class SettingsView(tk.Toplevel):
self.title("Database Setup" if first_run else "Connection Settings")
self.configure(bg=COLOURS["bg"])
self.resizable(False, False)
self.resizable(False, True) # allow vertical resize for high-DPI
self.grab_set()
if first_run:
@@ -58,7 +57,9 @@ class SettingsView(tk.Toplevel):
def _centre(self):
self.update_idletasks()
w, h = 480, 480
# Height increased to 560 to ensure button row is always visible.
# Vertical resize allowed for high-DPI / large-font environments.
w, h = 480, 560
x = (self.winfo_screenwidth() - w) // 2
y = (self.winfo_screenheight() - h) // 2
self.geometry(f"{w}x{h}+{x}+{y}")
@@ -77,6 +78,12 @@ class SettingsView(tk.Toplevel):
font=FONT_SMALL, bg=COLOURS["accent"],
fg=COLOURS["white"]).pack(pady=(2, 0))
# ── Buttons (packed before form so they anchor to bottom) ─────────────
# Packing the button row before the expanding form guarantees it is
# always visible even when the form content exceeds the window height.
btn_row = tk.Frame(self, bg=COLOURS["bg"], padx=36, pady=16)
btn_row.pack(side="bottom", fill="x")
# ── Form ──────────────────────────────────────────────────────────────
form = tk.Frame(self, bg=COLOURS["bg"], padx=36, pady=20)
form.pack(fill="both", expand=True)
@@ -116,7 +123,8 @@ class SettingsView(tk.Toplevel):
# ── Hint ──────────────────────────────────────────────────────────────
hint = (
"Settings are saved to config.ini in the application folder.\n"
"Credentials are saved to your OS keychain (Windows Credential Manager, "
"macOS Keychain, or Linux Secret Service) — no config.ini required.\n"
"Ensure the database user has CREATE, INSERT, UPDATE, DELETE privileges."
)
tk.Label(form, text=hint, bg=COLOURS["bg"],
@@ -124,10 +132,7 @@ class SettingsView(tk.Toplevel):
justify="left", wraplength=380).grid(
row=6, column=0, columnspan=2, sticky="w", pady=(8, 0))
# ── Buttons ───────────────────────────────────────────────────────────
btn_row = tk.Frame(self, bg=COLOURS["bg"], padx=36, pady=16)
btn_row.pack(fill="x")
# ── Buttons (btn_row already packed at top of _build_ui) ─────────────
self._save_btn = tk.Button(
btn_row, text="Save & Connect",
command=self._save,
@@ -263,9 +268,13 @@ class SettingsView(tk.Toplevel):
)
conn.close()
from config import save_config
from config import save_config, reload_db_config
save_config(host, port, database, user, password)
logger.info(f"Settings saved: {user}@{host}:{port}/{database}")
# Immediately update the in-memory DB_CONFIG and reset the
# connection pool so the app connects with the new credentials
# without requiring a restart.
reload_db_config()
logger.info(f"Settings saved and applied: {user}@{host}:{port}/{database}")
self.after(0, self._on_save_success)
except Exception as e:
@@ -284,4 +293,4 @@ class SettingsView(tk.Toplevel):
def _finish(self):
self.destroy()
self.on_save_callback()
self.on_save_callback()