From 2b664b048eac5f37421ab958e26efed9c158c8d0 Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 3 Jun 2019 18:16:11 +0200 Subject: User: Add function to get AP ids from nicknames. --- lib/pleroma/user.ex | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 474cd8c1a..dc534b05c 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1441,4 +1441,12 @@ defmodule Pleroma.User do update_and_set_cache(cng) end end + + def get_ap_ids_by_nicknames(nicknames) do + from(u in User, + where: u.nickname in ^nicknames, + select: u.ap_id + ) + |> Repo.all() + end end -- cgit v1.2.3 From 80d4d83aaccf49ddc2a594448851585bf80443bb Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 3 Jun 2019 18:17:08 +0200 Subject: CommonAPI: Add explicit addressing. --- lib/pleroma/web/common_api/common_api.ex | 4 +++- lib/pleroma/web/common_api/utils.ex | 24 +++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 5212d5ce5..f5f62eee3 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -201,8 +201,10 @@ defmodule Pleroma.Web.CommonAPI do data, visibility ), + mentioned_users <- for({_, mentioned_user} <- mentions, do: mentioned_user.ap_id), + addressed_users <- get_addressed_users(mentioned_users, data["to"]), {poll, poll_emoji} <- make_poll_data(data), - {to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility), + {to, cc} <- get_to_and_cc(user, addressed_users, in_reply_to, visibility), context <- make_context(in_reply_to), cw <- data["spoiler_text"] || "", sensitive <- data["sensitive"] || Enum.member?(tags, {"#nsfw", "nsfw"}), diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index f35ed36ab..6d82c0bd2 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -61,9 +61,9 @@ defmodule Pleroma.Web.CommonAPI.Utils do end) end - def to_for_user_and_mentions(user, mentions, inReplyTo, "public") do - mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end) - + @spec get_to_and_cc(User.t(), list(String.t()), Activity.t() | nil, String.t()) :: + {list(String.t()), list(String.t())} + def get_to_and_cc(user, mentioned_users, inReplyTo, "public") do to = ["https://www.w3.org/ns/activitystreams#Public" | mentioned_users] cc = [user.follower_address] @@ -74,9 +74,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do end end - def to_for_user_and_mentions(user, mentions, inReplyTo, "unlisted") do - mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end) - + def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted") do to = [user.follower_address | mentioned_users] cc = ["https://www.w3.org/ns/activitystreams#Public"] @@ -87,14 +85,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do end end - def to_for_user_and_mentions(user, mentions, inReplyTo, "private") do - {to, cc} = to_for_user_and_mentions(user, mentions, inReplyTo, "direct") + def get_to_and_cc(user, mentioned_users, inReplyTo, "private") do + {to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct") {[user.follower_address | to], cc} end - def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do - mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end) - + def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct") do if inReplyTo do {Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []} else @@ -102,6 +98,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do end end + def get_addressed_users(_, to) when is_list(to) do + User.get_ap_ids_by_nicknames(to) + end + + def get_addressed_users(mentioned_users, _), do: mentioned_users + def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_in}} = data) when is_list(options) do %{max_expiration: max_expiration, min_expiration: min_expiration} = -- cgit v1.2.3 From 18c35d84fd732a6d55c9d3174fcbb837e098ea0a Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 4 Jun 2019 17:10:54 +0200 Subject: NodeInfo: Add explicit addressing to nodeinfo. --- lib/pleroma/web/nodeinfo/nodeinfo_controller.ex | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex index 57f5b61bb..32be430b7 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -98,6 +98,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do "mastodon_api", "mastodon_api_streaming", "polls", + "pleroma_explicit_addressing", if Config.get([:media_proxy, :enabled]) do "media_proxy" end, -- cgit v1.2.3 From 93397fce3de54985bde3c3f260660a63157077be Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Fri, 31 May 2019 16:22:13 +0700 Subject: Contain search for unauthenticated users --- lib/pleroma/activity.ex | 2 + lib/pleroma/activity/search.ex | 75 ++++++++++++++++++++++ .../web/mastodon_api/mastodon_api_controller.ex | 61 +----------------- 3 files changed, 79 insertions(+), 59 deletions(-) create mode 100644 lib/pleroma/activity/search.ex (limited to 'lib') diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 99589590c..6db41fe6e 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -343,4 +343,6 @@ defmodule Pleroma.Activity do ) ) end + + defdelegate search(user, query), to: Pleroma.Activity.Search end diff --git a/lib/pleroma/activity/search.ex b/lib/pleroma/activity/search.ex new file mode 100644 index 000000000..f2fdfffe1 --- /dev/null +++ b/lib/pleroma/activity/search.ex @@ -0,0 +1,75 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Activity.Search do + alias Pleroma.Activity + alias Pleroma.Object.Fetcher + alias Pleroma.Repo + alias Pleroma.User + alias Pleroma.Web.ActivityPub.Visibility + + import Ecto.Query + + def search(user, search_query) do + index_type = if Pleroma.Config.get([:database, :rum_enabled]), do: :rum, else: :gin + + Activity + |> Activity.with_preloaded_object() + |> Activity.restrict_deactivated_users() + |> restrict_public() + |> query_with(index_type, search_query) + |> maybe_restrict_local(user) + |> Repo.all() + |> maybe_fetch(user, search_query) + end + + defp restrict_public(q) do + from([a, o] in q, + where: fragment("?->>'type' = 'Create'", a.data), + where: "https://www.w3.org/ns/activitystreams#Public" in a.recipients, + limit: 40 + ) + end + + defp query_with(q, :gin, search_query) do + from([a, o] in q, + where: + fragment( + "to_tsvector('english', ?->>'content') @@ plainto_tsquery('english', ?)", + o.data, + ^search_query + ), + order_by: [desc: :id] + ) + end + + defp query_with(q, :rum, search_query) do + from([a, o] in q, + where: + fragment( + "? @@ plainto_tsquery('english', ?)", + o.fts_content, + ^search_query + ), + order_by: [fragment("? <=> now()::date", o.inserted_at)] + ) + end + + # users can search everything + defp maybe_restrict_local(q, %User{}), do: q + + # unauthenticated users can only search local activities + defp maybe_restrict_local(q, _), do: where(q, local: true) + + defp maybe_fetch(activities, user, search_query) do + with true <- Regex.match?(~r/https?:/, search_query), + {:ok, object} <- Fetcher.fetch_object_from_id(search_query), + %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]), + true <- Visibility.visible_for_user?(activity, user) do + activities ++ [activity] + else + _ -> activities + end + end +end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index d825555c6..92cd77f62 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -14,7 +14,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do alias Pleroma.HTTP alias Pleroma.Notification alias Pleroma.Object - alias Pleroma.Object.Fetcher alias Pleroma.Pagination alias Pleroma.Repo alias Pleroma.ScheduledActivity @@ -1125,64 +1124,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end - def status_search_query_with_gin(q, query) do - from([a, o] in q, - where: - fragment( - "to_tsvector('english', ?->>'content') @@ plainto_tsquery('english', ?)", - o.data, - ^query - ), - order_by: [desc: :id] - ) - end - - def status_search_query_with_rum(q, query) do - from([a, o] in q, - where: - fragment( - "? @@ plainto_tsquery('english', ?)", - o.fts_content, - ^query - ), - order_by: [fragment("? <=> now()::date", o.inserted_at)] - ) - end - - def status_search(user, query) do - fetched = - if Regex.match?(~r/https?:/, query) do - with {:ok, object} <- Fetcher.fetch_object_from_id(query), - %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]), - true <- Visibility.visible_for_user?(activity, user) do - [activity] - else - _e -> [] - end - end || [] - - q = - from([a, o] in Activity.with_preloaded_object(Activity), - where: fragment("?->>'type' = 'Create'", a.data), - where: "https://www.w3.org/ns/activitystreams#Public" in a.recipients, - limit: 40 - ) - - q = - if Pleroma.Config.get([:database, :rum_enabled]) do - status_search_query_with_rum(q, query) - else - status_search_query_with_gin(q, query) - end - - Repo.all(q) ++ fetched - end - def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user) - - statuses = status_search(user, query) - + statuses = Activity.search(user, query) tags_path = Web.base_url() <> "/tag/" tags = @@ -1205,8 +1149,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user) - - statuses = status_search(user, query) + statuses = Activity.search(user, query) tags = query -- cgit v1.2.3 From 94b9e9d844ad47c198817e732a54ad286caa346a Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Fri, 31 May 2019 16:37:33 +0700 Subject: Update benchmark mix task --- lib/mix/tasks/benchmark.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mix/tasks/benchmark.ex b/lib/mix/tasks/benchmark.ex index 0fbb4dbb1..e4b1a638a 100644 --- a/lib/mix/tasks/benchmark.ex +++ b/lib/mix/tasks/benchmark.ex @@ -7,7 +7,7 @@ defmodule Mix.Tasks.Pleroma.Benchmark do Benchee.run(%{ "search" => fn -> - Pleroma.Web.MastodonAPI.MastodonAPIController.status_search(nil, "cofe") + Pleroma.Activity.search(nil, "cofe") end }) end -- cgit v1.2.3 From 5b04f07a1ebe6763270b406aa6638336cab04a31 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 5 Jun 2019 16:34:14 +0700 Subject: Limit search for unauthenticated users to local users only --- lib/pleroma/user.ex | 117 +----------------------------------- lib/pleroma/user/search.ex | 145 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 115 deletions(-) create mode 100644 lib/pleroma/user/search.ex (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index dc534b05c..498428269 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -735,121 +735,6 @@ defmodule Pleroma.User do |> Repo.all() end - def search(query, resolve \\ false, for_user \\ nil) do - # Strip the beginning @ off if there is a query - query = String.trim_leading(query, "@") - - if resolve, do: get_or_fetch(query) - - {:ok, results} = - Repo.transaction(fn -> - Ecto.Adapters.SQL.query(Repo, "select set_limit(0.25)", []) - Repo.all(search_query(query, for_user)) - end) - - results - end - - def search_query(query, for_user) do - fts_subquery = fts_search_subquery(query) - trigram_subquery = trigram_search_subquery(query) - union_query = from(s in trigram_subquery, union_all: ^fts_subquery) - distinct_query = from(s in subquery(union_query), order_by: s.search_type, distinct: s.id) - - from(s in subquery(boost_search_rank_query(distinct_query, for_user)), - order_by: [desc: s.search_rank], - limit: 40 - ) - end - - defp boost_search_rank_query(query, nil), do: query - - defp boost_search_rank_query(query, for_user) do - friends_ids = get_friends_ids(for_user) - followers_ids = get_followers_ids(for_user) - - from(u in subquery(query), - select_merge: %{ - search_rank: - fragment( - """ - CASE WHEN (?) THEN (?) * 1.3 - WHEN (?) THEN (?) * 1.2 - WHEN (?) THEN (?) * 1.1 - ELSE (?) END - """, - u.id in ^friends_ids and u.id in ^followers_ids, - u.search_rank, - u.id in ^friends_ids, - u.search_rank, - u.id in ^followers_ids, - u.search_rank, - u.search_rank - ) - } - ) - end - - defp fts_search_subquery(term, query \\ User) do - processed_query = - term - |> String.replace(~r/\W+/, " ") - |> String.trim() - |> String.split() - |> Enum.map(&(&1 <> ":*")) - |> Enum.join(" | ") - - from( - u in query, - select_merge: %{ - search_type: ^0, - search_rank: - fragment( - """ - ts_rank_cd( - setweight(to_tsvector('simple', regexp_replace(?, '\\W', ' ', 'g')), 'A') || - setweight(to_tsvector('simple', regexp_replace(coalesce(?, ''), '\\W', ' ', 'g')), 'B'), - to_tsquery('simple', ?), - 32 - ) - """, - u.nickname, - u.name, - ^processed_query - ) - }, - where: - fragment( - """ - (setweight(to_tsvector('simple', regexp_replace(?, '\\W', ' ', 'g')), 'A') || - setweight(to_tsvector('simple', regexp_replace(coalesce(?, ''), '\\W', ' ', 'g')), 'B')) @@ to_tsquery('simple', ?) - """, - u.nickname, - u.name, - ^processed_query - ) - ) - |> restrict_deactivated() - end - - defp trigram_search_subquery(term) do - from( - u in User, - select_merge: %{ - # ^1 gives 'Postgrex expected a binary, got 1' for some weird reason - search_type: fragment("?", 1), - search_rank: - fragment( - "similarity(?, trim(? || ' ' || coalesce(?, '')))", - ^term, - u.nickname, - u.name - ) - }, - where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^term) - ) - |> restrict_deactivated() - end def mute(muter, %User{ap_id: ap_id}) do info_cng = @@ -1449,4 +1334,6 @@ defmodule Pleroma.User do ) |> Repo.all() end + + defdelegate search(query, opts \\ []), to: User.Search end diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex new file mode 100644 index 000000000..d5b2eaa9f --- /dev/null +++ b/lib/pleroma/user/search.ex @@ -0,0 +1,145 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.User.Search do + alias Pleroma.Repo + alias Pleroma.User + import Ecto.Query + + def search(query, opts \\ []) do + resolve = Keyword.get(opts, :resolve, false) + for_user = Keyword.get(opts, :for_user) + + # Strip the beginning @ off if there is a query + query = String.trim_leading(query, "@") + + if match?(%User{}, for_user) and resolve, do: User.get_or_fetch(query) + + {:ok, results} = + Repo.transaction(fn -> + Ecto.Adapters.SQL.query(Repo, "select set_limit(0.25)", []) + + query + |> search_query(for_user) + |> Repo.all() + end) + + results + end + + defp search_query(query, for_user) do + query + |> union_query() + |> distinct_query() + |> boost_search_rank_query(for_user) + |> subquery() + |> order_by(desc: :search_rank) + |> limit(20) + |> maybe_restrict_local(for_user) + end + + defp union_query(query) do + fts_subquery = fts_search_subquery(query) + trigram_subquery = trigram_search_subquery(query) + + from(s in trigram_subquery, union_all: ^fts_subquery) + end + + defp distinct_query(q) do + from(s in subquery(q), order_by: s.search_type, distinct: s.id) + end + + # unauthenticated users can only search local activities + defp maybe_restrict_local(q, %User{}), do: q + defp maybe_restrict_local(q, _), do: where(q, [u], u.local == true) + + defp boost_search_rank_query(query, nil), do: query + + defp boost_search_rank_query(query, for_user) do + friends_ids = User.get_friends_ids(for_user) + followers_ids = User.get_followers_ids(for_user) + + from(u in subquery(query), + select_merge: %{ + search_rank: + fragment( + """ + CASE WHEN (?) THEN (?) * 1.3 + WHEN (?) THEN (?) * 1.2 + WHEN (?) THEN (?) * 1.1 + ELSE (?) END + """, + u.id in ^friends_ids and u.id in ^followers_ids, + u.search_rank, + u.id in ^friends_ids, + u.search_rank, + u.id in ^followers_ids, + u.search_rank, + u.search_rank + ) + } + ) + end + + defp fts_search_subquery(term, query \\ User) do + processed_query = + term + |> String.replace(~r/\W+/, " ") + |> String.trim() + |> String.split() + |> Enum.map(&(&1 <> ":*")) + |> Enum.join(" | ") + + from( + u in query, + select_merge: %{ + search_type: ^0, + search_rank: + fragment( + """ + ts_rank_cd( + setweight(to_tsvector('simple', regexp_replace(?, '\\W', ' ', 'g')), 'A') || + setweight(to_tsvector('simple', regexp_replace(coalesce(?, ''), '\\W', ' ', 'g')), 'B'), + to_tsquery('simple', ?), + 32 + ) + """, + u.nickname, + u.name, + ^processed_query + ) + }, + where: + fragment( + """ + (setweight(to_tsvector('simple', regexp_replace(?, '\\W', ' ', 'g')), 'A') || + setweight(to_tsvector('simple', regexp_replace(coalesce(?, ''), '\\W', ' ', 'g')), 'B')) @@ to_tsquery('simple', ?) + """, + u.nickname, + u.name, + ^processed_query + ) + ) + |> User.restrict_deactivated() + end + + defp trigram_search_subquery(term) do + from( + u in User, + select_merge: %{ + # ^1 gives 'Postgrex expected a binary, got 1' for some weird reason + search_type: fragment("?", 1), + search_rank: + fragment( + "similarity(?, trim(? || ' ' || coalesce(?, '')))", + ^term, + u.nickname, + u.name + ) + }, + where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^term) + ) + |> User.restrict_deactivated() + end +end -- cgit v1.2.3 From 1cb245c9825febb0b83cfc361f78d132cb5d05a8 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 5 Jun 2019 16:55:17 +0700 Subject: Fix formatting --- lib/pleroma/user.ex | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 498428269..cae2c14e3 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -735,7 +735,6 @@ defmodule Pleroma.User do |> Repo.all() end - def mute(muter, %User{ap_id: ap_id}) do info_cng = muter.info -- cgit v1.2.3 From 3eefb274f45e57ad855246cb930a6a094eeffe0e Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 5 Jun 2019 13:02:13 +0300 Subject: OAuth consumer: tests fix, comments, Keycloak config notes. --- lib/pleroma/web/auth/pleroma_authenticator.ex | 11 ++++++++++- lib/pleroma/web/oauth/oauth_controller.ex | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex index c4a6fce08..a9164ad98 100644 --- a/lib/pleroma/web/auth/pleroma_authenticator.ex +++ b/lib/pleroma/web/auth/pleroma_authenticator.ex @@ -24,6 +24,14 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do end end + @doc """ + Gets or creates Pleroma.Registration record from Ueberauth assigns. + Note: some strategies (like `keycloak`) might need extra configuration to fill `uid` from callback response — + see [`docs/config.md`](docs/config.md). + """ + def get_registration(%Plug.Conn{assigns: %{ueberauth_auth: %{uid: nil}}}), + do: {:error, :missing_uid} + def get_registration(%Plug.Conn{ assigns: %{ueberauth_auth: %{provider: provider, uid: uid} = auth} }) do @@ -51,9 +59,10 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do def get_registration(%Plug.Conn{} = _conn), do: {:error, :missing_credentials} + @doc "Creates Pleroma.User record basing on params and Pleroma.Registration record." def create_from_registration( %Plug.Conn{params: %{"authorization" => registration_attrs}}, - registration + %Registration{} = registration ) do nickname = value([registration_attrs["nickname"], Registration.nickname(registration)]) email = value([registration_attrs["email"], Registration.email(registration)]) diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index ae2b80d95..79d803295 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -17,6 +17,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do alias Pleroma.Web.OAuth.Token.Strategy.Revoke, as: RevokeToken alias Pleroma.Web.OAuth.Scopes + require Logger + if Pleroma.Config.oauth_consumer_enabled?(), do: plug(Ueberauth) plug(:fetch_session) @@ -318,7 +320,9 @@ defmodule Pleroma.Web.OAuth.OAuthController do |> registration_details(%{"authorization" => registration_params}) end else - _ -> + error -> + Logger.debug(inspect(["OAUTH_ERROR", error, conn.assigns])) + conn |> put_flash(:error, "Failed to set up user account.") |> redirect(external: redirect_uri(conn, params["redirect_uri"])) -- cgit v1.2.3 From 8b9a0dd4a7e60f610e3aa1db92e62bc0fbe54521 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Jun 2019 12:06:45 +0200 Subject: User: Don't error out when following a user that's already followed. This leads to a few situations where it is impossible to follow a user. --- lib/pleroma/user.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index dc534b05c..48b9f1d7d 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -370,8 +370,8 @@ defmodule Pleroma.User do ap_followers = followed.follower_address cond do - following?(follower, followed) or info.deactivated -> - {:error, "Could not follow user: #{followed.nickname} is already on your list."} + info.deactivated -> + {:error, "Could not follow user: You are deactivatedt."} deny_follow_blocked and blocks?(followed, follower) -> {:error, "Could not follow user: #{followed.nickname} blocked you."} -- cgit v1.2.3 From 024dfdc39c80e3a0c9f625f31101fc6aa896e93d Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Jun 2019 12:45:28 +0200 Subject: Typo + Linting. --- lib/pleroma/user.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 48b9f1d7d..d873d7623 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -371,7 +371,7 @@ defmodule Pleroma.User do cond do info.deactivated -> - {:error, "Could not follow user: You are deactivatedt."} + {:error, "Could not follow user: You are deactivated."} deny_follow_blocked and blocks?(followed, follower) -> {:error, "Could not follow user: #{followed.nickname} blocked you."} -- cgit v1.2.3 From 3115b64cfe220c1db61c71fc4cef51bdf167b9ab Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Jun 2019 14:10:46 +0200 Subject: Transmogrifier: Add tests for incoming follows to locked accounts. --- lib/pleroma/web/activity_pub/transmogrifier.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 66fa7c0b3..8aa44ec09 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -458,10 +458,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, %User{} = follower} <- User.get_or_fetch_by_ap_id(follower), {:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do with deny_follow_blocked <- Pleroma.Config.get([:user, :deny_follow_blocked]), - {:user_blocked, false} <- + {_, false} <- {:user_blocked, User.blocks?(followed, follower) && deny_follow_blocked}, - {:user_locked, false} <- {:user_locked, User.locked?(followed)}, - {:follow, {:ok, follower}} <- {:follow, User.follow(follower, followed)} do + {_, false} <- {:user_locked, User.locked?(followed)}, + {_, {:ok, follower}} <- {:follow, User.follow(follower, followed)}, + {_, {:ok, _}} <- {:follow_state_update, Utils.update_follow_state(activity, "accept")} do ActivityPub.accept(%{ to: [follower.ap_id], actor: followed, -- cgit v1.2.3 From 076c9ae40e1b944839472d5d337d32335590ab0c Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Jun 2019 14:24:31 +0200 Subject: User: Remove superfluous `maybe_follow`. --- lib/pleroma/user.ex | 8 -------- lib/pleroma/web/activity_pub/transmogrifier.ex | 21 ++++++++------------- lib/pleroma/web/common_api/common_api.ex | 2 +- 3 files changed, 9 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index d873d7623..3d8fa0edb 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -324,14 +324,6 @@ defmodule Pleroma.User do end end - def maybe_follow(%User{} = follower, %User{info: _info} = followed) do - if not following?(follower, followed) do - follow(follower, followed) - else - {:ok, follower} - end - end - @doc "A mass follow for local users. Respects blocks in both directions but does not create activities." @spec follow_all(User.t(), list(User.t())) :: {atom(), User.t()} def follow_all(follower, followeds) do diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 8aa44ec09..e8df112b9 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -509,19 +509,14 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:ok, follow_activity} <- get_follow_activity(follow_object, followed), {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), - {:ok, activity} <- - ActivityPub.accept(%{ - to: follow_activity.data["to"], - type: "Accept", - actor: followed, - object: follow_activity.data["id"], - local: false - }) do - if not User.following?(follower, followed) do - {:ok, _follower} = User.follow(follower, followed) - end - - {:ok, activity} + {:ok, _follower} = User.follow(follower, followed) do + ActivityPub.accept(%{ + to: follow_activity.data["to"], + type: "Accept", + actor: followed, + object: follow_activity.data["id"], + local: false + }) else _e -> :error end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 2b3ae3de5..71e166128 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -35,7 +35,7 @@ defmodule Pleroma.Web.CommonAPI do end def accept_follow_request(follower, followed) do - with {:ok, follower} <- User.maybe_follow(follower, followed), + with {:ok, follower} <- User.follow(follower, followed), %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), {:ok, _activity} <- -- cgit v1.2.3 From ad19bfc7feecddd5a0f049ece436c1415335efa3 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Jun 2019 16:43:35 +0200 Subject: Utils: Split update_follow_state and update_follow_state_for_all. --- lib/pleroma/web/activity_pub/utils.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index faae7e747..10ff572a2 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -376,8 +376,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do @doc """ Updates a follow activity's state (for locked accounts). """ - def update_follow_state( - %Activity{data: %{"actor" => actor, "object" => object, "state" => "pending"}} = activity, + def update_follow_state_for_all( + %Activity{data: %{"actor" => actor, "object" => object}} = activity, state ) do try do -- cgit v1.2.3 From e1370ba1316734f61d8326200df1cb0789a4686f Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Jun 2019 16:51:28 +0200 Subject: Utils: Use update_follow_state_for_all when appropriate. --- lib/pleroma/web/activity_pub/transmogrifier.ex | 11 ++++++----- lib/pleroma/web/common_api/common_api.ex | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index e8df112b9..ff031a16e 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -462,7 +462,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do {:user_blocked, User.blocks?(followed, follower) && deny_follow_blocked}, {_, false} <- {:user_locked, User.locked?(followed)}, {_, {:ok, follower}} <- {:follow, User.follow(follower, followed)}, - {_, {:ok, _}} <- {:follow_state_update, Utils.update_follow_state(activity, "accept")} do + {_, {:ok, _}} <- + {:follow_state_update, Utils.update_follow_state_for_all(activity, "accept")} do ActivityPub.accept(%{ to: [follower.ap_id], actor: followed, @@ -471,7 +472,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do }) else {:user_blocked, true} -> - {:ok, _} = Utils.update_follow_state(activity, "reject") + {:ok, _} = Utils.update_follow_state_for_all(activity, "reject") ActivityPub.reject(%{ to: [follower.ap_id], @@ -481,7 +482,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do }) {:follow, {:error, _}} -> - {:ok, _} = Utils.update_follow_state(activity, "reject") + {:ok, _} = Utils.update_follow_state_for_all(activity, "reject") ActivityPub.reject(%{ to: [follower.ap_id], @@ -507,7 +508,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do with actor <- Containment.get_actor(data), {:ok, %User{} = followed} <- User.get_or_fetch_by_ap_id(actor), {:ok, follow_activity} <- get_follow_activity(follow_object, followed), - {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), + {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"), %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), {:ok, _follower} = User.follow(follower, followed) do ActivityPub.accept(%{ @@ -528,7 +529,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do with actor <- Containment.get_actor(data), {:ok, %User{} = followed} <- User.get_or_fetch_by_ap_id(actor), {:ok, follow_activity} <- get_follow_activity(follow_object, followed), - {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"), + {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"), %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), {:ok, activity} <- ActivityPub.reject(%{ diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 71e166128..f5193512e 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -37,7 +37,7 @@ defmodule Pleroma.Web.CommonAPI do def accept_follow_request(follower, followed) do with {:ok, follower} <- User.follow(follower, followed), %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), - {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), + {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"), {:ok, _activity} <- ActivityPub.accept(%{ to: [follower.ap_id], @@ -51,7 +51,7 @@ defmodule Pleroma.Web.CommonAPI do def reject_follow_request(follower, followed) do with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), - {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"), + {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"), {:ok, _activity} <- ActivityPub.reject(%{ to: [follower.ap_id], -- cgit v1.2.3 From f82382de22c860c4a67a69e579e2d1fd2b186a87 Mon Sep 17 00:00:00 2001 From: Egor Date: Thu, 6 Jun 2019 12:17:49 +0000 Subject: [#943] Make the unauthenticated users limitation optional --- lib/pleroma/activity/search.ex | 8 +++++++- lib/pleroma/user/search.ex | 25 +++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/activity/search.ex b/lib/pleroma/activity/search.ex index f2fdfffe1..9ccedcd13 100644 --- a/lib/pleroma/activity/search.ex +++ b/lib/pleroma/activity/search.ex @@ -60,7 +60,13 @@ defmodule Pleroma.Activity.Search do defp maybe_restrict_local(q, %User{}), do: q # unauthenticated users can only search local activities - defp maybe_restrict_local(q, _), do: where(q, local: true) + defp maybe_restrict_local(q, _) do + if Pleroma.Config.get([:instance, :limit_unauthenticated_to_local_content], true) do + where(q, local: true) + else + q + end + end defp maybe_fetch(activities, user, search_query) do with true <- Regex.match?(~r/https?:/, search_query), diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index d5b2eaa9f..e74143cd0 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -14,7 +14,7 @@ defmodule Pleroma.User.Search do # Strip the beginning @ off if there is a query query = String.trim_leading(query, "@") - if match?(%User{}, for_user) and resolve, do: User.get_or_fetch(query) + maybe_resolve(resolve, for_user, query) {:ok, results} = Repo.transaction(fn -> @@ -28,6 +28,16 @@ defmodule Pleroma.User.Search do results end + defp maybe_resolve(true, %User{}, query) do + User.get_or_fetch(query) + end + + defp maybe_resolve(true, _, query) do + unless restrict_local?(), do: User.get_or_fetch(query) + end + + defp maybe_resolve(_, _, _), do: :noop + defp search_query(query, for_user) do query |> union_query() @@ -39,6 +49,10 @@ defmodule Pleroma.User.Search do |> maybe_restrict_local(for_user) end + defp restrict_local? do + Pleroma.Config.get([:instance, :limit_unauthenticated_to_local_content], true) + end + defp union_query(query) do fts_subquery = fts_search_subquery(query) trigram_subquery = trigram_search_subquery(query) @@ -52,7 +66,14 @@ defmodule Pleroma.User.Search do # unauthenticated users can only search local activities defp maybe_restrict_local(q, %User{}), do: q - defp maybe_restrict_local(q, _), do: where(q, [u], u.local == true) + + defp maybe_restrict_local(q, _) do + if restrict_local?() do + where(q, [u], u.local == true) + else + q + end + end defp boost_search_rank_query(query, nil), do: query -- cgit v1.2.3 From 9ae8f012a516495387aed07a73c46f91df0ad59d Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 6 Jun 2019 16:36:56 +0300 Subject: Switch to manual Supervisor child specifications instead of Supervisor.Spec Supervisor.Spec is deprecated and causes warnings on Elixir master, see https://hexdocs.pm/elixir/Supervisor.Spec.html --- lib/pleroma/application.ex | 205 ++++++++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 85 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 76df3945e..69a8a5761 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -4,7 +4,6 @@ defmodule Pleroma.Application do use Application - import Supervisor.Spec @name Mix.Project.config()[:name] @version Mix.Project.config()[:version] @@ -31,96 +30,127 @@ defmodule Pleroma.Application do children = [ # Start the Ecto repository - supervisor(Pleroma.Repo, []), - worker(Pleroma.Emoji, []), - worker(Pleroma.Captcha, []), - worker( - Cachex, - [ - :used_captcha_cache, - [ - ttl_interval: :timer.seconds(Pleroma.Config.get!([Pleroma.Captcha, :seconds_valid])) - ] - ], - id: :cachex_used_captcha_cache - ), - worker( - Cachex, - [ - :user_cache, - [ - default_ttl: 25_000, - ttl_interval: 1000, - limit: 2500 - ] - ], - id: :cachex_user - ), - worker( - Cachex, - [ - :object_cache, - [ - default_ttl: 25_000, - ttl_interval: 1000, - limit: 2500 - ] - ], - id: :cachex_object - ), - worker( - Cachex, - [ - :rich_media_cache, - [ - default_ttl: :timer.minutes(120), - limit: 5000 - ] - ], - id: :cachex_rich_media - ), - worker( - Cachex, - [ - :scrubber_cache, - [ - limit: 2500 - ] - ], - id: :cachex_scrubber - ), - worker( - Cachex, - [ - :idempotency_cache, - [ - expiration: - expiration( - default: :timer.seconds(6 * 60 * 60), - interval: :timer.seconds(60) - ), - limit: 2500 - ] - ], - id: :cachex_idem - ), - worker(Pleroma.FlakeId, []), - worker(Pleroma.ScheduledActivityWorker, []) + %{id: Pleroma.Repo, start: {Pleroma.Repo, :start_link, []}, type: :supervisor}, + %{id: Pleroma.Emoji, start: {Pleroma.Emoji, :start_link, []}}, + %{id: Pleroma.Captcha, start: {Pleroma.Captcha, :start_link, []}}, + %{ + id: :cachex_used_captcha_cache, + start: + {Cachex, :start_link, + [ + :used_captcha_cache, + [ + ttl_interval: + :timer.seconds(Pleroma.Config.get!([Pleroma.Captcha, :seconds_valid])) + ] + ]} + }, + %{ + id: :cachex_user, + start: + {Cachex, :start_link, + [ + :user_cache, + [ + default_ttl: 25_000, + ttl_interval: 1000, + limit: 2500 + ] + ]} + }, + %{ + id: :cachex_object, + start: + {Cachex, :start_link, + [ + :object_cache, + [ + default_ttl: 25_000, + ttl_interval: 1000, + limit: 2500 + ] + ]} + }, + %{ + id: :cachex_rich_media, + start: + {Cachex, :start_link, + [ + :rich_media_cache, + [ + default_ttl: :timer.minutes(120), + limit: 5000 + ] + ]} + }, + %{ + id: :cachex_scrubber, + start: + {Cachex, :start_link, + [ + :scrubber_cache, + [ + limit: 2500 + ] + ]} + }, + %{ + id: :cachex_idem, + start: + {Cachex, :start_link, + [ + :idempotency_cache, + [ + expiration: + expiration( + default: :timer.seconds(6 * 60 * 60), + interval: :timer.seconds(60) + ), + limit: 2500 + ] + ]} + }, + %{id: Pleroma.FlakeId, start: {Pleroma.FlakeId, :start_link, []}}, + %{ + id: Pleroma.ScheduledActivityWorker, + start: {Pleroma.ScheduledActivityWorker, :start_link, []} + } ] ++ hackney_pool_children() ++ [ - worker(Pleroma.Web.Federator.RetryQueue, []), - worker(Pleroma.Web.OAuth.Token.CleanWorker, []), - worker(Pleroma.Stats, []), - worker(Task, [&Pleroma.Web.Push.init/0], restart: :temporary, id: :web_push_init), - worker(Task, [&Pleroma.Web.Federator.init/0], restart: :temporary, id: :federator_init) + %{ + id: Pleroma.Web.Federator.RetryQueue, + start: {Pleroma.Web.Federator.RetryQueue, :start_link, []} + }, + %{ + id: Pleroma.Web.OAuth.Token.CleanWorker, + start: {Pleroma.Web.OAuth.Token.CleanWorker, :start_link, []} + }, + %{ + id: Pleroma.Stats, + start: {Pleroma.Stats, :start_link, []} + }, + %{ + id: :web_push_init, + start: {Task, :start_link, [&Pleroma.Web.Push.init/0]}, + restart: :temporary + }, + %{ + id: :federator_init, + start: {Task, :start_link, [&Pleroma.Web.Federator.init/0]}, + restart: :temporary + } ] ++ streamer_child() ++ chat_child() ++ [ # Start the endpoint when the application starts - supervisor(Pleroma.Web.Endpoint, []), - worker(Pleroma.Gopher.Server, []) + %{ + id: Pleroma.Web.Endpoint, + start: {Pleroma.Web.Endpoint, :start_link, []}, + type: :supervisor + }, + %{id: Pleroma.Gopher.Server, start: {Pleroma.Gopher.Server, :start_link, []}} ] # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html @@ -169,12 +199,17 @@ defmodule Pleroma.Application do defp chat_child, do: [] else defp streamer_child do - [worker(Pleroma.Web.Streamer, [])] + [%{id: Pleroma.Web.Streamer, start: {Pleroma.Web.Streamer, :start_link, []}}] end defp chat_child do if Pleroma.Config.get([:chat, :enabled]) do - [worker(Pleroma.Web.ChatChannel.ChatChannelState, [])] + [ + %{ + id: Pleroma.Web.ChatChannel.ChatChannelState, + start: {Pleroma.Web.ChatChannel.ChatChannelState, :start_link, []} + } + ] else [] end -- cgit v1.2.3 From cb2bcee842f07358db4d37de1b9a32c9d69d487c Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 6 Jun 2019 16:18:27 +0200 Subject: User Search: Boost friends more strongly. --- lib/pleroma/user/search.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index e74143cd0..add6a0bbf 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -86,8 +86,8 @@ defmodule Pleroma.User.Search do search_rank: fragment( """ - CASE WHEN (?) THEN (?) * 1.3 - WHEN (?) THEN (?) * 1.2 + CASE WHEN (?) THEN 0.5 + (?) * 1.3 + WHEN (?) THEN 0.5 + (?) * 1.2 WHEN (?) THEN (?) * 1.1 ELSE (?) END """, -- cgit v1.2.3