Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into alexgleason/pleroma-confirm-users

This commit is contained in:
lain 2021-01-05 13:33:57 +01:00
commit fee0c6a2cb
28 changed files with 303 additions and 128 deletions

View file

@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- **Breaking:** Changed `mix pleroma.user toggle_confirmed` to `mix pleroma.user confirm` - **Breaking:** Changed `mix pleroma.user toggle_confirmed` to `mix pleroma.user confirm`
- Search: When using Postgres 11+, Pleroma will use the `websearch_to_tsvector` function to parse search queries. - Search: When using Postgres 11+, Pleroma will use the `websearch_to_tsvector` function to parse search queries.
- Emoji: Support the full Unicode 13.1 set of Emoji for reactions, plus regional indicators. - Emoji: Support the full Unicode 13.1 set of Emoji for reactions, plus regional indicators.
- Admin API: Reports now ordered by newest
### Added ### Added
@ -29,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mix tasks to help with displaying and removing ConfigDB entries. See `mix pleroma.config`. - Mix tasks to help with displaying and removing ConfigDB entries. See `mix pleroma.config`.
- OAuth form improvements: users are remembered by their cookie, the CSS is overridable by the admin, and the style has been improved. - OAuth form improvements: users are remembered by their cookie, the CSS is overridable by the admin, and the style has been improved.
- OAuth improvements and fixes: more secure session-based authentication (by token that could be revoked anytime), ability to revoke belonging OAuth token from any client etc. - OAuth improvements and fixes: more secure session-based authentication (by token that could be revoked anytime), ability to revoke belonging OAuth token from any client etc.
- Ability to set ActivityPub aliases for follower migration.
<details> <details>
<summary>API Changes</summary> <summary>API Changes</summary>

View file

@ -134,6 +134,10 @@
config :pleroma, :cachex, provider: Pleroma.CachexMock config :pleroma, :cachex, provider: Pleroma.CachexMock
config :pleroma, :side_effects,
ap_streamer: Pleroma.Web.ActivityPub.ActivityPubMock,
logger: Pleroma.LoggerMock
if File.exists?("./config/test.secret.exs") do if File.exists?("./config/test.secret.exs") do
import_config "test.secret.exs" import_config "test.secret.exs"
else else

View file

@ -1123,6 +1123,7 @@ Loads json generated from `config/descriptions.exs`.
```json ```json
[ [
{ {
"id": 1234,
"data": { "data": {
"actor": { "actor": {
"id": 1, "id": 1,

View file

@ -206,6 +206,7 @@ Additional parameters can be added to the JSON body/Form data:
- `pleroma_settings_store` - Opaque user settings to be saved on the backend. - `pleroma_settings_store` - Opaque user settings to be saved on the backend.
- `skip_thread_containment` - if true, skip filtering out broken threads - `skip_thread_containment` - if true, skip filtering out broken threads
- `allow_following_move` - if true, allows automatically follow moved following accounts - `allow_following_move` - if true, allows automatically follow moved following accounts
- `also_known_as` - array of ActivityPub IDs, needed for following move
- `pleroma_background_image` - sets the background image of the user. Can be set to "" (an empty string) to reset. - `pleroma_background_image` - sets the background image of the user. Can be set to "" (an empty string) to reset.
- `discoverable` - if true, external services (search bots) etc. are allowed to index / list the account (regardless of this setting, user will still appear in regular search results). - `discoverable` - if true, external services (search bots) etc. are allowed to index / list the account (regardless of this setting, user will still appear in regular search results).
- `actor_type` - the type of this account. - `actor_type` - the type of this account.

7
lib/pleroma/logging.ex Normal file
View file

@ -0,0 +1,7 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Logging do
@callback error(String.t()) :: any()
end

View file

@ -142,7 +142,7 @@ defmodule Pleroma.User do
field(:allow_following_move, :boolean, default: true) field(:allow_following_move, :boolean, default: true)
field(:skip_thread_containment, :boolean, default: false) field(:skip_thread_containment, :boolean, default: false)
field(:actor_type, :string, default: "Person") field(:actor_type, :string, default: "Person")
field(:also_known_as, {:array, :string}, default: []) field(:also_known_as, {:array, ObjectValidators.ObjectID}, default: [])
field(:inbox, :string) field(:inbox, :string)
field(:shared_inbox, :string) field(:shared_inbox, :string)
field(:accepts_chat_messages, :boolean, default: nil) field(:accepts_chat_messages, :boolean, default: nil)
@ -515,6 +515,7 @@ def update_changeset(struct, params \\ %{}) do
:hide_follows_count, :hide_follows_count,
:hide_favorites, :hide_favorites,
:allow_following_move, :allow_following_move,
:also_known_as,
:background, :background,
:show_role, :show_role,
:skip_thread_containment, :skip_thread_containment,
@ -523,7 +524,6 @@ def update_changeset(struct, params \\ %{}) do
:pleroma_settings_store, :pleroma_settings_store,
:is_discoverable, :is_discoverable,
:actor_type, :actor_type,
:also_known_as,
:accepts_chat_messages :accepts_chat_messages
] ]
) )

View file

@ -33,6 +33,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
require Pleroma.Constants require Pleroma.Constants
@behaviour Pleroma.Web.ActivityPub.ActivityPub.Persisting @behaviour Pleroma.Web.ActivityPub.ActivityPub.Persisting
@behaviour Pleroma.Web.ActivityPub.ActivityPub.Streaming
defp get_recipients(%{"type" => "Create"} = data) do defp get_recipients(%{"type" => "Create"} = data) do
to = Map.get(data, "to", []) to = Map.get(data, "to", [])
@ -224,6 +225,7 @@ def stream_out_participations(participations) do
Streamer.stream("participation", participations) Streamer.stream("participation", participations)
end end
@impl true
def stream_out_participations(%Object{data: %{"context" => context}}, user) do def stream_out_participations(%Object{data: %{"context" => context}}, user) do
with %Conversation{} = conversation <- Conversation.get_for_ap_id(context) do with %Conversation{} = conversation <- Conversation.get_for_ap_id(context) do
conversation = Repo.preload(conversation, :participations) conversation = Repo.preload(conversation, :participations)
@ -240,8 +242,10 @@ def stream_out_participations(%Object{data: %{"context" => context}}, user) do
end end
end end
@impl true
def stream_out_participations(_, _), do: :noop def stream_out_participations(_, _), do: :noop
@impl true
def stream_out(%Activity{data: %{"type" => data_type}} = activity) def stream_out(%Activity{data: %{"type" => data_type}} = activity)
when data_type in ["Create", "Announce", "Delete"] do when data_type in ["Create", "Announce", "Delete"] do
activity activity
@ -249,6 +253,7 @@ def stream_out(%Activity{data: %{"type" => data_type}} = activity)
|> Streamer.stream(activity) |> Streamer.stream(activity)
end end
@impl true
def stream_out(_activity) do def stream_out(_activity) do
:noop :noop
end end

View file

@ -0,0 +1,12 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ActivityPub.Streaming do
alias Pleroma.Activity
alias Pleroma.Object
alias Pleroma.User
@callback stream_out(Activity.t()) :: any()
@callback stream_out_participations(Object.t(), User.t()) :: any()
end

View file

@ -28,6 +28,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
require Logger require Logger
@cachex Pleroma.Config.get([:cachex, :provider], Cachex) @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@ap_streamer Pleroma.Config.get([:side_effects, :ap_streamer], ActivityPub)
@logger Pleroma.Config.get([:side_effects, :logger], Logger)
@behaviour Pleroma.Web.ActivityPub.SideEffects.Handling @behaviour Pleroma.Web.ActivityPub.SideEffects.Handling
@ -287,12 +289,12 @@ def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object,
MessageReference.delete_for_object(deleted_object) MessageReference.delete_for_object(deleted_object)
ActivityPub.stream_out(object) @ap_streamer.stream_out(object)
ActivityPub.stream_out_participations(deleted_object, user) @ap_streamer.stream_out_participations(deleted_object, user)
:ok :ok
else else
{:actor, _} -> {:actor, _} ->
Logger.error("The object doesn't have an actor: #{inspect(deleted_object)}") @logger.error("The object doesn't have an actor: #{inspect(deleted_object)}")
:no_object_actor :no_object_actor
end end

View file

@ -112,7 +112,8 @@ def render("user.json", %{user: user}) do
"tag" => emoji_tags, "tag" => emoji_tags,
# Note: key name is indeed "discoverable" (not an error) # Note: key name is indeed "discoverable" (not an error)
"discoverable" => user.is_discoverable, "discoverable" => user.is_discoverable,
"capabilities" => capabilities "capabilities" => capabilities,
"alsoKnownAs" => user.also_known_as
} }
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
|> Map.merge(maybe_make_image(&User.banner_url/2, "image", user)) |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))

View file

@ -21,6 +21,7 @@ def render("show.json", %{log_entry: log_entry}) do
|> DateTime.to_unix() |> DateTime.to_unix()
%{ %{
id: log_entry.id,
data: log_entry.data, data: log_entry.data,
time: time, time: time,
message: ModerationLog.get_log_entry_message(log_entry) message: ModerationLog.get_log_entry_message(log_entry)

View file

@ -19,8 +19,7 @@ def render("index.json", %{reports: reports}) do
reports: reports:
reports[:items] reports[:items]
|> Enum.map(&Report.extract_report_info/1) |> Enum.map(&Report.extract_report_info/1)
|> Enum.map(&render(__MODULE__, "show.json", &1)) |> Enum.map(&render(__MODULE__, "show.json", &1)),
|> Enum.reverse(),
total: reports[:total] total: reports[:total]
} }
end end

View file

@ -614,6 +614,12 @@ defp update_credentials_request do
nullable: true, nullable: true,
description: "Allows automatically follow moved following accounts" description: "Allows automatically follow moved following accounts"
}, },
also_known_as: %Schema{
type: :array,
items: %Schema{type: :string},
nullable: true,
description: "List of alternate ActivityPub IDs"
},
pleroma_background_image: %Schema{ pleroma_background_image: %Schema{
type: :string, type: :string,
nullable: true, nullable: true,
@ -644,6 +650,7 @@ defp update_credentials_request do
pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}}, pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
skip_thread_containment: false, skip_thread_containment: false,
allow_following_move: false, allow_following_move: false,
also_known_as: ["https://foo.bar/users/foo"],
discoverable: false, discoverable: false,
actor_type: "Person" actor_type: "Person"
} }

View file

@ -40,6 +40,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
pleroma: %Schema{ pleroma: %Schema{
type: :object, type: :object,
properties: %{ properties: %{
ap_id: %Schema{type: :string},
also_known_as: %Schema{type: :array, items: %Schema{type: :string}},
allow_following_move: %Schema{ allow_following_move: %Schema{
type: :boolean, type: :boolean,
description: "whether the user allows automatically follow moved following accounts" description: "whether the user allows automatically follow moved following accounts"

View file

@ -184,6 +184,7 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p
:show_role, :show_role,
:skip_thread_containment, :skip_thread_containment,
:allow_following_move, :allow_following_move,
:also_known_as,
:accepts_chat_messages :accepts_chat_messages
] ]
|> Enum.reduce(%{}, fn key, acc -> |> Enum.reduce(%{}, fn key, acc ->
@ -207,6 +208,7 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p
if bot, do: {:ok, "Service"}, else: {:ok, "Person"} if bot, do: {:ok, "Service"}, else: {:ok, "Person"}
end) end)
|> Maps.put_if_present(:actor_type, params[:actor_type]) |> Maps.put_if_present(:actor_type, params[:actor_type])
|> Maps.put_if_present(:also_known_as, params[:also_known_as])
# Note: param name is indeed :locked (not an error) # Note: param name is indeed :locked (not an error)
|> Maps.put_if_present(:is_locked, params[:locked]) |> Maps.put_if_present(:is_locked, params[:locked])
# Note: param name is indeed :discoverable (not an error) # Note: param name is indeed :discoverable (not an error)

View file

@ -265,6 +265,7 @@ defp do_render("show.json", %{user: user} = opts) do
# Pleroma extension # Pleroma extension
pleroma: %{ pleroma: %{
ap_id: user.ap_id, ap_id: user.ap_id,
also_known_as: user.also_known_as,
confirmation_pending: user.confirmation_pending, confirmation_pending: user.confirmation_pending,
tags: user.tags, tags: user.tags,
hide_followers_count: user.hide_followers_count, hide_followers_count: user.hide_followers_count,

View file

@ -58,12 +58,16 @@ defp gather_links(%User{} = user) do
] ++ Publisher.gather_webfinger_links(user) ] ++ Publisher.gather_webfinger_links(user)
end end
defp gather_aliases(%User{} = user) do
[user.ap_id | user.also_known_as]
end
def represent_user(user, "JSON") do def represent_user(user, "JSON") do
{:ok, user} = User.ensure_keys_present(user) {:ok, user} = User.ensure_keys_present(user)
%{ %{
"subject" => "acct:#{user.nickname}@#{Pleroma.Web.Endpoint.host()}", "subject" => "acct:#{user.nickname}@#{Pleroma.Web.Endpoint.host()}",
"aliases" => [user.ap_id], "aliases" => gather_aliases(user),
"links" => gather_links(user) "links" => gather_links(user)
} }
end end
@ -71,6 +75,11 @@ def represent_user(user, "JSON") do
def represent_user(user, "XML") do def represent_user(user, "XML") do
{:ok, user} = User.ensure_keys_present(user) {:ok, user} = User.ensure_keys_present(user)
aliases =
user
|> gather_aliases()
|> Enum.map(&{:Alias, &1})
links = links =
gather_links(user) gather_links(user)
|> Enum.map(fn link -> {:Link, link} end) |> Enum.map(fn link -> {:Link, link} end)
@ -79,9 +88,8 @@ def represent_user(user, "XML") do
:XRD, :XRD,
%{xmlns: "http://docs.oasis-open.org/ns/xri/xrd-1.0"}, %{xmlns: "http://docs.oasis-open.org/ns/xri/xrd-1.0"},
[ [
{:Subject, "acct:#{user.nickname}@#{Pleroma.Web.Endpoint.host()}"}, {:Subject, "acct:#{user.nickname}@#{Pleroma.Web.Endpoint.host()}"}
{:Alias, user.ap_id} ] ++ aliases ++ links
] ++ links
} }
|> XmlBuilder.to_doc() |> XmlBuilder.to_doc()
end end

View file

@ -0,0 +1,147 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.SideEffects.DeleteTest do
use Oban.Testing, repo: Pleroma.Repo
use Pleroma.DataCase, async: true
alias Pleroma.Activity
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.SideEffects
alias Pleroma.Web.CommonAPI
alias Pleroma.LoggerMock
alias Pleroma.Web.ActivityPub.ActivityPubMock
import Mox
import Pleroma.Factory
describe "user deletion" do
setup do
user = insert(:user)
{:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
{:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
%{
user: user,
delete_user: delete_user
}
end
test "it handles user deletions", %{delete_user: delete, user: user} do
{:ok, _delete, _} = SideEffects.handle(delete)
ObanHelpers.perform_all()
assert User.get_cached_by_ap_id(user.ap_id).deactivated
end
end
describe "object deletion" do
setup do
user = insert(:user)
other_user = insert(:user)
{:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
{:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
{:ok, favorite} = CommonAPI.favorite(user, post.id)
object = Object.normalize(post)
{:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
{:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
%{
user: user,
delete: delete,
post: post,
object: object,
op: op,
favorite: favorite
}
end
test "it handles object deletions", %{
delete: delete,
post: post,
object: object,
user: user,
op: op,
favorite: favorite
} do
object_id = object.id
user_id = user.id
ActivityPubMock
|> expect(:stream_out, fn ^delete -> nil end)
|> expect(:stream_out_participations, fn %Object{id: ^object_id}, %User{id: ^user_id} ->
nil
end)
{:ok, _delete, _} = SideEffects.handle(delete)
user = User.get_cached_by_ap_id(object.data["actor"])
object = Object.get_by_id(object.id)
assert object.data["type"] == "Tombstone"
refute Activity.get_by_id(post.id)
refute Activity.get_by_id(favorite.id)
user = User.get_by_id(user.id)
assert user.note_count == 0
object = Object.normalize(op.data["object"], false)
assert object.data["repliesCount"] == 0
end
test "it handles object deletions when the object itself has been pruned", %{
delete: delete,
post: post,
object: object,
user: user,
op: op
} do
object_id = object.id
user_id = user.id
ActivityPubMock
|> expect(:stream_out, fn ^delete -> nil end)
|> expect(:stream_out_participations, fn %Object{id: ^object_id}, %User{id: ^user_id} ->
nil
end)
{:ok, _delete, _} = SideEffects.handle(delete)
user = User.get_cached_by_ap_id(object.data["actor"])
object = Object.get_by_id(object.id)
assert object.data["type"] == "Tombstone"
refute Activity.get_by_id(post.id)
user = User.get_by_id(user.id)
assert user.note_count == 0
object = Object.normalize(op.data["object"], false)
assert object.data["repliesCount"] == 0
end
test "it logs issues with objects deletion", %{
delete: delete,
object: object
} do
{:ok, _object} =
object
|> Object.change(%{data: Map.delete(object.data, "actor")})
|> Repo.update()
LoggerMock
|> expect(:error, fn str -> assert str =~ "The object doesn't have an actor" end)
{:error, :no_object_actor} = SideEffects.handle(delete)
end
end
end

View file

@ -19,7 +19,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
alias Pleroma.Web.ActivityPub.SideEffects alias Pleroma.Web.ActivityPub.SideEffects
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
import ExUnit.CaptureLog
import Mock import Mock
import Pleroma.Factory import Pleroma.Factory
@ -131,115 +130,6 @@ test "it uses a given changeset to update", %{user: user, update: update} do
end end
end end
describe "delete objects" do
setup do
user = insert(:user)
other_user = insert(:user)
{:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
{:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
{:ok, favorite} = CommonAPI.favorite(user, post.id)
object = Object.normalize(post)
{:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
{:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
{:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
{:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
%{
user: user,
delete: delete,
post: post,
object: object,
delete_user: delete_user,
op: op,
favorite: favorite
}
end
test "it handles object deletions", %{
delete: delete,
post: post,
object: object,
user: user,
op: op,
favorite: favorite
} do
with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
stream_out: fn _ -> nil end,
stream_out_participations: fn _, _ -> nil end do
{:ok, delete, _} = SideEffects.handle(delete)
user = User.get_cached_by_ap_id(object.data["actor"])
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
end
object = Object.get_by_id(object.id)
assert object.data["type"] == "Tombstone"
refute Activity.get_by_id(post.id)
refute Activity.get_by_id(favorite.id)
user = User.get_by_id(user.id)
assert user.note_count == 0
object = Object.normalize(op.data["object"], false)
assert object.data["repliesCount"] == 0
end
test "it handles object deletions when the object itself has been pruned", %{
delete: delete,
post: post,
object: object,
user: user,
op: op
} do
with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
stream_out: fn _ -> nil end,
stream_out_participations: fn _, _ -> nil end do
{:ok, delete, _} = SideEffects.handle(delete)
user = User.get_cached_by_ap_id(object.data["actor"])
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
end
object = Object.get_by_id(object.id)
assert object.data["type"] == "Tombstone"
refute Activity.get_by_id(post.id)
user = User.get_by_id(user.id)
assert user.note_count == 0
object = Object.normalize(op.data["object"], false)
assert object.data["repliesCount"] == 0
end
test "it handles user deletions", %{delete_user: delete, user: user} do
{:ok, _delete, _} = SideEffects.handle(delete)
ObanHelpers.perform_all()
assert User.get_cached_by_ap_id(user.ap_id).deactivated
end
test "it logs issues with objects deletion", %{
delete: delete,
object: object
} do
{:ok, object} =
object
|> Object.change(%{data: Map.delete(object.data, "actor")})
|> Repo.update()
Object.invalid_object_cache(object)
assert capture_log(fn ->
{:error, :no_object_actor} = SideEffects.handle(delete)
end) =~ "object doesn't have an actor"
end
end
describe "EmojiReact objects" do describe "EmojiReact objects" do
setup do setup do
poster = insert(:user) poster = insert(:user)

View file

@ -80,6 +80,12 @@ test "renders an invisible user with the invisible property set to true" do
assert %{"invisible" => true} = UserView.render("service.json", %{user: user}) assert %{"invisible" => true} = UserView.render("service.json", %{user: user})
end end
test "renders AKAs" do
akas = ["https://i.tusooa.xyz/users/test-pleroma"]
user = insert(:user, also_known_as: akas)
assert %{"alsoKnownAs" => ^akas} = UserView.render("user.json", %{user: user})
end
describe "endpoints" do describe "endpoints" do
test "local users have a usable endpoints structure" do test "local users have a usable endpoints structure" do
user = insert(:user) user = insert(:user)

View file

@ -9,6 +9,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do
describe "renders `report_note_delete` log messages" do describe "renders `report_note_delete` log messages" do
setup do setup do
log1 = %Pleroma.ModerationLog{ log1 = %Pleroma.ModerationLog{
id: 1,
data: %{ data: %{
"action" => "report_note_delete", "action" => "report_note_delete",
"actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
@ -21,6 +22,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do
} }
log2 = %Pleroma.ModerationLog{ log2 = %Pleroma.ModerationLog{
id: 2,
data: %{ data: %{
"action" => "report_note_delete", "action" => "report_note_delete",
"actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
@ -42,6 +44,7 @@ test "renders `report_note_delete` log messages", %{log1: log1, log2: log2} do
) == %{ ) == %{
items: [ items: [
%{ %{
id: 1,
data: %{ data: %{
"action" => "report_note_delete", "action" => "report_note_delete",
"actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
@ -59,6 +62,7 @@ test "renders `report_note_delete` log messages", %{log1: log1, log2: log2} do
time: 1_605_622_400 time: 1_605_622_400
}, },
%{ %{
id: 2,
data: %{ data: %{
"action" => "report_note_delete", "action" => "report_note_delete",
"actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
@ -82,6 +86,7 @@ test "renders `report_note_delete` log messages", %{log1: log1, log2: log2} do
test "renders `report_note_delete` log message", %{log1: log} do test "renders `report_note_delete` log message", %{log1: log} do
assert ModerationLogView.render("show.json", %{log_entry: log}) == %{ assert ModerationLogView.render("show.json", %{log_entry: log}) == %{
id: 1,
data: %{ data: %{
"action" => "report_note_delete", "action" => "report_note_delete",
"actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"}, "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},

View file

@ -143,4 +143,29 @@ test "doesn't error out when the user doesn't exists" do
assert %{} = ReportView.render("show.json", Report.extract_report_info(activity)) assert %{} = ReportView.render("show.json", Report.extract_report_info(activity))
end end
test "reports are ordered newest first" do
user = insert(:user)
other_user = insert(:user)
{:ok, report1} =
CommonAPI.report(user, %{
account_id: other_user.id,
comment: "first report"
})
{:ok, report2} =
CommonAPI.report(user, %{
account_id: other_user.id,
comment: "second report"
})
%{reports: rendered} =
ReportView.render("index.json",
reports: Pleroma.Web.ActivityPub.Utils.get_reports(%{}, 1, 50)
)
assert report2.id == rendered |> Enum.at(0) |> Map.get(:id)
assert report1.id == rendered |> Enum.at(1) |> Map.get(:id)
end
end end

View file

@ -218,6 +218,25 @@ test "updates the user's name", %{conn: conn} do
assert update_activity.data["object"]["name"] == "markorepairs" assert update_activity.data["object"]["name"] == "markorepairs"
end end
test "updates the user's AKAs", %{conn: conn} do
conn =
patch(conn, "/api/v1/accounts/update_credentials", %{
"also_known_as" => ["https://mushroom.kingdom/users/mario"]
})
assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["also_known_as"] == ["https://mushroom.kingdom/users/mario"]
end
test "doesn't update non-url akas", %{conn: conn} do
conn =
patch(conn, "/api/v1/accounts/update_credentials", %{
"also_known_as" => ["aReallyCoolGuy"]
})
assert json_response_and_validate_schema(conn, 403)
end
test "updates the user's avatar", %{user: user, conn: conn} do test "updates the user's avatar", %{user: user, conn: conn} do
new_avatar = %Plug.Upload{ new_avatar = %Plug.Upload{
content_type: "image/jpeg", content_type: "image/jpeg",

View file

@ -35,7 +35,8 @@ test "Represent a user account" do
"<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f '&<>\"", "<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f '&<>\"",
inserted_at: ~N[2017-08-15 15:47:06.597036], inserted_at: ~N[2017-08-15 15:47:06.597036],
emoji: %{"karjalanpiirakka" => "/file.png"}, emoji: %{"karjalanpiirakka" => "/file.png"},
raw_bio: "valid html. a\nb\nc\nd\nf '&<>\"" raw_bio: "valid html. a\nb\nc\nd\nf '&<>\"",
also_known_as: ["https://shitposter.zone/users/shp"]
}) })
expected = %{ expected = %{
@ -75,6 +76,7 @@ test "Represent a user account" do
}, },
pleroma: %{ pleroma: %{
ap_id: user.ap_id, ap_id: user.ap_id,
also_known_as: ["https://shitposter.zone/users/shp"],
background_image: "https://example.com/images/asuka_hospital.png", background_image: "https://example.com/images/asuka_hospital.png",
favicon: nil, favicon: nil,
confirmation_pending: false, confirmation_pending: false,
@ -173,6 +175,7 @@ test "Represent a Service(bot) account" do
}, },
pleroma: %{ pleroma: %{
ap_id: user.ap_id, ap_id: user.ap_id,
also_known_as: [],
background_image: nil, background_image: nil,
favicon: nil, favicon: nil,
confirmation_pending: false, confirmation_pending: false,

View file

@ -30,14 +30,24 @@ test "GET host-meta" do
end end
test "Webfinger JRD" do test "Webfinger JRD" do
user = insert(:user) user =
insert(:user,
ap_id: "https://hyrule.world/users/zelda",
also_known_as: ["https://mushroom.kingdom/users/toad"]
)
response = response =
build_conn() build_conn()
|> put_req_header("accept", "application/jrd+json") |> put_req_header("accept", "application/jrd+json")
|> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
|> json_response(200)
assert json_response(response, 200)["subject"] == "acct:#{user.nickname}@localhost" assert response["subject"] == "acct:#{user.nickname}@localhost"
assert response["aliases"] == [
"https://hyrule.world/users/zelda",
"https://mushroom.kingdom/users/toad"
]
end end
test "it returns 404 when user isn't found (JSON)" do test "it returns 404 when user isn't found (JSON)" do
@ -51,14 +61,20 @@ test "it returns 404 when user isn't found (JSON)" do
end end
test "Webfinger XML" do test "Webfinger XML" do
user = insert(:user) user =
insert(:user,
ap_id: "https://hyrule.world/users/zelda",
also_known_as: ["https://mushroom.kingdom/users/toad"]
)
response = response =
build_conn() build_conn()
|> put_req_header("accept", "application/xrd+xml") |> put_req_header("accept", "application/xrd+xml")
|> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
|> response(200)
assert response(response, 200) assert response =~ "<Alias>https://hyrule.world/users/zelda</Alias>"
assert response =~ "<Alias>https://mushroom.kingdom/users/toad</Alias>"
end end
test "it returns 404 when user isn't found (XML)" do test "it returns 404 when user isn't found (XML)" do

View file

@ -138,6 +138,8 @@ defp json_response_and_validate_schema(conn, _status) do
Pleroma.DataCase.stub_pipeline() Pleroma.DataCase.stub_pipeline()
Mox.verify_on_exit!()
{:ok, conn: Phoenix.ConnTest.build_conn()} {:ok, conn: Phoenix.ConnTest.build_conn()}
end end
end end

View file

@ -85,6 +85,8 @@ def clear_cachex do
stub_pipeline() stub_pipeline()
Mox.verify_on_exit!()
:ok :ok
end end

View file

@ -13,7 +13,10 @@
) )
Mox.defmock(Pleroma.Web.ActivityPub.ActivityPubMock, Mox.defmock(Pleroma.Web.ActivityPub.ActivityPubMock,
for: Pleroma.Web.ActivityPub.ActivityPub.Persisting for: [
Pleroma.Web.ActivityPub.ActivityPub.Persisting,
Pleroma.Web.ActivityPub.ActivityPub.Streaming
]
) )
Mox.defmock(Pleroma.Web.ActivityPub.SideEffectsMock, Mox.defmock(Pleroma.Web.ActivityPub.SideEffectsMock,
@ -23,3 +26,5 @@
Mox.defmock(Pleroma.Web.FederatorMock, for: Pleroma.Web.Federator.Publishing) Mox.defmock(Pleroma.Web.FederatorMock, for: Pleroma.Web.Federator.Publishing)
Mox.defmock(Pleroma.ConfigMock, for: Pleroma.Config.Getting) Mox.defmock(Pleroma.ConfigMock, for: Pleroma.Config.Getting)
Mox.defmock(Pleroma.LoggerMock, for: Pleroma.Logging)