diff --git a/config/description.exs b/config/description.exs index d18649ae8..4d80dd846 100644 --- a/config/description.exs +++ b/config/description.exs @@ -1061,6 +1061,18 @@ config :pleroma, :config_description, [ suggestions: [ "en" ] + }, + %{ + key: :multitenancy, + type: :map, + description: "Multitenancy support", + children: [ + %{ + key: :enabled, + type: :boolean, + description: "Enables allowing multiple Webfinger domains" + }, + ] } ] }, @@ -3466,5 +3478,5 @@ config :pleroma, :config_description, [ ] } ] - } + }, ] diff --git a/docs/configuration/how_to_serve_multiple_domains_for_webfinger.md b/docs/configuration/how_to_serve_multiple_domains_for_webfinger.md new file mode 100644 index 000000000..5a7a3733f --- /dev/null +++ b/docs/configuration/how_to_serve_multiple_domains_for_webfinger.md @@ -0,0 +1,30 @@ +# How to serve multiple domains for Pleroma user identifiers + +It is possible to use multiple domains for WebFinger identifiers. If configured, users can select from the available domains during registration. Domains can be set by instance administrator and can be marked as either public (everyone can choose it) or private (only available when admin creates a user) + +## Configuring + +### Configuring Pleroma + +To enable using multiple domains, append the following to your `prod.secret.exs` or `dev.secret.exs`: +```elixir +config :pleroma, :instance, :multitenancy, enabled: true +``` + +Creating, updating and deleting domains is available from the admin API. + +### Configuring WebFinger domains + +If you recall how webfinger queries work, the first step is to query `https://example.org/.well-known/host-meta`, which will contain an URL template. + +Therefore, the easiest way to configure the additional domains is to redirect `/.well-known/host-meta` to the domain used by Pleroma. + +With nginx, it would be as simple as adding: + +```nginx +location = /.well-known/host-meta { + return 301 https://pleroma.example.org$request_uri; +} +``` + +in the additional domain's server block. diff --git a/lib/pleroma/domain.ex b/lib/pleroma/domain.ex index d708188ee..cf7efc350 100644 --- a/lib/pleroma/domain.ex +++ b/lib/pleroma/domain.ex @@ -19,11 +19,13 @@ defmodule Pleroma.Domain do domain |> cast(params, [:domain, :public]) |> validate_required([:domain]) + |> update_change(:domain, &String.downcase/1) + |> unique_constraint(:domain) end def update_changeset(%__MODULE__{} = domain, params \\ %{}) do domain - |> cast(params, [:domain]) + |> cast(params, [:public]) end def get(id), do: Repo.get(__MODULE__, id) diff --git a/lib/pleroma/web/admin_api/controllers/domain_controller.ex b/lib/pleroma/web/admin_api/controllers/domain_controller.ex index 46b039460..cb2b7dd3f 100644 --- a/lib/pleroma/web/admin_api/controllers/domain_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/domain_controller.ex @@ -37,11 +37,13 @@ defmodule Pleroma.Web.AdminAPI.DomainController do end def create(%{body_params: params} = conn, _) do - domain = - params - |> Domain.create() - - render(conn, "show.json", domain: domain) + with {:domain_not_used, true} <- + {:domain_not_used, params[:domain] !== Pleroma.Web.WebFinger.domain()}, + {:domain, domain} <- Domain.create(params) do + render(conn, "show.json", domain: domain) + else + {:domain_not_used, false} -> {:error, :invalid_domain} + end end def update(%{body_params: params} = conn, %{id: id}) do diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index 4ab4ccb74..fa2b467ec 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -147,7 +147,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do end defp multitenancy do - enabled = Config.get([:multitenancy, :enabled]) + enabled = Config.get([:instance, :multitenancy, :enabled]) if enabled do domains = diff --git a/lib/pleroma/web/web_finger.ex b/lib/pleroma/web/web_finger.ex index 49c17e2c3..39e38d25c 100644 --- a/lib/pleroma/web/web_finger.ex +++ b/lib/pleroma/web/web_finger.ex @@ -102,7 +102,7 @@ defmodule Pleroma.Web.WebFinger do end end - defp domain do + def domain do Pleroma.Config.get([__MODULE__, :domain]) || Pleroma.Web.Endpoint.host() end diff --git a/priv/repo/migrations/20230618190919_create_domains.exs b/priv/repo/migrations/20230618190919_create_domains.exs index a306c80ee..c97e07326 100644 --- a/priv/repo/migrations/20230618190919_create_domains.exs +++ b/priv/repo/migrations/20230618190919_create_domains.exs @@ -3,7 +3,7 @@ defmodule Pleroma.Repo.Migrations.CreateDomains do def change do create_if_not_exists table(:domains) do - add(:domain, :string) + add(:domain, :citext) add(:public, :boolean) timestamps()