analytics/lib/plausible/site/domain.ex

63 lines
1.9 KiB
Elixir

defmodule Plausible.Site.Domain do
@expire_threshold_hours 72
@moduledoc """
Basic interface for domain changes.
Once `Plausible.DataMigration.NumericIDs` schema migration is ready,
domain change operation will be enabled, accessible to the users.
We will set a transition period of #{@expire_threshold_hours} hours
during which, both old and new domains, will be accepted as traffic
identifiers to the same site.
A periodic worker will call the `expire/0` function to end it where applicable.
See: `Plausible.Workers.ExpireDomainChangeTransitions`.
The underlying changeset for domain change (see: `Plausible.Site`) relies
on database trigger installed via `Plausible.Repo.Migrations.AllowDomainChange`
Postgres migration. The trigger checks if either `domain` or `domain_changed_from`
exist to ensure unicity.
"""
alias Plausible.Site
alias Plausible.Repo
import Ecto.Query
@spec expire_change_transitions(integer()) :: {:ok, non_neg_integer()}
def expire_change_transitions(expire_threshold_hours \\ @expire_threshold_hours) do
{updated, _} =
Repo.update_all(
from(s in Site.regular(),
where: s.domain_changed_at < ago(^expire_threshold_hours, "hour")
),
set: [
domain_changed_from: nil,
domain_changed_at: nil
]
)
{:ok, updated}
end
@spec change(Site.t(), String.t(), Keyword.t()) ::
{:ok, Site.t()} | {:error, Ecto.Changeset.t()}
def change(%Site{} = site, new_domain, opts \\ []) do
changeset = Site.update_changeset(site, %{domain: new_domain}, opts)
changeset =
if is_nil(changeset.errors[:domain]) and is_nil(changeset.changes[:domain]) do
Ecto.Changeset.add_error(
changeset,
:domain,
"New domain must be different than the current one"
)
else
changeset
end
Repo.update(changeset)
end
end