Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into feature/digest-email

This commit is contained in:
Roman Chvanikov 2019-04-19 23:27:13 +07:00
commit 73407f4eea
20 changed files with 252 additions and 143 deletions

View file

@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: `/api/v1/notifications/destroy_multiple` (glitch-soc extension) - Mastodon API: `/api/v1/notifications/destroy_multiple` (glitch-soc extension)
- Mastodon API: [Reports](https://docs.joinmastodon.org/api/rest/reports/) - Mastodon API: [Reports](https://docs.joinmastodon.org/api/rest/reports/)
- ActivityPub C2S: OAuth endpoints - ActivityPub C2S: OAuth endpoints
- Metadata RelMe provider
### Changed ### Changed
- **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer - **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer

View file

@ -1,6 +1,6 @@
# Pleroma # Pleroma
**Note**: This readme as well as complete documentation is also availible at <https://docs-develop.pleroma.social> **Note**: This readme as well as complete documentation is also available at <https://docs-develop.pleroma.social>
## About Pleroma ## About Pleroma

View file

@ -337,7 +337,9 @@
ip: {0, 0, 0, 0}, ip: {0, 0, 0, 0},
port: 9999 port: 9999
config :pleroma, Pleroma.Web.Metadata, providers: [], unfurl_nsfw: false config :pleroma, Pleroma.Web.Metadata,
providers: [Pleroma.Web.Metadata.Providers.RelMe],
unfurl_nsfw: false
config :pleroma, :suggestions, config :pleroma, :suggestions,
enabled: false, enabled: false,

View file

@ -41,6 +41,12 @@ Has these additional fields under the `pleroma` object:
- `is_admin`: boolean, true if user is an admin - `is_admin`: boolean, true if user is an admin
- `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated - `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
## Account Search
Behavior has changed:
- `/api/v1/accounts/search`: Does not require authentication
## Notifications ## Notifications
Has these additional fields under the `pleroma` object: Has these additional fields under the `pleroma` object:

View file

@ -343,9 +343,10 @@ This config contains two queues: `federator_incoming` and `federator_outgoing`.
* `max_retries`: The maximum number of times a federation job is retried * `max_retries`: The maximum number of times a federation job is retried
## Pleroma.Web.Metadata ## Pleroma.Web.Metadata
* `providers`: a list of metadata providers to enable. Providers availible: * `providers`: a list of metadata providers to enable. Providers available:
* Pleroma.Web.Metadata.Providers.OpenGraph * Pleroma.Web.Metadata.Providers.OpenGraph
* Pleroma.Web.Metadata.Providers.TwitterCard * Pleroma.Web.Metadata.Providers.TwitterCard
* Pleroma.Web.Metadata.Providers.RelMe - add links from user bio with rel=me into the `<header>` as `<link rel=me>`
* `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews * `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews
## :rich_media ## :rich_media

View file

@ -712,7 +712,14 @@ defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do
from( from(
activity in query, activity in query,
where: fragment("not (? = ANY(?))", activity.actor, ^blocks), where: fragment("not (? = ANY(?))", activity.actor, ^blocks),
where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks), where: fragment("not (? && ?)", activity.recipients, ^blocks),
where:
fragment(
"not (?->>'type' = 'Announce' and ?->'to' \\?| ?)",
activity.data,
activity.data,
^blocks
),
where: fragment("not (split_part(?, '/', 3) = ANY(?))", activity.actor, ^domain_blocks) where: fragment("not (split_part(?, '/', 3) = ANY(?))", activity.actor, ^domain_blocks)
) )
end end

View file

@ -13,21 +13,21 @@ def implementation do
) )
end end
@callback get_user(Plug.Conn.t(), Map.t()) :: {:ok, User.t()} | {:error, any()} @callback get_user(Plug.Conn.t()) :: {:ok, User.t()} | {:error, any()}
def get_user(plug, params), do: implementation().get_user(plug, params) def get_user(plug), do: implementation().get_user(plug)
@callback create_from_registration(Plug.Conn.t(), Map.t(), Registration.t()) :: @callback create_from_registration(Plug.Conn.t(), Registration.t()) ::
{:ok, User.t()} | {:error, any()} {:ok, User.t()} | {:error, any()}
def create_from_registration(plug, params, registration), def create_from_registration(plug, registration),
do: implementation().create_from_registration(plug, params, registration) do: implementation().create_from_registration(plug, registration)
@callback get_registration(Plug.Conn.t(), Map.t()) :: @callback get_registration(Plug.Conn.t()) ::
{:ok, Registration.t()} | {:error, any()} {:ok, Registration.t()} | {:error, any()}
def get_registration(plug, params), def get_registration(plug), do: implementation().get_registration(plug)
do: implementation().get_registration(plug, params)
@callback handle_error(Plug.Conn.t(), any()) :: any() @callback handle_error(Plug.Conn.t(), any()) :: any()
def handle_error(plug, error), do: implementation().handle_error(plug, error) def handle_error(plug, error),
do: implementation().handle_error(plug, error)
@callback auth_template() :: String.t() | nil @callback auth_template() :: String.t() | nil
def auth_template do def auth_template do

View file

@ -13,14 +13,16 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
@connection_timeout 10_000 @connection_timeout 10_000
@search_timeout 10_000 @search_timeout 10_000
defdelegate get_registration(conn, params), to: @base defdelegate get_registration(conn), to: @base
defdelegate create_from_registration(conn, registration), to: @base
defdelegate handle_error(conn, error), to: @base
defdelegate auth_template, to: @base
defdelegate oauth_consumer_template, to: @base
defdelegate create_from_registration(conn, params, registration), to: @base def get_user(%Plug.Conn{} = conn) do
def get_user(%Plug.Conn{} = conn, params) do
if Pleroma.Config.get([:ldap, :enabled]) do if Pleroma.Config.get([:ldap, :enabled]) do
{name, password} = {name, password} =
case params do case conn.params do
%{"authorization" => %{"name" => name, "password" => password}} -> %{"authorization" => %{"name" => name, "password" => password}} ->
{name, password} {name, password}
@ -34,25 +36,17 @@ def get_user(%Plug.Conn{} = conn, params) do
{:error, {:ldap_connection_error, _}} -> {:error, {:ldap_connection_error, _}} ->
# When LDAP is unavailable, try default authenticator # When LDAP is unavailable, try default authenticator
@base.get_user(conn, params) @base.get_user(conn)
error -> error ->
error error
end end
else else
# Fall back to default authenticator # Fall back to default authenticator
@base.get_user(conn, params) @base.get_user(conn)
end end
end end
def handle_error(%Plug.Conn{} = _conn, error) do
error
end
def auth_template, do: nil
def oauth_consumer_template, do: nil
defp ldap_user(name, password) do defp ldap_user(name, password) do
ldap = Pleroma.Config.get(:ldap, []) ldap = Pleroma.Config.get(:ldap, [])
host = Keyword.get(ldap, :host, "localhost") host = Keyword.get(ldap, :host, "localhost")

View file

@ -10,9 +10,9 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
@behaviour Pleroma.Web.Auth.Authenticator @behaviour Pleroma.Web.Auth.Authenticator
def get_user(%Plug.Conn{} = _conn, params) do def get_user(%Plug.Conn{} = conn) do
{name, password} = {name, password} =
case params do case conn.params do
%{"authorization" => %{"name" => name, "password" => password}} -> %{"authorization" => %{"name" => name, "password" => password}} ->
{name, password} {name, password}
@ -29,10 +29,9 @@ def get_user(%Plug.Conn{} = _conn, params) do
end end
end end
def get_registration( def get_registration(%Plug.Conn{
%Plug.Conn{assigns: %{ueberauth_auth: %{provider: provider, uid: uid} = auth}}, assigns: %{ueberauth_auth: %{provider: provider, uid: uid} = auth}
_params }) do
) do
registration = Registration.get_by_provider_uid(provider, uid) registration = Registration.get_by_provider_uid(provider, uid)
if registration do if registration do
@ -40,7 +39,8 @@ def get_registration(
else else
info = auth.info info = auth.info
Registration.changeset(%Registration{}, %{ %Registration{}
|> Registration.changeset(%{
provider: to_string(provider), provider: to_string(provider),
uid: to_string(uid), uid: to_string(uid),
info: %{ info: %{
@ -54,13 +54,16 @@ def get_registration(
end end
end end
def get_registration(%Plug.Conn{} = _conn, _params), do: {:error, :missing_credentials} def get_registration(%Plug.Conn{} = _conn), do: {:error, :missing_credentials}
def create_from_registration(_conn, params, registration) do def create_from_registration(
nickname = value([params["nickname"], Registration.nickname(registration)]) %Plug.Conn{params: %{"authorization" => registration_attrs}},
email = value([params["email"], Registration.email(registration)]) registration
name = value([params["name"], Registration.name(registration)]) || nickname ) do
bio = value([params["bio"], Registration.description(registration)]) nickname = value([registration_attrs["nickname"], Registration.nickname(registration)])
email = value([registration_attrs["email"], Registration.email(registration)])
name = value([registration_attrs["name"], Registration.name(registration)]) || nickname
bio = value([registration_attrs["bio"], Registration.description(registration)])
random_password = :crypto.strong_rand_bytes(64) |> Base.encode64() random_password = :crypto.strong_rand_bytes(64) |> Base.encode64()

View file

@ -0,0 +1,13 @@
defmodule Pleroma.Web.Metadata.Providers.RelMe do
alias Pleroma.Web.Metadata.Providers.Provider
@behaviour Provider
@impl Provider
def build_tags(%{user: user}) do
(Floki.attribute(user.bio, "link[rel~=me]", "href") ++
Floki.attribute(user.bio, "a[rel~=me]", "href"))
|> Enum.map(fn link ->
{:link, [rel: "me", href: link], []}
end)
end
end

View file

@ -24,6 +24,6 @@ def call(conn, _error) do
conn conn
|> put_status(:unauthorized) |> put_status(:unauthorized)
|> put_flash(:error, "Invalid Username/Password") |> put_flash(:error, "Invalid Username/Password")
|> OAuthController.authorize(conn.params["authorization"]) |> OAuthController.authorize(conn.params)
end end
end end

View file

@ -44,36 +44,40 @@ def authorize(%{assigns: %{token: %Token{} = token}} = conn, params) do
def authorize(conn, params), do: do_authorize(conn, params) def authorize(conn, params), do: do_authorize(conn, params)
defp do_authorize(conn, params) do defp do_authorize(conn, %{"authorization" => auth_attrs}), do: do_authorize(conn, auth_attrs)
app = Repo.get_by(App, client_id: params["client_id"])
defp do_authorize(conn, auth_attrs) do
app = Repo.get_by(App, client_id: auth_attrs["client_id"])
available_scopes = (app && app.scopes) || [] available_scopes = (app && app.scopes) || []
scopes = oauth_scopes(params, nil) || available_scopes scopes = oauth_scopes(auth_attrs, nil) || available_scopes
render(conn, Authenticator.auth_template(), %{ render(conn, Authenticator.auth_template(), %{
response_type: params["response_type"], response_type: auth_attrs["response_type"],
client_id: params["client_id"], client_id: auth_attrs["client_id"],
available_scopes: available_scopes, available_scopes: available_scopes,
scopes: scopes, scopes: scopes,
redirect_uri: params["redirect_uri"], redirect_uri: auth_attrs["redirect_uri"],
state: params["state"], state: auth_attrs["state"],
params: params params: auth_attrs
}) })
end end
def create_authorization( def create_authorization(
conn, conn,
%{"authorization" => auth_params} = params, %{"authorization" => _} = params,
opts \\ [] opts \\ []
) do ) do
with {:ok, auth} <- do_create_authorization(conn, params, opts[:user]) do with {:ok, auth} <- do_create_authorization(conn, params, opts[:user]) do
after_create_authorization(conn, auth, auth_params) after_create_authorization(conn, auth, params)
else else
error -> error ->
handle_create_authorization_error(conn, error, auth_params) handle_create_authorization_error(conn, error, params)
end end
end end
def after_create_authorization(conn, auth, %{"redirect_uri" => redirect_uri} = auth_params) do def after_create_authorization(conn, auth, %{
"authorization" => %{"redirect_uri" => redirect_uri} = auth_attrs
}) do
redirect_uri = redirect_uri(conn, redirect_uri) redirect_uri = redirect_uri(conn, redirect_uri)
if redirect_uri == "urn:ietf:wg:oauth:2.0:oob" do if redirect_uri == "urn:ietf:wg:oauth:2.0:oob" do
@ -86,8 +90,8 @@ def after_create_authorization(conn, auth, %{"redirect_uri" => redirect_uri} = a
url_params = %{:code => auth.token} url_params = %{:code => auth.token}
url_params = url_params =
if auth_params["state"] do if auth_attrs["state"] do
Map.put(url_params, :state, auth_params["state"]) Map.put(url_params, :state, auth_attrs["state"])
else else
url_params url_params
end end
@ -98,26 +102,34 @@ def after_create_authorization(conn, auth, %{"redirect_uri" => redirect_uri} = a
end end
end end
defp handle_create_authorization_error(conn, {scopes_issue, _}, auth_params) defp handle_create_authorization_error(
conn,
{scopes_issue, _},
%{"authorization" => _} = params
)
when scopes_issue in [:unsupported_scopes, :missing_scopes] do when scopes_issue in [:unsupported_scopes, :missing_scopes] do
# Per https://github.com/tootsuite/mastodon/blob/ # Per https://github.com/tootsuite/mastodon/blob/
# 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L39 # 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L39
conn conn
|> put_flash(:error, "This action is outside the authorized scopes") |> put_flash(:error, "This action is outside the authorized scopes")
|> put_status(:unauthorized) |> put_status(:unauthorized)
|> authorize(auth_params) |> authorize(params)
end end
defp handle_create_authorization_error(conn, {:auth_active, false}, auth_params) do defp handle_create_authorization_error(
conn,
{:auth_active, false},
%{"authorization" => _} = params
) do
# Per https://github.com/tootsuite/mastodon/blob/ # Per https://github.com/tootsuite/mastodon/blob/
# 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L76 # 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L76
conn conn
|> put_flash(:error, "Your login is missing a confirmed e-mail address") |> put_flash(:error, "Your login is missing a confirmed e-mail address")
|> put_status(:forbidden) |> put_status(:forbidden)
|> authorize(auth_params) |> authorize(params)
end end
defp handle_create_authorization_error(conn, error, _auth_params) do defp handle_create_authorization_error(conn, error, %{"authorization" => _}) do
Authenticator.handle_error(conn, error) Authenticator.handle_error(conn, error)
end end
@ -151,7 +163,7 @@ def token_exchange(
conn, conn,
%{"grant_type" => "password"} = params %{"grant_type" => "password"} = params
) do ) do
with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn, params)}, with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)},
%App{} = app <- get_app_from_request(conn, params), %App{} = app <- get_app_from_request(conn, params),
{:auth_active, true} <- {:auth_active, User.auth_active?(user)}, {:auth_active, true} <- {:auth_active, User.auth_active?(user)},
{:user_active, true} <- {:user_active, !user.info.deactivated}, {:user_active, true} <- {:user_active, !user.info.deactivated},
@ -214,19 +226,19 @@ def token_revoke(conn, %{"token" => token} = params) do
end end
@doc "Prepares OAuth request to provider for Ueberauth" @doc "Prepares OAuth request to provider for Ueberauth"
def prepare_request(conn, %{"provider" => provider} = params) do def prepare_request(conn, %{"provider" => provider, "authorization" => auth_attrs}) do
scope = scope =
oauth_scopes(params, []) oauth_scopes(auth_attrs, [])
|> Enum.join(" ") |> Enum.join(" ")
state = state =
params auth_attrs
|> Map.delete("scopes") |> Map.delete("scopes")
|> Map.put("scope", scope) |> Map.put("scope", scope)
|> Poison.encode!() |> Poison.encode!()
params = params =
params auth_attrs
|> Map.drop(~w(scope scopes client_id redirect_uri)) |> Map.drop(~w(scope scopes client_id redirect_uri))
|> Map.put("state", state) |> Map.put("state", state)
@ -260,26 +272,26 @@ def callback(%{assigns: %{ueberauth_failure: failure}} = conn, params) do
def callback(conn, params) do def callback(conn, params) do
params = callback_params(params) params = callback_params(params)
with {:ok, registration} <- Authenticator.get_registration(conn, params) do with {:ok, registration} <- Authenticator.get_registration(conn) do
user = Repo.preload(registration, :user).user user = Repo.preload(registration, :user).user
auth_params = Map.take(params, ~w(client_id redirect_uri scope scopes state)) auth_attrs = Map.take(params, ~w(client_id redirect_uri scope scopes state))
if user do if user do
create_authorization( create_authorization(
conn, conn,
%{"authorization" => auth_params}, %{"authorization" => auth_attrs},
user: user user: user
) )
else else
registration_params = registration_params =
Map.merge(auth_params, %{ Map.merge(auth_attrs, %{
"nickname" => Registration.nickname(registration), "nickname" => Registration.nickname(registration),
"email" => Registration.email(registration) "email" => Registration.email(registration)
}) })
conn conn
|> put_session(:registration_id, registration.id) |> put_session(:registration_id, registration.id)
|> registration_details(registration_params) |> registration_details(%{"authorization" => registration_params})
end end
else else
_ -> _ ->
@ -293,53 +305,44 @@ defp callback_params(%{"state" => state} = params) do
Map.merge(params, Poison.decode!(state)) Map.merge(params, Poison.decode!(state))
end end
def registration_details(conn, params) do def registration_details(conn, %{"authorization" => auth_attrs}) do
render(conn, "register.html", %{ render(conn, "register.html", %{
client_id: params["client_id"], client_id: auth_attrs["client_id"],
redirect_uri: params["redirect_uri"], redirect_uri: auth_attrs["redirect_uri"],
state: params["state"], state: auth_attrs["state"],
scopes: oauth_scopes(params, []), scopes: oauth_scopes(auth_attrs, []),
nickname: params["nickname"], nickname: auth_attrs["nickname"],
email: params["email"] email: auth_attrs["email"]
}) })
end end
def register(conn, %{"op" => "connect"} = params) do def register(conn, %{"authorization" => _, "op" => "connect"} = params) do
authorization_params = Map.put(params, "name", params["auth_name"])
create_authorization_params = %{"authorization" => authorization_params}
with registration_id when not is_nil(registration_id) <- get_session_registration_id(conn), with registration_id when not is_nil(registration_id) <- get_session_registration_id(conn),
%Registration{} = registration <- Repo.get(Registration, registration_id), %Registration{} = registration <- Repo.get(Registration, registration_id),
{_, {:ok, auth}} <- {_, {:ok, auth}} <-
{:create_authorization, do_create_authorization(conn, create_authorization_params)}, {:create_authorization, do_create_authorization(conn, params)},
%User{} = user <- Repo.preload(auth, :user).user, %User{} = user <- Repo.preload(auth, :user).user,
{:ok, _updated_registration} <- Registration.bind_to_user(registration, user) do {:ok, _updated_registration} <- Registration.bind_to_user(registration, user) do
conn conn
|> put_session_registration_id(nil) |> put_session_registration_id(nil)
|> after_create_authorization(auth, authorization_params) |> after_create_authorization(auth, params)
else else
{:create_authorization, error} -> {:create_authorization, error} ->
{:register, handle_create_authorization_error(conn, error, create_authorization_params)} {:register, handle_create_authorization_error(conn, error, params)}
_ -> _ ->
{:register, :generic_error} {:register, :generic_error}
end end
end end
def register(conn, %{"op" => "register"} = params) do def register(conn, %{"authorization" => _, "op" => "register"} = params) do
with registration_id when not is_nil(registration_id) <- get_session_registration_id(conn), with registration_id when not is_nil(registration_id) <- get_session_registration_id(conn),
%Registration{} = registration <- Repo.get(Registration, registration_id), %Registration{} = registration <- Repo.get(Registration, registration_id),
{:ok, user} <- Authenticator.create_from_registration(conn, params, registration) do {:ok, user} <- Authenticator.create_from_registration(conn, registration) do
conn conn
|> put_session_registration_id(nil) |> put_session_registration_id(nil)
|> create_authorization( |> create_authorization(
%{ params,
"authorization" => %{
"client_id" => params["client_id"],
"redirect_uri" => params["redirect_uri"],
"scopes" => oauth_scopes(params, nil)
}
},
user: user user: user
) )
else else
@ -374,15 +377,15 @@ defp do_create_authorization(
%{ %{
"client_id" => client_id, "client_id" => client_id,
"redirect_uri" => redirect_uri "redirect_uri" => redirect_uri
} = auth_params } = auth_attrs
} = params, },
user \\ nil user \\ nil
) do ) do
with {_, {:ok, %User{} = user}} <- with {_, {:ok, %User{} = user}} <-
{:get_user, (user && {:ok, user}) || Authenticator.get_user(conn, params)}, {:get_user, (user && {:ok, user}) || Authenticator.get_user(conn)},
%App{} = app <- Repo.get_by(App, client_id: client_id), %App{} = app <- Repo.get_by(App, client_id: client_id),
true <- redirect_uri in String.split(app.redirect_uris), true <- redirect_uri in String.split(app.redirect_uris),
scopes <- oauth_scopes(auth_params, []), scopes <- oauth_scopes(auth_attrs, []),
{:unsupported_scopes, []} <- {:unsupported_scopes, scopes -- app.scopes}, {:unsupported_scopes, []} <- {:unsupported_scopes, scopes -- app.scopes},
# Note: `scope` param is intentionally not optional in this context # Note: `scope` param is intentionally not optional in this context
{:missing_scopes, false} <- {:missing_scopes, scopes == []}, {:missing_scopes, false} <- {:missing_scopes, scopes == []},

View file

@ -242,7 +242,6 @@ defmodule Pleroma.Web.Router do
get("/accounts/verify_credentials", MastodonAPIController, :verify_credentials) get("/accounts/verify_credentials", MastodonAPIController, :verify_credentials)
get("/accounts/relationships", MastodonAPIController, :relationships) get("/accounts/relationships", MastodonAPIController, :relationships)
get("/accounts/search", MastodonAPIController, :account_search)
get("/accounts/:id/lists", MastodonAPIController, :account_lists) get("/accounts/:id/lists", MastodonAPIController, :account_lists)
get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array) get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array)
@ -377,6 +376,8 @@ defmodule Pleroma.Web.Router do
get("/trends", MastodonAPIController, :empty_array) get("/trends", MastodonAPIController, :empty_array)
get("/accounts/search", MastodonAPIController, :account_search)
scope [] do scope [] do
pipe_through(:oauth_read_or_unauthenticated) pipe_through(:oauth_read_or_unauthenticated)

View file

@ -5,7 +5,7 @@
<%= for scope <- @available_scopes do %> <%= 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 %> <%# Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %>
<div class="scope"> <div class="scope">
<%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: assigns[:scope_param] || "scope[]" %> <%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: "authorization[scope][]" %>
<%= label @form, :"scope_#{scope}", String.capitalize(scope) %> <%= label @form, :"scope_#{scope}", String.capitalize(scope) %>
</div> </div>
<% end %> <% end %>

View file

@ -1,6 +1,6 @@
<h2>Sign in with external provider</h2> <h2>Sign in with external provider</h2>
<%= form_for @conn, o_auth_path(@conn, :prepare_request), [method: "get"], fn f -> %> <%= form_for @conn, o_auth_path(@conn, :prepare_request), [as: "authorization", method: "get"], fn f -> %>
<%= render @view_module, "_scopes.html", Map.put(assigns, :form, f) %> <%= render @view_module, "_scopes.html", Map.put(assigns, :form, f) %>
<%= hidden_input f, :client_id, value: @client_id %> <%= hidden_input f, :client_id, value: @client_id %>

View file

@ -8,8 +8,7 @@
<h2>Registration Details</h2> <h2>Registration Details</h2>
<p>If you'd like to register a new account, please provide the details below.</p> <p>If you'd like to register a new account, please provide the details below.</p>
<%= form_for @conn, o_auth_path(@conn, :register), [as: "authorization"], fn f -> %>
<%= form_for @conn, o_auth_path(@conn, :register), [], fn f -> %>
<div class="input"> <div class="input">
<%= label f, :nickname, "Nickname" %> <%= label f, :nickname, "Nickname" %>
@ -25,8 +24,8 @@
<p>Alternatively, sign in to connect to existing account.</p> <p>Alternatively, sign in to connect to existing account.</p>
<div class="input"> <div class="input">
<%= label f, :auth_name, "Name or email" %> <%= label f, :name, "Name or email" %>
<%= text_input f, :auth_name %> <%= text_input f, :name %>
</div> </div>
<div class="input"> <div class="input">
<%= label f, :password, "Password" %> <%= label f, :password, "Password" %>

View file

@ -17,7 +17,7 @@
<%= password_input f, :password %> <%= password_input f, :password %>
</div> </div>
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f, scope_param: "authorization[scope][]"}) %> <%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
<%= hidden_input f, :client_id, value: @client_id %> <%= hidden_input f, :client_id, value: @client_id %>
<%= hidden_input f, :response_type, value: @response_type %> <%= hidden_input f, :response_type, value: @response_type %>

View file

@ -341,6 +341,51 @@ test "doesn't return blocked activities" do
assert Enum.member?(activities, activity_one) assert Enum.member?(activities, activity_one)
end end
test "doesn't return transitive interactions concerning blocked users" do
blocker = insert(:user)
blockee = insert(:user)
friend = insert(:user)
{:ok, blocker} = User.block(blocker, blockee)
{:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
{:ok, activity_two} = CommonAPI.post(friend, %{"status" => "hey! @#{blockee.nickname}"})
{:ok, activity_three} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
{:ok, activity_four} = CommonAPI.post(blockee, %{"status" => "hey! @#{blocker.nickname}"})
activities = ActivityPub.fetch_activities([], %{"blocking_user" => blocker})
assert Enum.member?(activities, activity_one)
refute Enum.member?(activities, activity_two)
refute Enum.member?(activities, activity_three)
refute Enum.member?(activities, activity_four)
end
test "doesn't return announce activities concerning blocked users" do
blocker = insert(:user)
blockee = insert(:user)
friend = insert(:user)
{:ok, blocker} = User.block(blocker, blockee)
{:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
{:ok, activity_two} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
{:ok, activity_three, _} = CommonAPI.repeat(activity_two.id, friend)
activities =
ActivityPub.fetch_activities([], %{"blocking_user" => blocker})
|> Enum.map(fn act -> act.id end)
assert Enum.member?(activities, activity_one.id)
refute Enum.member?(activities, activity_two.id)
refute Enum.member?(activities, activity_three.id)
end
test "doesn't return muted activities" do test "doesn't return muted activities" do
activity_one = insert(:note_activity) activity_one = insert(:note_activity)
activity_two = insert(:note_activity) activity_two = insert(:note_activity)

View file

@ -0,0 +1,18 @@
defmodule Pleroma.Web.Metadata.Providers.RelMeTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Web.Metadata.Providers.RelMe
test "it renders all links with rel='me' from user bio" do
bio =
~s(<a href="https://some-link.com">https://some-link.com</a> <a rel="me" href="https://another-link.com">https://another-link.com</a>
<link href="http://some.com"> <link rel="me" href="http://some3.com>")
user = insert(:user, %{bio: bio})
assert RelMe.build_tags(%{user: user}) == [
{:link, [rel: "me", href: "http://some3.com>"], []},
{:link, [rel: "me", href: "https://another-link.com"], []}
]
end
end

View file

@ -68,11 +68,13 @@ test "GET /oauth/prepare_request encodes parameters as `state` and redirects", %
"/oauth/prepare_request", "/oauth/prepare_request",
%{ %{
"provider" => "twitter", "provider" => "twitter",
"authorization" => %{
"scope" => "read follow", "scope" => "read follow",
"client_id" => app.client_id, "client_id" => app.client_id,
"redirect_uri" => app.redirect_uris, "redirect_uri" => app.redirect_uris,
"state" => "a_state" "state" => "a_state"
} }
}
) )
assert response = html_response(conn, 302) assert response = html_response(conn, 302)
@ -104,7 +106,7 @@ test "with user-bound registration, GET /oauth/<provider>/callback redirects to
} }
with_mock Pleroma.Web.Auth.Authenticator, with_mock Pleroma.Web.Auth.Authenticator,
get_registration: fn _, _ -> {:ok, registration} end do get_registration: fn _ -> {:ok, registration} end do
conn = conn =
get( get(
conn, conn,
@ -134,7 +136,7 @@ test "with user-unbound registration, GET /oauth/<provider>/callback renders reg
} }
with_mock Pleroma.Web.Auth.Authenticator, with_mock Pleroma.Web.Auth.Authenticator,
get_registration: fn _, _ -> {:ok, registration} end do get_registration: fn _ -> {:ok, registration} end do
conn = conn =
get( get(
conn, conn,
@ -193,6 +195,7 @@ test "GET /oauth/registration_details renders registration details form", %{
conn, conn,
"/oauth/registration_details", "/oauth/registration_details",
%{ %{
"authorization" => %{
"scopes" => app.scopes, "scopes" => app.scopes,
"client_id" => app.client_id, "client_id" => app.client_id,
"redirect_uri" => app.redirect_uris, "redirect_uri" => app.redirect_uris,
@ -200,6 +203,7 @@ test "GET /oauth/registration_details renders registration details form", %{
"nickname" => nil, "nickname" => nil,
"email" => "john@doe.com" "email" => "john@doe.com"
} }
}
) )
assert response = html_response(conn, 200) assert response = html_response(conn, 200)
@ -221,6 +225,7 @@ test "with valid params, POST /oauth/register?op=register redirects to `redirect
"/oauth/register", "/oauth/register",
%{ %{
"op" => "register", "op" => "register",
"authorization" => %{
"scopes" => app.scopes, "scopes" => app.scopes,
"client_id" => app.client_id, "client_id" => app.client_id,
"redirect_uri" => app.redirect_uris, "redirect_uri" => app.redirect_uris,
@ -228,6 +233,7 @@ test "with valid params, POST /oauth/register?op=register redirects to `redirect
"nickname" => "availablenick", "nickname" => "availablenick",
"email" => "available@email.com" "email" => "available@email.com"
} }
}
) )
assert response = html_response(conn, 302) assert response = html_response(conn, 302)
@ -244,6 +250,7 @@ test "with invalid params, POST /oauth/register?op=register renders registration
params = %{ params = %{
"op" => "register", "op" => "register",
"authorization" => %{
"scopes" => app.scopes, "scopes" => app.scopes,
"client_id" => app.client_id, "client_id" => app.client_id,
"redirect_uri" => app.redirect_uris, "redirect_uri" => app.redirect_uris,
@ -251,10 +258,15 @@ test "with invalid params, POST /oauth/register?op=register renders registration
"nickname" => "availablenickname", "nickname" => "availablenickname",
"email" => "available@email.com" "email" => "available@email.com"
} }
}
for {bad_param, bad_param_value} <- for {bad_param, bad_param_value} <-
[{"nickname", another_user.nickname}, {"email", another_user.email}] do [{"nickname", another_user.nickname}, {"email", another_user.email}] do
bad_params = Map.put(params, bad_param, bad_param_value) bad_registration_attrs = %{
"authorization" => Map.put(params["authorization"], bad_param, bad_param_value)
}
bad_params = Map.merge(params, bad_registration_attrs)
conn = conn =
conn conn
@ -281,13 +293,15 @@ test "with valid params, POST /oauth/register?op=connect redirects to `redirect_
"/oauth/register", "/oauth/register",
%{ %{
"op" => "connect", "op" => "connect",
"authorization" => %{
"scopes" => app.scopes, "scopes" => app.scopes,
"client_id" => app.client_id, "client_id" => app.client_id,
"redirect_uri" => app.redirect_uris, "redirect_uri" => app.redirect_uris,
"state" => "a_state", "state" => "a_state",
"auth_name" => user.nickname, "name" => user.nickname,
"password" => "testpassword" "password" => "testpassword"
} }
}
) )
assert response = html_response(conn, 302) assert response = html_response(conn, 302)
@ -304,13 +318,15 @@ test "with invalid params, POST /oauth/register?op=connect renders registration_
params = %{ params = %{
"op" => "connect", "op" => "connect",
"authorization" => %{
"scopes" => app.scopes, "scopes" => app.scopes,
"client_id" => app.client_id, "client_id" => app.client_id,
"redirect_uri" => app.redirect_uris, "redirect_uri" => app.redirect_uris,
"state" => "a_state", "state" => "a_state",
"auth_name" => user.nickname, "name" => user.nickname,
"password" => "wrong password" "password" => "wrong password"
} }
}
conn = conn =
conn conn