| defmodule Plausible.Site.SharedLink do |
| @moduledoc """ |
| Schema for shared links. |
| """ |
| use Ecto.Schema |
| import Ecto.Changeset |
|
|
| @type t() :: %__MODULE__{} |
|
|
| schema "shared_links" do |
| belongs_to :site, Plausible.Site |
| field :name, :string |
| field :slug, :string |
| field :password_hash, :string |
| field :password, :string, virtual: true |
| belongs_to :segment, Plausible.Segments.Segment |
|
|
| timestamps() |
| end |
|
|
| def changeset(link, attrs \\ %{}, opts \\ []) do |
| link |
| |> cast(attrs, [:password, :name]) |
| |> validate_required([:slug, :name]) |
| |> validate_special_name(opts) |
| |> unique_constraint(:slug) |
| |> unique_constraint(:name, name: :shared_links_site_id_name_index) |
| |> foreign_key_constraint(:segment_id) |
| |> hash_password() |
| end |
|
|
| defp validate_special_name(changeset, opts) do |
| name = get_change(changeset, :name) |
|
|
| if name not in Plausible.Sites.shared_link_special_names() || |
| Keyword.get(opts, :skip_special_name_check?, false) do |
| changeset |
| else |
| changeset |> add_error(:name, "This name is reserved. Please choose another one") |
| end |
| end |
|
|
| defp hash_password(link) do |
| case link.changes[:password] do |
| nil -> |
| link |
|
|
| password -> |
| hash = Plausible.Auth.Password.hash(password) |
| change(link, password_hash: hash) |
| end |
| end |
|
|
| def password_protected?(%__MODULE__{password_hash: hash}) when not is_nil(hash), do: true |
| def password_protected?(%__MODULE__{}), do: false |
|
|
| def limited_to_segment?(%__MODULE__{segment_id: segment_id}) when is_integer(segment_id), |
| do: true |
|
|
| def limited_to_segment?(%__MODULE__{}), do: false |
| end |
|
|