mirror of
https://git.pleroma.social/pleroma/pleroma.git
synced 2025-04-24 05:47:41 -04:00
Merge branch 'expiring-blocks' into 'develop'
Add expiring blocks See merge request pleroma/pleroma!4351
This commit is contained in:
commit
9aa8f80d59
12 changed files with 112 additions and 33 deletions
1
changelog.d/expiring-blocks.add
Normal file
1
changelog.d/expiring-blocks.add
Normal file
|
@ -0,0 +1 @@
|
|||
Add `duration` to the block endpoint, which makes block expire
|
|
@ -1708,7 +1708,9 @@ defmodule Pleroma.User do
|
|||
end
|
||||
end
|
||||
|
||||
def block(%User{} = blocker, %User{} = blocked) do
|
||||
def block(blocker, blocked, params \\ %{})
|
||||
|
||||
def block(%User{} = blocker, %User{} = blocked, params) do
|
||||
# sever any follow relationships to prevent leaks per activitypub (Pleroma issue #213)
|
||||
blocker =
|
||||
if following?(blocker, blocked) do
|
||||
|
@ -1738,12 +1740,33 @@ defmodule Pleroma.User do
|
|||
|
||||
{:ok, blocker} = update_follower_count(blocker)
|
||||
{:ok, blocker, _} = Participation.mark_all_as_read(blocker, blocked)
|
||||
add_to_block(blocker, blocked)
|
||||
|
||||
duration = Map.get(params, :duration, 0)
|
||||
|
||||
expires_at =
|
||||
if duration > 0 do
|
||||
DateTime.utc_now()
|
||||
|> DateTime.add(duration)
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
user_block = add_to_block(blocker, blocked, expires_at)
|
||||
|
||||
if duration > 0 do
|
||||
Pleroma.Workers.MuteExpireWorker.new(
|
||||
%{"op" => "unblock_user", "blocker_id" => blocker.id, "blocked_id" => blocked.id},
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
user_block
|
||||
end
|
||||
|
||||
# helper to handle the block given only an actor's AP id
|
||||
def block(%User{} = blocker, %{ap_id: ap_id}) do
|
||||
block(blocker, get_cached_by_ap_id(ap_id))
|
||||
def block(%User{} = blocker, %{ap_id: ap_id}, params) do
|
||||
block(blocker, get_cached_by_ap_id(ap_id), params)
|
||||
end
|
||||
|
||||
def unblock(%User{} = blocker, %User{} = blocked) do
|
||||
|
@ -2779,10 +2802,10 @@ defmodule Pleroma.User do
|
|||
set_domain_blocks(user, List.delete(user.domain_blocks, domain_blocked))
|
||||
end
|
||||
|
||||
@spec add_to_block(User.t(), User.t()) ::
|
||||
@spec add_to_block(User.t(), User.t(), integer() | nil) ::
|
||||
{:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()}
|
||||
defp add_to_block(%User{} = user, %User{} = blocked) do
|
||||
with {:ok, relationship} <- UserRelationship.create_block(user, blocked) do
|
||||
defp add_to_block(%User{} = user, %User{} = blocked, expires_at) do
|
||||
with {:ok, relationship} <- UserRelationship.create_block(user, blocked, expires_at) do
|
||||
@cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||
{:ok, relationship}
|
||||
end
|
||||
|
|
|
@ -327,8 +327,8 @@ defmodule Pleroma.Web.ActivityPub.Builder do
|
|||
}, []}
|
||||
end
|
||||
|
||||
@spec block(User.t(), User.t()) :: {:ok, map(), keyword()}
|
||||
def block(blocker, blocked) do
|
||||
@spec block(User.t(), User.t(), map()) :: {:ok, map(), keyword()}
|
||||
def block(blocker, blocked, params) do
|
||||
{:ok,
|
||||
%{
|
||||
"id" => Utils.generate_activity_id(),
|
||||
|
@ -336,7 +336,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
|
|||
"actor" => blocker.ap_id,
|
||||
"object" => blocked.ap_id,
|
||||
"to" => [blocked.ap_id]
|
||||
}, []}
|
||||
}, Keyword.new(params)}
|
||||
end
|
||||
|
||||
@spec announce(User.t(), Object.t(), keyword()) :: {:ok, map(), keyword()}
|
||||
|
|
|
@ -145,7 +145,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
) do
|
||||
with %User{} = blocker <- User.get_cached_by_ap_id(blocking_user),
|
||||
%User{} = blocked <- User.get_cached_by_ap_id(blocked_user) do
|
||||
User.block(blocker, blocked)
|
||||
User.block(blocker, blocked, Enum.into(meta, %{}))
|
||||
end
|
||||
|
||||
{:ok, object, meta}
|
||||
|
|
|
@ -284,18 +284,6 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
:query,
|
||||
%Schema{allOf: [BooleanLike], default: true},
|
||||
"Mute notifications in addition to statuses? Defaults to `true`."
|
||||
),
|
||||
Operation.parameter(
|
||||
:duration,
|
||||
:query,
|
||||
%Schema{type: :integer},
|
||||
"Expire the mute in `duration` seconds. Default 0 for infinity"
|
||||
),
|
||||
Operation.parameter(
|
||||
:expires_in,
|
||||
:query,
|
||||
%Schema{type: :integer, default: 0},
|
||||
"Deprecated, use `duration` instead"
|
||||
)
|
||||
],
|
||||
responses: %{
|
||||
|
@ -323,16 +311,37 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
tags: ["Account actions"],
|
||||
summary: "Block",
|
||||
operationId: "AccountController.block",
|
||||
requestBody: request_body("Parameters", block_request()),
|
||||
security: [%{"oAuth" => ["follow", "write:blocks"]}],
|
||||
description:
|
||||
"Block the given account. Clients should filter statuses from this account if received (e.g. due to a boost in the Home timeline)",
|
||||
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
|
||||
parameters: [
|
||||
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
|
||||
],
|
||||
responses: %{
|
||||
200 => Operation.response("Relationship", "application/json", AccountRelationship)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp block_request do
|
||||
%Schema{
|
||||
title: "AccountBlockRequest",
|
||||
description: "POST body for blocking an account",
|
||||
type: :object,
|
||||
properties: %{
|
||||
duration: %Schema{
|
||||
type: :integer,
|
||||
nullable: true,
|
||||
description: "Expire the mute in `duration` seconds. Default 0 for infinity"
|
||||
}
|
||||
},
|
||||
example: %{
|
||||
"duration" => 86_400
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def unblock_operation do
|
||||
%Operation{
|
||||
tags: ["Account actions"],
|
||||
|
|
|
@ -34,6 +34,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
|||
id: FlakeID,
|
||||
locked: %Schema{type: :boolean},
|
||||
mute_expires_at: %Schema{type: :string, format: "date-time", nullable: true},
|
||||
block_expires_at: %Schema{type: :string, format: "date-time", nullable: true},
|
||||
note: %Schema{type: :string, format: :html},
|
||||
statuses_count: %Schema{type: :integer},
|
||||
url: %Schema{type: :string, format: :uri},
|
||||
|
|
|
@ -27,9 +27,9 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
require Logger
|
||||
|
||||
@spec block(User.t(), User.t()) :: {:ok, Activity.t()} | Pipeline.errors()
|
||||
def block(blocked, blocker) do
|
||||
with {:ok, block_data, _} <- Builder.block(blocker, blocked),
|
||||
{:ok, block, _} <- Pipeline.common_pipeline(block_data, local: true) do
|
||||
def block(blocked, blocker, params \\ %{}) do
|
||||
with {:ok, block_data, meta} <- Builder.block(blocker, blocked, params),
|
||||
{:ok, block, _} <- Pipeline.common_pipeline(block_data, meta ++ [local: true]) do
|
||||
{:ok, block}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -501,8 +501,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/accounts/:id/block"
|
||||
def block(%{assigns: %{user: blocker, account: blocked}} = conn, _params) do
|
||||
with {:ok, _activity} <- CommonAPI.block(blocked, blocker) do
|
||||
def block(
|
||||
%{
|
||||
assigns: %{user: blocker, account: blocked},
|
||||
private: %{open_api_spex: %{body_params: params}}
|
||||
} = conn,
|
||||
_params
|
||||
) do
|
||||
with {:ok, _activity} <- CommonAPI.block(blocked, blocker, params) do
|
||||
render(conn, "relationship.json", user: blocker, target: blocked)
|
||||
else
|
||||
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||
|
@ -607,7 +613,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
users: users,
|
||||
for: user,
|
||||
as: :user,
|
||||
embed_relationships: embed_relationships?(params)
|
||||
embed_relationships: embed_relationships?(params),
|
||||
blocks: true
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -340,6 +340,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
|> maybe_put_unread_notification_count(user, opts[:for])
|
||||
|> maybe_put_email_address(user, opts[:for])
|
||||
|> maybe_put_mute_expires_at(user, opts[:for], opts)
|
||||
|> maybe_put_block_expires_at(user, opts[:for], opts)
|
||||
|> maybe_show_birthday(user, opts[:for])
|
||||
end
|
||||
|
||||
|
@ -476,6 +477,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
|
||||
defp maybe_put_mute_expires_at(data, _, _, _), do: data
|
||||
|
||||
defp maybe_put_block_expires_at(data, %User{} = user, target, %{blocks: true}) do
|
||||
Map.put(
|
||||
data,
|
||||
:block_expires_at,
|
||||
UserRelationship.get_block_expire_date(target, user)
|
||||
)
|
||||
end
|
||||
|
||||
defp maybe_put_block_expires_at(data, _, _, _), do: data
|
||||
|
||||
defp maybe_show_birthday(data, %User{id: user_id} = user, %User{id: user_id}) do
|
||||
data
|
||||
|> Kernel.put_in([:pleroma, :birthday], user.birthday)
|
||||
|
|
|
@ -157,7 +157,8 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
|||
"pleroma:bookmark_folders",
|
||||
if Pleroma.Language.LanguageDetector.configured?() do
|
||||
"pleroma:language_detection"
|
||||
end
|
||||
end,
|
||||
"pleroma:block_expiration"
|
||||
]
|
||||
|> Enum.filter(& &1)
|
||||
end
|
||||
|
|
|
@ -5,9 +5,13 @@
|
|||
defmodule Pleroma.Workers.MuteExpireWorker do
|
||||
use Oban.Worker, queue: :background
|
||||
|
||||
alias Pleroma.User
|
||||
|
||||
@impl true
|
||||
def perform(%Job{args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id}}) do
|
||||
Pleroma.User.unmute(muter_id, mutee_id)
|
||||
def perform(%Job{
|
||||
args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id}
|
||||
}) do
|
||||
User.unmute(muter_id, mutee_id)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
@ -18,6 +22,17 @@ defmodule Pleroma.Workers.MuteExpireWorker do
|
|||
:ok
|
||||
end
|
||||
|
||||
def perform(%Job{
|
||||
args: %{"op" => "unblock_user", "blocker_id" => blocker_id, "blocked_id" => blocked_id}
|
||||
}) do
|
||||
Pleroma.Web.CommonAPI.unblock(
|
||||
User.get_cached_by_id(blocked_id),
|
||||
User.get_cached_by_id(blocker_id)
|
||||
)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(5)
|
||||
end
|
||||
|
|
|
@ -111,6 +111,17 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
end
|
||||
end
|
||||
|
||||
test "add expiring block", %{blocker: blocker, blocked: blocked} do
|
||||
{:ok, _} = CommonAPI.block(blocked, blocker, %{expires_in: 60})
|
||||
assert User.blocks?(blocker, blocked)
|
||||
|
||||
worker = Pleroma.Workers.MuteExpireWorker
|
||||
args = %{"op" => "unblock_user", "blocker_id" => blocker.id, "blocked_id" => blocked.id}
|
||||
|
||||
assert :ok = perform_job(worker, args)
|
||||
refute User.blocks?(blocker, blocked)
|
||||
end
|
||||
|
||||
test "it blocks and does not federate if outgoing blocks are disabled", %{
|
||||
blocker: blocker,
|
||||
blocked: blocked
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue