Vereinfacht accounting software API closes #431 #432
1 changed files with 60 additions and 20 deletions
|
|
@ -45,12 +45,21 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
|> assign(:active_editing_section, nil)
|
|> assign(:active_editing_section, nil)
|
||||||
|> assign(:locale, locale)
|
|> assign(:locale, locale)
|
||||||
|> assign(:vereinfacht_env_configured, Mv.Config.vereinfacht_env_configured?())
|
|> assign(:vereinfacht_env_configured, Mv.Config.vereinfacht_env_configured?())
|
||||||
|
|> assign(:vereinfacht_api_url_env_set, Mv.Config.vereinfacht_api_url_env_set?())
|
||||||
|
|> assign(:vereinfacht_api_key_env_set, Mv.Config.vereinfacht_api_key_env_set?())
|
||||||
|
|> assign(:vereinfacht_club_id_env_set, Mv.Config.vereinfacht_club_id_env_set?())
|
||||||
|
|> assign(:vereinfacht_api_key_set, present?(settings.vereinfacht_api_key))
|
||||||
|> assign(:last_vereinfacht_sync_result, nil)
|
|> assign(:last_vereinfacht_sync_result, nil)
|
||||||
|> assign_form()
|
|> assign_form()
|
||||||
|
|
||||||
{:ok, socket}
|
{:ok, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp present?(nil), do: false
|
||||||
|
defp present?(""), do: false
|
||||||
|
defp present?(s) when is_binary(s), do: String.trim(s) != ""
|
||||||
|
defp present?(_), do: false
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
|
|
@ -83,9 +92,7 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
<.form_section title={gettext("Vereinfacht Integration")}>
|
<.form_section title={gettext("Vereinfacht Integration")}>
|
||||||
<%= if @vereinfacht_env_configured do %>
|
<%= if @vereinfacht_env_configured do %>
|
||||||
<p class="text-sm text-base-content/70 mb-4">
|
<p class="text-sm text-base-content/70 mb-4">
|
||||||
{gettext(
|
{gettext("Some values are set via environment variables. Those fields are read-only.")}
|
||||||
"Configured via environment variables (VEREINFACHT_API_URL, VEREINFACHT_API_KEY, VEREINFACHT_CLUB_ID). Fields below are read-only."
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
<.form for={@form} id="vereinfacht-form" phx-change="validate" phx-submit="save">
|
<.form for={@form} id="vereinfacht-form" phx-change="validate" phx-submit="save">
|
||||||
|
|
@ -94,35 +101,53 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
field={@form[:vereinfacht_api_url]}
|
field={@form[:vereinfacht_api_url]}
|
||||||
type="text"
|
type="text"
|
||||||
label={gettext("API URL")}
|
label={gettext("API URL")}
|
||||||
disabled={@vereinfacht_env_configured}
|
disabled={@vereinfacht_api_url_env_set}
|
||||||
placeholder={
|
placeholder={
|
||||||
if(@vereinfacht_env_configured,
|
if(@vereinfacht_api_url_env_set,
|
||||||
do: gettext("From VEREINFACHT_API_URL"),
|
do: gettext("From VEREINFACHT_API_URL"),
|
||||||
else: "https://api.verein.visuel.dev/api/v1"
|
else: "https://api.verein.visuel.dev/api/v1"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<.input
|
<div class="form-control">
|
||||||
field={@form[:vereinfacht_api_key]}
|
<label class="label" for={@form[:vereinfacht_api_key].id}>
|
||||||
type="password"
|
<span class="label-text">{gettext("API Key")}</span>
|
||||||
label={gettext("API Key")}
|
<%= if @vereinfacht_api_key_set do %>
|
||||||
disabled={@vereinfacht_env_configured}
|
<span class="label-text-alt badge badge-ghost">{gettext("(set)")}</span>
|
||||||
placeholder={
|
<% end %>
|
||||||
if(@vereinfacht_env_configured, do: gettext("From VEREINFACHT_API_KEY"), else: nil)
|
</label>
|
||||||
}
|
<.input
|
||||||
/>
|
field={@form[:vereinfacht_api_key]}
|
||||||
|
type="password"
|
||||||
|
label=""
|
||||||
|
disabled={@vereinfacht_api_key_env_set}
|
||||||
|
placeholder={
|
||||||
|
if(@vereinfacht_api_key_env_set,
|
||||||
|
do: gettext("From VEREINFACHT_API_KEY"),
|
||||||
|
else:
|
||||||
|
if(@vereinfacht_api_key_set,
|
||||||
|
do: gettext("Leave blank to keep current"),
|
||||||
|
else: nil
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<.input
|
<.input
|
||||||
field={@form[:vereinfacht_club_id]}
|
field={@form[:vereinfacht_club_id]}
|
||||||
type="text"
|
type="text"
|
||||||
label={gettext("Club ID")}
|
label={gettext("Club ID")}
|
||||||
disabled={@vereinfacht_env_configured}
|
disabled={@vereinfacht_club_id_env_set}
|
||||||
placeholder={
|
placeholder={
|
||||||
if(@vereinfacht_env_configured, do: gettext("From VEREINFACHT_CLUB_ID"), else: "2")
|
if(@vereinfacht_club_id_env_set, do: gettext("From VEREINFACHT_CLUB_ID"), else: "2")
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<.button
|
<.button
|
||||||
:if={not @vereinfacht_env_configured}
|
:if={
|
||||||
|
not (@vereinfacht_api_url_env_set and @vereinfacht_api_key_env_set and
|
||||||
|
@vereinfacht_club_id_env_set)
|
||||||
|
}
|
||||||
phx-disable-with={gettext("Saving...")}
|
phx-disable-with={gettext("Saving...")}
|
||||||
variant="primary"
|
variant="primary"
|
||||||
class="mt-2"
|
class="mt-2"
|
||||||
|
|
@ -206,15 +231,17 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
@impl true
|
@impl true
|
||||||
def handle_event("save", %{"setting" => setting_params}, socket) do
|
def handle_event("save", %{"setting" => setting_params}, socket) do
|
||||||
actor = MvWeb.LiveHelpers.current_actor(socket)
|
actor = MvWeb.LiveHelpers.current_actor(socket)
|
||||||
|
# Never send blank API key so we do not overwrite the stored secret (security)
|
||||||
|
setting_params_clean = drop_blank_vereinfacht_api_key(setting_params)
|
||||||
|
|
||||||
case MvWeb.LiveHelpers.submit_form(socket.assigns.form, setting_params, actor) do
|
case MvWeb.LiveHelpers.submit_form(socket.assigns.form, setting_params_clean, actor) do
|
||||||
{:ok, _updated_settings} ->
|
{:ok, _updated_settings} ->
|
||||||
# Reload settings from database to ensure all dependent data is updated
|
|
||||||
{:ok, fresh_settings} = Membership.get_settings()
|
{:ok, fresh_settings} = Membership.get_settings()
|
||||||
|
|
||||||
socket =
|
socket =
|
||||||
socket
|
socket
|
||||||
|> assign(:settings, fresh_settings)
|
|> assign(:settings, fresh_settings)
|
||||||
|
|> assign(:vereinfacht_api_key_set, present?(fresh_settings.vereinfacht_api_key))
|
||||||
|> put_flash(:info, gettext("Settings updated successfully"))
|
|> put_flash(:info, gettext("Settings updated successfully"))
|
||||||
|> assign_form()
|
|> assign_form()
|
||||||
|
|
||||||
|
|
@ -225,6 +252,16 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp drop_blank_vereinfacht_api_key(params) when is_map(params) do
|
||||||
|
case params do
|
||||||
|
%{"vereinfacht_api_key" => v} when v in [nil, ""] ->
|
||||||
|
Map.delete(params, "vereinfacht_api_key")
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
params
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_info({:custom_field_saved, _custom_field, action}, socket) do
|
def handle_info({:custom_field_saved, _custom_field, action}, socket) do
|
||||||
send_update(MvWeb.CustomFieldLive.IndexComponent,
|
send_update(MvWeb.CustomFieldLive.IndexComponent,
|
||||||
|
|
@ -305,9 +342,12 @@ defmodule MvWeb.GlobalSettingsLive do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp assign_form(%{assigns: %{settings: settings}} = socket) do
|
defp assign_form(%{assigns: %{settings: settings}} = socket) do
|
||||||
|
# Never put API key into form/DOM to avoid secret leak in source or DevTools
|
||||||
|
settings_for_form = %{settings | vereinfacht_api_key: nil}
|
||||||
|
|
||||||
form =
|
form =
|
||||||
AshPhoenix.Form.for_update(
|
AshPhoenix.Form.for_update(
|
||||||
settings,
|
settings_for_form,
|
||||||
:update,
|
:update,
|
||||||
api: Membership,
|
api: Membership,
|
||||||
as: "setting",
|
as: "setting",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue