adding domain mutes

This commit is contained in:
Alexander Strizhakov 2020-05-16 10:22:19 +03:00
parent 1199cf3a78
commit fa7cfbd0b0
No known key found for this signature in database
GPG key ID: 022896A53AEF1381
13 changed files with 338 additions and 38 deletions

View file

@ -120,8 +120,11 @@ defmodule Pleroma.Notification do
notification_muted_ap_ids =
opts[:notification_muted_users_ap_ids] || User.notification_muted_users_ap_ids(user)
domain_mutes = user.domain_mutes || []
query
|> where([n, a], a.actor not in ^notification_muted_ap_ids)
|> where([n, a], fragment("not split_part(?, '/', 3) = ANY(?)", a.actor, ^domain_mutes))
|> join(:left, [n, a], tm in ThreadMute,
on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
)

View file

@ -30,6 +30,7 @@ defmodule Pleroma.User do
alias Pleroma.Web
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.MRF
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Utils
@ -108,6 +109,7 @@ defmodule Pleroma.User do
field(:confirmation_token, :string, default: nil)
field(:default_scope, :string, default: "public")
field(:domain_blocks, {:array, :string}, default: [])
field(:domain_mutes, {:array, :string}, default: [])
field(:deactivated, :boolean, default: false)
field(:no_rich_text, :boolean, default: false)
field(:ap_enabled, :boolean, default: false)
@ -359,8 +361,8 @@ defmodule Pleroma.User do
defp fix_follower_address(params), do: params
def remote_user_changeset(struct \\ %User{local: false}, params) do
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
bio_limit = Config.get([:instance, :user_bio_length], 5000)
name_limit = Config.get([:instance, :user_name_length], 100)
name =
case params[:name] do
@ -419,8 +421,8 @@ defmodule Pleroma.User do
end
def update_changeset(struct, params \\ %{}) do
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
bio_limit = Config.get([:instance, :user_bio_length], 5000)
name_limit = Config.get([:instance, :user_name_length], 100)
struct
|> cast(
@ -589,12 +591,12 @@ defmodule Pleroma.User do
def force_password_reset(user), do: update_password_reset_pending(user, true)
def register_changeset(struct, params \\ %{}, opts \\ []) do
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
bio_limit = Config.get([:instance, :user_bio_length], 5000)
name_limit = Config.get([:instance, :user_name_length], 100)
need_confirmation? =
if is_nil(opts[:need_confirmation]) do
Pleroma.Config.get([:instance, :account_activation_required])
Config.get([:instance, :account_activation_required])
else
opts[:need_confirmation]
end
@ -606,7 +608,7 @@ defmodule Pleroma.User do
|> validate_confirmation(:password)
|> unique_constraint(:email)
|> unique_constraint(:nickname)
|> validate_exclusion(:nickname, Pleroma.Config.get([User, :restricted_nicknames]))
|> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
|> validate_format(:nickname, local_nickname_regex())
|> validate_format(:email, @email_regex)
|> validate_length(:bio, max: bio_limit)
@ -621,7 +623,7 @@ defmodule Pleroma.User do
def maybe_validate_required_email(changeset, true), do: changeset
def maybe_validate_required_email(changeset, _) do
if Pleroma.Config.get([:instance, :account_activation_required]) do
if Config.get([:instance, :account_activation_required]) do
validate_required(changeset, [:email])
else
changeset
@ -641,7 +643,7 @@ defmodule Pleroma.User do
end
defp autofollow_users(user) do
candidates = Pleroma.Config.get([:instance, :autofollowed_nicknames])
candidates = Config.get([:instance, :autofollowed_nicknames])
autofollowed_users =
User.Query.build(%{nickname: candidates, local: true, deactivated: false})
@ -668,7 +670,7 @@ defmodule Pleroma.User do
def try_send_confirmation_email(%User{} = user) do
if user.confirmation_pending &&
Pleroma.Config.get([:instance, :account_activation_required]) do
Config.get([:instance, :account_activation_required]) do
user
|> Pleroma.Emails.UserEmail.account_confirmation_email()
|> Pleroma.Emails.Mailer.deliver_async()
@ -725,7 +727,7 @@ defmodule Pleroma.User do
defdelegate following(user), to: FollowingRelationship
def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do
deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])
deny_follow_blocked = Config.get([:user, :deny_follow_blocked])
cond do
followed.deactivated ->
@ -916,7 +918,7 @@ defmodule Pleroma.User do
end
def get_cached_by_nickname_or_id(nickname_or_id, opts \\ []) do
restrict_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
restrict_to_local = Config.get([:instance, :limit_to_local_content])
cond do
is_integer(nickname_or_id) or FlakeId.flake_id?(nickname_or_id) ->
@ -977,14 +979,14 @@ defmodule Pleroma.User do
@spec get_followers_query(User.t()) :: Ecto.Query.t()
def get_followers_query(user), do: get_followers_query(user, nil)
@spec get_followers(User.t(), pos_integer() | nil) :: {:ok, list(User.t())}
@spec get_followers(User.t(), pos_integer() | nil) :: [User.t()]
def get_followers(user, page \\ nil) do
user
|> get_followers_query(page)
|> Repo.all()
end
@spec get_external_followers(User.t(), pos_integer() | nil) :: {:ok, list(User.t())}
@spec get_external_followers(User.t(), pos_integer() | nil) :: [User.t()]
def get_external_followers(user, page \\ nil) do
user
|> get_followers_query(page)
@ -1013,6 +1015,7 @@ defmodule Pleroma.User do
@spec get_friends_query(User.t()) :: Ecto.Query.t()
def get_friends_query(user), do: get_friends_query(user, nil)
@spec get_friends(User.t(), pos_integer() | nil) :: [User.t()]
def get_friends(user, page \\ nil) do
user
|> get_friends_query(page)
@ -1111,7 +1114,7 @@ defmodule Pleroma.User do
end
def update_follower_count(%User{} = user) do
if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do
if user.local or !Config.get([:instance, :external_user_synchronization]) do
follower_count_query =
User.Query.build(%{followers: user, deactivated: false})
|> select([u], %{count: count(u.id)})
@ -1135,7 +1138,7 @@ defmodule Pleroma.User do
@spec update_following_count(User.t()) :: User.t()
def update_following_count(%User{local: false} = user) do
if Pleroma.Config.get([:instance, :external_user_synchronization]) do
if Config.get([:instance, :external_user_synchronization]) do
maybe_fetch_follow_information(user)
else
user
@ -1219,7 +1222,7 @@ defmodule Pleroma.User do
end
def subscribe(%User{} = subscriber, %User{} = target) do
deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])
deny_follow_blocked = Config.get([:user, :deny_follow_blocked])
if blocks?(target, subscriber) and deny_follow_blocked do
{:error, "Could not subscribe: #{target.nickname} is blocking you"}
@ -1286,13 +1289,27 @@ defmodule Pleroma.User do
unblock(blocker, get_cached_by_ap_id(ap_id))
end
@spec mutes?(User.t() | nil, User.t()) :: boolean()
def mutes?(nil, _), do: false
def mutes?(%User{} = user, %User{} = target), do: mutes_user?(user, target)
def mutes?(%User{} = user, %User{} = target) do
mutes_user?(user, target) || mutes_domain?(user, target)
end
@spec mutes_user?(User.t(), User.t()) :: boolean()
def mutes_user?(%User{} = user, %User{} = target) do
UserRelationship.mute_exists?(user, target)
end
@spec mutes_domain?(User.t() | nil, User.t()) :: boolean()
def mutes_domain?(nil, _), do: false
def mutes_domain?(%User{} = user, %User{} = target) do
domain_mutes = MRF.subdomains_regex(user.domain_mutes)
%{host: host} = URI.parse(target.ap_id)
MRF.subdomain_match?(domain_mutes, host)
end
@spec muted_notifications?(User.t() | nil, User.t() | map()) :: boolean()
def muted_notifications?(nil, _), do: false
@ -1313,9 +1330,9 @@ defmodule Pleroma.User do
def blocks_user?(_, _), do: false
def blocks_domain?(%User{} = user, %User{} = target) do
domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.domain_blocks)
domain_blocks = MRF.subdomains_regex(user.domain_blocks)
%{host: host} = URI.parse(target.ap_id)
Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host)
MRF.subdomain_match?(domain_blocks, host)
end
def blocks_domain?(_, _), do: false
@ -1584,7 +1601,7 @@ defmodule Pleroma.User do
Pleroma.HTML.Scrubber.TwitterText
end
def html_filter_policy(_), do: Pleroma.Config.get([:markup, :scrub_policy])
def html_filter_policy(_), do: Config.get([:markup, :scrub_policy])
def fetch_by_ap_id(ap_id), do: ActivityPub.make_user_from_ap_id(ap_id)
@ -1759,7 +1776,7 @@ defmodule Pleroma.User do
end
defp local_nickname_regex do
if Pleroma.Config.get([:instance, :extended_nickname_format]) do
if Config.get([:instance, :extended_nickname_format]) do
@extended_local_nickname_regex
else
@strict_local_nickname_regex
@ -1887,8 +1904,8 @@ defmodule Pleroma.User do
def get_mascot(%{mascot: mascot}) when is_nil(mascot) do
# use instance-default
config = Pleroma.Config.get([:assets, :mascots])
default_mascot = Pleroma.Config.get([:assets, :default_mascot])
config = Config.get([:assets, :mascots])
default_mascot = Config.get([:assets, :default_mascot])
mascot = Keyword.get(config, default_mascot)
%{
@ -1983,7 +2000,7 @@ defmodule Pleroma.User do
def validate_fields(changeset, remote? \\ false) do
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
limit = Pleroma.Config.get([:instance, limit_name], 0)
limit = Config.get([:instance, limit_name], 0)
changeset
|> validate_length(:fields, max: limit)
@ -1997,8 +2014,8 @@ defmodule Pleroma.User do
end
defp valid_field?(%{"name" => name, "value" => value}) do
name_limit = Pleroma.Config.get([:instance, :account_field_name_length], 255)
value_limit = Pleroma.Config.get([:instance, :account_field_value_length], 255)
name_limit = Config.get([:instance, :account_field_name_length], 255)
value_limit = Config.get([:instance, :account_field_value_length], 255)
is_binary(name) && is_binary(value) && String.length(name) <= name_limit &&
String.length(value) <= value_limit
@ -2008,10 +2025,10 @@ defmodule Pleroma.User do
defp truncate_field(%{"name" => name, "value" => value}) do
{name, _chopped} =
String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255))
String.split_at(name, Config.get([:instance, :account_field_name_length], 255))
{value, _chopped} =
String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255))
String.split_at(value, Config.get([:instance, :account_field_value_length], 255))
%{"name" => name, "value" => value}
end
@ -2066,7 +2083,7 @@ defmodule Pleroma.User do
def add_pinnned_activity(user, %Pleroma.Activity{id: id}) do
if id not in user.pinned_activities do
max_pinned_statuses = Pleroma.Config.get([:instance, :max_pinned_statuses], 0)
max_pinned_statuses = Config.get([:instance, :max_pinned_statuses], 0)
params = %{pinned_activities: user.pinned_activities ++ [id]}
user
@ -2121,13 +2138,32 @@ defmodule Pleroma.User do
set_domain_blocks(user, List.delete(user.domain_blocks, domain_blocked))
end
defp set_domain_mutes(user, domain_mutes) do
params = %{domain_mutes: domain_mutes}
user
|> cast(params, [:domain_mutes])
|> validate_required([:domain_mutes])
|> update_and_set_cache()
end
@spec mute_domain(User.t(), String.t()) :: {:ok, User.t()}
def mute_domain(%User{} = user, muted_domain) do
set_domain_mutes(user, Enum.uniq([muted_domain | user.domain_mutes]))
end
@spec unmute_domain(User.t(), String.t()) :: {:ok, User.t()}
def unmute_domain(user, muted_domain) do
set_domain_mutes(user, List.delete(user.domain_mutes, muted_domain))
end
@spec add_to_block(User.t(), User.t()) ::
{:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()}
defp add_to_block(%User{} = user, %User{} = blocked) do
UserRelationship.create_block(user, blocked)
end
@spec add_to_block(User.t(), User.t()) ::
@spec remove_from_block(User.t(), User.t()) ::
{:ok, UserRelationship.t()} | {:ok, nil} | {:error, Ecto.Changeset.t()}
defp remove_from_block(%User{} = user, %User{} = blocked) do
UserRelationship.delete_block(user, blocked)

View file

@ -924,11 +924,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_muted(query, %{"muting_user" => %User{} = user} = opts) do
mutes = opts["muted_users_ap_ids"] || User.muted_users_ap_ids(user)
domain_mutes = user.domain_mutes || []
query =
from([activity] in query,
where: fragment("not (? = ANY(?))", activity.actor, ^mutes),
where: fragment("not (?->'to' \\?| ?)", activity.data, ^mutes)
where: fragment("not (?->'to' \\?| ?)", activity.data, ^mutes),
where: fragment("not split_part(?, '/', 3) = ANY(?)", activity.actor, ^domain_mutes)
)
unless opts["skip_preload"] do

View file

@ -0,0 +1,81 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ApiSpec.DomainMuteOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
import Pleroma.Web.ApiSpec.Helpers
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def index_operation do
%Operation{
tags: ["domain_mutes"],
summary: "Fetch domain mutes",
description: "View domains the user has muted.",
security: [%{"oAuth" => ["follow", "read:mutes"]}],
operationId: "DomainMuteController.index",
responses: %{
200 =>
Operation.response("Domain mutes", "application/json", %Schema{
description: "Response schema for domain mutes",
type: :array,
items: %Schema{type: :string},
example: ["google.com", "facebook.com"]
})
}
}
end
def create_operation do
%Operation{
tags: ["domain_mutes"],
summary: "Mute a domain",
description: """
Mute a domain to:
- hide all posts from it
- hide all notifications from it
""",
operationId: "DomainMuteController.create",
requestBody: domain_mute_request(),
security: [%{"oAuth" => ["follow", "write:mutes"]}],
responses: %{200 => empty_object_response()}
}
end
def delete_operation do
%Operation{
tags: ["domain_mutes"],
summary: "Unmute a domain",
description: "Remove a domain mute, if it exists in the user's array of muted domains.",
operationId: "DomainMuteController.delete",
requestBody: domain_mute_request(),
security: [%{"oAuth" => ["follow", "write:mutes"]}],
responses: %{
200 => Operation.response("Empty object", "application/json", %Schema{type: :object})
}
}
end
defp domain_mute_request do
request_body(
"Parameters",
%Schema{
type: :object,
properties: %{
domain: %Schema{type: :string}
},
required: [:domain]
},
required: true,
example: %{
"domain" => "facebook.com"
}
)
end
end

View file

@ -109,7 +109,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
:mute,
reading_user,
target,
&User.mutes?(&1, &2)
&User.mutes_user?(&1, &2)
),
muting_notifications:
UserRelationship.exists?(

View file

@ -308,6 +308,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
_ -> []
end
mutes_domain? = User.mutes_domain?(opts[:for], user)
# Status muted state (would do 1 request per status unless user mutes are preloaded)
muted =
thread_muted? ||
@ -316,8 +317,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
:mute,
opts[:for],
user,
fn for_user, user -> User.mutes?(for_user, user) end
)
fn for_user, user -> User.mutes_user?(for_user, user) end
) || mutes_domain?
%{
id: to_string(activity.id),
@ -364,7 +365,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
expires_at: expires_at,
direct_conversation_id: direct_conversation_id,
thread_muted: thread_muted?,
emoji_reactions: emoji_reactions
emoji_reactions: emoji_reactions,
instance_muted: mutes_domain?
}
}
end

View file

@ -0,0 +1,37 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.PleromaAPI.DomainMuteController do
use Pleroma.Web, :controller
plug(Pleroma.Web.ApiSpec.CastAndValidate)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DomainMuteOperation
plug(
Pleroma.Plugs.OAuthScopesPlug,
%{scopes: ["follow", "read:mutes"]} when action == :index
)
plug(
Pleroma.Plugs.OAuthScopesPlug,
%{scopes: ["follow", "write:mutes"]} when action != :index
)
@doc "GET /api/pleroma/domain_mutes"
def index(%{assigns: %{user: user}} = conn, _) do
json(conn, Map.get(user, :domain_mutes, []))
end
@doc "POST /api/pleroma/domain_mutes"
def create(%{assigns: %{user: user}, body_params: %{domain: domain}} = conn, _) do
Pleroma.User.mute_domain(user, domain)
json(conn, %{})
end
@doc "DELETE /api/pleroma/domain_mutes"
def delete(%{assigns: %{user: user}, body_params: %{domain: domain}} = conn, _) do
Pleroma.User.unmute_domain(user, domain)
json(conn, %{})
end
end

View file

@ -267,6 +267,10 @@ defmodule Pleroma.Web.Router do
get("/accounts/mfa/setup/:method", TwoFactorAuthenticationController, :setup)
post("/accounts/mfa/confirm/:method", TwoFactorAuthenticationController, :confirm)
delete("/accounts/mfa/:method", TwoFactorAuthenticationController, :disable)
get("/domain_mutes", DomainMuteController, :index)
post("/domain_mutes", DomainMuteController, :create)
delete("/domain_mutes", DomainMuteController, :delete)
end
scope "/oauth", Pleroma.Web.OAuth do

View file

@ -0,0 +1,9 @@
defmodule Pleroma.Repo.Migrations.AddDomainMutesToUsers do
use Ecto.Migration
def change do
alter table(:users) do
add_if_not_exists(:domain_mutes, {:array, :text}, default: [])
end
end
end

View file

@ -479,6 +479,30 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
assert length(json_response_and_validate_schema(conn, 200)) == 1
end
describe "muting domain" do
setup do
%{user: user, conn: conn} = oauth_access(["read:notifications"])
user2 = insert(:user, ap_id: "https://example.com/users/other_user")
{:ok, user, _, _} = CommonAPI.follow(user, user2)
{:ok, user} = User.mute_domain(user, "example.com")
{:ok, _} = CommonAPI.post(user2, %{status: "hello @#{user.nickname}"})
conn = assign(conn, :user, user)
[conn: conn]
end
test "see notifications with_muted parameter", %{conn: conn} do
conn = get(conn, "/api/v1/notifications?with_muted=true")
assert length(json_response_and_validate_schema(conn, 200)) == 1
end
test "doesn't see notifications without with_muted parameter", %{conn: conn} do
conn = get(conn, "/api/v1/notifications")
assert json_response_and_validate_schema(conn, 200) == []
end
end
@tag capture_log: true
test "see move notifications" do
old_user = insert(:user)

View file

@ -57,6 +57,63 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
end
end
describe "home timeline and user muting" do
setup do: oauth_access(["read:statuses"])
setup %{user: user} do
other_user = insert(:user, ap_id: "https://example.com/users/other_user")
{:ok, user} = User.follow(user, other_user)
{:ok, activity} = CommonAPI.post(other_user, %{status: "Some status"})
{:ok, _} = User.mute(user, other_user)
[activity: activity]
end
test "returns statuses with_muted = true", %{conn: conn, activity: activity} do
conn = get(conn, "/api/v1/timelines/home?with_muted=true")
[status] = json_response_and_validate_schema(conn, :ok)
assert activity.id == status["id"]
assert status["muted"]
refute status["pleroma"]["instance_muted"]
end
test "doesn't return statuses with_muted = false", %{conn: conn} do
conn = get(conn, "/api/v1/timelines/home?with_muted=false")
assert json_response_and_validate_schema(conn, :ok) == []
end
end
describe "home timeline and domain muting" do
setup do: oauth_access(["read:statuses"])
setup %{user: user, conn: conn} do
other_user = insert(:user, ap_id: "https://example.com/users/other_user")
{:ok, user} = User.follow(user, other_user)
{:ok, activity} = CommonAPI.post(other_user, %{status: "Some Status"})
{:ok, user} = User.mute_domain(user, "example.com")
conn = assign(conn, :user, user)
[activity: activity, conn: conn]
end
test "returns statuses with_muted = true", %{conn: conn, activity: activity} do
conn = get(conn, "/api/v1/timelines/home?with_muted=true")
[status] = json_response_and_validate_schema(conn, :ok)
assert activity.id == status["id"]
assert status["muted"]
assert status["pleroma"]["instance_muted"]
end
test "doesn't return statuses with_muted = false", %{conn: conn} do
conn = get(conn, "/api/v1/timelines/home?with_muted=false")
assert json_response_and_validate_schema(conn, :ok) == []
end
end
describe "public" do
@tag capture_log: true
test "the public timeline", %{conn: conn} do

View file

@ -226,7 +226,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
expires_at: nil,
direct_conversation_id: nil,
thread_muted: false,
emoji_reactions: []
emoji_reactions: [],
instance_muted: false
}
}

View file

@ -0,0 +1,44 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.PleromaAPI.DomainMuteControllerTest do
use Pleroma.Web.ConnCase, async: true
import Pleroma.Factory
alias Pleroma.User
test "muting / unmuting domain" do
%{user: user, conn: conn} = oauth_access(["write:mutes", "read:mutes"])
conn = put_req_header(conn, "content-type", "application/json")
other_user = insert(:user, ap_id: "https://example.com/users/other_user")
response = post(conn, "/api/pleroma/domain_mutes", %{"domain" => "example.com"})
assert %{} == json_response_and_validate_schema(response, 200)
user = User.get_cached_by_ap_id(user.ap_id)
assert User.mutes?(user, other_user)
assert User.mutes_domain?(user, other_user)
assert ["example.com"] ==
conn
|> assign(:user, user)
|> get("/api/pleroma/domain_mutes")
|> json_response_and_validate_schema(200)
response = delete(conn, "/api/pleroma/domain_mutes", %{"domain" => "example.com"})
assert %{} == json_response_and_validate_schema(response, 200)
user = User.get_cached_by_ap_id(user.ap_id)
refute User.mutes?(user, other_user)
refute User.mutes_domain?(user, other_user)
assert [] ==
conn
|> assign(:user, user)
|> get("/api/pleroma/domain_mutes")
|> json_response_and_validate_schema(200)
end
end