From 3b8d5faf3bd35020ee6d3f9fc485a17fc4739349 Mon Sep 17 00:00:00 2001 From: jamey Date: Sun, 8 Feb 2026 14:42:13 +0000 Subject: [PATCH] refactor: consolidate settings lookups and secrets loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Extract fetch_setting/1 in Settings (4 callsites → 1 repo lookup) - Replace hardcoded load_stripe_config with registry-driven load_all - Adding new secrets is now a one-line @secret_registry entry - Mark DRY refactor plan as complete (all 8 items done) Co-Authored-By: Claude Opus 4.6 --- PROGRESS.md | 4 ++-- docs/plans/dry-refactor.md | 2 +- lib/simpleshop_theme/secrets.ex | 31 +++++++++++++--------------- lib/simpleshop_theme/settings.ex | 29 +++++++++++++++++--------- lib/simpleshop_theme/stripe/setup.ex | 6 +++--- 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index 20b2deb..f726af3 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -202,9 +202,9 @@ See: [ROADMAP.md](ROADMAP.md) for design notes See: [docs/plans/products-context.md](docs/plans/products-context.md) for schema design ### DRY Refactor -**Status:** Planned +**Status:** Complete -Codebase analysis identified ~380 lines of duplication across LiveViews, templates, and the theme editor. Top priorities: extract `ThemeHook` for shared mount logic, extract `<.shop_layout>` wrapper component, consolidate preview assigns. Also: split `shop_components.ex` (4,400 lines) into focused modules. +All 8 items from the plan done. Key wins: ThemeHook eliminated mount duplication, shop_layout saved ~195 lines, shop_components split into 5 focused modules (largest file dropped from 4,487 to ~1,600 lines), Settings repo lookups consolidated via `fetch_setting/1`, secrets loading made scalable via registry pattern. See: [docs/plans/dry-refactor.md](docs/plans/dry-refactor.md) for full analysis and plan diff --git a/docs/plans/dry-refactor.md b/docs/plans/dry-refactor.md index 13097e0..4749fb9 100644 --- a/docs/plans/dry-refactor.md +++ b/docs/plans/dry-refactor.md @@ -1,6 +1,6 @@ # DRY refactor plan -Status: Planned +Status: Complete Codebase analysis identifying repeated patterns and consolidation opportunities. Ordered by impact. diff --git a/lib/simpleshop_theme/secrets.ex b/lib/simpleshop_theme/secrets.ex index a86602f..bf2f778 100644 --- a/lib/simpleshop_theme/secrets.ex +++ b/lib/simpleshop_theme/secrets.ex @@ -13,30 +13,27 @@ defmodule SimpleshopTheme.Secrets do require Logger + # Registry of {settings_key, app, env_key} — add new secrets here + @secret_registry [ + {"stripe_api_key", :stripity_stripe, :api_key}, + {"stripe_signing_secret", :stripity_stripe, :signing_secret} + ] + @doc """ Loads all secrets from the database into Application env. Called at startup from the supervision tree, after the Repo is ready. """ def load_all do - load_stripe_config() - end + for {settings_key, app, env_key} <- @secret_registry do + case Settings.get_secret(settings_key) do + nil -> + :skip - @doc """ - Loads Stripe credentials from encrypted settings into Application env. - """ - def load_stripe_config do - api_key = Settings.get_secret("stripe_api_key") - signing_secret = Settings.get_secret("stripe_signing_secret") - - if api_key do - Application.put_env(:stripity_stripe, :api_key, api_key) - Logger.debug("Stripe API key loaded from database") - end - - if signing_secret do - Application.put_env(:stripity_stripe, :signing_secret, signing_secret) - Logger.debug("Stripe webhook secret loaded from database") + value -> + Application.put_env(app, env_key, value) + Logger.debug("Loaded #{settings_key} from database") + end end :ok diff --git a/lib/simpleshop_theme/settings.ex b/lib/simpleshop_theme/settings.ex index b63f85f..de71847 100644 --- a/lib/simpleshop_theme/settings.ex +++ b/lib/simpleshop_theme/settings.ex @@ -18,9 +18,9 @@ defmodule SimpleshopTheme.Settings do """ def get_setting(key, default \\ nil) do - case Repo.get_by(Setting, key: key) do - nil -> default - setting -> decode_value(setting) + case fetch_setting(key) do + {:ok, setting} -> decode_value(setting) + :not_found -> default end end @@ -120,9 +120,9 @@ defmodule SimpleshopTheme.Settings do Deletes a setting by key. """ def delete_setting(key) do - case Repo.get_by(Setting, key: key) do - nil -> :ok - setting -> Repo.delete(setting) + case fetch_setting(key) do + {:ok, setting} -> Repo.delete(setting) + :not_found -> :ok end end @@ -157,8 +157,9 @@ defmodule SimpleshopTheme.Settings do Returns the plaintext value or the default if not found. """ def get_secret(key, default \\ nil) do - case Repo.get_by(Setting, key: key) do - %Setting{value_type: "encrypted", encrypted_value: encrypted} when not is_nil(encrypted) -> + case fetch_setting(key) do + {:ok, %Setting{value_type: "encrypted", encrypted_value: encrypted}} + when not is_nil(encrypted) -> case Vault.decrypt(encrypted) do {:ok, plaintext} -> plaintext {:error, _} -> default @@ -173,8 +174,9 @@ defmodule SimpleshopTheme.Settings do Checks whether an encrypted secret exists in the database. """ def has_secret?(key) do - case Repo.get_by(Setting, key: key) do - %Setting{value_type: "encrypted", encrypted_value: encrypted} when not is_nil(encrypted) -> + case fetch_setting(key) do + {:ok, %Setting{value_type: "encrypted", encrypted_value: encrypted}} + when not is_nil(encrypted) -> true _ -> @@ -204,6 +206,13 @@ defmodule SimpleshopTheme.Settings do # Private helpers + defp fetch_setting(key) do + case Repo.get_by(Setting, key: key) do + nil -> :not_found + setting -> {:ok, setting} + end + end + defp decode_value(%Setting{value_type: "encrypted", encrypted_value: encrypted}) when not is_nil(encrypted) do case Vault.decrypt(encrypted) do diff --git a/lib/simpleshop_theme/stripe/setup.ex b/lib/simpleshop_theme/stripe/setup.ex index 56c1c65..c92e15a 100644 --- a/lib/simpleshop_theme/stripe/setup.ex +++ b/lib/simpleshop_theme/stripe/setup.ex @@ -36,13 +36,13 @@ defmodule SimpleshopTheme.Stripe.Setup do case maybe_create_webhook(api_key) do {:ok, result} -> - Secrets.load_stripe_config() + Secrets.load_all() {:ok, result} {:error, reason} -> # Key is valid and stored, but webhook creation failed. # Still load the key so checkout works (webhooks can be set up manually). - Secrets.load_stripe_config() + Secrets.load_all() {:error, reason} end end @@ -68,7 +68,7 @@ defmodule SimpleshopTheme.Stripe.Setup do """ def save_signing_secret(signing_secret) do Settings.put_secret("stripe_signing_secret", signing_secret) - Secrets.load_stripe_config() + Secrets.load_all() end @doc """