Contain search for unauthenticated users
This commit is contained in:
parent
e4babb1c9f
commit
93397fce3d
4 changed files with 117 additions and 59 deletions
|
@ -343,4 +343,6 @@ def restrict_deactivated_users(query) do
|
|||
)
|
||||
)
|
||||
end
|
||||
|
||||
defdelegate search(user, query), to: Pleroma.Activity.Search
|
||||
end
|
||||
|
|
75
lib/pleroma/activity/search.ex
Normal file
75
lib/pleroma/activity/search.ex
Normal file
|
@ -0,0 +1,75 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# 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
|
|
@ -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 @@ def unsubscribe(%{assigns: %{user: user}} = conn, %{"id" => id}) 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 @@ def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) 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
|
||||
|
|
|
@ -99,4 +99,42 @@ test "when association is not loaded" do
|
|||
assert Activity.get_bookmark(queried_activity, user) == bookmark
|
||||
end
|
||||
end
|
||||
|
||||
describe "search" do
|
||||
setup do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
params = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"actor" => "http://mastodon.example.org/users/admin",
|
||||
"type" => "Create",
|
||||
"id" => "http://mastodon.example.org/users/admin/activities/1",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "find me!",
|
||||
"id" => "http://mastodon.example.org/users/admin/objects/1",
|
||||
"attributedTo" => "http://mastodon.example.org/users/admin"
|
||||
},
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
}
|
||||
|
||||
{:ok, local_activity} = Pleroma.Web.CommonAPI.post(user, %{"status" => "find me!"})
|
||||
{:ok, remote_activity} = Pleroma.Web.Federator.incoming_ap_doc(params)
|
||||
%{local_activity: local_activity, remote_activity: remote_activity, user: user}
|
||||
end
|
||||
|
||||
test "find local and remote statuses for authenticated users", %{
|
||||
local_activity: local_activity,
|
||||
remote_activity: remote_activity,
|
||||
user: user
|
||||
} do
|
||||
assert [^remote_activity, ^local_activity] = Activity.search(user, "find me")
|
||||
end
|
||||
|
||||
test "find only local statuses for unauthenticated users", %{local_activity: local_activity} do
|
||||
assert [^local_activity] = Activity.search(nil, "find me")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue