forked from AkkomaGang/akkoma
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
|
end
|
||||||
|
|
||||||
|
defdelegate search(user, query), to: Pleroma.Activity.Search
|
||||||
end
|
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.HTTP
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Object.Fetcher
|
|
||||||
alias Pleroma.Pagination
|
alias Pleroma.Pagination
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.ScheduledActivity
|
alias Pleroma.ScheduledActivity
|
||||||
|
@ -1125,64 +1124,9 @@ def unsubscribe(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
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
|
def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
||||||
accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user)
|
accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user)
|
||||||
|
statuses = Activity.search(user, query)
|
||||||
statuses = status_search(user, query)
|
|
||||||
|
|
||||||
tags_path = Web.base_url() <> "/tag/"
|
tags_path = Web.base_url() <> "/tag/"
|
||||||
|
|
||||||
tags =
|
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
|
def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
||||||
accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user)
|
accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user)
|
||||||
|
statuses = Activity.search(user, query)
|
||||||
statuses = status_search(user, query)
|
|
||||||
|
|
||||||
tags =
|
tags =
|
||||||
query
|
query
|
||||||
|
|
|
@ -99,4 +99,42 @@ test "when association is not loaded" do
|
||||||
assert Activity.get_bookmark(queried_activity, user) == bookmark
|
assert Activity.get_bookmark(queried_activity, user) == bookmark
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
Loading…
Reference in a new issue