From 0f0207d60d79bd88bb779a54881788b90ea1ac87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Sun, 13 Oct 2024 14:59:48 +0200 Subject: [PATCH 01/13] Update source link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- mix.exs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mix.exs b/mix.exs index 3e951e578a..ed206cc0d0 100644 --- a/mix.exs +++ b/mix.exs @@ -20,10 +20,10 @@ def project do deps: deps(), test_coverage: [tool: :covertool, summary: true], # Docs - homepage_url: "https://github.com/mkljczk/pleroma", - source_url: "https://github.com/mkljczk/pleroma", + homepage_url: "https://github.com/mkljczk/pl", + source_url: "https://github.com/mkljczk/pl", docs: [ - source_url_pattern: "https://github.com/mkljczk/pleroma/blob/develop/%{path}#L%{line}", + source_url_pattern: "https://github.com/mkljczk/pl/blob/develop/%{path}#L%{line}", logo: "priv/static/images/logo.png", extras: ["README.md", "CHANGELOG.md"] ++ Path.wildcard("docs/**/*.md"), groups_for_extras: [ From 2cdc1985a5e3533515cd468d9b4916c086c92e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Sun, 13 Oct 2024 15:39:13 +0200 Subject: [PATCH 02/13] Visual updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- priv/static/instance/static.css | Bin 6747 -> 6845 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/priv/static/instance/static.css b/priv/static/instance/static.css index 183f9156dda27f3630ea50deea80e956aa5e1e4b..f3b77aaa6b459db3110ba699a94df074d2238c2d 100644 GIT binary patch delta 80 zcmca@ve$G&J*!YrdXk2bv5}5~k&z*Yu+ZGx#=1&m@>x+8jimgdl++^Kr2LYS{9G#q f!-5Kh;{2S<6a|nb6H6ThV^bXk6BEtJs#0bE50MyX delta 24 gcmdmMdfQ|}JuAC%s%ffuYSQM3tgA#OPm Date: Tue, 27 Aug 2024 17:33:03 +0200 Subject: [PATCH 03/13] Allow to bite users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- .gitattributes | 1 + lib/pleroma/notification.ex | 9 +- lib/pleroma/web/activity_pub/builder.ex | 11 ++ .../web/activity_pub/object_validator.ex | 4 +- .../accept_reject_validator.ex | 14 +- .../object_validators/bite_validator.ex | 49 +++++++ lib/pleroma/web/activity_pub/side_effects.ex | 124 ++++++++++++++---- .../web/activity_pub/transmogrifier.ex | 4 +- lib/pleroma/web/activity_pub/utils.ex | 32 +++++ lib/pleroma/web/api_spec.ex | 2 +- .../web/api_spec/operations/bite_operation.ex | 33 +++++ .../operations/notification_operation.ex | 4 +- lib/pleroma/web/common_api.ex | 7 + .../controllers/bite_controller.ex | 39 ++++++ .../controllers/notification_controller.ex | 1 + .../web/mastodon_api/views/instance_view.ex | 3 +- .../mastodon_api/views/notification_view.ex | 2 +- lib/pleroma/web/nodeinfo/nodeinfo.ex | 4 + lib/pleroma/web/router.ex | 2 + ...7000000_add_bite_to_notifications_enum.exs | 52 ++++++++ priv/static/schemas/litepub-0.1.jsonld | 3 +- 21 files changed, 364 insertions(+), 36 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/object_validators/bite_validator.ex create mode 100644 lib/pleroma/web/api_spec/operations/bite_operation.ex create mode 100644 lib/pleroma/web/mastodon_api/controllers/bite_controller.ex create mode 100644 priv/repo/migrations/20240827000000_add_bite_to_notifications_enum.exs diff --git a/.gitattributes b/.gitattributes index eb0c947577..83285fb974 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,7 @@ *.exs diff=elixir priv/static/instance/static.css diff=css +priv/static/schemas/litepub-0.1.jsonld diff # Most of js/css files included in the repo are minified bundles, # and we don't want to search/diff those as text files. diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 75f4ba5033..232568db5a 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -74,6 +74,7 @@ def unread_notifications_count(%User{id: user_id}) do reblog poll status + bite } def changeset(%Notification{} = notification, attrs) do @@ -367,7 +368,7 @@ def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = act end def create_notifications(%Activity{data: %{"type" => type}} = activity) - when type in ["Follow", "Like", "Announce", "Move", "EmojiReact", "Flag", "Update"] do + when type in ["Follow", "Like", "Announce", "Move", "EmojiReact", "Flag", "Update", "Bite"] do do_create_notifications(activity) end @@ -425,6 +426,9 @@ defp type_from_activity(%{data: %{"type" => type}} = activity) do "Update" -> "update" + "Bite" -> + "bite" + t -> raise "No notification type for activity type #{t}" end @@ -501,7 +505,8 @@ def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, lo "Move", "EmojiReact", "Flag", - "Update" + "Update", + "Bite" ] do potential_receiver_ap_ids = get_potential_receiver_ap_ids(activity) diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index 2a1e562788..5c72f116c1 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -431,4 +431,15 @@ def unpin(%User{} = user, object) do defp pinned_url(nickname) when is_binary(nickname) do Pleroma.Web.Router.Helpers.activity_pub_url(Pleroma.Web.Endpoint, :pinned, nickname) end + + def bite(%User{} = biting, %User{} = bitten) do + {:ok, + %{ + "id" => Utils.generate_activity_id(), + "target" => bitten.ap_id, + "actor" => biting.ap_id, + "type" => "Bite", + "to" => [bitten.ap_id] + }, []} + end end diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index 35774d4107..a506504560 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -24,6 +24,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AudioImageVideoValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.BiteValidator alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator @@ -193,7 +194,7 @@ def validate( def validate(%{"type" => type} = object, meta) when type in ~w[Accept Reject Follow Update Like EmojiReact Announce - ChatMessage Answer] do + ChatMessage Answer Bite] do validator = case type do "Accept" -> AcceptRejectValidator @@ -205,6 +206,7 @@ def validate(%{"type" => type} = object, meta) "Announce" -> AnnounceValidator "ChatMessage" -> ChatMessageValidator "Answer" -> AnswerValidator + "Bite" -> BiteValidator end with {:ok, object} <- diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex index 03ab83347f..ce695c956f 100644 --- a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex @@ -32,7 +32,7 @@ defp validate_data(cng) do |> validate_required([:id, :type, :actor, :to, :object]) |> validate_inclusion(:type, ["Accept", "Reject"]) |> validate_actor_presence() - |> validate_object_presence(allowed_types: ["Follow"]) + |> validate_object_presence(allowed_types: ["Follow", "Bite"]) |> validate_accept_reject_rights() end @@ -44,8 +44,8 @@ def cast_and_validate(data) do def validate_accept_reject_rights(cng) do with object_id when is_binary(object_id) <- get_field(cng, :object), - %Activity{data: %{"object" => followed_actor}} <- Activity.get_by_ap_id(object_id), - true <- followed_actor == get_field(cng, :actor) do + %Activity{} = activity <- Activity.get_by_ap_id(object_id), + true <- validate_actor(activity, get_field(cng, :actor)) do cng else _e -> @@ -53,4 +53,12 @@ def validate_accept_reject_rights(cng) do |> add_error(:actor, "can't accept or reject the given activity") end end + + defp validate_actor(%Activity{data: %{"type" => "Follow", "object" => followed_actor}}, actor) do + followed_actor == actor + end + + defp validate_actor(%Activity{data: %{"type" => "Bite", "target" => biten_actor}}, actor) do + biten_actor == actor + end end diff --git a/lib/pleroma/web/activity_pub/object_validators/bite_validator.ex b/lib/pleroma/web/activity_pub/object_validators/bite_validator.ex new file mode 100644 index 0000000000..a2e0bac85e --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/bite_validator.ex @@ -0,0 +1,49 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2024 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.BiteValidator do + use Ecto.Schema + + alias Pleroma.EctoType.ActivityPub.ObjectValidators + + import Ecto.Changeset + import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + + @primary_key false + + embedded_schema do + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end + + field(:target, ObjectValidators.ObjectID) + end + + def cast_data(data) do + %__MODULE__{} + |> cast(data |> fix_object(), __schema__(:fields)) + end + + defp fix_object(data) do + Map.put(data, "object", data["target"]) + end + + defp validate_data(cng) do + cng + |> validate_required([:id, :type, :actor, :to, :target]) + |> validate_inclusion(:type, ["Bite"]) + |> validate_actor_presence() + |> validate_actor_presence(field_name: :target) + end + + def cast_and_validate(data) do + data + |> cast_data + |> validate_data + end +end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index d6d4036719..6d7aada2bc 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -42,23 +42,16 @@ def handle(object, meta \\ []) # - Sends a notification @impl true def handle( - %{ - data: %{ - "actor" => actor, - "type" => "Accept", - "object" => follow_activity_id - } - } = object, + %{data: %{"actor" => actor, "type" => "Accept", "object" => activity_id}} = object, meta ) do - with %Activity{actor: follower_id} = follow_activity <- - Activity.get_by_ap_id(follow_activity_id), - %User{} = followed <- User.get_cached_by_ap_id(actor), - %User{} = follower <- User.get_cached_by_ap_id(follower_id), - {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"), - {:ok, _follower, followed} <- - FollowingRelationship.update(follower, followed, :follow_accept) do - Notification.update_notification_type(followed, follow_activity) + with %Activity{} = activity <- + Activity.get_by_ap_id(activity_id) do + handle_accepted(activity, actor) + + if activity.data["type"] === "Join" do + Notification.create_notifications(object) + end end {:ok, object, meta} @@ -74,18 +67,14 @@ def handle( data: %{ "actor" => actor, "type" => "Reject", - "object" => follow_activity_id + "object" => activity_id } } = object, meta ) do - with %Activity{actor: follower_id} = follow_activity <- - Activity.get_by_ap_id(follow_activity_id), - %User{} = followed <- User.get_cached_by_ap_id(actor), - %User{} = follower <- User.get_cached_by_ap_id(follower_id), - {:ok, _follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject") do - FollowingRelationship.update(follower, followed, :follow_reject) - Notification.dismiss(follow_activity) + with %Activity{} = activity <- + Activity.get_by_ap_id(activity_id) do + handle_rejected(activity, actor) end {:ok, object, meta} @@ -427,12 +416,93 @@ def handle(%{data: %{"type" => "Remove"} = data} = object, meta) do end end + # Task this handles + # - Bites + # - Sends a notification + @impl true + def handle( + %{ + data: %{ + "id" => bite_id, + "type" => "Bite", + "target" => bitten_user, + "actor" => biting_user + } + } = object, + meta + ) do + with %User{} = biting <- User.get_cached_by_ap_id(biting_user), + %User{} = bitten <- User.get_cached_by_ap_id(bitten_user), + {:previous_bite, previous_bite} <- + {:previous_bite, Utils.fetch_latest_bite(biting, bitten, object)}, + {:reverse_bite, reverse_bite} <- + {:reverse_bite, Utils.fetch_latest_bite(bitten, biting)}, + {:can_bite, true, _} <- {:can_bite, can_bite?(previous_bite, reverse_bite), bitten} do + if bitten.local do + {:ok, accept_data, _} = Builder.accept(bitten, object) + {:ok, _activity, _} = Pipeline.common_pipeline(accept_data, local: true) + end + + if reverse_bite do + Notification.dismiss(reverse_bite) + end + + {:ok, notifications} = Notification.create_notifications(object) + + meta + |> add_notifications(notifications) + else + {:can_bite, false, bitten} -> + {:ok, reject_data, _} = Builder.reject(bitten, object) + {:ok, _activity, _} = Pipeline.common_pipeline(reject_data, local: true) + meta + + _ -> + meta + end + + updated_object = Activity.get_by_ap_id(bite_id) + + {:ok, updated_object, meta} + end + # Nothing to do @impl true def handle(object, meta) do {:ok, object, meta} end + defp handle_accepted( + %Activity{actor: follower_id, data: %{"type" => "Follow"}} = follow_activity, + actor + ) do + with %User{} = followed <- User.get_cached_by_ap_id(actor), + %User{} = follower <- User.get_cached_by_ap_id(follower_id), + {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"), + {:ok, _follower, followed} <- + FollowingRelationship.update(follower, followed, :follow_accept) do + Notification.update_notification_type(followed, follow_activity) + end + end + + defp handle_accepted(_, _), do: nil + + defp handle_rejected( + %Activity{actor: follower_id, data: %{"type" => "Follow"}} = follow_activity, + actor + ) do + with %User{} = followed <- User.get_cached_by_ap_id(actor), + %User{} = follower <- User.get_cached_by_ap_id(follower_id), + {:ok, _follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject") do + FollowingRelationship.update(follower, followed, :follow_reject) + Notification.dismiss(follow_activity) + end + end + + defp handle_rejected(%Activity{data: %{"type" => "Bite"}} = bite_activity, _actor) do + Notification.dismiss(bite_activity) + end + defp handle_update_user( %{data: %{"type" => "Update", "object" => updated_object}} = object, meta @@ -632,4 +702,12 @@ def handle_after_transaction(meta) do |> stream_notifications() |> send_streamables() end + + defp can_bite?(nil, _), do: true + + defp can_bite?(_, nil), do: false + + defp can_bite?(previous_bite, reverse_bite) do + NaiveDateTime.diff(previous_bite.inserted_at, reverse_bite.inserted_at) < 0 + end end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 2f8a7f8f27..f130f1e484 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -488,7 +488,7 @@ def handle_incoming( end def handle_incoming(%{"type" => type} = data, _options) - when type in ~w{Like EmojiReact Announce Add Remove} do + when type in ~w{Like EmojiReact Announce Add Remove Bite} do with :ok <- ObjectValidator.fetch_actor_and_object(data), {:ok, activity, _meta} <- Pipeline.common_pipeline(data, local: false) do @@ -502,7 +502,7 @@ def handle_incoming( %{"type" => type} = data, _options ) - when type in ~w{Update Block Follow Accept Reject} do + when type in ~w{Update Block Follow Accept Reject Bite} do with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 6c792804df..f6570cdde9 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -949,4 +949,36 @@ def maybe_handle_group_posts(activity) do |> Enum.reject(&User.blocks?(&1, poster)) |> Enum.each(&Pleroma.Web.CommonAPI.repeat(activity.id, &1)) end + + def make_bite_data(biting, bitten, activity_id) do + %{ + "type" => "Bite", + "actor" => biting.ap_id, + "to" => [bitten.ap_id], + "target" => bitten.ap_id + } + |> Maps.put_if_present("id", activity_id) + end + + def fetch_latest_bite( + %User{ap_id: biting_ap_id}, + %{ap_id: bitten_ap_id}, + exclude_activity \\ nil + ) do + "Bite" + |> Activity.Queries.by_type() + |> where(actor: ^biting_ap_id) + |> maybe_exclude_activity_id(exclude_activity) + |> Activity.Queries.by_object_id(bitten_ap_id) + |> order_by([activity], fragment("? desc nulls last", activity.id)) + |> limit(1) + |> Repo.one() + end + + defp maybe_exclude_activity_id(query, nil), do: query + + defp maybe_exclude_activity_id(query, %Activity{id: activity_id}) do + query + |> where([a], a.id != ^activity_id) + end end diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex index 314782818c..7d665bbc48 100644 --- a/lib/pleroma/web/api_spec.ex +++ b/lib/pleroma/web/api_spec.ex @@ -87,7 +87,7 @@ def spec(opts \\ []) do "x-tagGroups": [ %{ "name" => "Accounts", - "tags" => ["Account actions", "Retrieve account information", "Scrobbles"] + "tags" => ["Account actions", "Bites", "Retrieve account information", "Scrobbles"] }, %{ "name" => "Administration", diff --git a/lib/pleroma/web/api_spec/operations/bite_operation.ex b/lib/pleroma/web/api_spec/operations/bite_operation.ex new file mode 100644 index 0000000000..9fcbf643d5 --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/bite_operation.ex @@ -0,0 +1,33 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2024 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.BiteOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.Schemas.ApiError + + @spec open_api_operation(atom) :: Operation.t() + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def bite_operation do + %Operation{ + tags: ["Bites"], + summary: "Bite", + operationId: "BiteController.bite", + security: [%{"oAuth" => ["write:bites"]}], + description: "Bite the given account", + parameters: [ + Operation.parameter(:id, :query, :string, "Bitten account ID") + ], + responses: %{ + 200 => Operation.response("Empty object", "application/json", %Schema{type: :object}), + 400 => Operation.response("Error", "application/json", ApiError), + 404 => Operation.response("Error", "application/json", ApiError) + } + } + end +end diff --git a/lib/pleroma/web/api_spec/operations/notification_operation.ex b/lib/pleroma/web/api_spec/operations/notification_operation.ex index 94d1f6b82a..8dd78da43d 100644 --- a/lib/pleroma/web/api_spec/operations/notification_operation.ex +++ b/lib/pleroma/web/api_spec/operations/notification_operation.ex @@ -211,7 +211,8 @@ defp notification_type do "status", "update", "admin.sign_up", - "admin.report" + "admin.report", + "bite" ], description: """ The type of event that resulted in the notification. @@ -229,6 +230,7 @@ defp notification_type do - `update` - A status you boosted has been edited - `admin.sign_up` - Someone signed up (optionally sent to admins) - `admin.report` - A new report has been filed + - `bite` - Someone bit you """ } end diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex index 412424dae8..fb26207973 100644 --- a/lib/pleroma/web/common_api.ex +++ b/lib/pleroma/web/common_api.ex @@ -729,4 +729,11 @@ defp maybe_cancel_jobs(%Activity{id: activity_id}) do end defp maybe_cancel_jobs(_), do: {:ok, 0} + + def bite(biting, bitten) do + with {:ok, bite_data, _} <- Builder.bite(biting, bitten), + {:ok, activity, _} <- Pipeline.common_pipeline(bite_data, local: true) do + {:ok, biting, bitten, activity} + end + end end diff --git a/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex b/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex new file mode 100644 index 0000000000..69d865cb9b --- /dev/null +++ b/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex @@ -0,0 +1,39 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2024 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.BiteController do + use Pleroma.Web, :controller + + import Pleroma.Web.ControllerHelper, only: [assign_account_by_id: 2, json_response: 3] + + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.Plugs.OAuthScopesPlug + # alias Pleroma.Web.Plugs.RateLimiter + + plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false) + + plug(OAuthScopesPlug, %{scopes: ["write:bite"]} when action == :bite) + + # plug(RateLimiter, [name: :relations_actions] when action in @relationship_actions) + # plug(RateLimiter, [name: :app_account_creation] when action == :create) + + plug(:assign_account_by_id) + + action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.BiteOperation + + @doc "POST /api/v1/bite" + def bite(%{assigns: %{user: %{id: id}, account: %{id: id}}}, _params) do + {:error, "Can not bite yourself"} + end + + def bite(%{assigns: %{user: biting, account: bitten}} = conn, _) do + with {:ok, _, _, _} <- CommonAPI.bite(biting, bitten) do + json_response(conn, :ok, %{}) + else + {:error, message} -> json_response(conn, :forbidden, %{error: message}) + end + end +end diff --git a/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex b/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex index afd83b7857..948434f6da 100644 --- a/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex @@ -35,6 +35,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do poll update status + bite } # GET /api/v1/notifications diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index 913684928f..e660152fa9 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -145,7 +145,8 @@ def features do end, "pleroma:get:main/ostatus", "pleroma:group_actors", - "pleroma:bookmark_folders" + "pleroma:bookmark_folders", + "pleroma:bites" ] |> Enum.filter(& &1) end diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex index c277af98b5..94efe0f55d 100644 --- a/lib/pleroma/web/mastodon_api/views/notification_view.ex +++ b/lib/pleroma/web/mastodon_api/views/notification_view.ex @@ -138,7 +138,7 @@ def render( "pleroma:report" -> put_report(response, activity) - type when type in ["follow", "follow_request"] -> + type when type in ["follow", "follow_request", "bite"] -> response end end diff --git a/lib/pleroma/web/nodeinfo/nodeinfo.ex b/lib/pleroma/web/nodeinfo/nodeinfo.ex index 4d5a9a57fe..d7da8cdcf7 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo.ex @@ -74,6 +74,10 @@ def get_nodeinfo("2.0") do features: features, restrictedNicknames: Config.get([Pleroma.User, :restricted_nicknames]), skipThreadContainment: Config.get([:instance, :skip_thread_containment], false) + }, + operations: %{ + "com.shinolabs.api.bite": ["1.0.0"], + "jetzt.mia.ns.activitypub.accept.bite": ["1.0.0"] } } end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 0423ca9e22..4821bf9684 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -755,6 +755,8 @@ defmodule Pleroma.Web.Router do get("/announcements", AnnouncementController, :index) post("/announcements/:id/dismiss", AnnouncementController, :mark_read) + + post("/bite", BiteController, :bite) end scope "/api/v1", Pleroma.Web.MastodonAPI do diff --git a/priv/repo/migrations/20240827000000_add_bite_to_notifications_enum.exs b/priv/repo/migrations/20240827000000_add_bite_to_notifications_enum.exs new file mode 100644 index 0000000000..b8b9c76b18 --- /dev/null +++ b/priv/repo/migrations/20240827000000_add_bite_to_notifications_enum.exs @@ -0,0 +1,52 @@ +defmodule Pleroma.Repo.Migrations.AddBiteToNotificationsEnum do + use Ecto.Migration + + @disable_ddl_transaction true + + def up do + """ + alter type notification_type add value 'bite' + """ + |> execute() + end + + # 20220605185734_add_update_to_notifications_enum.exs + def down do + alter table(:notifications) do + modify(:type, :string) + end + + """ + delete from notifications where type = 'bite' + """ + |> execute() + + """ + drop type if exists notification_type + """ + |> execute() + + """ + create type notification_type as enum ( + 'follow', + 'follow_request', + 'mention', + 'move', + 'pleroma:emoji_reaction', + 'pleroma:chat_mention', + 'reblog', + 'favourite', + 'pleroma:report', + 'poll', + 'update' + ) + """ + |> execute() + + """ + alter table notifications + alter column type type notification_type using (type::notification_type) + """ + |> execute() + end +end diff --git a/priv/static/schemas/litepub-0.1.jsonld b/priv/static/schemas/litepub-0.1.jsonld index 3569165a40..4bc8d0ba82 100644 --- a/priv/static/schemas/litepub-0.1.jsonld +++ b/priv/static/schemas/litepub-0.1.jsonld @@ -43,7 +43,8 @@ "vcard": "http://www.w3.org/2006/vcard/ns#", "formerRepresentations": "litepub:formerRepresentations", "sm": "http://smithereen.software/ns#", - "nonAnonymous": "sm:nonAnonymous" + "nonAnonymous": "sm:nonAnonymous", + "Bite": "https://ns.mia.jetzt/as#Bite" } ] } From c2f32421772d1f2b333ffc3267b979cb6e365532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Thu, 29 Aug 2024 18:24:31 +0200 Subject: [PATCH 04/13] wip test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- config/config.exs | 3 +- .../controllers/bite_controller.ex | 7 ++--- .../controllers/bite_controller_test.exs | 30 +++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 test/pleroma/web/mastodon_api/controllers/bite_controller_test.exs diff --git a/config/config.exs b/config/config.exs index 07e98011d0..033f1c1e1d 100644 --- a/config/config.exs +++ b/config/config.exs @@ -727,7 +727,8 @@ status_id_action: {60_000, 3}, 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 diff --git a/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex b/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex index 69d865cb9b..48552a8dac 100644 --- a/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex @@ -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) diff --git a/test/pleroma/web/mastodon_api/controllers/bite_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/bite_controller_test.exs new file mode 100644 index 0000000000..dff5d01a65 --- /dev/null +++ b/test/pleroma/web/mastodon_api/controllers/bite_controller_test.exs @@ -0,0 +1,30 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2024 Pleroma Authors +# 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 From ad0ebe666cfdd247bc467465dbe816808ca73f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 18 Oct 2024 10:23:29 +0200 Subject: [PATCH 05/13] Add Bite to allowed activity types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- lib/pleroma/constants.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index 2828c79a92..1feb15a8f5 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -100,7 +100,8 @@ defmodule Pleroma.Constants do "Announce", "Undo", "Flag", - "EmojiReact" + "EmojiReact", + "Bite" ] ) From e79dcd2bfec23c45e88d51653a542a59508b651f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 18 Oct 2024 15:46:00 +0200 Subject: [PATCH 06/13] Fix rejecting duplicated bites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- lib/pleroma/web/activity_pub/utils.ex | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index f6570cdde9..dac42b7948 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -971,6 +971,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 @@ -981,4 +982,13 @@ 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 From 61410ad8861555950f7fe33dddba7acd8e9d23f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 18 Oct 2024 17:59:46 +0200 Subject: [PATCH 07/13] Accept bites for objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- .../object_validators/bite_validator.ex | 2 +- .../web/activity_pub/transmogrifier.ex | 29 ++++++++++++++++++- lib/pleroma/web/activity_pub/utils.ex | 7 +++-- .../controllers/bite_controller.ex | 2 +- .../controllers/bite_controller_test.exs | 4 +-- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/bite_validator.ex b/lib/pleroma/web/activity_pub/object_validators/bite_validator.ex index a2e0bac85e..51e58640e3 100644 --- a/lib/pleroma/web/activity_pub/object_validators/bite_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/bite_validator.ex @@ -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 diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index f130f1e484..8f242c58e2 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -487,8 +487,35 @@ 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) + when is_binary(data["actor"]) or is_binary(data["attributedTo"]) -> + data["actor"] || data["attributedTo"] + + _ -> + 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 Bite} do + when type in ~w{Like EmojiReact Announce Add Remove} do with :ok <- ObjectValidator.fetch_actor_and_object(data), {:ok, activity, _meta} <- Pipeline.common_pipeline(data, local: false) do diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index dac42b7948..65cdbdc55d 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -984,9 +984,10 @@ defp maybe_exclude_activity_id(query, %Activity{id: activity_id}) do end defp exclude_rejected(query) do - rejected_activities = "Reject" - |> Activity.Queries.by_type() - |> select([a], fragment("?->>'object'", a.data)) + 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)) diff --git a/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex b/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex index 48552a8dac..b9b1310103 100644 --- a/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex @@ -15,7 +15,7 @@ defmodule Pleroma.Web.MastodonAPI.BiteController do plug(OAuthScopesPlug, %{scopes: ["write:bites"]} when action == :bite) - plug(RateLimiter, [name: :bites]) + plug(RateLimiter, name: :bites) plug(:assign_account_by_id) diff --git a/test/pleroma/web/mastodon_api/controllers/bite_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/bite_controller_test.exs index dff5d01a65..96cd38e762 100644 --- a/test/pleroma/web/mastodon_api/controllers/bite_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/bite_controller_test.exs @@ -16,7 +16,7 @@ test "bites a user", %{conn: conn} do |> post("/api/v1/bite?id=#{bitten_id}") |> json_response_and_validate_schema(200) - assert response == %{} + assert response == %{} end test "self harm is not supported", %{conn: conn, user: %{id: self_id}} do @@ -25,6 +25,6 @@ test "self harm is not supported", %{conn: conn, user: %{id: self_id}} do |> post("/api/v1/bite?id=#{self_id}") |> json_response_and_validate_schema(400) - assert %{"error" => "Can not bite yourself"} = response + assert %{"error" => "Can not bite yourself"} = response end end From 181581dd6b87f7bc26c2f8d16cc8131e848b610f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 18 Oct 2024 19:50:32 +0200 Subject: [PATCH 08/13] Add test for BiteValidator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- .../web/activity_pub/transmogrifier.ex | 7 ++- .../object_validators/bite_validator_test.exs | 51 +++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 test/pleroma/web/activity_pub/object_validators/bite_validator_test.exs diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 8f242c58e2..55f4fcfc0b 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -489,18 +489,17 @@ def handle_incoming( def handle_incoming( %{"type" => "Bite", "target" => target_id} = data, - options + _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) - when is_binary(data["actor"]) or is_binary(data["attributedTo"]) -> + %Object{data: data} = Object.get_by_ap_id(target_id) -> data["actor"] || data["attributedTo"] - _ -> + true -> target_id end diff --git a/test/pleroma/web/activity_pub/object_validators/bite_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/bite_validator_test.exs new file mode 100644 index 0000000000..94e433d5af --- /dev/null +++ b/test/pleroma/web/activity_pub/object_validators/bite_validator_test.exs @@ -0,0 +1,51 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2024 Pleroma Authors +# 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 From 46dc19275ba537ca1854a733f4373af6b1b7e5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Sun, 20 Oct 2024 12:01:41 +0200 Subject: [PATCH 09/13] Fix the old poll votes count bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- lib/pleroma/object/updater.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pleroma/object/updater.ex b/lib/pleroma/object/updater.ex index 8fd7da0a42..27c315acb3 100644 --- a/lib/pleroma/object/updater.ex +++ b/lib/pleroma/object/updater.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Object.Updater do require Pleroma.Constants + alias Pleroma.Maps alias Pleroma.Object alias Pleroma.Repo alias Pleroma.Workers.EventReminderWorker @@ -116,6 +117,7 @@ defp maybe_update_poll(to_be_updated, updated_object) do # Choices are the same, but counts are different to_be_updated |> Map.put(key, updated_object[key]) + |> Maps.put_if_present("votersCount", updated_object["votersCount"]) else # Choices (or vote type) have changed, do not allow this _ -> to_be_updated From f048637b41a81c527b6f3c0f5e90db91971f3842 Mon Sep 17 00:00:00 2001 From: Mark Jaroski Date: Mon, 21 Oct 2024 00:10:27 +0000 Subject: [PATCH 10/13] Some tidying and grammer improvements for these installation docs, based on my experience installing Pleroma on Ubuntu 24.04 a few minutes ago. --- changelog.d/debian-install-improve.skip | 1 + docs/installation/debian_based_en.md | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 changelog.d/debian-install-improve.skip diff --git a/changelog.d/debian-install-improve.skip b/changelog.d/debian-install-improve.skip new file mode 100644 index 0000000000..6068a30664 --- /dev/null +++ b/changelog.d/debian-install-improve.skip @@ -0,0 +1 @@ +Fixed a formatting issue that had a required commend embedded in a textblock, and change the language to make it a bit more idiomatic. \ No newline at end of file diff --git a/docs/installation/debian_based_en.md b/docs/installation/debian_based_en.md index b61e4addd6..21cfe2bff3 100644 --- a/docs/installation/debian_based_en.md +++ b/docs/installation/debian_based_en.md @@ -69,12 +69,18 @@ cd /opt/pleroma sudo -Hu pleroma mix deps.get ``` -* Generate the configuration: `sudo -Hu pleroma MIX_ENV=prod mix pleroma.instance gen` +* Generate the configuration: + +```shell +sudo -Hu pleroma MIX_ENV=prod mix pleroma.instance gen` +``` + +* During this process: * Answer with `yes` if it asks you to install `rebar3`. * This may take some time, because parts of pleroma get compiled first. * After that it will ask you a few questions about your instance and generates a configuration file in `config/generated_config.exs`. -* Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances): +* Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for production instances, `dev.secret.exs` for development instances): ```shell sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs} From b52c948fb9adc2ea8695fafc99ef46ef9f71fbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Mon, 21 Oct 2024 21:03:49 +0200 Subject: [PATCH 11/13] Permit leave activity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- lib/pleroma/constants.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index ab11315e85..590832be1c 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -117,7 +117,8 @@ defmodule Pleroma.Constants do "Flag", "EmojiReact", "Bite", - "Join" + "Join", + "Leave" ] ) From 910c21cb856df1c536ed5691bbd8b6f1b516d0c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Tue, 22 Oct 2024 15:59:29 +0200 Subject: [PATCH 12/13] temporary fix for wordpress events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- .../web/activity_pub/object_validators/event_validator.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex index bdaf876d65..a836363c59 100644 --- a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex @@ -79,7 +79,7 @@ def changeset(struct, data) do defp validate_data(data_cng) do data_cng |> validate_inclusion(:type, ["Event"]) - |> validate_inclusion(:joinMode, ~w[free restricted invite]) + |> validate_inclusion(:joinMode, ~w[free restricted invite external]) |> validate_required([:id, :actor, :attributedTo, :type, :context]) |> CommonValidations.validate_any_presence([:cc, :to]) |> CommonValidations.validate_fields_match([:actor, :attributedTo]) From 8952354711dfead607f3674df0086dcad1c8940c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Sat, 26 Oct 2024 14:20:43 +0200 Subject: [PATCH 13/13] rebrand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1074593fce..0a907902e2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -`pl` is my personal fork of Pleroma that I use on my single-user instance. +Pleroma by mkljczk is a fork of Pleroma I'm developing for personal use. Added features: @@ -28,9 +28,9 @@ Features not authored by me: There might be more, it's hard to keep track of it. I'm trying to keep the fork as close to upstream and I hope the list will eventually get much shorter. **DISCLAIMER:** -Although `pl` *just works* for me, I cannot guarantee that it'll work well for you. There might be bugs I simply don't care about or I might decide to abandon the project one day. +Although Pleroma by mkljczk *just works* for me, I cannot guarantee that it'll work well for you. There might be bugs I simply don't care about or I might decide to abandon the project one day. -It should be possible to migrate from Pleroma or Rebased to `pl` without issues. It is recommended to use `pl` with [`pl-fe`](https://github.com/mkljczk/pl-fe/tree/develop/packages/pl-fe) for full feature compatibility, but pleroma-fe and other frontends work fine too. +It should be possible to migrate from Pleroma or Rebased to Pleroma by mkljczk without issues. It is recommended to use Pleroma by mkljczk with [`pl-fe`](https://github.com/mkljczk/pl-fe/tree/develop/packages/pl-fe) for full feature compatibility, but pleroma-fe and other frontends work fine too. ---