forked from AkkomaGang/akkoma
Compare commits
1 commit
develop
...
reprocess-
Author | SHA1 | Date | |
---|---|---|---|
d54ef82e8e |
32 changed files with 174 additions and 243 deletions
|
@ -25,16 +25,7 @@ sudo dnf upgrade --refresh
|
|||
* Install some of the above mentioned programs:
|
||||
|
||||
```shell
|
||||
sudo dnf install git gcc g++ make cmake file-devel postgresql-server postgresql-contrib
|
||||
```
|
||||
|
||||
* Enable and initialize Postgres:
|
||||
```shell
|
||||
sudo systemctl enable postgresql.service
|
||||
sudo postgresql-setup --initdb --unit postgresql
|
||||
# Allow password auth for postgres
|
||||
sudo sed -E -i 's|(host +all +all +127.0.0.1/32 +)ident|\1md5|' /var/lib/pgsql/data/pg_hba.conf
|
||||
sudo systemctl start postgresql.service
|
||||
sudo dnf install git gcc g++ make cmake file-devel postgresql postgresql-contrib
|
||||
```
|
||||
|
||||
### Install Elixir and Erlang
|
||||
|
|
|
@ -60,18 +60,13 @@ your upgrade path here depends on your setup
|
|||
|
||||
### I just run with the built-in frontend
|
||||
|
||||
You'll need to run a couple of commands,
|
||||
You'll need to run a single command,
|
||||
|
||||
```bash
|
||||
# From source
|
||||
mix pleroma.frontend install pleroma-fe
|
||||
# you'll probably want this too
|
||||
mix pleroma.frontend install admin-fe
|
||||
|
||||
# OTP
|
||||
./bin/pleroma_ctl frontend install pleroma-fe
|
||||
# you'll probably want this too
|
||||
./bin/pleroma_ctl frontend install admin-fe
|
||||
```
|
||||
|
||||
### I've run the mix task to install a frontend
|
||||
|
|
|
@ -32,9 +32,9 @@ defmodule Pleroma.Config.Holder do
|
|||
def release_defaults do
|
||||
[
|
||||
pleroma: [
|
||||
{:instance, [static_dir: "/var/lib/akkoma/static"]},
|
||||
{Pleroma.Uploaders.Local, [uploads: "/var/lib/akkoma/uploads"]},
|
||||
{:modules, [runtime_dir: "/var/lib/akkoma/modules"]},
|
||||
{:instance, [static_dir: "/var/lib/pleroma/static"]},
|
||||
{Pleroma.Uploaders.Local, [uploads: "/var/lib/pleroma/uploads"]},
|
||||
{:modules, [runtime_dir: "/var/lib/pleroma/modules"]},
|
||||
{:release, true}
|
||||
]
|
||||
]
|
||||
|
|
|
@ -208,6 +208,10 @@ defmodule Pleroma.Object do
|
|||
end
|
||||
end
|
||||
|
||||
def context_mapping(context) do
|
||||
Object.change(%Object{}, %{data: %{"id" => context}})
|
||||
end
|
||||
|
||||
def make_tombstone(%Object{data: %{"id" => id, "type" => type}}, deleted \\ DateTime.utc_now()) do
|
||||
%ObjectTombstone{
|
||||
id: id,
|
||||
|
|
|
@ -107,18 +107,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|
||||
@impl true
|
||||
def persist(object, meta) do
|
||||
with local <- Keyword.fetch!(meta, :local),
|
||||
{recipients, _, _} <- get_recipients(object),
|
||||
{:ok, activity} <-
|
||||
Repo.insert(%Activity{
|
||||
data: object,
|
||||
local: local,
|
||||
recipients: recipients,
|
||||
actor: object["actor"]
|
||||
}),
|
||||
# TODO: add tests for expired activities, when Note type will be supported in new pipeline
|
||||
{:ok, _} <- maybe_create_activity_expiration(activity) do
|
||||
{:ok, activity, meta}
|
||||
if meta[:activity] do
|
||||
{:ok, meta[:activity], meta}
|
||||
else
|
||||
with local <- Keyword.fetch!(meta, :local),
|
||||
{recipients, _, _} <- get_recipients(object),
|
||||
{:ok, activity} <-
|
||||
Repo.insert(%Activity{
|
||||
data: object,
|
||||
local: local,
|
||||
recipients: recipients,
|
||||
actor: object["actor"]
|
||||
}),
|
||||
# TODO: add tests for expired activities, when Note type will be supported in new pipeline
|
||||
{:ok, _} <- maybe_create_activity_expiration(activity) do
|
||||
{:ok, activity, meta}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -327,9 +331,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
end
|
||||
end
|
||||
|
||||
defp do_unfollow(follower, followed, activity_id, local)
|
||||
|
||||
defp do_unfollow(follower, followed, activity_id, local) when local == true do
|
||||
defp do_unfollow(follower, followed, activity_id, local) do
|
||||
with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed),
|
||||
{:ok, follow_activity} <- update_follow_state(follow_activity, "cancelled"),
|
||||
unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
|
||||
|
@ -343,32 +345,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
end
|
||||
end
|
||||
|
||||
defp do_unfollow(follower, followed, activity_id, false) do
|
||||
# On a remote unfollow, _remove_ their activity from the database, since some software (MISSKEEEEY)
|
||||
# uses deterministic ids for follows.
|
||||
with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed),
|
||||
{:ok, _activity} <- Repo.delete(follow_activity),
|
||||
unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
|
||||
unfollow_activity <- remote_unfollow_data(unfollow_data),
|
||||
_ <- notify_and_stream(unfollow_activity) do
|
||||
{:ok, unfollow_activity}
|
||||
else
|
||||
nil -> nil
|
||||
{:error, error} -> Repo.rollback(error)
|
||||
end
|
||||
end
|
||||
|
||||
defp remote_unfollow_data(data) do
|
||||
{recipients, _, _} = get_recipients(data)
|
||||
|
||||
%Activity{
|
||||
data: data,
|
||||
local: false,
|
||||
actor: data["actor"],
|
||||
recipients: recipients
|
||||
}
|
||||
end
|
||||
|
||||
@spec flag(map()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
def flag(params) do
|
||||
with {:ok, result} <- Repo.transaction(fn -> do_flag(params) end) do
|
||||
|
|
|
@ -174,7 +174,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
|
|||
defp validate_data(data_cng) do
|
||||
data_cng
|
||||
|> validate_inclusion(:type, ["Article", "Note", "Page"])
|
||||
|> validate_required([:id, :actor, :attributedTo, :type, :context])
|
||||
|> validate_required([:id, :actor, :attributedTo, :type, :context, :context_id])
|
||||
|> CommonValidations.validate_any_presence([:cc, :to])
|
||||
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|
||||
|> CommonValidations.validate_actor_presence()
|
||||
|
|
|
@ -51,6 +51,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
|
|||
field(:summary, :string)
|
||||
|
||||
field(:context, :string)
|
||||
# short identifier for PleromaFE to group statuses by context
|
||||
field(:context_id, :integer)
|
||||
|
||||
field(:sensitive, :boolean, default: false)
|
||||
field(:replies_count, :integer, default: 0)
|
||||
|
|
|
@ -22,12 +22,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
|
|||
end
|
||||
|
||||
def fix_object_defaults(data) do
|
||||
context = Utils.maybe_create_context(data["context"] || data["conversation"])
|
||||
%{data: %{"id" => context}, id: context_id} =
|
||||
Utils.create_context(data["context"] || data["conversation"])
|
||||
|
||||
%User{follower_address: follower_collection} = User.get_cached_by_ap_id(data["attributedTo"])
|
||||
|
||||
data
|
||||
|> Map.put("context", context)
|
||||
|> Map.put("context_id", context_id)
|
||||
|> cast_and_filter_recipients("to", follower_collection)
|
||||
|> cast_and_filter_recipients("cc", follower_collection)
|
||||
|> cast_and_filter_recipients("bto", follower_collection)
|
||||
|
|
|
@ -62,7 +62,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do
|
|||
defp validate_data(data_cng) do
|
||||
data_cng
|
||||
|> validate_inclusion(:type, ["Event"])
|
||||
|> validate_required([:id, :actor, :attributedTo, :type, :context])
|
||||
|> validate_required([:id, :actor, :attributedTo, :type, :context, :context_id])
|
||||
|> CommonValidations.validate_any_presence([:cc, :to])
|
||||
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|
||||
|> CommonValidations.validate_actor_presence()
|
||||
|
|
|
@ -80,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
|
|||
defp validate_data(data_cng) do
|
||||
data_cng
|
||||
|> validate_inclusion(:type, ["Question"])
|
||||
|> validate_required([:id, :actor, :attributedTo, :type, :context])
|
||||
|> validate_required([:id, :actor, :attributedTo, :type, :context, :context_id])
|
||||
|> CommonValidations.validate_any_presence([:cc, :to])
|
||||
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|
||||
|> CommonValidations.validate_actor_presence()
|
||||
|
|
|
@ -509,12 +509,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|
||||
def handle_incoming(
|
||||
%{"type" => type} = data,
|
||||
_options
|
||||
options
|
||||
)
|
||||
when type in ~w{Update Block Follow Accept Reject} do
|
||||
|
||||
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
|
||||
{:ok, activity, _} <-
|
||||
Pipeline.common_pipeline(data, local: false) do
|
||||
Pipeline.common_pipeline(data, Keyword.put(options, :local, false)) do
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -154,7 +154,22 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
Notification.get_notified_from_activity(%Activity{data: object}, false)
|
||||
end
|
||||
|
||||
def maybe_create_context(context), do: context || generate_id("contexts")
|
||||
def create_context(context) do
|
||||
context = context || generate_id("contexts")
|
||||
|
||||
# Ecto has problems accessing the constraint inside the jsonb,
|
||||
# so we explicitly check for the existed object before insert
|
||||
object = Object.get_cached_by_ap_id(context)
|
||||
|
||||
with true <- is_nil(object),
|
||||
changeset <- Object.context_mapping(context),
|
||||
{:ok, inserted_object} <- Repo.insert(changeset) do
|
||||
inserted_object
|
||||
else
|
||||
_ ->
|
||||
object
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Enqueues an activity for federation if it's local
|
||||
|
@ -186,16 +201,18 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
|> Map.put_new("id", "pleroma:fakeid")
|
||||
|> Map.put_new_lazy("published", &make_date/0)
|
||||
|> Map.put_new("context", "pleroma:fakecontext")
|
||||
|> Map.put_new("context_id", -1)
|
||||
|> lazy_put_object_defaults(true)
|
||||
end
|
||||
|
||||
def lazy_put_activity_defaults(map, _fake?) do
|
||||
context = maybe_create_context(map["context"])
|
||||
%{data: %{"id" => context}, id: context_id} = create_context(map["context"])
|
||||
|
||||
map
|
||||
|> Map.put_new_lazy("id", &generate_activity_id/0)
|
||||
|> Map.put_new_lazy("published", &make_date/0)
|
||||
|> Map.put_new("context", context)
|
||||
|> Map.put_new("context_id", context_id)
|
||||
|> lazy_put_object_defaults(false)
|
||||
end
|
||||
|
||||
|
@ -209,6 +226,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
|> Map.put_new("id", "pleroma:fake_object_id")
|
||||
|> Map.put_new_lazy("published", &make_date/0)
|
||||
|> Map.put_new("context", activity["context"])
|
||||
|> Map.put_new("context_id", activity["context_id"])
|
||||
|> Map.put_new("fake", true)
|
||||
|
||||
%{activity | "object" => object}
|
||||
|
@ -221,6 +239,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
|> Map.put_new_lazy("id", &generate_object_id/0)
|
||||
|> Map.put_new_lazy("published", &make_date/0)
|
||||
|> Map.put_new("context", activity["context"])
|
||||
|> Map.put_new("context_id", activity["context_id"])
|
||||
|
||||
%{activity | "object" => object}
|
||||
end
|
||||
|
|
|
@ -152,15 +152,9 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
|||
description:
|
||||
"A map consisting of alternate representations of the `content` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`"
|
||||
},
|
||||
context: %Schema{
|
||||
type: :string,
|
||||
description: "The thread identifier the status is associated with"
|
||||
},
|
||||
conversation_id: %Schema{
|
||||
type: :integer,
|
||||
deprecated: true,
|
||||
description:
|
||||
"The ID of the AP context the status is associated with (if any); deprecated, please use `context` instead"
|
||||
description: "The ID of the AP context the status is associated with (if any)"
|
||||
},
|
||||
direct_conversation_id: %Schema{
|
||||
type: :integer,
|
||||
|
@ -362,7 +356,6 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
|||
"pinned" => false,
|
||||
"pleroma" => %{
|
||||
"content" => %{"text/plain" => "foobar"},
|
||||
"context" => "http://localhost:4001/objects/8b4c0c80-6a37-4d2a-b1b9-05a19e3875aa",
|
||||
"conversation_id" => 345_972,
|
||||
"direct_conversation_id" => nil,
|
||||
"emoji_reactions" => [],
|
||||
|
|
|
@ -458,6 +458,35 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
|
||||
def get_report_statuses(_, _), do: {:ok, nil}
|
||||
|
||||
# DEPRECATED mostly, context objects are now created at insertion time.
|
||||
def context_to_conversation_id(context) do
|
||||
with %Object{id: id} <- Object.get_cached_by_ap_id(context) do
|
||||
id
|
||||
else
|
||||
_e ->
|
||||
changeset = Object.context_mapping(context)
|
||||
|
||||
case Repo.insert(changeset) do
|
||||
{:ok, %{id: id}} ->
|
||||
id
|
||||
|
||||
# This should be solved by an upsert, but it seems ecto
|
||||
# has problems accessing the constraint inside the jsonb.
|
||||
{:error, _} ->
|
||||
Object.get_cached_by_ap_id(context).id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def conversation_id_to_context(id) do
|
||||
with %Object{data: %{"id" => context}} <- Repo.get(Object, id) do
|
||||
context
|
||||
else
|
||||
_e ->
|
||||
{:error, dgettext("errors", "No such conversation")}
|
||||
end
|
||||
end
|
||||
|
||||
def validate_character_limit("" = _full_payload, [] = _attachments) do
|
||||
{:error, dgettext("errors", "Cannot post an empty status without attachments")}
|
||||
end
|
||||
|
|
|
@ -86,17 +86,17 @@ defmodule Pleroma.Web.Federator do
|
|||
# NOTE: we use the actor ID to do the containment, this is fine because an
|
||||
# actor shouldn't be acting on objects outside their own AP server.
|
||||
with {_, {:ok, _user}} <- {:actor, ap_enabled_actor(actor)},
|
||||
nil <- Activity.normalize(params["id"]),
|
||||
{true, activity} <- should_process?(Activity.normalize(params["id"])),
|
||||
{_, :ok} <-
|
||||
{:correct_origin?, Containment.contain_origin_from_id(actor, params)},
|
||||
{:ok, activity} <- Transmogrifier.handle_incoming(params) do
|
||||
{:ok, activity} <- Transmogrifier.handle_incoming(params, activity: activity) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:correct_origin?, _} ->
|
||||
Logger.debug("Origin containment failure for #{params["id"]}")
|
||||
{:error, :origin_containment_failed}
|
||||
|
||||
%Activity{} ->
|
||||
{false, nil} ->
|
||||
Logger.debug("Already had #{params["id"]}")
|
||||
{:error, :already_present}
|
||||
|
||||
|
@ -111,6 +111,7 @@ defmodule Pleroma.Web.Federator do
|
|||
|
||||
e ->
|
||||
# Just drop those for now
|
||||
IO.inspect(e)
|
||||
Logger.debug(fn -> "Unhandled activity\n" <> Jason.encode!(params, pretty: true) end)
|
||||
{:error, e}
|
||||
end
|
||||
|
@ -125,4 +126,23 @@ defmodule Pleroma.Web.Federator do
|
|||
ActivityPub.make_user_from_ap_id(id)
|
||||
end
|
||||
end
|
||||
|
||||
defp should_process?(%Activity{data: %{"type" => "Follow"}} = activity) do
|
||||
# Misskey can resend follows when it shouldn't
|
||||
# A follow/unfollow/follow in misskey land will die because it
|
||||
# reuses the same ID
|
||||
{true, activity}
|
||||
end
|
||||
|
||||
defp should_process?(
|
||||
%Activity{data: %{"type" => "Undo", "object" => %{"type" => "Follow"}}} = activity
|
||||
) do
|
||||
{true, activity}
|
||||
end
|
||||
|
||||
defp should_process?(%Activity{} = e) do
|
||||
{false, nil}
|
||||
end
|
||||
|
||||
defp should_process?(_), do: {true, nil}
|
||||
end
|
||||
|
|
|
@ -57,19 +57,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
end)
|
||||
end
|
||||
|
||||
# DEPRECATED This field seems to be a left-over from the StatusNet era.
|
||||
# If your application uses `pleroma.conversation_id`: this field is deprecated.
|
||||
# It is currently stubbed instead by doing a CRC32 of the context, and
|
||||
# clearing the MSB to avoid overflow exceptions with signed integers on the
|
||||
# different clients using this field (Java/Kotlin code, mostly; see Husky.)
|
||||
# This should be removed in a future version of Pleroma. Pleroma-FE currently
|
||||
# depends on this field, as well.
|
||||
defp get_context_id(%{data: %{"context" => context}}) when is_binary(context) do
|
||||
use Bitwise
|
||||
defp get_context_id(%{data: %{"context_id" => context_id}}) when not is_nil(context_id),
|
||||
do: context_id
|
||||
|
||||
:erlang.crc32(context)
|
||||
|> band(bnot(0x8000_0000))
|
||||
end
|
||||
defp get_context_id(%{data: %{"context" => context}}) when is_binary(context),
|
||||
do: Utils.context_to_conversation_id(context)
|
||||
|
||||
defp get_context_id(_), do: nil
|
||||
|
||||
|
@ -378,7 +370,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
pleroma: %{
|
||||
local: activity.local,
|
||||
conversation_id: get_context_id(activity),
|
||||
context: object.data["context"],
|
||||
in_reply_to_account_acct: reply_to_user && reply_to_user.nickname,
|
||||
content: %{"text/plain" => content_plaintext},
|
||||
spoiler_text: %{"text/plain" => summary},
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller, only: [get_format: 1, text: 2]
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Web.Router
|
||||
require Logger
|
||||
|
||||
def init(options) do
|
||||
|
@ -27,45 +25,21 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
|
|||
end
|
||||
end
|
||||
|
||||
def route_aliases(%{path_info: ["objects", id]} = conn) do
|
||||
ap_id = Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :object, id)
|
||||
|
||||
with %Activity{} = activity <- Activity.get_by_object_ap_id_with_object(ap_id) do
|
||||
["/notice/#{activity.id}"]
|
||||
else
|
||||
_ -> []
|
||||
end
|
||||
end
|
||||
|
||||
def route_aliases(_), do: []
|
||||
|
||||
defp assign_valid_signature_on_route_aliases(conn, []), do: conn
|
||||
|
||||
defp assign_valid_signature_on_route_aliases(%{assigns: %{valid_signature: true}} = conn, _),
|
||||
do: conn
|
||||
|
||||
defp assign_valid_signature_on_route_aliases(conn, [path | rest]) do
|
||||
request_target = String.downcase("#{conn.method}") <> " #{path}"
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("(request-target)", request_target)
|
||||
|> case do
|
||||
%{assigns: %{digest: digest}} = conn -> put_req_header(conn, "digest", digest)
|
||||
conn -> conn
|
||||
end
|
||||
|
||||
conn
|
||||
|> assign(:valid_signature, HTTPSignatures.validate_conn(conn))
|
||||
|> assign_valid_signature_on_route_aliases(rest)
|
||||
end
|
||||
|
||||
defp maybe_assign_valid_signature(conn) do
|
||||
if has_signature_header?(conn) do
|
||||
# set (request-target) header to the appropriate value
|
||||
# we also replace the digest header with the one we computed
|
||||
possible_paths = route_aliases(conn) ++ [conn.request_path]
|
||||
assign_valid_signature_on_route_aliases(conn, possible_paths)
|
||||
request_target = String.downcase("#{conn.method}") <> " #{conn.request_path}"
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("(request-target)", request_target)
|
||||
|> case do
|
||||
%{assigns: %{digest: digest}} = conn -> put_req_header(conn, "digest", digest)
|
||||
conn -> conn
|
||||
end
|
||||
|
||||
assign(conn, :valid_signature, HTTPSignatures.validate_conn(conn))
|
||||
else
|
||||
Logger.debug("No signature header!")
|
||||
conn
|
||||
|
|
|
@ -9,12 +9,6 @@ defmodule Pleroma.Workers.ReceiverWorker do
|
|||
|
||||
@impl Oban.Worker
|
||||
def perform(%Job{args: %{"op" => "incoming_ap_doc", "params" => params}}) do
|
||||
with {:ok, res} <- Federator.perform(:incoming_ap_doc, params) do
|
||||
{:ok, res}
|
||||
else
|
||||
{:error, :origin_containment_failed} -> {:cancel, :origin_containment_failed}
|
||||
{:error, {:reject, reason}} -> {:cancel, reason}
|
||||
e -> e
|
||||
end
|
||||
Federator.perform(:incoming_ap_doc, params)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
defmodule Pleroma.Repo.Migrations.RemoveRemoteCancelledFollowRequests do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
statement = """
|
||||
DELETE FROM
|
||||
activities
|
||||
WHERE
|
||||
(data->>'type') = 'Follow'
|
||||
AND
|
||||
(data->>'state') = 'cancelled'
|
||||
AND
|
||||
local = false;
|
||||
"""
|
||||
|
||||
execute(statement)
|
||||
|
||||
statement = """
|
||||
DELETE FROM
|
||||
activities
|
||||
WHERE
|
||||
(data->>'type') = 'Undo'
|
||||
AND
|
||||
(data->'object'->>'type') = 'Follow'
|
||||
AND
|
||||
local = false;
|
||||
"""
|
||||
|
||||
execute(statement)
|
||||
end
|
||||
|
||||
def down do
|
||||
:ok
|
||||
end
|
||||
end
|
|
@ -1,14 +0,0 @@
|
|||
defmodule Pleroma.Repo.Migrations.RemoveNullObjects do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
statement = """
|
||||
DELETE FROM objects
|
||||
WHERE (data->>'type') is null;
|
||||
"""
|
||||
|
||||
execute(statement)
|
||||
end
|
||||
|
||||
def down, do: :ok
|
||||
end
|
|
@ -56,7 +56,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
|||
Meta.allow_tag_with_these_attributes(:u, [])
|
||||
Meta.allow_tag_with_these_attributes(:ul, [])
|
||||
|
||||
Meta.allow_tag_with_this_attribute_values(:span, "class", ["h-card", "quote-inline"])
|
||||
Meta.allow_tag_with_this_attribute_values(:span, "class", ["h-card"])
|
||||
Meta.allow_tag_with_these_attributes(:span, [])
|
||||
|
||||
Meta.allow_tag_with_this_attribute_values(:code, "class", ["inline"])
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# XXX: This should be removed when elixir's releases get custom command support
|
||||
|
||||
detect_flavour() {
|
||||
echo "Trying to autodetect flavour, you may want to override this with --flavour"
|
||||
arch="$(uname -m)"
|
||||
if [ "$arch" = "x86_64" ]; then
|
||||
arch="amd64"
|
||||
|
|
|
@ -523,6 +523,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert activity.data["ok"] == data["ok"]
|
||||
assert activity.data["id"] == given_id
|
||||
assert activity.data["context"] == "blabla"
|
||||
assert activity.data["context_id"]
|
||||
end
|
||||
|
||||
test "adds a context when none is there" do
|
||||
|
@ -544,6 +545,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
assert is_binary(activity.data["context"])
|
||||
assert is_binary(object.data["context"])
|
||||
assert activity.data["context_id"]
|
||||
assert object.data["context_id"]
|
||||
end
|
||||
|
||||
test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do
|
||||
|
@ -1372,21 +1375,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert embedded_object["object"] == followed.ap_id
|
||||
assert embedded_object["id"] == follow_activity.data["id"]
|
||||
end
|
||||
|
||||
test "it removes the follow activity if it was remote" do
|
||||
follower = insert(:user, local: false)
|
||||
followed = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
|
||||
{:ok, activity} = ActivityPub.unfollow(follower, followed, nil, false)
|
||||
|
||||
assert activity.data["type"] == "Undo"
|
||||
assert activity.data["actor"] == follower.ap_id
|
||||
|
||||
activity = Activity.get_by_id(follow_activity.id)
|
||||
assert is_nil(activity)
|
||||
assert is_nil(Utils.fetch_latest_follow(follower, followed))
|
||||
end
|
||||
end
|
||||
|
||||
describe "timeline post-processing" do
|
||||
|
@ -1557,7 +1545,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
})
|
||||
|
||||
assert Repo.aggregate(Activity, :count, :id) == 1
|
||||
assert Repo.aggregate(Object, :count, :id) == 1
|
||||
assert Repo.aggregate(Object, :count, :id) == 2
|
||||
assert Repo.aggregate(Notification, :count, :id) == 0
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,6 +33,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do
|
|||
assert object.data["context"] ==
|
||||
"tag:mastodon.sdf.org,2019-05-10:objectId=15095122:objectType=Conversation"
|
||||
|
||||
assert object.data["context_id"]
|
||||
|
||||
assert object.data["anyOf"] == []
|
||||
|
||||
assert Enum.sort(object.data["oneOf"]) ==
|
||||
|
@ -66,6 +68,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do
|
|||
reply_object = Object.normalize(reply_activity, fetch: false)
|
||||
|
||||
assert reply_object.data["context"] == object.data["context"]
|
||||
assert reply_object.data["context_id"] == object.data["context_id"]
|
||||
end
|
||||
|
||||
test "Mastodon Question activity with HTML tags in plaintext" do
|
||||
|
|
|
@ -232,6 +232,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert is_nil(modified["object"]["like_count"])
|
||||
assert is_nil(modified["object"]["announcements"])
|
||||
assert is_nil(modified["object"]["announcement_count"])
|
||||
assert is_nil(modified["object"]["context_id"])
|
||||
assert is_nil(modified["object"]["generator"])
|
||||
end
|
||||
|
||||
|
@ -246,6 +247,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert is_nil(modified["object"]["like_count"])
|
||||
assert is_nil(modified["object"]["announcements"])
|
||||
assert is_nil(modified["object"]["announcement_count"])
|
||||
assert is_nil(modified["object"]["context_id"])
|
||||
assert is_nil(modified["object"]["likes"])
|
||||
end
|
||||
|
||||
|
|
|
@ -429,6 +429,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
object = Object.normalize(note_activity, fetch: false)
|
||||
res = Utils.lazy_put_activity_defaults(%{"context" => object.data["id"]})
|
||||
assert res["context"] == object.data["id"]
|
||||
assert res["context_id"] == object.id
|
||||
assert res["id"]
|
||||
assert res["published"]
|
||||
end
|
||||
|
@ -436,6 +437,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
test "returns map with fake id and published data" do
|
||||
assert %{
|
||||
"context" => "pleroma:fakecontext",
|
||||
"context_id" => -1,
|
||||
"id" => "pleroma:fakeid",
|
||||
"published" => _
|
||||
} = Utils.lazy_put_activity_defaults(%{}, true)
|
||||
|
@ -452,11 +454,13 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
})
|
||||
|
||||
assert res["context"] == object.data["id"]
|
||||
assert res["context_id"] == object.id
|
||||
assert res["id"]
|
||||
assert res["published"]
|
||||
assert res["object"]["id"]
|
||||
assert res["object"]["published"]
|
||||
assert res["object"]["context"] == object.data["id"]
|
||||
assert res["object"]["context_id"] == object.id
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
||||
alias Pleroma.Builders.UserBuilder
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.ActivityDraft
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
|
@ -272,6 +273,22 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "context_to_conversation_id" do
|
||||
test "creates a mapping object" do
|
||||
conversation_id = Utils.context_to_conversation_id("random context")
|
||||
object = Object.get_by_ap_id("random context")
|
||||
|
||||
assert conversation_id == object.id
|
||||
end
|
||||
|
||||
test "returns an existing mapping for an existing object" do
|
||||
{:ok, object} = Object.context_mapping("random context") |> Repo.insert()
|
||||
conversation_id = Utils.context_to_conversation_id("random context")
|
||||
|
||||
assert conversation_id == object.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "formats date to asctime" do
|
||||
test "when date is in ISO 8601 format" do
|
||||
date = DateTime.utc_now() |> DateTime.to_iso8601()
|
||||
|
@ -500,6 +517,17 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "conversation_id_to_context/1" do
|
||||
test "returns id" do
|
||||
object = insert(:note)
|
||||
assert Utils.conversation_id_to_context(object.id) == object.data["id"]
|
||||
end
|
||||
|
||||
test "returns error if object not found" do
|
||||
assert Utils.conversation_id_to_context("123") == {:error, "No such conversation"}
|
||||
end
|
||||
end
|
||||
|
||||
describe "maybe_notify_mentioned_recipients/2" do
|
||||
test "returns recipients when activity is not `Create`" do
|
||||
activity = insert(:like_activity)
|
||||
|
|
|
@ -153,7 +153,7 @@ defmodule Pleroma.Web.FederatorTest do
|
|||
}
|
||||
|
||||
assert {:ok, job} = Federator.incoming_ap_doc(params)
|
||||
assert {:cancel, :origin_containment_failed} = ObanHelpers.perform(job)
|
||||
assert {:error, :origin_containment_failed} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
test "it does not crash if MRF rejects the post" do
|
||||
|
@ -169,7 +169,7 @@ defmodule Pleroma.Web.FederatorTest do
|
|||
|> Jason.decode!()
|
||||
|
||||
assert {:ok, job} = Federator.incoming_ap_doc(params)
|
||||
assert {:cancel, _} = ObanHelpers.perform(job)
|
||||
assert {:error, _} = ObanHelpers.perform(job)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -264,7 +264,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|> Map.put("url", nil)
|
||||
|> Map.put("uri", nil)
|
||||
|> Map.put("created_at", nil)
|
||||
|> Kernel.put_in(["pleroma", "context"], nil)
|
||||
|> Kernel.put_in(["pleroma", "conversation_id"], nil)
|
||||
|
||||
fake_conn =
|
||||
|
@ -288,7 +287,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|> Map.put("url", nil)
|
||||
|> Map.put("uri", nil)
|
||||
|> Map.put("created_at", nil)
|
||||
|> Kernel.put_in(["pleroma", "context"], nil)
|
||||
|> Kernel.put_in(["pleroma", "conversation_id"], nil)
|
||||
|
||||
assert real_status == fake_status
|
||||
|
|
|
@ -14,6 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
alias Pleroma.User
|
||||
alias Pleroma.UserRelationship
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
|
@ -239,7 +240,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
object_data = Object.normalize(note, fetch: false).data
|
||||
user = User.get_cached_by_ap_id(note.data["actor"])
|
||||
|
||||
convo_id = :erlang.crc32(object_data["context"]) |> Bitwise.band(Bitwise.bnot(0x8000_0000))
|
||||
convo_id = Utils.context_to_conversation_id(object_data["context"])
|
||||
|
||||
status = StatusView.render("show.json", %{activity: note})
|
||||
|
||||
|
@ -292,7 +293,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
pleroma: %{
|
||||
local: true,
|
||||
conversation_id: convo_id,
|
||||
context: object_data["context"],
|
||||
in_reply_to_account_acct: nil,
|
||||
content: %{"text/plain" => HTML.strip_tags(object_data["content"])},
|
||||
spoiler_text: %{"text/plain" => HTML.strip_tags(object_data["summary"])},
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Web.Plugs.HTTPSignaturePlug
|
||||
|
||||
import Plug.Conn
|
||||
|
@ -82,14 +81,5 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do
|
|||
assert conn.state == :sent
|
||||
assert conn.resp_body == "Request not signed"
|
||||
end
|
||||
|
||||
test "aliases redirected /object endpoints", _ do
|
||||
obj = insert(:note)
|
||||
act = insert(:note_activity, note: obj)
|
||||
params = %{"actor" => "http://mastodon.example.org/users/admin"}
|
||||
path = URI.parse(obj.data["id"]).path
|
||||
conn = build_conn(:get, path, params)
|
||||
assert ["/notice/#{act.id}"] == HTTPSignaturePlug.route_aliases(conn)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Workers.ReceiverWorkerTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Workers.ReceiverWorker
|
||||
|
||||
test "it ignores MRF reject" do
|
||||
params = insert(:note).data
|
||||
|
||||
with_mock Pleroma.Web.ActivityPub.Transmogrifier,
|
||||
handle_incoming: fn _ -> {:reject, "MRF"} end do
|
||||
assert {:cancel, "MRF"} =
|
||||
ReceiverWorker.perform(%Oban.Job{
|
||||
args: %{"op" => "incoming_ap_doc", "params" => params}
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue