Merge branch 'develop' into issue/1383

This commit is contained in:
Maksim Pechnikov 2019-11-28 21:26:56 +03:00
commit b7c449118b
32 changed files with 510 additions and 211 deletions

View file

@ -303,4 +303,17 @@ defmodule Pleroma.Activity do
end
defdelegate search(user, query, options \\ []), to: Pleroma.Activity.Search
def direct_conversation_id(activity, for_user) do
alias Pleroma.Conversation.Participation
with %{data: %{"context" => context}} when is_binary(context) <- activity,
%Pleroma.Conversation{} = conversation <- Pleroma.Conversation.get_for_ap_id(context),
%Participation{id: participation_id} <-
Participation.for_user_and_conversation(for_user, conversation) do
participation_id
else
_ -> nil
end
end
end

View file

@ -17,8 +17,14 @@ defmodule Pleroma.Application do
def repository, do: @repository
def user_agent do
info = "#{Pleroma.Web.base_url()} <#{Pleroma.Config.get([:instance, :email], "")}>"
named_version() <> "; " <> info
case Pleroma.Config.get([:http, :user_agent], :default) do
:default ->
info = "#{Pleroma.Web.base_url()} <#{Pleroma.Config.get([:instance, :email], "")}>"
named_version() <> "; " <> info
custom ->
custom
end
end
# See http://elixir-lang.org/docs/stable/elixir/Application.html

View file

@ -255,4 +255,8 @@ defmodule Pleroma.Object do
|> Object.change(%{data: Map.merge(data || %{}, attrs)})
|> Repo.update()
end
def local?(%Object{data: %{"id" => id}}) do
String.starts_with?(id, Pleroma.Web.base_url() <> "/")
end
end

View file

@ -49,7 +49,7 @@ defmodule Pleroma.Object.Fetcher do
end
def refetch_object(%Object{data: %{"id" => id}} = object) do
with {:local, false} <- {:local, String.starts_with?(id, Pleroma.Web.base_url() <> "/")},
with {:local, false} <- {:local, Object.local?(object)},
{:ok, data} <- fetch_and_contain_remote_object_from_id(id),
{:ok, object} <- reinject_object(object, data) do
{:ok, object}

View file

@ -177,20 +177,6 @@ defmodule Pleroma.User do
def ap_following(%User{following_address: fa}) when is_binary(fa), do: fa
def ap_following(%User{} = user), do: "#{ap_id(user)}/following"
def user_info(%User{} = user, args \\ %{}) do
following_count = Map.get(args, :following_count, user.following_count)
follower_count = Map.get(args, :follower_count, user.follower_count)
%{
note_count: user.note_count,
locked: user.locked,
confirmation_pending: user.confirmation_pending,
default_scope: user.default_scope,
follower_count: follower_count,
following_count: following_count
}
end
def follow_state(%User{} = user, %User{} = target) do
case Utils.fetch_latest_follow(user, target) do
%{data: %{"state" => state}} -> state
@ -209,10 +195,6 @@ defmodule Pleroma.User do
Cachex.put(:user_cache, "follow_state:#{user_ap_id}|#{target_ap_id}", state)
end
def set_info_cache(user, args) do
Cachex.put(:user_cache, "user_info:#{user.id}", user_info(user, args))
end
@spec restrict_deactivated(Ecto.Query.t()) :: Ecto.Query.t()
def restrict_deactivated(query) do
from(u in query, where: u.deactivated != ^true)
@ -614,7 +596,6 @@ defmodule Pleroma.User do
def set_cache(%User{} = user) do
Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
Cachex.put(:user_cache, "nickname:#{user.nickname}", user)
Cachex.put(:user_cache, "user_info:#{user.id}", user_info(user))
{:ok, user}
end
@ -633,7 +614,6 @@ defmodule Pleroma.User do
def invalidate_cache(user) do
Cachex.del(:user_cache, "ap_id:#{user.ap_id}")
Cachex.del(:user_cache, "nickname:#{user.nickname}")
Cachex.del(:user_cache, "user_info:#{user.id}")
end
def get_cached_by_ap_id(ap_id) do
@ -701,11 +681,6 @@ defmodule Pleroma.User do
get_by_nickname(nickname_or_email) || get_by_email(nickname_or_email)
end
def get_cached_user_info(user) do
key = "user_info:#{user.id}"
Cachex.fetch!(:user_cache, key, fn -> user_info(user) end)
end
def fetch_by_nickname(nickname), do: ActivityPub.make_user_from_nickname(nickname)
def get_or_fetch_by_nickname(nickname) do

View file

@ -734,6 +734,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> Enum.reverse()
end
def fetch_instance_activities(params) do
params =
params
|> Map.put("type", ["Create", "Announce"])
|> Map.put("instance", params["instance"])
|> Map.put("whole_db", true)
fetch_activities([Pleroma.Constants.as_public()], params, :offset)
|> Enum.reverse()
end
defp user_activities_recipients(%{"godmode" => true}) do
[]
end
@ -961,6 +972,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_muted_reblogs(query, _), do: query
defp restrict_instance(query, %{"instance" => instance}) do
users =
from(
u in User,
select: u.ap_id,
where: fragment("? LIKE ?", u.nickname, ^"%@#{instance}")
)
|> Repo.all()
from(activity in query, where: activity.actor in ^users)
end
defp restrict_instance(query, _), do: query
defp exclude_poll_votes(query, %{"include_poll_votes" => true}), do: query
defp exclude_poll_votes(query, _) do
@ -1041,6 +1066,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_reblogs(opts)
|> restrict_pinned(opts)
|> restrict_muted_reblogs(opts)
|> restrict_instance(opts)
|> Activity.restrict_deactivated_users()
|> exclude_poll_votes(opts)
|> exclude_visibility(opts)

View file

@ -45,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
def user(conn, %{"nickname" => nickname}) do
with %User{} = user <- User.get_cached_by_nickname(nickname),
with %User{local: true} = user <- User.get_cached_by_nickname(nickname),
{:ok, user} <- User.ensure_keys_present(user) do
conn
|> put_resp_content_type("application/activity+json")
@ -53,6 +53,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> render("user.json", %{user: user})
else
nil -> {:error, :not_found}
%{local: false} -> {:error, :not_found}
end
end

View file

@ -903,7 +903,13 @@ defmodule Pleroma.Web.ActivityPub.Utils do
def strip_report_status_data(activity) do
[actor | reported_activities] = activity.data["object"]
stripped_activities = Enum.map(reported_activities, & &1["id"])
stripped_activities =
Enum.map(reported_activities, fn
act when is_map(act) -> act["id"]
act when is_binary(act) -> act
end)
new_data = put_in(activity.data, ["object"], [actor | stripped_activities])
{:ok, %{activity | data: new_data}}

View file

@ -227,6 +227,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
end
end
def list_instance_statuses(conn, %{"instance" => instance} = params) do
{page, page_size} = page_params(params)
activities =
ActivityPub.fetch_instance_activities(%{
"instance" => instance,
"limit" => page_size,
"offset" => (page - 1) * page_size
})
conn
|> put_view(StatusView)
|> render("index.json", %{activities: activities, as: :activity})
end
def list_user_statuses(conn, %{"nickname" => nickname} = params) do
godmode = params["godmode"] == "true" || params["godmode"] == true

View file

@ -71,18 +71,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
image = User.avatar_url(user) |> MediaProxy.url()
header = User.banner_url(user) |> MediaProxy.url()
user_info = User.get_cached_user_info(user)
following_count =
if !user.hide_follows_count or !user.hide_follows or opts[:for] == user do
user_info.following_count
user.following_count || 0
else
0
end
followers_count =
if !user.hide_followers_count or !user.hide_followers or opts[:for] == user do
user_info.follower_count
user.follower_count || 0
else
0
end
@ -144,7 +143,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
# Pleroma extension
pleroma: %{
confirmation_pending: user_info.confirmation_pending,
confirmation_pending: user.confirmation_pending,
tags: user.tags,
hide_followers_count: user.hide_followers_count,
hide_follows_count: user.hide_follows_count,
@ -157,7 +156,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
}
}
|> maybe_put_role(user, opts[:for])
|> maybe_put_settings(user, opts[:for], user_info)
|> maybe_put_settings(user, opts[:for], opts)
|> maybe_put_notification_settings(user, opts[:for])
|> maybe_put_settings_store(user, opts[:for], opts)
|> maybe_put_chat_token(user, opts[:for], opts)
@ -191,7 +190,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
data,
%User{id: user_id} = user,
%User{id: user_id},
_user_info
_opts
) do
data
|> Kernel.put_in([:source, :privacy], user.default_scope)

View file

@ -9,8 +9,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
alias Pleroma.Activity
alias Pleroma.ActivityExpiration
alias Pleroma.Conversation
alias Pleroma.Conversation.Participation
alias Pleroma.HTML
alias Pleroma.Object
alias Pleroma.Repo
@ -245,12 +243,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
direct_conversation_id =
with {_, nil} <- {:direct_conversation_id, opts[:direct_conversation_id]},
{_, true} <- {:include_id, opts[:with_direct_conversation_id]},
{_, %User{} = for_user} <- {:for_user, opts[:for]},
%{data: %{"context" => context}} when is_binary(context) <- activity,
%Conversation{} = conversation <- Conversation.get_for_ap_id(context),
%Participation{id: participation_id} <-
Participation.for_user_and_conversation(for_user, conversation) do
participation_id
{_, %User{} = for_user} <- {:for_user, opts[:for]} do
Activity.direct_conversation_id(activity, for_user)
else
{:direct_conversation_id, participation_id} when is_integer(participation_id) ->
participation_id

View file

@ -11,7 +11,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do
alias Pleroma.Plugs.RateLimiter
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPubController
alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Metadata.PlayerView
@ -38,11 +37,9 @@ defmodule Pleroma.Web.OStatus.OStatusController do
with id <- o_status_url(conn, :object, uuid),
{_, %Activity{} = activity} <-
{:activity, Activity.get_create_by_object_ap_id_with_object(id)},
{_, true} <- {:public?, Visibility.is_public?(activity)},
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
{_, true} <- {:public?, Visibility.is_public?(activity)} do
case format do
"html" -> redirect(conn, to: "/notice/#{activity.id}")
_ -> represent_activity(conn, nil, activity, user)
_ -> redirect(conn, to: "/notice/#{activity.id}")
end
else
reason when reason in [{:public?, false}, {:activity, nil}] ->
@ -61,11 +58,9 @@ defmodule Pleroma.Web.OStatus.OStatusController do
def activity(%{assigns: %{format: format}} = conn, %{"uuid" => uuid}) do
with id <- o_status_url(conn, :activity, uuid),
{_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
{_, true} <- {:public?, Visibility.is_public?(activity)},
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
{_, true} <- {:public?, Visibility.is_public?(activity)} do
case format do
"html" -> redirect(conn, to: "/notice/#{activity.id}")
_ -> represent_activity(conn, format, activity, user)
_ -> redirect(conn, to: "/notice/#{activity.id}")
end
else
reason when reason in [{:public?, false}, {:activity, nil}] ->
@ -81,7 +76,15 @@ defmodule Pleroma.Web.OStatus.OStatusController do
{_, true} <- {:public?, Visibility.is_public?(activity)},
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
cond do
format == "html" && activity.data["type"] == "Create" ->
format in ["json", "activity+json"] ->
if activity.local do
%{data: %{"id" => redirect_url}} = Object.normalize(activity)
redirect(conn, external: redirect_url)
else
{:error, :not_found}
end
activity.data["type"] == "Create" ->
%Object{} = object = Object.normalize(activity)
RedirectController.redirector_with_meta(
@ -94,11 +97,8 @@ defmodule Pleroma.Web.OStatus.OStatusController do
}
)
format == "html" ->
RedirectController.redirector(conn, nil)
true ->
represent_activity(conn, format, activity, user)
RedirectController.redirector(conn, nil)
end
else
reason when reason in [{:public?, false}, {:activity, nil}] ->
@ -135,24 +135,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do
end
end
defp represent_activity(
conn,
"activity+json",
%Activity{data: %{"type" => "Create"}} = activity,
_user
) do
object = Object.normalize(activity)
conn
|> put_resp_header("content-type", "application/activity+json")
|> put_view(ObjectView)
|> render("object.json", %{object: object})
end
defp represent_activity(_conn, _, _, _) do
{:error, :not_found}
end
def errors(conn, {:error, :not_found}) do
render_error(conn, :not_found, "Not found")
end

View file

@ -33,6 +33,8 @@ defmodule Pleroma.Web.Push.Impl do
gcm_api_key = Application.get_env(:web_push_encryption, :gcm_api_key)
avatar_url = User.avatar_url(actor)
object = Object.normalize(activity)
user = User.get_cached_by_id(user_id)
direct_conversation_id = Activity.direct_conversation_id(activity, user)
for subscription <- fetch_subsriptions(user_id),
get_in(subscription.data, ["alerts", type]) do
@ -45,7 +47,8 @@ defmodule Pleroma.Web.Push.Impl do
icon: avatar_url,
preferred_locale: "en",
pleroma: %{
activity_id: activity_id
activity_id: activity_id,
direct_conversation_id: direct_conversation_id
}
}
|> Jason.encode!()

View file

@ -178,6 +178,8 @@ defmodule Pleroma.Web.Router do
get("/users/:nickname", AdminAPIController, :user_show)
get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
get("/instances/:instance/statuses", AdminAPIController, :list_instance_statuses)
patch("/users/confirm_email", AdminAPIController, :confirm_email)
patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email)