diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/registration.ex | 57 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 18 | ||||
| -rw-r--r-- | lib/pleroma/web/auth/authenticator.ex | 21 | ||||
| -rw-r--r-- | lib/pleroma/web/auth/ldap_authenticator.ex | 15 | ||||
| -rw-r--r-- | lib/pleroma/web/auth/pleroma_authenticator.ex | 66 | ||||
| -rw-r--r-- | lib/pleroma/web/endpoint.ex | 18 | ||||
| -rw-r--r-- | lib/pleroma/web/oauth/oauth_controller.ex | 223 | ||||
| -rw-r--r-- | lib/pleroma/web/router.ex | 15 | ||||
| -rw-r--r-- | lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex | 13 | ||||
| -rw-r--r-- | lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex | 15 | ||||
| -rw-r--r-- | lib/pleroma/web/templates/o_auth/o_auth/register.html.eex | 49 | ||||
| -rw-r--r-- | lib/pleroma/web/templates/o_auth/o_auth/show.html.eex | 22 | 
12 files changed, 485 insertions, 47 deletions
| diff --git a/lib/pleroma/registration.ex b/lib/pleroma/registration.ex new file mode 100644 index 000000000..21fd1fc3f --- /dev/null +++ b/lib/pleroma/registration.ex @@ -0,0 +1,57 @@ +# 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 + +  @primary_key {:id, Pleroma.FlakeId, autogenerate: true} + +  schema "registrations" do +    belongs_to(:user, User, type: Pleroma.FlakeId) +    field(:provider, :string) +    field(:uid, :string) +    field(:info, :map, default: %{}) + +    timestamps() +  end + +  def nickname(registration, default \\ nil), +    do: Map.get(registration.info, "nickname", default) + +  def email(registration, default \\ nil), +    do: Map.get(registration.info, "email", default) + +  def name(registration, default \\ nil), +    do: Map.get(registration.info, "name", default) + +  def description(registration, default \\ nil), +    do: Map.get(registration.info, "description", default) + +  def changeset(registration, params \\ %{}) do +    registration +    |> cast(params, [:user_id, :provider, :uid, :info]) +    |> validate_required([:provider, :uid]) +    |> foreign_key_constraint(:user_id) +    |> unique_constraint(:uid, name: :registrations_provider_uid_index) +  end + +  def bind_to_user(registration, user) do +    registration +    |> changeset(%{user_id: (user && user.id) || nil}) +    |> Repo.update() +  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 5012aef77..05f56c01e 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 @@ -55,6 +56,7 @@ defmodule Pleroma.User do      field(:bookmarks, {:array, :string}, default: [])      field(:last_refreshed_at, :naive_datetime_usec)      has_many(:notifications, Notification) +    has_many(:registrations, Registration)      embeds_one(:info, Pleroma.User.Info)      timestamps() @@ -216,7 +218,7 @@ defmodule Pleroma.User do      changeset =        struct        |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation]) -      |> validate_required([:email, :name, :nickname, :password, :password_confirmation]) +      |> validate_required([:name, :nickname, :password, :password_confirmation])        |> validate_confirmation(:password)        |> unique_constraint(:email)        |> unique_constraint(:nickname) @@ -227,6 +229,13 @@ defmodule Pleroma.User do        |> validate_length(:name, min: 1, max: 100)        |> put_change(:info, info_change) +    changeset = +      if opts[:external] do +        changeset +      else +        validate_required(changeset, [:email]) +      end +      if changeset.valid? do        hashed = Pbkdf2.hashpwsalt(changeset.changes[:password])        ap_id = User.ap_id(%User{nickname: changeset.changes[:nickname]}) @@ -505,11 +514,10 @@ defmodule Pleroma.User do        end    end +  def get_by_email(email), do: Repo.get_by(User, email: email) +    def get_by_nickname_or_email(nickname_or_email) do -    case user = Repo.get_by(User, nickname: nickname_or_email) do -      %User{} -> user -      nil -> Repo.get_by(User, email: nickname_or_email) -    end +    get_by_nickname(nickname_or_email) || get_by_email(nickname_or_email)    end    def get_cached_user_info(user) do diff --git a/lib/pleroma/web/auth/authenticator.ex b/lib/pleroma/web/auth/authenticator.ex index 82267c595..4eeef5034 100644 --- a/lib/pleroma/web/auth/authenticator.ex +++ b/lib/pleroma/web/auth/authenticator.ex @@ -3,6 +3,7 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.Auth.Authenticator do +  alias Pleroma.Registration    alias Pleroma.User    def implementation do @@ -12,8 +13,18 @@ defmodule Pleroma.Web.Auth.Authenticator do      )    end -  @callback get_user(Plug.Conn.t()) :: {:ok, User.t()} | {:error, any()} -  def get_user(plug), do: implementation().get_user(plug) +  @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 create_from_registration(Plug.Conn.t(), Map.t(), Registration.t()) :: +              {:ok, User.t()} | {:error, any()} +  def create_from_registration(plug, params, registration), +    do: implementation().create_from_registration(plug, params, registration) + +  @callback get_registration(Plug.Conn.t(), Map.t()) :: +              {:ok, Registration.t()} | {:error, any()} +  def get_registration(plug, params), +    do: implementation().get_registration(plug, params)    @callback handle_error(Plug.Conn.t(), any()) :: any()    def handle_error(plug, error), do: implementation().handle_error(plug, error) @@ -22,4 +33,10 @@ defmodule Pleroma.Web.Auth.Authenticator do    def auth_template do      implementation().auth_template() || Pleroma.Config.get(:auth_template, "show.html")    end + +  @callback oauth_consumer_template() :: String.t() | nil +  def oauth_consumer_template do +    implementation().oauth_consumer_template() || +      Pleroma.Config.get(:oauth_consumer_template, "consumer.html") +  end  end diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex index 88217aab8..8b6d5a77f 100644 --- a/lib/pleroma/web/auth/ldap_authenticator.ex +++ b/lib/pleroma/web/auth/ldap_authenticator.ex @@ -8,14 +8,19 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do    require Logger    @behaviour Pleroma.Web.Auth.Authenticator +  @base Pleroma.Web.Auth.PleromaAuthenticator    @connection_timeout 10_000    @search_timeout 10_000 -  def get_user(%Plug.Conn{} = conn) do +  defdelegate get_registration(conn, params), to: @base + +  defdelegate create_from_registration(conn, params, registration), to: @base + +  def get_user(%Plug.Conn{} = conn, params) do      if Pleroma.Config.get([:ldap, :enabled]) do        {name, password} = -        case conn.params do +        case params do            %{"authorization" => %{"name" => name, "password" => password}} ->              {name, password} @@ -29,14 +34,14 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do          {:error, {:ldap_connection_error, _}} ->            # When LDAP is unavailable, try default authenticator -          Pleroma.Web.Auth.PleromaAuthenticator.get_user(conn) +          @base.get_user(conn, params)          error ->            error        end      else        # Fall back to default authenticator -      Pleroma.Web.Auth.PleromaAuthenticator.get_user(conn) +      @base.get_user(conn, params)      end    end @@ -46,6 +51,8 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do    def auth_template, do: nil +  def oauth_consumer_template, do: nil +    defp ldap_user(name, password) do      ldap = Pleroma.Config.get(:ldap, [])      host = Keyword.get(ldap, :host, "localhost") diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex index 94a19ad49..c826adb4c 100644 --- a/lib/pleroma/web/auth/pleroma_authenticator.ex +++ b/lib/pleroma/web/auth/pleroma_authenticator.ex @@ -4,13 +4,15 @@  defmodule Pleroma.Web.Auth.PleromaAuthenticator do    alias Comeonin.Pbkdf2 +  alias Pleroma.Registration +  alias Pleroma.Repo    alias Pleroma.User    @behaviour Pleroma.Web.Auth.Authenticator -  def get_user(%Plug.Conn{} = conn) do +  def get_user(%Plug.Conn{} = _conn, params) do      {name, password} = -      case conn.params do +      case params do          %{"authorization" => %{"name" => name, "password" => password}} ->            {name, password} @@ -27,9 +29,69 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do      end    end +  def get_registration( +        %Plug.Conn{assigns: %{ueberauth_auth: %{provider: provider, uid: uid} = auth}}, +        _params +      ) do +    registration = Registration.get_by_provider_uid(provider, uid) + +    if registration do +      {:ok, registration} +    else +      info = auth.info + +      Registration.changeset(%Registration{}, %{ +        provider: to_string(provider), +        uid: to_string(uid), +        info: %{ +          "nickname" => info.nickname, +          "email" => info.email, +          "name" => info.name, +          "description" => info.description +        } +      }) +      |> Repo.insert() +    end +  end + +  def get_registration(%Plug.Conn{} = _conn, _params), do: {:error, :missing_credentials} + +  def create_from_registration(_conn, params, registration) do +    nickname = value([params["nickname"], Registration.nickname(registration)]) +    email = value([params["email"], Registration.email(registration)]) +    name = value([params["name"], Registration.name(registration)]) || nickname +    bio = value([params["bio"], Registration.description(registration)]) + +    random_password = :crypto.strong_rand_bytes(64) |> Base.encode64() + +    with {:ok, new_user} <- +           User.register_changeset( +             %User{}, +             %{ +               email: email, +               nickname: nickname, +               name: name, +               bio: bio, +               password: random_password, +               password_confirmation: random_password +             }, +             external: true, +             confirmed: true +           ) +           |> Repo.insert(), +         {:ok, _} <- +           Registration.changeset(registration, %{user_id: new_user.id}) |> Repo.update() do +      {:ok, new_user} +    end +  end + +  defp value(list), do: Enum.find(list, &(to_string(&1) != "")) +    def handle_error(%Plug.Conn{} = _conn, error) do      error    end    def auth_template, do: nil + +  def oauth_consumer_template, do: nil  end diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index fa2d1cbe7..b85b95bf9 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -51,11 +51,22 @@ defmodule Pleroma.Web.Endpoint do    plug(Plug.MethodOverride)    plug(Plug.Head) +  secure_cookies = Pleroma.Config.get([__MODULE__, :secure_cookie_flag]) +    cookie_name = -    if Application.get_env(:pleroma, Pleroma.Web.Endpoint) |> Keyword.get(:secure_cookie_flag), +    if secure_cookies,        do: "__Host-pleroma_key",        else: "pleroma_key" +  same_site = +    if Pleroma.Config.get([:auth, :oauth_consumer_enabled]) do +      # Note: "SameSite=Strict" prevents sign in with external OAuth provider +      #   (there would be no cookies during callback request from OAuth provider) +      "SameSite=Lax" +    else +      "SameSite=Strict" +    end +    # The session will be stored in the cookie and signed,    # this means its contents can be read but not tampered with.    # Set :encryption_salt if you would also like to encrypt it. @@ -65,9 +76,8 @@ defmodule Pleroma.Web.Endpoint do      key: cookie_name,      signing_salt: {Pleroma.Config, :get, [[__MODULE__, :signing_salt], "CqaoopA2"]},      http_only: true, -    secure: -      Application.get_env(:pleroma, Pleroma.Web.Endpoint) |> Keyword.get(:secure_cookie_flag), -    extra: "SameSite=Strict" +    secure: secure_cookies, +    extra: same_site    )    plug(Pleroma.Web.Router) diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 26d53df1a..2dcaaabc1 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -5,6 +5,7 @@  defmodule Pleroma.Web.OAuth.OAuthController do    use Pleroma.Web, :controller +  alias Pleroma.Registration    alias Pleroma.Repo    alias Pleroma.User    alias Pleroma.Web.Auth.Authenticator @@ -15,6 +16,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do    import Pleroma.Web.ControllerHelper, only: [oauth_scopes: 2] +  if Pleroma.Config.get([:auth, :oauth_consumer_enabled]), do: plug(Ueberauth) +    plug(:fetch_session)    plug(:fetch_flash) @@ -57,22 +60,16 @@ defmodule Pleroma.Web.OAuth.OAuthController do      })    end -  def create_authorization(conn, %{ -        "authorization" => -          %{ -            "client_id" => client_id, -            "redirect_uri" => redirect_uri -          } = auth_params -      }) do -    with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)}, -         %App{} = app <- Repo.get_by(App, client_id: client_id), -         true <- redirect_uri in String.split(app.redirect_uris), -         scopes <- oauth_scopes(auth_params, []), -         {:unsupported_scopes, []} <- {:unsupported_scopes, scopes -- app.scopes}, -         # Note: `scope` param is intentionally not optional in this context -         {:missing_scopes, false} <- {:missing_scopes, scopes == []}, -         {:auth_active, true} <- {:auth_active, User.auth_active?(user)}, -         {:ok, auth} <- Authorization.create_authorization(app, user, scopes) do +  def create_authorization( +        conn, +        %{ +          "authorization" => %{"redirect_uri" => redirect_uri} = auth_params +        } = params, +        opts \\ [] +      ) do +    with {:ok, auth} <- +           (opts[:auth] && {:ok, opts[:auth]}) || +             do_create_authorization(conn, params, opts[:user]) do        redirect_uri = redirect_uri(conn, redirect_uri)        cond do @@ -149,7 +146,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do          conn,          %{"grant_type" => "password"} = params        ) do -    with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)}, +    with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn, params)},           %App{} = app <- get_app_from_request(conn, params),           {:auth_active, true} <- {:auth_active, User.auth_active?(user)},           scopes <- oauth_scopes(params, app.scopes), @@ -205,6 +202,193 @@ defmodule Pleroma.Web.OAuth.OAuthController do      end    end +  def prepare_request(conn, %{"provider" => provider} = params) do +    scope = +      oauth_scopes(params, []) +      |> Enum.join(" ") + +    state = +      params +      |> Map.delete("scopes") +      |> Map.put("scope", scope) +      |> Poison.encode!() + +    params = +      params +      |> Map.drop(~w(scope scopes client_id redirect_uri)) +      |> Map.put("state", state) + +    redirect(conn, to: o_auth_path(conn, :request, provider, params)) +  end + +  def request(conn, params) do +    message = +      if params["provider"] do +        "Unsupported OAuth provider: #{params["provider"]}." +      else +        "Bad OAuth request." +      end + +    conn +    |> put_flash(:error, message) +    |> redirect(to: "/") +  end + +  def callback(%{assigns: %{ueberauth_failure: failure}} = conn, params) do +    params = callback_params(params) +    messages = for e <- Map.get(failure, :errors, []), do: e.message +    message = Enum.join(messages, "; ") + +    conn +    |> put_flash(:error, "Failed to authenticate: #{message}.") +    |> redirect(external: redirect_uri(conn, params["redirect_uri"])) +  end + +  def callback(conn, params) do +    params = callback_params(params) + +    with {:ok, registration} <- Authenticator.get_registration(conn, params) do +      user = Repo.preload(registration, :user).user + +      auth_params = %{ +        "client_id" => params["client_id"], +        "redirect_uri" => params["redirect_uri"], +        "state" => params["state"], +        "scopes" => oauth_scopes(params, nil) +      } + +      if user do +        create_authorization( +          conn, +          %{"authorization" => auth_params}, +          user: user +        ) +      else +        registration_params = +          Map.merge(auth_params, %{ +            "nickname" => Registration.nickname(registration), +            "email" => Registration.email(registration) +          }) + +        conn +        |> put_session(:registration_id, registration.id) +        |> redirect(to: o_auth_path(conn, :registration_details, registration_params)) +      end +    else +      _ -> +        conn +        |> put_flash(:error, "Failed to set up user account.") +        |> redirect(external: redirect_uri(conn, params["redirect_uri"])) +    end +  end + +  defp callback_params(%{"state" => state} = params) do +    Map.merge(params, Poison.decode!(state)) +  end + +  def registration_details(conn, params) do +    render(conn, "register.html", %{ +      client_id: params["client_id"], +      redirect_uri: params["redirect_uri"], +      state: params["state"], +      scopes: oauth_scopes(params, []), +      nickname: params["nickname"], +      email: params["email"] +    }) +  end + +  def register(conn, %{"op" => "connect"} = params) do +    create_authorization_params = %{ +      "authorization" => Map.merge(params, %{"name" => params["auth_name"]}) +    } + +    with registration_id when not is_nil(registration_id) <- get_session_registration_id(conn), +         %Registration{} = registration <- Repo.get(Registration, registration_id), +         {:ok, auth} <- do_create_authorization(conn, create_authorization_params), +         %User{} = user <- Repo.preload(auth, :user).user, +         {:ok, _updated_registration} <- Registration.bind_to_user(registration, user) do +      conn +      |> put_session_registration_id(nil) +      |> create_authorization( +        create_authorization_params, +        auth: auth +      ) +    else +      _ -> +        params = Map.delete(params, "password") + +        conn +        |> put_flash(:error, "Unknown error, please try again.") +        |> redirect(to: o_auth_path(conn, :registration_details, params)) +    end +  end + +  def register(conn, params) do +    with registration_id when not is_nil(registration_id) <- get_session_registration_id(conn), +         %Registration{} = registration <- Repo.get(Registration, registration_id), +         {:ok, user} <- Authenticator.create_from_registration(conn, params, registration) do +      conn +      |> put_session_registration_id(nil) +      |> create_authorization( +        %{ +          "authorization" => %{ +            "client_id" => params["client_id"], +            "redirect_uri" => params["redirect_uri"], +            "scopes" => oauth_scopes(params, nil) +          } +        }, +        user: user +      ) +    else +      {:error, changeset} -> +        message = +          Enum.map(changeset.errors, fn {field, {error, _}} -> +            "#{field} #{error}" +          end) +          |> Enum.join("; ") + +        message = +          String.replace( +            message, +            "ap_id has already been taken", +            "nickname has already been taken" +          ) + +        conn +        |> put_flash(:error, "Error: #{message}.") +        |> redirect(to: o_auth_path(conn, :registration_details, params)) + +      _ -> +        conn +        |> put_flash(:error, "Unknown error, please try again.") +        |> redirect(to: o_auth_path(conn, :registration_details, params)) +    end +  end + +  defp do_create_authorization( +         conn, +         %{ +           "authorization" => +             %{ +               "client_id" => client_id, +               "redirect_uri" => redirect_uri +             } = auth_params +         } = params, +         user \\ nil +       ) do +    with {_, {:ok, %User{} = user}} <- +           {:get_user, (user && {:ok, user}) || Authenticator.get_user(conn, params)}, +         %App{} = app <- Repo.get_by(App, client_id: client_id), +         true <- redirect_uri in String.split(app.redirect_uris), +         scopes <- oauth_scopes(auth_params, []), +         {:unsupported_scopes, []} <- {:unsupported_scopes, scopes -- app.scopes}, +         # Note: `scope` param is intentionally not optional in this context +         {:missing_scopes, false} <- {:missing_scopes, scopes == []}, +         {:auth_active, true} <- {:auth_active, User.auth_active?(user)} do +      Authorization.create_authorization(app, user, scopes) +    end +  end +    # XXX - for whatever reason our token arrives urlencoded, but Plug.Conn should be    # decoding it.  Investigate sometime.    defp fix_padding(token) do @@ -242,4 +426,9 @@ defmodule Pleroma.Web.OAuth.OAuthController do    defp redirect_uri(conn, "."), do: mastodon_api_url(conn, :login)    defp redirect_uri(_conn, redirect_uri), do: redirect_uri + +  defp get_session_registration_id(conn), do: get_session(conn, :registration_id) + +  defp put_session_registration_id(conn, registration_id), +    do: put_session(conn, :registration_id, registration_id)  end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 605a327fc..5101e1b18 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -5,6 +5,11 @@  defmodule Pleroma.Web.Router do    use Pleroma.Web, :router +  pipeline :browser do +    plug(:accepts, ["html"]) +    plug(:fetch_session) +  end +    pipeline :oauth do      plug(:fetch_session)      plug(Pleroma.Plugs.OAuthPlug) @@ -209,6 +214,16 @@ defmodule Pleroma.Web.Router do      post("/authorize", OAuthController, :create_authorization)      post("/token", OAuthController, :token_exchange)      post("/revoke", OAuthController, :token_revoke) +    get("/registration_details", OAuthController, :registration_details) + +    scope [] do +      pipe_through(:browser) + +      get("/prepare_request", OAuthController, :prepare_request) +      get("/:provider", OAuthController, :request) +      get("/:provider/callback", OAuthController, :callback) +      post("/register", OAuthController, :register) +    end    end    scope "/api/v1", Pleroma.Web.MastodonAPI do diff --git a/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex new file mode 100644 index 000000000..4b8fb5dae --- /dev/null +++ b/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex @@ -0,0 +1,13 @@ +<div class="scopes-input"> +  <%= label @form, :scope, "Permissions" %> + +  <div class="scopes"> +    <%= for scope <- @available_scopes do %> +      <%# Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %> +      <div class="scope"> +        <%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: assigns[:scope_param] || "scope[]" %> +        <%= label @form, :"scope_#{scope}", String.capitalize(scope) %> +      </div> +    <% end %> +  </div> +</div> diff --git a/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex new file mode 100644 index 000000000..002f014e6 --- /dev/null +++ b/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex @@ -0,0 +1,15 @@ +<br> +<br> +<h2>Sign in with external provider</h2> + +<%= form_for @conn, o_auth_path(@conn, :prepare_request), [method: "get"], fn f -> %> +  <%= render @view_module, "_scopes.html", Map.put(assigns, :form, f) %> + +  <%= hidden_input f, :client_id, value: @client_id %> +  <%= hidden_input f, :redirect_uri, value: @redirect_uri %> +  <%= hidden_input f, :state, value: @state %> + +    <%= for strategy <- Pleroma.Config.get([:auth, :oauth_consumer_strategies], []) do %> +      <%= submit "Sign in with #{String.capitalize(strategy)}", name: "provider", value: strategy %> +    <% end %> +<% end %> diff --git a/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex new file mode 100644 index 000000000..2e806e5fb --- /dev/null +++ b/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex @@ -0,0 +1,49 @@ +<%= if get_flash(@conn, :info) do %> +  <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p> +<% end %> +<%= if get_flash(@conn, :error) do %> +  <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p> +<% end %> + +<h2>Registration Details</h2> + +<p>If you'd like to register a new account, +<br> +please provide the details below.</p> +<br> + +<%= form_for @conn, o_auth_path(@conn, :register), [], fn f -> %> + +<div class="input"> +  <%= label f, :nickname, "Nickname" %> +  <%= text_input f, :nickname, value: @nickname %> +</div> +<div class="input"> +  <%= label f, :email, "Email" %> +  <%= text_input f, :email, value: @email %> +</div> + +<%= submit "Proceed as new user", name: "op", value: "register" %> + +<br> +<br> +<br> +<p>Alternatively, sign in to connect to existing account.</p> + +<div class="input"> +  <%= label f, :auth_name, "Name or email" %> +  <%= text_input f, :auth_name %> +</div> +<div class="input"> +  <%= label f, :password, "Password" %> +  <%= password_input f, :password %> +</div> + +<%= submit "Proceed as existing user", name: "op", value: "connect" %> + +<%= hidden_input f, :client_id, value: @client_id %> +<%= hidden_input f, :redirect_uri, value: @redirect_uri %> +<%= hidden_input f, :scope, value: Enum.join(@scopes, " ") %> +<%= hidden_input f, :state, value: @state %> + +<% end %> diff --git a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex index 161333847..0144675ab 100644 --- a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex +++ b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex @@ -4,7 +4,9 @@  <%= if get_flash(@conn, :error) do %>  <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>  <% end %> +  <h2>OAuth Authorization</h2> +  <%= form_for @conn, o_auth_path(@conn, :authorize), [as: "authorization"], fn f -> %>  <div class="input">    <%= label f, :name, "Name or email" %> @@ -14,22 +16,16 @@    <%= label f, :password, "Password" %>    <%= password_input f, :password %>  </div> -<div class="scopes-input"> -<%= label f, :scope, "Permissions" %> -  <div class="scopes"> -    <%= for scope <- @available_scopes do %> -      <%# Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %> -      <div class="scope"> -        <%= checkbox f, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: "authorization[scope][]" %> -        <%= label f, :"scope_#{scope}", String.capitalize(scope) %> -      </div> -    <% end %> -  </div> -</div> + +<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f, scope_param: "authorization[scope][]"}) %>  <%= hidden_input f, :client_id, value: @client_id %>  <%= hidden_input f, :response_type, value: @response_type %>  <%= hidden_input f, :redirect_uri, value: @redirect_uri %> -<%= hidden_input f, :state, value: @state%> +<%= hidden_input f, :state, value: @state %>  <%= submit "Authorize" %>  <% end %> + +<%= if Pleroma.Config.get([:auth, :oauth_consumer_enabled]) do %> +  <%= render @view_module, Pleroma.Web.Auth.Authenticator.oauth_consumer_template(), assigns %> +<% end %> | 
