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. --- 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/config/config.exs b/config/config.exs index 776c5eef28..80ea57ddd2 100644 --- a/config/config.exs +++ b/config/config.exs @@ -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 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} diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index 5894ece22a..f8a6d24f34 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -116,7 +116,10 @@ defmodule Pleroma.Constants do "Announce", "Undo", "Flag", - "EmojiReact" + "EmojiReact", + "Bite", + "Join", + "Leave" ] ) 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 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/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex index 08a1db7a1f..e8abe6d70f 100644 --- a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex @@ -78,7 +78,7 @@ def changeset(struct, data, meta) do defp validate_data(data_cng, _meta) 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]) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index c5fe2fa56a..aa0276b2bf 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -498,6 +498,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), diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 6b2983d9d8..19b1438717 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -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 diff --git a/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex b/lib/pleroma/web/mastodon_api/controllers/bite_controller.ex index 69d865cb9b..b9b1310103 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/mix.exs b/mix.exs index dd1076cf27..80d1237d0f 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: [ diff --git a/priv/static/instance/static.css b/priv/static/instance/static.css index 183f9156dd..f3b77aaa6b 100644 Binary files a/priv/static/instance/static.css and b/priv/static/instance/static.css differ diff --git a/priv/static/schemas/litepub-0.1.jsonld b/priv/static/schemas/litepub-0.1.jsonld index 921c373af1..5a9e5c4bdc 100644 --- a/priv/static/schemas/litepub-0.1.jsonld +++ b/priv/static/schemas/litepub-0.1.jsonld @@ -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" } ] 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 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..96cd38e762 --- /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