Merge branch 'bites-pleroma' into fork

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-10-21 20:47:18 +02:00
commit c396c2cc47
9 changed files with 130 additions and 7 deletions

View file

@ -747,7 +747,8 @@
events_actions: {10_000, 15},
password_reset: {1_800_000, 5},
account_confirmation_resend: {8_640_000, 5},
ap_routes: {60_000, 15}
ap_routes: {60_000, 15},
bites: {10_000, 10}
config :pleroma, Pleroma.Workers.PurgeExpiredActivity, enabled: true, min_lifetime: 600

View file

@ -115,7 +115,9 @@ defmodule Pleroma.Constants do
"Announce",
"Undo",
"Flag",
"EmojiReact"
"EmojiReact",
"Bite",
"Join"
]
)

View file

@ -38,7 +38,7 @@ defp validate_data(cng) do
|> validate_required([:id, :type, :actor, :to, :target])
|> validate_inclusion(:type, ["Bite"])
|> validate_actor_presence()
|> validate_actor_presence(field_name: :target)
|> validate_object_or_user_presence(field_name: :target)
end
def cast_and_validate(data) do

View file

@ -497,6 +497,32 @@ def handle_incoming(
end
end
def handle_incoming(
%{"type" => "Bite", "target" => target_id} = data,
_options
) do
target_id =
cond do
%User{ap_id: actor_id} = User.get_by_ap_id(target_id) ->
actor_id
%Object{data: data} = Object.get_by_ap_id(target_id) ->
data["actor"] || data["attributedTo"]
true ->
target_id
end
with data = Map.put(data, "target", target_id),
:ok <- ObjectValidator.fetch_actor_and_object(data),
{:ok, activity, _meta} <-
Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
else
e -> {:error, e}
end
end
def handle_incoming(%{"type" => type} = data, _options)
when type in ~w{Like EmojiReact Announce Add Remove} do
with :ok <- ObjectValidator.fetch_actor_and_object(data),

View file

@ -1070,6 +1070,7 @@ def fetch_latest_bite(
|> maybe_exclude_activity_id(exclude_activity)
|> Activity.Queries.by_object_id(bitten_ap_id)
|> order_by([activity], fragment("? desc nulls last", activity.id))
|> exclude_rejected()
|> limit(1)
|> Repo.one()
end
@ -1080,4 +1081,14 @@ defp maybe_exclude_activity_id(query, %Activity{id: activity_id}) do
query
|> where([a], a.id != ^activity_id)
end
defp exclude_rejected(query) do
rejected_activities =
"Reject"
|> Activity.Queries.by_type()
|> select([a], fragment("?->>'object'", a.data))
query
|> where([a], fragment("?->>'id'", a.data) not in subquery(rejected_activities))
end
end

View file

@ -9,14 +9,13 @@ defmodule Pleroma.Web.MastodonAPI.BiteController do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Plugs.OAuthScopesPlug
# alias Pleroma.Web.Plugs.RateLimiter
alias Pleroma.Web.Plugs.RateLimiter
plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["write:bite"]} when action == :bite)
plug(OAuthScopesPlug, %{scopes: ["write:bites"]} when action == :bite)
# plug(RateLimiter, [name: :relations_actions] when action in @relationship_actions)
# plug(RateLimiter, [name: :app_account_creation] when action == :create)
plug(RateLimiter, name: :bites)
plug(:assign_account_by_id)

View file

@ -44,6 +44,7 @@
"formerRepresentations": "litepub:formerRepresentations",
"sm": "http://smithereen.software/ns#",
"nonAnonymous": "sm:nonAnonymous",
<<<<<<< HEAD
"votersCount": "toot:votersCount",
"mz": "https://joinmobilizon.org/ns#",
"joinMode": {
@ -67,6 +68,8 @@
"@id": "schema:location",
"@type": "schema:Place"
},
=======
>>>>>>> bites-pleroma
"Bite": "https://ns.mia.jetzt/as#Bite"
}
]

View file

@ -0,0 +1,51 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.BiteValidationTest do
use Pleroma.DataCase, async: true
alias Pleroma.Web.ActivityPub.ObjectValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.BiteValidator
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
describe "bites" do
setup do
biting = insert(:user)
bitten = insert(:user)
valid_bite = %{
"id" => Utils.generate_activity_id(),
"type" => "Bite",
"actor" => biting.ap_id,
"target" => bitten.ap_id,
"to" => [bitten.ap_id]
}
%{valid_bite: valid_bite, biting: biting, bitten: bitten}
end
test "returns ok when called in the ObjectValidator", %{valid_bite: valid_bite} do
{:ok, object, _meta} = ObjectValidator.validate(valid_bite, [])
assert "id" in Map.keys(object)
end
test "is valid for a valid object", %{valid_bite: valid_bite} do
assert BiteValidator.cast_and_validate(valid_bite).valid?
end
test "is valid when biting an object", %{valid_bite: valid_bite, bitten: bitten} do
{:ok, activity} = CommonAPI.post(bitten, %{status: "uguu"})
valid_bite =
valid_bite
|> Map.put("target", activity.data["object"])
assert BiteValidator.cast_and_validate(valid_bite).valid?
end
end
end

View file

@ -0,0 +1,30 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.BiteControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
setup do: oauth_access(["write:bites"])
test "bites a user", %{conn: conn} do
%{id: bitten_id} = insert(:user)
response =
conn
|> post("/api/v1/bite?id=#{bitten_id}")
|> json_response_and_validate_schema(200)
assert response == %{}
end
test "self harm is not supported", %{conn: conn, user: %{id: self_id}} do
response =
conn
|> post("/api/v1/bite?id=#{self_id}")
|> json_response_and_validate_schema(400)
assert %{"error" => "Can not bite yourself"} = response
end
end