92 lines
2.5 KiB
Elixir
92 lines
2.5 KiB
Elixir
defmodule Towerops.Settings.ApplicationSetting do
|
|
@moduledoc """
|
|
Application-wide settings schema.
|
|
|
|
Stores global configuration values that affect the entire application,
|
|
regardless of organization. Only accessible by superadmins.
|
|
"""
|
|
use Ecto.Schema
|
|
|
|
import Ecto.Changeset
|
|
|
|
require Logger
|
|
|
|
@primary_key {:id, :binary_id, autogenerate: true}
|
|
@foreign_key_type :binary_id
|
|
schema "application_settings" do
|
|
field :key, :string
|
|
field :value, :string
|
|
field :value_type, :string, default: "string"
|
|
field :description, :string
|
|
|
|
timestamps(type: :utc_datetime)
|
|
end
|
|
|
|
@type t :: %__MODULE__{
|
|
id: Ecto.UUID.t(),
|
|
key: String.t(),
|
|
value: String.t() | nil,
|
|
value_type: String.t(),
|
|
description: String.t() | nil,
|
|
inserted_at: DateTime.t(),
|
|
updated_at: DateTime.t()
|
|
}
|
|
|
|
@doc false
|
|
def changeset(setting, attrs) do
|
|
setting
|
|
|> cast(attrs, [:key, :value, :value_type, :description])
|
|
|> validate_required([:key, :value_type])
|
|
|> validate_inclusion(:value_type, ["string", "integer", "uuid", "boolean", "json", "decimal"])
|
|
|> unique_constraint(:key)
|
|
end
|
|
|
|
@doc """
|
|
Parses the value field according to value_type.
|
|
|
|
## Examples
|
|
|
|
iex> parse_value(%ApplicationSetting{value: "abc-123", value_type: "uuid"})
|
|
"abc-123"
|
|
|
|
iex> parse_value(%ApplicationSetting{value: nil, value_type: "uuid"})
|
|
nil
|
|
"""
|
|
def parse_value(%__MODULE__{value: nil}), do: nil
|
|
|
|
def parse_value(%__MODULE__{value: value, value_type: "string"}), do: value
|
|
def parse_value(%__MODULE__{value: value, value_type: "uuid"}), do: value
|
|
|
|
def parse_value(%__MODULE__{value: value, value_type: "integer"}) do
|
|
case Integer.parse(value) do
|
|
{int, _} -> int
|
|
:error -> nil
|
|
end
|
|
end
|
|
|
|
def parse_value(%__MODULE__{value: value, value_type: "boolean"}) do
|
|
value in ["true", "1", "yes"]
|
|
end
|
|
|
|
def parse_value(%__MODULE__{key: key, value: value, value_type: "json"}) do
|
|
case Jason.decode(value) do
|
|
{:ok, decoded} ->
|
|
decoded
|
|
|
|
{:error, reason} ->
|
|
Logger.warning("Failed to parse JSON value for setting '#{key}': #{inspect(reason)}")
|
|
nil
|
|
end
|
|
end
|
|
|
|
def parse_value(%__MODULE__{key: key, value: value, value_type: "decimal"}) do
|
|
case Decimal.parse(value) do
|
|
{decimal, _remainder} ->
|
|
decimal
|
|
|
|
:error ->
|
|
Logger.warning("Failed to parse decimal value for setting '#{key}': #{inspect(value)}")
|
|
nil
|
|
end
|
|
end
|
|
end
|