diff options
| -rw-r--r-- | config/config.exs | 2 | ||||
| -rw-r--r-- | lib/pleroma/registration.ex | 36 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 16 | ||||
| -rw-r--r-- | lib/pleroma/web/auth/authenticator.ex | 6 | ||||
| -rw-r--r-- | lib/pleroma/web/auth/ldap_authenticator.ex | 2 | ||||
| -rw-r--r-- | lib/pleroma/web/auth/pleroma_authenticator.ex | 51 | ||||
| -rw-r--r-- | lib/pleroma/web/oauth/oauth_controller.ex | 2 | ||||
| -rw-r--r-- | priv/repo/migrations/20190315101315_add_auth_provider_and_auth_provider_uid_to_users.exs | 12 | ||||
| -rw-r--r-- | priv/repo/migrations/20190315101315_create_registrations.exs | 16 | 
9 files changed, 93 insertions, 50 deletions
diff --git a/config/config.exs b/config/config.exs index 6839b489b..03baf894d 100644 --- a/config/config.exs +++ b/config/config.exs @@ -381,7 +381,7 @@ config :pleroma, :ldap,    base: System.get_env("LDAP_BASE") || "dc=example,dc=com",    uid: System.get_env("LDAP_UID") || "cn" -config :pleroma, :auth, oauth_consumer_enabled: false +config :pleroma, :auth, oauth_consumer_enabled: System.get_env("OAUTH_CONSUMER_ENABLED") == "true"  config :ueberauth,         Ueberauth, diff --git a/lib/pleroma/registration.ex b/lib/pleroma/registration.ex new file mode 100644 index 000000000..1bd91a316 --- /dev/null +++ b/lib/pleroma/registration.ex @@ -0,0 +1,36 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Registration do +  use Ecto.Schema + +  import Ecto.Changeset + +  alias Pleroma.Registration +  alias Pleroma.Repo +  alias Pleroma.User + +  schema "registrations" do +    belongs_to(:user, User, type: Pleroma.FlakeId) +    field(:provider, :string) +    field(:uid, :string) +    field(:info, :map, default: %{}) + +    timestamps() +  end + +  def changeset(registration, params \\ %{}) do +    registration +    |> cast(params, [:user_id, :provider, :uid, :info]) +    |> foreign_key_constraint(:user_id) +    |> unique_constraint(:uid, name: :registrations_provider_uid_index) +  end + +  def get_by_provider_uid(provider, uid) do +    Repo.get_by(Registration, +      provider: to_string(provider), +      uid: to_string(uid) +    ) +  end +end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 7f8b282e0..bd742b2fd 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -13,6 +13,7 @@ defmodule Pleroma.User do    alias Pleroma.Formatter    alias Pleroma.Notification    alias Pleroma.Object +  alias Pleroma.Registration    alias Pleroma.Repo    alias Pleroma.User    alias Pleroma.Web @@ -41,8 +42,6 @@ defmodule Pleroma.User do      field(:email, :string)      field(:name, :string)      field(:nickname, :string) -    field(:auth_provider, :string) -    field(:auth_provider_uid, :string)      field(:password_hash, :string)      field(:password, :string, virtual: true)      field(:password_confirmation, :string, virtual: true) @@ -56,6 +55,7 @@ defmodule Pleroma.User do      field(:bookmarks, {:array, :string}, default: [])      field(:last_refreshed_at, :naive_datetime)      has_many(:notifications, Notification) +    has_many(:registrations, Registration)      embeds_one(:info, Pleroma.User.Info)      timestamps() @@ -210,13 +210,12 @@ defmodule Pleroma.User do    end    # TODO: FIXME (WIP): -  def oauth_register_changeset(struct, params \\ %{}) do +  def external_registration_changeset(struct, params \\ %{}) do      info_change = User.Info.confirmation_changeset(%User.Info{}, :confirmed)      changeset =        struct -      |> cast(params, [:email, :nickname, :name, :bio, :auth_provider, :auth_provider_uid]) -      |> validate_required([:auth_provider, :auth_provider_uid]) +      |> cast(params, [:email, :nickname, :name, :bio])        |> unique_constraint(:email)        |> unique_constraint(:nickname)        |> validate_exclusion(:nickname, Pleroma.Config.get([Pleroma.User, :restricted_nicknames])) @@ -544,13 +543,6 @@ defmodule Pleroma.User do      get_by_nickname(nickname_or_email) || get_by_email(nickname_or_email)    end -  def get_by_auth_provider_uid(auth_provider, auth_provider_uid), -    do: -      Repo.get_by(User, -        auth_provider: to_string(auth_provider), -        auth_provider_uid: to_string(auth_provider_uid) -      ) -    def get_cached_user_info(user) do      key = "user_info:#{user.id}"      Cachex.fetch!(:user_cache, key, fn _ -> user_info(user) end) diff --git a/lib/pleroma/web/auth/authenticator.ex b/lib/pleroma/web/auth/authenticator.ex index fa439d562..11f45eec3 100644 --- a/lib/pleroma/web/auth/authenticator.ex +++ b/lib/pleroma/web/auth/authenticator.ex @@ -15,10 +15,10 @@ defmodule Pleroma.Web.Auth.Authenticator do    @callback get_user(Plug.Conn.t(), Map.t()) :: {:ok, User.t()} | {:error, any()}    def get_user(plug, params), do: implementation().get_user(plug, params) -  @callback get_or_create_user_by_oauth(Plug.Conn.t(), Map.t()) :: +  @callback get_by_external_registration(Plug.Conn.t(), Map.t()) ::                {:ok, User.t()} | {:error, any()} -  def get_or_create_user_by_oauth(plug, params), -    do: implementation().get_or_create_user_by_oauth(plug, params) +  def get_by_external_registration(plug, params), +    do: implementation().get_by_external_registration(plug, params)    @callback handle_error(Plug.Conn.t(), any()) :: any()    def handle_error(plug, error), do: implementation().handle_error(plug, error) diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex index 6c65cff27..51a0f0fa2 100644 --- a/lib/pleroma/web/auth/ldap_authenticator.ex +++ b/lib/pleroma/web/auth/ldap_authenticator.ex @@ -40,7 +40,7 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do      end    end -  def get_or_create_user_by_oauth(conn, params), do: get_user(conn, params) +  def get_by_external_registration(conn, params), do: get_user(conn, params)    def handle_error(%Plug.Conn{} = _conn, error) do      error diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex index 2e2bcfb70..2d4399490 100644 --- a/lib/pleroma/web/auth/pleroma_authenticator.ex +++ b/lib/pleroma/web/auth/pleroma_authenticator.ex @@ -5,6 +5,8 @@  defmodule Pleroma.Web.Auth.PleromaAuthenticator do    alias Comeonin.Pbkdf2    alias Pleroma.User +  alias Pleroma.Registration +  alias Pleroma.Repo    @behaviour Pleroma.Web.Auth.Authenticator @@ -27,20 +29,21 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do      end    end -  def get_or_create_user_by_oauth( +  def get_by_external_registration(          %Plug.Conn{assigns: %{ueberauth_auth: %{provider: provider, uid: uid} = auth}},          _params        ) do -    user = User.get_by_auth_provider_uid(provider, uid) +    registration = Registration.get_by_provider_uid(provider, uid) -    if user do +    if registration do +      user = Repo.preload(registration, :user).user        {:ok, user}      else        info = auth.info        email = info.email        nickname = info.nickname -      # TODO: FIXME: connect to existing (non-oauth) account (need a UI flow for that) / generate a random nickname? +      # Note: nullifying email in case this email is already taken        email =          if email && User.get_by_email(email) do            nil @@ -48,31 +51,39 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do            email          end +      # Note: generating a random numeric suffix to nickname in case this nickname is already taken        nickname =          if nickname && User.get_by_nickname(nickname) do -          nil +          "#{nickname}_#{:os.system_time()}"          else            nickname          end -      new_user = -        User.oauth_register_changeset( -          %User{}, -          %{ -            auth_provider: to_string(provider), -            auth_provider_uid: to_string(uid), -            name: info.name, -            bio: info.description, -            email: email, -            nickname: nickname -          } -        ) - -      Pleroma.Repo.insert(new_user) +      with {:ok, new_user} <- +             User.external_registration_changeset( +               %User{}, +               %{ +                 name: info.name, +                 bio: info.description, +                 email: email, +                 nickname: nickname +               } +             ) +             |> Repo.insert(), +           {:ok, _} <- +             Registration.changeset(%Registration{}, %{ +               user_id: new_user.id, +               provider: to_string(provider), +               uid: to_string(uid), +               info: %{nickname: info.nickname, email: info.email} +             }) +             |> Repo.insert() do +        {:ok, new_user} +      end      end    end -  def get_or_create_user_by_oauth(%Plug.Conn{} = _conn, _params), +  def get_by_external_registration(%Plug.Conn{} = _conn, _params),      do: {:error, :missing_credentials}    def handle_error(%Plug.Conn{} = _conn, error) do diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 588933d31..8c864cb1d 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -47,7 +47,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do          conn,          %{"client_id" => client_id, "redirect_uri" => redirect_uri} = params        ) do -    with {:ok, user} <- Authenticator.get_or_create_user_by_oauth(conn, params) do +    with {:ok, user} <- Authenticator.get_by_external_registration(conn, params) do        do_create_authorization(          conn,          %{ diff --git a/priv/repo/migrations/20190315101315_add_auth_provider_and_auth_provider_uid_to_users.exs b/priv/repo/migrations/20190315101315_add_auth_provider_and_auth_provider_uid_to_users.exs deleted file mode 100644 index 90947f85a..000000000 --- a/priv/repo/migrations/20190315101315_add_auth_provider_and_auth_provider_uid_to_users.exs +++ /dev/null @@ -1,12 +0,0 @@ -defmodule Pleroma.Repo.Migrations.AddAuthProviderAndAuthProviderUidToUsers do -  use Ecto.Migration - -  def change do -    alter table(:users) do -      add :auth_provider, :string -      add :auth_provider_uid, :string -    end - -    create unique_index(:users, [:auth_provider, :auth_provider_uid]) -  end -end diff --git a/priv/repo/migrations/20190315101315_create_registrations.exs b/priv/repo/migrations/20190315101315_create_registrations.exs new file mode 100644 index 000000000..dac86b780 --- /dev/null +++ b/priv/repo/migrations/20190315101315_create_registrations.exs @@ -0,0 +1,16 @@ +defmodule Pleroma.Repo.Migrations.CreateRegistrations do +  use Ecto.Migration + +  def change do +    create table(:registrations) do +      add :user_id, references(:users, type: :uuid, on_delete: :delete_all) +      add :provider, :string +      add :uid, :string +      add :info, :map, default: %{} + +      timestamps() +    end + +    create unique_index(:registrations, [:provider, :uid]) +  end +end  | 
