diff --git a/priv/repo/migrations/20230328062644_allow_domain_change.exs b/priv/repo/migrations/20230328062644_allow_domain_change.exs new file mode 100644 index 000000000..6236fa380 --- /dev/null +++ b/priv/repo/migrations/20230328062644_allow_domain_change.exs @@ -0,0 +1,49 @@ +defmodule Plausible.Repo.Migrations.AllowDomainChange do + use Ecto.Migration + + def up do + alter table(:sites) do + add(:domain_changed_from, :string, null: true) + add(:domain_changed_at, :naive_datetime, null: true) + end + + create(unique_index(:sites, :domain_changed_from)) + create(index(:sites, :domain_changed_at)) + + execute(""" + CREATE OR REPLACE FUNCTION check_domain() RETURNS TRIGGER AS $$ + BEGIN + IF EXISTS ( + SELECT 1 FROM sites + WHERE (NEW.domain = domain_changed_from AND NEW.id != id) + OR (OLD IS NULL AND NEW.domain_changed_from = domain) + ) THEN + RAISE unique_violation USING CONSTRAINT = 'domain_change_disallowed'; + END IF; + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + """) + + execute(""" + CREATE TRIGGER check_domain_trigger + BEFORE INSERT OR UPDATE ON sites + FOR EACH ROW EXECUTE FUNCTION check_domain(); + """) + end + + def down do + execute(""" + DROP TRIGGER check_domain_trigger ON sites + """) + + execute(""" + DROP FUNCTION check_domain() + """) + + alter table(:sites) do + remove(:domain_changed_from) + remove(:domain_changed_at) + end + end +end