From 7bcd7a959519ea023b075142aa36005f80503ba4 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 11 Jun 2020 20:23:10 +0200 Subject: QuestionValidator: Create --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- lib/pleroma/web/activity_pub/object_validator.ex | 41 +++++++++- .../object_validators/common_validations.ex | 4 +- .../object_validators/create_question_validator.ex | 94 ++++++++++++++++++++++ .../object_validators/note_validator.ex | 2 +- .../question_options_validator.ex | 47 +++++++++++ .../object_validators/question_validator.ex | 89 ++++++++++++++++++++ lib/pleroma/web/activity_pub/side_effects.ex | 10 ++- lib/pleroma/web/activity_pub/transmogrifier.ex | 17 +++- test/web/activity_pub/transmogrifier_test.exs | 2 +- 10 files changed, 297 insertions(+), 11 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex create mode 100644 lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex create mode 100644 lib/pleroma/web/activity_pub/object_validators/question_validator.ex diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index bc7b5d95a..462aa57a6 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -95,7 +95,7 @@ defp increase_poll_votes_if_vote(%{ defp increase_poll_votes_if_vote(_create_data), do: :noop - @object_types ["ChatMessage"] + @object_types ["ChatMessage", "Question"] @spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()} def persist(%{"type" => type} = object, meta) when type in @object_types do with {:ok, object} <- Object.create(object) do diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index df926829c..5cc66d7bd 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -16,10 +16,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.CreateQuestionValidator alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator @@ -105,17 +107,30 @@ def validate(%{"type" => "ChatMessage"} = object, meta) do end end + def validate(%{"type" => "Question"} = object, meta) do + with {:ok, object} <- + object + |> QuestionValidator.cast_and_validate() + |> Ecto.Changeset.apply_action(:insert) do + object = stringify_keys(object) + {:ok, object, meta} + end + end + def validate(%{"type" => "EmojiReact"} = object, meta) do with {:ok, object} <- object |> EmojiReactValidator.cast_and_validate() |> Ecto.Changeset.apply_action(:insert) do - object = stringify_keys(object |> Map.from_struct()) + object = stringify_keys(object) {:ok, object, meta} end end - def validate(%{"type" => "Create", "object" => object} = create_activity, meta) do + def validate( + %{"type" => "Create", "object" => %{"type" => "ChatMessage"} = object} = create_activity, + meta + ) do with {:ok, object_data} <- cast_and_apply(object), meta = Keyword.put(meta, :object_data, object_data |> stringify_keys), {:ok, create_activity} <- @@ -127,12 +142,27 @@ def validate(%{"type" => "Create", "object" => object} = create_activity, meta) end end + def validate( + %{"type" => "Create", "object" => %{"type" => "Question"} = object} = create_activity, + meta + ) do + with {:ok, object_data} <- cast_and_apply(object), + meta = Keyword.put(meta, :object_data, object_data |> stringify_keys), + {:ok, create_activity} <- + create_activity + |> CreateQuestionValidator.cast_and_validate(meta) + |> Ecto.Changeset.apply_action(:insert) do + create_activity = stringify_keys(create_activity) + {:ok, create_activity, meta} + end + end + def validate(%{"type" => "Announce"} = object, meta) do with {:ok, object} <- object |> AnnounceValidator.cast_and_validate() |> Ecto.Changeset.apply_action(:insert) do - object = stringify_keys(object |> Map.from_struct()) + object = stringify_keys(object) {:ok, object, meta} end end @@ -141,8 +171,13 @@ def cast_and_apply(%{"type" => "ChatMessage"} = object) do ChatMessageValidator.cast_and_apply(object) end + def cast_and_apply(%{"type" => "Question"} = object) do + QuestionValidator.cast_and_apply(object) + end + def cast_and_apply(o), do: {:error, {:validator_not_set, o}} + # is_struct/1 isn't present in Elixir 1.8.x def stringify_keys(%{__struct__: _} = object) do object |> Map.from_struct() diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index aeef31945..e746b9360 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations do alias Pleroma.Object alias Pleroma.User - def validate_recipients_presence(cng, fields \\ [:to, :cc]) do + def validate_any_presence(cng, fields) do non_empty = fields |> Enum.map(fn field -> get_field(cng, field) end) @@ -24,7 +24,7 @@ def validate_recipients_presence(cng, fields \\ [:to, :cc]) do fields |> Enum.reduce(cng, fn field, cng -> cng - |> add_error(field, "no recipients in any field") + |> add_error(field, "none of #{inspect(fields)} present") end) end end diff --git a/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex new file mode 100644 index 000000000..f09207418 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex @@ -0,0 +1,94 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +# Code based on CreateChatMessageValidator +# NOTES +# - Can probably be a generic create validator +# - doesn't embed, will only get the object id +defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateQuestionValidator do + use Ecto.Schema + + alias Pleroma.Object + alias Pleroma.Web.ActivityPub.ObjectValidators.Types + + import Ecto.Changeset + import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + + @primary_key false + + embedded_schema do + field(:id, Types.ObjectID, primary_key: true) + field(:actor, Types.ObjectID) + field(:type, :string) + field(:to, Types.Recipients, default: []) + field(:cc, Types.Recipients, default: []) + field(:object, Types.ObjectID) + end + + def cast_and_apply(data) do + data + |> cast_data + |> apply_action(:insert) + end + + def cast_data(data) do + cast(%__MODULE__{}, data, __schema__(:fields)) + end + + def cast_and_validate(data, meta \\ []) do + cast_data(data) + |> validate_data(meta) + end + + def validate_data(cng, meta \\ []) do + cng + |> validate_required([:actor, :type, :object]) + |> validate_inclusion(:type, ["Create"]) + |> validate_actor_presence() + |> validate_any_presence([:to, :cc]) + |> validate_recipients_match(meta) + |> validate_actors_match(meta) + |> validate_object_nonexistence() + end + + def validate_object_nonexistence(cng) do + cng + |> validate_change(:object, fn :object, object_id -> + if Object.get_cached_by_ap_id(object_id) do + [{:object, "The object to create already exists"}] + else + [] + end + end) + end + + def validate_actors_match(cng, meta) do + object_actor = meta[:object_data]["actor"] + + cng + |> validate_change(:actor, fn :actor, actor -> + if actor == object_actor do + [] + else + [{:actor, "Actor doesn't match with object actor"}] + end + end) + end + + def validate_recipients_match(cng, meta) do + object_recipients = meta[:object_data]["to"] || [] + + cng + |> validate_change(:to, fn :to, recipients -> + activity_set = MapSet.new(recipients) + object_set = MapSet.new(object_recipients) + + if MapSet.equal?(activity_set, object_set) do + [] + else + [{:to, "Recipients don't match with object recipients"}] + end + end) + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex index 56b93dde8..a65fe2354 100644 --- a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex @@ -34,7 +34,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do field(:replies_count, :integer, default: 0) field(:like_count, :integer, default: 0) field(:announcement_count, :integer, default: 0) - field(:inRepyTo, :string) + field(:inReplyTo, :string) field(:uri, ObjectValidators.Uri) field(:likes, {:array, :string}, default: []) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex new file mode 100644 index 000000000..9bc7e0cc0 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex @@ -0,0 +1,47 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator do + use Ecto.Schema + + alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsRepliesValidator + + import Ecto.Changeset + + @primary_key false + + embedded_schema do + field(:name, :string) + embeds_one(:replies, QuestionOptionsRepliesValidator) + field(:type, :string) + end + + def changeset(struct, data) do + struct + |> cast(data, [:name, :type]) + |> cast_embed(:replies) + |> validate_inclusion(:type, ["Note"]) + |> validate_required([:name, :type]) + end +end + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsRepliesValidator do + use Ecto.Schema + + import Ecto.Changeset + + @primary_key false + + embedded_schema do + field(:totalItems, :integer) + field(:type, :string) + end + + def changeset(struct, data) do + struct + |> cast(data, __schema__(:fields)) + |> validate_inclusion(:type, ["Collection"]) + |> validate_required([:type]) + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex new file mode 100644 index 000000000..f94d79352 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -0,0 +1,89 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do + use Ecto.Schema + + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.Types + + import Ecto.Changeset + + @primary_key false + @derive Jason.Encoder + + # Extends from NoteValidator + embedded_schema do + field(:id, Types.ObjectID, primary_key: true) + field(:to, {:array, :string}, default: []) + field(:cc, {:array, :string}, default: []) + field(:bto, {:array, :string}, default: []) + field(:bcc, {:array, :string}, default: []) + # TODO: Write type + field(:tag, {:array, :map}, default: []) + field(:type, :string) + field(:content, :string) + field(:context, :string) + field(:actor, Types.ObjectID) + field(:attributedTo, Types.ObjectID) + field(:summary, :string) + field(:published, Types.DateTime) + # TODO: Write type + field(:emoji, :map, default: %{}) + field(:sensitive, :boolean, default: false) + # TODO: Write type + field(:attachment, {:array, :map}, default: []) + field(:replies_count, :integer, default: 0) + field(:like_count, :integer, default: 0) + field(:announcement_count, :integer, default: 0) + field(:inReplyTo, :string) + field(:uri, Types.Uri) + + field(:likes, {:array, :string}, default: []) + field(:announcements, {:array, :string}, default: []) + + # see if needed + field(:conversation, :string) + field(:context_id, :string) + + field(:closed, Types.DateTime) + field(:voters, {:array, Types.ObjectID}, default: []) + embeds_many(:anyOf, QuestionOptionsValidator) + embeds_many(:oneOf, QuestionOptionsValidator) + end + + def cast_and_apply(data) do + data + |> cast_data + |> apply_action(:insert) + end + + def cast_and_validate(data) do + data + |> cast_data() + |> validate_data() + end + + def cast_data(data) do + %__MODULE__{} + |> changeset(data) + end + + def changeset(struct, data) do + struct + |> cast(data, __schema__(:fields) -- [:anyOf, :oneOf]) + |> cast_embed(:anyOf) + |> cast_embed(:oneOf) + end + + def validate_data(data_cng) do + data_cng + |> validate_inclusion(:type, ["Question"]) + |> validate_required([:id, :actor, :type, :content, :context]) + |> CommonValidations.validate_any_presence([:cc, :to]) + |> CommonValidations.validate_actor_presence() + |> CommonValidations.validate_any_presence([:oneOf, :anyOf]) + end +end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 1d2c296a5..a78ec411f 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -268,9 +268,15 @@ def handle_object_creation(%{"type" => "ChatMessage"} = object, meta) do end end + def handle_object_creation(%{"type" => "Question"} = object, meta) do + with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do + {:ok, object, meta} + end + end + # Nothing to do - def handle_object_creation(object) do - {:ok, object} + def handle_object_creation(object, meta) do + {:ok, object, meta} end defp undo_like(nil, object), do: delete_object(object) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index f37bcab3e..da5dc23bc 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -457,7 +457,7 @@ def handle_incoming( %{"type" => "Create", "object" => %{"type" => objtype} = object} = data, options ) - when objtype in ["Article", "Event", "Note", "Video", "Page", "Question", "Answer", "Audio"] do + when objtype in ["Article", "Event", "Note", "Video", "Page", "Answer", "Audio"] do actor = Containment.get_actor(data) with nil <- Activity.get_create_by_object_ap_id(object["id"]), @@ -613,6 +613,21 @@ def handle_incoming( |> handle_incoming(options) end + def handle_incoming( + %{"type" => "Create", "object" => %{"type" => "Question"} = object} = data, + _options + ) do + data = + data + |> Map.put("object", fix_object(object)) + |> fix_addressing() + + with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), + {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do + {:ok, activity} + end + end + def handle_incoming( %{"type" => "Create", "object" => %{"type" => "ChatMessage"}} = data, _options diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 248b410c6..73949b558 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -222,7 +222,7 @@ test "it works for incoming questions" do {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - object = Object.normalize(activity) + object = Object.normalize(activity, false) assert Enum.all?(object.data["oneOf"], fn choice -> choice["name"] in [ -- cgit v1.2.3 From c5efaf6b00bf582a6eef7b5728fe5042f5fcc702 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 11 Jun 2020 20:43:01 +0200 Subject: AnswerValidator: Create --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- lib/pleroma/web/activity_pub/object_validator.ex | 20 +++++++- .../object_validators/answer_validator.ex | 58 ++++++++++++++++++++++ lib/pleroma/web/activity_pub/transmogrifier.ex | 7 +-- 4 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/object_validators/answer_validator.ex diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 462aa57a6..d8cc8d24f 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -95,7 +95,7 @@ defp increase_poll_votes_if_vote(%{ defp increase_poll_votes_if_vote(_create_data), do: :noop - @object_types ["ChatMessage", "Question"] + @object_types ["ChatMessage", "Question", "Answer"] @spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()} def persist(%{"type" => type} = object, meta) when type in @object_types do with {:ok, object} <- Object.create(object) do diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index 5cc66d7bd..c89311187 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.Object alias Pleroma.User alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator @@ -117,6 +118,16 @@ def validate(%{"type" => "Question"} = object, meta) do end end + def validate(%{"type" => "Answer"} = object, meta) do + with {:ok, object} <- + object + |> AnswerValidator.cast_and_validate() + |> Ecto.Changeset.apply_action(:insert) do + object = stringify_keys(object) + {:ok, object, meta} + end + end + def validate(%{"type" => "EmojiReact"} = object, meta) do with {:ok, object} <- object @@ -143,9 +154,10 @@ def validate( end def validate( - %{"type" => "Create", "object" => %{"type" => "Question"} = object} = create_activity, + %{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity, meta - ) do + ) + when objtype in ["Question", "Answer"] do with {:ok, object_data} <- cast_and_apply(object), meta = Keyword.put(meta, :object_data, object_data |> stringify_keys), {:ok, create_activity} <- @@ -175,6 +187,10 @@ def cast_and_apply(%{"type" => "Question"} = object) do QuestionValidator.cast_and_apply(object) end + def cast_and_apply(%{"type" => "Answer"} = object) do + QuestionValidator.cast_and_apply(object) + end + def cast_and_apply(o), do: {:error, {:validator_not_set, o}} # is_struct/1 isn't present in Elixir 1.8.x diff --git a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex new file mode 100644 index 000000000..0b51eccfa --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex @@ -0,0 +1,58 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do + use Ecto.Schema + + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + alias Pleroma.Web.ActivityPub.ObjectValidators.Types + + import Ecto.Changeset + + @primary_key false + @derive Jason.Encoder + + # Extends from NoteValidator + embedded_schema do + field(:id, Types.ObjectID, primary_key: true) + field(:to, {:array, :string}, default: []) + field(:cc, {:array, :string}, default: []) + field(:bto, {:array, :string}, default: []) + field(:bcc, {:array, :string}, default: []) + field(:type, :string) + field(:name, :string) + field(:inReplyTo, :string) + field(:attributedTo, Types.ObjectID) + end + + def cast_and_apply(data) do + data + |> cast_data + |> apply_action(:insert) + end + + def cast_and_validate(data) do + data + |> cast_data() + |> validate_data() + end + + def cast_data(data) do + %__MODULE__{} + |> changeset(data) + end + + def changeset(struct, data) do + struct + |> cast(data, __schema__(:fields)) + end + + def validate_data(data_cng) do + data_cng + |> validate_inclusion(:type, ["Answer"]) + |> validate_required([:id, :inReplyTo, :name]) + |> CommonValidations.validate_any_presence([:cc, :to]) + |> CommonValidations.validate_actor_presence() + end +end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index da5dc23bc..9900602e4 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -457,7 +457,7 @@ def handle_incoming( %{"type" => "Create", "object" => %{"type" => objtype} = object} = data, options ) - when objtype in ["Article", "Event", "Note", "Video", "Page", "Answer", "Audio"] do + when objtype in ["Article", "Event", "Note", "Video", "Page", "Audio"] do actor = Containment.get_actor(data) with nil <- Activity.get_create_by_object_ap_id(object["id"]), @@ -614,9 +614,10 @@ def handle_incoming( end def handle_incoming( - %{"type" => "Create", "object" => %{"type" => "Question"} = object} = data, + %{"type" => "Create", "object" => %{"type" => objtype} = object} = data, _options - ) do + ) + when objtype in ["Question", "Answer"] do data = data |> Map.put("object", fix_object(object)) -- cgit v1.2.3 From 89a2433154b05c378f9c5b3224375049f3dbc8af Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 12 Jun 2020 21:22:05 +0200 Subject: QuestionOptionsValidator: inline schema for replies --- .../question_options_validator.ex | 28 +++++++--------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex index 9bc7e0cc0..8291d7b9f 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex @@ -5,42 +5,32 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator do use Ecto.Schema - alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsRepliesValidator - import Ecto.Changeset @primary_key false embedded_schema do field(:name, :string) - embeds_one(:replies, QuestionOptionsRepliesValidator) + + embeds_one :replies, Replies do + field(:totalItems, :integer) + field(:type, :string) + end + field(:type, :string) end def changeset(struct, data) do struct |> cast(data, [:name, :type]) - |> cast_embed(:replies) + |> cast_embed(:replies, with: &replies_changeset/2) |> validate_inclusion(:type, ["Note"]) |> validate_required([:name, :type]) end -end - -defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsRepliesValidator do - use Ecto.Schema - - import Ecto.Changeset - @primary_key false - - embedded_schema do - field(:totalItems, :integer) - field(:type, :string) - end - - def changeset(struct, data) do + def replies_changeset(struct, data) do struct - |> cast(data, __schema__(:fields)) + |> cast(data, [:totalItems, :type]) |> validate_inclusion(:type, ["Collection"]) |> validate_required([:type]) end -- cgit v1.2.3 From 10bd08ef07bd91995589ad37cb25e6889dac59b3 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sun, 14 Jun 2020 22:25:04 +0200 Subject: transmogrifier_test: test date, anyOf and oneOf completely --- .../question_options_validator.ex | 2 +- test/web/activity_pub/transmogrifier_test.exs | 35 +++++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex index 8291d7b9f..478b3b5cf 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex @@ -12,7 +12,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator do embedded_schema do field(:name, :string) - embeds_one :replies, Replies do + embeds_one :replies, Replies, primary_key: false do field(:totalItems, :integer) field(:type, :string) end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 73949b558..4184b93ce 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -224,14 +224,33 @@ test "it works for incoming questions" do object = Object.normalize(activity, false) - assert Enum.all?(object.data["oneOf"], fn choice -> - choice["name"] in [ - "Dunno", - "Everyone knows that!", - "25 char limit is dumb", - "I can't even fit a funny" - ] - end) + assert object.data["closed"] == "2019-05-11T09:03:36Z" + + assert object.data["anyOf"] == [] + + assert Enum.sort(object.data["oneOf"]) == + Enum.sort([ + %{ + "name" => "25 char limit is dumb", + "replies" => %{"totalItems" => 0, "type" => "Collection"}, + "type" => "Note" + }, + %{ + "name" => "Dunno", + "replies" => %{"totalItems" => 0, "type" => "Collection"}, + "type" => "Note" + }, + %{ + "name" => "Everyone knows that!", + "replies" => %{"totalItems" => 1, "type" => "Collection"}, + "type" => "Note" + }, + %{ + "name" => "I can't even fit a funny", + "replies" => %{"totalItems" => 1, "type" => "Collection"}, + "type" => "Note" + } + ]) end test "it works for incoming listens" do -- cgit v1.2.3 From 4644a8bd109faf6c684767fc60c37e298b8c5c07 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 15 Jun 2020 00:30:45 +0200 Subject: Fix multiple-choice poll detection --- lib/pleroma/object.ex | 17 ++++++++++------- lib/pleroma/web/common_api/common_api.ex | 9 +++++++-- lib/pleroma/web/mastodon_api/views/poll_view.ex | 4 ++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index 546c4ea01..4dd929cfd 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -255,6 +255,12 @@ def increase_replies_count(ap_id) do end end + defp poll_is_multiple?(%Object{data: %{"anyOf" => anyOf}}) do + !Enum.empty?(anyOf) + end + + defp poll_is_multiple?(_), do: false + def decrease_replies_count(ap_id) do Object |> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id))) @@ -281,10 +287,10 @@ def decrease_replies_count(ap_id) do def increase_vote_count(ap_id, name, actor) do with %Object{} = object <- Object.normalize(ap_id), "Question" <- object.data["type"] do - multiple = Map.has_key?(object.data, "anyOf") + key = if poll_is_multiple?(object), do: "anyOf", else: "oneOf" options = - (object.data["anyOf"] || object.data["oneOf"] || []) + object.data[key] |> Enum.map(fn %{"name" => ^name} = option -> Kernel.update_in(option["replies"]["totalItems"], &(&1 + 1)) @@ -296,11 +302,8 @@ def increase_vote_count(ap_id, name, actor) do voters = [actor | object.data["voters"] || []] |> Enum.uniq() data = - if multiple do - Map.put(object.data, "anyOf", options) - else - Map.put(object.data, "oneOf", options) - end + object.data + |> Map.put(key, options) |> Map.put("voters", voters) object diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 4d5b0decf..692ceab1e 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -340,8 +340,13 @@ defp validate_existing_votes(%{ap_id: ap_id}, object) do end end - defp get_options_and_max_count(%{data: %{"anyOf" => any_of}}), do: {any_of, Enum.count(any_of)} - defp get_options_and_max_count(%{data: %{"oneOf" => one_of}}), do: {one_of, 1} + defp get_options_and_max_count(%{data: %{"anyOf" => any_of}}) + when is_list(any_of) and any_of != [], + do: {any_of, Enum.count(any_of)} + + defp get_options_and_max_count(%{data: %{"oneOf" => one_of}}) + when is_list(one_of) and one_of != [], + do: {one_of, 1} defp normalize_and_validate_choices(choices, object) do choices = Enum.map(choices, fn i -> if is_binary(i), do: String.to_integer(i), else: i end) diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex index 59a5deb28..73c990e2e 100644 --- a/lib/pleroma/web/mastodon_api/views/poll_view.ex +++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex @@ -28,10 +28,10 @@ def render("show.json", %{object: object, multiple: multiple, options: options} def render("show.json", %{object: object} = params) do case object.data do - %{"anyOf" => options} when is_list(options) -> + %{"anyOf" => options} when is_list(options) and options != [] -> render(__MODULE__, "show.json", Map.merge(params, %{multiple: true, options: options})) - %{"oneOf" => options} when is_list(options) -> + %{"oneOf" => options} when is_list(options) and options != [] -> render(__MODULE__, "show.json", Map.merge(params, %{multiple: false, options: options})) _ -> -- cgit v1.2.3 From 6b9c4bc1f1e5013cdfc084603cdf6cfa83ac2778 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sun, 14 Jun 2020 22:24:00 +0200 Subject: fetcher: more descriptive variable names --- lib/pleroma/object/fetcher.ex | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex index 3e2949ee2..e1ab4ef8b 100644 --- a/lib/pleroma/object/fetcher.ex +++ b/lib/pleroma/object/fetcher.ex @@ -23,21 +23,21 @@ defp touch_changeset(changeset) do Ecto.Changeset.put_change(changeset, :updated_at, updated_at) end - defp maybe_reinject_internal_fields(data, %{data: %{} = old_data}) do + defp maybe_reinject_internal_fields(%{data: %{} = old_data}, new_data) do internal_fields = Map.take(old_data, Pleroma.Constants.object_internal_fields()) - Map.merge(data, internal_fields) + Map.merge(new_data, internal_fields) end - defp maybe_reinject_internal_fields(data, _), do: data + defp maybe_reinject_internal_fields(_, new_data), do: new_data @spec reinject_object(struct(), map()) :: {:ok, Object.t()} | {:error, any()} - defp reinject_object(struct, data) do - Logger.debug("Reinjecting object #{data["id"]}") + defp reinject_object(%Object{} = object, new_data) do + Logger.debug("Reinjecting object #{new_data["id"]}") - with data <- Transmogrifier.fix_object(data), - data <- maybe_reinject_internal_fields(data, struct), - changeset <- Object.change(struct, %{data: data}), + with new_data <- Transmogrifier.fix_object(new_data), + data <- maybe_reinject_internal_fields(object, new_data), + changeset <- Object.change(object, %{data: data}), changeset <- touch_changeset(changeset), {:ok, object} <- Repo.insert_or_update(changeset), {:ok, object} <- Object.set_cache(object) do @@ -51,8 +51,8 @@ defp reinject_object(struct, data) do def refetch_object(%Object{data: %{"id" => id}} = object) do with {:local, false} <- {:local, Object.local?(object)}, - {:ok, data} <- fetch_and_contain_remote_object_from_id(id), - {:ok, object} <- reinject_object(object, data) do + {:ok, new_data} <- fetch_and_contain_remote_object_from_id(id), + {:ok, object} <- reinject_object(object, new_data) do {:ok, object} else {:local, true} -> {:ok, object} -- cgit v1.2.3 From ad867ccfa18afe2a6104cad4d3035834c5a264c8 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sun, 14 Jun 2020 22:01:14 +0200 Subject: fetcher: Reinject Question through validator --- lib/pleroma/object/fetcher.ex | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex index e1ab4ef8b..3956bb727 100644 --- a/lib/pleroma/object/fetcher.ex +++ b/lib/pleroma/object/fetcher.ex @@ -9,6 +9,7 @@ defmodule Pleroma.Object.Fetcher do alias Pleroma.Repo alias Pleroma.Signature alias Pleroma.Web.ActivityPub.InternalFetchActor + alias Pleroma.Web.ActivityPub.ObjectValidator alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.Federator @@ -32,6 +33,24 @@ defp maybe_reinject_internal_fields(%{data: %{} = old_data}, new_data) do defp maybe_reinject_internal_fields(_, new_data), do: new_data @spec reinject_object(struct(), map()) :: {:ok, Object.t()} | {:error, any()} + defp reinject_object(%Object{data: %{"type" => "Question"}} = object, new_data) do + Logger.debug("Reinjecting object #{new_data["id"]}") + + with new_data <- Transmogrifier.fix_object(new_data), + data <- maybe_reinject_internal_fields(object, new_data), + {:ok, data, _} <- ObjectValidator.validate(data, %{}), + changeset <- Object.change(object, %{data: data}), + changeset <- touch_changeset(changeset), + {:ok, object} <- Repo.insert_or_update(changeset), + {:ok, object} <- Object.set_cache(object) do + {:ok, object} + else + e -> + Logger.error("Error while processing object: #{inspect(e)}") + {:error, e} + end + end + defp reinject_object(%Object{} = object, new_data) do Logger.debug("Reinjecting object #{new_data["id"]}") -- cgit v1.2.3 From 47ba796f415740c443cd8477c121280656b13032 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 15 Jun 2020 02:20:18 +0200 Subject: create_question_validator: remove validate_recipients_match --- .../object_validators/create_question_validator.ex | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex index f09207418..6d3f71566 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex @@ -47,7 +47,6 @@ def validate_data(cng, meta \\ []) do |> validate_inclusion(:type, ["Create"]) |> validate_actor_presence() |> validate_any_presence([:to, :cc]) - |> validate_recipients_match(meta) |> validate_actors_match(meta) |> validate_object_nonexistence() end @@ -75,20 +74,4 @@ def validate_actors_match(cng, meta) do end end) end - - def validate_recipients_match(cng, meta) do - object_recipients = meta[:object_data]["to"] || [] - - cng - |> validate_change(:to, fn :to, recipients -> - activity_set = MapSet.new(recipients) - object_set = MapSet.new(object_recipients) - - if MapSet.equal?(activity_set, object_set) do - [] - else - [{:to, "Recipients don't match with object recipients"}] - end - end) - end end -- cgit v1.2.3 From 173f69c854adf966d52b3767c4de43a0b1ce5b00 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 15 Jun 2020 05:18:30 +0200 Subject: question_validator: fix for mastodon poll expiration Mastodon activities do not have a "closed" field, this could be seen on https://pouet.it/users/lanodan_tmp/statuses/104345126997708380 which runs Mastodon 3.1.4 (SDF runs 3.1.2) --- .../activity_pub/object_validators/question_validator.ex | 10 ++++++++++ lib/pleroma/web/mastodon_api/views/poll_view.ex | 14 ++++++-------- test/fixtures/mastodon-question-activity.json | 1 - 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index f94d79352..605cb56f8 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -71,7 +71,17 @@ def cast_data(data) do |> changeset(data) end + def fix(data) do + cond do + is_binary(data["closed"]) -> data + is_binary(data["endTime"]) -> Map.put(data, "closed", data["endTime"]) + true -> Map.drop(data, ["closed"]) + end + end + def changeset(struct, data) do + data = fix(data) + struct |> cast(data, __schema__(:fields) -- [:anyOf, :oneOf]) |> cast_embed(:anyOf) diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex index 73c990e2e..ce595ae8a 100644 --- a/lib/pleroma/web/mastodon_api/views/poll_view.ex +++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex @@ -40,15 +40,13 @@ def render("show.json", %{object: object} = params) do end defp end_time_and_expired(object) do - case object.data["closed"] || object.data["endTime"] do - end_time when is_binary(end_time) -> - end_time = NaiveDateTime.from_iso8601!(end_time) - expired = NaiveDateTime.compare(end_time, NaiveDateTime.utc_now()) == :lt + if object.data["closed"] do + end_time = NaiveDateTime.from_iso8601!(object.data["closed"]) + expired = NaiveDateTime.compare(end_time, NaiveDateTime.utc_now()) == :lt - {Utils.to_masto_date(end_time), expired} - - _ -> - {nil, false} + {Utils.to_masto_date(end_time), expired} + else + {nil, false} end end diff --git a/test/fixtures/mastodon-question-activity.json b/test/fixtures/mastodon-question-activity.json index ac329c7d5..3648b9f90 100644 --- a/test/fixtures/mastodon-question-activity.json +++ b/test/fixtures/mastodon-question-activity.json @@ -49,7 +49,6 @@ "en": "

Why is Tenshi eating a corndog so cute?

" }, "endTime": "2019-05-11T09:03:36Z", - "closed": "2019-05-11T09:03:36Z", "attachment": [], "tag": [], "replies": { -- cgit v1.2.3 From 4f70fd4105e90c8fc06a1eb6bd70084874bae3a5 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 18 Jun 2020 19:54:56 +0200 Subject: question_validator: remove conversation field --- lib/pleroma/web/activity_pub/object_validators/question_validator.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index 605cb56f8..211f520c4 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -45,7 +45,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do field(:announcements, {:array, :string}, default: []) # see if needed - field(:conversation, :string) field(:context_id, :string) field(:closed, Types.DateTime) -- cgit v1.2.3 From 82895a40123ca24258a95b9ac7e117dd8b1e698e Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 18 Jun 2020 04:05:42 +0200 Subject: SideEffects: port ones from ActivityPub.do_create and ActivityPub.insert --- lib/pleroma/object/containment.ex | 2 +- lib/pleroma/web/activity_pub/activity_pub.ex | 13 +-- lib/pleroma/web/activity_pub/builder.ex | 15 ++++ lib/pleroma/web/activity_pub/object_validator.ex | 6 +- .../object_validators/answer_validator.ex | 7 +- .../object_validators/common_validations.ex | 38 ++++++++ .../object_validators/create_generic_validator.ex | 100 +++++++++++++++++++++ .../object_validators/create_question_validator.ex | 77 ---------------- .../object_validators/question_validator.ex | 28 ++++-- lib/pleroma/web/activity_pub/side_effects.ex | 30 ++++++- lib/pleroma/web/activity_pub/transmogrifier.ex | 49 ++++++---- lib/pleroma/web/common_api/common_api.ex | 25 +++--- lib/pleroma/web/common_api/utils.ex | 11 --- test/web/activity_pub/transmogrifier_test.exs | 2 +- 14 files changed, 259 insertions(+), 144 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex delete mode 100644 lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex diff --git a/lib/pleroma/object/containment.ex b/lib/pleroma/object/containment.ex index 99608b8a5..bc88e8a0c 100644 --- a/lib/pleroma/object/containment.ex +++ b/lib/pleroma/object/containment.ex @@ -55,7 +55,7 @@ defp compare_uris(%URI{host: host} = _id_uri, %URI{host: host} = _other_uri), do defp compare_uris(_id_uri, _other_uri), do: :error @doc """ - Checks that an imported AP object's actor matches the domain it came from. + Checks that an imported AP object's actor matches the host it came from. """ def contain_origin(_id, %{"actor" => nil}), do: :error diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index d8cc8d24f..9d13a06c4 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -66,7 +66,7 @@ defp check_remote_limit(%{"object" => %{"content" => content}}) when not is_nil( defp check_remote_limit(_), do: true - defp increase_note_count_if_public(actor, object) do + def increase_note_count_if_public(actor, object) do if is_public?(object), do: User.increase_note_count(actor), else: {:ok, actor} end @@ -85,16 +85,6 @@ defp increase_replies_count_if_reply(%{ defp increase_replies_count_if_reply(_create_data), do: :noop - defp increase_poll_votes_if_vote(%{ - "object" => %{"inReplyTo" => reply_ap_id, "name" => name}, - "type" => "Create", - "actor" => actor - }) do - Object.increase_vote_count(reply_ap_id, name, actor) - end - - defp increase_poll_votes_if_vote(_create_data), do: :noop - @object_types ["ChatMessage", "Question", "Answer"] @spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()} def persist(%{"type" => type} = object, meta) when type in @object_types do @@ -258,7 +248,6 @@ defp do_create(%{to: to, actor: actor, context: context, object: object} = param with {:ok, activity} <- insert(create_data, local, fake), {:fake, false, activity} <- {:fake, fake, activity}, _ <- increase_replies_count_if_reply(create_data), - _ <- increase_poll_votes_if_vote(create_data), {:quick_insert, false, activity} <- {:quick_insert, quick_insert?, activity}, {:ok, _actor} <- increase_note_count_if_public(actor, activity), _ <- notify_and_stream(activity), diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index d5f3610ed..e97381954 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -115,6 +115,21 @@ def chat_message(actor, recipient, content, opts \\ []) do end end + def answer(user, object, name) do + {:ok, + %{ + "type" => "Answer", + "actor" => user.ap_id, + "cc" => [object.data["actor"]], + "to" => [], + "name" => name, + "inReplyTo" => object.data["id"], + "context" => object.data["context"], + "published" => DateTime.utc_now() |> DateTime.to_iso8601(), + "id" => Utils.generate_object_id() + }, []} + end + @spec tombstone(String.t(), String.t()) :: {:ok, map(), keyword()} def tombstone(actor, id) do {:ok, diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index c89311187..a24aaf00c 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -17,7 +17,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator - alias Pleroma.Web.ActivityPub.ObjectValidators.CreateQuestionValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator @@ -162,7 +162,7 @@ def validate( meta = Keyword.put(meta, :object_data, object_data |> stringify_keys), {:ok, create_activity} <- create_activity - |> CreateQuestionValidator.cast_and_validate(meta) + |> CreateGenericValidator.cast_and_validate(meta) |> Ecto.Changeset.apply_action(:insert) do create_activity = stringify_keys(create_activity) {:ok, create_activity, meta} @@ -188,7 +188,7 @@ def cast_and_apply(%{"type" => "Question"} = object) do end def cast_and_apply(%{"type" => "Answer"} = object) do - QuestionValidator.cast_and_apply(object) + AnswerValidator.cast_and_apply(object) end def cast_and_apply(o), do: {:error, {:validator_not_set, o}} diff --git a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex index 0b51eccfa..8d4c92520 100644 --- a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex @@ -13,22 +13,25 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do @primary_key false @derive Jason.Encoder - # Extends from NoteValidator embedded_schema do field(:id, Types.ObjectID, primary_key: true) field(:to, {:array, :string}, default: []) field(:cc, {:array, :string}, default: []) + + # is this actually needed? field(:bto, {:array, :string}, default: []) field(:bcc, {:array, :string}, default: []) + field(:type, :string) field(:name, :string) field(:inReplyTo, :string) field(:attributedTo, Types.ObjectID) + field(:actor, Types.ObjectID) end def cast_and_apply(data) do data - |> cast_data + |> cast_data() |> apply_action(:insert) end diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index e746b9360..140555a45 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -42,6 +42,19 @@ def validate_actor_presence(cng, options \\ []) do end) end + def validate_actor_is_active(cng, options \\ []) do + field_name = Keyword.get(options, :field_name, :actor) + + cng + |> validate_change(field_name, fn field_name, actor -> + if %User{deactivated: false} = User.get_cached_by_ap_id(actor) do + [] + else + [{field_name, "can't find user (or deactivated)"}] + end + end) + end + def validate_object_presence(cng, options \\ []) do field_name = Keyword.get(options, :field_name, :object) allowed_types = Keyword.get(options, :allowed_types, false) @@ -77,4 +90,29 @@ def validate_object_or_user_presence(cng, options \\ []) do if actor_cng.valid?, do: actor_cng, else: object_cng end + + def validate_host_match(cng, fields \\ [:id, :actor]) do + unique_hosts = + fields + |> Enum.map(fn field -> + %URI{host: host} = + cng + |> get_field(field) + |> URI.parse() + + host + end) + |> Enum.uniq() + |> Enum.count() + + if unique_hosts == 1 do + cng + else + fields + |> Enum.reduce(cng, fn field, cng -> + cng + |> add_error(field, "hosts of #{inspect(fields)} aren't matching") + end) + end + end end diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex new file mode 100644 index 000000000..4ad4ca0de --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -0,0 +1,100 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +# Code based on CreateChatMessageValidator +# NOTES +# - doesn't embed, will only get the object id +defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do + use Ecto.Schema + + alias Pleroma.Object + alias Pleroma.Web.ActivityPub.ObjectValidators.Types + + import Ecto.Changeset + import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + + @primary_key false + + embedded_schema do + field(:id, Types.ObjectID, primary_key: true) + field(:actor, Types.ObjectID) + field(:type, :string) + field(:to, Types.Recipients, default: []) + field(:cc, Types.Recipients, default: []) + field(:object, Types.ObjectID) + end + + def cast_data(data) do + %__MODULE__{} + |> changeset(data) + end + + def cast_and_apply(data) do + data + |> cast_data + |> apply_action(:insert) + end + + def cast_and_validate(data, meta \\ []) do + data + |> cast_data + |> validate_data(meta) + end + + def changeset(struct, data) do + struct + |> cast(data, __schema__(:fields)) + end + + def validate_data(cng, meta \\ []) do + cng + |> validate_required([:actor, :type, :object]) + |> validate_inclusion(:type, ["Create"]) + |> validate_actor_is_active() + |> validate_any_presence([:to, :cc]) + |> validate_actors_match(meta) + |> validate_object_nonexistence() + |> validate_object_containment() + end + + def validate_object_containment(cng) do + actor = get_field(cng, :actor) + + cng + |> validate_change(:object, fn :object, object_id -> + %URI{host: object_id_host} = URI.parse(object_id) + %URI{host: actor_host} = URI.parse(actor) + + if object_id_host == actor_host do + [] + else + [{:object, "The host of the object id doesn't match with the host of the actor"}] + end + end) + end + + def validate_object_nonexistence(cng) do + cng + |> validate_change(:object, fn :object, object_id -> + if Object.get_cached_by_ap_id(object_id) do + [{:object, "The object to create already exists"}] + else + [] + end + end) + end + + def validate_actors_match(cng, meta) do + object_actor = meta[:object_data]["actor"] + + cng + |> validate_change(:actor, fn :actor, actor -> + if actor == object_actor do + [] + else + [{:actor, "Actor doesn't match with object actor"}] + end + end) + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex deleted file mode 100644 index 6d3f71566..000000000 --- a/lib/pleroma/web/activity_pub/object_validators/create_question_validator.ex +++ /dev/null @@ -1,77 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -# Code based on CreateChatMessageValidator -# NOTES -# - Can probably be a generic create validator -# - doesn't embed, will only get the object id -defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateQuestionValidator do - use Ecto.Schema - - alias Pleroma.Object - alias Pleroma.Web.ActivityPub.ObjectValidators.Types - - import Ecto.Changeset - import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations - - @primary_key false - - embedded_schema do - field(:id, Types.ObjectID, primary_key: true) - field(:actor, Types.ObjectID) - field(:type, :string) - field(:to, Types.Recipients, default: []) - field(:cc, Types.Recipients, default: []) - field(:object, Types.ObjectID) - end - - def cast_and_apply(data) do - data - |> cast_data - |> apply_action(:insert) - end - - def cast_data(data) do - cast(%__MODULE__{}, data, __schema__(:fields)) - end - - def cast_and_validate(data, meta \\ []) do - cast_data(data) - |> validate_data(meta) - end - - def validate_data(cng, meta \\ []) do - cng - |> validate_required([:actor, :type, :object]) - |> validate_inclusion(:type, ["Create"]) - |> validate_actor_presence() - |> validate_any_presence([:to, :cc]) - |> validate_actors_match(meta) - |> validate_object_nonexistence() - end - - def validate_object_nonexistence(cng) do - cng - |> validate_change(:object, fn :object, object_id -> - if Object.get_cached_by_ap_id(object_id) do - [{:object, "The object to create already exists"}] - else - [] - end - end) - end - - def validate_actors_match(cng, meta) do - object_actor = meta[:object_data]["actor"] - - cng - |> validate_change(:actor, fn :actor, actor -> - if actor == object_actor do - [] - else - [{:actor, "Actor doesn't match with object actor"}] - end - end) - end -end diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index 211f520c4..f7f3b1354 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do use Ecto.Schema + alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator alias Pleroma.Web.ActivityPub.ObjectValidators.Types @@ -40,13 +41,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do field(:announcement_count, :integer, default: 0) field(:inReplyTo, :string) field(:uri, Types.Uri) + # short identifier for PleromaFE to group statuses by context + field(:context_id, :integer) field(:likes, {:array, :string}, default: []) field(:announcements, {:array, :string}, default: []) - # see if needed - field(:context_id, :string) - field(:closed, Types.DateTime) field(:voters, {:array, Types.ObjectID}, default: []) embeds_many(:anyOf, QuestionOptionsValidator) @@ -70,7 +70,7 @@ def cast_data(data) do |> changeset(data) end - def fix(data) do + defp fix_closed(data) do cond do is_binary(data["closed"]) -> data is_binary(data["endTime"]) -> Map.put(data, "closed", data["endTime"]) @@ -78,6 +78,23 @@ def fix(data) do end end + # based on Pleroma.Web.ActivityPub.Utils.lazy_put_objects_defaults + defp fix_defaults(data) do + %{data: %{"id" => context}, id: context_id} = Utils.create_context(data["context"]) + + data + |> Map.put_new_lazy("id", &Utils.generate_object_id/0) + |> Map.put_new_lazy("published", &Utils.make_date/0) + |> Map.put_new("context", context) + |> Map.put_new("context_id", context_id) + end + + defp fix(data) do + data + |> fix_closed() + |> fix_defaults() + end + def changeset(struct, data) do data = fix(data) @@ -92,7 +109,8 @@ def validate_data(data_cng) do |> validate_inclusion(:type, ["Question"]) |> validate_required([:id, :actor, :type, :content, :context]) |> CommonValidations.validate_any_presence([:cc, :to]) - |> CommonValidations.validate_actor_presence() + |> CommonValidations.validate_actor_is_active() |> CommonValidations.validate_any_presence([:oneOf, :anyOf]) + |> CommonValidations.validate_host_match() end end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index a78ec411f..c17197bec 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do """ alias Pleroma.Activity alias Pleroma.Activity.Ir.Topics + alias Pleroma.ActivityExpiration alias Pleroma.Chat alias Pleroma.Chat.MessageReference alias Pleroma.FollowingRelationship @@ -19,6 +20,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.Push alias Pleroma.Web.Streamer + alias Pleroma.Workers.BackgroundWorker def handle(object, meta \\ []) @@ -135,10 +137,24 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do # Tasks this handles # - Actually create object # - Rollback if we couldn't create it + # - Increase the user note count + # - Increase the reply count # - Set up notifications def handle(%{data: %{"type" => "Create"}} = activity, meta) do - with {:ok, _object, meta} <- handle_object_creation(meta[:object_data], meta) do + with {:ok, object, meta} <- handle_object_creation(meta[:object_data], meta), + %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do {:ok, notifications} = Notification.create_notifications(activity, do_send: false) + {:ok, _user} = ActivityPub.increase_note_count_if_public(user, object) + + if in_reply_to = object.data["inReplyTo"] do + Object.increase_replies_count(in_reply_to) + end + + if expires_at = activity.data["expires_at"] do + ActivityExpiration.create(activity, expires_at) + end + + BackgroundWorker.enqueue("fetch_data_for_activity", %{"activity_id" => activity.id}) meta = meta @@ -268,6 +284,18 @@ def handle_object_creation(%{"type" => "ChatMessage"} = object, meta) do end end + def handle_object_creation(%{"type" => "Answer"} = object_map, meta) do + with {:ok, object, meta} <- Pipeline.common_pipeline(object_map, meta) do + Object.increase_vote_count( + object.data["inReplyTo"], + object.data["name"], + object.data["actor"] + ) + + {:ok, object, meta} + end + end + def handle_object_creation(%{"type" => "Question"} = object, meta) do with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do {:ok, object, meta} diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 9900602e4..26325d5de 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -419,6 +419,29 @@ defp get_reported(objects) do end) end + # Compatibility wrapper for Mastodon votes + defp handle_create(%{"object" => %{"type" => "Answer"}} = data, _user) do + handle_incoming(data) + end + + defp handle_create(%{"object" => object} = data, user) do + %{ + to: data["to"], + object: object, + actor: user, + context: object["context"], + local: false, + published: data["published"], + additional: + Map.take(data, [ + "cc", + "directMessage", + "id" + ]) + } + |> ActivityPub.create() + end + def handle_incoming(data, options \\ []) # Flag objects are placed ahead of the ID check because Mastodon 2.8 and earlier send them @@ -461,26 +484,14 @@ def handle_incoming( actor = Containment.get_actor(data) with nil <- Activity.get_create_by_object_ap_id(object["id"]), - {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(actor), - data <- Map.put(data, "actor", actor) |> fix_addressing() do - object = fix_object(object, options) - - params = %{ - to: data["to"], - object: object, - actor: user, - context: object["context"], - local: false, - published: data["published"], - additional: - Map.take(data, [ - "cc", - "directMessage", - "id" - ]) - } + {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(actor) do + data = + data + |> Map.put("object", fix_object(object, options)) + |> Map.put("actor", actor) + |> fix_addressing() - with {:ok, created_activity} <- ActivityPub.create(params) do + with {:ok, created_activity} <- handle_create(data, user) do reply_depth = (options[:depth] || 0) + 1 if Federator.allowed_thread_distance?(reply_depth) do diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 692ceab1e..c08e0ffeb 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -308,18 +308,19 @@ def vote(user, %{data: %{"type" => "Question"}} = object, choices) do {:ok, options, choices} <- normalize_and_validate_choices(choices, object) do answer_activities = Enum.map(choices, fn index -> - answer_data = make_answer_data(user, object, Enum.at(options, index)["name"]) - - {:ok, activity} = - ActivityPub.create(%{ - to: answer_data["to"], - actor: user, - context: object.data["context"], - object: answer_data, - additional: %{"cc" => answer_data["cc"]} - }) - - activity + {:ok, answer_object, _meta} = + Builder.answer(user, object, Enum.at(options, index)["name"]) + + {:ok, activity_data, _meta} = Builder.create(user, answer_object, []) + + {:ok, activity, _meta} = + activity_data + |> Map.put("cc", answer_object["cc"]) + |> Map.put("context", answer_object["context"]) + |> Pipeline.common_pipeline(local: true) + + # TODO: Do preload of Pleroma.Object in Pipeline + Activity.normalize(activity.data) end) object = Object.get_cached_by_ap_id(object.data["id"]) diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 9c38b73eb..9d7b24eb2 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -548,17 +548,6 @@ def conversation_id_to_context(id) do end end - def make_answer_data(%User{ap_id: ap_id}, object, name) do - %{ - "type" => "Answer", - "actor" => ap_id, - "cc" => [object.data["actor"]], - "to" => [], - "name" => name, - "inReplyTo" => object.data["id"] - } - end - def validate_character_limit("" = _full_payload, [] = _attachments) do {:error, dgettext("errors", "Cannot post an empty status without attachments")} end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 4184b93ce..62b5b06aa 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -282,7 +282,7 @@ test "it works for incoming listens" do assert object.data["length"] == 180_000 end - test "it rewrites Note votes to Answers and increments vote counters on question activities" do + test "it rewrites Note votes to Answer and increments vote counters on Question activities" do user = insert(:user) {:ok, activity} = -- cgit v1.2.3 From 39870d99b810940ccce430411c9fc6939f760663 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 19 Jun 2020 23:31:19 +0200 Subject: transmogrifier tests: Move & enhance in specialised modules --- .../transmogrifier/answer_handling_test.exs | 78 ++++++++++++++++++ .../transmogrifier/question_handling_test.exs | 65 +++++++++++++++ test/web/activity_pub/transmogrifier_test.exs | 92 ---------------------- 3 files changed, 143 insertions(+), 92 deletions(-) create mode 100644 test/web/activity_pub/transmogrifier/answer_handling_test.exs create mode 100644 test/web/activity_pub/transmogrifier/question_handling_test.exs diff --git a/test/web/activity_pub/transmogrifier/answer_handling_test.exs b/test/web/activity_pub/transmogrifier/answer_handling_test.exs new file mode 100644 index 000000000..0f6605c3f --- /dev/null +++ b/test/web/activity_pub/transmogrifier/answer_handling_test.exs @@ -0,0 +1,78 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnswerHandlingTest do + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + :ok + end + + test "incoming, rewrites Note to Answer and increments vote counters" do + user = insert(:user) + + {:ok, activity} = + CommonAPI.post(user, %{ + status: "suya...", + poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} + }) + + object = Object.normalize(activity) + + data = + File.read!("test/fixtures/mastodon-vote.json") + |> Poison.decode!() + |> Kernel.put_in(["to"], user.ap_id) + |> Kernel.put_in(["object", "inReplyTo"], object.data["id"]) + |> Kernel.put_in(["object", "to"], user.ap_id) + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + answer_object = Object.normalize(activity) + assert answer_object.data["type"] == "Answer" + assert answer_object.data["inReplyTo"] == object.data["id"] + + new_object = Object.get_by_ap_id(object.data["id"]) + assert new_object.data["replies_count"] == object.data["replies_count"] + + assert Enum.any?( + new_object.data["oneOf"], + fn + %{"name" => "suya..", "replies" => %{"totalItems" => 1}} -> true + _ -> false + end + ) + end + + test "outgoing, rewrites Answer to Note" do + user = insert(:user) + + {:ok, poll_activity} = + CommonAPI.post(user, %{ + status: "suya...", + poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} + }) + + poll_object = Object.normalize(poll_activity) + # TODO: Replace with CommonAPI vote creation when implemented + data = + File.read!("test/fixtures/mastodon-vote.json") + |> Poison.decode!() + |> Kernel.put_in(["to"], user.ap_id) + |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"]) + |> Kernel.put_in(["object", "to"], user.ap_id) + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + {:ok, data} = Transmogrifier.prepare_outgoing(activity.data) + + assert data["object"]["type"] == "Note" + end +end diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs new file mode 100644 index 000000000..b7b9a1a7b --- /dev/null +++ b/test/web/activity_pub/transmogrifier/question_handling_test.exs @@ -0,0 +1,65 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.Web.ActivityPub.Transmogrifier + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + :ok + end + + test "Mastodon Question activity" do + data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + + object = Object.normalize(activity, false) + + assert object.data["closed"] == "2019-05-11T09:03:36Z" + + 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"]) == + Enum.sort([ + %{ + "name" => "25 char limit is dumb", + "replies" => %{"totalItems" => 0, "type" => "Collection"}, + "type" => "Note" + }, + %{ + "name" => "Dunno", + "replies" => %{"totalItems" => 0, "type" => "Collection"}, + "type" => "Note" + }, + %{ + "name" => "Everyone knows that!", + "replies" => %{"totalItems" => 1, "type" => "Collection"}, + "type" => "Note" + }, + %{ + "name" => "I can't even fit a funny", + "replies" => %{"totalItems" => 1, "type" => "Collection"}, + "type" => "Note" + } + ]) + end + + test "returns an error if received a second time" do + data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() + + assert {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + + assert {:error, {:validate_object, {:error, _}}} = Transmogrifier.handle_incoming(data) + end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 62b5b06aa..272431135 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -217,42 +217,6 @@ test "it works for incoming notices with hashtags" do assert Enum.at(object.data["tag"], 2) == "moo" end - test "it works for incoming questions" do - data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() - - {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - - object = Object.normalize(activity, false) - - assert object.data["closed"] == "2019-05-11T09:03:36Z" - - assert object.data["anyOf"] == [] - - assert Enum.sort(object.data["oneOf"]) == - Enum.sort([ - %{ - "name" => "25 char limit is dumb", - "replies" => %{"totalItems" => 0, "type" => "Collection"}, - "type" => "Note" - }, - %{ - "name" => "Dunno", - "replies" => %{"totalItems" => 0, "type" => "Collection"}, - "type" => "Note" - }, - %{ - "name" => "Everyone knows that!", - "replies" => %{"totalItems" => 1, "type" => "Collection"}, - "type" => "Note" - }, - %{ - "name" => "I can't even fit a funny", - "replies" => %{"totalItems" => 1, "type" => "Collection"}, - "type" => "Note" - } - ]) - end - test "it works for incoming listens" do data = %{ "@context" => "https://www.w3.org/ns/activitystreams", @@ -282,38 +246,6 @@ test "it works for incoming listens" do assert object.data["length"] == 180_000 end - test "it rewrites Note votes to Answer and increments vote counters on Question activities" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "suya...", - poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} - }) - - object = Object.normalize(activity) - - data = - File.read!("test/fixtures/mastodon-vote.json") - |> Poison.decode!() - |> Kernel.put_in(["to"], user.ap_id) - |> Kernel.put_in(["object", "inReplyTo"], object.data["id"]) - |> Kernel.put_in(["object", "to"], user.ap_id) - - {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - answer_object = Object.normalize(activity) - assert answer_object.data["type"] == "Answer" - object = Object.get_by_ap_id(object.data["id"]) - - assert Enum.any?( - object.data["oneOf"], - fn - %{"name" => "suya..", "replies" => %{"totalItems" => 1}} -> true - _ -> false - end - ) - end - test "it works for incoming notices with contentMap" do data = File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!() @@ -1280,30 +1212,6 @@ test "successfully reserializes a message with AS2 objects in IR" do end end - test "Rewrites Answers to Notes" do - user = insert(:user) - - {:ok, poll_activity} = - CommonAPI.post(user, %{ - status: "suya...", - poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} - }) - - poll_object = Object.normalize(poll_activity) - # TODO: Replace with CommonAPI vote creation when implemented - data = - File.read!("test/fixtures/mastodon-vote.json") - |> Poison.decode!() - |> Kernel.put_in(["to"], user.ap_id) - |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"]) - |> Kernel.put_in(["object", "to"], user.ap_id) - - {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - {:ok, data} = Transmogrifier.prepare_outgoing(activity.data) - - assert data["object"]["type"] == "Note" - end - describe "fix_explicit_addressing" do setup do user = insert(:user) -- cgit v1.2.3 From fe6924d00d710e7e568d0ed40c02d3c516d91460 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 19 Jun 2020 23:43:36 +0200 Subject: CreateGenericValidator: add expires_at --- .../web/activity_pub/object_validators/create_generic_validator.ex | 1 + lib/pleroma/web/activity_pub/side_effects.ex | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex index 4ad4ca0de..f467ccc7c 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -23,6 +23,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do field(:to, Types.Recipients, default: []) field(:cc, Types.Recipients, default: []) field(:object, Types.ObjectID) + field(:expires_at, Types.DateTime) end def cast_data(data) do diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index c17197bec..5104d38ee 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -139,6 +139,8 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do # - Rollback if we couldn't create it # - Increase the user note count # - Increase the reply count + # - Increase replies count + # - Set up ActivityExpiration # - Set up notifications def handle(%{data: %{"type" => "Create"}} = activity, meta) do with {:ok, object, meta} <- handle_object_creation(meta[:object_data], meta), -- cgit v1.2.3 From 435a65b9768b9f2c614ba5e00d83753b5834a695 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 20 Jun 2020 00:07:39 +0200 Subject: QuestionValidator: Use AttachmentValidator --- .../web/activity_pub/object_validators/question_validator.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index f7f3b1354..56f02777d 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do use Ecto.Schema alias Pleroma.Web.ActivityPub.Utils + alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator alias Pleroma.Web.ActivityPub.ObjectValidators.Types @@ -34,8 +35,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do # TODO: Write type field(:emoji, :map, default: %{}) field(:sensitive, :boolean, default: false) - # TODO: Write type - field(:attachment, {:array, :map}, default: []) + embeds_many(:attachment, AttachmentValidator) field(:replies_count, :integer, default: 0) field(:like_count, :integer, default: 0) field(:announcement_count, :integer, default: 0) @@ -99,7 +99,8 @@ def changeset(struct, data) do data = fix(data) struct - |> cast(data, __schema__(:fields) -- [:anyOf, :oneOf]) + |> cast(data, __schema__(:fields) -- [:anyOf, :oneOf, :attachment]) + |> cast_embed(:attachment) |> cast_embed(:anyOf) |> cast_embed(:oneOf) end -- cgit v1.2.3 From d713930ea7fe78f705f534febe4ceaf0a0216d24 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 20 Jun 2020 00:23:04 +0200 Subject: Fixup for EctoType module move --- .../activity_pub/object_validators/answer_validator.ex | 8 ++++---- .../object_validators/create_generic_validator.ex | 14 +++++++------- .../object_validators/question_validator.ex | 18 +++++++++--------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex index 8d4c92520..9861eec7f 100644 --- a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex @@ -5,8 +5,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do use Ecto.Schema + alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations - alias Pleroma.Web.ActivityPub.ObjectValidators.Types import Ecto.Changeset @@ -14,7 +14,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do @derive Jason.Encoder embedded_schema do - field(:id, Types.ObjectID, primary_key: true) + field(:id, ObjectValidators.ObjectID, primary_key: true) field(:to, {:array, :string}, default: []) field(:cc, {:array, :string}, default: []) @@ -25,8 +25,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do field(:type, :string) field(:name, :string) field(:inReplyTo, :string) - field(:attributedTo, Types.ObjectID) - field(:actor, Types.ObjectID) + field(:attributedTo, ObjectValidators.ObjectID) + field(:actor, ObjectValidators.ObjectID) end def cast_and_apply(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex index f467ccc7c..97e2def10 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -8,8 +8,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do use Ecto.Schema + alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Object - alias Pleroma.Web.ActivityPub.ObjectValidators.Types import Ecto.Changeset import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations @@ -17,13 +17,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do @primary_key false embedded_schema do - field(:id, Types.ObjectID, primary_key: true) - field(:actor, Types.ObjectID) + field(:id, ObjectValidators.ObjectID, primary_key: true) + field(:actor, ObjectValidators.ObjectID) field(:type, :string) - field(:to, Types.Recipients, default: []) - field(:cc, Types.Recipients, default: []) - field(:object, Types.ObjectID) - field(:expires_at, Types.DateTime) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:object, ObjectValidators.ObjectID) + field(:expires_at, ObjectValidators.DateTime) end def cast_data(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index 56f02777d..53cf35d40 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -5,11 +5,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do use Ecto.Schema - alias Pleroma.Web.ActivityPub.Utils + alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator - alias Pleroma.Web.ActivityPub.ObjectValidators.Types + alias Pleroma.Web.ActivityPub.Utils import Ecto.Changeset @@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do # Extends from NoteValidator embedded_schema do - field(:id, Types.ObjectID, primary_key: true) + field(:id, ObjectValidators.ObjectID, primary_key: true) field(:to, {:array, :string}, default: []) field(:cc, {:array, :string}, default: []) field(:bto, {:array, :string}, default: []) @@ -28,10 +28,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do field(:type, :string) field(:content, :string) field(:context, :string) - field(:actor, Types.ObjectID) - field(:attributedTo, Types.ObjectID) + field(:actor, ObjectValidators.ObjectID) + field(:attributedTo, ObjectValidators.ObjectID) field(:summary, :string) - field(:published, Types.DateTime) + field(:published, ObjectValidators.DateTime) # TODO: Write type field(:emoji, :map, default: %{}) field(:sensitive, :boolean, default: false) @@ -40,15 +40,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do field(:like_count, :integer, default: 0) field(:announcement_count, :integer, default: 0) field(:inReplyTo, :string) - field(:uri, Types.Uri) + field(:uri, ObjectValidators.Uri) # short identifier for PleromaFE to group statuses by context field(:context_id, :integer) field(:likes, {:array, :string}, default: []) field(:announcements, {:array, :string}, default: []) - field(:closed, Types.DateTime) - field(:voters, {:array, Types.ObjectID}, default: []) + field(:closed, ObjectValidators.DateTime) + field(:voters, {:array, ObjectValidators.ObjectID}, default: []) embeds_many(:anyOf, QuestionOptionsValidator) embeds_many(:oneOf, QuestionOptionsValidator) end -- cgit v1.2.3 From c19bdc811e526f83a2120c58f858044f4ff96e5f Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 23 Jun 2020 05:30:34 +0200 Subject: Fix attachments in polls --- .../object_validators/url_object_validator.ex | 2 +- lib/pleroma/web/activity_pub/transmogrifier.ex | 12 ++- test/fixtures/tesla_mock/poll_attachment.json | 99 ++++++++++++++++++++++ test/object/fetcher_test.exs | 7 ++ test/support/http_request_mock.ex | 8 ++ test/web/activity_pub/transmogrifier_test.exs | 27 ++++-- 6 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 test/fixtures/tesla_mock/poll_attachment.json diff --git a/lib/pleroma/web/activity_pub/object_validators/url_object_validator.ex b/lib/pleroma/web/activity_pub/object_validators/url_object_validator.ex index f64fac46d..881030f38 100644 --- a/lib/pleroma/web/activity_pub/object_validators/url_object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/url_object_validator.ex @@ -13,7 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UrlObjectValidator do embedded_schema do field(:type, :string) field(:href, ObjectValidators.Uri) - field(:mediaType, :string) + field(:mediaType, :string, default: "application/octet-stream") end def changeset(struct, data) do diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 26325d5de..0ad982720 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -240,13 +240,17 @@ def fix_attachments(%{"attachment" => attachment} = object) when is_list(attachm if href do attachment_url = - %{"href" => href} + %{ + "href" => href, + "type" => Map.get(url || %{}, "type", "Link") + } |> Maps.put_if_present("mediaType", media_type) - |> Maps.put_if_present("type", Map.get(url || %{}, "type")) - %{"url" => [attachment_url]} + %{ + "url" => [attachment_url], + "type" => data["type"] || "Document" + } |> Maps.put_if_present("mediaType", media_type) - |> Maps.put_if_present("type", data["type"]) |> Maps.put_if_present("name", data["name"]) else nil diff --git a/test/fixtures/tesla_mock/poll_attachment.json b/test/fixtures/tesla_mock/poll_attachment.json new file mode 100644 index 000000000..92e822dc8 --- /dev/null +++ b/test/fixtures/tesla_mock/poll_attachment.json @@ -0,0 +1,99 @@ +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://patch.cx/schemas/litepub-0.1.jsonld", + { + "@language": "und" + } + ], + "actor": "https://patch.cx/users/rin", + "anyOf": [], + "attachment": [ + { + "mediaType": "image/jpeg", + "name": "screenshot_mpv:Totoro@01:18:44.345.jpg", + "type": "Document", + "url": "https://shitposter.club/media/3bb4c4d402f8fdcc7f80963c3d7cf6f10f936897fd374922ade33199d2f86d87.jpg?name=screenshot_mpv%3ATotoro%4001%3A18%3A44.345.jpg" + } + ], + "attributedTo": "https://patch.cx/users/rin", + "cc": [ + "https://patch.cx/users/rin/followers" + ], + "closed": "2020-06-19T23:22:02.754678Z", + "content": "@rinpatch", + "closed": "2019-09-19T00:32:36.785333", + "content": "can you vote on this poll?", + "id": "https://patch.cx/objects/tesla_mock/poll_attachment", + "oneOf": [ + { + "name": "a", + "replies": { + "totalItems": 0, + "type": "Collection" + }, + "type": "Note" + }, + { + "name": "A", + "replies": { + "totalItems": 0, + "type": "Collection" + }, + "type": "Note" + }, + { + "name": "Aa", + "replies": { + "totalItems": 0, + "type": "Collection" + }, + "type": "Note" + }, + { + "name": "AA", + "replies": { + "totalItems": 0, + "type": "Collection" + }, + "type": "Note" + }, + { + "name": "AAa", + "replies": { + "totalItems": 1, + "type": "Collection" + }, + "type": "Note" + }, + { + "name": "AAA", + "replies": { + "totalItems": 3, + "type": "Collection" + }, + "type": "Note" + } + ], + "published": "2020-06-19T23:12:02.786113Z", + "sensitive": false, + "summary": "", + "tag": [ + { + "href": "https://mastodon.sdf.org/users/rinpatch", + "name": "@rinpatch@mastodon.sdf.org", + "type": "Mention" + } + ], + "to": [ + "https://www.w3.org/ns/activitystreams#Public", + "https://mastodon.sdf.org/users/rinpatch" + ], + "type": "Question", + "voters": [ + "https://shitposter.club/users/moonman", + "https://skippers-bin.com/users/7v1w1r8ce6", + "https://mastodon.sdf.org/users/rinpatch", + "https://mastodon.social/users/emelie" + ] +} diff --git a/test/object/fetcher_test.exs b/test/object/fetcher_test.exs index d9098ea1b..16cfa7f5c 100644 --- a/test/object/fetcher_test.exs +++ b/test/object/fetcher_test.exs @@ -177,6 +177,13 @@ test "handle HTTP 404 response" do "https://mastodon.example.org/users/userisgone404" ) end + + test "it can fetch pleroma polls with attachments" do + {:ok, object} = + Fetcher.fetch_object_from_id("https://patch.cx/objects/tesla_mock/poll_attachment") + + assert object + end end describe "pruning" do diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 19a202654..eeeba7880 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -82,6 +82,14 @@ def get("https://mastodon.sdf.org/users/rinpatch", _, _, _) do }} end + def get("https://patch.cx/objects/tesla_mock/poll_attachment", _, _, _) do + {:ok, + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/poll_attachment.json") + }} + end + def get( "https://mastodon.social/.well-known/webfinger?resource=https://mastodon.social/users/emelie", _, diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 272431135..7269e81bb 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -620,7 +620,8 @@ test "it remaps video URLs as attachments if necessary" do %{ "href" => "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", - "mediaType" => "video/mp4" + "mediaType" => "video/mp4", + "type" => "Link" } ] } @@ -639,7 +640,8 @@ test "it remaps video URLs as attachments if necessary" do %{ "href" => "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", - "mediaType" => "video/mp4" + "mediaType" => "video/mp4", + "type" => "Link" } ] } @@ -1459,8 +1461,13 @@ test "returns modified object when attachment is map" do "attachment" => [ %{ "mediaType" => "video/mp4", + "type" => "Document", "url" => [ - %{"href" => "https://peertube.moe/stat-480.mp4", "mediaType" => "video/mp4"} + %{ + "href" => "https://peertube.moe/stat-480.mp4", + "mediaType" => "video/mp4", + "type" => "Link" + } ] } ] @@ -1477,14 +1484,24 @@ test "returns modified object when attachment is list" do "attachment" => [ %{ "mediaType" => "video/mp4", + "type" => "Document", "url" => [ - %{"href" => "https://pe.er/stat-480.mp4", "mediaType" => "video/mp4"} + %{ + "href" => "https://pe.er/stat-480.mp4", + "mediaType" => "video/mp4", + "type" => "Link" + } ] }, %{ "mediaType" => "video/mp4", + "type" => "Document", "url" => [ - %{"href" => "https://pe.er/stat-480.mp4", "mediaType" => "video/mp4"} + %{ + "href" => "https://pe.er/stat-480.mp4", + "mediaType" => "video/mp4", + "type" => "Link" + } ] } ] -- cgit v1.2.3 From bfe2dafd398114240fcc2d3472799d6770904f6a Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 26 Jun 2020 00:07:43 +0200 Subject: {Answer,Question}Validator: Keep both actor and attributedTo for now but sync them --- lib/pleroma/web/activity_pub/builder.ex | 1 + .../activity_pub/object_validators/answer_validator.ex | 8 ++++++-- .../object_validators/common_validations.ex | 18 ++++++++++++++++++ .../object_validators/create_generic_validator.ex | 6 +++--- .../object_validators/question_validator.ex | 6 +++++- lib/pleroma/web/activity_pub/transmogrifier.ex | 7 ++++++- 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index e97381954..49ce5a938 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -120,6 +120,7 @@ def answer(user, object, name) do %{ "type" => "Answer", "actor" => user.ap_id, + "attributedTo" => user.ap_id, "cc" => [object.data["actor"]], "to" => [], "name" => name, diff --git a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex index 9861eec7f..ebddd5038 100644 --- a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex @@ -26,6 +26,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do field(:name, :string) field(:inReplyTo, :string) field(:attributedTo, ObjectValidators.ObjectID) + + # TODO: Remove actor on objects field(:actor, ObjectValidators.ObjectID) end @@ -54,8 +56,10 @@ def changeset(struct, data) do def validate_data(data_cng) do data_cng |> validate_inclusion(:type, ["Answer"]) - |> validate_required([:id, :inReplyTo, :name]) + |> validate_required([:id, :inReplyTo, :name, :attributedTo, :actor]) |> CommonValidations.validate_any_presence([:cc, :to]) - |> CommonValidations.validate_actor_presence() + |> CommonValidations.validate_fields_match([:actor, :attributedTo]) + |> CommonValidations.validate_actor_is_active() + |> CommonValidations.validate_host_match() end end diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index 140555a45..e981dacaa 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -115,4 +115,22 @@ def validate_host_match(cng, fields \\ [:id, :actor]) do end) end end + + def validate_fields_match(cng, fields) do + unique_fields = + fields + |> Enum.map(fn field -> get_field(cng, field) end) + |> Enum.uniq() + |> Enum.count() + + if unique_fields == 1 do + cng + else + fields + |> Enum.reduce(cng, fn field, cng -> + cng + |> add_error(field, "Fields #{inspect(fields)} aren't matching") + end) + end + end end diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex index 97e2def10..54ea14f89 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -87,14 +87,14 @@ def validate_object_nonexistence(cng) do end def validate_actors_match(cng, meta) do - object_actor = meta[:object_data]["actor"] + attributed_to = meta[:object_data]["attributedTo"] || meta[:object_data]["actor"] cng |> validate_change(:actor, fn :actor, actor -> - if actor == object_actor do + if actor == attributed_to do [] else - [{:actor, "Actor doesn't match with object actor"}] + [{:actor, "Actor doesn't match with object attributedTo"}] end end) end diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index 53cf35d40..466b3e6c2 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -28,7 +28,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do field(:type, :string) field(:content, :string) field(:context, :string) + + # TODO: Remove actor on objects field(:actor, ObjectValidators.ObjectID) + field(:attributedTo, ObjectValidators.ObjectID) field(:summary, :string) field(:published, ObjectValidators.DateTime) @@ -108,8 +111,9 @@ def changeset(struct, data) do def validate_data(data_cng) do data_cng |> validate_inclusion(:type, ["Question"]) - |> validate_required([:id, :actor, :type, :content, :context]) + |> validate_required([:id, :actor, :attributedTo, :type, :content, :context]) |> CommonValidations.validate_any_presence([:cc, :to]) + |> CommonValidations.validate_fields_match([:actor, :attributedTo]) |> CommonValidations.validate_actor_is_active() |> CommonValidations.validate_any_presence([:oneOf, :anyOf]) |> CommonValidations.validate_host_match() diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 0ad982720..6ab8a52c1 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -157,7 +157,12 @@ def fix_addressing(object) do end def fix_actor(%{"attributedTo" => actor} = object) do - Map.put(object, "actor", Containment.get_actor(%{"actor" => actor})) + actor = Containment.get_actor(%{"actor" => actor}) + + # TODO: Remove actor field for Objects + object + |> Map.put("actor", actor) + |> Map.put("attributedTo", actor) end def fix_in_reply_to(object, options \\ []) -- cgit v1.2.3 From 922ca232988b90b7a4fb5918bb76c383c90fd770 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 2 Jul 2020 05:47:18 +0200 Subject: Question: Add tests on HTML tags in options Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/1362 --- .../transmogrifier/question_handling_test.exs | 35 ++++++++++++++++++++++ test/web/mastodon_api/views/poll_view_test.exs | 29 ++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs index b7b9a1a7b..fba8106b5 100644 --- a/test/web/activity_pub/transmogrifier/question_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/question_handling_test.exs @@ -55,6 +55,41 @@ test "Mastodon Question activity" do ]) end + test "Mastodon Question activity with HTML tags in plaintext" do + options = [ + %{ + "type" => "Note", + "name" => "", + "replies" => %{"totalItems" => 0, "type" => "Collection"} + }, + %{ + "type" => "Note", + "name" => "", + "replies" => %{"totalItems" => 0, "type" => "Collection"} + }, + %{ + "type" => "Note", + "name" => "", + "replies" => %{"totalItems" => 1, "type" => "Collection"} + }, + %{ + "type" => "Note", + "name" => "", + "replies" => %{"totalItems" => 1, "type" => "Collection"} + } + ] + + data = + File.read!("test/fixtures/mastodon-question-activity.json") + |> Poison.decode!() + |> Kernel.put_in(["object", "oneOf"], options) + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + object = Object.normalize(activity, false) + + assert Enum.sort(object.data["oneOf"]) == Enum.sort(options) + end + test "returns an error if received a second time" do data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() diff --git a/test/web/mastodon_api/views/poll_view_test.exs b/test/web/mastodon_api/views/poll_view_test.exs index 76672f36c..b7e2f17ef 100644 --- a/test/web/mastodon_api/views/poll_view_test.exs +++ b/test/web/mastodon_api/views/poll_view_test.exs @@ -135,4 +135,33 @@ test "does not crash on polls with no end date" do assert result[:expires_at] == nil assert result[:expired] == false end + + test "doesn't strips HTML tags" do + user = insert(:user) + + {:ok, activity} = + CommonAPI.post(user, %{ + status: "What's with the smug face?", + poll: %{ + options: [ + "", + "", + "", + "" + ], + expires_in: 20 + } + }) + + object = Object.normalize(activity) + + assert %{ + options: [ + %{title: "", votes_count: 0}, + %{title: "", votes_count: 0}, + %{title: "", votes_count: 0}, + %{title: "", votes_count: 0} + ] + } = PollView.render("show.json", %{object: object}) + end end -- cgit v1.2.3 From e4beff90f5670876184b2593c1b4a49f2339d048 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 2 Jul 2020 05:45:19 +0200 Subject: Create Question: Add context field to create --- lib/pleroma/web/activity_pub/builder.ex | 10 +++++++++- .../object_validators/create_generic_validator.ex | 17 +++++++++++++++++ lib/pleroma/web/activity_pub/transmogrifier.ex | 2 ++ .../transmogrifier/question_handling_test.exs | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index 49ce5a938..1b4c421b8 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -80,6 +80,13 @@ def delete(actor, object_id) do end def create(actor, object, recipients) do + context = + if is_map(object) do + object["context"] + else + nil + end + {:ok, %{ "id" => Utils.generate_activity_id(), @@ -88,7 +95,8 @@ def create(actor, object, recipients) do "object" => object, "type" => "Create", "published" => DateTime.utc_now() |> DateTime.to_iso8601() - }, []} + } + |> Pleroma.Maps.put_if_present("context", context), []} end def chat_message(actor, recipient, content, opts \\ []) do diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex index 54ea14f89..ff889330e 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -24,6 +24,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do field(:cc, ObjectValidators.Recipients, default: []) field(:object, ObjectValidators.ObjectID) field(:expires_at, ObjectValidators.DateTime) + + # Should be moved to object, done for CommonAPI.Utils.make_context + field(:context, :string) end def cast_data(data) do @@ -55,6 +58,7 @@ def validate_data(cng, meta \\ []) do |> validate_actor_is_active() |> validate_any_presence([:to, :cc]) |> validate_actors_match(meta) + |> validate_context_match(meta) |> validate_object_nonexistence() |> validate_object_containment() end @@ -98,4 +102,17 @@ def validate_actors_match(cng, meta) do end end) end + + def validate_context_match(cng, %{object_data: %{"context" => object_context}}) do + cng + |> validate_change(:context, fn :context, context -> + if context == object_context do + [] + else + [{:context, "context field not matching between Create and object (#{object_context})"}] + end + end) + end + + def validate_context_match(cng, _), do: cng end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 6ab8a52c1..edabe1130 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -643,6 +643,8 @@ def handle_incoming( |> Map.put("object", fix_object(object)) |> fix_addressing() + data = Map.put_new(data, "context", data["object"]["context"]) + with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do {:ok, activity} diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs index fba8106b5..12516c4ab 100644 --- a/test/web/activity_pub/transmogrifier/question_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/question_handling_test.exs @@ -8,6 +8,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do alias Pleroma.Activity alias Pleroma.Object alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory setup_all do Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -23,6 +26,8 @@ test "Mastodon Question activity" do assert object.data["closed"] == "2019-05-11T09:03:36Z" + assert object.data["context"] == activity.data["context"] + assert object.data["context"] == "tag:mastodon.sdf.org,2019-05-10:objectId=15095122:objectType=Conversation" @@ -53,6 +58,15 @@ test "Mastodon Question activity" do "type" => "Note" } ]) + + user = insert(:user) + + {:ok, reply_activity} = CommonAPI.post(user, %{status: "hewwo", in_reply_to_id: activity.id}) + + reply_object = Object.normalize(reply_activity, 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 -- cgit v1.2.3 From 1489c2ae5fdb01ee2f1a40c40582842868cac888 Mon Sep 17 00:00:00 2001 From: Angelina Filippova Date: Tue, 4 Aug 2020 01:45:18 +0300 Subject: Fix :args settings description in Upload.Filter.Mogrify group --- config/description.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/description.exs b/config/description.exs index ae2f6d23f..00bab20eb 100644 --- a/config/description.exs +++ b/config/description.exs @@ -194,7 +194,7 @@ type: [:string, {:list, :string}, {:list, :tuple}], description: "List of actions for the mogrify command. It's possible to add self-written settings as string. " <> - "For example `[\"auto-orient\", \"strip\", {\"resize\", \"3840x1080>\"}]` string will be parsed into list of the settings.", + "For example `auto-orient, strip, {\"resize\", \"3840x1080>\"}` value will be parsed into valid list of the settings.", suggestions: [ "strip", "auto-orient", -- cgit v1.2.3 From ae95472dccbf708259f49730149a1599e9ac0e9c Mon Sep 17 00:00:00 2001 From: Angelina Filippova Date: Tue, 4 Aug 2020 02:04:29 +0300 Subject: Update :welcome settings description --- config/description.exs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/config/description.exs b/config/description.exs index 00bab20eb..a947c8f3f 100644 --- a/config/description.exs +++ b/config/description.exs @@ -964,25 +964,26 @@ ] }, %{ - group: :welcome, + group: :pleroma, + key: :welcome, type: :group, description: "Welcome messages settings", children: [ %{ - group: :direct_message, - type: :group, + key: :direct_message, + type: :keyword, descpiption: "Direct message settings", children: [ %{ key: :enabled, type: :boolean, - description: "Enables sends direct message for new user after registration" + description: "Enables sending a direct message to newly registered users" }, %{ key: :message, type: :string, description: - "A message that will be sent to a newly registered users as a direct message", + "A message that will be sent to newly registered users", suggestions: [ "Hi, @username! Welcome on board!" ] @@ -990,7 +991,7 @@ %{ key: :sender_nickname, type: :string, - description: "The nickname of the local user that sends the welcome message", + description: "The nickname of the local user that sends a welcome message", suggestions: [ "lain" ] @@ -998,20 +999,20 @@ ] }, %{ - group: :chat_message, - type: :group, + key: :chat_message, + type: :keyword, descpiption: "Chat message settings", children: [ %{ key: :enabled, type: :boolean, - description: "Enables sends chat message for new user after registration" + description: "Enables sending a chat message to newly registered users" }, %{ key: :message, type: :string, description: - "A message that will be sent to a newly registered users as a chat message", + "A message that will be sent to newly registered users as a chat message", suggestions: [ "Hello, welcome on board!" ] @@ -1019,7 +1020,7 @@ %{ key: :sender_nickname, type: :string, - description: "The nickname of the local user that sends the welcome message", + description: "The nickname of the local user that sends a welcome chat message", suggestions: [ "lain" ] @@ -1027,20 +1028,20 @@ ] }, %{ - group: :email, - type: :group, + key: :email, + type: :keyword, descpiption: "Email message settings", children: [ %{ key: :enabled, type: :boolean, - description: "Enables sends direct message for new user after registration" + description: "Enables sending an email to newly registered users" }, %{ key: :sender, type: [:string, :tuple], description: - "The email address or tuple with `{nickname, email}` that will use as sender to the welcome email.", + "Email address and/or nickname that will be used to send the welcome email.", suggestions: [ {"Pleroma App", "welcome@pleroma.app"} ] @@ -1049,21 +1050,21 @@ key: :subject, type: :string, description: - "The subject of welcome email. Can be use EEX template with `user` and `instance_name` variables.", + "Subject of the welcome email. EEX template with user and instance_name variables can be used.", suggestions: ["Welcome to <%= instance_name%>"] }, %{ key: :html, type: :string, description: - "The html content of welcome email. Can be use EEX template with `user` and `instance_name` variables.", + "HTML content of the welcome email. EEX template with user and instance_name variables can be used.", suggestions: ["

Hello <%= user.name%>. Welcome to <%= instance_name%>

"] }, %{ key: :text, type: :string, description: - "The text content of welcome email. Can be use EEX template with `user` and `instance_name` variables.", + "Text content of the welcome email. EEX template with user and instance_name variables can be used.", suggestions: ["Hello <%= user.name%>. \n Welcome to <%= instance_name%>\n"] } ] -- cgit v1.2.3 From 63b1ca6a0766772edb2affc65c42e2dad96c0de4 Mon Sep 17 00:00:00 2001 From: Angelina Filippova Date: Tue, 4 Aug 2020 02:21:25 +0300 Subject: Add label to :restrict_unauthenticated setting, fix typos --- config/description.exs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/config/description.exs b/config/description.exs index a947c8f3f..9c8e330bf 100644 --- a/config/description.exs +++ b/config/description.exs @@ -3293,13 +3293,13 @@ group: :pleroma, key: :connections_pool, type: :group, - description: "Advanced settings for `gun` connections pool", + description: "Advanced settings for `Gun` connections pool", children: [ %{ key: :connection_acquisition_wait, type: :integer, description: - "Timeout to acquire a connection from pool.The total max time is this value multiplied by the number of retries. Default: 250ms.", + "Timeout to acquire a connection from pool. The total max time is this value multiplied by the number of retries. Default: 250ms.", suggestions: [250] }, %{ @@ -3334,7 +3334,7 @@ group: :pleroma, key: :pools, type: :group, - description: "Advanced settings for `gun` workers pools", + description: "Advanced settings for `Gun` workers pools", children: Enum.map([:federation, :media, :upload, :default], fn pool_name -> %{ @@ -3363,7 +3363,7 @@ group: :pleroma, key: :hackney_pools, type: :group, - description: "Advanced settings for `hackney` connections pools", + description: "Advanced settings for `Hackney` connections pools", children: [ %{ key: :federation, @@ -3427,6 +3427,7 @@ %{ group: :pleroma, key: :restrict_unauthenticated, + label: "Restrict Unauthenticated", type: :group, description: "Disallow viewing timelines, user profiles and statuses for unauthenticated users.", -- cgit v1.2.3 From 8bb54415470852f95967bc75fb8917db78eb0fbd Mon Sep 17 00:00:00 2001 From: Angelina Filippova Date: Tue, 4 Aug 2020 15:10:44 +0300 Subject: Update descriptions in :frontends group --- config/description.exs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/config/description.exs b/config/description.exs index 9c8e330bf..7da01b175 100644 --- a/config/description.exs +++ b/config/description.exs @@ -3550,13 +3550,15 @@ children: [ %{ key: "name", + label: "Name", type: :string, - description: "Name of the installed primary frontend" + description: "Name of the installed primary frontend. Valid config must include both `Name` and `Reference` values." }, %{ key: "ref", + label: "Reference", type: :string, - description: "reference of the installed primary frontend to be used" + description: "Reference of the installed primary frontend to be used. Valid config must include both `Name` and `Reference` values." } ] } -- cgit v1.2.3 From 0f088d8ce35150d7baa0591a25c831fce0181239 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 4 Aug 2020 14:23:35 +0200 Subject: question_validator: Allow content to be an empty-string (blank) --- .../web/activity_pub/object_validators/question_validator.ex | 2 +- test/web/activity_pub/transmogrifier/question_handling_test.exs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index 466b3e6c2..d248c6aec 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -111,7 +111,7 @@ def changeset(struct, data) do def validate_data(data_cng) do data_cng |> validate_inclusion(:type, ["Question"]) - |> validate_required([:id, :actor, :attributedTo, :type, :content, :context]) + |> validate_required([:id, :actor, :attributedTo, :type, :context]) |> CommonValidations.validate_any_presence([:cc, :to]) |> CommonValidations.validate_fields_match([:actor, :attributedTo]) |> CommonValidations.validate_actor_is_active() diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs index 12516c4ab..9fb965d7f 100644 --- a/test/web/activity_pub/transmogrifier/question_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/question_handling_test.exs @@ -111,4 +111,13 @@ test "returns an error if received a second time" do assert {:error, {:validate_object, {:error, _}}} = Transmogrifier.handle_incoming(data) end + + test "accepts a Question with no content" do + data = + File.read!("test/fixtures/mastodon-question-activity.json") + |> Poison.decode!() + |> Kernel.put_in(["object", "content"], "") + + assert {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data) + end end -- cgit v1.2.3 From 00c4c6a382d9965ea42236232094c4352c9ebae1 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 12:24:34 +0200 Subject: CommonValidations: Remove superfluous function The `is_active` functionality was integrated into the presence checker. --- .../web/activity_pub/object_validators/answer_validator.ex | 2 +- .../activity_pub/object_validators/common_validations.ex | 13 ------------- .../object_validators/create_generic_validator.ex | 2 +- .../activity_pub/object_validators/question_validator.ex | 2 +- 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex index ebddd5038..323367642 100644 --- a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex @@ -59,7 +59,7 @@ def validate_data(data_cng) do |> validate_required([:id, :inReplyTo, :name, :attributedTo, :actor]) |> CommonValidations.validate_any_presence([:cc, :to]) |> CommonValidations.validate_fields_match([:actor, :attributedTo]) - |> CommonValidations.validate_actor_is_active() + |> CommonValidations.validate_actor_presence() |> CommonValidations.validate_host_match() end end diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index 57d4456aa..67352f801 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -47,19 +47,6 @@ def validate_actor_presence(cng, options \\ []) do end) end - def validate_actor_is_active(cng, options \\ []) do - field_name = Keyword.get(options, :field_name, :actor) - - cng - |> validate_change(field_name, fn field_name, actor -> - if %User{deactivated: false} = User.get_cached_by_ap_id(actor) do - [] - else - [{field_name, "can't find user (or deactivated)"}] - end - end) - end - def validate_object_presence(cng, options \\ []) do field_name = Keyword.get(options, :field_name, :object) allowed_types = Keyword.get(options, :allowed_types, false) diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex index ff889330e..2569df7f6 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -55,7 +55,7 @@ def validate_data(cng, meta \\ []) do cng |> validate_required([:actor, :type, :object]) |> validate_inclusion(:type, ["Create"]) - |> validate_actor_is_active() + |> validate_actor_presence() |> validate_any_presence([:to, :cc]) |> validate_actors_match(meta) |> validate_context_match(meta) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index d248c6aec..694cb6730 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -114,7 +114,7 @@ def validate_data(data_cng) do |> validate_required([:id, :actor, :attributedTo, :type, :context]) |> CommonValidations.validate_any_presence([:cc, :to]) |> CommonValidations.validate_fields_match([:actor, :attributedTo]) - |> CommonValidations.validate_actor_is_active() + |> CommonValidations.validate_actor_presence() |> CommonValidations.validate_any_presence([:oneOf, :anyOf]) |> CommonValidations.validate_host_match() end -- cgit v1.2.3 From 70522989d9d1119e5b3d86151f633f849d92f307 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 11:14:58 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- lib/pleroma/web/mastodon_api/views/poll_view.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex index ce595ae8a..1bfc99259 100644 --- a/lib/pleroma/web/mastodon_api/views/poll_view.ex +++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex @@ -28,10 +28,10 @@ def render("show.json", %{object: object, multiple: multiple, options: options} def render("show.json", %{object: object} = params) do case object.data do - %{"anyOf" => options} when is_list(options) and options != [] -> + %{"anyOf" => [ _ | _] = options} -> render(__MODULE__, "show.json", Map.merge(params, %{multiple: true, options: options})) - %{"oneOf" => options} when is_list(options) and options != [] -> + %{"oneOf" => [ _ | _] = options} -> render(__MODULE__, "show.json", Map.merge(params, %{multiple: false, options: options})) _ -> -- cgit v1.2.3 From b5f0cef156c1d1dd0376a791d8b4be48591f2c27 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 11:33:21 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- lib/pleroma/object.ex | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index 4dd929cfd..b3e654857 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -255,9 +255,7 @@ def increase_replies_count(ap_id) do end end - defp poll_is_multiple?(%Object{data: %{"anyOf" => anyOf}}) do - !Enum.empty?(anyOf) - end + defp poll_is_multiple?(%Object{data: %{"anyOf" => [_ | _]}}), do: true defp poll_is_multiple?(_), do: false -- cgit v1.2.3 From f889400d05e86d8d9509577946a0ab3a55b3eabb Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 14:51:33 +0200 Subject: Questions: Move fixes to validators. --- .../object_validators/create_generic_validator.ex | 19 +++++++++++++++++-- .../object_validators/question_validator.ex | 10 ++++++++-- lib/pleroma/web/activity_pub/transmogrifier.ex | 11 ++--------- lib/pleroma/web/mastodon_api/views/poll_view.ex | 4 ++-- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex index 2569df7f6..60868eae0 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -29,7 +29,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do field(:context, :string) end - def cast_data(data) do + def cast_data(data, meta \\ []) do + data = fix(data, meta) + %__MODULE__{} |> changeset(data) end @@ -42,7 +44,7 @@ def cast_and_apply(data) do def cast_and_validate(data, meta \\ []) do data - |> cast_data + |> cast_data(meta) |> validate_data(meta) end @@ -51,6 +53,19 @@ def changeset(struct, data) do |> cast(data, __schema__(:fields)) end + defp fix_context(data, meta) do + if object = meta[:object_data] do + Map.put_new(data, "context", object["context"]) + else + data + end + end + + defp fix(data, meta) do + data + |> fix_context(meta) + end + def validate_data(cng, meta \\ []) do cng |> validate_required([:actor, :type, :object]) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index 694cb6730..f47acf606 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -83,17 +83,23 @@ defp fix_closed(data) do # based on Pleroma.Web.ActivityPub.Utils.lazy_put_objects_defaults defp fix_defaults(data) do - %{data: %{"id" => context}, id: context_id} = Utils.create_context(data["context"]) + %{data: %{"id" => context}, id: context_id} = + Utils.create_context(data["context"] || data["conversation"]) data - |> Map.put_new_lazy("id", &Utils.generate_object_id/0) |> Map.put_new_lazy("published", &Utils.make_date/0) |> Map.put_new("context", context) |> Map.put_new("context_id", context_id) end + defp fix_attribution(data) do + data + |> Map.put_new("actor", data["attributedTo"]) + end + defp fix(data) do data + |> fix_attribution() |> fix_closed() |> fix_defaults() end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index f85a26679..7381d4476 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -634,17 +634,10 @@ def handle_incoming( end def handle_incoming( - %{"type" => "Create", "object" => %{"type" => objtype} = object} = data, + %{"type" => "Create", "object" => %{"type" => objtype}} = data, _options ) - when objtype in ["Question", "Answer"] do - data = - data - |> Map.put("object", fix_object(object)) - |> fix_addressing() - - data = Map.put_new(data, "context", data["object"]["context"]) - + when objtype in ["Question", "Answer", "ChatMessage"] do with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do {:ok, activity} diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex index 1bfc99259..1208dc9a0 100644 --- a/lib/pleroma/web/mastodon_api/views/poll_view.ex +++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex @@ -28,10 +28,10 @@ def render("show.json", %{object: object, multiple: multiple, options: options} def render("show.json", %{object: object} = params) do case object.data do - %{"anyOf" => [ _ | _] = options} -> + %{"anyOf" => [_ | _] = options} -> render(__MODULE__, "show.json", Map.merge(params, %{multiple: true, options: options})) - %{"oneOf" => [ _ | _] = options} -> + %{"oneOf" => [_ | _] = options} -> render(__MODULE__, "show.json", Map.merge(params, %{multiple: false, options: options})) _ -> -- cgit v1.2.3 From f7146583e5f1c2d0e8a198db00dfafced79d0706 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 5 Aug 2020 08:15:57 -0500 Subject: Remove LDAP mail attribute as a requirement for registering an account --- lib/pleroma/web/auth/ldap_authenticator.ex | 34 ++++++++++++------------------ test/web/oauth/ldap_authorization_test.exs | 4 +--- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex index f63a66c03..f320ec746 100644 --- a/lib/pleroma/web/auth/ldap_authenticator.ex +++ b/lib/pleroma/web/auth/ldap_authenticator.ex @@ -105,29 +105,21 @@ defp register_user(connection, base, uid, name, password) do {:base, to_charlist(base)}, {:filter, :eldap.equalityMatch(to_charlist(uid), to_charlist(name))}, {:scope, :eldap.wholeSubtree()}, - {:attributes, ['mail', 'email']}, {:timeout, @search_timeout} ]) do - {:ok, {:eldap_search_result, [{:eldap_entry, _, attributes}], _}} -> - with {_, [mail]} <- List.keyfind(attributes, 'mail', 0) do - params = %{ - email: :erlang.list_to_binary(mail), - name: name, - nickname: name, - password: password, - password_confirmation: password - } - - changeset = User.register_changeset(%User{}, params) - - case User.register(changeset) do - {:ok, user} -> user - error -> error - end - else - _ -> - Logger.error("Could not find LDAP attribute mail: #{inspect(attributes)}") - {:error, :ldap_registration_missing_attributes} + {:ok, {:eldap_search_result, [{:eldap_entry, _, _}], _}} -> + params = %{ + name: name, + nickname: name, + password: password, + password_confirmation: password + } + + changeset = User.register_changeset(%User{}, params) + + case User.register(changeset) do + {:ok, user} -> user + error -> error end error -> diff --git a/test/web/oauth/ldap_authorization_test.exs b/test/web/oauth/ldap_authorization_test.exs index 011642c08..76ae461c3 100644 --- a/test/web/oauth/ldap_authorization_test.exs +++ b/test/web/oauth/ldap_authorization_test.exs @@ -72,9 +72,7 @@ test "creates a new user after successful LDAP authorization" do equalityMatch: fn _type, _value -> :ok end, wholeSubtree: fn -> :ok end, search: fn _connection, _options -> - {:ok, - {:eldap_search_result, [{:eldap_entry, '', [{'mail', [to_charlist(user.email)]}]}], - []}} + {:ok, {:eldap_search_result, [{:eldap_entry, '', []}], []}} end, close: fn _connection -> send(self(), :close_connection) -- cgit v1.2.3 From 0f9aecbca49c828158d2cb549659a68fb21697df Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 5 Aug 2020 08:18:16 -0500 Subject: Remove fallback to local database when LDAP is unavailable. In many environments this will not work as the LDAP password and the copy stored in Pleroma will stay synchronized. --- lib/pleroma/web/auth/ldap_authenticator.ex | 4 --- test/web/oauth/ldap_authorization_test.exs | 45 ------------------------------ 2 files changed, 49 deletions(-) diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex index f320ec746..ec47f6f91 100644 --- a/lib/pleroma/web/auth/ldap_authenticator.ex +++ b/lib/pleroma/web/auth/ldap_authenticator.ex @@ -28,10 +28,6 @@ def get_user(%Plug.Conn{} = conn) do %User{} = user <- ldap_user(name, password) do {:ok, user} else - {:error, {:ldap_connection_error, _}} -> - # When LDAP is unavailable, try default authenticator - @base.get_user(conn) - {:ldap, _} -> @base.get_user(conn) diff --git a/test/web/oauth/ldap_authorization_test.exs b/test/web/oauth/ldap_authorization_test.exs index 76ae461c3..63b1c0eb8 100644 --- a/test/web/oauth/ldap_authorization_test.exs +++ b/test/web/oauth/ldap_authorization_test.exs @@ -7,7 +7,6 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do alias Pleroma.Repo alias Pleroma.Web.OAuth.Token import Pleroma.Factory - import ExUnit.CaptureLog import Mock @skip if !Code.ensure_loaded?(:eldap), do: :skip @@ -99,50 +98,6 @@ test "creates a new user after successful LDAP authorization" do end end - @tag @skip - test "falls back to the default authorization when LDAP is unavailable" do - password = "testpassword" - user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password)) - app = insert(:oauth_app, scopes: ["read", "write"]) - - host = Pleroma.Config.get([:ldap, :host]) |> to_charlist - port = Pleroma.Config.get([:ldap, :port]) - - with_mocks [ - {:eldap, [], - [ - open: fn [^host], [{:port, ^port}, {:ssl, false} | _] -> {:error, 'connect failed'} end, - simple_bind: fn _connection, _dn, ^password -> :ok end, - close: fn _connection -> - send(self(), :close_connection) - :ok - end - ]} - ] do - log = - capture_log(fn -> - conn = - build_conn() - |> post("/oauth/token", %{ - "grant_type" => "password", - "username" => user.nickname, - "password" => password, - "client_id" => app.client_id, - "client_secret" => app.client_secret - }) - - assert %{"access_token" => token} = json_response(conn, 200) - - token = Repo.get_by(Token, token: token) - - assert token.user_id == user.id - end) - - assert log =~ "Could not open LDAP connection: 'connect failed'" - refute_received :close_connection - end - end - @tag @skip test "disallow authorization for wrong LDAP credentials" do password = "testpassword" -- cgit v1.2.3 From 5221879c358a7859d54013597c9ed9ccbb494155 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 15:40:32 +0200 Subject: Fix linting. --- lib/pleroma/object.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index b3e654857..052ad413b 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -255,7 +255,7 @@ def increase_replies_count(ap_id) do end end - defp poll_is_multiple?(%Object{data: %{"anyOf" => [_ | _]}}), do: true + defp poll_is_multiple?(%Object{data: %{"anyOf" => [_ | _]}}), do: true defp poll_is_multiple?(_), do: false -- cgit v1.2.3 From d5e4d8a6f3f7b577183809a4b371609aa29fa968 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 5 Aug 2020 09:41:17 -0500 Subject: Define default authenticator in the config --- config/config.exs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/config.exs b/config/config.exs index 933a899ab..257b2e061 100644 --- a/config/config.exs +++ b/config/config.exs @@ -737,6 +737,8 @@ config :pleroma, :instances_favicons, enabled: false +config :pleroma, Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.PleromaAuthenticator + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" -- cgit v1.2.3 From 2192d1e4920e2c6deffe9a205cc2ade27d4dc0b1 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 5 Aug 2020 10:07:31 -0500 Subject: Permit LDAP users to register without capturing their password hash We don't need it, and local auth fallback has been removed. --- lib/pleroma/user.ex | 19 +++++++++++++++++++ lib/pleroma/web/auth/ldap_authenticator.ex | 7 +++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 09e606b37..df9f34baa 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -638,6 +638,25 @@ def force_password_reset_async(user) do @spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} def force_password_reset(user), do: update_password_reset_pending(user, true) + # Used to auto-register LDAP accounts which don't have a password hash + def register_changeset(struct, params = %{password: password}) + when is_nil(password) do + params = Map.put_new(params, :accepts_chat_messages, true) + + struct + |> cast(params, [ + :name, + :nickname, + :accepts_chat_messages + ]) + |> unique_constraint(:nickname) + |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames])) + |> validate_format(:nickname, local_nickname_regex()) + |> put_ap_id() + |> unique_constraint(:ap_id) + |> put_following_and_follower_address() + end + def register_changeset(struct, params \\ %{}, opts \\ []) do bio_limit = Config.get([:instance, :user_bio_length], 5000) name_limit = Config.get([:instance, :user_name_length], 100) diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex index ec47f6f91..f667da68b 100644 --- a/lib/pleroma/web/auth/ldap_authenticator.ex +++ b/lib/pleroma/web/auth/ldap_authenticator.ex @@ -88,7 +88,7 @@ defp bind_user(connection, ldap, name, password) do user _ -> - register_user(connection, base, uid, name, password) + register_user(connection, base, uid, name) end error -> @@ -96,7 +96,7 @@ defp bind_user(connection, ldap, name, password) do end end - defp register_user(connection, base, uid, name, password) do + defp register_user(connection, base, uid, name) do case :eldap.search(connection, [ {:base, to_charlist(base)}, {:filter, :eldap.equalityMatch(to_charlist(uid), to_charlist(name))}, @@ -107,8 +107,7 @@ defp register_user(connection, base, uid, name, password) do params = %{ name: name, nickname: name, - password: password, - password_confirmation: password + password: nil } changeset = User.register_changeset(%User{}, params) -- cgit v1.2.3 From 2173945f9012ec0db82a73fc7ed9423899dfd28f Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 17:26:03 +0200 Subject: MailerTest: Give it some time. --- test/emails/mailer_test.exs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/emails/mailer_test.exs b/test/emails/mailer_test.exs index e6e34cba8..3da45056b 100644 --- a/test/emails/mailer_test.exs +++ b/test/emails/mailer_test.exs @@ -19,6 +19,7 @@ defmodule Pleroma.Emails.MailerTest do test "not send email when mailer is disabled" do Pleroma.Config.put([Pleroma.Emails.Mailer, :enabled], false) Mailer.deliver(@email) + :timer.sleep(100) refute_email_sent( from: {"Pleroma", "noreply@example.com"}, @@ -30,6 +31,7 @@ test "not send email when mailer is disabled" do test "send email" do Mailer.deliver(@email) + :timer.sleep(100) assert_email_sent( from: {"Pleroma", "noreply@example.com"}, @@ -41,6 +43,7 @@ test "send email" do test "perform" do Mailer.perform(:deliver_async, @email, []) + :timer.sleep(100) assert_email_sent( from: {"Pleroma", "noreply@example.com"}, -- cgit v1.2.3 From 9c96fc052a89789b398794761741783eaa86d6a1 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 17:26:53 +0200 Subject: CommonValidations: Extract modification right checker --- .../object_validators/common_validations.ex | 27 +++++++++++++++++++++ .../object_validators/delete_validator.ex | 28 +--------------------- .../object_validators/delete_validation_test.exs | 2 +- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index 67352f801..e4c5d9619 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -125,4 +125,31 @@ def validate_fields_match(cng, fields) do end) end end + + def same_domain?(cng, field_one \\ :actor, field_two \\ :object) do + actor_uri = + cng + |> get_field(field_one) + |> URI.parse() + + object_uri = + cng + |> get_field(field_two) + |> URI.parse() + + object_uri.host == actor_uri.host + end + + # This figures out if a user is able to create, delete or modify something + # based on the domain and superuser status + def validate_modification_rights(cng) do + actor = User.get_cached_by_ap_id(get_field(cng, :actor)) + + if User.superuser?(actor) || same_domain?(cng) do + cng + else + cng + |> add_error(:actor, "is not allowed to modify object") + end + end end diff --git a/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex b/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex index 93a7b0e0b..2634e8d4d 100644 --- a/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex @@ -7,7 +7,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator do alias Pleroma.Activity alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.User import Ecto.Changeset import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations @@ -59,7 +58,7 @@ def validate_data(cng) do |> validate_required([:id, :type, :actor, :to, :cc, :object]) |> validate_inclusion(:type, ["Delete"]) |> validate_actor_presence() - |> validate_deletion_rights() + |> validate_modification_rights() |> validate_object_or_user_presence(allowed_types: @deletable_types) |> add_deleted_activity_id() end @@ -68,31 +67,6 @@ def do_not_federate?(cng) do !same_domain?(cng) end - defp same_domain?(cng) do - actor_uri = - cng - |> get_field(:actor) - |> URI.parse() - - object_uri = - cng - |> get_field(:object) - |> URI.parse() - - object_uri.host == actor_uri.host - end - - def validate_deletion_rights(cng) do - actor = User.get_cached_by_ap_id(get_field(cng, :actor)) - - if User.superuser?(actor) || same_domain?(cng) do - cng - else - cng - |> add_error(:actor, "is not allowed to delete object") - end - end - def cast_and_validate(data) do data |> cast_data diff --git a/test/web/activity_pub/object_validators/delete_validation_test.exs b/test/web/activity_pub/object_validators/delete_validation_test.exs index 42cd18298..02683b899 100644 --- a/test/web/activity_pub/object_validators/delete_validation_test.exs +++ b/test/web/activity_pub/object_validators/delete_validation_test.exs @@ -87,7 +87,7 @@ test "it's invalid if the actor of the object and the actor of delete are from d {:error, cng} = ObjectValidator.validate(invalid_other_actor, []) - assert {:actor, {"is not allowed to delete object", []}} in cng.errors + assert {:actor, {"is not allowed to modify object", []}} in cng.errors end test "it's valid if the actor of the object is a local superuser", -- cgit v1.2.3 From 3655175639a004976ef8296a0838e72642ba0b11 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 17:36:27 +0200 Subject: CommonValidations: Refactor `same_domain?` --- .../object_validators/common_validations.ex | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index e4c5d9619..82a9d39b5 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -126,18 +126,21 @@ def validate_fields_match(cng, fields) do end end - def same_domain?(cng, field_one \\ :actor, field_two \\ :object) do - actor_uri = - cng - |> get_field(field_one) - |> URI.parse() + def same_domain?(cng, fields \\ [:actor, :object]) do + unique_domains = + fields + |> Enum.map(fn field -> + %URI{host: host} = + cng + |> get_field(field) + |> URI.parse() - object_uri = - cng - |> get_field(field_two) - |> URI.parse() + host + end) + |> Enum.uniq() + |> Enum.count() - object_uri.host == actor_uri.host + unique_domains == 1 end # This figures out if a user is able to create, delete or modify something -- cgit v1.2.3 From 9d7ce1a6d014499eb4d55190b81e55da849b5ad0 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 5 Aug 2020 17:56:12 +0200 Subject: CommonValidations: More refactors. --- .../object_validators/common_validations.ex | 51 ++++++++-------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index 82a9d39b5..603d87b8e 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -84,20 +84,7 @@ def validate_object_or_user_presence(cng, options \\ []) do end def validate_host_match(cng, fields \\ [:id, :actor]) do - unique_hosts = - fields - |> Enum.map(fn field -> - %URI{host: host} = - cng - |> get_field(field) - |> URI.parse() - - host - end) - |> Enum.uniq() - |> Enum.count() - - if unique_hosts == 1 do + if same_domain?(cng, fields) do cng else fields @@ -109,13 +96,7 @@ def validate_host_match(cng, fields \\ [:id, :actor]) do end def validate_fields_match(cng, fields) do - unique_fields = - fields - |> Enum.map(fn field -> get_field(cng, field) end) - |> Enum.uniq() - |> Enum.count() - - if unique_fields == 1 do + if map_unique?(cng, fields) do cng else fields @@ -126,21 +107,23 @@ def validate_fields_match(cng, fields) do end end - def same_domain?(cng, fields \\ [:actor, :object]) do - unique_domains = - fields - |> Enum.map(fn field -> - %URI{host: host} = - cng - |> get_field(field) - |> URI.parse() + defp map_unique?(cng, fields, func \\ & &1) do + Enum.reduce_while(fields, nil, fn field, acc -> + value = + cng + |> get_field(field) + |> func.() - host - end) - |> Enum.uniq() - |> Enum.count() + case {value, acc} do + {value, nil} -> {:cont, value} + {value, value} -> {:cont, value} + _ -> {:halt, false} + end + end) + end - unique_domains == 1 + def same_domain?(cng, fields \\ [:actor, :object]) do + map_unique?(cng, fields, fn value -> URI.parse(value).host end) end # This figures out if a user is able to create, delete or modify something -- cgit v1.2.3 From 81126b0142ec54c785952d0c84a2bdef76965fc7 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 5 Aug 2020 11:36:12 -0500 Subject: Add email to user account only if it exists in LDAP --- lib/pleroma/user.ex | 9 +++++++++ lib/pleroma/web/auth/ldap_authenticator.ex | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index df9f34baa..6d39c9d1b 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -643,12 +643,21 @@ def register_changeset(struct, params = %{password: password}) when is_nil(password) do params = Map.put_new(params, :accepts_chat_messages, true) + params = + if Map.has_key?(params, :email) do + Map.put_new(params, :email, params[:email]) + else + params + end + struct |> cast(params, [ :name, :nickname, + :email, :accepts_chat_messages ]) + |> validate_required([:name, :nickname]) |> unique_constraint(:nickname) |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames])) |> validate_format(:nickname, local_nickname_regex()) diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex index f667da68b..b1645a359 100644 --- a/lib/pleroma/web/auth/ldap_authenticator.ex +++ b/lib/pleroma/web/auth/ldap_authenticator.ex @@ -103,13 +103,19 @@ defp register_user(connection, base, uid, name) do {:scope, :eldap.wholeSubtree()}, {:timeout, @search_timeout} ]) do - {:ok, {:eldap_search_result, [{:eldap_entry, _, _}], _}} -> + {:ok, {:eldap_search_result, [{:eldap_entry, _, attributes}], _}} -> params = %{ name: name, nickname: name, password: nil } + params = + case List.keyfind(attributes, 'mail', 0) do + {_, [mail]} -> Map.put_new(params, :email, :erlang.list_to_binary(mail)) + _ -> params + end + changeset = User.register_changeset(%User{}, params) case User.register(changeset) do -- cgit v1.2.3 From 2a4bca5bd7e33388193d252f9f956d10ce38ad77 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 5 Aug 2020 11:40:09 -0500 Subject: Comments are good when they're precise... --- lib/pleroma/user.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 6d39c9d1b..69b0e1781 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -638,7 +638,7 @@ def force_password_reset_async(user) do @spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} def force_password_reset(user), do: update_password_reset_pending(user, true) - # Used to auto-register LDAP accounts which don't have a password hash + # Used to auto-register LDAP accounts which won't have a password hash stored locally def register_changeset(struct, params = %{password: password}) when is_nil(password) do params = Map.put_new(params, :accepts_chat_messages, true) -- cgit v1.2.3 From cb7879c7c148cfc318a176d19b1402e370c509e7 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 5 Aug 2020 11:53:57 -0500 Subject: Add note about removal of Pleroma.Web.Auth.LDAPAuthenticator fallback to Pleroma.Web.Auth.PleromaAuthenticator --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index de017e30a..c0d0fe269 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Configuration: `:instance, rewrite_policy` moved to `:mrf, policies`, `:instance, :mrf_transparency` moved to `:mrf, :transparency`, `:instance, :mrf_transparency_exclusions` moved to `:mrf, :transparency_exclusions`. Old config namespace is deprecated. - Configuration: `:media_proxy, whitelist` format changed to host with scheme (e.g. `http://example.com` instead of `example.com`). Domain format is deprecated. - **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated. +- **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated.
API Changes -- cgit v1.2.3 From 135ae4e35a3e6a084eb611ce3a21c7a6c6bba9fc Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Thu, 6 Aug 2020 16:00:00 +0300 Subject: [#2025] Defaulted OAuth login scopes choice to all scopes when user selects no scopes. --- lib/pleroma/web/oauth/oauth_controller.ex | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index f29b3cb57..dd00600ea 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -76,6 +76,13 @@ defp do_authorize(%Plug.Conn{} = conn, params) do available_scopes = (app && app.scopes) || [] scopes = Scopes.fetch_scopes(params, available_scopes) + scopes = + if scopes == [] do + available_scopes + else + scopes + end + # Note: `params` might differ from `conn.params`; use `@params` not `@conn.params` in template render(conn, Authenticator.auth_template(), %{ response_type: params["response_type"], -- cgit v1.2.3 From e639eee82e1e0136bf6e64e571f2b05b5b7b948c Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 6 Aug 2020 18:01:29 -0500 Subject: restricted_nicknames: Add names from MastoAPI endpoints --- config/config.exs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/config/config.exs b/config/config.exs index 933a899ab..393f74372 100644 --- a/config/config.exs +++ b/config/config.exs @@ -515,7 +515,13 @@ "user-search", "user_exists", "users", - "web" + "web", + "verify_credentials", + "update_credentials", + "relationships", + "search", + "confirmation_resend", + "mfa" ], email_blacklist: [] -- cgit v1.2.3 From 6e6276b4f8a7a46c6038480f6a842339c5214d1c Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Fri, 7 Aug 2020 09:47:05 +0300 Subject: added test --- config/description.exs | 9 +-- .../controllers/config_controller_test.exs | 69 ++++++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/config/description.exs b/config/description.exs index 7da01b175..ac43bc814 100644 --- a/config/description.exs +++ b/config/description.exs @@ -982,8 +982,7 @@ %{ key: :message, type: :string, - description: - "A message that will be sent to newly registered users", + description: "A message that will be sent to newly registered users", suggestions: [ "Hi, @username! Welcome on board!" ] @@ -3552,13 +3551,15 @@ key: "name", label: "Name", type: :string, - description: "Name of the installed primary frontend. Valid config must include both `Name` and `Reference` values." + description: + "Name of the installed primary frontend. Valid config must include both `Name` and `Reference` values." }, %{ key: "ref", label: "Reference", type: :string, - description: "Reference of the installed primary frontend to be used. Valid config must include both `Name` and `Reference` values." + description: + "Reference of the installed primary frontend to be used. Valid config must include both `Name` and `Reference` values." } ] } diff --git a/test/web/admin_api/controllers/config_controller_test.exs b/test/web/admin_api/controllers/config_controller_test.exs index 61bc9fd39..4e897455f 100644 --- a/test/web/admin_api/controllers/config_controller_test.exs +++ b/test/web/admin_api/controllers/config_controller_test.exs @@ -1342,6 +1342,75 @@ test "args for Pleroma.Upload.Filter.Mogrify with custom tuples", %{conn: conn} args: ["auto-orient", "strip", {"implode", "1"}, {"resize", "3840x1080>"}] ] end + + test "enables the welcome messages", %{conn: conn} do + clear_config([:welcome]) + + params = %{ + "group" => ":pleroma", + "key" => ":welcome", + "value" => [ + %{ + "tuple" => [ + ":direct_message", + [ + %{"tuple" => [":enabled", true]}, + %{"tuple" => [":message", "Welcome to Pleroma!"]}, + %{"tuple" => [":sender_nickname", "pleroma"]} + ] + ] + }, + %{ + "tuple" => [ + ":chat_message", + [ + %{"tuple" => [":enabled", true]}, + %{"tuple" => [":message", "Welcome to Pleroma!"]}, + %{"tuple" => [":sender_nickname", "pleroma"]} + ] + ] + }, + %{ + "tuple" => [ + ":email", + [ + %{"tuple" => [":enabled", true]}, + %{"tuple" => [":sender", %{"tuple" => ["pleroma@dev.dev", "Pleroma"]}]}, + %{"tuple" => [":subject", "Welcome to <%= instance_name %>!"]}, + %{"tuple" => [":html", "Welcome to <%= instance_name %>!"]}, + %{"tuple" => [":text", "Welcome to <%= instance_name %>!"]} + ] + ] + } + ] + } + + refute Pleroma.User.WelcomeEmail.enabled?() + refute Pleroma.User.WelcomeMessage.enabled?() + refute Pleroma.User.WelcomeChatMessage.enabled?() + + res = + assert conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/config", %{"configs" => [params]}) + |> json_response_and_validate_schema(200) + + assert Pleroma.User.WelcomeEmail.enabled?() + assert Pleroma.User.WelcomeMessage.enabled?() + assert Pleroma.User.WelcomeChatMessage.enabled?() + + assert res == %{ + "configs" => [ + %{ + "db" => [":direct_message", ":chat_message", ":email"], + "group" => ":pleroma", + "key" => ":welcome", + "value" => params["value"] + } + ], + "need_reboot" => false + } + end end describe "GET /api/pleroma/admin/config/descriptions" do -- cgit v1.2.3 From 325c7c924bf05d240fcf535a37d32edf15370a0c Mon Sep 17 00:00:00 2001 From: rinpatch Date: Tue, 11 Feb 2020 00:29:25 +0300 Subject: Make Floki use fast_html --- config/config.exs | 2 ++ test/web/metadata/rel_me_test.exs | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/config.exs b/config/config.exs index 933a899ab..78f3232e6 100644 --- a/config/config.exs +++ b/config/config.exs @@ -737,6 +737,8 @@ config :pleroma, :instances_favicons, enabled: false +config :floki, :html_parser, Floki.HTMLParser.FastHtml + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/test/web/metadata/rel_me_test.exs b/test/web/metadata/rel_me_test.exs index 4107a8459..ac7558014 100644 --- a/test/web/metadata/rel_me_test.exs +++ b/test/web/metadata/rel_me_test.exs @@ -9,13 +9,11 @@ defmodule Pleroma.Web.Metadata.Providers.RelMeTest do test "it renders all links with rel='me' from user bio" do bio = - ~s(https://some-link.com https://another-link.com - https://some-link.com https://another-link.com ) user = insert(:user, %{bio: bio}) assert RelMe.build_tags(%{user: user}) == [ - {:link, [rel: "me", href: "http://some3.com>"], []}, + {:link, [rel: "me", href: "http://some3.com"], []}, {:link, [rel: "me", href: "https://another-link.com"], []} ] end -- cgit v1.2.3 From 7e23a48d38da50f1653f37c65610623f585ada9e Mon Sep 17 00:00:00 2001 From: rinpatch Date: Thu, 16 Jul 2020 21:09:48 +0300 Subject: rel me test: fix HTML so broken browsers (and therefore lexbor) refuse to parse it like mochiweb does --- test/web/metadata/rel_me_test.exs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/web/metadata/rel_me_test.exs b/test/web/metadata/rel_me_test.exs index ac7558014..2293d6e13 100644 --- a/test/web/metadata/rel_me_test.exs +++ b/test/web/metadata/rel_me_test.exs @@ -10,6 +10,7 @@ defmodule Pleroma.Web.Metadata.Providers.RelMeTest do test "it renders all links with rel='me' from user bio" do bio = ~s(https://some-link.com https://another-link.com ) + user = insert(:user, %{bio: bio}) assert RelMe.build_tags(%{user: user}) == [ -- cgit v1.2.3 From c662b09eee7f1e8a598c595f66e5b38b5dcbad45 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Fri, 7 Aug 2020 16:45:04 +0300 Subject: mix.exs: update fast_sanitize to 0.2.0 --- mix.exs | 2 +- mix.lock | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mix.exs b/mix.exs index aab833c5e..11fdb1670 100644 --- a/mix.exs +++ b/mix.exs @@ -127,7 +127,7 @@ defp deps do {:pbkdf2_elixir, "~> 1.2"}, {:bcrypt_elixir, "~> 2.2"}, {:trailing_format_plug, "~> 0.0.7"}, - {:fast_sanitize, "~> 0.1"}, + {:fast_sanitize, "~> 0.2.0"}, {:html_entities, "~> 0.5", override: true}, {:phoenix_html, "~> 2.14"}, {:calendar, "~> 1.0"}, diff --git a/mix.lock b/mix.lock index 55c3c59c6..7ec3a0b28 100644 --- a/mix.lock +++ b/mix.lock @@ -42,8 +42,8 @@ "ex_machina": {:hex, :ex_machina, "2.4.0", "09a34c5d371bfb5f78399029194a8ff67aff340ebe8ba19040181af35315eabb", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "a20bc9ddc721b33ea913b93666c5d0bdca5cbad7a67540784ae277228832d72c"}, "ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"}, "excoveralls": {:hex, :excoveralls, "0.13.1", "b9f1697f7c9e0cfe15d1a1d737fb169c398803ffcbc57e672aa007e9fd42864c", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b4bb550e045def1b4d531a37fb766cbbe1307f7628bf8f0414168b3f52021cce"}, - "fast_html": {:hex, :fast_html, "1.0.3", "2cc0d4b68496266a1530e0c852cafeaede0bd10cfdee26fda50dc696c203162f", [:make, :mix], [], "hexpm", "ab3d782b639d3c4655fbaec0f9d032c91f8cab8dd791ac7469c2381bc7c32f85"}, - "fast_sanitize": {:hex, :fast_sanitize, "0.1.7", "2a7cd8734c88a2de6de55022104f8a3b87f1fdbe8bbf131d9049764b53d50d0d", [:mix], [{:fast_html, "~> 1.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f39fe8ea08fbac17487c30bf09b7d9f3e12472e51fb07a88ffeb8fd17da8ab67"}, + "fast_html": {:hex, :fast_html, "2.0.1", "e126c74d287768ae78c48938da6711164517300d108a78f8a38993df8d588335", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "bdd6f8525c95ad391a4f10d9a1b3da4cea94078ec8638487aa8c24015ad9393a"}, + "fast_sanitize": {:hex, :fast_sanitize, "0.2.0", "004b40d5bbecda182b6fdba762a51fffd3501e689e8eafe196e1a97eb0caf733", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "11fcb37f26d272a3a2aff861872bf100be4eeacea69505908b8cdbcea5b0813a"}, "flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"}, "floki": {:hex, :floki, "0.27.0", "6b29a14283f1e2e8fad824bc930eaa9477c462022075df6bea8f0ad811c13599", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "583b8c13697c37179f1f82443bcc7ad2f76fbc0bf4c186606eebd658f7f2631b"}, "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"}, @@ -76,6 +76,7 @@ "mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm", "df4310628cd628ee181df93f50ddfd07be3e5ecc30232d3b6aadf30bdfe6092b"}, "myhtmlex": {:git, "https://git.pleroma.social/pleroma/myhtmlex.git", "ad0097e2f61d4953bfef20fb6abddf23b87111e6", [ref: "ad0097e2f61d4953bfef20fb6abddf23b87111e6", submodules: true]}, "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"}, + "nimble_pool": {:hex, :nimble_pool, "0.1.0", "ffa9d5be27eee2b00b0c634eb649aa27f97b39186fec3c493716c2a33e784ec6", [:mix], [], "hexpm", "343a1eaa620ddcf3430a83f39f2af499fe2370390d4f785cd475b4df5acaf3f9"}, "nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]}, "oban": {:hex, :oban, "2.0.0", "e6ce70d94dd46815ec0882a1ffb7356df9a9d5b8a40a64ce5c2536617a447379", [:mix], [{:ecto_sql, ">= 3.4.3", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cf574813bd048b98a698aa587c21367d2e06842d4e1b1993dcd6a696e9e633bd"}, "open_api_spex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git", "f296ac0924ba3cf79c7a588c4c252889df4c2edd", [ref: "f296ac0924ba3cf79c7a588c4c252889df4c2edd"]}, -- cgit v1.2.3 From ebb30128af653d146091fa2317418103fd1e46a3 Mon Sep 17 00:00:00 2001 From: lain Date: Fri, 7 Aug 2020 16:20:13 +0200 Subject: Changelog: Add information about the object age policy --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 572f9e84b..e2a855bef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] ### Changed +- **Breaking:** Added the ObjectAgePolicy to the default set of MRFs. This will delist and strip the follower collection of any message received that is older than 7 days. This will stop users from seeing very old messages in the timelines. The messages can still be viewed on the user's page and in conversations. They also still trigger notifications. - **Breaking:** Elixir >=1.9 is now required (was >= 1.8) - **Breaking:** Configuration: `:auto_linker, :opts` moved to `:pleroma, Pleroma.Formatter`. Old config namespace is deprecated. - In Conversations, return only direct messages as `last_status` -- cgit v1.2.3 From 6ddea8ebe8794a9626f3907a5d0e0db9604bf949 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 7 Aug 2020 09:42:10 -0500 Subject: Add a note about the proper value for uid --- docs/configuration/cheatsheet.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index f23cf4fe4..d9115a958 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -890,6 +890,9 @@ Pleroma account will be created with the same name as the LDAP user name. * `base`: LDAP base, e.g. "dc=example,dc=com" * `uid`: LDAP attribute name to authenticate the user, e.g. when "cn", the filter will be "cn=username,base" +Note, if your LDAP server is an Active Directory server the correct value is commonly `uid: "cn"`, but if you use an +OpenLDAP server the value may be `uid: "uid"`. + ### OAuth consumer mode OAuth consumer mode allows sign in / sign up via external OAuth providers (e.g. Twitter, Facebook, Google, Microsoft, etc.). -- cgit v1.2.3 From cb376c4c4ca6491f2b58a9a916986998312640f5 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Fri, 7 Aug 2020 17:33:59 +0300 Subject: CI: install cmake since fast_html now requires it --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c9ab84892..66813c814 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,6 +22,7 @@ stages: - docker before_script: + - apt-get update && apt-get install -y cmake - mix local.hex --force - mix local.rebar --force -- cgit v1.2.3 From 60fe0a08f0ed4b83847995f4e0a5ff10dcf9d336 Mon Sep 17 00:00:00 2001 From: lain Date: Fri, 7 Aug 2020 17:59:55 +0200 Subject: Docs: Remove wrong / confusing auth docs. --- docs/configuration/cheatsheet.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index f23cf4fe4..89036ded0 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -858,9 +858,6 @@ Warning: it's discouraged to use this feature because of the associated security ### :auth -* `Pleroma.Web.Auth.PleromaAuthenticator`: default database authenticator. -* `Pleroma.Web.Auth.LDAPAuthenticator`: LDAP authentication. - Authentication / authorization settings. * `auth_template`: authentication form template. By default it's `show.html` which corresponds to `lib/pleroma/web/templates/o_auth/o_auth/show.html.eex`. -- cgit v1.2.3 From 673e8e3ac154c4ce5801077234cf2bdee99e78c9 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 7 Aug 2020 13:02:39 -0500 Subject: Force 204 responses to be empty, fixes #2029 --- lib/pleroma/web/controller_helper.ex | 6 ++++++ test/support/conn_case.ex | 9 ++++++++- test/web/admin_api/controllers/admin_api_controller_test.exs | 10 +++++----- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/pleroma/web/controller_helper.ex b/lib/pleroma/web/controller_helper.ex index 69946fb81..6445966e0 100644 --- a/lib/pleroma/web/controller_helper.ex +++ b/lib/pleroma/web/controller_helper.ex @@ -18,6 +18,12 @@ def falsy_param?(value), def truthy_param?(value), do: not falsy_param?(value) + def json_response(conn, status, _) when status in [204, :no_content] do + conn + |> put_resp_header("content-type", "application/json") + |> send_resp(status, "") + end + def json_response(conn, status, json) do conn |> put_status(status) diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index b23918dd1..b50ff1bcc 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -56,6 +56,13 @@ defp request_content_type(%{conn: conn}) do [conn: conn] end + defp empty_json_response(conn) do + body = response(conn, 204) + _ = response_content_type(conn, :json) + + body + end + defp json_response_and_validate_schema( %{ private: %{ @@ -79,7 +86,7 @@ defp json_response_and_validate_schema( end schema = lookup[op_id].responses[status].content[content_type].schema - json = json_response(conn, status) + json = if status == 204, do: empty_json_response(conn), else: json_response(conn, status) case OpenApiSpex.cast_value(json, schema, spec) do {:ok, _data} -> diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index b5d5bd8c7..e63268831 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -439,7 +439,7 @@ test "it appends specified tags to users with specified nicknames", %{ user1: user1, user2: user2 } do - assert json_response(conn, :no_content) + assert empty_json_response(conn) assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"] assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"] @@ -457,7 +457,7 @@ test "it appends specified tags to users with specified nicknames", %{ end test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do - assert json_response(conn, :no_content) + assert empty_json_response(conn) assert User.get_cached_by_id(user3.id).tags == ["unchanged"] end end @@ -485,7 +485,7 @@ test "it removes specified tags from users with specified nicknames", %{ user1: user1, user2: user2 } do - assert json_response(conn, :no_content) + assert empty_json_response(conn) assert User.get_cached_by_id(user1.id).tags == [] assert User.get_cached_by_id(user2.id).tags == ["y"] @@ -503,7 +503,7 @@ test "it removes specified tags from users with specified nicknames", %{ end test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do - assert json_response(conn, :no_content) + assert empty_json_response(conn) assert User.get_cached_by_id(user3.id).tags == ["unchanged"] end end @@ -1756,7 +1756,7 @@ test "sets password_reset_pending to true", %{conn: conn} do conn = patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]}) - assert json_response(conn, 204) == "" + assert empty_json_response(conn) == "" ObanHelpers.perform_all() -- cgit v1.2.3 From 8e1f7a3eff05a43f59f15dc6fa0483713e221fa7 Mon Sep 17 00:00:00 2001 From: Angelina Filippova Date: Fri, 7 Aug 2020 21:04:13 +0300 Subject: Add new `image` type to settings whose values are image urls --- config/description.exs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/config/description.exs b/config/description.exs index 7da01b175..e2f78e77d 100644 --- a/config/description.exs +++ b/config/description.exs @@ -951,7 +951,7 @@ }, %{ key: :instance_thumbnail, - type: :string, + type: {:string, :image}, description: "The instance thumbnail can be any image that represents your instance and is used by some apps or services when they display information about your instance.", suggestions: ["/instance/thumbnail.jpeg"] @@ -1237,7 +1237,7 @@ }, %{ key: :background, - type: :string, + type: {:string, :image}, description: "URL of the background, unless viewing a user profile with a background that is set", suggestions: ["/images/city.jpg"] @@ -1294,7 +1294,7 @@ }, %{ key: :logo, - type: :string, + type: {:string, :image}, description: "URL of the logo, defaults to Pleroma's logo", suggestions: ["/static/logo.png"] }, @@ -1326,7 +1326,7 @@ %{ key: :nsfwCensorImage, label: "NSFW Censor Image", - type: :string, + type: {:string, :image}, description: "URL of the image to use for hiding NSFW media attachments in the timeline", suggestions: ["/static/img/nsfw.74818f9.png"] @@ -1452,7 +1452,7 @@ }, %{ key: :default_user_avatar, - type: :string, + type: {:string, :image}, description: "URL of the default user avatar", suggestions: ["/images/avi.png"] } @@ -2643,7 +2643,7 @@ children: [ %{ key: :logo, - type: :string, + type: {:string, :image}, description: "A path to a custom logo. Set it to `nil` to use the default Pleroma logo.", suggestions: ["some/path/logo.png"] }, @@ -3552,13 +3552,15 @@ key: "name", label: "Name", type: :string, - description: "Name of the installed primary frontend. Valid config must include both `Name` and `Reference` values." + description: + "Name of the installed primary frontend. Valid config must include both `Name` and `Reference` values." }, %{ key: "ref", label: "Reference", type: :string, - description: "Reference of the installed primary frontend to be used. Valid config must include both `Name` and `Reference` values." + description: + "Reference of the installed primary frontend to be used. Valid config must include both `Name` and `Reference` values." } ] } -- cgit v1.2.3 From 881fdb3a97740425555f4f8b9ddb75123ace73b7 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Fri, 7 Aug 2020 21:25:16 +0300 Subject: Add security policy for Pleroma backend Closes #1848 --- SECURITY.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..c212a2505 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,16 @@ +# Pleroma backend security policy + +## Supported versions + +Currently, Pleroma offers bugfixes and security patches only for the latest minor release. + +| Version | Support +|---------| -------- +| 2.0 | Bugfixes and security patches + +## Reporting a vulnerability + +Please use confidential issues (tick the "This issue is confidential and should only be visible to team members with at least Reporter access." box when submitting) at our [bugtracker](https://git.pleroma.social/pleroma/pleroma/-/issues/new) for reporting vulnerabilities. +## Announcements + +New releases are announced at [pleroma.social](https://pleroma.social/announcements/). All security releases are tagged with ["Security"](https://pleroma.social/announcements/tags/security/). You can be notified of them by subscribing to an Atom feed at . -- cgit v1.2.3 From 474147a67a89f8bd92186dbda93d78d8e2045d52 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 7 Aug 2020 14:54:14 -0500 Subject: Make a new function instead of overloading register_changeset/3 --- lib/pleroma/user.ex | 2 +- lib/pleroma/web/auth/ldap_authenticator.ex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 69b0e1781..d1436a688 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -639,7 +639,7 @@ def force_password_reset_async(user) do def force_password_reset(user), do: update_password_reset_pending(user, true) # Used to auto-register LDAP accounts which won't have a password hash stored locally - def register_changeset(struct, params = %{password: password}) + def register_changeset_ldap(struct, params = %{password: password}) when is_nil(password) do params = Map.put_new(params, :accepts_chat_messages, true) diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex index b1645a359..402ab428b 100644 --- a/lib/pleroma/web/auth/ldap_authenticator.ex +++ b/lib/pleroma/web/auth/ldap_authenticator.ex @@ -116,7 +116,7 @@ defp register_user(connection, base, uid, name) do _ -> params end - changeset = User.register_changeset(%User{}, params) + changeset = User.register_changeset_ldap(%User{}, params) case User.register(changeset) do {:ok, user} -> user -- cgit v1.2.3 From e0dee833f2b192e07cd00cc4fd78f646a3cd21d9 Mon Sep 17 00:00:00 2001 From: Ilja Date: Sat, 8 Aug 2020 12:21:44 +0200 Subject: Improve static_dir documentation * It was still written for From Source installs. Now it's both OTP and From Source * I linked to the cheatsheet where it was about configuration * I moved the mix tasks of the robot.txt section to the CLI tasks and linked to it * i checked the code at https://git.pleroma.social/pleroma/pleroma/-/blob/develop/lib/mix/tasks/pleroma/robotstxt.ex and it doesn't seem to more than just this one command with this option * I also added the location of robot.txt and an example to dissallow everything, but allow the fediverse.network crawlers * The Thumbnail section still linked to distsn.org which doesn't exist any more. I changed it to a general statemant that it can be used by external applications. (I don't know any that actually use it.) * Both the logo and TOS need an extra `static` folder. I've seen confusion about that in #pleroma so I added an Important note. --- docs/administration/CLI_tasks/robots_txt.md | 17 +++++++++ docs/configuration/static_dir.md | 55 +++++++++++++++++++---------- 2 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 docs/administration/CLI_tasks/robots_txt.md diff --git a/docs/administration/CLI_tasks/robots_txt.md b/docs/administration/CLI_tasks/robots_txt.md new file mode 100644 index 000000000..b1de0981b --- /dev/null +++ b/docs/administration/CLI_tasks/robots_txt.md @@ -0,0 +1,17 @@ +# Managing robot.txt + +{! backend/administration/CLI_tasks/general_cli_task_info.include !} + +## Generate a new robot.txt file and add it to the static directory + +The `robots.txt` that ships by default is permissive. It allows well-behaved search engines to index all of your instance's URIs. + +If you want to generate a restrictive `robots.txt`, you can run the following mix task. The generated `robots.txt` will be written in your instance [static directory](../../../configuration/static_dir/). + +```elixir tab="OTP" +./bin/pleroma_ctl robots_txt disallow_all +``` + +```elixir tab="From Source" +mix pleroma.robots_txt disallow_all +``` diff --git a/docs/configuration/static_dir.md b/docs/configuration/static_dir.md index 5fb38c3de..8e7eea7fb 100644 --- a/docs/configuration/static_dir.md +++ b/docs/configuration/static_dir.md @@ -1,45 +1,57 @@ # Static Directory -Static frontend files are shipped in `priv/static/` and tracked by version control in this repository. If you want to overwrite or update these without the possibility of merge conflicts, you can write your custom versions to `instance/static/`. +Static frontend files are shipped with pleroma. If you want to overwrite or update these without problems during upgrades, you can write your custom versions to the static directory. +You can find the location of the static directory in the [configuration](../cheatsheet/#instance). + +```elixir tab="OTP" +config :pleroma, :instance, + static_dir: "/var/lib/pleroma/static/", ``` + +```elixir tab="From Source" config :pleroma, :instance, static_dir: "instance/static/", ``` -For example, edit `instance/static/instance/panel.html` . - Alternatively, you can overwrite this value in your configuration to use a different static instance directory. -This document is written assuming `instance/static/`. +This document is written using `$static_dir` as the value of the `config :pleroma, :instance, static_dir` setting. -Or, if you want to manage your custom file in git repository, basically remove the `instance/` entry from `.gitignore`. +If you use a From Source installation and want to manage your custom files in the git repository, you can remove the `instance/` entry from `.gitignore`. ## robots.txt -By default, the `robots.txt` that ships in `priv/static/` is permissive. It allows well-behaved search engines to index all of your instance's URIs. +There's a mix tasks to [generate a new robot.txt](../../administration/CLI_tasks/robots_txt/). + +For more complex things, you can write your own robots.txt to `$static_dir/robots.txt`. -If you want to generate a restrictive `robots.txt`, you can run the following mix task. The generated `robots.txt` will be written in your instance static directory. +E.g. if you want to block all crawerls except for [fediverse.newtork](https://fediverse.network/about) you can use ``` -mix pleroma.robots_txt disallow_all +User-Agent: * +Disallow: / + +User-Agent: crawler-us-il-1.fediverse.network +Allow: / + +User-Agent: makhnovtchina.random.sh +Allow: / ``` ## Thumbnail -Put on `instance/static/instance/thumbnail.jpeg` with your selfie or other neat picture. It will appear in [Pleroma Instances](http://distsn.org/pleroma-instances.html). +Add `$static_dir/instance/thumbnail.jpeg` with your selfie or other neat picture. It will be available on `http://your-domain.tld/instance/thumbnail.jpeg` and can be used by external applications. ## Instance-specific panel -![instance-specific panel demo](/uploads/296b19ec806b130e0b49b16bfe29ce8a/image.png) - -Create and Edit your file on `instance/static/instance/panel.html`. +Create and Edit your file on `$static_dir/instance/panel.html`. ## Background -You can change the background of your Pleroma instance by uploading it to `instance/static/`, and then changing `background` in `config/prod.secret.exs` accordingly. +You can change the background of your Pleroma instance by uploading it to `$static_dir/`, and then changing `background` in [your configuration](../cheatsheet/#frontend_configurations) accordingly. -If you put `instance/static/images/background.jpg` +E.g. if you put `$static_dir/images/background.jpg` ``` config :pleroma, :frontend_configurations, @@ -50,12 +62,14 @@ config :pleroma, :frontend_configurations, ## Logo -![logo modification demo](/uploads/c70b14de60fa74245e7f0dcfa695ebff/image.png) +!!! important + Note the extra `static` folder for the default logo.png location -If you want to give a brand to your instance, You can change the logo of your instance by uploading it to `instance/static/`. +If you want to give a brand to your instance, You can change the logo of your instance by uploading it to the static directory `$static_dir/static/logo.png`. -Alternatively, you can specify the path with config. -If you put `instance/static/static/mylogo-file.png` +Alternatively, you can specify the path to your logo in [your configuration](../cheatsheet/#frontend_configurations). + +E.g. if you put `$static_dir/static/mylogo-file.png` ``` config :pleroma, :frontend_configurations, @@ -66,4 +80,7 @@ config :pleroma, :frontend_configurations, ## Terms of Service -Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by changing `instance/static/static/terms-of-service.html`. +!!! important + Note the extra `static` folder for the terms-of-service.html + +Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by adding and changing `$static_dir/static/terms-of-service.html`. -- cgit v1.2.3 From e5557bf8ba6a56996ba8847a522042a748dc046b Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sat, 8 Aug 2020 16:29:40 +0400 Subject: Add mix task to add expiration to all local statuses --- docs/administration/CLI_tasks/database.md | 12 +++++++++- lib/mix/tasks/pleroma/database.ex | 24 +++++++++++++++---- lib/pleroma/activity_expiration.ex | 12 ++++++---- test/tasks/database_test.exs | 39 +++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/docs/administration/CLI_tasks/database.md b/docs/administration/CLI_tasks/database.md index 647f6f274..64dd66c0c 100644 --- a/docs/administration/CLI_tasks/database.md +++ b/docs/administration/CLI_tasks/database.md @@ -97,4 +97,14 @@ but should only be run if necessary. **It is safe to cancel this.** ```sh tab="From Source" mix pleroma.database vacuum full -``` \ No newline at end of file +``` + +## Add expiration to all local statuses + +```sh tab="OTP" +./bin/pleroma_ctl database ensure_expiration +``` + +```sh tab="From Source" +mix pleroma.database ensure_expiration +``` diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 82e2abdcb..d57e59b11 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -10,6 +10,7 @@ defmodule Mix.Tasks.Pleroma.Database do alias Pleroma.User require Logger require Pleroma.Constants + import Ecto.Query import Mix.Pleroma use Mix.Task @@ -53,8 +54,6 @@ def run(["update_users_following_followers_counts"]) do end def run(["prune_objects" | args]) do - import Ecto.Query - {options, [], []} = OptionParser.parse( args, @@ -94,8 +93,6 @@ def run(["prune_objects" | args]) do end def run(["fix_likes_collections"]) do - import Ecto.Query - start_pleroma() from(object in Object, @@ -130,4 +127,23 @@ def run(["vacuum", args]) do Maintenance.vacuum(args) end + + def run(["ensure_expiration"]) do + start_pleroma() + days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365) + + Pleroma.Activity + |> join(:left, [a], u in assoc(a, :expiration)) + |> where(local: true) + |> where([a, u], is_nil(u)) + |> Pleroma.RepoStreamer.chunk_stream(100) + |> Stream.each(fn activities -> + Enum.each(activities, fn activity -> + expires_at = Timex.shift(activity.inserted_at, days: days) + + Pleroma.ActivityExpiration.create(activity, expires_at, false) + end) + end) + |> Stream.run() + end end diff --git a/lib/pleroma/activity_expiration.ex b/lib/pleroma/activity_expiration.ex index db9c88d84..7cc9668b3 100644 --- a/lib/pleroma/activity_expiration.ex +++ b/lib/pleroma/activity_expiration.ex @@ -20,11 +20,11 @@ defmodule Pleroma.ActivityExpiration do field(:scheduled_at, :naive_datetime) end - def changeset(%ActivityExpiration{} = expiration, attrs) do + def changeset(%ActivityExpiration{} = expiration, attrs, validate_scheduled_at) do expiration |> cast(attrs, [:scheduled_at]) |> validate_required([:scheduled_at]) - |> validate_scheduled_at() + |> validate_scheduled_at(validate_scheduled_at) end def get_by_activity_id(activity_id) do @@ -33,9 +33,9 @@ def get_by_activity_id(activity_id) do |> Repo.one() end - def create(%Activity{} = activity, scheduled_at) do + def create(%Activity{} = activity, scheduled_at, validate_scheduled_at \\ true) do %ActivityExpiration{activity_id: activity.id} - |> changeset(%{scheduled_at: scheduled_at}) + |> changeset(%{scheduled_at: scheduled_at}, validate_scheduled_at) |> Repo.insert() end @@ -49,7 +49,9 @@ def due_expirations(offset \\ 0) do |> Repo.all() end - def validate_scheduled_at(changeset) do + def validate_scheduled_at(changeset, false), do: changeset + + def validate_scheduled_at(changeset, true) do validate_change(changeset, :scheduled_at, fn _, scheduled_at -> if not expires_late_enough?(scheduled_at) do [scheduled_at: "an ephemeral activity must live for at least one hour"] diff --git a/test/tasks/database_test.exs b/test/tasks/database_test.exs index 883828d77..3a28aa133 100644 --- a/test/tasks/database_test.exs +++ b/test/tasks/database_test.exs @@ -127,4 +127,43 @@ test "it turns OrderedCollection likes into empty arrays" do assert Enum.empty?(Object.get_by_id(object2.id).data["likes"]) end end + + describe "ensure_expiration" do + test "it adds to expiration old statuses" do + %{id: activity_id1} = insert(:note_activity) + + %{id: activity_id2} = + insert(:note_activity, %{inserted_at: NaiveDateTime.from_iso8601!("2015-01-23 23:50:07")}) + + %{id: activity_id3} = activity3 = insert(:note_activity) + + expires_at = + NaiveDateTime.utc_now() + |> NaiveDateTime.add(60 * 61, :second) + |> NaiveDateTime.truncate(:second) + + Pleroma.ActivityExpiration.create(activity3, expires_at) + + Mix.Tasks.Pleroma.Database.run(["ensure_expiration"]) + + expirations = + Pleroma.ActivityExpiration + |> order_by(:activity_id) + |> Repo.all() + + assert [ + %Pleroma.ActivityExpiration{ + activity_id: ^activity_id1 + }, + %Pleroma.ActivityExpiration{ + activity_id: ^activity_id2, + scheduled_at: ~N[2016-01-23 23:50:07] + }, + %Pleroma.ActivityExpiration{ + activity_id: ^activity_id3, + scheduled_at: ^expires_at + } + ] = expirations + end + end end -- cgit v1.2.3 From 2e7c5fe2ded095c95f8596970d8fc3aaf0128f1b Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Sat, 8 Aug 2020 12:33:37 -0500 Subject: Add migration to remove invalid activity expirations --- .../20200808173046_only_expire_creates.exs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 priv/repo/migrations/20200808173046_only_expire_creates.exs diff --git a/priv/repo/migrations/20200808173046_only_expire_creates.exs b/priv/repo/migrations/20200808173046_only_expire_creates.exs new file mode 100644 index 000000000..5a34dc7c1 --- /dev/null +++ b/priv/repo/migrations/20200808173046_only_expire_creates.exs @@ -0,0 +1,20 @@ +defmodule Pleroma.Repo.Migrations.OnlyExpireCreates do + use Ecto.Migration + + def up do + statement = """ + DELETE FROM + activity_expirations A USING activities B + WHERE + A.activity_id = B.id + AND B.local = false + AND B.data->>'type' != 'Create'; + """ + + execute(statement) + end + + def down do + :ok + end +end -- cgit v1.2.3 From cf4c97242be588e55dfccb37ab2c3d6dcac3cb0f Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Sat, 8 Aug 2020 12:40:52 -0500 Subject: Ensure we only expire Create activities with the Mix task --- lib/mix/tasks/pleroma/database.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index d57e59b11..b2dc3d0f3 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -136,6 +136,7 @@ def run(["ensure_expiration"]) do |> join(:left, [a], u in assoc(a, :expiration)) |> where(local: true) |> where([a, u], is_nil(u)) + |> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data)) |> Pleroma.RepoStreamer.chunk_stream(100) |> Stream.each(fn activities -> Enum.each(activities, fn activity -> -- cgit v1.2.3 From 761cc5b4a2b4c0ef610ae7296f614ec4c9ceccad Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Sat, 8 Aug 2020 12:44:18 -0500 Subject: Don't filter on local --- priv/repo/migrations/20200808173046_only_expire_creates.exs | 1 - 1 file changed, 1 deletion(-) diff --git a/priv/repo/migrations/20200808173046_only_expire_creates.exs b/priv/repo/migrations/20200808173046_only_expire_creates.exs index 5a34dc7c1..42fb73375 100644 --- a/priv/repo/migrations/20200808173046_only_expire_creates.exs +++ b/priv/repo/migrations/20200808173046_only_expire_creates.exs @@ -7,7 +7,6 @@ def up do activity_expirations A USING activities B WHERE A.activity_id = B.id - AND B.local = false AND B.data->>'type' != 'Create'; """ -- cgit v1.2.3 From e08ea01d09c67a93801aa05d33bad0eb24dfca8b Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Sat, 8 Aug 2020 12:49:02 -0500 Subject: Limit expirations for each cron execution to 50. This should prevent servers from being crushed. 50/min is a pretty good rate. --- lib/pleroma/activity_expiration.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pleroma/activity_expiration.ex b/lib/pleroma/activity_expiration.ex index 7cc9668b3..84edf68ef 100644 --- a/lib/pleroma/activity_expiration.ex +++ b/lib/pleroma/activity_expiration.ex @@ -46,6 +46,7 @@ def due_expirations(offset \\ 0) do ActivityExpiration |> where([exp], exp.scheduled_at < ^naive_datetime) + |> limit(50) |> Repo.all() end -- cgit v1.2.3 From 66122a11b59a3859f3eb67066148e9c75139d3ee Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 10 Aug 2020 10:33:05 +0200 Subject: AccountController: Build the correct update activity. Will fix federation issues. --- lib/pleroma/web/mastodon_api/controllers/account_controller.ex | 2 +- .../controllers/account_controller/update_credentials_test.exs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index f45678184..95d8452df 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -226,7 +226,7 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p with changeset <- User.update_changeset(user, user_params), {:ok, unpersisted_user} <- Ecto.Changeset.apply_action(changeset, :update), updated_object <- - Pleroma.Web.ActivityPub.UserView.render("user.json", user: user) + Pleroma.Web.ActivityPub.UserView.render("user.json", user: unpersisted_user) |> Map.delete("@context"), {:ok, update_data, []} <- Builder.update(user, updated_object), {:ok, _update, _} <- diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs index b888e4c71..2e6704726 100644 --- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs +++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs @@ -214,6 +214,10 @@ test "updates the user's name", %{conn: conn} do assert user_data = json_response_and_validate_schema(conn, 200) assert user_data["display_name"] == "markorepairs" + + update_activity = Repo.one(Pleroma.Activity) + assert update_activity.data["type"] == "Update" + assert update_activity.data["object"]["name"] == "markorepairs" end test "updates the user's avatar", %{user: user, conn: conn} do -- cgit v1.2.3 From a818587467feb1f5d5ad1f9499e61dcd7184e864 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Fri, 7 Aug 2020 22:05:17 +0300 Subject: 20200802170532_fix_legacy_tags: Select only fields the migration needs Selecting the full struct will break as soon as a new field is added. --- priv/repo/migrations/20200802170532_fix_legacy_tags.exs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/priv/repo/migrations/20200802170532_fix_legacy_tags.exs b/priv/repo/migrations/20200802170532_fix_legacy_tags.exs index f7274b44e..a84b5d0f6 100644 --- a/priv/repo/migrations/20200802170532_fix_legacy_tags.exs +++ b/priv/repo/migrations/20200802170532_fix_legacy_tags.exs @@ -18,7 +18,10 @@ defmodule Pleroma.Repo.Migrations.FixLegacyTags do def change do legacy_tags = Map.keys(@old_new_map) - from(u in User, where: fragment("? && ?", u.tags, ^legacy_tags)) + from(u in User, + where: fragment("? && ?", u.tags, ^legacy_tags), + select: struct(u, [:tags, :id]) + ) |> Repo.all() |> Enum.each(fn user -> fix_tags_changeset(user) -- cgit v1.2.3 From 15fa3b6bd8dcc65b74715c500cd23923251d7fd3 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Fri, 7 Aug 2020 22:10:09 +0300 Subject: 20200802170532_fix_legacy_tags: chunk the user query --- priv/repo/migrations/20200802170532_fix_legacy_tags.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/priv/repo/migrations/20200802170532_fix_legacy_tags.exs b/priv/repo/migrations/20200802170532_fix_legacy_tags.exs index a84b5d0f6..ca82fac42 100644 --- a/priv/repo/migrations/20200802170532_fix_legacy_tags.exs +++ b/priv/repo/migrations/20200802170532_fix_legacy_tags.exs @@ -22,7 +22,7 @@ def change do where: fragment("? && ?", u.tags, ^legacy_tags), select: struct(u, [:tags, :id]) ) - |> Repo.all() + |> Repo.chunk_stream(100) |> Enum.each(fn user -> fix_tags_changeset(user) |> Repo.update() -- cgit v1.2.3 From a4a2d3864049e03599057ab87ead4aea423c47eb Mon Sep 17 00:00:00 2001 From: Ilja Date: Mon, 10 Aug 2020 11:29:40 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- docs/configuration/static_dir.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/static_dir.md b/docs/configuration/static_dir.md index 8e7eea7fb..2c18e3d38 100644 --- a/docs/configuration/static_dir.md +++ b/docs/configuration/static_dir.md @@ -26,7 +26,7 @@ There's a mix tasks to [generate a new robot.txt](../../administration/CLI_tasks For more complex things, you can write your own robots.txt to `$static_dir/robots.txt`. -E.g. if you want to block all crawerls except for [fediverse.newtork](https://fediverse.network/about) you can use +E.g. if you want to block all crawlers except for [fediverse.network](https://fediverse.network/about) you can use ``` User-Agent: * -- cgit v1.2.3 From bd7bf6cd196ffe30652ea1f7785354a7eb1e912c Mon Sep 17 00:00:00 2001 From: Ilja Date: Mon, 10 Aug 2020 11:29:54 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- docs/configuration/static_dir.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/static_dir.md b/docs/configuration/static_dir.md index 2c18e3d38..58703e3be 100644 --- a/docs/configuration/static_dir.md +++ b/docs/configuration/static_dir.md @@ -45,7 +45,7 @@ Add `$static_dir/instance/thumbnail.jpeg` with your selfie or other neat picture ## Instance-specific panel -Create and Edit your file on `$static_dir/instance/panel.html`. +Create and Edit your file at `$static_dir/instance/panel.html`. ## Background -- cgit v1.2.3 From 5c4548d5e74e40e18d8d1ed98ad256568a063370 Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 10 Aug 2020 13:05:13 +0000 Subject: Revert "Merge branch 'issue/1023' into 'develop'" This reverts merge request !2763 --- .gitignore | 2 - .../CLI_tasks/release_environments.md | 9 --- docs/installation/otp_en.md | 7 +- installation/init.d/pleroma | 1 - installation/pleroma.service | 2 - lib/mix/tasks/pleroma/release_env.ex | 76 ---------------------- test/tasks/release_env_test.exs | 30 --------- 7 files changed, 2 insertions(+), 125 deletions(-) delete mode 100644 docs/administration/CLI_tasks/release_environments.md delete mode 100644 lib/mix/tasks/pleroma/release_env.ex delete mode 100644 test/tasks/release_env_test.exs diff --git a/.gitignore b/.gitignore index 6ae21e914..599b52b9e 100644 --- a/.gitignore +++ b/.gitignore @@ -27,8 +27,6 @@ erl_crash.dump # variables. /config/*.secret.exs /config/generated_config.exs -/config/*.env - # Database setup file, some may forget to delete it /config/setup_db.psql diff --git a/docs/administration/CLI_tasks/release_environments.md b/docs/administration/CLI_tasks/release_environments.md deleted file mode 100644 index 36ab43864..000000000 --- a/docs/administration/CLI_tasks/release_environments.md +++ /dev/null @@ -1,9 +0,0 @@ -# Generate release environment file - -```sh tab="OTP" - ./bin/pleroma_ctl release_env gen -``` - -```sh tab="From Source" -mix pleroma.release_env gen -``` diff --git a/docs/installation/otp_en.md b/docs/installation/otp_en.md index 338dfa7d0..e4f822d1c 100644 --- a/docs/installation/otp_en.md +++ b/docs/installation/otp_en.md @@ -121,9 +121,6 @@ chown -R pleroma /etc/pleroma # Run the config generator su pleroma -s $SHELL -lc "./bin/pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql" -# Run the environment file generator. -su pleroma -s $SHELL -lc "./bin/pleroma_ctl release_env gen" - # Create the postgres database su postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql" @@ -134,7 +131,7 @@ su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate" # su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/" # Start the instance to verify that everything is working as expected -su pleroma -s $SHELL -lc "export $(cat /opt/pleroma/config/pleroma.env); ./bin/pleroma daemon" +su pleroma -s $SHELL -lc "./bin/pleroma daemon" # Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly sleep 20 && curl http://localhost:4000/api/v1/instance @@ -203,7 +200,6 @@ rc-update add pleroma # Copy the service into a proper directory cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service - # Start pleroma and enable it on boot systemctl start pleroma systemctl enable pleroma @@ -279,3 +275,4 @@ This will create an account withe the username of 'joeuser' with the email addre ## Questions Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**. + diff --git a/installation/init.d/pleroma b/installation/init.d/pleroma index e908cda1b..384536f7e 100755 --- a/installation/init.d/pleroma +++ b/installation/init.d/pleroma @@ -8,7 +8,6 @@ pidfile="/var/run/pleroma.pid" directory=/opt/pleroma healthcheck_delay=60 healthcheck_timer=30 -export $(cat /opt/pleroma/config/pleroma.env) : ${pleroma_port:-4000} diff --git a/installation/pleroma.service b/installation/pleroma.service index ee00a3b7a..5dcbc1387 100644 --- a/installation/pleroma.service +++ b/installation/pleroma.service @@ -17,8 +17,6 @@ Environment="MIX_ENV=prod" Environment="HOME=/var/lib/pleroma" ; Path to the folder containing the Pleroma installation. WorkingDirectory=/opt/pleroma -; Path to the environment file. the file contains RELEASE_COOKIE and etc -EnvironmentFile=/opt/pleroma/config/pleroma.env ; Path to the Mix binary. ExecStart=/usr/bin/mix phx.server diff --git a/lib/mix/tasks/pleroma/release_env.ex b/lib/mix/tasks/pleroma/release_env.ex deleted file mode 100644 index 9da74ffcf..000000000 --- a/lib/mix/tasks/pleroma/release_env.ex +++ /dev/null @@ -1,76 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Mix.Tasks.Pleroma.ReleaseEnv do - use Mix.Task - import Mix.Pleroma - - @shortdoc "Generate Pleroma environment file." - @moduledoc File.read!("docs/administration/CLI_tasks/release_environments.md") - - def run(["gen" | rest]) do - {options, [], []} = - OptionParser.parse( - rest, - strict: [ - force: :boolean, - path: :string - ], - aliases: [ - p: :path, - f: :force - ] - ) - - file_path = - get_option( - options, - :path, - "Environment file path", - "./config/pleroma.env" - ) - - env_path = Path.expand(file_path) - - proceed? = - if File.exists?(env_path) do - get_option( - options, - :force, - "Environment file already exists. Do you want to overwrite the #{env_path} file? (y/n)", - "n" - ) === "y" - else - true - end - - if proceed? do - case do_generate(env_path) do - {:error, reason} -> - shell_error( - File.Error.message(%{action: "write to file", reason: reason, path: env_path}) - ) - - _ -> - shell_info("\nThe file generated: #{env_path}.\n") - - shell_info(""" - WARNING: before start pleroma app please make sure to make the file read-only and non-modifiable. - Example: - chmod 0444 #{file_path} - chattr +i #{file_path} - """) - end - else - shell_info("\nThe file is exist. #{env_path}.\n") - end - end - - def do_generate(path) do - content = "RELEASE_COOKIE=#{Base.encode32(:crypto.strong_rand_bytes(32))}" - - File.mkdir_p!(Path.dirname(path)) - File.write(path, content) - end -end diff --git a/test/tasks/release_env_test.exs b/test/tasks/release_env_test.exs deleted file mode 100644 index 519f1eba9..000000000 --- a/test/tasks/release_env_test.exs +++ /dev/null @@ -1,30 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Mix.Tasks.Pleroma.ReleaseEnvTest do - use ExUnit.Case - import ExUnit.CaptureIO, only: [capture_io: 1] - - @path "config/pleroma.test.env" - - def do_clean do - if File.exists?(@path) do - File.rm_rf(@path) - end - end - - setup do - do_clean() - on_exit(fn -> do_clean() end) - :ok - end - - test "generate pleroma.env" do - assert capture_io(fn -> - Mix.Tasks.Pleroma.ReleaseEnv.run(["gen", "--path", @path, "--force"]) - end) =~ "The file generated" - - assert File.read!(@path) =~ "RELEASE_COOKIE=" - end -end -- cgit v1.2.3 From 4d76c0ec8b24d7bc91a9e432a0cf3be17c6c10b5 Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 10 Aug 2020 15:12:45 +0200 Subject: Docs: Add cmake dependency --- docs/installation/debian_based_en.md | 3 ++- docs/installation/debian_based_jp.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/installation/debian_based_en.md b/docs/installation/debian_based_en.md index 8ae5044b5..60c2f47e5 100644 --- a/docs/installation/debian_based_en.md +++ b/docs/installation/debian_based_en.md @@ -12,6 +12,7 @@ This guide will assume you are on Debian Stretch. This guide should also work wi * `erlang-nox` * `git` * `build-essential` +* `cmake` #### Optional packages used in this guide @@ -30,7 +31,7 @@ sudo apt full-upgrade * Install some of the above mentioned programs: ```shell -sudo apt install git build-essential postgresql postgresql-contrib +sudo apt install git build-essential postgresql postgresql-contrib cmake ``` ### Install Elixir and Erlang diff --git a/docs/installation/debian_based_jp.md b/docs/installation/debian_based_jp.md index 42e91cda7..c2dd840d3 100644 --- a/docs/installation/debian_based_jp.md +++ b/docs/installation/debian_based_jp.md @@ -16,6 +16,7 @@ - `erlang-nox` - `git` - `build-essential` +- `cmake` #### このガイドで利用している追加パッケージ @@ -32,7 +33,7 @@ sudo apt full-upgrade * 上記に挙げたパッケージをインストールしておきます。 ``` -sudo apt install git build-essential postgresql postgresql-contrib +sudo apt install git build-essential postgresql postgresql-contrib cmake ``` -- cgit v1.2.3 From a2f2ba3fbbc9788b16e7d62044756b99fa0c45e1 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Mon, 10 Aug 2020 16:24:45 +0300 Subject: docs: add cmake to other installation guides --- docs/installation/alpine_linux_en.md | 3 ++- docs/installation/arch_linux_en.md | 3 ++- docs/installation/gentoo_en.md | 3 ++- docs/installation/netbsd_en.md | 1 + docs/installation/openbsd_en.md | 3 ++- docs/installation/openbsd_fi.md | 2 +- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/installation/alpine_linux_en.md b/docs/installation/alpine_linux_en.md index c726d559f..a5683f18c 100644 --- a/docs/installation/alpine_linux_en.md +++ b/docs/installation/alpine_linux_en.md @@ -14,6 +14,7 @@ It assumes that you have administrative rights, either as root or a user with [s * `erlang-xmerl` * `git` * Development Tools +* `cmake` #### Optional packages used in this guide @@ -39,7 +40,7 @@ sudo apk upgrade * Install some tools, which are needed later: ```shell -sudo apk add git build-base +sudo apk add git build-base cmake ``` ### Install Elixir and Erlang diff --git a/docs/installation/arch_linux_en.md b/docs/installation/arch_linux_en.md index bf9cfb488..7fb69dd60 100644 --- a/docs/installation/arch_linux_en.md +++ b/docs/installation/arch_linux_en.md @@ -9,6 +9,7 @@ This guide will assume that you have administrative rights, either as root or a * `elixir` * `git` * `base-devel` +* `cmake` #### Optional packages used in this guide @@ -26,7 +27,7 @@ sudo pacman -Syu * Install some of the above mentioned programs: ```shell -sudo pacman -S git base-devel elixir +sudo pacman -S git base-devel elixir cmake ``` ### Install PostgreSQL diff --git a/docs/installation/gentoo_en.md b/docs/installation/gentoo_en.md index 32152aea7..5a676380c 100644 --- a/docs/installation/gentoo_en.md +++ b/docs/installation/gentoo_en.md @@ -28,6 +28,7 @@ Gentoo quite pointedly does not come with a cron daemon installed, and as such i * `dev-db/postgresql` * `dev-lang/elixir` * `dev-vcs/git` +* `dev-util/cmake` #### Optional ebuilds used in this guide @@ -46,7 +47,7 @@ Gentoo quite pointedly does not come with a cron daemon installed, and as such i * Emerge all required the required and suggested software in one go: ```shell - # emerge --ask dev-db/postgresql dev-lang/elixir dev-vcs/git www-servers/nginx app-crypt/certbot app-crypt/certbot-nginx + # emerge --ask dev-db/postgresql dev-lang/elixir dev-vcs/git www-servers/nginx app-crypt/certbot app-crypt/certbot-nginx dev-util/cmake ``` If you would not like to install the optional packages, remove them from this line. diff --git a/docs/installation/netbsd_en.md b/docs/installation/netbsd_en.md index 3626acc69..6ad0de2f6 100644 --- a/docs/installation/netbsd_en.md +++ b/docs/installation/netbsd_en.md @@ -19,6 +19,7 @@ databases/postgresql11-client databases/postgresql11-server devel/git-base devel/git-docs +devel/cmake lang/elixir security/acmesh security/sudo diff --git a/docs/installation/openbsd_en.md b/docs/installation/openbsd_en.md index 5dbe24f75..eee452845 100644 --- a/docs/installation/openbsd_en.md +++ b/docs/installation/openbsd_en.md @@ -14,11 +14,12 @@ The following packages need to be installed: * git * postgresql-server * postgresql-contrib + * cmake To install them, run the following command (with doas or as root): ``` -pkg_add elixir gmake ImageMagick git postgresql-server postgresql-contrib +pkg_add elixir gmake ImageMagick git postgresql-server postgresql-contrib cmake ``` Pleroma requires a reverse proxy, OpenBSD has relayd in base (and is used in this guide) and packages/ports are available for nginx (www/nginx) and apache (www/apache-httpd). Independently of the reverse proxy, [acme-client(1)](https://man.openbsd.org/acme-client) can be used to get a certificate from Let's Encrypt. diff --git a/docs/installation/openbsd_fi.md b/docs/installation/openbsd_fi.md index 272273cff..b5b5056a9 100644 --- a/docs/installation/openbsd_fi.md +++ b/docs/installation/openbsd_fi.md @@ -16,7 +16,7 @@ Matrix-kanava #freenode_#pleroma:matrix.org ovat hyviä paikkoja löytää apua Asenna tarvittava ohjelmisto: -`# pkg_add git elixir gmake postgresql-server-10.3 postgresql-contrib-10.3` +`# pkg_add git elixir gmake postgresql-server-10.3 postgresql-contrib-10.3 cmake` Luo postgresql-tietokanta: -- cgit v1.2.3 From 11fc90744c89097969a94d2accaa8f97cb1bbd7d Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 10 Aug 2020 15:31:36 +0200 Subject: Transmogrifier: Remove duplicate code. --- lib/pleroma/web/activity_pub/transmogrifier.ex | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 7381d4476..2f04cc6ff 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -644,16 +644,6 @@ def handle_incoming( end end - def handle_incoming( - %{"type" => "Create", "object" => %{"type" => "ChatMessage"}} = data, - _options - ) do - with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), - {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do - {:ok, activity} - end - end - def handle_incoming(%{"type" => type} = data, _options) when type in ~w{Like EmojiReact Announce} do with :ok <- ObjectValidator.fetch_actor_and_object(data), -- cgit v1.2.3 From 249f21dcbbbc20f401a9ea9bfc6179c858abce6f Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Mon, 10 Aug 2020 17:57:36 +0400 Subject: Admin API: Filter out unapproved users when the `active` filter is on --- lib/pleroma/user/query.ex | 1 + .../controllers/admin_api_controller_test.exs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 45553cb6c..d618432ff 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -130,6 +130,7 @@ defp compose_query({:external, _}, query), do: location_query(query, false) defp compose_query({:active, _}, query) do User.restrict_deactivated(query) |> where([u], not is_nil(u.nickname)) + |> where([u], u.approval_pending == false) end defp compose_query({:legacy_active, _}, query) do diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index b5d5bd8c7..7f0f02605 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -1164,6 +1164,27 @@ test "load users with tags list", %{conn: conn} do } end + test "`active` filters out users pending approval", %{token: token} do + insert(:user, approval_pending: true) + %{id: user_id} = insert(:user, approval_pending: false) + %{id: admin_id} = token.user + + conn = + build_conn() + |> assign(:user, token.user) + |> assign(:token, token) + |> get("/api/pleroma/admin/users?filters=active") + + assert %{ + "count" => 2, + "page_size" => 50, + "users" => [ + %{"id" => ^admin_id}, + %{"id" => ^user_id} + ] + } = json_response(conn, 200) + end + test "it works with multiple filters" do admin = insert(:user, nickname: "john", is_admin: true) token = insert(:oauth_admin_token, user: admin) -- cgit v1.2.3 From 345ac512e43fbb127c45552690741088d465d31d Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Tue, 11 Aug 2020 10:28:35 +0300 Subject: added paginate+search for admin/MediaProxy URLs --- .../controllers/media_proxy_cache_controller.ex | 41 +++++++----- .../web/admin_api/views/media_proxy_cache_view.ex | 8 ++- .../admin/media_proxy_cache_operation.ex | 47 ++++++++------ lib/pleroma/web/media_proxy/media_proxy.ex | 13 ++-- .../media_proxy_cache_controller_test.exs | 72 ++++++++++++++-------- 5 files changed, 114 insertions(+), 67 deletions(-) diff --git a/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex b/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex index e2759d59f..76d3af4ef 100644 --- a/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex @@ -26,29 +26,38 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do defdelegate open_api_operation(action), to: Spec.MediaProxyCacheOperation def index(%{assigns: %{user: _}} = conn, params) do - cursor = - :banned_urls_cache - |> :ets.table([{:traverse, {:select, Cachex.Query.create(true, :key)}}]) - |> :qlc.cursor() + entries = fetch_entries(params) + urls = paginate_entries(entries, params.page, params.page_size) + + render(conn, "index.json", + urls: urls, + page_size: params.page_size, + count: length(entries) + ) + end - urls = - case params.page do - 1 -> - :qlc.next_answers(cursor, params.page_size) + defp fetch_entries(params) do + MediaProxy.cache_table() + |> Cachex.export!() + |> filter_urls(params[:query]) + end - _ -> - :qlc.next_answers(cursor, (params.page - 1) * params.page_size) - :qlc.next_answers(cursor, params.page_size) - end + defp filter_urls(entries, query) when is_binary(query) do + for {_, url, _, _, _} <- entries, String.contains?(url, query), do: url + end - :qlc.delete_cursor(cursor) + defp filter_urls(entries, _) do + Enum.map(entries, fn {_, url, _, _, _} -> url end) + end - render(conn, "index.json", urls: urls) + defp paginate_entries(entries, page, page_size) do + offset = page_size * (page - 1) + Enum.slice(entries, offset, page_size) end def delete(%{assigns: %{user: _}, body_params: %{urls: urls}} = conn, _) do MediaProxy.remove_from_banned_urls(urls) - render(conn, "index.json", urls: urls) + json(conn, %{}) end def purge(%{assigns: %{user: _}, body_params: %{urls: urls, ban: ban}} = conn, _) do @@ -58,6 +67,6 @@ def purge(%{assigns: %{user: _}, body_params: %{urls: urls, ban: ban}} = conn, _ MediaProxy.put_in_banned_urls(urls) end - render(conn, "index.json", urls: urls) + json(conn, %{}) end end diff --git a/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex b/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex index c97400beb..a803bda0b 100644 --- a/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex +++ b/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex @@ -5,7 +5,11 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheView do use Pleroma.Web, :view - def render("index.json", %{urls: urls}) do - %{urls: urls} + def render("index.json", %{urls: urls, page_size: page_size, count: count}) do + %{ + urls: urls, + count: count, + page_size: page_size + } end end diff --git a/lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex b/lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex index 20d033f66..ab45d6633 100644 --- a/lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex +++ b/lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex @@ -21,6 +21,12 @@ def index_operation do operationId: "AdminAPI.MediaProxyCacheController.index", security: [%{"oAuth" => ["read:media_proxy_caches"]}], parameters: [ + Operation.parameter( + :query, + :query, + %Schema{type: :string, default: nil}, + "Page" + ), Operation.parameter( :page, :query, @@ -36,7 +42,26 @@ def index_operation do | admin_api_params() ], responses: %{ - 200 => success_response() + 200 => + Operation.response( + "Array of banned MediaProxy URLs in Cachex", + "application/json", + %Schema{ + type: :object, + properties: %{ + count: %Schema{type: :integer}, + page_size: %Schema{type: :integer}, + urls: %Schema{ + type: :array, + items: %Schema{ + type: :string, + format: :uri, + description: "MediaProxy URLs" + } + } + } + } + ) } } end @@ -61,7 +86,7 @@ def delete_operation do required: true ), responses: %{ - 200 => success_response(), + 200 => empty_object_response(), 400 => Operation.response("Error", "application/json", ApiError) } } @@ -88,25 +113,9 @@ def purge_operation do required: true ), responses: %{ - 200 => success_response(), + 200 => empty_object_response(), 400 => Operation.response("Error", "application/json", ApiError) } } end - - defp success_response do - Operation.response("Array of banned MediaProxy URLs in Cachex", "application/json", %Schema{ - type: :object, - properties: %{ - urls: %Schema{ - type: :array, - items: %Schema{ - type: :string, - format: :uri, - description: "MediaProxy URLs" - } - } - } - }) - end end diff --git a/lib/pleroma/web/media_proxy/media_proxy.ex b/lib/pleroma/web/media_proxy/media_proxy.ex index dfbfcea6b..e18dd8224 100644 --- a/lib/pleroma/web/media_proxy/media_proxy.ex +++ b/lib/pleroma/web/media_proxy/media_proxy.ex @@ -9,28 +9,31 @@ defmodule Pleroma.Web.MediaProxy do alias Pleroma.Web.MediaProxy.Invalidation @base64_opts [padding: false] + @cache_table :banned_urls_cache + + def cache_table, do: @cache_table @spec in_banned_urls(String.t()) :: boolean() - def in_banned_urls(url), do: elem(Cachex.exists?(:banned_urls_cache, url(url)), 1) + def in_banned_urls(url), do: elem(Cachex.exists?(@cache_table, url(url)), 1) def remove_from_banned_urls(urls) when is_list(urls) do - Cachex.execute!(:banned_urls_cache, fn cache -> + Cachex.execute!(@cache_table, fn cache -> Enum.each(Invalidation.prepare_urls(urls), &Cachex.del(cache, &1)) end) end def remove_from_banned_urls(url) when is_binary(url) do - Cachex.del(:banned_urls_cache, url(url)) + Cachex.del(@cache_table, url(url)) end def put_in_banned_urls(urls) when is_list(urls) do - Cachex.execute!(:banned_urls_cache, fn cache -> + Cachex.execute!(@cache_table, fn cache -> Enum.each(Invalidation.prepare_urls(urls), &Cachex.put(cache, &1, true)) end) end def put_in_banned_urls(url) when is_binary(url) do - Cachex.put(:banned_urls_cache, url(url), true) + Cachex.put(@cache_table, url(url), true) end def url(url) when is_nil(url) or url == "", do: nil diff --git a/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs b/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs index 5ab6cb78a..3cf98d7c7 100644 --- a/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs +++ b/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs @@ -48,6 +48,9 @@ test "shows banned MediaProxy URLs", %{conn: conn} do |> get("/api/pleroma/admin/media_proxy_caches?page_size=2") |> json_response_and_validate_schema(200) + assert response["page_size"] == 2 + assert response["count"] == 5 + assert response["urls"] == [ "http://localhost:4001/media/fb1f4d.jpg", "http://localhost:4001/media/a688346.jpg" @@ -63,6 +66,9 @@ test "shows banned MediaProxy URLs", %{conn: conn} do "http://localhost:4001/media/tb13f47.jpg" ] + assert response["page_size"] == 2 + assert response["count"] == 5 + response = conn |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=3") @@ -70,6 +76,30 @@ test "shows banned MediaProxy URLs", %{conn: conn} do assert response["urls"] == ["http://localhost:4001/media/wb1f46.jpg"] end + + test "search banned MediaProxy URLs", %{conn: conn} do + MediaProxy.put_in_banned_urls([ + "http://localhost:4001/media/a688346.jpg", + "http://localhost:4001/media/ff44b1f4d.jpg" + ]) + + MediaProxy.put_in_banned_urls("http://localhost:4001/media/gb1f44.jpg") + MediaProxy.put_in_banned_urls("http://localhost:4001/media/tb13f47.jpg") + MediaProxy.put_in_banned_urls("http://localhost:4001/media/wb1f46.jpg") + + response = + conn + |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&query=f44") + |> json_response_and_validate_schema(200) + + assert response["urls"] == [ + "http://localhost:4001/media/gb1f44.jpg", + "http://localhost:4001/media/ff44b1f4d.jpg" + ] + + assert response["page_size"] == 2 + assert response["count"] == 2 + end end describe "POST /api/pleroma/admin/media_proxy_caches/delete" do @@ -79,15 +109,13 @@ test "deleted MediaProxy URLs from banned", %{conn: conn} do "http://localhost:4001/media/fb1f4d.jpg" ]) - response = - conn - |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/media_proxy_caches/delete", %{ - urls: ["http://localhost:4001/media/a688346.jpg"] - }) - |> json_response_and_validate_schema(200) + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/media_proxy_caches/delete", %{ + urls: ["http://localhost:4001/media/a688346.jpg"] + }) + |> json_response_and_validate_schema(200) - assert response["urls"] == ["http://localhost:4001/media/a688346.jpg"] refute MediaProxy.in_banned_urls("http://localhost:4001/media/a688346.jpg") assert MediaProxy.in_banned_urls("http://localhost:4001/media/fb1f4d.jpg") end @@ -106,13 +134,10 @@ test "perform invalidates cache of MediaProxy", %{conn: conn} do purge: fn _, _ -> {"ok", 0} end ]} ] do - response = - conn - |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/media_proxy_caches/purge", %{urls: urls, ban: false}) - |> json_response_and_validate_schema(200) - - assert response["urls"] == urls + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/media_proxy_caches/purge", %{urls: urls, ban: false}) + |> json_response_and_validate_schema(200) refute MediaProxy.in_banned_urls("http://example.com/media/a688346.jpg") refute MediaProxy.in_banned_urls("http://example.com/media/fb1f4d.jpg") @@ -126,16 +151,13 @@ test "perform invalidates cache of MediaProxy and adds url to banned", %{conn: c ] with_mocks [{MediaProxy.Invalidation.Script, [], [purge: fn _, _ -> {"ok", 0} end]}] do - response = - conn - |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/media_proxy_caches/purge", %{ - urls: urls, - ban: true - }) - |> json_response_and_validate_schema(200) - - assert response["urls"] == urls + conn + |> put_req_header("content-type", "application/json") + |> post( + "/api/pleroma/admin/media_proxy_caches/purge", + %{urls: urls, ban: true} + ) + |> json_response_and_validate_schema(200) assert MediaProxy.in_banned_urls("http://example.com/media/a688346.jpg") assert MediaProxy.in_banned_urls("http://example.com/media/fb1f4d.jpg") -- cgit v1.2.3 From 7e4932362b7e672b08543cfd189deb3776268fe3 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 10:54:38 +0200 Subject: SideEffects: Handle strange deletion case. --- lib/pleroma/web/activity_pub/side_effects.ex | 12 ++++++++++-- test/web/activity_pub/side_effects_test.exs | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 5104d38ee..bff7c6629 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -22,6 +22,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do alias Pleroma.Web.Streamer alias Pleroma.Workers.BackgroundWorker + require Logger + def handle(object, meta \\ []) # Tasks this handle @@ -217,13 +219,15 @@ def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do # - Stream out the activity def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do deleted_object = - Object.normalize(deleted_object, false) || User.get_cached_by_ap_id(deleted_object) + Object.normalize(deleted_object, false) || + User.get_cached_by_ap_id(deleted_object) result = case deleted_object do %Object{} -> with {:ok, deleted_object, activity} <- Object.delete(deleted_object), - %User{} = user <- User.get_cached_by_ap_id(deleted_object.data["actor"]) do + {_, actor} when is_binary(actor) <- {:actor, deleted_object.data["actor"]}, + %User{} = user <- User.get_cached_by_ap_id(actor) do User.remove_pinnned_activity(user, activity) {:ok, user} = ActivityPub.decrease_note_count_if_public(user, deleted_object) @@ -237,6 +241,10 @@ def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, ActivityPub.stream_out(object) ActivityPub.stream_out_participations(deleted_object, user) :ok + else + {:actor, _} -> + Logger.error("The object doesn't have an actor: #{inspect(deleted_object)}") + :no_object_actor end %User{} -> diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index 4a08eb7ee..9efbaad04 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -19,8 +19,9 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do alias Pleroma.Web.ActivityPub.SideEffects alias Pleroma.Web.CommonAPI - import Pleroma.Factory + import ExUnit.CaptureLog import Mock + import Pleroma.Factory describe "handle_after_transaction" do test "it streams out notifications and streams" do @@ -221,6 +222,22 @@ test "it handles user deletions", %{delete_user: delete, user: user} do assert User.get_cached_by_ap_id(user.ap_id).deactivated end + + test "it logs issues with objects deletion", %{ + delete: delete, + object: object + } do + {:ok, object} = + object + |> Object.change(%{data: Map.delete(object.data, "actor")}) + |> Repo.update() + + Object.invalid_object_cache(object) + + assert capture_log(fn -> + {:error, :no_object_actor} = SideEffects.handle(delete) + end) =~ "object doesn't have an actor" + end end describe "EmojiReact objects" do -- cgit v1.2.3 From 9a9121805ceccfa62c77e9abc81af5f7c7fd4049 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 09:08:27 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- test/support/conn_case.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index b50ff1bcc..7ef681258 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -58,7 +58,7 @@ defp request_content_type(%{conn: conn}) do defp empty_json_response(conn) do body = response(conn, 204) - _ = response_content_type(conn, :json) + response_content_type(conn, :json) body end -- cgit v1.2.3 From 54a6855ddfb4b47b91b8fe2c184bbca3dbc2884d Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 14:00:21 +0200 Subject: Transmogrifier Tests: Extract Accept handling --- .../transmogrifier/accept_handling_test.exs | 113 +++++++++++++++++++++ test/web/activity_pub/transmogrifier_test.exs | 102 +------------------ 2 files changed, 114 insertions(+), 101 deletions(-) create mode 100644 test/web/activity_pub/transmogrifier/accept_handling_test.exs diff --git a/test/web/activity_pub/transmogrifier/accept_handling_test.exs b/test/web/activity_pub/transmogrifier/accept_handling_test.exs new file mode 100644 index 000000000..3c4e134ff --- /dev/null +++ b/test/web/activity_pub/transmogrifier/accept_handling_test.exs @@ -0,0 +1,113 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.AcceptHandlingTest do + use Pleroma.DataCase + + alias Pleroma.User + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + test "it works for incoming accepts which were pre-accepted" do + follower = insert(:user) + followed = insert(:user) + + {:ok, follower} = User.follow(follower, followed) + assert User.following?(follower, followed) == true + + {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) + + accept_data = + File.read!("test/fixtures/mastodon-accept-activity.json") + |> Poison.decode!() + |> Map.put("actor", followed.ap_id) + + object = + accept_data["object"] + |> Map.put("actor", follower.ap_id) + |> Map.put("id", follow_activity.data["id"]) + + accept_data = Map.put(accept_data, "object", object) + + {:ok, activity} = Transmogrifier.handle_incoming(accept_data) + refute activity.local + + assert activity.data["object"] == follow_activity.data["id"] + + assert activity.data["id"] == accept_data["id"] + + follower = User.get_cached_by_id(follower.id) + + assert User.following?(follower, followed) == true + end + + test "it works for incoming accepts which were orphaned" do + follower = insert(:user) + followed = insert(:user, locked: true) + + {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) + + accept_data = + File.read!("test/fixtures/mastodon-accept-activity.json") + |> Poison.decode!() + |> Map.put("actor", followed.ap_id) + + accept_data = + Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) + + {:ok, activity} = Transmogrifier.handle_incoming(accept_data) + assert activity.data["object"] == follow_activity.data["id"] + + follower = User.get_cached_by_id(follower.id) + + assert User.following?(follower, followed) == true + end + + test "it works for incoming accepts which are referenced by IRI only" do + follower = insert(:user) + followed = insert(:user, locked: true) + + {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) + + accept_data = + File.read!("test/fixtures/mastodon-accept-activity.json") + |> Poison.decode!() + |> Map.put("actor", followed.ap_id) + |> Map.put("object", follow_activity.data["id"]) + + {:ok, activity} = Transmogrifier.handle_incoming(accept_data) + assert activity.data["object"] == follow_activity.data["id"] + + follower = User.get_cached_by_id(follower.id) + + assert User.following?(follower, followed) == true + + follower = User.get_by_id(follower.id) + assert follower.following_count == 1 + + followed = User.get_by_id(followed.id) + assert followed.follower_count == 1 + end + + test "it fails for incoming accepts which cannot be correlated" do + follower = insert(:user) + followed = insert(:user, locked: true) + + accept_data = + File.read!("test/fixtures/mastodon-accept-activity.json") + |> Poison.decode!() + |> Map.put("actor", followed.ap_id) + + accept_data = + Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) + + :error = Transmogrifier.handle_incoming(accept_data) + + follower = User.get_cached_by_id(follower.id) + + refute User.following?(follower, followed) == true + end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 6dd9a3fec..52b4178bf 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -359,7 +359,7 @@ test "it strips internal reactions" do refute Map.has_key?(object_data, "reaction_count") end - test "it works for incomming unfollows with an existing follow" do + test "it works for incoming unfollows with an existing follow" do user = insert(:user) follow_data = @@ -403,106 +403,6 @@ test "it works for incoming follows to locked account" do assert [^pending_follower] = User.get_follow_requests(user) end - test "it works for incoming accepts which were pre-accepted" do - follower = insert(:user) - followed = insert(:user) - - {:ok, follower} = User.follow(follower, followed) - assert User.following?(follower, followed) == true - - {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - - accept_data = - File.read!("test/fixtures/mastodon-accept-activity.json") - |> Poison.decode!() - |> Map.put("actor", followed.ap_id) - - object = - accept_data["object"] - |> Map.put("actor", follower.ap_id) - |> Map.put("id", follow_activity.data["id"]) - - accept_data = Map.put(accept_data, "object", object) - - {:ok, activity} = Transmogrifier.handle_incoming(accept_data) - refute activity.local - - assert activity.data["object"] == follow_activity.data["id"] - - assert activity.data["id"] == accept_data["id"] - - follower = User.get_cached_by_id(follower.id) - - assert User.following?(follower, followed) == true - end - - test "it works for incoming accepts which were orphaned" do - follower = insert(:user) - followed = insert(:user, locked: true) - - {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - - accept_data = - File.read!("test/fixtures/mastodon-accept-activity.json") - |> Poison.decode!() - |> Map.put("actor", followed.ap_id) - - accept_data = - Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - - {:ok, activity} = Transmogrifier.handle_incoming(accept_data) - assert activity.data["object"] == follow_activity.data["id"] - - follower = User.get_cached_by_id(follower.id) - - assert User.following?(follower, followed) == true - end - - test "it works for incoming accepts which are referenced by IRI only" do - follower = insert(:user) - followed = insert(:user, locked: true) - - {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - - accept_data = - File.read!("test/fixtures/mastodon-accept-activity.json") - |> Poison.decode!() - |> Map.put("actor", followed.ap_id) - |> Map.put("object", follow_activity.data["id"]) - - {:ok, activity} = Transmogrifier.handle_incoming(accept_data) - assert activity.data["object"] == follow_activity.data["id"] - - follower = User.get_cached_by_id(follower.id) - - assert User.following?(follower, followed) == true - - follower = User.get_by_id(follower.id) - assert follower.following_count == 1 - - followed = User.get_by_id(followed.id) - assert followed.follower_count == 1 - end - - test "it fails for incoming accepts which cannot be correlated" do - follower = insert(:user) - followed = insert(:user, locked: true) - - accept_data = - File.read!("test/fixtures/mastodon-accept-activity.json") - |> Poison.decode!() - |> Map.put("actor", followed.ap_id) - - accept_data = - Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - - :error = Transmogrifier.handle_incoming(accept_data) - - follower = User.get_cached_by_id(follower.id) - - refute User.following?(follower, followed) == true - end - test "it fails for incoming rejects which cannot be correlated" do follower = insert(:user) followed = insert(:user, locked: true) -- cgit v1.2.3 From 8f9fbc86c0dcf307b87b38d218b36df2f9f35a7f Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 14:02:09 +0200 Subject: Transmogrifier: Small readability changes. --- lib/pleroma/web/activity_pub/transmogrifier.ex | 6 ++++-- test/web/activity_pub/transmogrifier/undo_handling_test.exs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 2f04cc6ff..fe016e720 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -661,7 +661,8 @@ def handle_incoming( ) when type in ~w{Update Block Follow} do with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), - {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do + {:ok, activity, _} <- + Pipeline.common_pipeline(data, local: false) do {:ok, activity} end end @@ -670,7 +671,8 @@ def handle_incoming( %{"type" => "Delete"} = data, _options ) do - with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do + with {:ok, activity, _} <- + Pipeline.common_pipeline(data, local: false) do {:ok, activity} else {:error, {:validate_object, _}} = e -> diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs index 01dd6c370..8683f7135 100644 --- a/test/web/activity_pub/transmogrifier/undo_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/undo_handling_test.exs @@ -130,7 +130,7 @@ test "it works for incoming unannounces with an existing notice" do "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" end - test "it works for incomming unfollows with an existing follow" do + test "it works for incoming unfollows with an existing follow" do user = insert(:user) follow_data = -- cgit v1.2.3 From f1a0c10b17ff20a5ebbd070dc38aaedf82f8fe2e Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 15:13:07 +0200 Subject: AcceptValidator: Add basic validator with tests. --- lib/pleroma/web/activity_pub/builder.ex | 13 +++++++ lib/pleroma/web/activity_pub/object_validator.ex | 11 ++++++ .../object_validators/accept_validator.ex | 42 +++++++++++++++++++++ .../object_validators/accept_validation_test.exs | 44 ++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 lib/pleroma/web/activity_pub/object_validators/accept_validator.ex create mode 100644 test/web/activity_pub/object_validators/accept_validation_test.exs diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index 1b4c421b8..e1f88e6cc 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -14,6 +14,19 @@ defmodule Pleroma.Web.ActivityPub.Builder do require Pleroma.Constants + @spec accept(User.t(), Activity.t()) :: {:ok, map(), keyword()} + def accept(actor, accepted_activity) do + data = %{ + "id" => Utils.generate_activity_id(), + "actor" => actor.ap_id, + "type" => "Accept", + "object" => accepted_activity.data["id"], + "to" => [accepted_activity.actor] + } + + {:ok, data, []} + end + @spec follow(User.t(), User.t()) :: {:ok, map(), keyword()} def follow(follower, followed) do data = %{ diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index e1114a44d..d9dd2bc30 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Object alias Pleroma.User + alias Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator @@ -30,6 +31,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do @spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()} def validate(object, meta) + def validate(%{"type" => "Accept"} = object, meta) do + with {:ok, object} <- + object + |> AcceptValidator.cast_and_validate() + |> Ecto.Changeset.apply_action(:insert) do + object = stringify_keys(object) + {:ok, object, meta} + end + end + def validate(%{"type" => "Follow"} = object, meta) do with {:ok, object} <- object diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex new file mode 100644 index 000000000..b81e078e3 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex @@ -0,0 +1,42 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidator do + use Ecto.Schema + + alias Pleroma.EctoType.ActivityPub.ObjectValidators + + import Ecto.Changeset + import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + + @primary_key false + + embedded_schema do + field(:id, ObjectValidators.ObjectID, primary_key: true) + field(:type, :string) + field(:object, ObjectValidators.ObjectID) + field(:actor, ObjectValidators.ObjectID) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + end + + def cast_data(data) do + %__MODULE__{} + |> cast(data, __schema__(:fields)) + end + + def validate_data(cng) do + cng + |> validate_required([:id, :type, :actor, :to, :cc, :object]) + |> validate_inclusion(:type, ["Accept"]) + |> validate_actor_presence() + |> validate_object_presence() + end + + def cast_and_validate(data) do + data + |> cast_data + |> validate_data + end +end diff --git a/test/web/activity_pub/object_validators/accept_validation_test.exs b/test/web/activity_pub/object_validators/accept_validation_test.exs new file mode 100644 index 000000000..7f5dc14af --- /dev/null +++ b/test/web/activity_pub/object_validators/accept_validation_test.exs @@ -0,0 +1,44 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidationTest do + use Pleroma.DataCase + alias Pleroma.Web.ActivityPub.Builder + alias Pleroma.Web.ActivityPub.Pipeline + alias Pleroma.Web.ActivityPub.ObjectValidator + + import Pleroma.Factory + + setup do + follower = insert(:user) + followed = insert(:user, local: false) + + {:ok, follow_data, _} = Builder.follow(follower, followed) + {:ok, follow_activity, _} = Pipeline.common_pipeline(follow_data, local: true) + + {:ok, accept_data, _} = Builder.accept(followed, follow_activity) + + %{accept_data: accept_data, followed: followed} + end + + test "it validates a basic 'accept'", %{accept_data: accept_data} do + assert {:ok, _, _} = ObjectValidator.validate(accept_data, []) + end + + test "it fails when the actor doesn't exist", %{accept_data: accept_data} do + accept_data = + accept_data + |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") + + assert {:error, _} = ObjectValidator.validate(accept_data, []) + end + + test "it fails when the accepted activity doesn't exist", %{accept_data: accept_data} do + accept_data = + accept_data + |> Map.put("object", "https://gensokyo.2hu/users/raymoo/follows/1") + + assert {:error, _} = ObjectValidator.validate(accept_data, []) + end +end -- cgit v1.2.3 From 304ed357436522f73036c912eaaa8d8e38e1d469 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 11 Aug 2020 17:21:17 +0400 Subject: Set `users.approval_pending` default to `false` --- ...200811125613_set_defaults_to_user_approval_pending.exs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 priv/repo/migrations/20200811125613_set_defaults_to_user_approval_pending.exs diff --git a/priv/repo/migrations/20200811125613_set_defaults_to_user_approval_pending.exs b/priv/repo/migrations/20200811125613_set_defaults_to_user_approval_pending.exs new file mode 100644 index 000000000..eec7da03f --- /dev/null +++ b/priv/repo/migrations/20200811125613_set_defaults_to_user_approval_pending.exs @@ -0,0 +1,15 @@ +defmodule Pleroma.Repo.Migrations.SetDefaultsToUserApprovalPending do + use Ecto.Migration + + def up do + execute("UPDATE users SET approval_pending = false WHERE approval_pending IS NULL") + + alter table(:users) do + modify(:approval_pending, :boolean, default: false, null: false) + end + end + + def down do + :ok + end +end -- cgit v1.2.3 From 8b1e8bec2ffcb3a73eea93015d73b44c4996baff Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 15:32:00 +0200 Subject: AcceptValidation: Codify accept rules. --- .../activity_pub/object_validators/accept_validator.ex | 16 +++++++++++++++- .../object_validators/accept_validation_test.exs | 11 +++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex index b81e078e3..6d0fa669a 100644 --- a/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidator do use Ecto.Schema alias Pleroma.EctoType.ActivityPub.ObjectValidators + alias Pleroma.Activity import Ecto.Changeset import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations @@ -31,7 +32,8 @@ def validate_data(cng) do |> validate_required([:id, :type, :actor, :to, :cc, :object]) |> validate_inclusion(:type, ["Accept"]) |> validate_actor_presence() - |> validate_object_presence() + |> validate_object_presence(allowed_types: ["Follow"]) + |> validate_accept_rights() end def cast_and_validate(data) do @@ -39,4 +41,16 @@ def cast_and_validate(data) do |> cast_data |> validate_data end + + def validate_accept_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 + cng + else + _e -> + cng + |> add_error(:actor, "can't accept the given activity") + end + end end diff --git a/test/web/activity_pub/object_validators/accept_validation_test.exs b/test/web/activity_pub/object_validators/accept_validation_test.exs index 7f5dc14af..2d5d18046 100644 --- a/test/web/activity_pub/object_validators/accept_validation_test.exs +++ b/test/web/activity_pub/object_validators/accept_validation_test.exs @@ -41,4 +41,15 @@ test "it fails when the accepted activity doesn't exist", %{accept_data: accept_ assert {:error, _} = ObjectValidator.validate(accept_data, []) end + + test "for an accepted follow, it only validates if the actor of the accept is the followed actor", + %{accept_data: accept_data} do + stranger = insert(:user) + + accept_data = + accept_data + |> Map.put("actor", stranger.ap_id) + + assert {:error, _} = ObjectValidator.validate(accept_data, []) + end end -- cgit v1.2.3 From da3f9b9988d2cee4baa6018e6450b2d6027e1ce3 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 15:41:19 +0200 Subject: Transmogrifier: Remove handling of orphaned accepts This was a Mastodon 2.3 issue and has been fixed for a long time. According to fediverse.networks, less than one percent of servers still run a version this old or older. --- lib/pleroma/web/activity_pub/transmogrifier.ex | 18 +----------------- .../transmogrifier/accept_handling_test.exs | 22 ---------------------- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index fe016e720..5ea97e9b7 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -391,27 +391,11 @@ defp fix_content(%{"mediaType" => "text/markdown", "content" => content} = objec defp fix_content(object), do: object - defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do - with true <- id =~ "follows", - %User{local: true} = follower <- User.get_cached_by_ap_id(follower_id), - %Activity{} = activity <- Utils.fetch_latest_follow(follower, followed) do - {:ok, activity} - else - _ -> {:error, nil} - end - end - - defp mastodon_follow_hack(_, _), do: {:error, nil} - - defp get_follow_activity(follow_object, followed) do + defp get_follow_activity(follow_object, _followed) do with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object), {_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do {:ok, activity} else - # Can't find the activity. This might a Mastodon 2.3 "Accept" - {:activity, nil} -> - mastodon_follow_hack(follow_object, followed) - _ -> {:error, nil} end diff --git a/test/web/activity_pub/transmogrifier/accept_handling_test.exs b/test/web/activity_pub/transmogrifier/accept_handling_test.exs index 3c4e134ff..bc4cc227d 100644 --- a/test/web/activity_pub/transmogrifier/accept_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/accept_handling_test.exs @@ -44,28 +44,6 @@ test "it works for incoming accepts which were pre-accepted" do assert User.following?(follower, followed) == true end - test "it works for incoming accepts which were orphaned" do - follower = insert(:user) - followed = insert(:user, locked: true) - - {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - - accept_data = - File.read!("test/fixtures/mastodon-accept-activity.json") - |> Poison.decode!() - |> Map.put("actor", followed.ap_id) - - accept_data = - Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - - {:ok, activity} = Transmogrifier.handle_incoming(accept_data) - assert activity.data["object"] == follow_activity.data["id"] - - follower = User.get_cached_by_id(follower.id) - - assert User.following?(follower, followed) == true - end - test "it works for incoming accepts which are referenced by IRI only" do follower = insert(:user) followed = insert(:user, locked: true) -- cgit v1.2.3 From 3f6d50111e57a942ecc24d4aa7cdbec23b95dfec Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 16:07:42 +0200 Subject: Linter fixes. --- lib/pleroma/web/activity_pub/object_validators/accept_validator.ex | 2 +- test/web/activity_pub/object_validators/accept_validation_test.exs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex index 6d0fa669a..fd75f4b6e 100644 --- a/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex @@ -5,8 +5,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidator do use Ecto.Schema - alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Activity + alias Pleroma.EctoType.ActivityPub.ObjectValidators import Ecto.Changeset import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations diff --git a/test/web/activity_pub/object_validators/accept_validation_test.exs b/test/web/activity_pub/object_validators/accept_validation_test.exs index 2d5d18046..d6111ba41 100644 --- a/test/web/activity_pub/object_validators/accept_validation_test.exs +++ b/test/web/activity_pub/object_validators/accept_validation_test.exs @@ -4,9 +4,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidationTest do use Pleroma.DataCase + alias Pleroma.Web.ActivityPub.Builder - alias Pleroma.Web.ActivityPub.Pipeline alias Pleroma.Web.ActivityPub.ObjectValidator + alias Pleroma.Web.ActivityPub.Pipeline import Pleroma.Factory -- cgit v1.2.3 From 9dda13bfa193be8ab5d9b2c117f7a50aaba451e1 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 16:22:15 +0200 Subject: Transmogrifier Test: Remove mastodon hack test. --- test/web/activity_pub/transmogrifier_test.exs | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 52b4178bf..13da864d1 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -422,32 +422,6 @@ test "it fails for incoming rejects which cannot be correlated" do refute User.following?(follower, followed) == true end - test "it works for incoming rejects which are orphaned" do - follower = insert(:user) - followed = insert(:user, locked: true) - - {:ok, follower} = User.follow(follower, followed) - {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, followed) - - assert User.following?(follower, followed) == true - - reject_data = - File.read!("test/fixtures/mastodon-reject-activity.json") - |> Poison.decode!() - |> Map.put("actor", followed.ap_id) - - reject_data = - Map.put(reject_data, "object", Map.put(reject_data["object"], "actor", follower.ap_id)) - - {:ok, activity} = Transmogrifier.handle_incoming(reject_data) - refute activity.local - assert activity.data["id"] == reject_data["id"] - - follower = User.get_cached_by_id(follower.id) - - assert User.following?(follower, followed) == false - end - test "it works for incoming rejects which are referenced by IRI only" do follower = insert(:user) followed = insert(:user, locked: true) -- cgit v1.2.3 From f988d82e463d2c08fa2cc22dc6ee733ee8668671 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 17:26:01 +0200 Subject: Transmogrifier: Handle accepts with the pipeline --- lib/pleroma/web/activity_pub/side_effects.ex | 28 +++++++++++++++++++ lib/pleroma/web/activity_pub/transmogrifier.ex | 32 +--------------------- .../transmogrifier/accept_handling_test.exs | 2 +- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 5104d38ee..3ba7eaf9e 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -21,9 +21,37 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do alias Pleroma.Web.Push alias Pleroma.Web.Streamer alias Pleroma.Workers.BackgroundWorker + alias Pleroma.FollowingRelationship def handle(object, meta \\ []) + # Task this handles + # - Follows + # - Sends a notification + def handle( + %{ + data: %{ + "actor" => actor, + "type" => "Accept", + "object" => follow_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, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept) do + Notification.update_notification_type(followed, follow_activity) + User.update_follower_count(followed) + User.update_following_count(follower) + end + + {:ok, object, meta} + end + # Tasks this handle # - Follows if possible # - Sends a notification diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 5ea97e9b7..24da1ef9c 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -11,7 +11,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.FollowingRelationship alias Pleroma.Maps - alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Object.Containment alias Pleroma.Repo @@ -535,35 +534,6 @@ def handle_incoming( end end - def handle_incoming( - %{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => id} = data, - _options - ) do - with actor <- Containment.get_actor(data), - {:ok, %User{} = followed} <- User.get_or_fetch_by_ap_id(actor), - {:ok, follow_activity} <- get_follow_activity(follow_object, followed), - {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"), - %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), - {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept) do - User.update_follower_count(followed) - User.update_following_count(follower) - - Notification.update_notification_type(followed, follow_activity) - - ActivityPub.accept(%{ - to: follow_activity.data["to"], - type: "Accept", - actor: followed, - object: follow_activity.data["id"], - local: false, - activity_id: id - }) - else - _e -> - :error - end - end - def handle_incoming( %{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => id} = data, _options @@ -643,7 +613,7 @@ def handle_incoming( %{"type" => type} = data, _options ) - when type in ~w{Update Block Follow} do + when type in ~w{Update Block Follow Accept} do with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do diff --git a/test/web/activity_pub/transmogrifier/accept_handling_test.exs b/test/web/activity_pub/transmogrifier/accept_handling_test.exs index bc4cc227d..77d468f5c 100644 --- a/test/web/activity_pub/transmogrifier/accept_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/accept_handling_test.exs @@ -82,7 +82,7 @@ test "it fails for incoming accepts which cannot be correlated" do accept_data = Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - :error = Transmogrifier.handle_incoming(accept_data) + {:error, _} = Transmogrifier.handle_incoming(accept_data) follower = User.get_cached_by_id(follower.id) -- cgit v1.2.3 From ff4e282aad09954db5d7e234923854a21a002128 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 11 Aug 2020 09:52:28 -0500 Subject: Ensure ap_id column in users table cannot be null --- priv/repo/migrations/20200811143147_ap_id_not_null.exs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 priv/repo/migrations/20200811143147_ap_id_not_null.exs diff --git a/priv/repo/migrations/20200811143147_ap_id_not_null.exs b/priv/repo/migrations/20200811143147_ap_id_not_null.exs new file mode 100644 index 000000000..3e5d27fe1 --- /dev/null +++ b/priv/repo/migrations/20200811143147_ap_id_not_null.exs @@ -0,0 +1,13 @@ +defmodule Pleroma.Repo.Migrations.ApIdNotNull do + use Ecto.Migration + + def up do + alter table(:users) do + modify(:ap_id, :string, null: false) + end + end + + def down do + :ok + end +end -- cgit v1.2.3 From 25bfee0d12d6ee096bba169089cc57c91efd7bc3 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 17:43:16 +0200 Subject: ActivityPub: Remove ActivityPub.accept Switch to the pipeline in CommonAPI and SideEffects --- lib/pleroma/web/activity_pub/activity_pub.ex | 5 ----- lib/pleroma/web/activity_pub/side_effects.ex | 15 +++------------ lib/pleroma/web/common_api/common_api.ex | 13 ++----------- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index fe62673dc..6dd94119b 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -285,11 +285,6 @@ def listen(%{to: to, actor: actor, context: context, object: object} = params) d end end - @spec accept(map()) :: {:ok, Activity.t()} | {:error, any()} - def accept(params) do - accept_or_reject("Accept", params) - end - @spec reject(map()) :: {:ok, Activity.t()} | {:error, any()} def reject(params) do accept_or_reject("Reject", params) diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 3ba7eaf9e..4228041e7 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -16,6 +16,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Pipeline alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.Push @@ -72,18 +73,8 @@ def handle( {_, {:ok, _}, _, _} <- {:following, User.follow(follower, followed, :follow_pending), follower, followed} do if followed.local && !followed.locked do - Utils.update_follow_state_for_all(object, "accept") - FollowingRelationship.update(follower, followed, :follow_accept) - User.update_follower_count(followed) - User.update_following_count(follower) - - %{ - to: [following_user], - actor: followed, - object: follow_id, - local: true - } - |> ActivityPub.accept() + {:ok, accept_data, _} = Builder.accept(followed, object) + {:ok, _activity, _} = Pipeline.common_pipeline(accept_data, local: true) end else {:following, {:error, _}, follower, followed} -> diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index c08e0ffeb..7b08c19a8 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -122,17 +122,8 @@ def unfollow(follower, unfollowed) do def accept_follow_request(follower, followed) do with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), - {:ok, follower} <- User.follow(follower, followed), - {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"), - {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept), - {:ok, _activity} <- - ActivityPub.accept(%{ - to: [follower.ap_id], - actor: followed, - object: follow_activity.data["id"], - type: "Accept" - }) do - Notification.update_notification_type(followed, follow_activity) + {:ok, accept_data, _} <- Builder.accept(followed, follow_activity), + {:ok, _activity, _} <- Pipeline.common_pipeline(accept_data, local: true) do {:ok, follower} end end -- cgit v1.2.3 From 724ed354f25fb83f65dff2fbadd4b5a121fb77d0 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 11 Aug 2020 11:28:22 -0500 Subject: Ensure only Note objects are set to expire --- lib/mix/tasks/pleroma/database.ex | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index b2dc3d0f3..7d8f00b08 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -134,14 +134,23 @@ def run(["ensure_expiration"]) do Pleroma.Activity |> join(:left, [a], u in assoc(a, :expiration)) + |> join(:inner, [a, _u], o in Object, + on: + fragment( + "(?->>'id') = COALESCE((?)->'object'->> 'id', (?)->>'object')", + o.data, + a.data, + a.data + ) + ) |> where(local: true) |> where([a, u], is_nil(u)) |> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data)) + |> where([_a, _u, o], fragment("?->>'type' = 'Note'", o.data)) |> Pleroma.RepoStreamer.chunk_stream(100) |> Stream.each(fn activities -> Enum.each(activities, fn activity -> expires_at = Timex.shift(activity.inserted_at, days: days) - Pleroma.ActivityExpiration.create(activity, expires_at, false) end) end) -- cgit v1.2.3 From 500576dcb623bdc29193e3b372837c581e151755 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 11 Aug 2020 19:22:14 +0200 Subject: Linting fixes. --- lib/pleroma/web/activity_pub/side_effects.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 4228041e7..e1fa75e1c 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -22,7 +22,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do alias Pleroma.Web.Push alias Pleroma.Web.Streamer alias Pleroma.Workers.BackgroundWorker - alias Pleroma.FollowingRelationship def handle(object, meta \\ []) -- cgit v1.2.3 From 76462efbfaa4bc01ca80cb702161b3197968c584 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Tue, 11 Aug 2020 22:06:33 +0300 Subject: fix job monitor --- lib/pleroma/job_queue_monitor.ex | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/job_queue_monitor.ex b/lib/pleroma/job_queue_monitor.ex index 2ecf261f3..c255a61ec 100644 --- a/lib/pleroma/job_queue_monitor.ex +++ b/lib/pleroma/job_queue_monitor.ex @@ -15,8 +15,8 @@ def start_link(_) do @impl true def init(state) do - :telemetry.attach("oban-monitor-failure", [:oban, :failure], &handle_event/4, nil) - :telemetry.attach("oban-monitor-success", [:oban, :success], &handle_event/4, nil) + :telemetry.attach("oban-monitor-failure", [:oban, :job, :exception], &handle_event/4, nil) + :telemetry.attach("oban-monitor-success", [:oban, :job, :stop], &handle_event/4, nil) {:ok, state} end @@ -25,8 +25,11 @@ def stats do GenServer.call(__MODULE__, :stats) end - def handle_event([:oban, status], %{duration: duration}, meta, _) do - GenServer.cast(__MODULE__, {:process_event, status, duration, meta}) + def handle_event([:oban, :job, event], %{duration: duration}, meta, _) do + GenServer.cast( + __MODULE__, + {:process_event, mapping_status(event), duration, meta} + ) end @impl true @@ -75,4 +78,7 @@ defp update_queue(queue, status, _meta, _duration) do |> Map.update!(:processed_jobs, &(&1 + 1)) |> Map.update!(status, &(&1 + 1)) end + + defp mapping_status(:stop), do: :success + defp mapping_status(:exception), do: :failure end -- cgit v1.2.3 From 644effc63b870d23830875aaca2b8caa81262662 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Wed, 12 Aug 2020 08:51:09 +0300 Subject: update docs --- docs/API/admin_api.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md index 4b143e4ee..05e63b528 100644 --- a/docs/API/admin_api.md +++ b/docs/API/admin_api.md @@ -1266,11 +1266,14 @@ Loads json generated from `config/descriptions.exs`. - Params: - *optional* `page`: **integer** page number - *optional* `page_size`: **integer** number of log entries per page (default is `50`) +- *optional* `query`: **string** search term - Response: ``` json { + "page_size": integer, + "count": integer, "urls": [ "http://example.com/media/a688346.jpg", "http://example.com/media/fb1f4d.jpg" @@ -1290,12 +1293,7 @@ Loads json generated from `config/descriptions.exs`. - Response: ``` json -{ - "urls": [ - "http://example.com/media/a688346.jpg", - "http://example.com/media/fb1f4d.jpg" - ] -} +{ } ``` @@ -1311,11 +1309,6 @@ Loads json generated from `config/descriptions.exs`. - Response: ``` json -{ - "urls": [ - "http://example.com/media/a688346.jpg", - "http://example.com/media/fb1f4d.jpg" - ] -} +{ } ``` -- cgit v1.2.3 From 57b455de5a378d661eb794c2c9d75a2684d74ef3 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 12 Aug 2020 12:41:47 +0300 Subject: leave expirations with Create and Note types --- priv/repo/migrations/20200808173046_only_expire_creates.exs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/priv/repo/migrations/20200808173046_only_expire_creates.exs b/priv/repo/migrations/20200808173046_only_expire_creates.exs index 42fb73375..9df52956f 100644 --- a/priv/repo/migrations/20200808173046_only_expire_creates.exs +++ b/priv/repo/migrations/20200808173046_only_expire_creates.exs @@ -4,10 +4,10 @@ defmodule Pleroma.Repo.Migrations.OnlyExpireCreates do def up do statement = """ DELETE FROM - activity_expirations A USING activities B + activity_expirations a_exp USING activities a, objects o WHERE - A.activity_id = B.id - AND B.data->>'type' != 'Create'; + a_exp.activity_id = a.id AND (o.data->>'id') = COALESCE(a.data->'object'->>'id', a.data->>'object') + AND (a.data->>'type' != 'Create' OR o.data->>'type' != 'Note'); """ execute(statement) -- cgit v1.2.3 From 62f7cca9a1e3f6c6685094eb3618876d4b6ca3a7 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 12 Aug 2020 13:39:54 +0200 Subject: Transmogrifier Tests: Extract rejections. --- .../transmogrifier/follow_handling_test.exs | 19 ++++++ .../transmogrifier/reject_handling_test.exs | 67 ++++++++++++++++++++ test/web/activity_pub/transmogrifier_test.exs | 72 ---------------------- 3 files changed, 86 insertions(+), 72 deletions(-) create mode 100644 test/web/activity_pub/transmogrifier/reject_handling_test.exs diff --git a/test/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs index 17e764ca1..757d90941 100644 --- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -185,5 +185,24 @@ test "it works for incoming follow requests from hubzilla" do assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2" assert User.following?(User.get_cached_by_ap_id(data["actor"]), user) end + + test "it works for incoming follows to locked account" do + pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin") + user = insert(:user, locked: true) + + data = + File.read!("test/fixtures/mastodon-follow-activity.json") + |> Poison.decode!() + |> Map.put("object", user.ap_id) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + + assert data["type"] == "Follow" + assert data["object"] == user.ap_id + assert data["state"] == "pending" + assert data["actor"] == "http://mastodon.example.org/users/admin" + + assert [^pending_follower] = User.get_follow_requests(user) + end end end diff --git a/test/web/activity_pub/transmogrifier/reject_handling_test.exs b/test/web/activity_pub/transmogrifier/reject_handling_test.exs new file mode 100644 index 000000000..5e5248641 --- /dev/null +++ b/test/web/activity_pub/transmogrifier/reject_handling_test.exs @@ -0,0 +1,67 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.RejectHandlingTest do + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.User + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + test "it fails for incoming rejects which cannot be correlated" do + follower = insert(:user) + followed = insert(:user, locked: true) + + accept_data = + File.read!("test/fixtures/mastodon-reject-activity.json") + |> Poison.decode!() + |> Map.put("actor", followed.ap_id) + + accept_data = + Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) + + :error = Transmogrifier.handle_incoming(accept_data) + + follower = User.get_cached_by_id(follower.id) + + refute User.following?(follower, followed) == true + end + + test "it works for incoming rejects which are referenced by IRI only" do + follower = insert(:user) + followed = insert(:user, locked: true) + + {:ok, follower} = User.follow(follower, followed) + {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) + + assert User.following?(follower, followed) == true + + reject_data = + File.read!("test/fixtures/mastodon-reject-activity.json") + |> Poison.decode!() + |> Map.put("actor", followed.ap_id) + |> Map.put("object", follow_activity.data["id"]) + + {:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data) + + follower = User.get_cached_by_id(follower.id) + + assert User.following?(follower, followed) == false + end + + test "it rejects activities without a valid ID" do + user = insert(:user) + + data = + File.read!("test/fixtures/mastodon-follow-activity.json") + |> Poison.decode!() + |> Map.put("object", user.ap_id) + |> Map.put("id", "") + + :error = Transmogrifier.handle_incoming(data) + end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 13da864d1..0dd4e6e47 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -384,78 +384,6 @@ test "it works for incoming unfollows with an existing follow" do refute User.following?(User.get_cached_by_ap_id(data["actor"]), user) end - test "it works for incoming follows to locked account" do - pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin") - user = insert(:user, locked: true) - - data = - File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() - |> Map.put("object", user.ap_id) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["type"] == "Follow" - assert data["object"] == user.ap_id - assert data["state"] == "pending" - assert data["actor"] == "http://mastodon.example.org/users/admin" - - assert [^pending_follower] = User.get_follow_requests(user) - end - - test "it fails for incoming rejects which cannot be correlated" do - follower = insert(:user) - followed = insert(:user, locked: true) - - accept_data = - File.read!("test/fixtures/mastodon-reject-activity.json") - |> Poison.decode!() - |> Map.put("actor", followed.ap_id) - - accept_data = - Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - - :error = Transmogrifier.handle_incoming(accept_data) - - follower = User.get_cached_by_id(follower.id) - - refute User.following?(follower, followed) == true - end - - test "it works for incoming rejects which are referenced by IRI only" do - follower = insert(:user) - followed = insert(:user, locked: true) - - {:ok, follower} = User.follow(follower, followed) - {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - - assert User.following?(follower, followed) == true - - reject_data = - File.read!("test/fixtures/mastodon-reject-activity.json") - |> Poison.decode!() - |> Map.put("actor", followed.ap_id) - |> Map.put("object", follow_activity.data["id"]) - - {:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data) - - follower = User.get_cached_by_id(follower.id) - - assert User.following?(follower, followed) == false - end - - test "it rejects activities without a valid ID" do - user = insert(:user) - - data = - File.read!("test/fixtures/mastodon-follow-activity.json") - |> Poison.decode!() - |> Map.put("object", user.ap_id) - |> Map.put("id", "") - - :error = Transmogrifier.handle_incoming(data) - end - test "skip converting the content when it is nil" do object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe" -- cgit v1.2.3 From eec1ba232c42285fc69c26b5ccc32c504955eab5 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 12 Aug 2020 15:15:17 +0300 Subject: don't expire pinned posts --- lib/mix/tasks/pleroma/database.ex | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 7d8f00b08..0142071a8 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -150,8 +150,12 @@ def run(["ensure_expiration"]) do |> Pleroma.RepoStreamer.chunk_stream(100) |> Stream.each(fn activities -> Enum.each(activities, fn activity -> - expires_at = Timex.shift(activity.inserted_at, days: days) - Pleroma.ActivityExpiration.create(activity, expires_at, false) + user = User.get_cached_by_ap_id(activity.actor) + + if activity.id not in user.pinned_activities do + expires_at = Timex.shift(activity.inserted_at, days: days) + Pleroma.ActivityExpiration.create(activity, expires_at, false) + end end) end) |> Stream.run() -- cgit v1.2.3 From 7224bf309ef38a80898d7e560e96fbc2895737be Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 12 Aug 2020 14:48:51 +0200 Subject: Transmogrifier: Move Rejects to the Pipeline --- lib/pleroma/web/activity_pub/builder.ex | 19 ++++++-- lib/pleroma/web/activity_pub/object_validator.ex | 7 +-- .../object_validators/accept_reject_validator.ex | 56 ++++++++++++++++++++++ .../object_validators/accept_validator.ex | 56 ---------------------- lib/pleroma/web/activity_pub/side_effects.ex | 24 ++++++++++ lib/pleroma/web/activity_pub/transmogrifier.ex | 38 +-------------- .../object_validators/reject_validation_test.exs | 56 ++++++++++++++++++++++ .../transmogrifier/reject_handling_test.exs | 2 +- 8 files changed, 156 insertions(+), 102 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex delete mode 100644 lib/pleroma/web/activity_pub/object_validators/accept_validator.ex create mode 100644 test/web/activity_pub/object_validators/reject_validation_test.exs diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index e1f88e6cc..f2392ce79 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -14,19 +14,28 @@ defmodule Pleroma.Web.ActivityPub.Builder do require Pleroma.Constants - @spec accept(User.t(), Activity.t()) :: {:ok, map(), keyword()} - def accept(actor, accepted_activity) do + def accept_or_reject(actor, activity, type) do data = %{ "id" => Utils.generate_activity_id(), "actor" => actor.ap_id, - "type" => "Accept", - "object" => accepted_activity.data["id"], - "to" => [accepted_activity.actor] + "type" => type, + "object" => activity.data["id"], + "to" => [activity.actor] } {:ok, data, []} end + @spec reject(User.t(), Activity.t()) :: {:ok, map(), keyword()} + def reject(actor, rejected_activity) do + accept_or_reject(actor, rejected_activity, "Reject") + end + + @spec accept(User.t(), Activity.t()) :: {:ok, map(), keyword()} + def accept(actor, accepted_activity) do + accept_or_reject(actor, accepted_activity, "Accept") + end + @spec follow(User.t(), User.t()) :: {:ok, map(), keyword()} def follow(follower, followed) do data = %{ diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index d9dd2bc30..3f1dffe2b 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -13,7 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Object alias Pleroma.User - alias Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator @@ -31,10 +31,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do @spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()} def validate(object, meta) - def validate(%{"type" => "Accept"} = object, meta) do + def validate(%{"type" => type} = object, meta) + when type in ~w[Accept Reject] do with {:ok, object} <- object - |> AcceptValidator.cast_and_validate() + |> AcceptRejectValidator.cast_and_validate() |> Ecto.Changeset.apply_action(:insert) do object = stringify_keys(object) {:ok, object, meta} 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 new file mode 100644 index 000000000..179beda58 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator do + use Ecto.Schema + + alias Pleroma.Activity + alias Pleroma.EctoType.ActivityPub.ObjectValidators + + import Ecto.Changeset + import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + + @primary_key false + + embedded_schema do + field(:id, ObjectValidators.ObjectID, primary_key: true) + field(:type, :string) + field(:object, ObjectValidators.ObjectID) + field(:actor, ObjectValidators.ObjectID) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + end + + def cast_data(data) do + %__MODULE__{} + |> cast(data, __schema__(:fields)) + end + + def validate_data(cng) do + cng + |> validate_required([:id, :type, :actor, :to, :cc, :object]) + |> validate_inclusion(:type, ["Accept", "Reject"]) + |> validate_actor_presence() + |> validate_object_presence(allowed_types: ["Follow"]) + |> validate_accept_reject_rights() + end + + def cast_and_validate(data) do + data + |> cast_data + |> validate_data + end + + 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 + cng + else + _e -> + cng + |> add_error(:actor, "can't accept or reject the given activity") + end + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex deleted file mode 100644 index fd75f4b6e..000000000 --- a/lib/pleroma/web/activity_pub/object_validators/accept_validator.ex +++ /dev/null @@ -1,56 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidator do - use Ecto.Schema - - alias Pleroma.Activity - alias Pleroma.EctoType.ActivityPub.ObjectValidators - - import Ecto.Changeset - import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations - - @primary_key false - - embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:object, ObjectValidators.ObjectID) - field(:actor, ObjectValidators.ObjectID) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - end - - def cast_data(data) do - %__MODULE__{} - |> cast(data, __schema__(:fields)) - end - - def validate_data(cng) do - cng - |> validate_required([:id, :type, :actor, :to, :cc, :object]) - |> validate_inclusion(:type, ["Accept"]) - |> validate_actor_presence() - |> validate_object_presence(allowed_types: ["Follow"]) - |> validate_accept_rights() - end - - def cast_and_validate(data) do - data - |> cast_data - |> validate_data - end - - def validate_accept_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 - cng - else - _e -> - cng - |> add_error(:actor, "can't accept the given activity") - end - end -end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index e1fa75e1c..a4ad12d53 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -52,6 +52,30 @@ def handle( {:ok, object, meta} end + # Task this handles + # - Rejects all existing follow activities for this person + # - Updates the follow state + def handle( + %{ + data: %{ + "actor" => actor, + "type" => "Reject", + "object" => follow_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) + end + + {:ok, object, meta} + end + # Tasks this handle # - Follows if possible # - Sends a notification diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 24da1ef9c..544f3f3b6 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -9,7 +9,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do alias Pleroma.Activity alias Pleroma.EarmarkRenderer alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.FollowingRelationship alias Pleroma.Maps alias Pleroma.Object alias Pleroma.Object.Containment @@ -390,16 +389,6 @@ defp fix_content(%{"mediaType" => "text/markdown", "content" => content} = objec defp fix_content(object), do: object - defp get_follow_activity(follow_object, _followed) do - with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object), - {_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do - {:ok, activity} - else - _ -> - {:error, nil} - end - end - # Reduce the object list to find the reported user. defp get_reported(objects) do Enum.reduce_while(objects, nil, fn ap_id, _ -> @@ -534,31 +523,6 @@ def handle_incoming( end end - def handle_incoming( - %{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => id} = data, - _options - ) do - with actor <- Containment.get_actor(data), - {:ok, %User{} = followed} <- User.get_or_fetch_by_ap_id(actor), - {:ok, follow_activity} <- get_follow_activity(follow_object, followed), - {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"), - %User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]), - {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_reject), - {:ok, activity} <- - ActivityPub.reject(%{ - to: follow_activity.data["to"], - type: "Reject", - actor: followed, - object: follow_activity.data["id"], - local: false, - activity_id: id - }) do - {:ok, activity} - else - _e -> :error - end - end - @misskey_reactions %{ "like" => "👍", "love" => "❤️", @@ -613,7 +577,7 @@ def handle_incoming( %{"type" => type} = data, _options ) - when type in ~w{Update Block Follow Accept} do + 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 diff --git a/test/web/activity_pub/object_validators/reject_validation_test.exs b/test/web/activity_pub/object_validators/reject_validation_test.exs new file mode 100644 index 000000000..370bb6e5c --- /dev/null +++ b/test/web/activity_pub/object_validators/reject_validation_test.exs @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.RejectValidationTest do + use Pleroma.DataCase + + alias Pleroma.Web.ActivityPub.Builder + alias Pleroma.Web.ActivityPub.ObjectValidator + alias Pleroma.Web.ActivityPub.Pipeline + + import Pleroma.Factory + + setup do + follower = insert(:user) + followed = insert(:user, local: false) + + {:ok, follow_data, _} = Builder.follow(follower, followed) + {:ok, follow_activity, _} = Pipeline.common_pipeline(follow_data, local: true) + + {:ok, reject_data, _} = Builder.reject(followed, follow_activity) + + %{reject_data: reject_data, followed: followed} + end + + test "it validates a basic 'reject'", %{reject_data: reject_data} do + assert {:ok, _, _} = ObjectValidator.validate(reject_data, []) + end + + test "it fails when the actor doesn't exist", %{reject_data: reject_data} do + reject_data = + reject_data + |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") + + assert {:error, _} = ObjectValidator.validate(reject_data, []) + end + + test "it fails when the rejected activity doesn't exist", %{reject_data: reject_data} do + reject_data = + reject_data + |> Map.put("object", "https://gensokyo.2hu/users/raymoo/follows/1") + + assert {:error, _} = ObjectValidator.validate(reject_data, []) + end + + test "for an rejected follow, it only validates if the actor of the reject is the followed actor", + %{reject_data: reject_data} do + stranger = insert(:user) + + reject_data = + reject_data + |> Map.put("actor", stranger.ap_id) + + assert {:error, _} = ObjectValidator.validate(reject_data, []) + end +end diff --git a/test/web/activity_pub/transmogrifier/reject_handling_test.exs b/test/web/activity_pub/transmogrifier/reject_handling_test.exs index 5e5248641..7592fbe1c 100644 --- a/test/web/activity_pub/transmogrifier/reject_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/reject_handling_test.exs @@ -24,7 +24,7 @@ test "it fails for incoming rejects which cannot be correlated" do accept_data = Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - :error = Transmogrifier.handle_incoming(accept_data) + {:error, _} = Transmogrifier.handle_incoming(accept_data) follower = User.get_cached_by_id(follower.id) -- cgit v1.2.3 From 2e347e8286fab13075e6e39e64e56cb3ba14e7e8 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 12 Aug 2020 15:07:46 +0200 Subject: ActivityPub: Remove `reject`, move everything to the Pipeline. --- lib/pleroma/web/activity_pub/activity_pub.ex | 21 --------------------- lib/pleroma/web/activity_pub/side_effects.ex | 18 +++++------------- lib/pleroma/web/common_api/common_api.ex | 14 ++------------ 3 files changed, 7 insertions(+), 46 deletions(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 6dd94119b..bde1fe708 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -285,27 +285,6 @@ def listen(%{to: to, actor: actor, context: context, object: object} = params) d end end - @spec reject(map()) :: {:ok, Activity.t()} | {:error, any()} - def reject(params) do - accept_or_reject("Reject", params) - end - - @spec accept_or_reject(String.t(), map()) :: {:ok, Activity.t()} | {:error, any()} - defp accept_or_reject(type, %{to: to, actor: actor, object: object} = params) do - local = Map.get(params, :local, true) - activity_id = Map.get(params, :activity_id, nil) - - data = - %{"to" => to, "type" => type, "actor" => actor.ap_id, "object" => object} - |> Maps.put_if_present("id", activity_id) - - with {:ok, activity} <- insert(data, local), - _ <- notify_and_stream(activity), - :ok <- maybe_federate(activity) do - {:ok, activity} - end - end - @spec unfollow(User.t(), User.t(), String.t() | nil, boolean()) :: {:ok, Activity.t()} | nil | {:error, any()} def unfollow(follower, followed, activity_id \\ nil, local \\ true) do diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index a4ad12d53..14a1da0c1 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -55,6 +55,7 @@ def handle( # Task this handles # - Rejects all existing follow activities for this person # - Updates the follow state + # - Dismisses notificatios def handle( %{ data: %{ @@ -71,6 +72,7 @@ def handle( %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 {:ok, object, meta} @@ -100,19 +102,9 @@ def handle( {:ok, _activity, _} = Pipeline.common_pipeline(accept_data, local: true) end else - {:following, {:error, _}, follower, followed} -> - Utils.update_follow_state_for_all(object, "reject") - FollowingRelationship.update(follower, followed, :follow_reject) - - if followed.local do - %{ - to: [follower.ap_id], - actor: followed, - object: follow_id, - local: true - } - |> ActivityPub.reject() - end + {:following, {:error, _}, _follower, followed} -> + {:ok, reject_data, _} = Builder.reject(followed, object) + {:ok, _activity, _} = Pipeline.common_pipeline(reject_data, local: true) _ -> nil diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 7b08c19a8..a8141b28f 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -6,9 +6,7 @@ defmodule Pleroma.Web.CommonAPI do alias Pleroma.Activity alias Pleroma.ActivityExpiration alias Pleroma.Conversation.Participation - alias Pleroma.FollowingRelationship alias Pleroma.Formatter - alias Pleroma.Notification alias Pleroma.Object alias Pleroma.ThreadMute alias Pleroma.User @@ -130,16 +128,8 @@ def accept_follow_request(follower, followed) do def reject_follow_request(follower, followed) do with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), - {:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "reject"), - {:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_reject), - {:ok, _notifications} <- Notification.dismiss(follow_activity), - {:ok, _activity} <- - ActivityPub.reject(%{ - to: [follower.ap_id], - actor: followed, - object: follow_activity.data["id"], - type: "Reject" - }) do + {:ok, reject_data, _} <- Builder.reject(followed, follow_activity), + {:ok, _activity, _} <- Pipeline.common_pipeline(reject_data, local: true) do {:ok, follower} end end -- cgit v1.2.3 From 05ff666f997173bda2f7d96bff237da0cf1c8ca5 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 12 Aug 2020 16:31:00 +0200 Subject: AdminApiControllerTest: Add test that `deleted` users get deactivated. --- test/web/admin_api/controllers/admin_api_controller_test.exs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index eca9272e0..66d4b1ef3 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -158,6 +158,8 @@ test "single user", %{admin: admin, conn: conn} do user = insert(:user) clear_config([:instance, :federating], true) + refute user.deactivated + with_mock Pleroma.Web.Federator, publish: fn _ -> nil end do conn = @@ -176,6 +178,9 @@ test "single user", %{admin: admin, conn: conn} do assert json_response(conn, 200) == [user.nickname] + user = Repo.get(User, user.id) + assert user.deactivated + assert called(Pleroma.Web.Federator.publish(:_)) end end -- cgit v1.2.3 From 091da10832b35ce55e5d7a5a3655d4cdb98bb27c Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 12 Aug 2020 11:00:01 -0500 Subject: Add the ActivityExpirationPolicy MRF to docs and clarify post expiration criteria. --- docs/configuration/cheatsheet.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index ca587af8e..e5742bc3a 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -114,6 +114,7 @@ To add configuration to your config file, you can copy it from the base config. * `Pleroma.Web.ActivityPub.MRF.MentionPolicy`: Drops posts mentioning configurable users. (See [`:mrf_mention`](#mrf_mention)). * `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)). * `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)). + * `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.ActivityExpiration` to be enabled for processing the scheduled delections. * `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo). * `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value. @@ -220,6 +221,8 @@ config :pleroma, :mrf_user_allowlist, %{ ## Pleroma.ActivityExpiration +Enables the worker which processes posts scheduled for deletion. Pinned posts are exempt from expiration. + * `enabled`: whether expired activities will be sent to the job queue to be deleted ## Frontends -- cgit v1.2.3 From b89fc1f2274424e7542a133d96373a1738eb53bb Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 12 Aug 2020 11:13:24 -0500 Subject: Add warning to the migration --- priv/repo/migrations/20200811143147_ap_id_not_null.exs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/priv/repo/migrations/20200811143147_ap_id_not_null.exs b/priv/repo/migrations/20200811143147_ap_id_not_null.exs index 3e5d27fe1..50f1810b2 100644 --- a/priv/repo/migrations/20200811143147_ap_id_not_null.exs +++ b/priv/repo/migrations/20200811143147_ap_id_not_null.exs @@ -2,6 +2,8 @@ defmodule Pleroma.Repo.Migrations.ApIdNotNull do use Ecto.Migration def up do + Logger.warn("If this migration fails please open an issue at https://git.pleroma.social/pleroma/pleroma/-/issues/new \n") + alter table(:users) do modify(:ap_id, :string, null: false) end -- cgit v1.2.3 From 3aa7969ff9c92ddd4b38caa91b453537ce11dcae Mon Sep 17 00:00:00 2001 From: feld Date: Wed, 12 Aug 2020 16:19:34 +0000 Subject: Update robots_txt.md --- docs/administration/CLI_tasks/robots_txt.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/administration/CLI_tasks/robots_txt.md b/docs/administration/CLI_tasks/robots_txt.md index b1de0981b..844318cc8 100644 --- a/docs/administration/CLI_tasks/robots_txt.md +++ b/docs/administration/CLI_tasks/robots_txt.md @@ -1,8 +1,8 @@ -# Managing robot.txt +# Managing robots.txt {! backend/administration/CLI_tasks/general_cli_task_info.include !} -## Generate a new robot.txt file and add it to the static directory +## Generate a new robots.txt file and add it to the static directory The `robots.txt` that ships by default is permissive. It allows well-behaved search engines to index all of your instance's URIs. -- cgit v1.2.3 From 3ab83f837eb9c454b91374c6aeb14b37e8fdd3b1 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 12 Aug 2020 19:46:47 +0300 Subject: don't load pinned activities in due_expirations --- lib/mix/tasks/pleroma/database.ex | 4 +--- lib/pleroma/activity.ex | 6 ++++++ lib/pleroma/activity_expiration.ex | 4 ++++ test/activity_expiration_test.exs | 5 ++++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 0142071a8..22a325b47 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -150,9 +150,7 @@ def run(["ensure_expiration"]) do |> Pleroma.RepoStreamer.chunk_stream(100) |> Stream.each(fn activities -> Enum.each(activities, fn activity -> - user = User.get_cached_by_ap_id(activity.actor) - - if activity.id not in user.pinned_activities do + if not Pleroma.Activity.pinned_by_actor?(activity) do expires_at = Timex.shift(activity.inserted_at, days: days) Pleroma.ActivityExpiration.create(activity, expires_at, false) end diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index c3cea8d2a..97feebeaa 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -340,4 +340,10 @@ def direct_conversation_id(activity, for_user) do _ -> nil end end + + @spec pinned_by_actor?(Activity.t()) :: boolean() + def pinned_by_actor?(%Activity{} = activity) do + actor = user_actor(activity) + activity.id in actor.pinned_activities + end end diff --git a/lib/pleroma/activity_expiration.ex b/lib/pleroma/activity_expiration.ex index 84edf68ef..955f0578e 100644 --- a/lib/pleroma/activity_expiration.ex +++ b/lib/pleroma/activity_expiration.ex @@ -47,7 +47,11 @@ def due_expirations(offset \\ 0) do ActivityExpiration |> where([exp], exp.scheduled_at < ^naive_datetime) |> limit(50) + |> preload(:activity) |> Repo.all() + |> Enum.reject(fn %{activity: activity} -> + Activity.pinned_by_actor?(activity) + end) end def validate_scheduled_at(changeset, false), do: changeset diff --git a/test/activity_expiration_test.exs b/test/activity_expiration_test.exs index d75c06cc7..f86d79826 100644 --- a/test/activity_expiration_test.exs +++ b/test/activity_expiration_test.exs @@ -11,7 +11,10 @@ defmodule Pleroma.ActivityExpirationTest do test "finds activities due to be deleted only" do activity = insert(:note_activity) - expiration_due = insert(:expiration_in_the_past, %{activity_id: activity.id}) + + expiration_due = + insert(:expiration_in_the_past, %{activity_id: activity.id}) |> Repo.preload(:activity) + activity2 = insert(:note_activity) insert(:expiration_in_the_future, %{activity_id: activity2.id}) -- cgit v1.2.3 From 29a7bcd5bbb3a39fe1b31c9f5ffc0077f23fc101 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 12 Aug 2020 20:01:21 +0300 Subject: reverting pinned posts in filtering --- lib/mix/tasks/pleroma/database.ex | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 22a325b47..7d8f00b08 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -150,10 +150,8 @@ def run(["ensure_expiration"]) do |> Pleroma.RepoStreamer.chunk_stream(100) |> Stream.each(fn activities -> Enum.each(activities, fn activity -> - if not Pleroma.Activity.pinned_by_actor?(activity) do - expires_at = Timex.shift(activity.inserted_at, days: days) - Pleroma.ActivityExpiration.create(activity, expires_at, false) - end + expires_at = Timex.shift(activity.inserted_at, days: days) + Pleroma.ActivityExpiration.create(activity, expires_at, false) end) end) |> Stream.run() -- cgit v1.2.3 From aaf7bd89a71b174ad54040eb9a6106df51ef7ad5 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 13 Aug 2020 12:32:05 +0200 Subject: Migrations: Fix Logger requirements. --- priv/repo/migrations/20200811143147_ap_id_not_null.exs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/priv/repo/migrations/20200811143147_ap_id_not_null.exs b/priv/repo/migrations/20200811143147_ap_id_not_null.exs index 50f1810b2..df649c7ca 100644 --- a/priv/repo/migrations/20200811143147_ap_id_not_null.exs +++ b/priv/repo/migrations/20200811143147_ap_id_not_null.exs @@ -1,8 +1,12 @@ defmodule Pleroma.Repo.Migrations.ApIdNotNull do use Ecto.Migration + require Logger + def up do - Logger.warn("If this migration fails please open an issue at https://git.pleroma.social/pleroma/pleroma/-/issues/new \n") + Logger.warn( + "If this migration fails please open an issue at https://git.pleroma.social/pleroma/pleroma/-/issues/new \n" + ) alter table(:users) do modify(:ap_id, :string, null: false) -- cgit v1.2.3 From a47406d577e6760ca05880f4d3c80d5e8f391e04 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 13 Aug 2020 14:12:45 +0200 Subject: Build files: Add cmake --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 66813c814..5f82e58e5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -212,7 +212,7 @@ amd64-musl: cache: *release-cache variables: *release-variables before_script: &before-release-musl - - apk add git gcc g++ musl-dev make + - apk add git gcc g++ musl-dev make cmake - echo "import Mix.Config" > config/prod.secret.exs - mix local.hex --force - mix local.rebar --force diff --git a/Dockerfile b/Dockerfile index 0f4fcd0bb..aa50e27ec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ COPY . . ENV MIX_ENV=prod -RUN apk add git gcc g++ musl-dev make &&\ +RUN apk add git gcc g++ musl-dev make cmake &&\ echo "import Mix.Config" > config/prod.secret.exs &&\ mix local.hex --force &&\ mix local.rebar --force &&\ -- cgit v1.2.3 From 5bcf15d5538fcd9ae0a4cba387d963ff686b921b Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 13 Aug 2020 16:04:34 +0200 Subject: Update frontend --- priv/static/index.html | 2 +- .../static/static/css/app.6dbc7dea4fc148c85860.css | Bin 5616 -> 0 bytes .../static/css/app.6dbc7dea4fc148c85860.css.map | 1 - .../static/static/css/app.77b1644622e3bae24b6b.css | Bin 0 -> 5616 bytes .../static/css/app.77b1644622e3bae24b6b.css.map | 1 + priv/static/static/font/fontello.1594823398494.eot | Bin 24524 -> 0 bytes priv/static/static/font/fontello.1594823398494.svg | 138 --------------------- priv/static/static/font/fontello.1594823398494.ttf | Bin 24356 -> 0 bytes .../static/static/font/fontello.1594823398494.woff | Bin 14912 -> 0 bytes .../static/font/fontello.1594823398494.woff2 | Bin 12584 -> 0 bytes priv/static/static/font/fontello.1597327457363.eot | Bin 0 -> 24524 bytes priv/static/static/font/fontello.1597327457363.svg | 138 +++++++++++++++++++++ priv/static/static/font/fontello.1597327457363.ttf | Bin 0 -> 24356 bytes .../static/static/font/fontello.1597327457363.woff | Bin 0 -> 14912 bytes .../static/font/fontello.1597327457363.woff2 | Bin 0 -> 12548 bytes priv/static/static/fontello.1597327457363.css | Bin 0 -> 3736 bytes priv/static/static/js/10.5ef4671883649cf93524.js | Bin 22666 -> 0 bytes .../static/js/10.5ef4671883649cf93524.js.map | Bin 113 -> 0 bytes priv/static/static/js/10.8c5b75840b696a152c7e.js | Bin 0 -> 22666 bytes .../static/js/10.8c5b75840b696a152c7e.js.map | Bin 0 -> 113 bytes priv/static/static/js/11.bfcde1c26c4d54b84ee4.js | Bin 0 -> 16124 bytes .../static/js/11.bfcde1c26c4d54b84ee4.js.map | Bin 0 -> 113 bytes priv/static/static/js/11.c5b938b4349f87567338.js | Bin 16124 -> 0 bytes .../static/js/11.c5b938b4349f87567338.js.map | Bin 113 -> 0 bytes priv/static/static/js/12.76095ee23394e0ef65bb.js | Bin 0 -> 22115 bytes .../static/js/12.76095ee23394e0ef65bb.js.map | Bin 0 -> 113 bytes priv/static/static/js/12.ab82f9512fa85e78c114.js | Bin 22115 -> 0 bytes .../static/js/12.ab82f9512fa85e78c114.js.map | Bin 113 -> 0 bytes priv/static/static/js/13.40e59c5015d3307b94ad.js | Bin 27100 -> 0 bytes .../static/js/13.40e59c5015d3307b94ad.js.map | Bin 113 -> 0 bytes priv/static/static/js/13.957b04ac11d6cde66f5b.js | Bin 0 -> 27095 bytes .../static/js/13.957b04ac11d6cde66f5b.js.map | Bin 0 -> 113 bytes priv/static/static/js/14.aae5a904931591edfaa7.js | Bin 0 -> 28304 bytes .../static/js/14.aae5a904931591edfaa7.js.map | Bin 0 -> 113 bytes priv/static/static/js/14.de791a47ee5249a526b1.js | Bin 28164 -> 0 bytes .../static/js/14.de791a47ee5249a526b1.js.map | Bin 113 -> 0 bytes priv/static/static/js/15.139f5de3950adc3b66df.js | Bin 0 -> 7789 bytes .../static/js/15.139f5de3950adc3b66df.js.map | Bin 0 -> 113 bytes priv/static/static/js/15.e24854297ad682aec45a.js | Bin 7787 -> 0 bytes .../static/js/15.e24854297ad682aec45a.js.map | Bin 113 -> 0 bytes priv/static/static/js/16.7b8466d62084c04f6671.js | Bin 0 -> 15700 bytes .../static/js/16.7b8466d62084c04f6671.js.map | Bin 0 -> 113 bytes priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js | Bin 15702 -> 0 bytes .../static/js/16.b7b0e4b8227a50fcb9bb.js.map | Bin 113 -> 0 bytes priv/static/static/js/17.c98118b6bb84ee3b5b08.js | Bin 2086 -> 0 bytes .../static/js/17.c98118b6bb84ee3b5b08.js.map | Bin 113 -> 0 bytes priv/static/static/js/17.e8ec1f5666cb4e28784a.js | Bin 0 -> 2086 bytes .../static/js/17.e8ec1f5666cb4e28784a.js.map | Bin 0 -> 113 bytes priv/static/static/js/18.89c20aa67a4dd067ea37.js | Bin 28169 -> 0 bytes .../static/js/18.89c20aa67a4dd067ea37.js.map | Bin 113 -> 0 bytes priv/static/static/js/18.d32389579b85948022b8.js | Bin 0 -> 28393 bytes .../static/js/18.d32389579b85948022b8.js.map | Bin 0 -> 113 bytes priv/static/static/js/19.6e13bad8131c4501c1c5.js | Bin 31632 -> 0 bytes .../static/js/19.6e13bad8131c4501c1c5.js.map | Bin 113 -> 0 bytes priv/static/static/js/19.d180c594b843c17c80fa.js | Bin 0 -> 31593 bytes .../static/js/19.d180c594b843c17c80fa.js.map | Bin 0 -> 113 bytes priv/static/static/js/2.5ecefab707beea40b7f0.js | Bin 0 -> 178475 bytes .../static/static/js/2.5ecefab707beea40b7f0.js.map | Bin 0 -> 458701 bytes priv/static/static/js/2.78a48aa26599b00c3b8d.js | Bin 178659 -> 0 bytes .../static/static/js/2.78a48aa26599b00c3b8d.js.map | Bin 459053 -> 0 bytes priv/static/static/js/20.27e04f2209628de3092b.js | Bin 0 -> 26374 bytes .../static/js/20.27e04f2209628de3092b.js.map | Bin 0 -> 113 bytes priv/static/static/js/20.3615c3cea2e1c2707a4f.js | Bin 26374 -> 0 bytes .../static/js/20.3615c3cea2e1c2707a4f.js.map | Bin 113 -> 0 bytes priv/static/static/js/21.641aba6f96885c381070.js | Bin 0 -> 13162 bytes .../static/js/21.641aba6f96885c381070.js.map | Bin 0 -> 113 bytes priv/static/static/js/21.64dedfc646e13e6f7915.js | Bin 13162 -> 0 bytes .../static/js/21.64dedfc646e13e6f7915.js.map | Bin 113 -> 0 bytes priv/static/static/js/22.6fa63bc6a054b7638e9e.js | Bin 19706 -> 0 bytes .../static/js/22.6fa63bc6a054b7638e9e.js.map | Bin 113 -> 0 bytes priv/static/static/js/22.cbe4790c7601004ed96f.js | Bin 0 -> 19706 bytes .../static/js/22.cbe4790c7601004ed96f.js.map | Bin 0 -> 113 bytes priv/static/static/js/23.96b5bf8d37de3bf02a17.js | Bin 0 -> 27732 bytes .../static/js/23.96b5bf8d37de3bf02a17.js.map | Bin 0 -> 113 bytes priv/static/static/js/23.e0ddea2b6e049d221ee7.js | Bin 27732 -> 0 bytes .../static/js/23.e0ddea2b6e049d221ee7.js.map | Bin 113 -> 0 bytes priv/static/static/js/24.38e3b9d44e9ee703ebf6.js | Bin 18493 -> 0 bytes .../static/js/24.38e3b9d44e9ee703ebf6.js.map | Bin 113 -> 0 bytes priv/static/static/js/24.5e5eea3542b0e17c6479.js | Bin 0 -> 18493 bytes .../static/js/24.5e5eea3542b0e17c6479.js.map | Bin 0 -> 113 bytes priv/static/static/js/25.696b41c0a8660e1f85af.js | Bin 26932 -> 0 bytes .../static/js/25.696b41c0a8660e1f85af.js.map | Bin 113 -> 0 bytes priv/static/static/js/25.dd8471a33b5a4d256564.js | Bin 0 -> 28110 bytes .../static/js/25.dd8471a33b5a4d256564.js.map | Bin 0 -> 113 bytes priv/static/static/js/26.1168f22384be75dc5492.js | Bin 14249 -> 0 bytes .../static/js/26.1168f22384be75dc5492.js.map | Bin 113 -> 0 bytes priv/static/static/js/26.91a9c2effdd1a423a79f.js | Bin 0 -> 14249 bytes .../static/js/26.91a9c2effdd1a423a79f.js.map | Bin 0 -> 113 bytes priv/static/static/js/27.3c0cfbb2a898b35486dd.js | Bin 2022 -> 0 bytes .../static/js/27.3c0cfbb2a898b35486dd.js.map | Bin 113 -> 0 bytes priv/static/static/js/27.949d608895f6e29a2fc2.js | Bin 0 -> 2022 bytes .../static/js/27.949d608895f6e29a2fc2.js.map | Bin 0 -> 113 bytes priv/static/static/js/28.1e879ccb6222c26ee837.js | Bin 0 -> 25289 bytes .../static/js/28.1e879ccb6222c26ee837.js.map | Bin 0 -> 113 bytes priv/static/static/js/28.926c71d6f1813e177271.js | Bin 25289 -> 0 bytes .../static/js/28.926c71d6f1813e177271.js.map | Bin 113 -> 0 bytes priv/static/static/js/29.187064ebed099ae45749.js | Bin 23857 -> 0 bytes .../static/js/29.187064ebed099ae45749.js.map | Bin 113 -> 0 bytes priv/static/static/js/29.a0eb0eee98462dc00d86.js | Bin 0 -> 23857 bytes .../static/js/29.a0eb0eee98462dc00d86.js.map | Bin 0 -> 113 bytes priv/static/static/js/3.44ee95fa34170fe38ef7.js | Bin 0 -> 78761 bytes .../static/static/js/3.44ee95fa34170fe38ef7.js.map | Bin 0 -> 332972 bytes priv/static/static/js/3.56898c1005d9ba1b8d4a.js | Bin 78761 -> 0 bytes .../static/static/js/3.56898c1005d9ba1b8d4a.js.map | Bin 332972 -> 0 bytes priv/static/static/js/30.73f0507f6b66caa1b632.js | Bin 0 -> 21107 bytes .../static/js/30.73f0507f6b66caa1b632.js.map | Bin 0 -> 113 bytes priv/static/static/js/30.d78855ca19bf749be905.js | Bin 21107 -> 0 bytes .../static/js/30.d78855ca19bf749be905.js.map | Bin 113 -> 0 bytes priv/static/static/js/4.2d3bef896b463484e6eb.js | Bin 2177 -> 0 bytes .../static/static/js/4.2d3bef896b463484e6eb.js.map | Bin 7940 -> 0 bytes priv/static/static/js/4.77639012e321d98c064c.js | Bin 0 -> 2177 bytes .../static/static/js/4.77639012e321d98c064c.js.map | Bin 0 -> 7940 bytes priv/static/static/js/5.84f3dce298bc720719c7.js | Bin 6994 -> 0 bytes .../static/static/js/5.84f3dce298bc720719c7.js.map | Bin 112 -> 0 bytes priv/static/static/js/5.abcc811ac6e85e621b0d.js | Bin 0 -> 6994 bytes .../static/static/js/5.abcc811ac6e85e621b0d.js.map | Bin 0 -> 112 bytes priv/static/static/js/6.389907251866808cf2c4.js | Bin 0 -> 7792 bytes .../static/static/js/6.389907251866808cf2c4.js.map | Bin 0 -> 112 bytes priv/static/static/js/6.b9497e1d403b901a664e.js | Bin 7790 -> 0 bytes .../static/static/js/6.b9497e1d403b901a664e.js.map | Bin 112 -> 0 bytes priv/static/static/js/7.33e3cc5c9abab3f21825.js | Bin 0 -> 15617 bytes .../static/static/js/7.33e3cc5c9abab3f21825.js.map | Bin 0 -> 112 bytes priv/static/static/js/7.455b574116ce3f004ffb.js | Bin 15618 -> 0 bytes .../static/static/js/7.455b574116ce3f004ffb.js.map | Bin 112 -> 0 bytes priv/static/static/js/8.5e0b07052c330e85bead.js | Bin 0 -> 21670 bytes .../static/static/js/8.5e0b07052c330e85bead.js.map | Bin 0 -> 112 bytes priv/static/static/js/8.8db9f2dcc5ed429777f7.js | Bin 21682 -> 0 bytes .../static/static/js/8.8db9f2dcc5ed429777f7.js.map | Bin 112 -> 0 bytes priv/static/static/js/9.da3973d058660aa9612f.js | Bin 13753 -> 0 bytes .../static/static/js/9.da3973d058660aa9612f.js.map | Bin 112 -> 0 bytes priv/static/static/js/9.f8e3aa590f4a66aedc3f.js | Bin 0 -> 27113 bytes .../static/static/js/9.f8e3aa590f4a66aedc3f.js.map | Bin 0 -> 112 bytes priv/static/static/js/app.032cb80dafd1f208df1c.js | Bin 0 -> 580679 bytes .../static/js/app.032cb80dafd1f208df1c.js.map | Bin 0 -> 1483327 bytes priv/static/static/js/app.31bba9f1e242ff273dcb.js | Bin 572414 -> 0 bytes .../static/js/app.31bba9f1e242ff273dcb.js.map | Bin 1465392 -> 0 bytes .../static/js/vendors~app.811c8482146cad566f7e.js | Bin 0 -> 304081 bytes .../js/vendors~app.811c8482146cad566f7e.js.map | Bin 0 -> 1274957 bytes .../static/js/vendors~app.9e24ed238da5a8538f50.js | Bin 304076 -> 0 bytes .../js/vendors~app.9e24ed238da5a8538f50.js.map | Bin 1274957 -> 0 bytes priv/static/sw-pleroma.js | Bin 181435 -> 181549 bytes priv/static/sw-pleroma.js.map | Bin 695166 -> 696193 bytes 142 files changed, 140 insertions(+), 140 deletions(-) delete mode 100644 priv/static/static/css/app.6dbc7dea4fc148c85860.css delete mode 100644 priv/static/static/css/app.6dbc7dea4fc148c85860.css.map create mode 100644 priv/static/static/css/app.77b1644622e3bae24b6b.css create mode 100644 priv/static/static/css/app.77b1644622e3bae24b6b.css.map delete mode 100644 priv/static/static/font/fontello.1594823398494.eot delete mode 100644 priv/static/static/font/fontello.1594823398494.svg delete mode 100644 priv/static/static/font/fontello.1594823398494.ttf delete mode 100644 priv/static/static/font/fontello.1594823398494.woff delete mode 100644 priv/static/static/font/fontello.1594823398494.woff2 create mode 100644 priv/static/static/font/fontello.1597327457363.eot create mode 100644 priv/static/static/font/fontello.1597327457363.svg create mode 100644 priv/static/static/font/fontello.1597327457363.ttf create mode 100644 priv/static/static/font/fontello.1597327457363.woff create mode 100644 priv/static/static/font/fontello.1597327457363.woff2 create mode 100644 priv/static/static/fontello.1597327457363.css delete mode 100644 priv/static/static/js/10.5ef4671883649cf93524.js delete mode 100644 priv/static/static/js/10.5ef4671883649cf93524.js.map create mode 100644 priv/static/static/js/10.8c5b75840b696a152c7e.js create mode 100644 priv/static/static/js/10.8c5b75840b696a152c7e.js.map create mode 100644 priv/static/static/js/11.bfcde1c26c4d54b84ee4.js create mode 100644 priv/static/static/js/11.bfcde1c26c4d54b84ee4.js.map delete mode 100644 priv/static/static/js/11.c5b938b4349f87567338.js delete mode 100644 priv/static/static/js/11.c5b938b4349f87567338.js.map create mode 100644 priv/static/static/js/12.76095ee23394e0ef65bb.js create mode 100644 priv/static/static/js/12.76095ee23394e0ef65bb.js.map delete mode 100644 priv/static/static/js/12.ab82f9512fa85e78c114.js delete mode 100644 priv/static/static/js/12.ab82f9512fa85e78c114.js.map delete mode 100644 priv/static/static/js/13.40e59c5015d3307b94ad.js delete mode 100644 priv/static/static/js/13.40e59c5015d3307b94ad.js.map create mode 100644 priv/static/static/js/13.957b04ac11d6cde66f5b.js create mode 100644 priv/static/static/js/13.957b04ac11d6cde66f5b.js.map create mode 100644 priv/static/static/js/14.aae5a904931591edfaa7.js create mode 100644 priv/static/static/js/14.aae5a904931591edfaa7.js.map delete mode 100644 priv/static/static/js/14.de791a47ee5249a526b1.js delete mode 100644 priv/static/static/js/14.de791a47ee5249a526b1.js.map create mode 100644 priv/static/static/js/15.139f5de3950adc3b66df.js create mode 100644 priv/static/static/js/15.139f5de3950adc3b66df.js.map delete mode 100644 priv/static/static/js/15.e24854297ad682aec45a.js delete mode 100644 priv/static/static/js/15.e24854297ad682aec45a.js.map create mode 100644 priv/static/static/js/16.7b8466d62084c04f6671.js create mode 100644 priv/static/static/js/16.7b8466d62084c04f6671.js.map delete mode 100644 priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js delete mode 100644 priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js.map delete mode 100644 priv/static/static/js/17.c98118b6bb84ee3b5b08.js delete mode 100644 priv/static/static/js/17.c98118b6bb84ee3b5b08.js.map create mode 100644 priv/static/static/js/17.e8ec1f5666cb4e28784a.js create mode 100644 priv/static/static/js/17.e8ec1f5666cb4e28784a.js.map delete mode 100644 priv/static/static/js/18.89c20aa67a4dd067ea37.js delete mode 100644 priv/static/static/js/18.89c20aa67a4dd067ea37.js.map create mode 100644 priv/static/static/js/18.d32389579b85948022b8.js create mode 100644 priv/static/static/js/18.d32389579b85948022b8.js.map delete mode 100644 priv/static/static/js/19.6e13bad8131c4501c1c5.js delete mode 100644 priv/static/static/js/19.6e13bad8131c4501c1c5.js.map create mode 100644 priv/static/static/js/19.d180c594b843c17c80fa.js create mode 100644 priv/static/static/js/19.d180c594b843c17c80fa.js.map create mode 100644 priv/static/static/js/2.5ecefab707beea40b7f0.js create mode 100644 priv/static/static/js/2.5ecefab707beea40b7f0.js.map delete mode 100644 priv/static/static/js/2.78a48aa26599b00c3b8d.js delete mode 100644 priv/static/static/js/2.78a48aa26599b00c3b8d.js.map create mode 100644 priv/static/static/js/20.27e04f2209628de3092b.js create mode 100644 priv/static/static/js/20.27e04f2209628de3092b.js.map delete mode 100644 priv/static/static/js/20.3615c3cea2e1c2707a4f.js delete mode 100644 priv/static/static/js/20.3615c3cea2e1c2707a4f.js.map create mode 100644 priv/static/static/js/21.641aba6f96885c381070.js create mode 100644 priv/static/static/js/21.641aba6f96885c381070.js.map delete mode 100644 priv/static/static/js/21.64dedfc646e13e6f7915.js delete mode 100644 priv/static/static/js/21.64dedfc646e13e6f7915.js.map delete mode 100644 priv/static/static/js/22.6fa63bc6a054b7638e9e.js delete mode 100644 priv/static/static/js/22.6fa63bc6a054b7638e9e.js.map create mode 100644 priv/static/static/js/22.cbe4790c7601004ed96f.js create mode 100644 priv/static/static/js/22.cbe4790c7601004ed96f.js.map create mode 100644 priv/static/static/js/23.96b5bf8d37de3bf02a17.js create mode 100644 priv/static/static/js/23.96b5bf8d37de3bf02a17.js.map delete mode 100644 priv/static/static/js/23.e0ddea2b6e049d221ee7.js delete mode 100644 priv/static/static/js/23.e0ddea2b6e049d221ee7.js.map delete mode 100644 priv/static/static/js/24.38e3b9d44e9ee703ebf6.js delete mode 100644 priv/static/static/js/24.38e3b9d44e9ee703ebf6.js.map create mode 100644 priv/static/static/js/24.5e5eea3542b0e17c6479.js create mode 100644 priv/static/static/js/24.5e5eea3542b0e17c6479.js.map delete mode 100644 priv/static/static/js/25.696b41c0a8660e1f85af.js delete mode 100644 priv/static/static/js/25.696b41c0a8660e1f85af.js.map create mode 100644 priv/static/static/js/25.dd8471a33b5a4d256564.js create mode 100644 priv/static/static/js/25.dd8471a33b5a4d256564.js.map delete mode 100644 priv/static/static/js/26.1168f22384be75dc5492.js delete mode 100644 priv/static/static/js/26.1168f22384be75dc5492.js.map create mode 100644 priv/static/static/js/26.91a9c2effdd1a423a79f.js create mode 100644 priv/static/static/js/26.91a9c2effdd1a423a79f.js.map delete mode 100644 priv/static/static/js/27.3c0cfbb2a898b35486dd.js delete mode 100644 priv/static/static/js/27.3c0cfbb2a898b35486dd.js.map create mode 100644 priv/static/static/js/27.949d608895f6e29a2fc2.js create mode 100644 priv/static/static/js/27.949d608895f6e29a2fc2.js.map create mode 100644 priv/static/static/js/28.1e879ccb6222c26ee837.js create mode 100644 priv/static/static/js/28.1e879ccb6222c26ee837.js.map delete mode 100644 priv/static/static/js/28.926c71d6f1813e177271.js delete mode 100644 priv/static/static/js/28.926c71d6f1813e177271.js.map delete mode 100644 priv/static/static/js/29.187064ebed099ae45749.js delete mode 100644 priv/static/static/js/29.187064ebed099ae45749.js.map create mode 100644 priv/static/static/js/29.a0eb0eee98462dc00d86.js create mode 100644 priv/static/static/js/29.a0eb0eee98462dc00d86.js.map create mode 100644 priv/static/static/js/3.44ee95fa34170fe38ef7.js create mode 100644 priv/static/static/js/3.44ee95fa34170fe38ef7.js.map delete mode 100644 priv/static/static/js/3.56898c1005d9ba1b8d4a.js delete mode 100644 priv/static/static/js/3.56898c1005d9ba1b8d4a.js.map create mode 100644 priv/static/static/js/30.73f0507f6b66caa1b632.js create mode 100644 priv/static/static/js/30.73f0507f6b66caa1b632.js.map delete mode 100644 priv/static/static/js/30.d78855ca19bf749be905.js delete mode 100644 priv/static/static/js/30.d78855ca19bf749be905.js.map delete mode 100644 priv/static/static/js/4.2d3bef896b463484e6eb.js delete mode 100644 priv/static/static/js/4.2d3bef896b463484e6eb.js.map create mode 100644 priv/static/static/js/4.77639012e321d98c064c.js create mode 100644 priv/static/static/js/4.77639012e321d98c064c.js.map delete mode 100644 priv/static/static/js/5.84f3dce298bc720719c7.js delete mode 100644 priv/static/static/js/5.84f3dce298bc720719c7.js.map create mode 100644 priv/static/static/js/5.abcc811ac6e85e621b0d.js create mode 100644 priv/static/static/js/5.abcc811ac6e85e621b0d.js.map create mode 100644 priv/static/static/js/6.389907251866808cf2c4.js create mode 100644 priv/static/static/js/6.389907251866808cf2c4.js.map delete mode 100644 priv/static/static/js/6.b9497e1d403b901a664e.js delete mode 100644 priv/static/static/js/6.b9497e1d403b901a664e.js.map create mode 100644 priv/static/static/js/7.33e3cc5c9abab3f21825.js create mode 100644 priv/static/static/js/7.33e3cc5c9abab3f21825.js.map delete mode 100644 priv/static/static/js/7.455b574116ce3f004ffb.js delete mode 100644 priv/static/static/js/7.455b574116ce3f004ffb.js.map create mode 100644 priv/static/static/js/8.5e0b07052c330e85bead.js create mode 100644 priv/static/static/js/8.5e0b07052c330e85bead.js.map delete mode 100644 priv/static/static/js/8.8db9f2dcc5ed429777f7.js delete mode 100644 priv/static/static/js/8.8db9f2dcc5ed429777f7.js.map delete mode 100644 priv/static/static/js/9.da3973d058660aa9612f.js delete mode 100644 priv/static/static/js/9.da3973d058660aa9612f.js.map create mode 100644 priv/static/static/js/9.f8e3aa590f4a66aedc3f.js create mode 100644 priv/static/static/js/9.f8e3aa590f4a66aedc3f.js.map create mode 100644 priv/static/static/js/app.032cb80dafd1f208df1c.js create mode 100644 priv/static/static/js/app.032cb80dafd1f208df1c.js.map delete mode 100644 priv/static/static/js/app.31bba9f1e242ff273dcb.js delete mode 100644 priv/static/static/js/app.31bba9f1e242ff273dcb.js.map create mode 100644 priv/static/static/js/vendors~app.811c8482146cad566f7e.js create mode 100644 priv/static/static/js/vendors~app.811c8482146cad566f7e.js.map delete mode 100644 priv/static/static/js/vendors~app.9e24ed238da5a8538f50.js delete mode 100644 priv/static/static/js/vendors~app.9e24ed238da5a8538f50.js.map diff --git a/priv/static/index.html b/priv/static/index.html index 2257dec35..7dd080b2d 100644 --- a/priv/static/index.html +++ b/priv/static/index.html @@ -1 +1 @@ -Pleroma
\ No newline at end of file +Pleroma
\ No newline at end of file diff --git a/priv/static/static/css/app.6dbc7dea4fc148c85860.css b/priv/static/static/css/app.6dbc7dea4fc148c85860.css deleted file mode 100644 index 3927e3b77..000000000 Binary files a/priv/static/static/css/app.6dbc7dea4fc148c85860.css and /dev/null differ diff --git a/priv/static/static/css/app.6dbc7dea4fc148c85860.css.map b/priv/static/static/css/app.6dbc7dea4fc148c85860.css.map deleted file mode 100644 index 963d5b3b8..000000000 --- a/priv/static/static/css/app.6dbc7dea4fc148c85860.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///./src/components/tab_switcher/tab_switcher.scss","webpack:///./src/hocs/with_load_more/with_load_more.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACtOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C","file":"static/css/app.6dbc7dea4fc148c85860.css","sourcesContent":[".tab-switcher {\n display: -ms-flexbox;\n display: flex;\n}\n.tab-switcher .tab-icon {\n font-size: 2em;\n display: block;\n}\n.tab-switcher.top-tabs {\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher.top-tabs > .tabs {\n width: 100%;\n overflow-y: hidden;\n overflow-x: auto;\n padding-top: 5px;\n -ms-flex-direction: row;\n flex-direction: row;\n}\n.tab-switcher.top-tabs > .tabs::after, .tab-switcher.top-tabs > .tabs::before {\n content: \"\";\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher.top-tabs > .tabs .tab-wrapper {\n height: 28px;\n}\n.tab-switcher.top-tabs > .tabs .tab-wrapper:not(.active)::after {\n left: 0;\n right: 0;\n bottom: 0;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher.top-tabs > .tabs .tab {\n width: 100%;\n min-width: 1px;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n padding-bottom: 99px;\n margin-bottom: -93px;\n}\n.tab-switcher.top-tabs .contents.scrollable-tabs {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n}\n.tab-switcher.side-tabs {\n -ms-flex-direction: row;\n flex-direction: row;\n}\n@media all and (max-width: 800px) {\n .tab-switcher.side-tabs {\n overflow-x: auto;\n }\n}\n.tab-switcher.side-tabs > .contents {\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n}\n.tab-switcher.side-tabs > .tabs {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n overflow-y: auto;\n overflow-x: hidden;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher.side-tabs > .tabs::after, .tab-switcher.side-tabs > .tabs::before {\n -ms-flex-negative: 0;\n flex-shrink: 0;\n -ms-flex-preferred-size: 0.5em;\n flex-basis: 0.5em;\n content: \"\";\n border-right: 1px solid;\n border-right-color: #222;\n border-right-color: var(--border, #222);\n}\n.tab-switcher.side-tabs > .tabs::after {\n -ms-flex-positive: 1;\n flex-grow: 1;\n}\n.tab-switcher.side-tabs > .tabs::before {\n -ms-flex-positive: 0;\n flex-grow: 0;\n}\n.tab-switcher.side-tabs > .tabs .tab-wrapper {\n min-width: 10em;\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n@media all and (max-width: 800px) {\n .tab-switcher.side-tabs > .tabs .tab-wrapper {\n min-width: 1em;\n }\n}\n.tab-switcher.side-tabs > .tabs .tab-wrapper:not(.active)::after {\n top: 0;\n right: 0;\n bottom: 0;\n border-right: 1px solid;\n border-right-color: #222;\n border-right-color: var(--border, #222);\n}\n.tab-switcher.side-tabs > .tabs .tab-wrapper::before {\n -ms-flex: 0 0 6px;\n flex: 0 0 6px;\n content: \"\";\n border-right: 1px solid;\n border-right-color: #222;\n border-right-color: var(--border, #222);\n}\n.tab-switcher.side-tabs > .tabs .tab-wrapper:last-child .tab {\n margin-bottom: 0;\n}\n.tab-switcher.side-tabs > .tabs .tab {\n -ms-flex: 1;\n flex: 1;\n box-sizing: content-box;\n min-width: 10em;\n min-width: 1px;\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n padding-left: 1em;\n padding-right: calc(1em + 200px);\n margin-right: -200px;\n margin-left: 1em;\n}\n@media all and (max-width: 800px) {\n .tab-switcher.side-tabs > .tabs .tab {\n padding-left: 0.25em;\n padding-right: calc(.25em + 200px);\n margin-right: calc(.25em - 200px);\n margin-left: 0.25em;\n }\n .tab-switcher.side-tabs > .tabs .tab .text {\n display: none;\n }\n}\n.tab-switcher .contents {\n -ms-flex: 1 0 auto;\n flex: 1 0 auto;\n min-height: 0px;\n}\n.tab-switcher .contents .hidden {\n display: none;\n}\n.tab-switcher .contents .full-height:not(.hidden) {\n height: 100%;\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher .contents .full-height:not(.hidden) > *:not(.mobile-label) {\n -ms-flex: 1;\n flex: 1;\n}\n.tab-switcher .contents.scrollable-tabs {\n overflow-y: auto;\n}\n.tab-switcher .tab {\n position: relative;\n white-space: nowrap;\n padding: 6px 1em;\n background-color: #182230;\n background-color: var(--tab, #182230);\n}\n.tab-switcher .tab, .tab-switcher .tab:active .tab-icon {\n color: #b9b9ba;\n color: var(--tabText, #b9b9ba);\n}\n.tab-switcher .tab:not(.active) {\n z-index: 4;\n}\n.tab-switcher .tab:not(.active):hover {\n z-index: 6;\n}\n.tab-switcher .tab.active {\n background: transparent;\n z-index: 5;\n color: #b9b9ba;\n color: var(--tabActiveText, #b9b9ba);\n}\n.tab-switcher .tab img {\n max-height: 26px;\n vertical-align: top;\n margin-top: -5px;\n}\n.tab-switcher .tabs {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n box-sizing: border-box;\n}\n.tab-switcher .tabs::after, .tab-switcher .tabs::before {\n display: block;\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n}\n.tab-switcher .tab-wrapper {\n position: relative;\n display: -ms-flexbox;\n display: flex;\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n}\n.tab-switcher .tab-wrapper:not(.active)::after {\n content: \"\";\n position: absolute;\n z-index: 7;\n}\n.tab-switcher .mobile-label {\n padding-left: 0.3em;\n padding-bottom: 0.25em;\n margin-top: 0.5em;\n margin-left: 0.2em;\n margin-bottom: 0.25em;\n border-bottom: 1px solid var(--border, #222);\n}\n@media all and (min-width: 800px) {\n .tab-switcher .mobile-label {\n display: none;\n }\n}",".with-load-more-footer {\n padding: 10px;\n text-align: center;\n border-top: 1px solid;\n border-top-color: #222;\n border-top-color: var(--border, #222);\n}\n.with-load-more-footer .error {\n font-size: 14px;\n}\n.with-load-more-footer a {\n cursor: pointer;\n}"],"sourceRoot":""} \ No newline at end of file diff --git a/priv/static/static/css/app.77b1644622e3bae24b6b.css b/priv/static/static/css/app.77b1644622e3bae24b6b.css new file mode 100644 index 000000000..8038882c0 Binary files /dev/null and b/priv/static/static/css/app.77b1644622e3bae24b6b.css differ diff --git a/priv/static/static/css/app.77b1644622e3bae24b6b.css.map b/priv/static/static/css/app.77b1644622e3bae24b6b.css.map new file mode 100644 index 000000000..4b042ef35 --- /dev/null +++ b/priv/static/static/css/app.77b1644622e3bae24b6b.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/components/tab_switcher/tab_switcher.scss","webpack:///./src/hocs/with_load_more/with_load_more.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACtOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C","file":"static/css/app.77b1644622e3bae24b6b.css","sourcesContent":[".tab-switcher {\n display: -ms-flexbox;\n display: flex;\n}\n.tab-switcher .tab-icon {\n font-size: 2em;\n display: block;\n}\n.tab-switcher.top-tabs {\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher.top-tabs > .tabs {\n width: 100%;\n overflow-y: hidden;\n overflow-x: auto;\n padding-top: 5px;\n -ms-flex-direction: row;\n flex-direction: row;\n}\n.tab-switcher.top-tabs > .tabs::after, .tab-switcher.top-tabs > .tabs::before {\n content: \"\";\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher.top-tabs > .tabs .tab-wrapper {\n height: 28px;\n}\n.tab-switcher.top-tabs > .tabs .tab-wrapper:not(.active)::after {\n left: 0;\n right: 0;\n bottom: 0;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher.top-tabs > .tabs .tab {\n width: 100%;\n min-width: 1px;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n padding-bottom: 99px;\n margin-bottom: -93px;\n}\n.tab-switcher.top-tabs .contents.scrollable-tabs {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n}\n.tab-switcher.side-tabs {\n -ms-flex-direction: row;\n flex-direction: row;\n}\n@media all and (max-width: 800px) {\n .tab-switcher.side-tabs {\n overflow-x: auto;\n }\n}\n.tab-switcher.side-tabs > .contents {\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n}\n.tab-switcher.side-tabs > .tabs {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n overflow-y: auto;\n overflow-x: hidden;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher.side-tabs > .tabs::after, .tab-switcher.side-tabs > .tabs::before {\n -ms-flex-negative: 0;\n flex-shrink: 0;\n -ms-flex-preferred-size: 0.5em;\n flex-basis: 0.5em;\n content: \"\";\n border-right: 1px solid;\n border-right-color: #222;\n border-right-color: var(--border, #222);\n}\n.tab-switcher.side-tabs > .tabs::after {\n -ms-flex-positive: 1;\n flex-grow: 1;\n}\n.tab-switcher.side-tabs > .tabs::before {\n -ms-flex-positive: 0;\n flex-grow: 0;\n}\n.tab-switcher.side-tabs > .tabs .tab-wrapper {\n min-width: 10em;\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n@media all and (max-width: 800px) {\n .tab-switcher.side-tabs > .tabs .tab-wrapper {\n min-width: 1em;\n }\n}\n.tab-switcher.side-tabs > .tabs .tab-wrapper:not(.active)::after {\n top: 0;\n right: 0;\n bottom: 0;\n border-right: 1px solid;\n border-right-color: #222;\n border-right-color: var(--border, #222);\n}\n.tab-switcher.side-tabs > .tabs .tab-wrapper::before {\n -ms-flex: 0 0 6px;\n flex: 0 0 6px;\n content: \"\";\n border-right: 1px solid;\n border-right-color: #222;\n border-right-color: var(--border, #222);\n}\n.tab-switcher.side-tabs > .tabs .tab-wrapper:last-child .tab {\n margin-bottom: 0;\n}\n.tab-switcher.side-tabs > .tabs .tab {\n -ms-flex: 1;\n flex: 1;\n box-sizing: content-box;\n min-width: 10em;\n min-width: 1px;\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n padding-left: 1em;\n padding-right: calc(1em + 200px);\n margin-right: -200px;\n margin-left: 1em;\n}\n@media all and (max-width: 800px) {\n .tab-switcher.side-tabs > .tabs .tab {\n padding-left: 0.25em;\n padding-right: calc(.25em + 200px);\n margin-right: calc(.25em - 200px);\n margin-left: 0.25em;\n }\n .tab-switcher.side-tabs > .tabs .tab .text {\n display: none;\n }\n}\n.tab-switcher .contents {\n -ms-flex: 1 0 auto;\n flex: 1 0 auto;\n min-height: 0px;\n}\n.tab-switcher .contents .hidden {\n display: none;\n}\n.tab-switcher .contents .full-height:not(.hidden) {\n height: 100%;\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.tab-switcher .contents .full-height:not(.hidden) > *:not(.mobile-label) {\n -ms-flex: 1;\n flex: 1;\n}\n.tab-switcher .contents.scrollable-tabs {\n overflow-y: auto;\n}\n.tab-switcher .tab {\n position: relative;\n white-space: nowrap;\n padding: 6px 1em;\n background-color: #182230;\n background-color: var(--tab, #182230);\n}\n.tab-switcher .tab, .tab-switcher .tab:active .tab-icon {\n color: #b9b9ba;\n color: var(--tabText, #b9b9ba);\n}\n.tab-switcher .tab:not(.active) {\n z-index: 4;\n}\n.tab-switcher .tab:not(.active):hover {\n z-index: 6;\n}\n.tab-switcher .tab.active {\n background: transparent;\n z-index: 5;\n color: #b9b9ba;\n color: var(--tabActiveText, #b9b9ba);\n}\n.tab-switcher .tab img {\n max-height: 26px;\n vertical-align: top;\n margin-top: -5px;\n}\n.tab-switcher .tabs {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n box-sizing: border-box;\n}\n.tab-switcher .tabs::after, .tab-switcher .tabs::before {\n display: block;\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n}\n.tab-switcher .tab-wrapper {\n position: relative;\n display: -ms-flexbox;\n display: flex;\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n}\n.tab-switcher .tab-wrapper:not(.active)::after {\n content: \"\";\n position: absolute;\n z-index: 7;\n}\n.tab-switcher .mobile-label {\n padding-left: 0.3em;\n padding-bottom: 0.25em;\n margin-top: 0.5em;\n margin-left: 0.2em;\n margin-bottom: 0.25em;\n border-bottom: 1px solid var(--border, #222);\n}\n@media all and (min-width: 800px) {\n .tab-switcher .mobile-label {\n display: none;\n }\n}",".with-load-more-footer {\n padding: 10px;\n text-align: center;\n border-top: 1px solid;\n border-top-color: #222;\n border-top-color: var(--border, #222);\n}\n.with-load-more-footer .error {\n font-size: 14px;\n}\n.with-load-more-footer a {\n cursor: pointer;\n}"],"sourceRoot":""} \ No newline at end of file diff --git a/priv/static/static/font/fontello.1594823398494.eot b/priv/static/static/font/fontello.1594823398494.eot deleted file mode 100644 index 12e6beabf..000000000 Binary files a/priv/static/static/font/fontello.1594823398494.eot and /dev/null differ diff --git a/priv/static/static/font/fontello.1594823398494.svg b/priv/static/static/font/fontello.1594823398494.svg deleted file mode 100644 index 71b5d70af..000000000 --- a/priv/static/static/font/fontello.1594823398494.svg +++ /dev/null @@ -1,138 +0,0 @@ - - - -Copyright (C) 2020 by original authors @ fontello.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/priv/static/static/font/fontello.1594823398494.ttf b/priv/static/static/font/fontello.1594823398494.ttf deleted file mode 100644 index 6f21845a8..000000000 Binary files a/priv/static/static/font/fontello.1594823398494.ttf and /dev/null differ diff --git a/priv/static/static/font/fontello.1594823398494.woff b/priv/static/static/font/fontello.1594823398494.woff deleted file mode 100644 index a7cd098f4..000000000 Binary files a/priv/static/static/font/fontello.1594823398494.woff and /dev/null differ diff --git a/priv/static/static/font/fontello.1594823398494.woff2 b/priv/static/static/font/fontello.1594823398494.woff2 deleted file mode 100644 index c61bf111a..000000000 Binary files a/priv/static/static/font/fontello.1594823398494.woff2 and /dev/null differ diff --git a/priv/static/static/font/fontello.1597327457363.eot b/priv/static/static/font/fontello.1597327457363.eot new file mode 100644 index 000000000..af2c39275 Binary files /dev/null and b/priv/static/static/font/fontello.1597327457363.eot differ diff --git a/priv/static/static/font/fontello.1597327457363.svg b/priv/static/static/font/fontello.1597327457363.svg new file mode 100644 index 000000000..71b5d70af --- /dev/null +++ b/priv/static/static/font/fontello.1597327457363.svg @@ -0,0 +1,138 @@ + + + +Copyright (C) 2020 by original authors @ fontello.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/priv/static/static/font/fontello.1597327457363.ttf b/priv/static/static/font/fontello.1597327457363.ttf new file mode 100644 index 000000000..1d5640d5d Binary files /dev/null and b/priv/static/static/font/fontello.1597327457363.ttf differ diff --git a/priv/static/static/font/fontello.1597327457363.woff b/priv/static/static/font/fontello.1597327457363.woff new file mode 100644 index 000000000..c04735bf5 Binary files /dev/null and b/priv/static/static/font/fontello.1597327457363.woff differ diff --git a/priv/static/static/font/fontello.1597327457363.woff2 b/priv/static/static/font/fontello.1597327457363.woff2 new file mode 100644 index 000000000..f53414761 Binary files /dev/null and b/priv/static/static/font/fontello.1597327457363.woff2 differ diff --git a/priv/static/static/fontello.1597327457363.css b/priv/static/static/fontello.1597327457363.css new file mode 100644 index 000000000..22d148873 Binary files /dev/null and b/priv/static/static/fontello.1597327457363.css differ diff --git a/priv/static/static/js/10.5ef4671883649cf93524.js b/priv/static/static/js/10.5ef4671883649cf93524.js deleted file mode 100644 index 6819c854b..000000000 Binary files a/priv/static/static/js/10.5ef4671883649cf93524.js and /dev/null differ diff --git a/priv/static/static/js/10.5ef4671883649cf93524.js.map b/priv/static/static/js/10.5ef4671883649cf93524.js.map deleted file mode 100644 index 95fa2207e..000000000 Binary files a/priv/static/static/js/10.5ef4671883649cf93524.js.map and /dev/null differ diff --git a/priv/static/static/js/10.8c5b75840b696a152c7e.js b/priv/static/static/js/10.8c5b75840b696a152c7e.js new file mode 100644 index 000000000..eb95d66d1 Binary files /dev/null and b/priv/static/static/js/10.8c5b75840b696a152c7e.js differ diff --git a/priv/static/static/js/10.8c5b75840b696a152c7e.js.map b/priv/static/static/js/10.8c5b75840b696a152c7e.js.map new file mode 100644 index 000000000..b390fbeaf Binary files /dev/null and b/priv/static/static/js/10.8c5b75840b696a152c7e.js.map differ diff --git a/priv/static/static/js/11.bfcde1c26c4d54b84ee4.js b/priv/static/static/js/11.bfcde1c26c4d54b84ee4.js new file mode 100644 index 000000000..0dea63f5a Binary files /dev/null and b/priv/static/static/js/11.bfcde1c26c4d54b84ee4.js differ diff --git a/priv/static/static/js/11.bfcde1c26c4d54b84ee4.js.map b/priv/static/static/js/11.bfcde1c26c4d54b84ee4.js.map new file mode 100644 index 000000000..2b2305773 Binary files /dev/null and b/priv/static/static/js/11.bfcde1c26c4d54b84ee4.js.map differ diff --git a/priv/static/static/js/11.c5b938b4349f87567338.js b/priv/static/static/js/11.c5b938b4349f87567338.js deleted file mode 100644 index b97f69bf3..000000000 Binary files a/priv/static/static/js/11.c5b938b4349f87567338.js and /dev/null differ diff --git a/priv/static/static/js/11.c5b938b4349f87567338.js.map b/priv/static/static/js/11.c5b938b4349f87567338.js.map deleted file mode 100644 index 5ccf83b1d..000000000 Binary files a/priv/static/static/js/11.c5b938b4349f87567338.js.map and /dev/null differ diff --git a/priv/static/static/js/12.76095ee23394e0ef65bb.js b/priv/static/static/js/12.76095ee23394e0ef65bb.js new file mode 100644 index 000000000..6c34e2da2 Binary files /dev/null and b/priv/static/static/js/12.76095ee23394e0ef65bb.js differ diff --git a/priv/static/static/js/12.76095ee23394e0ef65bb.js.map b/priv/static/static/js/12.76095ee23394e0ef65bb.js.map new file mode 100644 index 000000000..e00137a2b Binary files /dev/null and b/priv/static/static/js/12.76095ee23394e0ef65bb.js.map differ diff --git a/priv/static/static/js/12.ab82f9512fa85e78c114.js b/priv/static/static/js/12.ab82f9512fa85e78c114.js deleted file mode 100644 index 100d72b33..000000000 Binary files a/priv/static/static/js/12.ab82f9512fa85e78c114.js and /dev/null differ diff --git a/priv/static/static/js/12.ab82f9512fa85e78c114.js.map b/priv/static/static/js/12.ab82f9512fa85e78c114.js.map deleted file mode 100644 index 23335ae23..000000000 Binary files a/priv/static/static/js/12.ab82f9512fa85e78c114.js.map and /dev/null differ diff --git a/priv/static/static/js/13.40e59c5015d3307b94ad.js b/priv/static/static/js/13.40e59c5015d3307b94ad.js deleted file mode 100644 index 2088bb6b7..000000000 Binary files a/priv/static/static/js/13.40e59c5015d3307b94ad.js and /dev/null differ diff --git a/priv/static/static/js/13.40e59c5015d3307b94ad.js.map b/priv/static/static/js/13.40e59c5015d3307b94ad.js.map deleted file mode 100644 index 3931b5ef9..000000000 Binary files a/priv/static/static/js/13.40e59c5015d3307b94ad.js.map and /dev/null differ diff --git a/priv/static/static/js/13.957b04ac11d6cde66f5b.js b/priv/static/static/js/13.957b04ac11d6cde66f5b.js new file mode 100644 index 000000000..917b6a58b Binary files /dev/null and b/priv/static/static/js/13.957b04ac11d6cde66f5b.js differ diff --git a/priv/static/static/js/13.957b04ac11d6cde66f5b.js.map b/priv/static/static/js/13.957b04ac11d6cde66f5b.js.map new file mode 100644 index 000000000..25434f73b Binary files /dev/null and b/priv/static/static/js/13.957b04ac11d6cde66f5b.js.map differ diff --git a/priv/static/static/js/14.aae5a904931591edfaa7.js b/priv/static/static/js/14.aae5a904931591edfaa7.js new file mode 100644 index 000000000..001914ad7 Binary files /dev/null and b/priv/static/static/js/14.aae5a904931591edfaa7.js differ diff --git a/priv/static/static/js/14.aae5a904931591edfaa7.js.map b/priv/static/static/js/14.aae5a904931591edfaa7.js.map new file mode 100644 index 000000000..24719fee8 Binary files /dev/null and b/priv/static/static/js/14.aae5a904931591edfaa7.js.map differ diff --git a/priv/static/static/js/14.de791a47ee5249a526b1.js b/priv/static/static/js/14.de791a47ee5249a526b1.js deleted file mode 100644 index 0e341275e..000000000 Binary files a/priv/static/static/js/14.de791a47ee5249a526b1.js and /dev/null differ diff --git a/priv/static/static/js/14.de791a47ee5249a526b1.js.map b/priv/static/static/js/14.de791a47ee5249a526b1.js.map deleted file mode 100644 index 4bef54546..000000000 Binary files a/priv/static/static/js/14.de791a47ee5249a526b1.js.map and /dev/null differ diff --git a/priv/static/static/js/15.139f5de3950adc3b66df.js b/priv/static/static/js/15.139f5de3950adc3b66df.js new file mode 100644 index 000000000..303e00130 Binary files /dev/null and b/priv/static/static/js/15.139f5de3950adc3b66df.js differ diff --git a/priv/static/static/js/15.139f5de3950adc3b66df.js.map b/priv/static/static/js/15.139f5de3950adc3b66df.js.map new file mode 100644 index 000000000..d5a3c800d Binary files /dev/null and b/priv/static/static/js/15.139f5de3950adc3b66df.js.map differ diff --git a/priv/static/static/js/15.e24854297ad682aec45a.js b/priv/static/static/js/15.e24854297ad682aec45a.js deleted file mode 100644 index 671370192..000000000 Binary files a/priv/static/static/js/15.e24854297ad682aec45a.js and /dev/null differ diff --git a/priv/static/static/js/15.e24854297ad682aec45a.js.map b/priv/static/static/js/15.e24854297ad682aec45a.js.map deleted file mode 100644 index 89789a542..000000000 Binary files a/priv/static/static/js/15.e24854297ad682aec45a.js.map and /dev/null differ diff --git a/priv/static/static/js/16.7b8466d62084c04f6671.js b/priv/static/static/js/16.7b8466d62084c04f6671.js new file mode 100644 index 000000000..587b41dd0 Binary files /dev/null and b/priv/static/static/js/16.7b8466d62084c04f6671.js differ diff --git a/priv/static/static/js/16.7b8466d62084c04f6671.js.map b/priv/static/static/js/16.7b8466d62084c04f6671.js.map new file mode 100644 index 000000000..22818639f Binary files /dev/null and b/priv/static/static/js/16.7b8466d62084c04f6671.js.map differ diff --git a/priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js b/priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js deleted file mode 100644 index 6a3ea9513..000000000 Binary files a/priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js and /dev/null differ diff --git a/priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js.map b/priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js.map deleted file mode 100644 index fec45b087..000000000 Binary files a/priv/static/static/js/16.b7b0e4b8227a50fcb9bb.js.map and /dev/null differ diff --git a/priv/static/static/js/17.c98118b6bb84ee3b5b08.js b/priv/static/static/js/17.c98118b6bb84ee3b5b08.js deleted file mode 100644 index c41f0b6b8..000000000 Binary files a/priv/static/static/js/17.c98118b6bb84ee3b5b08.js and /dev/null differ diff --git a/priv/static/static/js/17.c98118b6bb84ee3b5b08.js.map b/priv/static/static/js/17.c98118b6bb84ee3b5b08.js.map deleted file mode 100644 index 0c20fc89b..000000000 Binary files a/priv/static/static/js/17.c98118b6bb84ee3b5b08.js.map and /dev/null differ diff --git a/priv/static/static/js/17.e8ec1f5666cb4e28784a.js b/priv/static/static/js/17.e8ec1f5666cb4e28784a.js new file mode 100644 index 000000000..03a7d28e5 Binary files /dev/null and b/priv/static/static/js/17.e8ec1f5666cb4e28784a.js differ diff --git a/priv/static/static/js/17.e8ec1f5666cb4e28784a.js.map b/priv/static/static/js/17.e8ec1f5666cb4e28784a.js.map new file mode 100644 index 000000000..0fe92287e Binary files /dev/null and b/priv/static/static/js/17.e8ec1f5666cb4e28784a.js.map differ diff --git a/priv/static/static/js/18.89c20aa67a4dd067ea37.js b/priv/static/static/js/18.89c20aa67a4dd067ea37.js deleted file mode 100644 index db1c78a49..000000000 Binary files a/priv/static/static/js/18.89c20aa67a4dd067ea37.js and /dev/null differ diff --git a/priv/static/static/js/18.89c20aa67a4dd067ea37.js.map b/priv/static/static/js/18.89c20aa67a4dd067ea37.js.map deleted file mode 100644 index 72cdf0e0e..000000000 Binary files a/priv/static/static/js/18.89c20aa67a4dd067ea37.js.map and /dev/null differ diff --git a/priv/static/static/js/18.d32389579b85948022b8.js b/priv/static/static/js/18.d32389579b85948022b8.js new file mode 100644 index 000000000..477f6e06f Binary files /dev/null and b/priv/static/static/js/18.d32389579b85948022b8.js differ diff --git a/priv/static/static/js/18.d32389579b85948022b8.js.map b/priv/static/static/js/18.d32389579b85948022b8.js.map new file mode 100644 index 000000000..62fc5b84f Binary files /dev/null and b/priv/static/static/js/18.d32389579b85948022b8.js.map differ diff --git a/priv/static/static/js/19.6e13bad8131c4501c1c5.js b/priv/static/static/js/19.6e13bad8131c4501c1c5.js deleted file mode 100644 index 8b32827cc..000000000 Binary files a/priv/static/static/js/19.6e13bad8131c4501c1c5.js and /dev/null differ diff --git a/priv/static/static/js/19.6e13bad8131c4501c1c5.js.map b/priv/static/static/js/19.6e13bad8131c4501c1c5.js.map deleted file mode 100644 index 762d85e27..000000000 Binary files a/priv/static/static/js/19.6e13bad8131c4501c1c5.js.map and /dev/null differ diff --git a/priv/static/static/js/19.d180c594b843c17c80fa.js b/priv/static/static/js/19.d180c594b843c17c80fa.js new file mode 100644 index 000000000..c30dc75c2 Binary files /dev/null and b/priv/static/static/js/19.d180c594b843c17c80fa.js differ diff --git a/priv/static/static/js/19.d180c594b843c17c80fa.js.map b/priv/static/static/js/19.d180c594b843c17c80fa.js.map new file mode 100644 index 000000000..e90081dd9 Binary files /dev/null and b/priv/static/static/js/19.d180c594b843c17c80fa.js.map differ diff --git a/priv/static/static/js/2.5ecefab707beea40b7f0.js b/priv/static/static/js/2.5ecefab707beea40b7f0.js new file mode 100644 index 000000000..bf563c79f Binary files /dev/null and b/priv/static/static/js/2.5ecefab707beea40b7f0.js differ diff --git a/priv/static/static/js/2.5ecefab707beea40b7f0.js.map b/priv/static/static/js/2.5ecefab707beea40b7f0.js.map new file mode 100644 index 000000000..7452e1f6e Binary files /dev/null and b/priv/static/static/js/2.5ecefab707beea40b7f0.js.map differ diff --git a/priv/static/static/js/2.78a48aa26599b00c3b8d.js b/priv/static/static/js/2.78a48aa26599b00c3b8d.js deleted file mode 100644 index ecb27aa9c..000000000 Binary files a/priv/static/static/js/2.78a48aa26599b00c3b8d.js and /dev/null differ diff --git a/priv/static/static/js/2.78a48aa26599b00c3b8d.js.map b/priv/static/static/js/2.78a48aa26599b00c3b8d.js.map deleted file mode 100644 index 167cfa1c6..000000000 Binary files a/priv/static/static/js/2.78a48aa26599b00c3b8d.js.map and /dev/null differ diff --git a/priv/static/static/js/20.27e04f2209628de3092b.js b/priv/static/static/js/20.27e04f2209628de3092b.js new file mode 100644 index 000000000..e41b60066 Binary files /dev/null and b/priv/static/static/js/20.27e04f2209628de3092b.js differ diff --git a/priv/static/static/js/20.27e04f2209628de3092b.js.map b/priv/static/static/js/20.27e04f2209628de3092b.js.map new file mode 100644 index 000000000..4009ef5b9 Binary files /dev/null and b/priv/static/static/js/20.27e04f2209628de3092b.js.map differ diff --git a/priv/static/static/js/20.3615c3cea2e1c2707a4f.js b/priv/static/static/js/20.3615c3cea2e1c2707a4f.js deleted file mode 100644 index 74f89016c..000000000 Binary files a/priv/static/static/js/20.3615c3cea2e1c2707a4f.js and /dev/null differ diff --git a/priv/static/static/js/20.3615c3cea2e1c2707a4f.js.map b/priv/static/static/js/20.3615c3cea2e1c2707a4f.js.map deleted file mode 100644 index acddecea7..000000000 Binary files a/priv/static/static/js/20.3615c3cea2e1c2707a4f.js.map and /dev/null differ diff --git a/priv/static/static/js/21.641aba6f96885c381070.js b/priv/static/static/js/21.641aba6f96885c381070.js new file mode 100644 index 000000000..d80f64e11 Binary files /dev/null and b/priv/static/static/js/21.641aba6f96885c381070.js differ diff --git a/priv/static/static/js/21.641aba6f96885c381070.js.map b/priv/static/static/js/21.641aba6f96885c381070.js.map new file mode 100644 index 000000000..8f6253113 Binary files /dev/null and b/priv/static/static/js/21.641aba6f96885c381070.js.map differ diff --git a/priv/static/static/js/21.64dedfc646e13e6f7915.js b/priv/static/static/js/21.64dedfc646e13e6f7915.js deleted file mode 100644 index 407e6665e..000000000 Binary files a/priv/static/static/js/21.64dedfc646e13e6f7915.js and /dev/null differ diff --git a/priv/static/static/js/21.64dedfc646e13e6f7915.js.map b/priv/static/static/js/21.64dedfc646e13e6f7915.js.map deleted file mode 100644 index 8e3432668..000000000 Binary files a/priv/static/static/js/21.64dedfc646e13e6f7915.js.map and /dev/null differ diff --git a/priv/static/static/js/22.6fa63bc6a054b7638e9e.js b/priv/static/static/js/22.6fa63bc6a054b7638e9e.js deleted file mode 100644 index 4a8740c99..000000000 Binary files a/priv/static/static/js/22.6fa63bc6a054b7638e9e.js and /dev/null differ diff --git a/priv/static/static/js/22.6fa63bc6a054b7638e9e.js.map b/priv/static/static/js/22.6fa63bc6a054b7638e9e.js.map deleted file mode 100644 index 1c556f040..000000000 Binary files a/priv/static/static/js/22.6fa63bc6a054b7638e9e.js.map and /dev/null differ diff --git a/priv/static/static/js/22.cbe4790c7601004ed96f.js b/priv/static/static/js/22.cbe4790c7601004ed96f.js new file mode 100644 index 000000000..0e9c6ab97 Binary files /dev/null and b/priv/static/static/js/22.cbe4790c7601004ed96f.js differ diff --git a/priv/static/static/js/22.cbe4790c7601004ed96f.js.map b/priv/static/static/js/22.cbe4790c7601004ed96f.js.map new file mode 100644 index 000000000..8de20817c Binary files /dev/null and b/priv/static/static/js/22.cbe4790c7601004ed96f.js.map differ diff --git a/priv/static/static/js/23.96b5bf8d37de3bf02a17.js b/priv/static/static/js/23.96b5bf8d37de3bf02a17.js new file mode 100644 index 000000000..6a78c71fd Binary files /dev/null and b/priv/static/static/js/23.96b5bf8d37de3bf02a17.js differ diff --git a/priv/static/static/js/23.96b5bf8d37de3bf02a17.js.map b/priv/static/static/js/23.96b5bf8d37de3bf02a17.js.map new file mode 100644 index 000000000..12929720a Binary files /dev/null and b/priv/static/static/js/23.96b5bf8d37de3bf02a17.js.map differ diff --git a/priv/static/static/js/23.e0ddea2b6e049d221ee7.js b/priv/static/static/js/23.e0ddea2b6e049d221ee7.js deleted file mode 100644 index 51fe36368..000000000 Binary files a/priv/static/static/js/23.e0ddea2b6e049d221ee7.js and /dev/null differ diff --git a/priv/static/static/js/23.e0ddea2b6e049d221ee7.js.map b/priv/static/static/js/23.e0ddea2b6e049d221ee7.js.map deleted file mode 100644 index 36bae2bf4..000000000 Binary files a/priv/static/static/js/23.e0ddea2b6e049d221ee7.js.map and /dev/null differ diff --git a/priv/static/static/js/24.38e3b9d44e9ee703ebf6.js b/priv/static/static/js/24.38e3b9d44e9ee703ebf6.js deleted file mode 100644 index e5abf0af6..000000000 Binary files a/priv/static/static/js/24.38e3b9d44e9ee703ebf6.js and /dev/null differ diff --git a/priv/static/static/js/24.38e3b9d44e9ee703ebf6.js.map b/priv/static/static/js/24.38e3b9d44e9ee703ebf6.js.map deleted file mode 100644 index 09f3c19d0..000000000 Binary files a/priv/static/static/js/24.38e3b9d44e9ee703ebf6.js.map and /dev/null differ diff --git a/priv/static/static/js/24.5e5eea3542b0e17c6479.js b/priv/static/static/js/24.5e5eea3542b0e17c6479.js new file mode 100644 index 000000000..45787dddd Binary files /dev/null and b/priv/static/static/js/24.5e5eea3542b0e17c6479.js differ diff --git a/priv/static/static/js/24.5e5eea3542b0e17c6479.js.map b/priv/static/static/js/24.5e5eea3542b0e17c6479.js.map new file mode 100644 index 000000000..1938ee57a Binary files /dev/null and b/priv/static/static/js/24.5e5eea3542b0e17c6479.js.map differ diff --git a/priv/static/static/js/25.696b41c0a8660e1f85af.js b/priv/static/static/js/25.696b41c0a8660e1f85af.js deleted file mode 100644 index b114890fc..000000000 Binary files a/priv/static/static/js/25.696b41c0a8660e1f85af.js and /dev/null differ diff --git a/priv/static/static/js/25.696b41c0a8660e1f85af.js.map b/priv/static/static/js/25.696b41c0a8660e1f85af.js.map deleted file mode 100644 index f6d208812..000000000 Binary files a/priv/static/static/js/25.696b41c0a8660e1f85af.js.map and /dev/null differ diff --git a/priv/static/static/js/25.dd8471a33b5a4d256564.js b/priv/static/static/js/25.dd8471a33b5a4d256564.js new file mode 100644 index 000000000..b30f01f9b Binary files /dev/null and b/priv/static/static/js/25.dd8471a33b5a4d256564.js differ diff --git a/priv/static/static/js/25.dd8471a33b5a4d256564.js.map b/priv/static/static/js/25.dd8471a33b5a4d256564.js.map new file mode 100644 index 000000000..e6a6bf3a0 Binary files /dev/null and b/priv/static/static/js/25.dd8471a33b5a4d256564.js.map differ diff --git a/priv/static/static/js/26.1168f22384be75dc5492.js b/priv/static/static/js/26.1168f22384be75dc5492.js deleted file mode 100644 index b77a4d30f..000000000 Binary files a/priv/static/static/js/26.1168f22384be75dc5492.js and /dev/null differ diff --git a/priv/static/static/js/26.1168f22384be75dc5492.js.map b/priv/static/static/js/26.1168f22384be75dc5492.js.map deleted file mode 100644 index c9b0d8495..000000000 Binary files a/priv/static/static/js/26.1168f22384be75dc5492.js.map and /dev/null differ diff --git a/priv/static/static/js/26.91a9c2effdd1a423a79f.js b/priv/static/static/js/26.91a9c2effdd1a423a79f.js new file mode 100644 index 000000000..f30ff939a Binary files /dev/null and b/priv/static/static/js/26.91a9c2effdd1a423a79f.js differ diff --git a/priv/static/static/js/26.91a9c2effdd1a423a79f.js.map b/priv/static/static/js/26.91a9c2effdd1a423a79f.js.map new file mode 100644 index 000000000..ae4781108 Binary files /dev/null and b/priv/static/static/js/26.91a9c2effdd1a423a79f.js.map differ diff --git a/priv/static/static/js/27.3c0cfbb2a898b35486dd.js b/priv/static/static/js/27.3c0cfbb2a898b35486dd.js deleted file mode 100644 index a0765356f..000000000 Binary files a/priv/static/static/js/27.3c0cfbb2a898b35486dd.js and /dev/null differ diff --git a/priv/static/static/js/27.3c0cfbb2a898b35486dd.js.map b/priv/static/static/js/27.3c0cfbb2a898b35486dd.js.map deleted file mode 100644 index 0cc5f46b2..000000000 Binary files a/priv/static/static/js/27.3c0cfbb2a898b35486dd.js.map and /dev/null differ diff --git a/priv/static/static/js/27.949d608895f6e29a2fc2.js b/priv/static/static/js/27.949d608895f6e29a2fc2.js new file mode 100644 index 000000000..f735c1a04 Binary files /dev/null and b/priv/static/static/js/27.949d608895f6e29a2fc2.js differ diff --git a/priv/static/static/js/27.949d608895f6e29a2fc2.js.map b/priv/static/static/js/27.949d608895f6e29a2fc2.js.map new file mode 100644 index 000000000..9f75161dd Binary files /dev/null and b/priv/static/static/js/27.949d608895f6e29a2fc2.js.map differ diff --git a/priv/static/static/js/28.1e879ccb6222c26ee837.js b/priv/static/static/js/28.1e879ccb6222c26ee837.js new file mode 100644 index 000000000..64e286799 Binary files /dev/null and b/priv/static/static/js/28.1e879ccb6222c26ee837.js differ diff --git a/priv/static/static/js/28.1e879ccb6222c26ee837.js.map b/priv/static/static/js/28.1e879ccb6222c26ee837.js.map new file mode 100644 index 000000000..123aae91b Binary files /dev/null and b/priv/static/static/js/28.1e879ccb6222c26ee837.js.map differ diff --git a/priv/static/static/js/28.926c71d6f1813e177271.js b/priv/static/static/js/28.926c71d6f1813e177271.js deleted file mode 100644 index 55cf840f2..000000000 Binary files a/priv/static/static/js/28.926c71d6f1813e177271.js and /dev/null differ diff --git a/priv/static/static/js/28.926c71d6f1813e177271.js.map b/priv/static/static/js/28.926c71d6f1813e177271.js.map deleted file mode 100644 index 1ae8f08cb..000000000 Binary files a/priv/static/static/js/28.926c71d6f1813e177271.js.map and /dev/null differ diff --git a/priv/static/static/js/29.187064ebed099ae45749.js b/priv/static/static/js/29.187064ebed099ae45749.js deleted file mode 100644 index 6eaae0226..000000000 Binary files a/priv/static/static/js/29.187064ebed099ae45749.js and /dev/null differ diff --git a/priv/static/static/js/29.187064ebed099ae45749.js.map b/priv/static/static/js/29.187064ebed099ae45749.js.map deleted file mode 100644 index b5dd63f96..000000000 Binary files a/priv/static/static/js/29.187064ebed099ae45749.js.map and /dev/null differ diff --git a/priv/static/static/js/29.a0eb0eee98462dc00d86.js b/priv/static/static/js/29.a0eb0eee98462dc00d86.js new file mode 100644 index 000000000..740e150ca Binary files /dev/null and b/priv/static/static/js/29.a0eb0eee98462dc00d86.js differ diff --git a/priv/static/static/js/29.a0eb0eee98462dc00d86.js.map b/priv/static/static/js/29.a0eb0eee98462dc00d86.js.map new file mode 100644 index 000000000..357679d53 Binary files /dev/null and b/priv/static/static/js/29.a0eb0eee98462dc00d86.js.map differ diff --git a/priv/static/static/js/3.44ee95fa34170fe38ef7.js b/priv/static/static/js/3.44ee95fa34170fe38ef7.js new file mode 100644 index 000000000..ad2b9294c Binary files /dev/null and b/priv/static/static/js/3.44ee95fa34170fe38ef7.js differ diff --git a/priv/static/static/js/3.44ee95fa34170fe38ef7.js.map b/priv/static/static/js/3.44ee95fa34170fe38ef7.js.map new file mode 100644 index 000000000..7efe5d6a5 Binary files /dev/null and b/priv/static/static/js/3.44ee95fa34170fe38ef7.js.map differ diff --git a/priv/static/static/js/3.56898c1005d9ba1b8d4a.js b/priv/static/static/js/3.56898c1005d9ba1b8d4a.js deleted file mode 100644 index 6b20ecb04..000000000 Binary files a/priv/static/static/js/3.56898c1005d9ba1b8d4a.js and /dev/null differ diff --git a/priv/static/static/js/3.56898c1005d9ba1b8d4a.js.map b/priv/static/static/js/3.56898c1005d9ba1b8d4a.js.map deleted file mode 100644 index 594d9047b..000000000 Binary files a/priv/static/static/js/3.56898c1005d9ba1b8d4a.js.map and /dev/null differ diff --git a/priv/static/static/js/30.73f0507f6b66caa1b632.js b/priv/static/static/js/30.73f0507f6b66caa1b632.js new file mode 100644 index 000000000..0f1beeb58 Binary files /dev/null and b/priv/static/static/js/30.73f0507f6b66caa1b632.js differ diff --git a/priv/static/static/js/30.73f0507f6b66caa1b632.js.map b/priv/static/static/js/30.73f0507f6b66caa1b632.js.map new file mode 100644 index 000000000..e73f818cd Binary files /dev/null and b/priv/static/static/js/30.73f0507f6b66caa1b632.js.map differ diff --git a/priv/static/static/js/30.d78855ca19bf749be905.js b/priv/static/static/js/30.d78855ca19bf749be905.js deleted file mode 100644 index 9202d19d3..000000000 Binary files a/priv/static/static/js/30.d78855ca19bf749be905.js and /dev/null differ diff --git a/priv/static/static/js/30.d78855ca19bf749be905.js.map b/priv/static/static/js/30.d78855ca19bf749be905.js.map deleted file mode 100644 index b9f39664d..000000000 Binary files a/priv/static/static/js/30.d78855ca19bf749be905.js.map and /dev/null differ diff --git a/priv/static/static/js/4.2d3bef896b463484e6eb.js b/priv/static/static/js/4.2d3bef896b463484e6eb.js deleted file mode 100644 index 4a611feb4..000000000 Binary files a/priv/static/static/js/4.2d3bef896b463484e6eb.js and /dev/null differ diff --git a/priv/static/static/js/4.2d3bef896b463484e6eb.js.map b/priv/static/static/js/4.2d3bef896b463484e6eb.js.map deleted file mode 100644 index ebcc883e5..000000000 Binary files a/priv/static/static/js/4.2d3bef896b463484e6eb.js.map and /dev/null differ diff --git a/priv/static/static/js/4.77639012e321d98c064c.js b/priv/static/static/js/4.77639012e321d98c064c.js new file mode 100644 index 000000000..e8d35a81d Binary files /dev/null and b/priv/static/static/js/4.77639012e321d98c064c.js differ diff --git a/priv/static/static/js/4.77639012e321d98c064c.js.map b/priv/static/static/js/4.77639012e321d98c064c.js.map new file mode 100644 index 000000000..1a0373e08 Binary files /dev/null and b/priv/static/static/js/4.77639012e321d98c064c.js.map differ diff --git a/priv/static/static/js/5.84f3dce298bc720719c7.js b/priv/static/static/js/5.84f3dce298bc720719c7.js deleted file mode 100644 index 242b2a525..000000000 Binary files a/priv/static/static/js/5.84f3dce298bc720719c7.js and /dev/null differ diff --git a/priv/static/static/js/5.84f3dce298bc720719c7.js.map b/priv/static/static/js/5.84f3dce298bc720719c7.js.map deleted file mode 100644 index 4fcc32982..000000000 Binary files a/priv/static/static/js/5.84f3dce298bc720719c7.js.map and /dev/null differ diff --git a/priv/static/static/js/5.abcc811ac6e85e621b0d.js b/priv/static/static/js/5.abcc811ac6e85e621b0d.js new file mode 100644 index 000000000..1575d2a95 Binary files /dev/null and b/priv/static/static/js/5.abcc811ac6e85e621b0d.js differ diff --git a/priv/static/static/js/5.abcc811ac6e85e621b0d.js.map b/priv/static/static/js/5.abcc811ac6e85e621b0d.js.map new file mode 100644 index 000000000..03251d1d8 Binary files /dev/null and b/priv/static/static/js/5.abcc811ac6e85e621b0d.js.map differ diff --git a/priv/static/static/js/6.389907251866808cf2c4.js b/priv/static/static/js/6.389907251866808cf2c4.js new file mode 100644 index 000000000..def098eda Binary files /dev/null and b/priv/static/static/js/6.389907251866808cf2c4.js differ diff --git a/priv/static/static/js/6.389907251866808cf2c4.js.map b/priv/static/static/js/6.389907251866808cf2c4.js.map new file mode 100644 index 000000000..7b96d2998 Binary files /dev/null and b/priv/static/static/js/6.389907251866808cf2c4.js.map differ diff --git a/priv/static/static/js/6.b9497e1d403b901a664e.js b/priv/static/static/js/6.b9497e1d403b901a664e.js deleted file mode 100644 index 8c66e9062..000000000 Binary files a/priv/static/static/js/6.b9497e1d403b901a664e.js and /dev/null differ diff --git a/priv/static/static/js/6.b9497e1d403b901a664e.js.map b/priv/static/static/js/6.b9497e1d403b901a664e.js.map deleted file mode 100644 index 5af0576c7..000000000 Binary files a/priv/static/static/js/6.b9497e1d403b901a664e.js.map and /dev/null differ diff --git a/priv/static/static/js/7.33e3cc5c9abab3f21825.js b/priv/static/static/js/7.33e3cc5c9abab3f21825.js new file mode 100644 index 000000000..6a4e332e9 Binary files /dev/null and b/priv/static/static/js/7.33e3cc5c9abab3f21825.js differ diff --git a/priv/static/static/js/7.33e3cc5c9abab3f21825.js.map b/priv/static/static/js/7.33e3cc5c9abab3f21825.js.map new file mode 100644 index 000000000..a04c36f4c Binary files /dev/null and b/priv/static/static/js/7.33e3cc5c9abab3f21825.js.map differ diff --git a/priv/static/static/js/7.455b574116ce3f004ffb.js b/priv/static/static/js/7.455b574116ce3f004ffb.js deleted file mode 100644 index 0e35f6904..000000000 Binary files a/priv/static/static/js/7.455b574116ce3f004ffb.js and /dev/null differ diff --git a/priv/static/static/js/7.455b574116ce3f004ffb.js.map b/priv/static/static/js/7.455b574116ce3f004ffb.js.map deleted file mode 100644 index 971b570e1..000000000 Binary files a/priv/static/static/js/7.455b574116ce3f004ffb.js.map and /dev/null differ diff --git a/priv/static/static/js/8.5e0b07052c330e85bead.js b/priv/static/static/js/8.5e0b07052c330e85bead.js new file mode 100644 index 000000000..7fd0ec5a1 Binary files /dev/null and b/priv/static/static/js/8.5e0b07052c330e85bead.js differ diff --git a/priv/static/static/js/8.5e0b07052c330e85bead.js.map b/priv/static/static/js/8.5e0b07052c330e85bead.js.map new file mode 100644 index 000000000..d324ed4b0 Binary files /dev/null and b/priv/static/static/js/8.5e0b07052c330e85bead.js.map differ diff --git a/priv/static/static/js/8.8db9f2dcc5ed429777f7.js b/priv/static/static/js/8.8db9f2dcc5ed429777f7.js deleted file mode 100644 index 79082fc7c..000000000 Binary files a/priv/static/static/js/8.8db9f2dcc5ed429777f7.js and /dev/null differ diff --git a/priv/static/static/js/8.8db9f2dcc5ed429777f7.js.map b/priv/static/static/js/8.8db9f2dcc5ed429777f7.js.map deleted file mode 100644 index e193375de..000000000 Binary files a/priv/static/static/js/8.8db9f2dcc5ed429777f7.js.map and /dev/null differ diff --git a/priv/static/static/js/9.da3973d058660aa9612f.js b/priv/static/static/js/9.da3973d058660aa9612f.js deleted file mode 100644 index 50d977f67..000000000 Binary files a/priv/static/static/js/9.da3973d058660aa9612f.js and /dev/null differ diff --git a/priv/static/static/js/9.da3973d058660aa9612f.js.map b/priv/static/static/js/9.da3973d058660aa9612f.js.map deleted file mode 100644 index 4c8f70599..000000000 Binary files a/priv/static/static/js/9.da3973d058660aa9612f.js.map and /dev/null differ diff --git a/priv/static/static/js/9.f8e3aa590f4a66aedc3f.js b/priv/static/static/js/9.f8e3aa590f4a66aedc3f.js new file mode 100644 index 000000000..353737ab0 Binary files /dev/null and b/priv/static/static/js/9.f8e3aa590f4a66aedc3f.js differ diff --git a/priv/static/static/js/9.f8e3aa590f4a66aedc3f.js.map b/priv/static/static/js/9.f8e3aa590f4a66aedc3f.js.map new file mode 100644 index 000000000..452afcc41 Binary files /dev/null and b/priv/static/static/js/9.f8e3aa590f4a66aedc3f.js.map differ diff --git a/priv/static/static/js/app.032cb80dafd1f208df1c.js b/priv/static/static/js/app.032cb80dafd1f208df1c.js new file mode 100644 index 000000000..c4b099811 Binary files /dev/null and b/priv/static/static/js/app.032cb80dafd1f208df1c.js differ diff --git a/priv/static/static/js/app.032cb80dafd1f208df1c.js.map b/priv/static/static/js/app.032cb80dafd1f208df1c.js.map new file mode 100644 index 000000000..397fbfbe8 Binary files /dev/null and b/priv/static/static/js/app.032cb80dafd1f208df1c.js.map differ diff --git a/priv/static/static/js/app.31bba9f1e242ff273dcb.js b/priv/static/static/js/app.31bba9f1e242ff273dcb.js deleted file mode 100644 index 22413689c..000000000 Binary files a/priv/static/static/js/app.31bba9f1e242ff273dcb.js and /dev/null differ diff --git a/priv/static/static/js/app.31bba9f1e242ff273dcb.js.map b/priv/static/static/js/app.31bba9f1e242ff273dcb.js.map deleted file mode 100644 index 8ff7a00c6..000000000 Binary files a/priv/static/static/js/app.31bba9f1e242ff273dcb.js.map and /dev/null differ diff --git a/priv/static/static/js/vendors~app.811c8482146cad566f7e.js b/priv/static/static/js/vendors~app.811c8482146cad566f7e.js new file mode 100644 index 000000000..c2114925d Binary files /dev/null and b/priv/static/static/js/vendors~app.811c8482146cad566f7e.js differ diff --git a/priv/static/static/js/vendors~app.811c8482146cad566f7e.js.map b/priv/static/static/js/vendors~app.811c8482146cad566f7e.js.map new file mode 100644 index 000000000..858078059 Binary files /dev/null and b/priv/static/static/js/vendors~app.811c8482146cad566f7e.js.map differ diff --git a/priv/static/static/js/vendors~app.9e24ed238da5a8538f50.js b/priv/static/static/js/vendors~app.9e24ed238da5a8538f50.js deleted file mode 100644 index 76c8a8dc1..000000000 Binary files a/priv/static/static/js/vendors~app.9e24ed238da5a8538f50.js and /dev/null differ diff --git a/priv/static/static/js/vendors~app.9e24ed238da5a8538f50.js.map b/priv/static/static/js/vendors~app.9e24ed238da5a8538f50.js.map deleted file mode 100644 index f3c067c15..000000000 Binary files a/priv/static/static/js/vendors~app.9e24ed238da5a8538f50.js.map and /dev/null differ diff --git a/priv/static/sw-pleroma.js b/priv/static/sw-pleroma.js index 9b7d127fd..5aabeb744 100644 Binary files a/priv/static/sw-pleroma.js and b/priv/static/sw-pleroma.js differ diff --git a/priv/static/sw-pleroma.js.map b/priv/static/sw-pleroma.js.map index 5749809d5..20dac11d0 100644 Binary files a/priv/static/sw-pleroma.js.map and b/priv/static/sw-pleroma.js.map differ -- cgit v1.2.3 From 035c44dd7bc34dedc184ec0434ed994cc7a190dd Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 13 Aug 2020 16:38:04 +0200 Subject: CI: Add cmake to build --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5f82e58e5..9e9107ce3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -194,6 +194,7 @@ amd64: variables: &release-variables MIX_ENV: prod before_script: &before-release + - apt install cmake -y - echo "import Mix.Config" > config/prod.secret.exs - mix local.hex --force - mix local.rebar --force -- cgit v1.2.3 From 4f3c955f264c9a6bfcc302b4644ea9da6e7ad38b Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 13 Aug 2020 18:10:43 +0200 Subject: side_effects: Fix typo on notification --- lib/pleroma/web/activity_pub/side_effects.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 14a1da0c1..5a02f1d69 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -55,7 +55,7 @@ def handle( # Task this handles # - Rejects all existing follow activities for this person # - Updates the follow state - # - Dismisses notificatios + # - Dismisses notification def handle( %{ data: %{ -- cgit v1.2.3 From 3515cb5c3ac138c3e19eacc8fd78bb1480e3a98c Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Thu, 13 Aug 2020 21:01:21 +0300 Subject: fix Cron.PurgeExpiredActivitiesWorker --- lib/pleroma/workers/cron/purge_expired_activities_worker.ex | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/pleroma/workers/cron/purge_expired_activities_worker.ex b/lib/pleroma/workers/cron/purge_expired_activities_worker.ex index e926c5dc8..0de8edd24 100644 --- a/lib/pleroma/workers/cron/purge_expired_activities_worker.ex +++ b/lib/pleroma/workers/cron/purge_expired_activities_worker.ex @@ -21,11 +21,12 @@ defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker do @impl Oban.Worker def perform(_job) do - if Config.get([ActivityExpiration, :enabled]) do - Enum.each(ActivityExpiration.due_expirations(@interval), &delete_activity/1) - else - :ok - end + if Config.get([ActivityExpiration, :enabled]) do + Enum.each(ActivityExpiration.due_expirations(@interval), &delete_activity/1) + end + + after + :ok end def delete_activity(%ActivityExpiration{activity_id: activity_id}) do @@ -41,7 +42,7 @@ def delete_activity(%ActivityExpiration{activity_id: activity_id}) do {:user, _} -> Logger.error( - "#{__MODULE__} Couldn't delete expired activity: not found actorof ##{activity_id}" + "#{__MODULE__} Couldn't delete expired activity: not found actor of ##{activity_id}" ) end end -- cgit v1.2.3 From 9b055f72119b3c4b51f026b88814fd17e87eba26 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Thu, 13 Aug 2020 21:01:54 +0300 Subject: fix cron wroker --- lib/pleroma/workers/cron/clear_oauth_token_worker.ex | 4 ++-- lib/pleroma/workers/cron/digest_emails_worker.ex | 4 ++-- lib/pleroma/workers/cron/new_users_digest_worker.ex | 6 ++---- lib/pleroma/workers/cron/purge_expired_activities_worker.ex | 7 +++---- lib/pleroma/workers/cron/stats_worker.ex | 1 + 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/pleroma/workers/cron/clear_oauth_token_worker.ex b/lib/pleroma/workers/cron/clear_oauth_token_worker.ex index d41be4e87..276f47efc 100644 --- a/lib/pleroma/workers/cron/clear_oauth_token_worker.ex +++ b/lib/pleroma/workers/cron/clear_oauth_token_worker.ex @@ -16,8 +16,8 @@ defmodule Pleroma.Workers.Cron.ClearOauthTokenWorker do def perform(_job) do if Config.get([:oauth2, :clean_expired_tokens], false) do Token.delete_expired_tokens() - else - :ok end + + :ok end end diff --git a/lib/pleroma/workers/cron/digest_emails_worker.ex b/lib/pleroma/workers/cron/digest_emails_worker.ex index ee646229f..0c56f00fb 100644 --- a/lib/pleroma/workers/cron/digest_emails_worker.ex +++ b/lib/pleroma/workers/cron/digest_emails_worker.ex @@ -37,9 +37,9 @@ def perform(_job) do ) |> Repo.all() |> send_emails - else - :ok end + + :ok end def send_emails(users) do diff --git a/lib/pleroma/workers/cron/new_users_digest_worker.ex b/lib/pleroma/workers/cron/new_users_digest_worker.ex index abc8a5e95..8bbaed83d 100644 --- a/lib/pleroma/workers/cron/new_users_digest_worker.ex +++ b/lib/pleroma/workers/cron/new_users_digest_worker.ex @@ -55,11 +55,9 @@ def perform(_job) do |> Repo.all() |> Enum.map(&Pleroma.Emails.NewUsersDigestEmail.new_users(&1, users_and_statuses)) |> Enum.each(&Pleroma.Emails.Mailer.deliver/1) - else - :ok end - else - :ok end + + :ok end end diff --git a/lib/pleroma/workers/cron/purge_expired_activities_worker.ex b/lib/pleroma/workers/cron/purge_expired_activities_worker.ex index 0de8edd24..6549207fc 100644 --- a/lib/pleroma/workers/cron/purge_expired_activities_worker.ex +++ b/lib/pleroma/workers/cron/purge_expired_activities_worker.ex @@ -21,10 +21,9 @@ defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker do @impl Oban.Worker def perform(_job) do - if Config.get([ActivityExpiration, :enabled]) do - Enum.each(ActivityExpiration.due_expirations(@interval), &delete_activity/1) - end - + if Config.get([ActivityExpiration, :enabled]) do + Enum.each(ActivityExpiration.due_expirations(@interval), &delete_activity/1) + end after :ok end diff --git a/lib/pleroma/workers/cron/stats_worker.ex b/lib/pleroma/workers/cron/stats_worker.ex index e54bd9a7f..6a79540bc 100644 --- a/lib/pleroma/workers/cron/stats_worker.ex +++ b/lib/pleroma/workers/cron/stats_worker.ex @@ -12,5 +12,6 @@ defmodule Pleroma.Workers.Cron.StatsWorker do @impl Oban.Worker def perform(_job) do Pleroma.Stats.do_collect() + :ok end end -- cgit v1.2.3 From 07376bd21ae732a00c61ce55be920ddf8ba603ee Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 6 Aug 2020 00:01:57 -0400 Subject: Adding installation documentation for FreeBSD + rc.d script --- docs/installation/freebsd_en.md | 201 ++++++++++++++++++++++++++++++++++++++ installation/freebsd/rc.d/pleroma | 28 ++++++ 2 files changed, 229 insertions(+) create mode 100644 docs/installation/freebsd_en.md create mode 100755 installation/freebsd/rc.d/pleroma diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md new file mode 100644 index 000000000..51990c5e4 --- /dev/null +++ b/docs/installation/freebsd_en.md @@ -0,0 +1,201 @@ +# Installing on FreeBSD + +This document was written for FreeBSD 12.1, but should be trivially trailerable to future releases. +Additionally, this guide document can be modified to + +## Required software + +This assumes the target system has `pkg(8)`. + +`# pkg install elixir postgresql12-server postgresql12-client postgresql12-contrib git-lite sudo nginx gmake acme.sh` + +Copy the rc.d scripts to the right directory: + +Setup the required services to automatically start at boot, using `sysrc(8)`. + +``` +# sysrc nginx_enable=YES +# sysrc postgresql_enable=YES +``` + +## Initialize postgres + +``` +# service postgresql initdb +# service postgresql start +``` + +## Configuring Pleroma + +Create a user for Pleroma: + +``` +# pw add user pleroma -m +# echo 'export LC_ALL="en_US.UTF-8"' >> /home/pleroma/.profile +# su -l pleroma +``` + +Clone the repository: + +``` +$ cd $HOME # Should be the same as /home/pleroma +$ git clone -b stable https://git.pleroma.social/pleroma/pleroma.git +``` + +Configure Pleroma. Note that you need a domain name at this point: + +``` +$ cd /home/pleroma/pleroma +$ mix deps.get +$ mix pleroma.instance gen # You will be asked a few questions here. +$ cp config/generated_config.exs config/prod.secret.exs # The default values should be sufficient but you should edit it and check that everything seems OK. +``` + +Since Postgres is configured, we can now initialize the database. There should +now be a file in `config/setup_db.psql` that makes this easier. Edit it, and +*change the password* to a password of your choice. Make sure it is secure, since +it'll be protecting your database. As root, you can now initialize the database: + +``` +# cd /home/pleroma/pleroma +# sudo -Hu postgres -g postgres psql -f config/setup_db.psql +``` + +Postgres allows connections from all users without a password by default. To +fix this, edit `/var/db/postgres/data12/pg_hba.conf`. Change every `trust` to +`password`. + +Once this is done, restart Postgres with `# service postgresql restart`. + +Run the database migrations. + +Back as the pleroma user, you will need to do this whenever you update with `git pull`: + +``` +# su -l pleroma +$ cd /home/pleroma/pleroma +$ MIX_ENV=prod mix ecto.migrate +``` + +## Configuring nginx + +Install the example configuration file +`/home/pleroma/pleroma/installation/pleroma.nginx` to +`/usr/local/etc/nginx/nginx.conf`. + +Note that it will need to be wrapped in a `http {}` block. You should add +settings for the nginx daemon outside of the http block, for example: + +``` +user nginx nginx; +error_log /var/log/nginx/error.log; +worker_processes 4; + +events { +} +``` + +Edit the defaults: + +* Change `ssl_certificate` and `ssl_trusted_certificate` to +`/etc/ssl/example.tld/fullchain`. +* Change `ssl_certificate_key` to `/etc/ssl/example.tld/key`. +* Change `example.tld` to your instance's domain name. + +## Configuring acme.sh + +We'll be using acme.sh in Stateless Mode for TLS certificate renewal. + +First, get your account fingerprint: + +``` +$ sudo -Hu nginx -g nginx acme.sh --register-account +``` + +You need to add the following to your nginx configuration for the server +running on port 80: + +``` + location ~ ^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$ { + default_type text/plain; + return 200 "$1.6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd"; + } +``` + +Replace the string after after `$1.` with your fingerprint. + +Start nginx: + +``` +# service nginx start +``` + +It should now be possible to issue a cert (replace `example.com` +with your domain name): + +``` +$ sudo -Hu nginx -g nginx acme.sh --issue -d example.com --stateless +$ acme.sh --install-cert -d example.com \ + --key-file /path/to/keyfile/in/nginx/key.pem \ + --fullchain-file /path/to/fullchain/nginx/cert.pem \ +``` + +Let's add auto-renewal to `/etc/daily.local` +(replace `example.com` with your domain): + +``` +/usr/pkg/bin/sudo -Hu nginx -g nginx \ + /usr/pkg/sbin/acme.sh -r \ + -d example.com \ + --cert-file /etc/nginx/tls/cert \ + --key-file /etc/nginx/tls/key \ + --ca-file /etc/nginx/tls/ca \ + --fullchain-file /etc/nginx/tls/fullchain \ + --stateless +``` + +## Creating a startup script for Pleroma + +Pleroma will need to compile when it initially starts, which typically takes a longer +period of time. Therefore, it is good practice to initially run pleroma from the +command-line before utilizing the rc.d script. That is done as follows: + +``` +# su -l pleroma +$ cd $HOME/pleroma +$ MIX_ENV=prod mix phx.server +``` + +Copy the startup script to the correct location and make sure it's executable: + +``` +# cp /home/pleroma/pleroma/installation/freebsd/rc.d/pleroma /usr/local/etc/rc.d/pleroma +# chmod +x /etc/rc.d/pleroma +``` + +Add the following to `/etc/rc.conf`: + +``` +pleroma=YES +pleroma_home="/home/pleroma" +pleroma_user="pleroma" +``` + +Run `# /etc/rc.d/pleroma start` to start Pleroma. + +## Conclusion + +Restart nginx with `# /etc/rc.d/nginx restart` and you should be up and running. + +If you need further help, contact niaa on freenode. + +Make sure your time is in sync, or other instances will receive your posts with +incorrect timestamps. You should have ntpd running. + +#### Further reading + +{! backend/installation/further_reading.include !} + +## Questions + +Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**. diff --git a/installation/freebsd/rc.d/pleroma b/installation/freebsd/rc.d/pleroma new file mode 100755 index 000000000..1e41e57e6 --- /dev/null +++ b/installation/freebsd/rc.d/pleroma @@ -0,0 +1,28 @@ +#!/bin/sh +# REQUIRE: DAEMON postgresql +# PROVIDE: pleroma + +# sudo -u pleroma MIX_ENV=prod elixir --erl \"-detached\" -S mix phx.server + +. /etc/rc.subr + +name="pleroma" +desc="Pleroma Social Media Platform" +rcvar=${name}_enable +command="/usr/local/bin/elixir" +command_args="--erl \"-detached\" -S /usr/local/bin/mix phx.server" +pidfile="/dev/null" + +pleroma_user="pleroma" +pleroma_home="/home/pleroma" +pleroma_chdir="${pleroma_home}/pleroma" +pleroma_env="HOME=${pleroma_home} MIX_ENV=prod" + +check_pidfile() +{ + pid=$(pgrep beam.smp$) + echo -n "${pid}" +} + +load_rc_config ${name} +run_rc_command "$1" -- cgit v1.2.3 From da5aca27a8c79edcb4577c3a9f05cfa5d0463e83 Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 6 Aug 2020 23:24:12 +0000 Subject: Minor reorganization --- docs/installation/freebsd_en.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index 51990c5e4..c98992fe5 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -69,7 +69,7 @@ Once this is done, restart Postgres with `# service postgresql restart`. Run the database migrations. -Back as the pleroma user, you will need to do this whenever you update with `git pull`: +Back as the pleroma user, run the following to implement any database migrations. ``` # su -l pleroma @@ -77,9 +77,11 @@ $ cd /home/pleroma/pleroma $ MIX_ENV=prod mix ecto.migrate ``` +You will need to do this whenever you update with `git pull`: + ## Configuring nginx -Install the example configuration file +As root, install the example configuration file `/home/pleroma/pleroma/installation/pleroma.nginx` to `/usr/local/etc/nginx/nginx.conf`. -- cgit v1.2.3 From f6686a64afceb775d775e623c847d413fecf65f8 Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 6 Aug 2020 23:35:33 +0000 Subject: Updated ssl and domain name updates Removed the reference to niaa --- docs/installation/freebsd_en.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index c98992fe5..9c5caa4d3 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -97,12 +97,12 @@ events { } ``` -Edit the defaults: +Edit the defaults of `/usr/local/etc/nginx/nginx.conf`: -* Change `ssl_certificate` and `ssl_trusted_certificate` to -`/etc/ssl/example.tld/fullchain`. -* Change `ssl_certificate_key` to `/etc/ssl/example.tld/key`. -* Change `example.tld` to your instance's domain name. +* Change `ssl_trusted_certificate` to `/etc/ssl/example.tld/chain.pem`. +* Change `ssl_certificate` to `/etc/ssl/example.tld/fullchain.pem`. +* Change `ssl_certificate_key` to `/etc/ssl/example.tld/privkey.pem`. +* Change all references of `example.tld` to your instance's domain name. ## Configuring acme.sh @@ -189,8 +189,6 @@ Run `# /etc/rc.d/pleroma start` to start Pleroma. Restart nginx with `# /etc/rc.d/nginx restart` and you should be up and running. -If you need further help, contact niaa on freenode. - Make sure your time is in sync, or other instances will receive your posts with incorrect timestamps. You should have ntpd running. -- cgit v1.2.3 From 53c4215ef1d65300ffbf8d47cdb5a713558df528 Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Fri, 7 Aug 2020 01:04:33 +0000 Subject: Updated some more instruction specifics. --- docs/installation/freebsd_en.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index 9c5caa4d3..ee42b9427 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -172,18 +172,16 @@ Copy the startup script to the correct location and make sure it's executable: ``` # cp /home/pleroma/pleroma/installation/freebsd/rc.d/pleroma /usr/local/etc/rc.d/pleroma -# chmod +x /etc/rc.d/pleroma +# chmod +x /usr/local/etc/rc.d/pleroma ``` -Add the following to `/etc/rc.conf`: +Update the `/etc/rc.conf` file with the following command: ``` -pleroma=YES -pleroma_home="/home/pleroma" -pleroma_user="pleroma" +# sysrc pleroma_enable=YES ``` -Run `# /etc/rc.d/pleroma start` to start Pleroma. +Now you can start pleroma with `# service pleroma start`. ## Conclusion -- cgit v1.2.3 From 33ea430f3b026f4e9b353b74bcc60846c67a5a69 Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Fri, 7 Aug 2020 01:52:39 +0000 Subject: acme.sh and netbsd to freebsd updates --- docs/installation/freebsd_en.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index ee42b9427..b5c62bee6 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -146,8 +146,8 @@ Let's add auto-renewal to `/etc/daily.local` (replace `example.com` with your domain): ``` -/usr/pkg/bin/sudo -Hu nginx -g nginx \ - /usr/pkg/sbin/acme.sh -r \ +/usr/pkg/bin/sudo -Hu www -g www \ + /usr/local/sbin/acme.sh -r \ -d example.com \ --cert-file /etc/nginx/tls/cert \ --key-file /etc/nginx/tls/key \ @@ -175,25 +175,22 @@ Copy the startup script to the correct location and make sure it's executable: # chmod +x /usr/local/etc/rc.d/pleroma ``` -Update the `/etc/rc.conf` file with the following command: +Update the `/etc/rc.conf` and start pleroma with the following commands: ``` # sysrc pleroma_enable=YES +# service pleroma start ``` Now you can start pleroma with `# service pleroma start`. ## Conclusion -Restart nginx with `# /etc/rc.d/nginx restart` and you should be up and running. +Restart nginx with `# service nginx restart` and you should be up and running. Make sure your time is in sync, or other instances will receive your posts with incorrect timestamps. You should have ntpd running. -#### Further reading - -{! backend/installation/further_reading.include !} - ## Questions Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**. -- cgit v1.2.3 From b5f48275c5a0802ac5e7da0caf3d3af0bfbb7c6c Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 13 Aug 2020 19:08:13 -0400 Subject: Minor patch update --- docs/installation/freebsd_en.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index b5c62bee6..12c870322 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -108,10 +108,10 @@ Edit the defaults of `/usr/local/etc/nginx/nginx.conf`: We'll be using acme.sh in Stateless Mode for TLS certificate renewal. -First, get your account fingerprint: +First, as root, get your account fingerprint: ``` -$ sudo -Hu nginx -g nginx acme.sh --register-account +# sudo -Hu acme -g acme acme.sh --register-account ``` You need to add the following to your nginx configuration for the server @@ -136,7 +136,7 @@ It should now be possible to issue a cert (replace `example.com` with your domain name): ``` -$ sudo -Hu nginx -g nginx acme.sh --issue -d example.com --stateless +$ sudo -Hu acme -g acme acme.sh --issue -d example.com --stateless $ acme.sh --install-cert -d example.com \ --key-file /path/to/keyfile/in/nginx/key.pem \ --fullchain-file /path/to/fullchain/nginx/cert.pem \ @@ -146,7 +146,7 @@ Let's add auto-renewal to `/etc/daily.local` (replace `example.com` with your domain): ``` -/usr/pkg/bin/sudo -Hu www -g www \ +/usr/local/bin/sudo -Hu acme -g acme \ /usr/local/sbin/acme.sh -r \ -d example.com \ --cert-file /etc/nginx/tls/cert \ -- cgit v1.2.3 From cba9f368af13768f7c0161074ab3f25deae5b5a6 Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 13 Aug 2020 19:34:04 -0400 Subject: Added comment --- docs/installation/freebsd_en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index 12c870322..38afd76e4 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -46,7 +46,7 @@ Configure Pleroma. Note that you need a domain name at this point: ``` $ cd /home/pleroma/pleroma -$ mix deps.get +$ mix deps.get # Enter "y" when asked to install Hex $ mix pleroma.instance gen # You will be asked a few questions here. $ cp config/generated_config.exs config/prod.secret.exs # The default values should be sufficient but you should edit it and check that everything seems OK. ``` -- cgit v1.2.3 From 24eb917dbc752a81716699ebd23ad9ff9cbd6a24 Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 13 Aug 2020 20:58:46 -0400 Subject: Rearranging acme --- docs/installation/freebsd_en.md | 63 +++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index 38afd76e4..a8741e565 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -79,36 +79,19 @@ $ MIX_ENV=prod mix ecto.migrate You will need to do this whenever you update with `git pull`: -## Configuring nginx +## Configuring acme.sh -As root, install the example configuration file -`/home/pleroma/pleroma/installation/pleroma.nginx` to -`/usr/local/etc/nginx/nginx.conf`. +We'll be using acme.sh in Stateless Mode for TLS certificate renewal. -Note that it will need to be wrapped in a `http {}` block. You should add -settings for the nginx daemon outside of the http block, for example: +First, as root, allow the user `acme` to have access to the acme log file, as follows: ``` -user nginx nginx; -error_log /var/log/nginx/error.log; -worker_processes 4; - -events { -} +# touch /var/log/acme.sh.log +# chown acme:acme /var/log/acme.sh.log +# chmod 600 /var/log/acme.sh.log ``` -Edit the defaults of `/usr/local/etc/nginx/nginx.conf`: - -* Change `ssl_trusted_certificate` to `/etc/ssl/example.tld/chain.pem`. -* Change `ssl_certificate` to `/etc/ssl/example.tld/fullchain.pem`. -* Change `ssl_certificate_key` to `/etc/ssl/example.tld/privkey.pem`. -* Change all references of `example.tld` to your instance's domain name. - -## Configuring acme.sh - -We'll be using acme.sh in Stateless Mode for TLS certificate renewal. - -First, as root, get your account fingerprint: +Next, obtain your account fingerprint: ``` # sudo -Hu acme -g acme acme.sh --register-account @@ -156,6 +139,38 @@ Let's add auto-renewal to `/etc/daily.local` --stateless ``` +### Configuring nginx + +FreeBSD's default nginx configuration does not contain an include directive, which is +typically used for multiple sites. Therefore, you will need to first create the required +directory as follows: + + +``` +# mkdir -p /usr/local/etc/nginx/sites-available +``` + +Next, add an `include` directive to `/usr/local/etc/nginx/nginx.conf`, within the `http {}` +block, as follows: + + +``` +http { +... + include /usr/local/etc/nginx/sites-available/*.conf; +} +``` + +As root, copy `/home/pleroma/pleroma/installation/pleroma.nginx` to +`/usr/local/etc/nginx/sites-available/pleroma.conf`. + +Edit the defaults of `/usr/local/etc/nginx/sites-available/pleroma.conf`: + +* Change `ssl_trusted_certificate` to `/etc/ssl/example.tld/chain.pem`. +* Change `ssl_certificate` to `/etc/ssl/example.tld/fullchain.pem`. +* Change `ssl_certificate_key` to `/etc/ssl/example.tld/privkey.pem`. +* Change all references of `example.tld` to your instance's domain name. + ## Creating a startup script for Pleroma Pleroma will need to compile when it initially starts, which typically takes a longer -- cgit v1.2.3 From f2665547f59a7043cf8bac9d39c56a9b717d5099 Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 13 Aug 2020 21:24:08 -0400 Subject: acme updates --- docs/installation/freebsd_en.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index a8741e565..386a0ae10 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -119,10 +119,11 @@ It should now be possible to issue a cert (replace `example.com` with your domain name): ``` -$ sudo -Hu acme -g acme acme.sh --issue -d example.com --stateless -$ acme.sh --install-cert -d example.com \ - --key-file /path/to/keyfile/in/nginx/key.pem \ - --fullchain-file /path/to/fullchain/nginx/cert.pem \ +# mkdir -p /etc/ssl/example.com +# sudo -Hu acme -g acme acme.sh --issue -d example.com --stateless +# acme.sh --home /var/db/acme/.acme.sh/ --install-cert -d example.com \ + --key-file /etc/ssl/example.com/key.pem + --fullchain-file /etc/ssl/example.com/fullchain.pem ``` Let's add auto-renewal to `/etc/daily.local` -- cgit v1.2.3 From b0c456d18d3b4e20233a7dbaef3c55d0586a1946 Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 13 Aug 2020 22:18:33 -0400 Subject: more acme.sh updates --- docs/installation/freebsd_en.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index 386a0ae10..458b8032d 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -122,22 +122,22 @@ with your domain name): # mkdir -p /etc/ssl/example.com # sudo -Hu acme -g acme acme.sh --issue -d example.com --stateless # acme.sh --home /var/db/acme/.acme.sh/ --install-cert -d example.com \ - --key-file /etc/ssl/example.com/key.pem + --ca-file /etc/ssl/example.com/ca.pem \ + --key-file /etc/ssl/example.com/key.pem \ + --cert-file /etc/ssl/example.com/cert.pem \ --fullchain-file /etc/ssl/example.com/fullchain.pem ``` -Let's add auto-renewal to `/etc/daily.local` +Let's add auto-renewal to `/etc/crontab` (replace `example.com` with your domain): ``` -/usr/local/bin/sudo -Hu acme -g acme \ - /usr/local/sbin/acme.sh -r \ - -d example.com \ - --cert-file /etc/nginx/tls/cert \ - --key-file /etc/nginx/tls/key \ - --ca-file /etc/nginx/tls/ca \ - --fullchain-file /etc/nginx/tls/fullchain \ - --stateless +/usr/local/bin/sudo -Hu acme -g acme /usr/local/sbin/acme.sh -r -d example.com --stateless +/usr/local/sbin/acme.sh --home /var/db/acme/.acme.sh/ --install-cert -d example.com \ + --ca-file /etc/ssl/example.com/ca.pem \ + --key-file /etc/ssl/example.com/key.pem \ + --cert-file /etc/ssl/test-app.mailchar.com/cert.pem \ + --fullchain-file /etc/ssl/example.com/fullchain.pem ``` ### Configuring nginx -- cgit v1.2.3 From 816c04abdc2e8045f3fa52071b953c5ac608d0bd Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 13 Aug 2020 22:38:23 -0400 Subject: Updates --- docs/installation/freebsd_en.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index 458b8032d..f1e06892c 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -123,8 +123,8 @@ with your domain name): # sudo -Hu acme -g acme acme.sh --issue -d example.com --stateless # acme.sh --home /var/db/acme/.acme.sh/ --install-cert -d example.com \ --ca-file /etc/ssl/example.com/ca.pem \ - --key-file /etc/ssl/example.com/key.pem \ - --cert-file /etc/ssl/example.com/cert.pem \ + --key-file /etc/ssl/example.com/privkey.pem \ + --cert-file /etc/ssl/example.com/chain.pem \ --fullchain-file /etc/ssl/example.com/fullchain.pem ``` @@ -135,8 +135,8 @@ Let's add auto-renewal to `/etc/crontab` /usr/local/bin/sudo -Hu acme -g acme /usr/local/sbin/acme.sh -r -d example.com --stateless /usr/local/sbin/acme.sh --home /var/db/acme/.acme.sh/ --install-cert -d example.com \ --ca-file /etc/ssl/example.com/ca.pem \ - --key-file /etc/ssl/example.com/key.pem \ - --cert-file /etc/ssl/test-app.mailchar.com/cert.pem \ + --key-file /etc/ssl/example.com/privkey.pem \ + --cert-file /etc/ssl/example.com/chain.pem \ --fullchain-file /etc/ssl/example.com/fullchain.pem ``` @@ -158,7 +158,7 @@ block, as follows: ``` http { ... - include /usr/local/etc/nginx/sites-available/*.conf; + include /usr/local/etc/nginx/sites-available/*; } ``` -- cgit v1.2.3 From a5144f05c2245c5043f2469955e8960b5d80b48e Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Thu, 13 Aug 2020 22:49:50 -0400 Subject: Removed a trailing comment --- docs/installation/freebsd_en.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index f1e06892c..ce0cdead6 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -198,8 +198,6 @@ Update the `/etc/rc.conf` and start pleroma with the following commands: # service pleroma start ``` -Now you can start pleroma with `# service pleroma start`. - ## Conclusion Restart nginx with `# service nginx restart` and you should be up and running. -- cgit v1.2.3 From e8c20c42cd02cc4dcbcb420cec98f68951a1609d Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Fri, 14 Aug 2020 00:21:42 -0400 Subject: minor changes --- docs/installation/freebsd_en.md | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index ce0cdead6..130d68766 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -1,13 +1,14 @@ # Installing on FreeBSD -This document was written for FreeBSD 12.1, but should be trivially trailerable to future releases. -Additionally, this guide document can be modified to +This document was written for FreeBSD 12.1, but should be work on future releases. ## Required software This assumes the target system has `pkg(8)`. -`# pkg install elixir postgresql12-server postgresql12-client postgresql12-contrib git-lite sudo nginx gmake acme.sh` +``` +# pkg install elixir postgresql12-server postgresql12-client postgresql12-contrib git-lite sudo nginx gmake acme.sh +``` Copy the rc.d scripts to the right directory: @@ -48,7 +49,7 @@ Configure Pleroma. Note that you need a domain name at this point: $ cd /home/pleroma/pleroma $ mix deps.get # Enter "y" when asked to install Hex $ mix pleroma.instance gen # You will be asked a few questions here. -$ cp config/generated_config.exs config/prod.secret.exs # The default values should be sufficient but you should edit it and check that everything seems OK. +$ cp config/generated_config.exs config/prod.secret.exs ``` Since Postgres is configured, we can now initialize the database. There should @@ -65,7 +66,10 @@ Postgres allows connections from all users without a password by default. To fix this, edit `/var/db/postgres/data12/pg_hba.conf`. Change every `trust` to `password`. -Once this is done, restart Postgres with `# service postgresql restart`. +Once this is done, restart Postgres with: +``` +# service postgresql restart +``` Run the database migrations. @@ -119,13 +123,7 @@ It should now be possible to issue a cert (replace `example.com` with your domain name): ``` -# mkdir -p /etc/ssl/example.com # sudo -Hu acme -g acme acme.sh --issue -d example.com --stateless -# acme.sh --home /var/db/acme/.acme.sh/ --install-cert -d example.com \ - --ca-file /etc/ssl/example.com/ca.pem \ - --key-file /etc/ssl/example.com/privkey.pem \ - --cert-file /etc/ssl/example.com/chain.pem \ - --fullchain-file /etc/ssl/example.com/fullchain.pem ``` Let's add auto-renewal to `/etc/crontab` @@ -133,11 +131,6 @@ Let's add auto-renewal to `/etc/crontab` ``` /usr/local/bin/sudo -Hu acme -g acme /usr/local/sbin/acme.sh -r -d example.com --stateless -/usr/local/sbin/acme.sh --home /var/db/acme/.acme.sh/ --install-cert -d example.com \ - --ca-file /etc/ssl/example.com/ca.pem \ - --key-file /etc/ssl/example.com/privkey.pem \ - --cert-file /etc/ssl/example.com/chain.pem \ - --fullchain-file /etc/ssl/example.com/fullchain.pem ``` ### Configuring nginx @@ -163,13 +156,13 @@ http { ``` As root, copy `/home/pleroma/pleroma/installation/pleroma.nginx` to -`/usr/local/etc/nginx/sites-available/pleroma.conf`. +`/usr/local/etc/nginx/sites-available/pleroma.nginx`. -Edit the defaults of `/usr/local/etc/nginx/sites-available/pleroma.conf`: +Edit the defaults of `/usr/local/etc/nginx/sites-available/pleroma.nginx`: -* Change `ssl_trusted_certificate` to `/etc/ssl/example.tld/chain.pem`. -* Change `ssl_certificate` to `/etc/ssl/example.tld/fullchain.pem`. -* Change `ssl_certificate_key` to `/etc/ssl/example.tld/privkey.pem`. +* Change `ssl_trusted_certificate` to `/var/db/acme/certs/example.tld/example.tld.cer`. +* Change `ssl_certificate` to `/var/db/acme/certs/example.tld/fullchain.cer`. +* Change `ssl_certificate_key` to `/var/db/acme/certs/example.tld/example.tld.key`. * Change all references of `example.tld` to your instance's domain name. ## Creating a startup script for Pleroma @@ -198,6 +191,13 @@ Update the `/etc/rc.conf` and start pleroma with the following commands: # service pleroma start ``` +#### Create your first user + +If your instance is up and running, you can create your first user with administrative rights with the following task: + +```shell +sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new --admin +``` ## Conclusion Restart nginx with `# service nginx restart` and you should be up and running. -- cgit v1.2.3 From 76ce3a1c9e36181dac47dde013e8dad98f606387 Mon Sep 17 00:00:00 2001 From: lain Date: Fri, 14 Aug 2020 18:27:18 +0200 Subject: Mogrifun: Add a line about the purpose of the module. --- lib/pleroma/upload/filter/mogrifun.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pleroma/upload/filter/mogrifun.ex b/lib/pleroma/upload/filter/mogrifun.ex index a8503ac24..c8fa7b190 100644 --- a/lib/pleroma/upload/filter/mogrifun.ex +++ b/lib/pleroma/upload/filter/mogrifun.ex @@ -6,6 +6,10 @@ defmodule Pleroma.Upload.Filter.Mogrifun do @behaviour Pleroma.Upload.Filter alias Pleroma.Upload.Filter + @moduledoc """ + This module is just an example of an Upload filter. It's not supposed to be used in production. + """ + @filters [ {"implode", "1"}, {"-raise", "20"}, -- cgit v1.2.3 From f510dc30b4d47fe1af14b91bcc42f0438f2367eb Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 14 Aug 2020 12:48:49 -0500 Subject: Update AdminFE bundle for 2.1.0 release --- priv/static/adminfe/app.01bdb34a.css | Bin 12837 -> 0 bytes priv/static/adminfe/app.61bb0915.css | Bin 0 -> 12895 bytes priv/static/adminfe/chunk-0171.8dc0d9da.css | Bin 0 -> 3545 bytes priv/static/adminfe/chunk-070d.d2dd6533.css | Bin 4748 -> 0 bytes priv/static/adminfe/chunk-0cbc.60bba79b.css | Bin 3385 -> 0 bytes priv/static/adminfe/chunk-143c.43ada4fc.css | Bin 692 -> 0 bytes priv/static/adminfe/chunk-1609.408dae86.css | Bin 1381 -> 0 bytes priv/static/adminfe/chunk-176e.4d21033f.css | Bin 0 -> 2163 bytes priv/static/adminfe/chunk-176e.5d7d957b.css | Bin 2163 -> 0 bytes priv/static/adminfe/chunk-2d97.7053ff89.css | Bin 0 -> 692 bytes priv/static/adminfe/chunk-40a4.2fe71f6c.css | Bin 0 -> 5006 bytes priv/static/adminfe/chunk-43ca.af749c6c.css | Bin 24279 -> 0 bytes priv/static/adminfe/chunk-4e7e.5afe1978.css | Bin 2044 -> 0 bytes priv/static/adminfe/chunk-565e.33809ac8.css | Bin 0 -> 26965 bytes priv/static/adminfe/chunk-5882.f65db7f2.css | Bin 4401 -> 0 bytes priv/static/adminfe/chunk-60a9.a80ec218.css | Bin 0 -> 1139 bytes priv/static/adminfe/chunk-654e.e105ec9c.css | Bin 0 -> 1381 bytes priv/static/adminfe/chunk-68ea.be16aa5f.css | Bin 0 -> 4748 bytes priv/static/adminfe/chunk-6e81.7f126ac7.css | Bin 0 -> 745 bytes priv/static/adminfe/chunk-6e81.ca3b222f.css | Bin 745 -> 0 bytes priv/static/adminfe/chunk-6e8c.f7407fd4.css | Bin 0 -> 4474 bytes priv/static/adminfe/chunk-7503.c75b68df.css | Bin 0 -> 3290 bytes priv/static/adminfe/chunk-7506.f01f6c2a.css | Bin 3290 -> 0 bytes priv/static/adminfe/chunk-7c6b.4c8fa90a.css | Bin 0 -> 2340 bytes priv/static/adminfe/chunk-7c6b.d9e7180a.css | Bin 2340 -> 0 bytes priv/static/adminfe/chunk-97e2.b21a8915.css | Bin 0 -> 5842 bytes priv/static/adminfe/chunk-9a72.3e577534.css | Bin 0 -> 2044 bytes priv/static/adminfe/chunk-c5f4.b1112f18.css | Bin 5842 -> 0 bytes priv/static/adminfe/chunk-commons.67f053f7.css | Bin 0 -> 2495 bytes priv/static/adminfe/chunk-commons.7f6d2d11.css | Bin 2495 -> 0 bytes priv/static/adminfe/chunk-e404.a56021ae.css | Bin 5063 -> 0 bytes priv/static/adminfe/chunk-libs.5cf7f50a.css | Bin 0 -> 3577 bytes priv/static/adminfe/chunk-libs.686b5876.css | Bin 3577 -> 0 bytes priv/static/adminfe/index.html | 2 +- priv/static/adminfe/static/js/ZhIB.861df339.js | Bin 11328 -> 0 bytes priv/static/adminfe/static/js/ZhIB.861df339.js.map | Bin 49483 -> 0 bytes priv/static/adminfe/static/js/app.86bfcdf3.js | Bin 0 -> 203611 bytes priv/static/adminfe/static/js/app.86bfcdf3.js.map | Bin 0 -> 449775 bytes priv/static/adminfe/static/js/app.f220ac13.js | Bin 194930 -> 0 bytes priv/static/adminfe/static/js/app.f220ac13.js.map | Bin 430912 -> 0 bytes priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js | Bin 0 -> 24601 bytes .../adminfe/static/js/chunk-0171.9ad03c0e.js.map | Bin 0 -> 94865 bytes priv/static/adminfe/static/js/chunk-070d.7e10a520.js | Bin 7919 -> 0 bytes .../adminfe/static/js/chunk-070d.7e10a520.js.map | Bin 17438 -> 0 bytes priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js | Bin 21596 -> 0 bytes .../adminfe/static/js/chunk-0cbc.2b0f8802.js.map | Bin 86354 -> 0 bytes priv/static/adminfe/static/js/chunk-143c.fc1825bf.js | Bin 13814 -> 0 bytes .../adminfe/static/js/chunk-143c.fc1825bf.js.map | Bin 37014 -> 0 bytes priv/static/adminfe/static/js/chunk-1609.98da6b01.js | Bin 10740 -> 0 bytes .../adminfe/static/js/chunk-1609.98da6b01.js.map | Bin 46790 -> 0 bytes priv/static/adminfe/static/js/chunk-176e.c4995511.js | Bin 10092 -> 0 bytes .../adminfe/static/js/chunk-176e.c4995511.js.map | Bin 32132 -> 0 bytes priv/static/adminfe/static/js/chunk-176e.fe016b36.js | Bin 0 -> 10092 bytes .../adminfe/static/js/chunk-176e.fe016b36.js.map | Bin 0 -> 32132 bytes priv/static/adminfe/static/js/chunk-2d97.931fa130.js | Bin 0 -> 15034 bytes .../adminfe/static/js/chunk-2d97.931fa130.js.map | Bin 0 -> 39781 bytes priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js | Bin 0 -> 19901 bytes .../adminfe/static/js/chunk-40a4.e7e37fc4.js.map | Bin 0 -> 75861 bytes priv/static/adminfe/static/js/chunk-43ca.aceb457c.js | Bin 112966 -> 0 bytes .../adminfe/static/js/chunk-43ca.aceb457c.js.map | Bin 386132 -> 0 bytes priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js | Bin 5112 -> 0 bytes .../adminfe/static/js/chunk-4e7e.91b5e73a.js.map | Bin 19744 -> 0 bytes priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js | Bin 0 -> 126482 bytes .../adminfe/static/js/chunk-565e.32b3b7b0.js.map | Bin 0 -> 426950 bytes priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js | Bin 24347 -> 0 bytes .../adminfe/static/js/chunk-5882.7cbc4c1b.js.map | Bin 81471 -> 0 bytes priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js | Bin 0 -> 6125 bytes .../adminfe/static/js/chunk-60a9.15f68a0f.js.map | Bin 0 -> 29926 bytes priv/static/adminfe/static/js/chunk-654e.d523dfc3.js | Bin 0 -> 10740 bytes .../adminfe/static/js/chunk-654e.d523dfc3.js.map | Bin 0 -> 46790 bytes priv/static/adminfe/static/js/chunk-68ea.a283cad8.js | Bin 0 -> 7919 bytes .../adminfe/static/js/chunk-68ea.a283cad8.js.map | Bin 0 -> 17438 bytes priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js | Bin 2080 -> 0 bytes .../adminfe/static/js/chunk-6e81.6efb01f4.js.map | Bin 9090 -> 0 bytes priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js | Bin 0 -> 2080 bytes .../adminfe/static/js/chunk-6e81.b4ee7cf5.js.map | Bin 0 -> 9090 bytes priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js | Bin 0 -> 26275 bytes .../adminfe/static/js/chunk-6e8c.46fda72d.js.map | Bin 0 -> 86864 bytes priv/static/adminfe/static/js/chunk-7503.ee7af549.js | Bin 0 -> 18559 bytes .../adminfe/static/js/chunk-7503.ee7af549.js.map | Bin 0 -> 62271 bytes priv/static/adminfe/static/js/chunk-7506.a3364e53.js | Bin 17041 -> 0 bytes .../adminfe/static/js/chunk-7506.a3364e53.js.map | Bin 58197 -> 0 bytes priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js | Bin 0 -> 8606 bytes .../adminfe/static/js/chunk-7c6b.7c4844a9.js.map | Bin 0 -> 28838 bytes priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js | Bin 8606 -> 0 bytes .../adminfe/static/js/chunk-7c6b.e63ae1da.js.map | Bin 28838 -> 0 bytes priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js | Bin 0 -> 26121 bytes .../adminfe/static/js/chunk-97e2.5baa6e73.js.map | Bin 0 -> 89970 bytes priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js | Bin 0 -> 5112 bytes .../adminfe/static/js/chunk-9a72.7b2fc06e.js.map | Bin 0 -> 19744 bytes priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js | Bin 26121 -> 0 bytes .../adminfe/static/js/chunk-c5f4.cf269f9b.js.map | Bin 89970 -> 0 bytes .../adminfe/static/js/chunk-commons.38728553.js | Bin 0 -> 9443 bytes .../adminfe/static/js/chunk-commons.38728553.js.map | Bin 0 -> 33718 bytes .../adminfe/static/js/chunk-commons.5a106955.js | Bin 9443 -> 0 bytes .../adminfe/static/js/chunk-commons.5a106955.js.map | Bin 33718 -> 0 bytes priv/static/adminfe/static/js/chunk-e404.554bc2e3.js | Bin 19723 -> 0 bytes .../adminfe/static/js/chunk-e404.554bc2e3.js.map | Bin 75596 -> 0 bytes .../adminfe/static/js/chunk-elementUI.2de79b84.js | Bin 0 -> 663883 bytes .../adminfe/static/js/chunk-elementUI.2de79b84.js.map | Bin 0 -> 2404935 bytes .../adminfe/static/js/chunk-elementUI.fba0efec.js | Bin 663883 -> 0 bytes .../adminfe/static/js/chunk-elementUI.fba0efec.js.map | Bin 2404935 -> 0 bytes priv/static/adminfe/static/js/chunk-libs.76802be9.js | Bin 0 -> 287147 bytes .../adminfe/static/js/chunk-libs.76802be9.js.map | Bin 0 -> 1691901 bytes priv/static/adminfe/static/js/chunk-libs.b8c453ab.js | Bin 275926 -> 0 bytes .../adminfe/static/js/chunk-libs.b8c453ab.js.map | Bin 1642077 -> 0 bytes priv/static/adminfe/static/js/runtime.0a70a9f5.js | Bin 4229 -> 0 bytes priv/static/adminfe/static/js/runtime.0a70a9f5.js.map | Bin 17240 -> 0 bytes priv/static/adminfe/static/js/runtime.ba9393f3.js | Bin 0 -> 4260 bytes priv/static/adminfe/static/js/runtime.ba9393f3.js.map | Bin 0 -> 17283 bytes 110 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 priv/static/adminfe/app.01bdb34a.css create mode 100644 priv/static/adminfe/app.61bb0915.css create mode 100644 priv/static/adminfe/chunk-0171.8dc0d9da.css delete mode 100644 priv/static/adminfe/chunk-070d.d2dd6533.css delete mode 100644 priv/static/adminfe/chunk-0cbc.60bba79b.css delete mode 100644 priv/static/adminfe/chunk-143c.43ada4fc.css delete mode 100644 priv/static/adminfe/chunk-1609.408dae86.css create mode 100644 priv/static/adminfe/chunk-176e.4d21033f.css delete mode 100644 priv/static/adminfe/chunk-176e.5d7d957b.css create mode 100644 priv/static/adminfe/chunk-2d97.7053ff89.css create mode 100644 priv/static/adminfe/chunk-40a4.2fe71f6c.css delete mode 100644 priv/static/adminfe/chunk-43ca.af749c6c.css delete mode 100644 priv/static/adminfe/chunk-4e7e.5afe1978.css create mode 100644 priv/static/adminfe/chunk-565e.33809ac8.css delete mode 100644 priv/static/adminfe/chunk-5882.f65db7f2.css create mode 100644 priv/static/adminfe/chunk-60a9.a80ec218.css create mode 100644 priv/static/adminfe/chunk-654e.e105ec9c.css create mode 100644 priv/static/adminfe/chunk-68ea.be16aa5f.css create mode 100644 priv/static/adminfe/chunk-6e81.7f126ac7.css delete mode 100644 priv/static/adminfe/chunk-6e81.ca3b222f.css create mode 100644 priv/static/adminfe/chunk-6e8c.f7407fd4.css create mode 100644 priv/static/adminfe/chunk-7503.c75b68df.css delete mode 100644 priv/static/adminfe/chunk-7506.f01f6c2a.css create mode 100644 priv/static/adminfe/chunk-7c6b.4c8fa90a.css delete mode 100644 priv/static/adminfe/chunk-7c6b.d9e7180a.css create mode 100644 priv/static/adminfe/chunk-97e2.b21a8915.css create mode 100644 priv/static/adminfe/chunk-9a72.3e577534.css delete mode 100644 priv/static/adminfe/chunk-c5f4.b1112f18.css create mode 100644 priv/static/adminfe/chunk-commons.67f053f7.css delete mode 100644 priv/static/adminfe/chunk-commons.7f6d2d11.css delete mode 100644 priv/static/adminfe/chunk-e404.a56021ae.css create mode 100644 priv/static/adminfe/chunk-libs.5cf7f50a.css delete mode 100644 priv/static/adminfe/chunk-libs.686b5876.css delete mode 100644 priv/static/adminfe/static/js/ZhIB.861df339.js delete mode 100644 priv/static/adminfe/static/js/ZhIB.861df339.js.map create mode 100644 priv/static/adminfe/static/js/app.86bfcdf3.js create mode 100644 priv/static/adminfe/static/js/app.86bfcdf3.js.map delete mode 100644 priv/static/adminfe/static/js/app.f220ac13.js delete mode 100644 priv/static/adminfe/static/js/app.f220ac13.js.map create mode 100644 priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js create mode 100644 priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-070d.7e10a520.js delete mode 100644 priv/static/adminfe/static/js/chunk-070d.7e10a520.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js delete mode 100644 priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-143c.fc1825bf.js delete mode 100644 priv/static/adminfe/static/js/chunk-143c.fc1825bf.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-1609.98da6b01.js delete mode 100644 priv/static/adminfe/static/js/chunk-1609.98da6b01.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-176e.c4995511.js delete mode 100644 priv/static/adminfe/static/js/chunk-176e.c4995511.js.map create mode 100644 priv/static/adminfe/static/js/chunk-176e.fe016b36.js create mode 100644 priv/static/adminfe/static/js/chunk-176e.fe016b36.js.map create mode 100644 priv/static/adminfe/static/js/chunk-2d97.931fa130.js create mode 100644 priv/static/adminfe/static/js/chunk-2d97.931fa130.js.map create mode 100644 priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js create mode 100644 priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-43ca.aceb457c.js delete mode 100644 priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js delete mode 100644 priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js.map create mode 100644 priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js create mode 100644 priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js delete mode 100644 priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js.map create mode 100644 priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js create mode 100644 priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js.map create mode 100644 priv/static/adminfe/static/js/chunk-654e.d523dfc3.js create mode 100644 priv/static/adminfe/static/js/chunk-654e.d523dfc3.js.map create mode 100644 priv/static/adminfe/static/js/chunk-68ea.a283cad8.js create mode 100644 priv/static/adminfe/static/js/chunk-68ea.a283cad8.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js delete mode 100644 priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js.map create mode 100644 priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js create mode 100644 priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js.map create mode 100644 priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js create mode 100644 priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js.map create mode 100644 priv/static/adminfe/static/js/chunk-7503.ee7af549.js create mode 100644 priv/static/adminfe/static/js/chunk-7503.ee7af549.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-7506.a3364e53.js delete mode 100644 priv/static/adminfe/static/js/chunk-7506.a3364e53.js.map create mode 100644 priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js create mode 100644 priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js delete mode 100644 priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js.map create mode 100644 priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js create mode 100644 priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js.map create mode 100644 priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js create mode 100644 priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js delete mode 100644 priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map create mode 100644 priv/static/adminfe/static/js/chunk-commons.38728553.js create mode 100644 priv/static/adminfe/static/js/chunk-commons.38728553.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-commons.5a106955.js delete mode 100644 priv/static/adminfe/static/js/chunk-commons.5a106955.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-e404.554bc2e3.js delete mode 100644 priv/static/adminfe/static/js/chunk-e404.554bc2e3.js.map create mode 100644 priv/static/adminfe/static/js/chunk-elementUI.2de79b84.js create mode 100644 priv/static/adminfe/static/js/chunk-elementUI.2de79b84.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js delete mode 100644 priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js.map create mode 100644 priv/static/adminfe/static/js/chunk-libs.76802be9.js create mode 100644 priv/static/adminfe/static/js/chunk-libs.76802be9.js.map delete mode 100644 priv/static/adminfe/static/js/chunk-libs.b8c453ab.js delete mode 100644 priv/static/adminfe/static/js/chunk-libs.b8c453ab.js.map delete mode 100644 priv/static/adminfe/static/js/runtime.0a70a9f5.js delete mode 100644 priv/static/adminfe/static/js/runtime.0a70a9f5.js.map create mode 100644 priv/static/adminfe/static/js/runtime.ba9393f3.js create mode 100644 priv/static/adminfe/static/js/runtime.ba9393f3.js.map diff --git a/priv/static/adminfe/app.01bdb34a.css b/priv/static/adminfe/app.01bdb34a.css deleted file mode 100644 index 1b83a8a39..000000000 Binary files a/priv/static/adminfe/app.01bdb34a.css and /dev/null differ diff --git a/priv/static/adminfe/app.61bb0915.css b/priv/static/adminfe/app.61bb0915.css new file mode 100644 index 000000000..9d74d13dc Binary files /dev/null and b/priv/static/adminfe/app.61bb0915.css differ diff --git a/priv/static/adminfe/chunk-0171.8dc0d9da.css b/priv/static/adminfe/chunk-0171.8dc0d9da.css new file mode 100644 index 000000000..824bddc85 Binary files /dev/null and b/priv/static/adminfe/chunk-0171.8dc0d9da.css differ diff --git a/priv/static/adminfe/chunk-070d.d2dd6533.css b/priv/static/adminfe/chunk-070d.d2dd6533.css deleted file mode 100644 index 30bf7de23..000000000 Binary files a/priv/static/adminfe/chunk-070d.d2dd6533.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-0cbc.60bba79b.css b/priv/static/adminfe/chunk-0cbc.60bba79b.css deleted file mode 100644 index c6280f7ef..000000000 Binary files a/priv/static/adminfe/chunk-0cbc.60bba79b.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-143c.43ada4fc.css b/priv/static/adminfe/chunk-143c.43ada4fc.css deleted file mode 100644 index b580e0699..000000000 Binary files a/priv/static/adminfe/chunk-143c.43ada4fc.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-1609.408dae86.css b/priv/static/adminfe/chunk-1609.408dae86.css deleted file mode 100644 index 483d88545..000000000 Binary files a/priv/static/adminfe/chunk-1609.408dae86.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-176e.4d21033f.css b/priv/static/adminfe/chunk-176e.4d21033f.css new file mode 100644 index 000000000..0bedf3773 Binary files /dev/null and b/priv/static/adminfe/chunk-176e.4d21033f.css differ diff --git a/priv/static/adminfe/chunk-176e.5d7d957b.css b/priv/static/adminfe/chunk-176e.5d7d957b.css deleted file mode 100644 index 0bedf3773..000000000 Binary files a/priv/static/adminfe/chunk-176e.5d7d957b.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-2d97.7053ff89.css b/priv/static/adminfe/chunk-2d97.7053ff89.css new file mode 100644 index 000000000..f6e28e1fb Binary files /dev/null and b/priv/static/adminfe/chunk-2d97.7053ff89.css differ diff --git a/priv/static/adminfe/chunk-40a4.2fe71f6c.css b/priv/static/adminfe/chunk-40a4.2fe71f6c.css new file mode 100644 index 000000000..83fefcb55 Binary files /dev/null and b/priv/static/adminfe/chunk-40a4.2fe71f6c.css differ diff --git a/priv/static/adminfe/chunk-43ca.af749c6c.css b/priv/static/adminfe/chunk-43ca.af749c6c.css deleted file mode 100644 index 504affb93..000000000 Binary files a/priv/static/adminfe/chunk-43ca.af749c6c.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-4e7e.5afe1978.css b/priv/static/adminfe/chunk-4e7e.5afe1978.css deleted file mode 100644 index c0074e6f7..000000000 Binary files a/priv/static/adminfe/chunk-4e7e.5afe1978.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-565e.33809ac8.css b/priv/static/adminfe/chunk-565e.33809ac8.css new file mode 100644 index 000000000..063b0b35d Binary files /dev/null and b/priv/static/adminfe/chunk-565e.33809ac8.css differ diff --git a/priv/static/adminfe/chunk-5882.f65db7f2.css b/priv/static/adminfe/chunk-5882.f65db7f2.css deleted file mode 100644 index b5e2a00b0..000000000 Binary files a/priv/static/adminfe/chunk-5882.f65db7f2.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-60a9.a80ec218.css b/priv/static/adminfe/chunk-60a9.a80ec218.css new file mode 100644 index 000000000..d45d79f4c Binary files /dev/null and b/priv/static/adminfe/chunk-60a9.a80ec218.css differ diff --git a/priv/static/adminfe/chunk-654e.e105ec9c.css b/priv/static/adminfe/chunk-654e.e105ec9c.css new file mode 100644 index 000000000..483d88545 Binary files /dev/null and b/priv/static/adminfe/chunk-654e.e105ec9c.css differ diff --git a/priv/static/adminfe/chunk-68ea.be16aa5f.css b/priv/static/adminfe/chunk-68ea.be16aa5f.css new file mode 100644 index 000000000..30bf7de23 Binary files /dev/null and b/priv/static/adminfe/chunk-68ea.be16aa5f.css differ diff --git a/priv/static/adminfe/chunk-6e81.7f126ac7.css b/priv/static/adminfe/chunk-6e81.7f126ac7.css new file mode 100644 index 000000000..da819ca09 Binary files /dev/null and b/priv/static/adminfe/chunk-6e81.7f126ac7.css differ diff --git a/priv/static/adminfe/chunk-6e81.ca3b222f.css b/priv/static/adminfe/chunk-6e81.ca3b222f.css deleted file mode 100644 index da819ca09..000000000 Binary files a/priv/static/adminfe/chunk-6e81.ca3b222f.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-6e8c.f7407fd4.css b/priv/static/adminfe/chunk-6e8c.f7407fd4.css new file mode 100644 index 000000000..6936755b9 Binary files /dev/null and b/priv/static/adminfe/chunk-6e8c.f7407fd4.css differ diff --git a/priv/static/adminfe/chunk-7503.c75b68df.css b/priv/static/adminfe/chunk-7503.c75b68df.css new file mode 100644 index 000000000..93d3eac84 Binary files /dev/null and b/priv/static/adminfe/chunk-7503.c75b68df.css differ diff --git a/priv/static/adminfe/chunk-7506.f01f6c2a.css b/priv/static/adminfe/chunk-7506.f01f6c2a.css deleted file mode 100644 index 93d3eac84..000000000 Binary files a/priv/static/adminfe/chunk-7506.f01f6c2a.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-7c6b.4c8fa90a.css b/priv/static/adminfe/chunk-7c6b.4c8fa90a.css new file mode 100644 index 000000000..9d730019a Binary files /dev/null and b/priv/static/adminfe/chunk-7c6b.4c8fa90a.css differ diff --git a/priv/static/adminfe/chunk-7c6b.d9e7180a.css b/priv/static/adminfe/chunk-7c6b.d9e7180a.css deleted file mode 100644 index 9d730019a..000000000 Binary files a/priv/static/adminfe/chunk-7c6b.d9e7180a.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-97e2.b21a8915.css b/priv/static/adminfe/chunk-97e2.b21a8915.css new file mode 100644 index 000000000..d3b7604aa Binary files /dev/null and b/priv/static/adminfe/chunk-97e2.b21a8915.css differ diff --git a/priv/static/adminfe/chunk-9a72.3e577534.css b/priv/static/adminfe/chunk-9a72.3e577534.css new file mode 100644 index 000000000..c0074e6f7 Binary files /dev/null and b/priv/static/adminfe/chunk-9a72.3e577534.css differ diff --git a/priv/static/adminfe/chunk-c5f4.b1112f18.css b/priv/static/adminfe/chunk-c5f4.b1112f18.css deleted file mode 100644 index d3b7604aa..000000000 Binary files a/priv/static/adminfe/chunk-c5f4.b1112f18.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-commons.67f053f7.css b/priv/static/adminfe/chunk-commons.67f053f7.css new file mode 100644 index 000000000..42f5e0ee9 Binary files /dev/null and b/priv/static/adminfe/chunk-commons.67f053f7.css differ diff --git a/priv/static/adminfe/chunk-commons.7f6d2d11.css b/priv/static/adminfe/chunk-commons.7f6d2d11.css deleted file mode 100644 index 42f5e0ee9..000000000 Binary files a/priv/static/adminfe/chunk-commons.7f6d2d11.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-e404.a56021ae.css b/priv/static/adminfe/chunk-e404.a56021ae.css deleted file mode 100644 index 7d8596ef6..000000000 Binary files a/priv/static/adminfe/chunk-e404.a56021ae.css and /dev/null differ diff --git a/priv/static/adminfe/chunk-libs.5cf7f50a.css b/priv/static/adminfe/chunk-libs.5cf7f50a.css new file mode 100644 index 000000000..3a7a99679 Binary files /dev/null and b/priv/static/adminfe/chunk-libs.5cf7f50a.css differ diff --git a/priv/static/adminfe/chunk-libs.686b5876.css b/priv/static/adminfe/chunk-libs.686b5876.css deleted file mode 100644 index 3a7a99679..000000000 Binary files a/priv/static/adminfe/chunk-libs.686b5876.css and /dev/null differ diff --git a/priv/static/adminfe/index.html b/priv/static/adminfe/index.html index 22b3143d2..5214cc94f 100644 --- a/priv/static/adminfe/index.html +++ b/priv/static/adminfe/index.html @@ -1 +1 @@ -Admin FE
\ No newline at end of file +Admin FE
\ No newline at end of file diff --git a/priv/static/adminfe/static/js/ZhIB.861df339.js b/priv/static/adminfe/static/js/ZhIB.861df339.js deleted file mode 100644 index aeec873c8..000000000 Binary files a/priv/static/adminfe/static/js/ZhIB.861df339.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/ZhIB.861df339.js.map b/priv/static/adminfe/static/js/ZhIB.861df339.js.map deleted file mode 100644 index ff11a2e71..000000000 Binary files a/priv/static/adminfe/static/js/ZhIB.861df339.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/app.86bfcdf3.js b/priv/static/adminfe/static/js/app.86bfcdf3.js new file mode 100644 index 000000000..083555948 Binary files /dev/null and b/priv/static/adminfe/static/js/app.86bfcdf3.js differ diff --git a/priv/static/adminfe/static/js/app.86bfcdf3.js.map b/priv/static/adminfe/static/js/app.86bfcdf3.js.map new file mode 100644 index 000000000..1e35d9d3d Binary files /dev/null and b/priv/static/adminfe/static/js/app.86bfcdf3.js.map differ diff --git a/priv/static/adminfe/static/js/app.f220ac13.js b/priv/static/adminfe/static/js/app.f220ac13.js deleted file mode 100644 index e5e1eda91..000000000 Binary files a/priv/static/adminfe/static/js/app.f220ac13.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/app.f220ac13.js.map b/priv/static/adminfe/static/js/app.f220ac13.js.map deleted file mode 100644 index 90c22121e..000000000 Binary files a/priv/static/adminfe/static/js/app.f220ac13.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js b/priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js new file mode 100644 index 000000000..070fe2201 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js differ diff --git a/priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js.map b/priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js.map new file mode 100644 index 000000000..4696152ee Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0171.9ad03c0e.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-070d.7e10a520.js b/priv/static/adminfe/static/js/chunk-070d.7e10a520.js deleted file mode 100644 index 8726dbcd3..000000000 Binary files a/priv/static/adminfe/static/js/chunk-070d.7e10a520.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-070d.7e10a520.js.map b/priv/static/adminfe/static/js/chunk-070d.7e10a520.js.map deleted file mode 100644 index 6b75a215e..000000000 Binary files a/priv/static/adminfe/static/js/chunk-070d.7e10a520.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js b/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js deleted file mode 100644 index d29070b62..000000000 Binary files a/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map b/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map deleted file mode 100644 index 7c99d9d48..000000000 Binary files a/priv/static/adminfe/static/js/chunk-0cbc.2b0f8802.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-143c.fc1825bf.js b/priv/static/adminfe/static/js/chunk-143c.fc1825bf.js deleted file mode 100644 index 6fbc5b1ed..000000000 Binary files a/priv/static/adminfe/static/js/chunk-143c.fc1825bf.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-143c.fc1825bf.js.map b/priv/static/adminfe/static/js/chunk-143c.fc1825bf.js.map deleted file mode 100644 index 425a7427a..000000000 Binary files a/priv/static/adminfe/static/js/chunk-143c.fc1825bf.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-1609.98da6b01.js b/priv/static/adminfe/static/js/chunk-1609.98da6b01.js deleted file mode 100644 index 29dbad261..000000000 Binary files a/priv/static/adminfe/static/js/chunk-1609.98da6b01.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-1609.98da6b01.js.map b/priv/static/adminfe/static/js/chunk-1609.98da6b01.js.map deleted file mode 100644 index f287a503a..000000000 Binary files a/priv/static/adminfe/static/js/chunk-1609.98da6b01.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-176e.c4995511.js b/priv/static/adminfe/static/js/chunk-176e.c4995511.js deleted file mode 100644 index 80474b904..000000000 Binary files a/priv/static/adminfe/static/js/chunk-176e.c4995511.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-176e.c4995511.js.map b/priv/static/adminfe/static/js/chunk-176e.c4995511.js.map deleted file mode 100644 index f0caa5f62..000000000 Binary files a/priv/static/adminfe/static/js/chunk-176e.c4995511.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-176e.fe016b36.js b/priv/static/adminfe/static/js/chunk-176e.fe016b36.js new file mode 100644 index 000000000..eb57c5863 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-176e.fe016b36.js differ diff --git a/priv/static/adminfe/static/js/chunk-176e.fe016b36.js.map b/priv/static/adminfe/static/js/chunk-176e.fe016b36.js.map new file mode 100644 index 000000000..b3d84706b Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-176e.fe016b36.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-2d97.931fa130.js b/priv/static/adminfe/static/js/chunk-2d97.931fa130.js new file mode 100644 index 000000000..d5ba28881 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-2d97.931fa130.js differ diff --git a/priv/static/adminfe/static/js/chunk-2d97.931fa130.js.map b/priv/static/adminfe/static/js/chunk-2d97.931fa130.js.map new file mode 100644 index 000000000..69c447abc Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-2d97.931fa130.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js b/priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js new file mode 100644 index 000000000..7e3de73d2 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js differ diff --git a/priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js.map b/priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js.map new file mode 100644 index 000000000..935c150cc Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-40a4.e7e37fc4.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js b/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js deleted file mode 100644 index f9fcbc288..000000000 Binary files a/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map b/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map deleted file mode 100644 index 3c71ad178..000000000 Binary files a/priv/static/adminfe/static/js/chunk-43ca.aceb457c.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js b/priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js deleted file mode 100644 index 0fdf0de50..000000000 Binary files a/priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js.map b/priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js.map deleted file mode 100644 index 7a6751cf8..000000000 Binary files a/priv/static/adminfe/static/js/chunk-4e7e.91b5e73a.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js b/priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js new file mode 100644 index 000000000..b72017611 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js differ diff --git a/priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js.map b/priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js.map new file mode 100644 index 000000000..a2bc8a3cd Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-565e.32b3b7b0.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js b/priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js deleted file mode 100644 index a29b6daab..000000000 Binary files a/priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js.map b/priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js.map deleted file mode 100644 index d1aa2037f..000000000 Binary files a/priv/static/adminfe/static/js/chunk-5882.7cbc4c1b.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js b/priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js new file mode 100644 index 000000000..7b3e2e46c Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js differ diff --git a/priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js.map b/priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js.map new file mode 100644 index 000000000..a1bd1aa43 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-60a9.15f68a0f.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-654e.d523dfc3.js b/priv/static/adminfe/static/js/chunk-654e.d523dfc3.js new file mode 100644 index 000000000..44c2c61c8 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-654e.d523dfc3.js differ diff --git a/priv/static/adminfe/static/js/chunk-654e.d523dfc3.js.map b/priv/static/adminfe/static/js/chunk-654e.d523dfc3.js.map new file mode 100644 index 000000000..00f04d1d4 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-654e.d523dfc3.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-68ea.a283cad8.js b/priv/static/adminfe/static/js/chunk-68ea.a283cad8.js new file mode 100644 index 000000000..bb7cbff96 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-68ea.a283cad8.js differ diff --git a/priv/static/adminfe/static/js/chunk-68ea.a283cad8.js.map b/priv/static/adminfe/static/js/chunk-68ea.a283cad8.js.map new file mode 100644 index 000000000..201d8eaa9 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-68ea.a283cad8.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js b/priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js deleted file mode 100644 index f40d31879..000000000 Binary files a/priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js.map b/priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js.map deleted file mode 100644 index 0390c3309..000000000 Binary files a/priv/static/adminfe/static/js/chunk-6e81.6efb01f4.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js b/priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js new file mode 100644 index 000000000..32ede5eff Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js differ diff --git a/priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js.map b/priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js.map new file mode 100644 index 000000000..7301b6957 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-6e81.b4ee7cf5.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js b/priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js new file mode 100644 index 000000000..f6175a4b5 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js differ diff --git a/priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js.map b/priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js.map new file mode 100644 index 000000000..159876ea9 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-6e8c.46fda72d.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-7503.ee7af549.js b/priv/static/adminfe/static/js/chunk-7503.ee7af549.js new file mode 100644 index 000000000..6126d904d Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7503.ee7af549.js differ diff --git a/priv/static/adminfe/static/js/chunk-7503.ee7af549.js.map b/priv/static/adminfe/static/js/chunk-7503.ee7af549.js.map new file mode 100644 index 000000000..cf893c61f Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7503.ee7af549.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-7506.a3364e53.js b/priv/static/adminfe/static/js/chunk-7506.a3364e53.js deleted file mode 100644 index d4eaa356a..000000000 Binary files a/priv/static/adminfe/static/js/chunk-7506.a3364e53.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-7506.a3364e53.js.map b/priv/static/adminfe/static/js/chunk-7506.a3364e53.js.map deleted file mode 100644 index c8e9db8e0..000000000 Binary files a/priv/static/adminfe/static/js/chunk-7506.a3364e53.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js b/priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js new file mode 100644 index 000000000..a349860a8 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js differ diff --git a/priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js.map b/priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js.map new file mode 100644 index 000000000..632e5750e Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7c6b.7c4844a9.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js b/priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js deleted file mode 100644 index 27478ddb1..000000000 Binary files a/priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js.map b/priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js.map deleted file mode 100644 index 2114a3c52..000000000 Binary files a/priv/static/adminfe/static/js/chunk-7c6b.e63ae1da.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js b/priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js new file mode 100644 index 000000000..a3b706d5d Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js differ diff --git a/priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js.map b/priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js.map new file mode 100644 index 000000000..b7a392337 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-97e2.5baa6e73.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js b/priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js new file mode 100644 index 000000000..0dc8e9b68 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js differ diff --git a/priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js.map b/priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js.map new file mode 100644 index 000000000..c351b689e Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-9a72.7b2fc06e.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js b/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js deleted file mode 100644 index 2d5308031..000000000 Binary files a/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map b/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map deleted file mode 100644 index d5fc047ee..000000000 Binary files a/priv/static/adminfe/static/js/chunk-c5f4.cf269f9b.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-commons.38728553.js b/priv/static/adminfe/static/js/chunk-commons.38728553.js new file mode 100644 index 000000000..0f2ffce9f Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-commons.38728553.js differ diff --git a/priv/static/adminfe/static/js/chunk-commons.38728553.js.map b/priv/static/adminfe/static/js/chunk-commons.38728553.js.map new file mode 100644 index 000000000..048f21e43 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-commons.38728553.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-commons.5a106955.js b/priv/static/adminfe/static/js/chunk-commons.5a106955.js deleted file mode 100644 index a6cf2ce52..000000000 Binary files a/priv/static/adminfe/static/js/chunk-commons.5a106955.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-commons.5a106955.js.map b/priv/static/adminfe/static/js/chunk-commons.5a106955.js.map deleted file mode 100644 index d924490e5..000000000 Binary files a/priv/static/adminfe/static/js/chunk-commons.5a106955.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-e404.554bc2e3.js b/priv/static/adminfe/static/js/chunk-e404.554bc2e3.js deleted file mode 100644 index 769e9f4f9..000000000 Binary files a/priv/static/adminfe/static/js/chunk-e404.554bc2e3.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-e404.554bc2e3.js.map b/priv/static/adminfe/static/js/chunk-e404.554bc2e3.js.map deleted file mode 100644 index e8214adbb..000000000 Binary files a/priv/static/adminfe/static/js/chunk-e404.554bc2e3.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-elementUI.2de79b84.js b/priv/static/adminfe/static/js/chunk-elementUI.2de79b84.js new file mode 100644 index 000000000..c76b0430b Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-elementUI.2de79b84.js differ diff --git a/priv/static/adminfe/static/js/chunk-elementUI.2de79b84.js.map b/priv/static/adminfe/static/js/chunk-elementUI.2de79b84.js.map new file mode 100644 index 000000000..fa9dc12f0 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-elementUI.2de79b84.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js b/priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js deleted file mode 100644 index f106931f5..000000000 Binary files a/priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js.map b/priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js.map deleted file mode 100644 index a1f726fde..000000000 Binary files a/priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-libs.76802be9.js b/priv/static/adminfe/static/js/chunk-libs.76802be9.js new file mode 100644 index 000000000..984b5ad40 Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-libs.76802be9.js differ diff --git a/priv/static/adminfe/static/js/chunk-libs.76802be9.js.map b/priv/static/adminfe/static/js/chunk-libs.76802be9.js.map new file mode 100644 index 000000000..d4680796a Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-libs.76802be9.js.map differ diff --git a/priv/static/adminfe/static/js/chunk-libs.b8c453ab.js b/priv/static/adminfe/static/js/chunk-libs.b8c453ab.js deleted file mode 100644 index 2af35eb62..000000000 Binary files a/priv/static/adminfe/static/js/chunk-libs.b8c453ab.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/chunk-libs.b8c453ab.js.map b/priv/static/adminfe/static/js/chunk-libs.b8c453ab.js.map deleted file mode 100644 index 9c9d9acde..000000000 Binary files a/priv/static/adminfe/static/js/chunk-libs.b8c453ab.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/runtime.0a70a9f5.js b/priv/static/adminfe/static/js/runtime.0a70a9f5.js deleted file mode 100644 index a99d1d369..000000000 Binary files a/priv/static/adminfe/static/js/runtime.0a70a9f5.js and /dev/null differ diff --git a/priv/static/adminfe/static/js/runtime.0a70a9f5.js.map b/priv/static/adminfe/static/js/runtime.0a70a9f5.js.map deleted file mode 100644 index 62e726b22..000000000 Binary files a/priv/static/adminfe/static/js/runtime.0a70a9f5.js.map and /dev/null differ diff --git a/priv/static/adminfe/static/js/runtime.ba9393f3.js b/priv/static/adminfe/static/js/runtime.ba9393f3.js new file mode 100644 index 000000000..c66462ab6 Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.ba9393f3.js differ diff --git a/priv/static/adminfe/static/js/runtime.ba9393f3.js.map b/priv/static/adminfe/static/js/runtime.ba9393f3.js.map new file mode 100644 index 000000000..c167edf90 Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.ba9393f3.js.map differ -- cgit v1.2.3 From 95529ab709b14acbf0b4ef2c17a76e0540e1e84e Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Fri, 14 Aug 2020 20:55:45 +0300 Subject: [#2046] Defaulted pleroma/restrict_unauthenticated basing on instance privacy setting (i.e. restrict on private instances only by default). --- config/config.exs | 8 ++++--- lib/pleroma/config.ex | 10 ++++++++ lib/pleroma/user.ex | 8 ++++--- lib/pleroma/web/activity_pub/visibility.ex | 7 ++---- .../controllers/timeline_controller.ex | 5 ++-- lib/pleroma/web/preload/timelines.ex | 2 +- test/web/preload/timeline_test.exs | 28 ++++------------------ 7 files changed, 31 insertions(+), 37 deletions(-) diff --git a/config/config.exs b/config/config.exs index eb85a6ed4..a7c9e54b1 100644 --- a/config/config.exs +++ b/config/config.exs @@ -725,10 +725,12 @@ timeout: 300_000 ] +private_instance? = :if_instance_is_private + config :pleroma, :restrict_unauthenticated, - timelines: %{local: false, federated: false}, - profiles: %{local: false, remote: false}, - activities: %{local: false, remote: false} + timelines: %{local: private_instance?, federated: private_instance?}, + profiles: %{local: private_instance?, remote: private_instance?}, + activities: %{local: private_instance?, remote: private_instance?} config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false diff --git a/lib/pleroma/config.ex b/lib/pleroma/config.ex index a8329cc1e..97f877595 100644 --- a/lib/pleroma/config.ex +++ b/lib/pleroma/config.ex @@ -81,6 +81,16 @@ def delete(key) do Application.delete_env(:pleroma, key) end + def restrict_unauthenticated_access?(resource, kind) do + setting = get([:restrict_unauthenticated, resource, kind]) + + if setting in [nil, :if_instance_is_private] do + !get!([:instance, :public]) + else + setting + end + end + def oauth_consumer_strategies, do: get([:auth, :oauth_consumer_strategies], []) def oauth_consumer_enabled?, do: oauth_consumer_strategies() != [] diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index d1436a688..ac065e9dc 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -311,10 +311,12 @@ def visible_for(%User{} = user, for_user) do def visible_for(_, _), do: :invisible - defp restrict_unauthenticated?(%User{local: local}) do - config_key = if local, do: :local, else: :remote + defp restrict_unauthenticated?(%User{local: true}) do + Config.restrict_unauthenticated_access?(:profiles, :local) + end - Config.get([:restrict_unauthenticated, :profiles, config_key], false) + defp restrict_unauthenticated?(%User{local: _}) do + Config.restrict_unauthenticated_access?(:profiles, :remote) end defp visible_account_status(user) do diff --git a/lib/pleroma/web/activity_pub/visibility.ex b/lib/pleroma/web/activity_pub/visibility.ex index 343f41caa..5c349bb7a 100644 --- a/lib/pleroma/web/activity_pub/visibility.ex +++ b/lib/pleroma/web/activity_pub/visibility.ex @@ -59,12 +59,9 @@ def visible_for_user?(%{data: %{"listMessage" => list_ap_id}} = activity, %User{ end def visible_for_user?(%{local: local} = activity, nil) do - cfg_key = - if local, - do: :local, - else: :remote + cfg_key = if local, do: :local, else: :remote - if Pleroma.Config.get([:restrict_unauthenticated, :activities, cfg_key]), + if Pleroma.Config.restrict_unauthenticated_access?(:activities, cfg_key), do: false, else: is_public?(activity) end diff --git a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex index ab7b1d6aa..9244316ed 100644 --- a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex @@ -8,6 +8,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, add_link_headers: 3] + alias Pleroma.Config alias Pleroma.Pagination alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug alias Pleroma.Plugs.OAuthScopesPlug @@ -89,11 +90,11 @@ def direct(%{assigns: %{user: user}} = conn, params) do end defp restrict_unauthenticated?(true = _local_only) do - Pleroma.Config.get([:restrict_unauthenticated, :timelines, :local]) + Config.restrict_unauthenticated_access?(:timelines, :local) end defp restrict_unauthenticated?(_) do - Pleroma.Config.get([:restrict_unauthenticated, :timelines, :federated]) + Config.restrict_unauthenticated_access?(:timelines, :federated) end # GET /api/v1/timelines/public diff --git a/lib/pleroma/web/preload/timelines.ex b/lib/pleroma/web/preload/timelines.ex index 57de04051..b279a865d 100644 --- a/lib/pleroma/web/preload/timelines.ex +++ b/lib/pleroma/web/preload/timelines.ex @@ -16,7 +16,7 @@ def generate_terms(params) do end def build_public_tag(acc, params) do - if Pleroma.Config.get([:restrict_unauthenticated, :timelines, :federated], true) do + if Pleroma.Config.restrict_unauthenticated_access?(:timelines, :federated) do acc else Map.put(acc, @public_url, public_timeline(params)) diff --git a/test/web/preload/timeline_test.exs b/test/web/preload/timeline_test.exs index fea95a6a4..3b1f2f1aa 100644 --- a/test/web/preload/timeline_test.exs +++ b/test/web/preload/timeline_test.exs @@ -12,16 +12,8 @@ defmodule Pleroma.Web.Preload.Providers.TimelineTest do @public_url "/api/v1/timelines/public" describe "unauthenticated timeliness when restricted" do - setup do - svd_config = Pleroma.Config.get([:restrict_unauthenticated, :timelines]) - Pleroma.Config.put([:restrict_unauthenticated, :timelines], %{local: true, federated: true}) - - on_exit(fn -> - Pleroma.Config.put([:restrict_unauthenticated, :timelines], svd_config) - end) - - :ok - end + setup do: clear_config([:restrict_unauthenticated, :timelines, :local], true) + setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], true) test "return nothing" do tl_data = Timelines.generate_terms(%{}) @@ -31,20 +23,10 @@ test "return nothing" do end describe "unauthenticated timeliness when unrestricted" do - setup do - svd_config = Pleroma.Config.get([:restrict_unauthenticated, :timelines]) + setup do: clear_config([:restrict_unauthenticated, :timelines, :local], false) + setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], false) - Pleroma.Config.put([:restrict_unauthenticated, :timelines], %{ - local: false, - federated: false - }) - - on_exit(fn -> - Pleroma.Config.put([:restrict_unauthenticated, :timelines], svd_config) - end) - - {:ok, user: insert(:user)} - end + setup do: {:ok, user: insert(:user)} test "returns the timeline when not restricted" do assert Timelines.generate_terms(%{}) -- cgit v1.2.3 From 6c3130ef47562496e9b2605bc05cae90cd6af03b Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 14 Aug 2020 13:07:58 -0500 Subject: Improve description for mediaproxy cache invalidation settings --- config/description.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/description.exs b/config/description.exs index 7734ff7a1..e27abf40f 100644 --- a/config/description.exs +++ b/config/description.exs @@ -1810,12 +1810,12 @@ %{ key: :enabled, type: :boolean, - description: "Enables invalidate media cache" + description: "Enables media cache object invalidation." }, %{ key: :provider, type: :module, - description: "Module which will be used to cache purge.", + description: "Module which will be used to purge objects from the cache.", suggestions: [ Pleroma.Web.MediaProxy.Invalidation.Script, Pleroma.Web.MediaProxy.Invalidation.Http -- cgit v1.2.3 From 4fcf272717bf2d8f582720de69fa9e50cab1b66a Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sat, 15 Aug 2020 09:49:12 +0300 Subject: Docs: Fix the way tabs are declared Since python doesn't have a way to lock deps for a particlar project by default, I didn't bother with it. This resulted in mkdocs updating at some point, bringing a breaking change to how tabs are declared and broken tabs on docs-develop.pleroma.social. I've learned my lesson and locked deps with pipenv in pleroma/docs!5. This MR updates Pleroma docs to use the new tab style, fortunately my editor did most of it. Closes #2045 --- docs/administration/CLI_tasks/config.md | 29 ++- docs/administration/CLI_tasks/database.md | 129 ++++++---- docs/administration/CLI_tasks/digest.md | 32 ++- docs/administration/CLI_tasks/email.md | 32 ++- docs/administration/CLI_tasks/emoji.md | 49 ++-- docs/administration/CLI_tasks/instance.md | 16 +- docs/administration/CLI_tasks/oauth_app.md | 16 +- docs/administration/CLI_tasks/relay.md | 48 ++-- docs/administration/CLI_tasks/robots_txt.md | 16 +- docs/administration/CLI_tasks/uploads.md | 16 +- docs/administration/CLI_tasks/user.md | 288 ++++++++++++++-------- docs/configuration/static_dir.md | 20 +- docs/installation/migrating_from_source_otp_en.md | 48 ++-- docs/installation/otp_en.md | 200 ++++++++------- 14 files changed, 567 insertions(+), 372 deletions(-) diff --git a/docs/administration/CLI_tasks/config.md b/docs/administration/CLI_tasks/config.md index cc32bf859..0923004b5 100644 --- a/docs/administration/CLI_tasks/config.md +++ b/docs/administration/CLI_tasks/config.md @@ -11,14 +11,17 @@ config :pleroma, configurable_from_database: true ``` -```sh tab="OTP" - ./bin/pleroma_ctl config migrate_to_db -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.config migrate_to_db -``` + ```sh + ./bin/pleroma_ctl config migrate_to_db + ``` + +=== "From Source" + ```sh + mix pleroma.config migrate_to_db + ``` ## Transfer config from DB to `config/env.exported_from_db.secret.exs` @@ -31,10 +34,12 @@ mix pleroma.config migrate_to_db To delete transfered settings from database optional flag `-d` can be used. `` is `prod` by default. -```sh tab="OTP" - ./bin/pleroma_ctl config migrate_from_db [--env=] [-d] -``` +=== "OTP" + ```sh + ./bin/pleroma_ctl config migrate_from_db [--env=] [-d] + ``` -```sh tab="From Source" -mix pleroma.config migrate_from_db [--env=] [-d] -``` +=== "From Source" + ```sh + mix pleroma.config migrate_from_db [--env=] [-d] + ``` diff --git a/docs/administration/CLI_tasks/database.md b/docs/administration/CLI_tasks/database.md index 64dd66c0c..6dca83167 100644 --- a/docs/administration/CLI_tasks/database.md +++ b/docs/administration/CLI_tasks/database.md @@ -9,13 +9,18 @@ Replaces embedded objects with references to them in the `objects` table. Only needs to be ran once if the instance was created before Pleroma 1.0.5. The reason why this is not a migration is because it could significantly increase the database size after being ran, however after this `VACUUM FULL` will be able to reclaim about 20% (really depends on what is in the database, your mileage may vary) of the db size before the migration. -```sh tab="OTP" -./bin/pleroma_ctl database remove_embedded_objects [option ...] -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl database remove_embedded_objects [option ...] + ``` + +=== "From Source" + + ```sh + mix pleroma.database remove_embedded_objects [option ...] + ``` -```sh tab="From Source" -mix pleroma.database remove_embedded_objects [option ...] -``` ### Options - `--vacuum` - run `VACUUM FULL` after the embedded objects are replaced with their references @@ -27,13 +32,17 @@ This will prune remote posts older than 90 days (configurable with [`config :ple !!! danger The disk space will only be reclaimed after `VACUUM FULL`. You may run out of disk space during the execution of the task or vacuuming if you don't have about 1/3rds of the database size free. -```sh tab="OTP" -./bin/pleroma_ctl database prune_objects [option ...] -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl database prune_objects [option ...] + ``` + +=== "From Source" -```sh tab="From Source" -mix pleroma.database prune_objects [option ...] -``` + ```sh + mix pleroma.database prune_objects [option ...] + ``` ### Options - `--vacuum` - run `VACUUM FULL` after the objects are pruned @@ -42,33 +51,45 @@ mix pleroma.database prune_objects [option ...] Can be safely re-run -```sh tab="OTP" -./bin/pleroma_ctl database bump_all_conversations -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.database bump_all_conversations -``` + ```sh + ./bin/pleroma_ctl database bump_all_conversations + ``` + +=== "From Source" + + ```sh + mix pleroma.database bump_all_conversations + ``` ## Remove duplicated items from following and update followers count for all users -```sh tab="OTP" -./bin/pleroma_ctl database update_users_following_followers_counts -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl database update_users_following_followers_counts + ``` + +=== "From Source" -```sh tab="From Source" -mix pleroma.database update_users_following_followers_counts -``` + ```sh + mix pleroma.database update_users_following_followers_counts + ``` ## Fix the pre-existing "likes" collections for all objects -```sh tab="OTP" -./bin/pleroma_ctl database fix_likes_collections -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.database fix_likes_collections -``` + ```sh + ./bin/pleroma_ctl database fix_likes_collections + ``` + +=== "From Source" + + ```sh + mix pleroma.database fix_likes_collections + ``` ## Vacuum the database @@ -76,13 +97,17 @@ mix pleroma.database fix_likes_collections Running an `analyze` vacuum job can improve performance by updating statistics used by the query planner. **It is safe to cancel this.** -```sh tab="OTP" -./bin/pleroma_ctl database vacuum analyze -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl database vacuum analyze + ``` + +=== "From Source" -```sh tab="From Source" -mix pleroma.database vacuum analyze -``` + ```sh + mix pleroma.database vacuum analyze + ``` ### Full @@ -91,20 +116,28 @@ and more compact files with an optimized layout. This process will take a long t it builds the files side-by-side the existing database files. It can make your database faster and use less disk space, but should only be run if necessary. **It is safe to cancel this.** -```sh tab="OTP" -./bin/pleroma_ctl database vacuum full -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.database vacuum full -``` + ```sh + ./bin/pleroma_ctl database vacuum full + ``` + +=== "From Source" + + ```sh + mix pleroma.database vacuum full + ``` ## Add expiration to all local statuses -```sh tab="OTP" -./bin/pleroma_ctl database ensure_expiration -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl database ensure_expiration + ``` + +=== "From Source" -```sh tab="From Source" -mix pleroma.database ensure_expiration -``` + ```sh + mix pleroma.database ensure_expiration + ``` diff --git a/docs/administration/CLI_tasks/digest.md b/docs/administration/CLI_tasks/digest.md index 2eb31379e..a590581e3 100644 --- a/docs/administration/CLI_tasks/digest.md +++ b/docs/administration/CLI_tasks/digest.md @@ -4,22 +4,30 @@ ## Send digest email since given date (user registration date by default) ignoring user activity status. -```sh tab="OTP" - ./bin/pleroma_ctl digest test [since_date] -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.digest test [since_date] -``` + ```sh + ./bin/pleroma_ctl digest test [since_date] + ``` + +=== "From Source" + + ```sh + mix pleroma.digest test [since_date] + ``` Example: -```sh tab="OTP" -./bin/pleroma_ctl digest test donaldtheduck 2019-05-20 -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl digest test donaldtheduck 2019-05-20 + ``` + +=== "From Source" -```sh tab="From Source" -mix pleroma.digest test donaldtheduck 2019-05-20 -``` + ```sh + mix pleroma.digest test donaldtheduck 2019-05-20 + ``` diff --git a/docs/administration/CLI_tasks/email.md b/docs/administration/CLI_tasks/email.md index 7b7a8457a..00d2e74f8 100644 --- a/docs/administration/CLI_tasks/email.md +++ b/docs/administration/CLI_tasks/email.md @@ -4,21 +4,29 @@ ## Send test email (instance email by default) -```sh tab="OTP" - ./bin/pleroma_ctl email test [--to ] -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.email test [--to ] -``` + ```sh + ./bin/pleroma_ctl email test [--to ] + ``` + +=== "From Source" + + ```sh + mix pleroma.email test [--to ] + ``` Example: -```sh tab="OTP" -./bin/pleroma_ctl email test --to root@example.org -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl email test --to root@example.org + ``` + +=== "From Source" -```sh tab="From Source" -mix pleroma.email test --to root@example.org -``` + ```sh + mix pleroma.email test --to root@example.org + ``` diff --git a/docs/administration/CLI_tasks/emoji.md b/docs/administration/CLI_tasks/emoji.md index ddcb7e62c..e3d1b210e 100644 --- a/docs/administration/CLI_tasks/emoji.md +++ b/docs/administration/CLI_tasks/emoji.md @@ -4,13 +4,15 @@ ## Lists emoji packs and metadata specified in the manifest -```sh tab="OTP" -./bin/pleroma_ctl emoji ls-packs [option ...] -``` +=== "OTP" + ```sh + ./bin/pleroma_ctl emoji ls-packs [option ...] + ``` -```sh tab="From Source" -mix pleroma.emoji ls-packs [option ...] -``` +=== "From Source" + ```sh + mix pleroma.emoji ls-packs [option ...] + ``` ### Options @@ -18,26 +20,30 @@ mix pleroma.emoji ls-packs [option ...] ## Fetch, verify and install the specified packs from the manifest into `STATIC-DIR/emoji/PACK-NAME` -```sh tab="OTP" -./bin/pleroma_ctl emoji get-packs [option ...] -``` +=== "OTP" + ```sh + ./bin/pleroma_ctl emoji get-packs [option ...] + ``` -```sh tab="From Source" -mix pleroma.emoji get-packs [option ...] -``` +=== "From Source" + ```sh + mix pleroma.emoji get-packs [option ...] + ``` ### Options - `-m, --manifest PATH/URL` - same as [`ls-packs`](#ls-packs) ## Create a new manifest entry and a file list from the specified remote pack file -```sh tab="OTP" -./bin/pleroma_ctl emoji gen-pack PACK-URL -``` +=== "OTP" + ```sh + ./bin/pleroma_ctl emoji gen-pack PACK-URL + ``` -```sh tab="From Source" -mix pleroma.emoji gen-pack PACK-URL -``` +=== "From Source" + ```sh + mix pleroma.emoji gen-pack PACK-URL + ``` Currently, only .zip archives are recognized as remote pack files and packs are therefore assumed to be zip archives. This command is intended to run interactively and will first ask you some basic questions about the pack, then download the remote file and generate an SHA256 checksum for it, then generate an emoji file list for you. @@ -47,8 +53,9 @@ Currently, only .zip archives are recognized as remote pack files and packs are ## Reload emoji packs -```sh tab="OTP" -./bin/pleroma_ctl emoji reload -``` +=== "OTP" + ```sh + ./bin/pleroma_ctl emoji reload + ``` This command only works with OTP releases. diff --git a/docs/administration/CLI_tasks/instance.md b/docs/administration/CLI_tasks/instance.md index 52e264bb1..989ecc55d 100644 --- a/docs/administration/CLI_tasks/instance.md +++ b/docs/administration/CLI_tasks/instance.md @@ -3,13 +3,17 @@ {! backend/administration/CLI_tasks/general_cli_task_info.include !} ## Generate a new configuration file -```sh tab="OTP" - ./bin/pleroma_ctl instance gen [option ...] -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.instance gen [option ...] -``` + ```sh + ./bin/pleroma_ctl instance gen [option ...] + ``` + +=== "From Source" + + ```sh + mix pleroma.instance gen [option ...] + ``` If any of the options are left unspecified, you will be prompted interactively. diff --git a/docs/administration/CLI_tasks/oauth_app.md b/docs/administration/CLI_tasks/oauth_app.md index 4d6bfc25a..f0568491e 100644 --- a/docs/administration/CLI_tasks/oauth_app.md +++ b/docs/administration/CLI_tasks/oauth_app.md @@ -7,10 +7,14 @@ Optional params: * `-s SCOPES` - scopes for app, e.g. `read,write,follow,push`. -```sh tab="OTP" - ./bin/pleroma_ctl app create -n APP_NAME -r REDIRECT_URI -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.app create -n APP_NAME -r REDIRECT_URI -``` \ No newline at end of file + ```sh + ./bin/pleroma_ctl app create -n APP_NAME -r REDIRECT_URI + ``` + +=== "From Source" + + ```sh + mix pleroma.app create -n APP_NAME -r REDIRECT_URI + ``` \ No newline at end of file diff --git a/docs/administration/CLI_tasks/relay.md b/docs/administration/CLI_tasks/relay.md index c4f078f4d..bdd7e8be4 100644 --- a/docs/administration/CLI_tasks/relay.md +++ b/docs/administration/CLI_tasks/relay.md @@ -4,30 +4,42 @@ ## Follow a relay -```sh tab="OTP" -./bin/pleroma_ctl relay follow -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.relay follow -``` + ```sh + ./bin/pleroma_ctl relay follow + ``` + +=== "From Source" + + ```sh + mix pleroma.relay follow + ``` ## Unfollow a remote relay -```sh tab="OTP" -./bin/pleroma_ctl relay unfollow -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl relay unfollow + ``` -```sh tab="From Source" -mix pleroma.relay unfollow -``` +=== "From Source" + + ```sh + mix pleroma.relay unfollow + ``` ## List relay subscriptions -```sh tab="OTP" -./bin/pleroma_ctl relay list -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl relay list + ``` + +=== "From Source" -```sh tab="From Source" -mix pleroma.relay list -``` + ```sh + mix pleroma.relay list + ``` diff --git a/docs/administration/CLI_tasks/robots_txt.md b/docs/administration/CLI_tasks/robots_txt.md index 844318cc8..7eeedf571 100644 --- a/docs/administration/CLI_tasks/robots_txt.md +++ b/docs/administration/CLI_tasks/robots_txt.md @@ -8,10 +8,14 @@ The `robots.txt` that ships by default is permissive. It allows well-behaved sea If you want to generate a restrictive `robots.txt`, you can run the following mix task. The generated `robots.txt` will be written in your instance [static directory](../../../configuration/static_dir/). -```elixir tab="OTP" -./bin/pleroma_ctl robots_txt disallow_all -``` +=== "OTP" -```elixir tab="From Source" -mix pleroma.robots_txt disallow_all -``` + ```sh + ./bin/pleroma_ctl robots_txt disallow_all + ``` + +=== "From Source" + + ```sh + mix pleroma.robots_txt disallow_all + ``` diff --git a/docs/administration/CLI_tasks/uploads.md b/docs/administration/CLI_tasks/uploads.md index 6a15d22f6..8585ec76b 100644 --- a/docs/administration/CLI_tasks/uploads.md +++ b/docs/administration/CLI_tasks/uploads.md @@ -3,13 +3,17 @@ {! backend/administration/CLI_tasks/general_cli_task_info.include !} ## Migrate uploads from local to remote storage -```sh tab="OTP" - ./bin/pleroma_ctl uploads migrate_local [option ...] -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.uploads migrate_local [option ...] -``` + ```sh + ./bin/pleroma_ctl uploads migrate_local [option ...] + ``` + +=== "From Source" + + ```sh + mix pleroma.uploads migrate_local [option ...] + ``` ### Options - `--delete` - delete local uploads after migrating them to the target uploader diff --git a/docs/administration/CLI_tasks/user.md b/docs/administration/CLI_tasks/user.md index 3b4c421a7..3e7f028ba 100644 --- a/docs/administration/CLI_tasks/user.md +++ b/docs/administration/CLI_tasks/user.md @@ -4,13 +4,17 @@ ## Create a user -```sh tab="OTP" -./bin/pleroma_ctl user new [option ...] -``` +=== "OTP" -```sh tab="From Source" -mix pleroma.user new [option ...] -``` + ```sh + ./bin/pleroma_ctl user new [option ...] + ``` + +=== "From Source" + + ```sh + mix pleroma.user new [option ...] + ``` ### Options @@ -22,23 +26,33 @@ mix pleroma.user new [option ...] - `-y`, `--assume-yes`/`--no-assume-yes` - whether to assume yes to all questions ## List local users -```sh tab="OTP" - ./bin/pleroma_ctl user list -``` -```sh tab="From Source" -mix pleroma.user list -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user list + ``` + +=== "From Source" + + ```sh + mix pleroma.user list + ``` ## Generate an invite link -```sh tab="OTP" - ./bin/pleroma_ctl user invite [option ...] -``` -```sh tab="From Source" -mix pleroma.user invite [option ...] -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user invite [option ...] + ``` + +=== "From Source" + + ```sh + mix pleroma.user invite [option ...] + ``` ### Options @@ -46,113 +60,168 @@ mix pleroma.user invite [option ...] - `--max-use NUMBER` - maximum numbers of token uses ## List generated invites -```sh tab="OTP" - ./bin/pleroma_ctl user invites -``` -```sh tab="From Source" -mix pleroma.user invites -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user invites + ``` + +=== "From Source" + + ```sh + mix pleroma.user invites + ``` ## Revoke invite -```sh tab="OTP" - ./bin/pleroma_ctl user revoke_invite -``` -```sh tab="From Source" -mix pleroma.user revoke_invite -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user revoke_invite + ``` + +=== "From Source" + + ```sh + mix pleroma.user revoke_invite + ``` ## Delete a user -```sh tab="OTP" - ./bin/pleroma_ctl user rm -``` -```sh tab="From Source" -mix pleroma.user rm -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user rm + ``` + +=== "From Source" + + ```sh + mix pleroma.user rm + ``` ## Delete user's posts and interactions -```sh tab="OTP" - ./bin/pleroma_ctl user delete_activities -``` -```sh tab="From Source" -mix pleroma.user delete_activities -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user delete_activities + ``` + +=== "From Source" + + ```sh + mix pleroma.user delete_activities + ``` ## Sign user out from all applications (delete user's OAuth tokens and authorizations) -```sh tab="OTP" - ./bin/pleroma_ctl user sign_out -``` -```sh tab="From Source" -mix pleroma.user sign_out -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user sign_out + ``` + +=== "From Source" + + ```sh + mix pleroma.user sign_out + ``` ## Deactivate or activate a user -```sh tab="OTP" - ./bin/pleroma_ctl user toggle_activated -``` -```sh tab="From Source" -mix pleroma.user toggle_activated -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user toggle_activated + ``` + +=== "From Source" + + ```sh + mix pleroma.user toggle_activated + ``` ## Deactivate a user and unsubscribes local users from the user -```sh tab="OTP" - ./bin/pleroma_ctl user deactivate NICKNAME -``` -```sh tab="From Source" -mix pleroma.user deactivate NICKNAME -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user deactivate NICKNAME + ``` + +=== "From Source" + + ```sh + mix pleroma.user deactivate NICKNAME + ``` ## Deactivate all accounts from an instance and unsubscribe local users on it -```sh tab="OTP" - ./bin/pleroma_ctl user deactivate_all_from_instance -``` -```sh tab="From Source" -mix pleroma.user deactivate_all_from_instance -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user deactivate_all_from_instance + ``` + +=== "From Source" + + ```sh + mix pleroma.user deactivate_all_from_instance + ``` ## Create a password reset link for user -```sh tab="OTP" - ./bin/pleroma_ctl user reset_password -``` -```sh tab="From Source" -mix pleroma.user reset_password -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user reset_password + ``` + +=== "From Source" + + ```sh + mix pleroma.user reset_password + ``` ## Disable Multi Factor Authentication (MFA/2FA) for a user -```sh tab="OTP" - ./bin/pleroma_ctl user reset_mfa -``` -```sh tab="From Source" -mix pleroma.user reset_mfa -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user reset_mfa + ``` + +=== "From Source" + + ```sh + mix pleroma.user reset_mfa + ``` ## Set the value of the given user's settings -```sh tab="OTP" - ./bin/pleroma_ctl user set [option ...] -``` -```sh tab="From Source" -mix pleroma.user set [option ...] -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user set [option ...] + ``` + +=== "From Source" + + ```sh + mix pleroma.user set [option ...] + ``` ### Options - `--locked`/`--no-locked` - whether the user should be locked @@ -160,30 +229,45 @@ mix pleroma.user set [option ...] - `--admin`/`--no-admin` - whether the user should be an admin ## Add tags to a user -```sh tab="OTP" - ./bin/pleroma_ctl user tag -``` -```sh tab="From Source" -mix pleroma.user tag -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user tag + ``` + +=== "From Source" + + ```sh + mix pleroma.user tag + ``` ## Delete tags from a user -```sh tab="OTP" - ./bin/pleroma_ctl user untag -``` -```sh tab="From Source" -mix pleroma.user untag -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user untag + ``` + +=== "From Source" + + ```sh + mix pleroma.user untag + ``` ## Toggle confirmation status of the user -```sh tab="OTP" - ./bin/pleroma_ctl user toggle_confirmed -``` -```sh tab="From Source" -mix pleroma.user toggle_confirmed -``` +=== "OTP" + + ```sh + ./bin/pleroma_ctl user toggle_confirmed + ``` + +=== "From Source" + + ```sh + mix pleroma.user toggle_confirmed + ``` diff --git a/docs/configuration/static_dir.md b/docs/configuration/static_dir.md index 58703e3be..8ac07b725 100644 --- a/docs/configuration/static_dir.md +++ b/docs/configuration/static_dir.md @@ -4,15 +4,19 @@ Static frontend files are shipped with pleroma. If you want to overwrite or upda You can find the location of the static directory in the [configuration](../cheatsheet/#instance). -```elixir tab="OTP" -config :pleroma, :instance, - static_dir: "/var/lib/pleroma/static/", -``` +=== "OTP" -```elixir tab="From Source" -config :pleroma, :instance, - static_dir: "instance/static/", -``` + ```elixir + config :pleroma, :instance, + static_dir: "/var/lib/pleroma/static/" + ``` + +=== "From Source" + + ```elixir + config :pleroma, :instance, + static_dir: "instance/static/" + ``` Alternatively, you can overwrite this value in your configuration to use a different static instance directory. diff --git a/docs/installation/migrating_from_source_otp_en.md b/docs/installation/migrating_from_source_otp_en.md index 31c2f1294..d303a6daf 100644 --- a/docs/installation/migrating_from_source_otp_en.md +++ b/docs/installation/migrating_from_source_otp_en.md @@ -8,13 +8,15 @@ You will be running commands as root. If you aren't root already, please elevate The system needs to have `curl` and `unzip` installed for downloading and unpacking release builds. -```sh tab="Alpine" -apk add curl unzip -``` +=== "Alpine" + ```sh + apk add curl unzip + ``` -```sh tab="Debian/Ubuntu" -apt install curl unzip -``` +=== "Debian/Ubuntu" + ```sh + apt install curl unzip + ``` ## Moving content out of the application directory When using OTP releases the application directory changes with every version so it would be a bother to keep content there (and also dangerous unless `--no-rm` option is used when updating). Fortunately almost all paths in Pleroma are configurable, so it is possible to move them out of there. @@ -110,27 +112,29 @@ OTP releases have different service files than from-source installs so they need **Warning:** The service files assume pleroma user's home directory is `/opt/pleroma`, please make sure all paths fit your installation. -```sh tab="Alpine" -# Copy the service into a proper directory -cp -f ~pleroma/installation/init.d/pleroma /etc/init.d/pleroma +=== "Alpine" + ```sh + # Copy the service into a proper directory + cp -f ~pleroma/installation/init.d/pleroma /etc/init.d/pleroma -# Start pleroma -rc-service pleroma start -``` + # Start pleroma + rc-service pleroma start + ``` -```sh tab="Debian/Ubuntu" -# Copy the service into a proper directory -cp ~pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service +=== "Debian/Ubuntu" + ```sh + # Copy the service into a proper directory + cp ~pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service -# Reload service files -systemctl daemon-reload + # Reload service files + systemctl daemon-reload -# Reenable pleroma to start on boot -systemctl reenable pleroma + # Reenable pleroma to start on boot + systemctl reenable pleroma -# Start pleroma -systemctl start pleroma -``` + # Start pleroma + systemctl start pleroma + ``` ## Running mix tasks Refer to [Running mix tasks](otp_en.md#running-mix-tasks) section from OTP release installation guide. diff --git a/docs/installation/otp_en.md b/docs/installation/otp_en.md index e4f822d1c..b7e3bb2ac 100644 --- a/docs/installation/otp_en.md +++ b/docs/installation/otp_en.md @@ -28,15 +28,17 @@ Other than things bundled in the OTP release Pleroma depends on: * nginx (could be swapped with another reverse proxy but this guide covers only it) * certbot (for Let's Encrypt certificates, could be swapped with another ACME client, but this guide covers only it) -```sh tab="Alpine" -echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories -apk update -apk add curl unzip ncurses postgresql postgresql-contrib nginx certbot -``` - -```sh tab="Debian/Ubuntu" -apt install curl unzip libncurses5 postgresql postgresql-contrib nginx certbot -``` +=== "Alpine" + ``` + echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories + apk update + apk add curl unzip ncurses postgresql postgresql-contrib nginx certbot + ``` + +=== "Debian/Ubuntu" + ``` + apt install curl unzip libncurses5 postgresql postgresql-contrib nginx certbot + ``` ## Setup ### Configuring PostgreSQL @@ -47,31 +49,35 @@ apt install curl unzip libncurses5 postgresql postgresql-contrib nginx certbot RUM indexes are an alternative indexing scheme that is not included in PostgreSQL by default. You can read more about them on the [Configuration page](../configuration/cheatsheet.md#rum-indexing-for-full-text-search). They are completely optional and most of the time are not worth it, especially if you are running a single user instance (unless you absolutely need ordered search results). -```sh tab="Alpine" -apk add git build-base postgresql-dev -git clone https://github.com/postgrespro/rum /tmp/rum -cd /tmp/rum -make USE_PGXS=1 -make USE_PGXS=1 install -cd -rm -r /tmp/rum -``` - -```sh tab="Debian/Ubuntu" -# Available only on Buster/19.04 -apt install postgresql-11-rum -``` +=== "Alpine" + ``` + apk add git build-base postgresql-dev + git clone https://github.com/postgrespro/rum /tmp/rum + cd /tmp/rum + make USE_PGXS=1 + make USE_PGXS=1 install + cd + rm -r /tmp/rum + ``` + +=== "Debian/Ubuntu" + ``` + # Available only on Buster/19.04 + apt install postgresql-11-rum + ``` #### (Optional) Performance configuration It is encouraged to check [Optimizing your PostgreSQL performance](../configuration/postgresql.md) document, for tips on PostgreSQL tuning. -```sh tab="Alpine" -rc-service postgresql restart -``` +=== "Alpine" + ``` + rc-service postgresql restart + ``` -```sh tab="Debian/Ubuntu" -systemctl restart postgresql -``` +=== "Debian/Ubuntu" + ``` + systemctl restart postgresql + ``` If you are using PostgreSQL 12 or higher, add this to your Ecto database configuration @@ -151,14 +157,16 @@ certbot certonly --standalone --preferred-challenges http -d yourinstance.tld The location of nginx configs is dependent on the distro -```sh tab="Alpine" -cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/conf.d/pleroma.conf -``` +=== "Alpine" + ``` + cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/conf.d/pleroma.conf + ``` -```sh tab="Debian/Ubuntu" -cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/pleroma.conf -ln -s /etc/nginx/sites-available/pleroma.conf /etc/nginx/sites-enabled/pleroma.conf -``` +=== "Debian/Ubuntu" + ``` + cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/pleroma.conf + ln -s /etc/nginx/sites-available/pleroma.conf /etc/nginx/sites-enabled/pleroma.conf + ``` If your distro does not have either of those you can append `include /etc/nginx/pleroma.conf` to the end of the http section in /etc/nginx/nginx.conf and ```sh @@ -175,35 +183,39 @@ nginx -t ``` #### Start nginx -```sh tab="Alpine" -rc-service nginx start -``` +=== "Alpine" + ``` + rc-service nginx start + ``` -```sh tab="Debian/Ubuntu" -systemctl start nginx -``` +=== "Debian/Ubuntu" + ``` + systemctl start nginx + ``` At this point if you open your (sub)domain in a browser you should see a 502 error, that's because Pleroma is not started yet. ### Setting up a system service -```sh tab="Alpine" -# Copy the service into a proper directory -cp /opt/pleroma/installation/init.d/pleroma /etc/init.d/pleroma +=== "Alpine" + ``` + # Copy the service into a proper directory + cp /opt/pleroma/installation/init.d/pleroma /etc/init.d/pleroma -# Start pleroma and enable it on boot -rc-service pleroma start -rc-update add pleroma -``` + # Start pleroma and enable it on boot + rc-service pleroma start + rc-update add pleroma + ``` -```sh tab="Debian/Ubuntu" -# Copy the service into a proper directory -cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service +=== "Debian/Ubuntu" + ``` + # Copy the service into a proper directory + cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service -# Start pleroma and enable it on boot -systemctl start pleroma -systemctl enable pleroma -``` + # Start pleroma and enable it on boot + systemctl start pleroma + systemctl enable pleroma + ``` If everything worked, you should see Pleroma-FE when visiting your domain. If that didn't happen, try reviewing the installation steps, starting Pleroma in the foreground and seeing if there are any errrors. @@ -223,43 +235,45 @@ $EDITOR path-to-nginx-config nginx -t ``` -```sh tab="Alpine" -# Restart nginx -rc-service nginx restart - -# Start the cron daemon and make it start on boot -rc-service crond start -rc-update add crond - -# Ensure the webroot menthod and post hook is working -certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --dry-run --post-hook 'rc-service nginx reload' - -# Add it to the daily cron -echo '#!/bin/sh -certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --post-hook "rc-service nginx reload" -' > /etc/periodic/daily/renew-pleroma-cert -chmod +x /etc/periodic/daily/renew-pleroma-cert - -# If everything worked the output should contain /etc/cron.daily/renew-pleroma-cert -run-parts --test /etc/periodic/daily -``` - -```sh tab="Debian/Ubuntu" -# Restart nginx -systemctl restart nginx - -# Ensure the webroot menthod and post hook is working -certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --dry-run --post-hook 'systemctl reload nginx' - -# Add it to the daily cron -echo '#!/bin/sh -certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --post-hook "systemctl reload nginx" -' > /etc/cron.daily/renew-pleroma-cert -chmod +x /etc/cron.daily/renew-pleroma-cert - -# If everything worked the output should contain /etc/cron.daily/renew-pleroma-cert -run-parts --test /etc/cron.daily -``` +=== "Alpine" + ``` + # Restart nginx + rc-service nginx restart + + # Start the cron daemon and make it start on boot + rc-service crond start + rc-update add crond + + # Ensure the webroot menthod and post hook is working + certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --dry-run --post-hook 'rc-service nginx reload' + + # Add it to the daily cron + echo '#!/bin/sh + certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --post-hook "rc-service nginx reload" + ' > /etc/periodic/daily/renew-pleroma-cert + chmod +x /etc/periodic/daily/renew-pleroma-cert + + # If everything worked the output should contain /etc/cron.daily/renew-pleroma-cert + run-parts --test /etc/periodic/daily + ``` + +=== "Debian/Ubuntu" + ``` + # Restart nginx + systemctl restart nginx + + # Ensure the webroot menthod and post hook is working + certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --dry-run --post-hook 'systemctl reload nginx' + + # Add it to the daily cron + echo '#!/bin/sh + certbot renew --cert-name yourinstance.tld --webroot -w /var/lib/letsencrypt/ --post-hook "systemctl reload nginx" + ' > /etc/cron.daily/renew-pleroma-cert + chmod +x /etc/cron.daily/renew-pleroma-cert + + # If everything worked the output should contain /etc/cron.daily/renew-pleroma-cert + run-parts --test /etc/cron.daily + ``` ## Create your first user and set as admin ```sh -- cgit v1.2.3 From 60ac83a4c196233ed13c3da9ca296b0a4224e9a3 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sat, 15 Aug 2020 18:30:20 +0300 Subject: [#2046] Added test for pleroma/restrict_unauthenticated defaults on private instance. Updated docs and changelog. --- CHANGELOG.md | 1 + docs/configuration/cheatsheet.md | 6 ++++-- .../controllers/timeline_controller_test.exs | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8e80eb3c..d0fa138df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Configuration: `:media_proxy, whitelist` format changed to host with scheme (e.g. `http://example.com` instead of `example.com`). Domain format is deprecated. - **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated. - **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated. +- **Breaking** Changed defaults for `:restrict_unauthenticated` so that when `:instance, :public` is set to `false` then all `:restrict_unauthenticated` items be effectively set to `true`. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`.
API Changes diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index e5742bc3a..e68b6c6dc 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -38,8 +38,8 @@ To add configuration to your config file, you can copy it from the base config. * `federation_incoming_replies_max_depth`: Max. depth of reply-to activities fetching on incoming federation, to prevent out-of-memory situations while fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes. * `federation_reachability_timeout_days`: Timeout (in days) of each external federation target being unreachable prior to pausing federating to it. * `allow_relay`: Enable Pleroma’s Relay, which makes it possible to follow a whole instance. -* `public`: Makes the client API in authenticated mode-only except for user-profiles. Useful for disabling the Local Timeline and The Whole Known Network. See also: `restrict_unauthenticated`. -* `quarantined_instances`: List of ActivityPub instances where private(DMs, followers-only) activities will not be send. +* `public`: Makes the client API in authenticated mode-only except for user-profiles. Useful for disabling the Local Timeline and The Whole Known Network. Note that there is a dependent setting restricting or allowing unauthenticated access to specific resources, see `restrict_unauthenticated` for more details. +* `quarantined_instances`: List of ActivityPub instances where private (DMs, followers-only) activities will not be send. * `managed_config`: Whenether the config for pleroma-fe is configured in [:frontend_configurations](#frontend_configurations) or in ``static/config.json``. * `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML). * `extended_nickname_format`: Set to `true` to use extended local nicknames format (allows underscores/dashes). This will break federation with @@ -1051,6 +1051,8 @@ Restrict access for unauthenticated users to timelines (public and federated), u * `local` * `remote` +Note: when `:instance, :public` is set to `false`, all `:restrict_unauthenticated` items be effectively set to `true` by default. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`. + Note: setting `restrict_unauthenticated/timelines/local` to `true` has no practical sense if `restrict_unauthenticated/timelines/federated` is set to `false` (since local public activities will still be delivered to unauthenticated users as part of federated timeline). ## Pleroma.Web.ApiSpec.CastAndValidate diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs index 50e0d783d..71bac99f7 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -445,6 +445,23 @@ defp ensure_authenticated_access(base_uri) do assert length(json_response(res_conn, 200)) == 2 end + test "with default settings on private instances, returns 403 for unauthenticated users", %{ + conn: conn, + base_uri: base_uri, + error_response: error_response + } do + clear_config([:instance, :public], false) + clear_config([:restrict_unauthenticated, :timelines]) + + for local <- [true, false] do + res_conn = get(conn, "#{base_uri}?local=#{local}") + + assert json_response(res_conn, :unauthorized) == error_response + end + + ensure_authenticated_access(base_uri) + end + test "with `%{local: true, federated: true}`, returns 403 for unauthenticated users", %{ conn: conn, base_uri: base_uri, -- cgit v1.2.3 From f6da12f45d98707ad5e106e56cf36c055c3e105d Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Sun, 16 Aug 2020 06:54:48 +0300 Subject: fix search media proxy urls --- .../controllers/media_proxy_cache_controller.ex | 16 +++++++++------- .../controllers/media_proxy_cache_controller_test.exs | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex b/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex index 76d3af4ef..131e22d78 100644 --- a/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex @@ -38,18 +38,20 @@ def index(%{assigns: %{user: _}} = conn, params) do defp fetch_entries(params) do MediaProxy.cache_table() - |> Cachex.export!() - |> filter_urls(params[:query]) + |> Cachex.stream!(Cachex.Query.create(true, :key)) + |> filter_entries(params[:query]) end - defp filter_urls(entries, query) when is_binary(query) do - for {_, url, _, _, _} <- entries, String.contains?(url, query), do: url - end + defp filter_entries(stream, query) when is_binary(query) do + regex = ~r/#{query}/i - defp filter_urls(entries, _) do - Enum.map(entries, fn {_, url, _, _, _} -> url end) + stream + |> Enum.filter(fn url -> String.match?(url, regex) end) + |> Enum.to_list() end + defp filter_entries(stream, _), do: Enum.to_list(stream) + defp paginate_entries(entries, page, page_size) do offset = page_size * (page - 1) Enum.slice(entries, offset, page_size) diff --git a/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs b/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs index 3cf98d7c7..f243d1fb2 100644 --- a/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs +++ b/test/web/admin_api/controllers/media_proxy_cache_controller_test.exs @@ -89,7 +89,7 @@ test "search banned MediaProxy URLs", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&query=f44") + |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&query=F44") |> json_response_and_validate_schema(200) assert response["urls"] == [ -- cgit v1.2.3 From 317b6c6c526d14dda928abeb411a76dac53849db Mon Sep 17 00:00:00 2001 From: Hugo Müller-Downing Date: Sun, 16 Aug 2020 14:02:33 +1000 Subject: Start :ssl if not started when running migration or rollback --- CHANGELOG.md | 1 + lib/mix/tasks/pleroma/ecto/migrate.ex | 4 ++++ lib/mix/tasks/pleroma/ecto/rollback.ex | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8e80eb3c..eecdd78e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fix edge case where MediaProxy truncates media, usually caused when Caddy is serving content for the other Federated instance. - Emoji Packs could not be listed when instance was set to `public: false` - Fix whole_word always returning false on filter get requests +- Fix SSL not being started for database migrations in OTP release ## [Unreleased (patch)] diff --git a/lib/mix/tasks/pleroma/ecto/migrate.ex b/lib/mix/tasks/pleroma/ecto/migrate.ex index bc8ed29fb..e903bd171 100644 --- a/lib/mix/tasks/pleroma/ecto/migrate.ex +++ b/lib/mix/tasks/pleroma/ecto/migrate.ex @@ -41,6 +41,10 @@ def run(args \\ []) do load_pleroma() {opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases) + if Application.get_env(:pleroma, Pleroma.Repo)[:ssl] do + Application.ensure_all_started(:ssl) + end + opts = if opts[:to] || opts[:step] || opts[:all], do: opts, diff --git a/lib/mix/tasks/pleroma/ecto/rollback.ex b/lib/mix/tasks/pleroma/ecto/rollback.ex index f43bd0b98..3dba952cb 100644 --- a/lib/mix/tasks/pleroma/ecto/rollback.ex +++ b/lib/mix/tasks/pleroma/ecto/rollback.ex @@ -40,6 +40,10 @@ def run(args \\ []) do load_pleroma() {opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases) + if Application.get_env(:pleroma, Pleroma.Repo)[:ssl] do + Application.ensure_all_started(:ssl) + end + opts = if opts[:to] || opts[:step] || opts[:all], do: opts, -- cgit v1.2.3 From b2d3b26511476bc2786520130a37847f1d560333 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 17 Aug 2020 07:58:24 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eecdd78e0..83697beaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,7 +105,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fix edge case where MediaProxy truncates media, usually caused when Caddy is serving content for the other Federated instance. - Emoji Packs could not be listed when instance was set to `public: false` - Fix whole_word always returning false on filter get requests -- Fix SSL not being started for database migrations in OTP release +- Migrations not working on OTP releases if the database was connected over ssl ## [Unreleased (patch)] -- cgit v1.2.3 From 5ea752dab2c5b0aab7efff67e2d007273d534da6 Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 17 Aug 2020 14:11:36 +0200 Subject: Migrations: Add an index on the `invisible` field on users. --- .../migrations/20200817120935_add_invisible_index_to_users.exs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 priv/repo/migrations/20200817120935_add_invisible_index_to_users.exs diff --git a/priv/repo/migrations/20200817120935_add_invisible_index_to_users.exs b/priv/repo/migrations/20200817120935_add_invisible_index_to_users.exs new file mode 100644 index 000000000..2417d366e --- /dev/null +++ b/priv/repo/migrations/20200817120935_add_invisible_index_to_users.exs @@ -0,0 +1,7 @@ +defmodule Pleroma.Repo.Migrations.AddInvisibleIndexToUsers do + use Ecto.Migration + + def change do + create(index(:users, [:invisible])) + end +end -- cgit v1.2.3 From 7a273087ed7b49dedd821ca69a6e09d5f893c913 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 17 Aug 2020 23:46:42 +0200 Subject: object_validators: Use ecto_types where available --- .../web/activity_pub/object_validators/answer_validator.ex | 13 +++++-------- .../activity_pub/object_validators/create_note_validator.ex | 9 ++++----- .../activity_pub/object_validators/emoji_react_validator.ex | 4 ++-- .../web/activity_pub/object_validators/note_validator.ex | 10 +++++----- .../activity_pub/object_validators/question_validator.ex | 12 ++++++------ .../web/activity_pub/object_validators/undo_validator.ex | 4 ++-- 6 files changed, 24 insertions(+), 28 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex index 323367642..b9fbaf4f6 100644 --- a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex @@ -15,16 +15,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do embedded_schema do field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, {:array, :string}, default: []) - field(:cc, {:array, :string}, default: []) - - # is this actually needed? - field(:bto, {:array, :string}, default: []) - field(:bcc, {:array, :string}, default: []) - + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) field(:type, :string) field(:name, :string) - field(:inReplyTo, :string) + field(:inReplyTo, ObjectValidators.ObjectID) field(:attributedTo, ObjectValidators.ObjectID) # TODO: Remove actor on objects diff --git a/lib/pleroma/web/activity_pub/object_validators/create_note_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_note_validator.ex index 316bd0c07..9b9743c4a 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_note_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_note_validator.ex @@ -16,11 +16,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateNoteValidator do field(:id, ObjectValidators.ObjectID, primary_key: true) field(:actor, ObjectValidators.ObjectID) field(:type, :string) - field(:to, {:array, :string}) - field(:cc, {:array, :string}) - field(:bto, {:array, :string}, default: []) - field(:bcc, {:array, :string}, default: []) - + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) embeds_one(:object, NoteValidator) end diff --git a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex index a543af1f8..336c92d35 100644 --- a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex @@ -20,8 +20,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do field(:actor, ObjectValidators.ObjectID) field(:context, :string) field(:content, :string) - field(:to, {:array, :string}, default: []) - field(:cc, {:array, :string}, default: []) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) end def cast_and_validate(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex index a65fe2354..14ae29cb6 100644 --- a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex @@ -13,10 +13,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do embedded_schema do field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, {:array, :string}, default: []) - field(:cc, {:array, :string}, default: []) - field(:bto, {:array, :string}, default: []) - field(:bcc, {:array, :string}, default: []) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) # TODO: Write type field(:tag, {:array, :map}, default: []) field(:type, :string) @@ -34,7 +34,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do field(:replies_count, :integer, default: 0) field(:like_count, :integer, default: 0) field(:announcement_count, :integer, default: 0) - field(:inReplyTo, :string) + field(:inReplyTo, ObjectValidators.ObjectID) field(:uri, ObjectValidators.Uri) field(:likes, {:array, :string}, default: []) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index f47acf606..220065fd4 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -19,10 +19,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do # Extends from NoteValidator embedded_schema do field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, {:array, :string}, default: []) - field(:cc, {:array, :string}, default: []) - field(:bto, {:array, :string}, default: []) - field(:bcc, {:array, :string}, default: []) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) # TODO: Write type field(:tag, {:array, :map}, default: []) field(:type, :string) @@ -42,7 +42,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do field(:replies_count, :integer, default: 0) field(:like_count, :integer, default: 0) field(:announcement_count, :integer, default: 0) - field(:inReplyTo, :string) + field(:inReplyTo, ObjectValidators.ObjectID) field(:uri, ObjectValidators.Uri) # short identifier for PleromaFE to group statuses by context field(:context_id, :integer) @@ -117,7 +117,7 @@ def changeset(struct, data) do def 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() diff --git a/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex b/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex index e8d2d39c1..8cae94467 100644 --- a/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex @@ -18,8 +18,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator do field(:type, :string) field(:object, ObjectValidators.ObjectID) field(:actor, ObjectValidators.ObjectID) - field(:to, {:array, :string}, default: []) - field(:cc, {:array, :string}, default: []) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) end def cast_and_validate(data) do -- cgit v1.2.3 From b1fc4fe0ca6abab97be69e0b1bf138e8b5c1c303 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 18 Aug 2020 02:01:40 +0200 Subject: fetcher: fallback to [] when to/cc is nil Related: https://git.pleroma.social/pleroma/pleroma/-/issues/2063 --- lib/pleroma/object/fetcher.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex index 3ff25118d..6fdbc8efd 100644 --- a/lib/pleroma/object/fetcher.ex +++ b/lib/pleroma/object/fetcher.ex @@ -125,8 +125,8 @@ def fetch_object_from_id(id, options \\ []) do defp prepare_activity_params(data) do %{ "type" => "Create", - "to" => data["to"], - "cc" => data["cc"], + "to" => data["to"] || [], + "cc" => data["cc"] || [], # Should we seriously keep this attributedTo thing? "actor" => data["actor"] || data["attributedTo"], "object" => data -- cgit v1.2.3 From 2bc08d5573782ba491c36450b817aa352264fb27 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 18 Aug 2020 01:48:42 +0200 Subject: Pipeline Ingestion: Audio --- lib/pleroma/web/activity_pub/object_validator.ex | 17 +++- .../object_validators/audio_validator.ex | 109 +++++++++++++++++++++ lib/pleroma/web/activity_pub/side_effects.ex | 3 +- lib/pleroma/web/activity_pub/transmogrifier.ex | 4 +- 4 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/object_validators/audio_validator.ex diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index 3f1dffe2b..d770ce1be 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -16,6 +16,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator @@ -137,6 +138,16 @@ def validate(%{"type" => "Question"} = object, meta) do end end + def validate(%{"type" => "Audio"} = object, meta) do + with {:ok, object} <- + object + |> AudioValidator.cast_and_validate() + |> Ecto.Changeset.apply_action(:insert) do + object = stringify_keys(object) + {:ok, object, meta} + end + end + def validate(%{"type" => "Answer"} = object, meta) do with {:ok, object} <- object @@ -176,7 +187,7 @@ def validate( %{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity, meta ) - when objtype in ["Question", "Answer"] do + when objtype in ~w[Question Answer Audio] do with {:ok, object_data} <- cast_and_apply(object), meta = Keyword.put(meta, :object_data, object_data |> stringify_keys), {:ok, create_activity} <- @@ -210,6 +221,10 @@ def cast_and_apply(%{"type" => "Answer"} = object) do AnswerValidator.cast_and_apply(object) end + def cast_and_apply(%{"type" => "Audio"} = object) do + AudioValidator.cast_and_apply(object) + end + def cast_and_apply(o), do: {:error, {:validator_not_set, o}} # is_struct/1 isn't present in Elixir 1.8.x diff --git a/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex new file mode 100644 index 000000000..5ff9e3832 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex @@ -0,0 +1,109 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do + use Ecto.Schema + + alias Pleroma.EctoType.ActivityPub.ObjectValidators + alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + alias Pleroma.Web.ActivityPub.Utils + + import Ecto.Changeset + + @primary_key false + @derive Jason.Encoder + + # Extends from NoteValidator + embedded_schema do + field(:id, ObjectValidators.ObjectID, primary_key: true) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) + # TODO: Write type + field(:tag, {:array, :map}, default: []) + field(:type, :string) + field(:content, :string) + field(:context, :string) + + # TODO: Remove actor on objects + field(:actor, ObjectValidators.ObjectID) + + field(:attributedTo, ObjectValidators.ObjectID) + field(:summary, :string) + field(:published, ObjectValidators.DateTime) + # TODO: Write type + field(:emoji, :map, default: %{}) + field(:sensitive, :boolean, default: false) + embeds_many(:attachment, AttachmentValidator) + field(:replies_count, :integer, default: 0) + field(:like_count, :integer, default: 0) + field(:announcement_count, :integer, default: 0) + field(:inReplyTo, :string) + field(:uri, ObjectValidators.Uri) + # short identifier for PleromaFE to group statuses by context + field(:context_id, :integer) + + field(:likes, {:array, :string}, default: []) + field(:announcements, {:array, :string}, default: []) + end + + def cast_and_apply(data) do + data + |> cast_data + |> apply_action(:insert) + end + + def cast_and_validate(data) do + data + |> cast_data() + |> validate_data() + end + + def cast_data(data) do + %__MODULE__{} + |> changeset(data) + end + + # based on Pleroma.Web.ActivityPub.Utils.lazy_put_objects_defaults + defp fix_defaults(data) do + %{data: %{"id" => context}, id: context_id} = + Utils.create_context(data["context"] || data["conversation"]) + + data + |> Map.put_new_lazy("published", &Utils.make_date/0) + |> Map.put_new("context", context) + |> Map.put_new("context_id", context_id) + end + + defp fix_attribution(data) do + data + |> Map.put_new("actor", data["attributedTo"]) + end + + defp fix(data) do + data + |> fix_defaults() + |> fix_attribution() + end + + def changeset(struct, data) do + data = fix(data) + + struct + |> cast(data, __schema__(:fields) -- [:attachment]) + |> cast_embed(:attachment) + end + + def validate_data(data_cng) do + data_cng + |> validate_inclusion(:type, ["Audio"]) + |> validate_required([:id, :actor, :attributedTo, :type, :context]) + |> CommonValidations.validate_any_presence([:cc, :to]) + |> CommonValidations.validate_fields_match([:actor, :attributedTo]) + |> CommonValidations.validate_actor_presence() + |> CommonValidations.validate_host_match() + end +end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index bcd6fd2fb..3dc66c60b 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -340,7 +340,8 @@ def handle_object_creation(%{"type" => "Answer"} = object_map, meta) do end end - def handle_object_creation(%{"type" => "Question"} = object, meta) do + def handle_object_creation(%{"type" => objtype} = object, meta) + when objtype in ~w[Audio Question] do with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do {:ok, object, meta} end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 544f3f3b6..6be17e0ed 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -461,7 +461,7 @@ def handle_incoming( %{"type" => "Create", "object" => %{"type" => objtype} = object} = data, options ) - when objtype in ["Article", "Event", "Note", "Video", "Page", "Audio"] do + when objtype in ~w{Article Event Note Video Page} do actor = Containment.get_actor(data) with nil <- Activity.get_create_by_object_ap_id(object["id"]), @@ -555,7 +555,7 @@ def handle_incoming( %{"type" => "Create", "object" => %{"type" => objtype}} = data, _options ) - when objtype in ["Question", "Answer", "ChatMessage"] do + when objtype in ~w{Question Answer ChatMessage Audio} do with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do {:ok, activity} -- cgit v1.2.3 From c9d6638461e62a5b9e357f55a6d6d4e468b6bc92 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 18 Aug 2020 02:11:38 +0200 Subject: common_fixes: Get fixes common from Audio and Question --- .../object_validators/audio_validator.ex | 23 +++------------------- .../activity_pub/object_validators/common_fixes.ex | 23 ++++++++++++++++++++++ .../object_validators/question_validator.ex | 22 +++------------------ 3 files changed, 29 insertions(+), 39 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/object_validators/common_fixes.ex diff --git a/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex index 5ff9e3832..5d9bf345f 100644 --- a/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex @@ -7,15 +7,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations - alias Pleroma.Web.ActivityPub.Utils import Ecto.Changeset @primary_key false @derive Jason.Encoder - # Extends from NoteValidator embedded_schema do field(:id, ObjectValidators.ObjectID, primary_key: true) field(:to, ObjectValidators.Recipients, default: []) @@ -67,26 +66,10 @@ def cast_data(data) do |> changeset(data) end - # based on Pleroma.Web.ActivityPub.Utils.lazy_put_objects_defaults - defp fix_defaults(data) do - %{data: %{"id" => context}, id: context_id} = - Utils.create_context(data["context"] || data["conversation"]) - - data - |> Map.put_new_lazy("published", &Utils.make_date/0) - |> Map.put_new("context", context) - |> Map.put_new("context_id", context_id) - end - - defp fix_attribution(data) do - data - |> Map.put_new("actor", data["attributedTo"]) - end - defp fix(data) do data - |> fix_defaults() - |> fix_attribution() + |> CommonFixes.fix_defaults() + |> CommonFixes.fix_attribution() end def changeset(struct, data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex new file mode 100644 index 000000000..f13c16eca --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex @@ -0,0 +1,23 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do + alias Pleroma.Web.ActivityPub.Utils + + # based on Pleroma.Web.ActivityPub.Utils.lazy_put_objects_defaults + def fix_defaults(data) do + %{data: %{"id" => context}, id: context_id} = + Utils.create_context(data["context"] || data["conversation"]) + + data + |> Map.put_new_lazy("published", &Utils.make_date/0) + |> Map.put_new("context", context) + |> Map.put_new("context_id", context_id) + end + + def fix_attribution(data) do + data + |> Map.put_new("actor", data["attributedTo"]) + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index f47acf606..0aa70ee30 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -7,9 +7,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator - alias Pleroma.Web.ActivityPub.Utils import Ecto.Changeset @@ -81,27 +81,11 @@ defp fix_closed(data) do end end - # based on Pleroma.Web.ActivityPub.Utils.lazy_put_objects_defaults - defp fix_defaults(data) do - %{data: %{"id" => context}, id: context_id} = - Utils.create_context(data["context"] || data["conversation"]) - - data - |> Map.put_new_lazy("published", &Utils.make_date/0) - |> Map.put_new("context", context) - |> Map.put_new("context_id", context_id) - end - - defp fix_attribution(data) do - data - |> Map.put_new("actor", data["attributedTo"]) - end - defp fix(data) do data - |> fix_attribution() + |> CommonFixes.fix_defaults() + |> CommonFixes.fix_attribution() |> fix_closed() - |> fix_defaults() end def changeset(struct, data) do -- cgit v1.2.3 From 2f8c3c842dd48c26009e1272a28220175d0b1f06 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 18 Aug 2020 02:12:13 +0200 Subject: common_fixes: Remove Utils.make_date call --- lib/pleroma/web/activity_pub/object_validators/common_fixes.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex index f13c16eca..721749de0 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex @@ -11,7 +11,6 @@ def fix_defaults(data) do Utils.create_context(data["context"] || data["conversation"]) data - |> Map.put_new_lazy("published", &Utils.make_date/0) |> Map.put_new("context", context) |> Map.put_new("context_id", context_id) end -- cgit v1.2.3 From d55faa2f8fc3d613a3fa44b521fed27f8231c558 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 17 Aug 2020 21:52:28 -0500 Subject: Purge a local user upon deletion, fixes #2062 --- lib/pleroma/user.ex | 14 +++++++++++- .../controllers/admin_api_controller_test.exs | 25 ++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index ac065e9dc..a8bdcdad7 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1583,6 +1583,18 @@ def update_notification_settings(%User{} = user, settings) do |> update_and_set_cache() end + @spec purge_user_changeset(User.t()) :: Changeset.t() + def purge_user_changeset(user) do + change(user, %{ + deactivated: true, + email: nil, + avatar: %{}, + banner: %{}, + background: %{}, + fields: [] + }) + end + def delete(users) when is_list(users) do for user <- users, do: delete(user) end @@ -1610,7 +1622,7 @@ defp delete_or_deactivate(%User{local: true} = user) do _ -> user - |> change(%{deactivated: true, email: nil}) + |> purge_user_changeset() |> update_and_set_cache() end end diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index 66d4b1ef3..f23d23e05 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -155,13 +155,28 @@ test "GET /api/pleroma/admin/users/:nickname requires " <> describe "DELETE /api/pleroma/admin/users" do test "single user", %{admin: admin, conn: conn} do - user = insert(:user) clear_config([:instance, :federating], true) + user = + insert(:user, + avatar: %{"url" => [%{"href" => "https://someurl"}]}, + banner: %{"url" => [%{"href" => "https://somebanner"}]} + ) + + # Create some activities to check they got deleted later + follower = insert(:user) + {:ok, _} = CommonAPI.post(user, %{status: "test"}) + {:ok, _, _, _} = CommonAPI.follow(user, follower) + {:ok, _, _, _} = CommonAPI.follow(follower, user) + user = Repo.get(User, user.id) + assert user.note_count == 1 + assert user.follower_count == 1 + assert user.following_count == 1 refute user.deactivated with_mock Pleroma.Web.Federator, - publish: fn _ -> nil end do + publish: fn _ -> nil end, + perform: fn _, _ -> nil end do conn = conn |> put_req_header("accept", "application/json") @@ -181,6 +196,12 @@ test "single user", %{admin: admin, conn: conn} do user = Repo.get(User, user.id) assert user.deactivated + assert user.avatar == %{} + assert user.banner == %{} + assert user.note_count == 0 + assert user.follower_count == 0 + assert user.following_count == 0 + assert called(Pleroma.Web.Federator.publish(:_)) end end -- cgit v1.2.3 From c12c576ee28016444b89c426d67c960f156e831e Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 17 Aug 2020 22:08:08 -0500 Subject: Also purge bio and display name --- lib/pleroma/user.ex | 4 +++- test/web/admin_api/controllers/admin_api_controller_test.exs | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index a8bdcdad7..1a7d25801 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1591,7 +1591,9 @@ def purge_user_changeset(user) do avatar: %{}, banner: %{}, background: %{}, - fields: [] + fields: [], + bio: nil, + name: nil }) end diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index f23d23e05..2eb698807 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -160,7 +160,9 @@ test "single user", %{admin: admin, conn: conn} do user = insert(:user, avatar: %{"url" => [%{"href" => "https://someurl"}]}, - banner: %{"url" => [%{"href" => "https://somebanner"}]} + banner: %{"url" => [%{"href" => "https://somebanner"}]}, + bio: "Hello world!", + name: "A guy" ) # Create some activities to check they got deleted later @@ -201,6 +203,8 @@ test "single user", %{admin: admin, conn: conn} do assert user.note_count == 0 assert user.follower_count == 0 assert user.following_count == 0 + assert user.bio == nil + assert user.name == nil assert called(Pleroma.Web.Federator.publish(:_)) end -- cgit v1.2.3 From 72cbe20a5887cf2457895b0559e7eb97cc1bc871 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 17 Aug 2020 23:44:44 -0500 Subject: Purge most user fields upon deletion, "right to be forgotten" #859 --- lib/pleroma/user.ex | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 1a7d25801..a9820affa 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1585,15 +1585,44 @@ def update_notification_settings(%User{} = user, settings) do @spec purge_user_changeset(User.t()) :: Changeset.t() def purge_user_changeset(user) do + # "Right to be forgotten" + # https://gdpr.eu/right-to-be-forgotten/ change(user, %{ - deactivated: true, + bio: nil, + raw_bio: nil, email: nil, + name: nil, + password_hash: nil, + keys: nil, + public_key: nil, avatar: %{}, + tags: [], + last_refreshed_at: nil, + last_digest_emailed_at: nil, banner: %{}, background: %{}, + note_count: 0, + follower_count: 0, + following_count: 0, + locked: false, + confirmation_pending: false, + password_reset_pending: false, + approval_pending: false, + registration_reason: nil, + confirmation_token: nil, + domain_blocks: [], + deactivated: true, + ap_enabled: false, + is_moderator: false, + is_admin: false, + mastofe_settings: nil, + mascot: nil, + emoji: %{}, + pleroma_settings_store: %{}, fields: [], - bio: nil, - name: nil + raw_fields: [], + discoverable: false, + also_known_as: [] }) end -- cgit v1.2.3 From dcc8926ff1bb7206295dcfe9ad9388cb3c05be2a Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 18 Aug 2020 00:10:09 -0500 Subject: Test purging a user with User.delete/1 --- test/user_test.exs | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/test/user_test.exs b/test/user_test.exs index b47405895..3cf248659 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1417,7 +1417,6 @@ test "deactivates user when activation is not required", %{user: user} do test "delete/1 when approval is pending deletes the user" do user = insert(:user, approval_pending: true) - {:ok, user: user} {:ok, job} = User.delete(user) {:ok, _} = ObanHelpers.perform(job) @@ -1426,6 +1425,85 @@ test "delete/1 when approval is pending deletes the user" do refute User.get_by_id(user.id) end + test "delete/1 purges a user when they wouldn't be fully deleted" do + user = + insert(:user, %{ + bio: "eyy lmao", + name: "qqqqqqq", + password_hash: "pdfk2$1b3n159001", + keys: "RSA begin buplic key", + public_key: "--PRIVATE KEYE--", + avatar: %{"a" => "b"}, + tags: ["qqqqq"], + banner: %{"a" => "b"}, + background: %{"a" => "b"}, + note_count: 9, + follower_count: 9, + following_count: 9001, + locked: true, + confirmation_pending: true, + password_reset_pending: true, + approval_pending: true, + registration_reason: "ahhhhh", + confirmation_token: "qqqq", + domain_blocks: ["lain.com"], + deactivated: true, + ap_enabled: true, + is_moderator: true, + is_admin: true, + mastofe_settings: %{"a" => "b"}, + mascot: %{"a" => "b"}, + emoji: %{"a" => "b"}, + pleroma_settings_store: %{"q" => "x"}, + fields: [%{"gg" => "qq"}], + raw_fields: [%{"gg" => "qq"}], + discoverable: true, + also_known_as: ["https://lol.olo/users/loll"] + }) + + {:ok, job} = User.delete(user) + {:ok, _} = ObanHelpers.perform(job) + user = User.get_by_id(user.id) + + assert %User{ + bio: nil, + raw_bio: nil, + email: nil, + name: nil, + password_hash: nil, + keys: nil, + public_key: nil, + avatar: %{}, + tags: [], + last_refreshed_at: nil, + last_digest_emailed_at: nil, + banner: %{}, + background: %{}, + note_count: 0, + follower_count: 0, + following_count: 0, + locked: false, + confirmation_pending: false, + password_reset_pending: false, + approval_pending: false, + registration_reason: nil, + confirmation_token: nil, + domain_blocks: [], + deactivated: true, + ap_enabled: false, + is_moderator: false, + is_admin: false, + mastofe_settings: nil, + mascot: nil, + emoji: %{}, + pleroma_settings_store: %{}, + fields: [], + raw_fields: [], + discoverable: false, + also_known_as: [] + } = user + end + test "get_public_key_for_ap_id fetches a user that's not in the db" do assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin") end -- cgit v1.2.3 From a0f5eb1a552cf161f0efb746d74c4c590de4f02f Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 18 Aug 2020 00:24:28 -0500 Subject: Test that `POST /api/pleroma/delete_account` purges the user --- test/web/twitter_api/util_controller_test.exs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs index 109c1e637..354d77b56 100644 --- a/test/web/twitter_api/util_controller_test.exs +++ b/test/web/twitter_api/util_controller_test.exs @@ -586,10 +586,16 @@ test "with proper permissions and wrong or missing password", %{conn: conn} do end end - test "with proper permissions and valid password", %{conn: conn} do + test "with proper permissions and valid password", %{conn: conn, user: user} do conn = post(conn, "/api/pleroma/delete_account", %{"password" => "test"}) - + ObanHelpers.perform_all() assert json_response(conn, 200) == %{"status" => "success"} + + user = User.get_by_id(user.id) + assert user.deactivated == true + assert user.name == nil + assert user.bio == nil + assert user.password_hash == nil end end end -- cgit v1.2.3 From aabc26a57327b15c1aa5ee9980b7542c9e2f4899 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 18 Aug 2020 13:21:30 +0200 Subject: Pleroma.Upload: Set default upload name / description based on config. --- config/config.exs | 3 ++- lib/pleroma/upload.ex | 11 ++++++++++- test/web/activity_pub/activity_pub_test.exs | 30 +++++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/config/config.exs b/config/config.exs index a7c9e54b1..1ed3157c3 100644 --- a/config/config.exs +++ b/config/config.exs @@ -72,7 +72,8 @@ pool: :upload ] ], - filename_display_max_length: 30 + filename_display_max_length: 30, + default_description: nil config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads" diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 0fa6b89dc..015c87593 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -56,6 +56,15 @@ defmodule Pleroma.Upload do } defstruct [:id, :name, :tempfile, :content_type, :path] + defp get_description(opts, upload) do + case {opts[:description], Pleroma.Config.get([Pleroma.Upload, :default_description])} do + {description, _} when is_binary(description) -> description + {_, :filename} -> upload.name + {_, str} when is_binary(str) -> str + _ -> "" + end + end + @spec store(source, options :: [option()]) :: {:ok, Map.t()} | {:error, any()} def store(upload, opts \\ []) do opts = get_opts(opts) @@ -63,7 +72,7 @@ def store(upload, opts \\ []) do with {:ok, upload} <- prepare_upload(upload, opts), upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"}, {:ok, upload} <- Pleroma.Upload.Filter.filter(opts.filters, upload), - description = Map.get(opts, :description) || upload.name, + description = get_description(opts, upload), {_, true} <- {:description_limit, String.length(description) <= Pleroma.Config.get([:instance, :description_limit])}, diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index d6eab7337..03f968aaf 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -990,13 +990,39 @@ test "returns reblogs for users for whom reblogs have not been muted" do end describe "uploading files" do - test "copies the file to the configured folder" do - file = %Plug.Upload{ + setup do + test_file = %Plug.Upload{ content_type: "image/jpg", path: Path.absname("test/fixtures/image.jpg"), filename: "an_image.jpg" } + %{test_file: test_file} + end + + test "sets a description if given", %{test_file: file} do + {:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file") + assert object.data["name"] == "a cool file" + end + + test "it sets the default description depending on the configuration", %{test_file: file} do + clear_config([Pleroma.Upload, :default_description]) + + Pleroma.Config.put([Pleroma.Upload, :default_description], nil) + {:ok, %Object{} = object} = ActivityPub.upload(file) + assert object.data["name"] == "" + + Pleroma.Config.put([Pleroma.Upload, :default_description], :filename) + {:ok, %Object{} = object} = ActivityPub.upload(file) + assert object.data["name"] == "an_image.jpg" + + Pleroma.Config.put([Pleroma.Upload, :default_description], "unnamed attachment") + {:ok, %Object{} = object} = ActivityPub.upload(file) + assert object.data["name"] == "unnamed attachment" + end + + test "copies the file to the configured folder", %{test_file: file} do + clear_config([Pleroma.Upload, :default_description], :filename) {:ok, %Object{} = object} = ActivityPub.upload(file) assert object.data["name"] == "an_image.jpg" end -- cgit v1.2.3 From 368fd04b47834a49391424e3ce2073bfc80d7b7a Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 18 Aug 2020 13:22:00 +0200 Subject: Cheatsheet: Add information about filename descriptions --- docs/configuration/cheatsheet.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index e68b6c6dc..4758fca66 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -552,6 +552,7 @@ the source code is here: [kocaptcha](https://github.com/koto-bank/kocaptcha). Th * `proxy_remote`: If you're using a remote uploader, Pleroma will proxy media requests instead of redirecting to it. * `proxy_opts`: Proxy options, see `Pleroma.ReverseProxy` documentation. * `filename_display_max_length`: Set max length of a filename to display. 0 = no limit. Default: 30. +* `default_description`: Sets which default description an image has if none is set explicitly. Options: nil (default) - Don't set a default, :filename - use the filename of the file, a string (e.g. "attachment") - Use this string !!! warning `strip_exif` has been replaced by `Pleroma.Upload.Filter.Mogrify`. -- cgit v1.2.3 From 757410a17758600514107edd4ed946e4f67fd9a6 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 18 Aug 2020 13:24:39 +0200 Subject: Changelog: Add info about upload description changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0ae2981c..cdc0cd8ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] ### Changed +- **Breaking:** The default descriptions on uploads are now empty. The old behavior (filename as default) can be configured, see the cheat sheet. - **Breaking:** Added the ObjectAgePolicy to the default set of MRFs. This will delist and strip the follower collection of any message received that is older than 7 days. This will stop users from seeing very old messages in the timelines. The messages can still be viewed on the user's page and in conversations. They also still trigger notifications. - **Breaking:** Elixir >=1.9 is now required (was >= 1.8) - **Breaking:** Configuration: `:auto_linker, :opts` moved to `:pleroma, Pleroma.Formatter`. Old config namespace is deprecated. -- cgit v1.2.3 From f0a8d723bb4c4ec31dd2ab5ce7a1606aa280efbb Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 18 Aug 2020 13:37:28 +0200 Subject: Transmogrifier Test: Extract audio tests. --- .../transmogrifier/audio_handling_test.exs | 45 ++++++++++++++++++++++ test/web/activity_pub/transmogrifier_test.exs | 29 -------------- 2 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 test/web/activity_pub/transmogrifier/audio_handling_test.exs diff --git a/test/web/activity_pub/transmogrifier/audio_handling_test.exs b/test/web/activity_pub/transmogrifier/audio_handling_test.exs new file mode 100644 index 000000000..c74a9c45d --- /dev/null +++ b/test/web/activity_pub/transmogrifier/audio_handling_test.exs @@ -0,0 +1,45 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do + use Oban.Testing, repo: Pleroma.Repo + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.Web.ActivityPub.Transmogrifier + + import Pleroma.Factory + + test "it works for incoming listens" do + _user = insert(:user, ap_id: "http://mastodon.example.org/users/admin") + + data = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => ["https://www.w3.org/ns/activitystreams#Public"], + "cc" => [], + "type" => "Listen", + "id" => "http://mastodon.example.org/users/admin/listens/1234/activity", + "actor" => "http://mastodon.example.org/users/admin", + "object" => %{ + "type" => "Audio", + "id" => "http://mastodon.example.org/users/admin/listens/1234", + "attributedTo" => "http://mastodon.example.org/users/admin", + "title" => "lain radio episode 1", + "artist" => "lain", + "album" => "lain radio", + "length" => 180_000 + } + } + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + + object = Object.normalize(activity) + + assert object.data["title"] == "lain radio episode 1" + assert object.data["artist"] == "lain" + assert object.data["album"] == "lain radio" + assert object.data["length"] == 180_000 + end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 0dd4e6e47..3fa41b0c7 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -225,35 +225,6 @@ test "it works for incoming notices with hashtags" do assert Enum.at(object.data["tag"], 2) == "moo" end - test "it works for incoming listens" do - data = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "type" => "Listen", - "id" => "http://mastodon.example.org/users/admin/listens/1234/activity", - "actor" => "http://mastodon.example.org/users/admin", - "object" => %{ - "type" => "Audio", - "id" => "http://mastodon.example.org/users/admin/listens/1234", - "attributedTo" => "http://mastodon.example.org/users/admin", - "title" => "lain radio episode 1", - "artist" => "lain", - "album" => "lain radio", - "length" => 180_000 - } - } - - {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - - object = Object.normalize(activity) - - assert object.data["title"] == "lain radio episode 1" - assert object.data["artist"] == "lain" - assert object.data["album"] == "lain radio" - assert object.data["length"] == 180_000 - end - test "it works for incoming notices with contentMap" do data = File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!() -- cgit v1.2.3 From 52a79506c786a1388eeab24892c7b36ee9682977 Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 18 Aug 2020 14:37:35 +0200 Subject: Test config: Default to filename for descriptions --- config/test.exs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/config/test.exs b/config/test.exs index 413c7f0b9..f0358e384 100644 --- a/config/test.exs +++ b/config/test.exs @@ -21,7 +21,10 @@ config :pleroma, :auth, oauth_consumer_strategies: [] -config :pleroma, Pleroma.Upload, filters: [], link_name: false +config :pleroma, Pleroma.Upload, + filters: [], + link_name: false, + default_description: :filename config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads" -- cgit v1.2.3 From dfcb1401c701edb6e963d40772f4d26662c40793 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 18 Aug 2020 10:24:34 -0500 Subject: Improve FreeBSD rc script Passes rclint now, $HOME is dynamic, and properly matches process name for signalling shutdown. --- installation/freebsd/rc.d/pleroma | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/installation/freebsd/rc.d/pleroma b/installation/freebsd/rc.d/pleroma index 1e41e57e6..f62aef18d 100755 --- a/installation/freebsd/rc.d/pleroma +++ b/installation/freebsd/rc.d/pleroma @@ -1,28 +1,27 @@ #!/bin/sh -# REQUIRE: DAEMON postgresql +# $FreeBSD$ # PROVIDE: pleroma +# REQUIRE: DAEMON postgresql +# KEYWORD: shutdown # sudo -u pleroma MIX_ENV=prod elixir --erl \"-detached\" -S mix phx.server . /etc/rc.subr -name="pleroma" +name=pleroma +rcvar=pleroma_enable + desc="Pleroma Social Media Platform" -rcvar=${name}_enable -command="/usr/local/bin/elixir" -command_args="--erl \"-detached\" -S /usr/local/bin/mix phx.server" -pidfile="/dev/null" -pleroma_user="pleroma" -pleroma_home="/home/pleroma" -pleroma_chdir="${pleroma_home}/pleroma" -pleroma_env="HOME=${pleroma_home} MIX_ENV=prod" +load_rc_config ${name} -check_pidfile() -{ - pid=$(pgrep beam.smp$) - echo -n "${pid}" -} +: ${pleroma_user:=pleroma} +: ${pleroma_home:=$(getent passwd ${pleroma_user} | awk -F: '{print $6}')} +: ${pleroma_chdir:="${pleroma_home}/pleroma"} +: ${pleroma_env:="HOME=${pleroma_home} MIX_ENV=prod"} + +command=/usr/local/bin/elixir +command_args="--erl \"-detached\" -S /usr/local/bin/mix phx.server" +procname="*beam.smp" -load_rc_config ${name} run_rc_command "$1" -- cgit v1.2.3 From 5316e231b0b007ce05bc1bffdf6ce0244749fb9e Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Wed, 19 Aug 2020 00:05:48 +0200 Subject: Pipeline Ingestion: Audio (Part 2) --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- .../object_validators/attachment_validator.ex | 42 ++++++++-------- .../object_validators/audio_validator.ex | 18 ++++++- .../object_validators/create_generic_validator.ex | 11 ++++ .../object_validators/note_validator.ex | 2 +- .../object_validators/question_validator.ex | 2 +- lib/pleroma/web/activity_pub/transmogrifier.ex | 5 +- .../tesla_mock/funkwhale_create_audio.json | 58 ++++++++++++++++++++++ .../transmogrifier/audio_handling_test.exs | 35 +++++++++++++ .../transmogrifier/question_handling_test.exs | 2 + 10 files changed, 148 insertions(+), 29 deletions(-) create mode 100644 test/fixtures/tesla_mock/funkwhale_create_audio.json diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index bde1fe708..db1867494 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -85,7 +85,7 @@ defp increase_replies_count_if_reply(%{ defp increase_replies_count_if_reply(_create_data), do: :noop - @object_types ["ChatMessage", "Question", "Answer"] + @object_types ~w[ChatMessage Question Answer Audio] @spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()} def persist(%{"type" => type} = object, meta) when type in @object_types do with {:ok, object} <- Object.create(object) do diff --git a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex index f53bb02be..c8b148280 100644 --- a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex @@ -41,34 +41,34 @@ def changeset(struct, data) do end def fix_media_type(data) do - data = - data - |> Map.put_new("mediaType", data["mimeType"]) + data = Map.put_new(data, "mediaType", data["mimeType"]) if MIME.valid?(data["mediaType"]) do data else - data - |> Map.put("mediaType", "application/octet-stream") + Map.put(data, "mediaType", "application/octet-stream") end end - def fix_url(data) do - case data["url"] do - url when is_binary(url) -> - data - |> Map.put( - "url", - [ - %{ - "href" => url, - "type" => "Link", - "mediaType" => data["mediaType"] - } - ] - ) - - _ -> + defp handle_href(href, mediaType) do + [ + %{ + "href" => href, + "type" => "Link", + "mediaType" => mediaType + } + ] + end + + defp fix_url(data) do + cond do + is_binary(data["url"]) -> + Map.put(data, "url", handle_href(data["url"], data["mediaType"])) + + is_binary(data["href"]) and data["url"] == nil -> + Map.put(data, "url", handle_href(data["href"], data["mediaType"])) + + true -> data end end diff --git a/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex index 5d9bf345f..d1869f188 100644 --- a/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/audio_validator.ex @@ -41,7 +41,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do field(:like_count, :integer, default: 0) field(:announcement_count, :integer, default: 0) field(:inReplyTo, :string) - field(:uri, ObjectValidators.Uri) + field(:url, ObjectValidators.Uri) # short identifier for PleromaFE to group statuses by context field(:context_id, :integer) @@ -66,10 +66,24 @@ def cast_data(data) do |> changeset(data) end + defp fix_url(%{"url" => url} = data) when is_list(url) do + attachment = + Enum.find(url, fn x -> is_map(x) and String.starts_with?(x["mimeType"], "audio/") end) + + link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end) + + data + |> Map.put("attachment", [attachment]) + |> Map.put("url", link_element["href"]) + end + + defp fix_url(data), do: data + defp fix(data) do data |> CommonFixes.fix_defaults() |> CommonFixes.fix_attribution() + |> fix_url() end def changeset(struct, data) do @@ -83,7 +97,7 @@ def changeset(struct, data) do def validate_data(data_cng) do data_cng |> validate_inclusion(:type, ["Audio"]) - |> validate_required([:id, :actor, :attributedTo, :type, :context]) + |> validate_required([:id, :actor, :attributedTo, :type, :context, :attachment]) |> CommonValidations.validate_any_presence([:cc, :to]) |> CommonValidations.validate_fields_match([:actor, :attributedTo]) |> CommonValidations.validate_actor_presence() diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex index 60868eae0..b3dbeea57 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -61,9 +61,20 @@ defp fix_context(data, meta) do end end + defp fix_addressing(data, meta) do + if object = meta[:object_data] do + data + |> Map.put_new("to", object["to"] || []) + |> Map.put_new("cc", object["cc"] || []) + else + data + end + end + defp fix(data, meta) do data |> fix_context(meta) + |> fix_addressing(meta) end def validate_data(cng, meta \\ []) do diff --git a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex index 14ae29cb6..3e1f13a88 100644 --- a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex @@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do field(:like_count, :integer, default: 0) field(:announcement_count, :integer, default: 0) field(:inReplyTo, ObjectValidators.ObjectID) - field(:uri, ObjectValidators.Uri) + field(:url, ObjectValidators.Uri) field(:likes, {:array, :string}, default: []) field(:announcements, {:array, :string}, default: []) diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index a7ca42b2f..712047424 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -43,7 +43,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do field(:like_count, :integer, default: 0) field(:announcement_count, :integer, default: 0) field(:inReplyTo, ObjectValidators.ObjectID) - field(:uri, ObjectValidators.Uri) + field(:url, ObjectValidators.Uri) # short identifier for PleromaFE to group statuses by context field(:context_id, :integer) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 6be17e0ed..7c860af9f 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -276,13 +276,12 @@ def fix_url(%{"url" => url} = object) when is_map(url) do Map.put(object, "url", url["href"]) end - def fix_url(%{"type" => object_type, "url" => url} = object) - when object_type in ["Video", "Audio"] and is_list(url) do + def fix_url(%{"type" => "Video", "url" => url} = object) when is_list(url) do attachment = Enum.find(url, fn x -> media_type = x["mediaType"] || x["mimeType"] || "" - is_map(x) and String.starts_with?(media_type, ["audio/", "video/"]) + is_map(x) and String.starts_with?(media_type, "video/") end) link_element = diff --git a/test/fixtures/tesla_mock/funkwhale_create_audio.json b/test/fixtures/tesla_mock/funkwhale_create_audio.json new file mode 100644 index 000000000..fe6059cbf --- /dev/null +++ b/test/fixtures/tesla_mock/funkwhale_create_audio.json @@ -0,0 +1,58 @@ +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + "https://funkwhale.audio/ns", + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "Hashtag": "as:Hashtag" + } + ], + "type": "Create", + "id": "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871/activity", + "actor": "https://channels.tests.funkwhale.audio/federation/actors/compositions", + "object": { + "id": "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871", + "type": "Audio", + "name": "Compositions - Test Audio for Pleroma", + "attributedTo": "https://channels.tests.funkwhale.audio/federation/actors/compositions", + "published": "2020-03-11T10:01:52.714918+00:00", + "to": "https://www.w3.org/ns/activitystreams#Public", + "url": [ + { + "type": "Link", + "mimeType": "audio/ogg", + "href": "https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false" + }, + { + "type": "Link", + "mimeType": "text/html", + "href": "https://channels.tests.funkwhale.audio/library/tracks/74" + } + ], + "content": "

This is a test Audio for Pleroma.

", + "mediaType": "text/html", + "tag": [ + { + "type": "Hashtag", + "name": "#funkwhale" + }, + { + "type": "Hashtag", + "name": "#test" + }, + { + "type": "Hashtag", + "name": "#tests" + } + ], + "summary": "#funkwhale #test #tests", + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers" + } + ] + } +} diff --git a/test/web/activity_pub/transmogrifier/audio_handling_test.exs b/test/web/activity_pub/transmogrifier/audio_handling_test.exs index c74a9c45d..9cb53c48b 100644 --- a/test/web/activity_pub/transmogrifier/audio_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/audio_handling_test.exs @@ -12,6 +12,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do import Pleroma.Factory + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + :ok + end + test "it works for incoming listens" do _user = insert(:user, ap_id: "http://mastodon.example.org/users/admin") @@ -42,4 +47,34 @@ test "it works for incoming listens" do assert object.data["album"] == "lain radio" assert object.data["length"] == 180_000 end + + test "Funkwhale Audio object" do + data = File.read!("test/fixtures/tesla_mock/funkwhale_create_audio.json") |> Poison.decode!() + + {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + + assert object = Object.normalize(activity, false) + + assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"] + + assert object.data["cc"] == [] + + assert object.data["url"] == "https://channels.tests.funkwhale.audio/library/tracks/74" + + assert object.data["attachment"] == [ + %{ + "mediaType" => "audio/ogg", + "type" => "Link", + "name" => nil, + "url" => [ + %{ + "href" => + "https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false", + "mediaType" => "audio/ogg", + "type" => "Link" + } + ] + } + ] + end end diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs index 9fb965d7f..c82361828 100644 --- a/test/web/activity_pub/transmogrifier/question_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/question_handling_test.exs @@ -24,6 +24,8 @@ test "Mastodon Question activity" do object = Object.normalize(activity, false) + assert object.data["url"] == "https://mastodon.sdf.org/@rinpatch/102070944809637304" + assert object.data["closed"] == "2019-05-11T09:03:36Z" assert object.data["context"] == activity.data["context"] -- cgit v1.2.3 From 7dc275b69bbd50e7a6944c76c5541c0a9c41a051 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Tue, 18 Aug 2020 18:21:34 +0300 Subject: relay fix for admin-fe --- docs/API/admin_api.md | 48 ++++++++++++++----- lib/mix/tasks/pleroma/relay.ex | 10 +++- lib/pleroma/following_relationship.ex | 8 ++++ lib/pleroma/user.ex | 17 +++---- lib/pleroma/web/activity_pub/activity_pub.ex | 7 ++- lib/pleroma/web/activity_pub/builder.ex | 2 +- lib/pleroma/web/activity_pub/relay.ex | 56 +++++++++++----------- .../web/admin_api/controllers/relay_controller.ex | 2 +- .../api_spec/operations/admin/relay_operation.ex | 50 +++++++++++-------- test/tasks/relay_test.exs | 10 ++-- .../activity_pub/activity_pub_controller_test.exs | 2 +- .../controllers/relay_controller_test.exs | 15 ++++-- 12 files changed, 138 insertions(+), 89 deletions(-) diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md index 05e63b528..c0ea074f0 100644 --- a/docs/API/admin_api.md +++ b/docs/API/admin_api.md @@ -313,31 +313,53 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - On failure: `Not found` - On success: JSON array of user's latest statuses +## `GET /api/pleroma/admin/relay` + +### List Relays + +Params: none +Response: + +* On success: JSON array of relays + +```json +[ + {"actor": "https://example.com/relay", "followed_back": true}, + {"actor": "https://example2.com/relay", "followed_back": false} +] +``` + ## `POST /api/pleroma/admin/relay` ### Follow a Relay -- Params: - - `relay_url` -- Response: - - On success: URL of the followed relay +Params: + +* `relay_url` + +Response: + +* On success: relay json object + +```json +{"actor": "https://example.com/relay", "followed_back": true} +``` ## `DELETE /api/pleroma/admin/relay` ### Unfollow a Relay -- Params: - - `relay_url` -- Response: - - On success: URL of the unfollowed relay +Params: -## `GET /api/pleroma/admin/relay` +* `relay_url` -### List Relays +Response: -- Params: none -- Response: - - On success: JSON array of relays +* On success: URL of the unfollowed relay + +```json +{"https://example.com/relay"} +``` ## `POST /api/pleroma/admin/users/invite_token` diff --git a/lib/mix/tasks/pleroma/relay.ex b/lib/mix/tasks/pleroma/relay.ex index c3312507e..a6d8d6c1c 100644 --- a/lib/mix/tasks/pleroma/relay.ex +++ b/lib/mix/tasks/pleroma/relay.ex @@ -35,10 +35,16 @@ def run(["unfollow", target]) do def run(["list"]) do start_pleroma() - with {:ok, list} <- Relay.list(true) do - list |> Enum.each(&shell_info(&1)) + with {:ok, list} <- Relay.list() do + Enum.each(list, &print_relay_url/1) else {:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}") end end + + defp print_relay_url(%{followed_back: false} = relay) do + shell_info("#{relay.actor} - no Accept received (relay didn't follow back)") + end + + defp print_relay_url(relay), do: shell_info(relay.actor) end diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex index 83b366dd4..2039a259d 100644 --- a/lib/pleroma/following_relationship.ex +++ b/lib/pleroma/following_relationship.ex @@ -264,4 +264,12 @@ defp validate_following_id_follower_id_inequality(%Changeset{} = changeset) do end end) end + + @spec following_ap_ids(User.t()) :: [String.t()] + def following_ap_ids(%User{} = user) do + user + |> following_query() + |> select([r, u], u.ap_id) + |> Repo.all() + end end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index a9820affa..d2ad9516f 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -247,6 +247,13 @@ def unquote(:"#{outgoing_relation_target}_ap_ids")(user, restrict_deactivated? \ end end + defdelegate following_count(user), to: FollowingRelationship + defdelegate following(user), to: FollowingRelationship + defdelegate following?(follower, followed), to: FollowingRelationship + defdelegate following_ap_ids(user), to: FollowingRelationship + defdelegate get_follow_requests(user), to: FollowingRelationship + defdelegate search(query, opts \\ []), to: User.Search + @doc """ Dumps Flake Id to SQL-compatible format (16-byte UUID). E.g. "9pQtDGXuq4p3VlcJEm" -> <<0, 0, 1, 110, 179, 218, 42, 92, 213, 41, 44, 227, 95, 213, 0, 0>> @@ -372,8 +379,6 @@ def restrict_deactivated(query) do from(u in query, where: u.deactivated != ^true) end - defdelegate following_count(user), to: FollowingRelationship - defp truncate_fields_param(params) do if Map.has_key?(params, :fields) do Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1)) @@ -868,8 +873,6 @@ def follow_all(follower, followeds) do set_cache(follower) end - defdelegate following(user), to: FollowingRelationship - def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do deny_follow_blocked = Config.get([:user, :deny_follow_blocked]) @@ -923,8 +926,6 @@ defp do_unfollow(%User{} = follower, %User{} = followed) do end end - defdelegate following?(follower, followed), to: FollowingRelationship - @doc "Returns follow state as Pleroma.FollowingRelationship.State value" def get_follow_state(%User{} = follower, %User{} = following) do following_relationship = FollowingRelationship.get(follower, following) @@ -1189,8 +1190,6 @@ def get_friends_ids(user, page \\ nil) do |> Repo.all() end - defdelegate get_follow_requests(user), to: FollowingRelationship - def increase_note_count(%User{} = user) do User |> where(id: ^user.id) @@ -2163,8 +2162,6 @@ def get_ap_ids_by_nicknames(nicknames) do |> Repo.all() end - defdelegate search(query, opts \\ []), to: User.Search - defp put_password_hash( %Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset ) do diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index bde1fe708..04478bc33 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1344,9 +1344,8 @@ def fetch_and_prepare_user_from_ap_id(ap_id) do end def maybe_handle_clashing_nickname(data) do - nickname = data[:nickname] - - with %User{} = old_user <- User.get_by_nickname(nickname), + with nickname when is_binary(nickname) <- data[:nickname], + %User{} = old_user <- User.get_by_nickname(nickname), {_, false} <- {:ap_id_comparison, data[:ap_id] == old_user.ap_id} do Logger.info( "Found an old user for #{nickname}, the old ap id is #{old_user.ap_id}, new one is #{ @@ -1360,7 +1359,7 @@ def maybe_handle_clashing_nickname(data) do else {:ap_id_comparison, true} -> Logger.info( - "Found an old user for #{nickname}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything." + "Found an old user for #{data[:nickname]}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything." ) _ -> diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index f2392ce79..9a7b7d9de 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -215,7 +215,7 @@ def announce(actor, object, options \\ []) do to = cond do - actor.ap_id == Relay.relay_ap_id() -> + actor.ap_id == Relay.ap_id() -> [actor.follower_address] public? -> diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex index b09764d2b..b65710a94 100644 --- a/lib/pleroma/web/activity_pub/relay.ex +++ b/lib/pleroma/web/activity_pub/relay.ex @@ -10,19 +10,13 @@ defmodule Pleroma.Web.ActivityPub.Relay do alias Pleroma.Web.CommonAPI require Logger - @relay_nickname "relay" + @nickname "relay" - def get_actor do - actor = - relay_ap_id() - |> User.get_or_create_service_actor_by_ap_id(@relay_nickname) + @spec ap_id() :: String.t() + def ap_id, do: "#{Pleroma.Web.Endpoint.url()}/#{@nickname}" - actor - end - - def relay_ap_id do - "#{Pleroma.Web.Endpoint.url()}/relay" - end + @spec get_actor() :: User.t() | nil + def get_actor, do: User.get_or_create_service_actor_by_ap_id(ap_id(), @nickname) @spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()} def follow(target_instance) do @@ -61,34 +55,38 @@ def publish(%Activity{data: %{"type" => "Create"}} = activity) do def publish(_), do: {:error, "Not implemented"} - @spec list(boolean()) :: {:ok, [String.t()]} | {:error, any()} - def list(with_not_accepted \\ false) do + @spec list() :: {:ok, [%{actor: String.t(), followed_back: boolean()}]} | {:error, any()} + def list do with %User{} = user <- get_actor() do accepted = user - |> User.following() - |> Enum.map(fn entry -> URI.parse(entry).host end) - |> Enum.uniq() - - list = - if with_not_accepted do - without_accept = - user - |> Pleroma.Activity.following_requests_for_actor() - |> Enum.map(fn a -> URI.parse(a.data["object"]).host <> " (no Accept received)" end) - |> Enum.uniq() + |> following() + |> Enum.map(fn actor -> %{actor: actor, followed_back: true} end) - accepted ++ without_accept - else - accepted - end + without_accept = + user + |> Pleroma.Activity.following_requests_for_actor() + |> Enum.map(fn activity -> %{actor: activity.data["object"], followed_back: false} end) + |> Enum.uniq() - {:ok, list} + {:ok, accepted ++ without_accept} else error -> format_error(error) end end + @spec following() :: [String.t()] + def following do + get_actor() + |> following() + end + + defp following(user) do + user + |> User.following_ap_ids() + |> Enum.uniq() + end + defp format_error({:error, error}), do: format_error(error) defp format_error(error) do diff --git a/lib/pleroma/web/admin_api/controllers/relay_controller.ex b/lib/pleroma/web/admin_api/controllers/relay_controller.ex index cf9f3a14b..95d06dde7 100644 --- a/lib/pleroma/web/admin_api/controllers/relay_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/relay_controller.ex @@ -39,7 +39,7 @@ def follow(%{assigns: %{user: admin}, body_params: %{relay_url: target}} = conn, target: target }) - json(conn, target) + json(conn, %{actor: target, followed_back: target in Relay.following()}) else _ -> conn diff --git a/lib/pleroma/web/api_spec/operations/admin/relay_operation.ex b/lib/pleroma/web/api_spec/operations/admin/relay_operation.ex index 67ee5eee0..e06b2d164 100644 --- a/lib/pleroma/web/api_spec/operations/admin/relay_operation.ex +++ b/lib/pleroma/web/api_spec/operations/admin/relay_operation.ex @@ -27,8 +27,7 @@ def index_operation do properties: %{ relays: %Schema{ type: :array, - items: %Schema{type: :string}, - example: ["lain.com", "mstdn.io"] + items: relay() } } }) @@ -43,19 +42,9 @@ def follow_operation do operationId: "AdminAPI.RelayController.follow", security: [%{"oAuth" => ["write:follows"]}], parameters: admin_api_params(), - requestBody: - request_body("Parameters", %Schema{ - type: :object, - properties: %{ - relay_url: %Schema{type: :string, format: :uri} - } - }), + requestBody: request_body("Parameters", relay_url()), responses: %{ - 200 => - Operation.response("Status", "application/json", %Schema{ - type: :string, - example: "http://mastodon.example.org/users/admin" - }) + 200 => Operation.response("Status", "application/json", relay()) } } end @@ -67,13 +56,7 @@ def unfollow_operation do operationId: "AdminAPI.RelayController.unfollow", security: [%{"oAuth" => ["write:follows"]}], parameters: admin_api_params(), - requestBody: - request_body("Parameters", %Schema{ - type: :object, - properties: %{ - relay_url: %Schema{type: :string, format: :uri} - } - }), + requestBody: request_body("Parameters", relay_url()), responses: %{ 200 => Operation.response("Status", "application/json", %Schema{ @@ -83,4 +66,29 @@ def unfollow_operation do } } end + + defp relay do + %Schema{ + type: :object, + properties: %{ + actor: %Schema{ + type: :string, + example: "https://example.com/relay" + }, + followed_back: %Schema{ + type: :boolean, + description: "Is relay followed back by this actor?" + } + } + } + end + + defp relay_url do + %Schema{ + type: :object, + properties: %{ + relay_url: %Schema{type: :string, format: :uri} + } + } + end end diff --git a/test/tasks/relay_test.exs b/test/tasks/relay_test.exs index 79ab72002..e5225b64c 100644 --- a/test/tasks/relay_test.exs +++ b/test/tasks/relay_test.exs @@ -42,7 +42,11 @@ test "relay is followed" do assert activity.data["object"] == target_user.ap_id :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) - assert_receive {:mix_shell, :info, ["mastodon.example.org (no Accept received)"]} + + assert_receive {:mix_shell, :info, + [ + "http://mastodon.example.org/users/admin - no Accept received (relay didn't follow back)" + ]} end end @@ -95,8 +99,8 @@ test "Prints relay subscription list" do :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) - assert_receive {:mix_shell, :info, ["mstdn.io"]} - assert_receive {:mix_shell, :info, ["mastodon.example.org"]} + assert_receive {:mix_shell, :info, ["https://mstdn.io/users/mayuutann"]} + assert_receive {:mix_shell, :info, ["http://mastodon.example.org/users/admin"]} end end end diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index ed900d8f8..57988dc1e 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -533,7 +533,7 @@ test "accept follow activity", %{conn: conn} do end) :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) - assert_receive {:mix_shell, :info, ["relay.mastodon.host"]} + assert_receive {:mix_shell, :info, ["https://relay.mastodon.host/actor"]} end @tag capture_log: true diff --git a/test/web/admin_api/controllers/relay_controller_test.exs b/test/web/admin_api/controllers/relay_controller_test.exs index 64086adc5..adadf2b5c 100644 --- a/test/web/admin_api/controllers/relay_controller_test.exs +++ b/test/web/admin_api/controllers/relay_controller_test.exs @@ -39,8 +39,10 @@ test "POST /relay", %{conn: conn, admin: admin} do relay_url: "http://mastodon.example.org/users/admin" }) - assert json_response_and_validate_schema(conn, 200) == - "http://mastodon.example.org/users/admin" + assert json_response_and_validate_schema(conn, 200) == %{ + "actor" => "http://mastodon.example.org/users/admin", + "followed_back" => false + } log_entry = Repo.one(ModerationLog) @@ -59,8 +61,13 @@ test "GET /relay", %{conn: conn} do conn = get(conn, "/api/pleroma/admin/relay") - assert json_response_and_validate_schema(conn, 200)["relays"] -- - ["mastodon.example.org", "mstdn.io"] == [] + assert json_response_and_validate_schema(conn, 200)["relays"] == [ + %{ + "actor" => "http://mastodon.example.org/users/admin", + "followed_back" => true + }, + %{"actor" => "https://mstdn.io/users/mayuutann", "followed_back" => true} + ] end test "DELETE /relay", %{conn: conn, admin: admin} do -- cgit v1.2.3 From fa23d5d3d3dddc5dc8fea893c14d06193a8d997b Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 19 Aug 2020 08:40:26 +0300 Subject: changelog entry --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdc0cd8ae..e2210dbec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Configuration: `:media_proxy, whitelist` format changed to host with scheme (e.g. `http://example.com` instead of `example.com`). Domain format is deprecated. - **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated. - **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated. -- **Breaking** Changed defaults for `:restrict_unauthenticated` so that when `:instance, :public` is set to `false` then all `:restrict_unauthenticated` items be effectively set to `true`. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`. +- **Breaking** Changed defaults for `:restrict_unauthenticated` so that when `:instance, :public` is set to `false` then all `:restrict_unauthenticated` items be effectively set to `true`. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`.
API Changes @@ -108,6 +108,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Emoji Packs could not be listed when instance was set to `public: false` - Fix whole_word always returning false on filter get requests - Migrations not working on OTP releases if the database was connected over ssl +- Fix relay following ## [Unreleased (patch)] -- cgit v1.2.3 From 13f6029b4b7aad145c68fe804d34fbff9a371d36 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 19 Aug 2020 08:55:03 +0300 Subject: additional changelog entry --- CHANGELOG.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2210dbec..1ed8445b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,19 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] ### Changed + - **Breaking:** The default descriptions on uploads are now empty. The old behavior (filename as default) can be configured, see the cheat sheet. - **Breaking:** Added the ObjectAgePolicy to the default set of MRFs. This will delist and strip the follower collection of any message received that is older than 7 days. This will stop users from seeing very old messages in the timelines. The messages can still be viewed on the user's page and in conversations. They also still trigger notifications. - **Breaking:** Elixir >=1.9 is now required (was >= 1.8) - **Breaking:** Configuration: `:auto_linker, :opts` moved to `:pleroma, Pleroma.Formatter`. Old config namespace is deprecated. +- **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated. +- **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated. +- **Breaking** Changed defaults for `:restrict_unauthenticated` so that when `:instance, :public` is set to `false` then all `:restrict_unauthenticated` items be effectively set to `true`. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`. - In Conversations, return only direct messages as `last_status` - Using the `only_media` filter on timelines will now exclude reblog media - MFR policy to set global expiration for all local Create activities - OGP rich media parser merged with TwitterCard - Configuration: `:instance, rewrite_policy` moved to `:mrf, policies`, `:instance, :mrf_transparency` moved to `:mrf, :transparency`, `:instance, :mrf_transparency_exclusions` moved to `:mrf, :transparency_exclusions`. Old config namespace is deprecated. - Configuration: `:media_proxy, whitelist` format changed to host with scheme (e.g. `http://example.com` instead of `example.com`). Domain format is deprecated. -- **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated. -- **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated. -- **Breaking** Changed defaults for `:restrict_unauthenticated` so that when `:instance, :public` is set to `false` then all `:restrict_unauthenticated` items be effectively set to `true`. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`.
API Changes @@ -26,29 +27,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - **Breaking:** Pleroma API: The routes to update avatar, banner and background have been removed. - **Breaking:** Image description length is limited now. - **Breaking:** Emoji API: changed methods and renamed routes. +- **Breaking:** Notification Settings API for suppressing notifications has been simplified down to `block_from_strangers`. +- **Breaking:** Notification Settings API option for hiding push notification contents has been renamed to `hide_notification_contents`. - MastodonAPI: Allow removal of avatar, banner and background. - Streaming: Repeats of a user's posts will no longer be pushed to the user's stream. - Mastodon API: Added `pleroma.metadata.fields_limits` to /api/v1/instance - Mastodon API: On deletion, returns the original post text. - Mastodon API: Add `pleroma.unread_count` to the Marker entity. -- **Breaking:** Notification Settings API for suppressing notifications - has been simplified down to `block_from_strangers`. -- **Breaking:** Notification Settings API option for hiding push notification - contents has been renamed to `hide_notification_contents` - Mastodon API: Added `pleroma.metadata.post_formats` to /api/v1/instance - Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone` - Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value. +
Admin API Changes +- **Breaking** Changed relay `/api/pleroma/admin/relay` endpoints response format. - Status visibility stats: now can return stats per instance. - - Mix task to refresh counter cache (`mix pleroma.refresh_counter_cache`) +
### Removed + - **Breaking:** removed `with_move` parameter from notifications timeline. ### Added -- cgit v1.2.3 From 4727030f59a5d879a579c4bccd0f1612c5221670 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 19 Aug 2020 11:06:03 +0300 Subject: fixes for mix tasks - fix for `mix pleroma.database update_users_following_followers_counts` - raise error, if fetch was unsuccessful in emoji tasks - fix for `pleroma.digest test` task --- lib/mix/pleroma.ex | 2 +- lib/mix/tasks/pleroma/emoji.ex | 10 ++++++---- lib/pleroma/emails/user_email.ex | 31 ++++++++++++++++++++----------- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/lib/mix/pleroma.ex b/lib/mix/pleroma.ex index 074492a46..fe9b0d16c 100644 --- a/lib/mix/pleroma.ex +++ b/lib/mix/pleroma.ex @@ -14,7 +14,7 @@ defmodule Mix.Pleroma do :swoosh, :timex ] - @cachex_children ["object", "user"] + @cachex_children ["object", "user", "scrubber"] @doc "Common functions to be reused in mix tasks" def start_pleroma do Pleroma.Config.Holder.save_default() diff --git a/lib/mix/tasks/pleroma/emoji.ex b/lib/mix/tasks/pleroma/emoji.ex index f4eaeac98..8f52ee98d 100644 --- a/lib/mix/tasks/pleroma/emoji.ex +++ b/lib/mix/tasks/pleroma/emoji.ex @@ -15,7 +15,7 @@ def run(["ls-packs" | args]) do {options, [], []} = parse_global_opts(args) url_or_path = options[:manifest] || default_manifest() - manifest = fetch_and_decode(url_or_path) + manifest = fetch_and_decode!(url_or_path) Enum.each(manifest, fn {name, info} -> to_print = [ @@ -42,7 +42,7 @@ def run(["get-packs" | args]) do url_or_path = options[:manifest] || default_manifest() - manifest = fetch_and_decode(url_or_path) + manifest = fetch_and_decode!(url_or_path) for pack_name <- pack_names do if Map.has_key?(manifest, pack_name) do @@ -92,7 +92,7 @@ def run(["get-packs" | args]) do ]) ) - files = fetch_and_decode(files_loc) + files = fetch_and_decode!(files_loc) IO.puts(IO.ANSI.format(["Unpacking ", :bright, pack_name])) @@ -243,9 +243,11 @@ def run(["reload"]) do IO.puts("Emoji packs have been reloaded.") end - defp fetch_and_decode(from) do + defp fetch_and_decode!(from) do with {:ok, json} <- fetch(from) do Jason.decode!(json) + else + {:error, error} -> raise "#{from} cannot be fetched. Error: #{error} occur." end end diff --git a/lib/pleroma/emails/user_email.ex b/lib/pleroma/emails/user_email.ex index 313533859..1d8c72ae9 100644 --- a/lib/pleroma/emails/user_email.ex +++ b/lib/pleroma/emails/user_email.ex @@ -107,25 +107,34 @@ def digest_email(user) do |> Enum.filter(&(&1.activity.data["type"] == "Create")) |> Enum.map(fn notification -> object = Pleroma.Object.normalize(notification.activity) - object = update_in(object.data["content"], &format_links/1) - %{ - data: notification, - object: object, - from: User.get_by_ap_id(notification.activity.actor) - } + if not is_nil(object) do + object = update_in(object.data["content"], &format_links/1) + + %{ + data: notification, + object: object, + from: User.get_by_ap_id(notification.activity.actor) + } + end end) + |> Enum.filter(& &1) followers = notifications |> Enum.filter(&(&1.activity.data["type"] == "Follow")) |> Enum.map(fn notification -> - %{ - data: notification, - object: Pleroma.Object.normalize(notification.activity), - from: User.get_by_ap_id(notification.activity.actor) - } + from = User.get_by_ap_id(notification.activity.actor) + + if not is_nil(from) do + %{ + data: notification, + object: Pleroma.Object.normalize(notification.activity), + from: User.get_by_ap_id(notification.activity.actor) + } + end end) + |> Enum.filter(& &1) unless Enum.empty?(mentions) do styling = Config.get([__MODULE__, :styling]) -- cgit v1.2.3 From c68bcae362921a16dfb0995539a97ca521036dd7 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Wed, 19 Aug 2020 12:57:29 +0300 Subject: fix for sometimes failing tests --- test/emails/mailer_test.exs | 4 ++-- test/tasks/digest_test.exs | 2 ++ test/tasks/email_test.exs | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/emails/mailer_test.exs b/test/emails/mailer_test.exs index 3da45056b..9e232d2a0 100644 --- a/test/emails/mailer_test.exs +++ b/test/emails/mailer_test.exs @@ -14,10 +14,10 @@ defmodule Pleroma.Emails.MailerTest do subject: "Pleroma test email", to: [{"Test User", "user1@example.com"}] } - setup do: clear_config([Pleroma.Emails.Mailer, :enabled]) + setup do: clear_config([Pleroma.Emails.Mailer, :enabled], true) test "not send email when mailer is disabled" do - Pleroma.Config.put([Pleroma.Emails.Mailer, :enabled], false) + clear_config([Pleroma.Emails.Mailer, :enabled], false) Mailer.deliver(@email) :timer.sleep(100) diff --git a/test/tasks/digest_test.exs b/test/tasks/digest_test.exs index eefbc8936..0b444c86d 100644 --- a/test/tasks/digest_test.exs +++ b/test/tasks/digest_test.exs @@ -17,6 +17,8 @@ defmodule Mix.Tasks.Pleroma.DigestTest do :ok end + setup do: clear_config([Pleroma.Emails.Mailer, :enabled], true) + describe "pleroma.digest test" do test "Sends digest to the given user" do user1 = insert(:user) diff --git a/test/tasks/email_test.exs b/test/tasks/email_test.exs index 944c07064..c3af7ef68 100644 --- a/test/tasks/email_test.exs +++ b/test/tasks/email_test.exs @@ -16,6 +16,8 @@ defmodule Mix.Tasks.Pleroma.EmailTest do :ok end + setup do: clear_config([Pleroma.Emails.Mailer, :enabled], true) + describe "pleroma.email test" do test "Sends test email with no given address" do mail_to = Config.get([:instance, :email]) -- cgit v1.2.3 From d833d2c1fd3861caa055c2d5c87d549b8f246d30 Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 19 Aug 2020 13:37:33 +0200 Subject: CI: Fix release builds once more. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9e9107ce3..be0dd4773 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -194,7 +194,7 @@ amd64: variables: &release-variables MIX_ENV: prod before_script: &before-release - - apt install cmake -y + - apt-get update && apt-get install -y cmake - echo "import Mix.Config" > config/prod.secret.exs - mix local.hex --force - mix local.rebar --force -- cgit v1.2.3 From c1277be041167be255e966eebf95a5137f49e34b Mon Sep 17 00:00:00 2001 From: lain Date: Wed, 19 Aug 2020 14:36:42 +0200 Subject: AudioHandlingTest: Make mock explicit --- .../web/activity_pub/transmogrifier/audio_handling_test.exs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/web/activity_pub/transmogrifier/audio_handling_test.exs b/test/web/activity_pub/transmogrifier/audio_handling_test.exs index 9cb53c48b..0636d00c5 100644 --- a/test/web/activity_pub/transmogrifier/audio_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/audio_handling_test.exs @@ -12,11 +12,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do import Pleroma.Factory - setup_all do - Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) - :ok - end - test "it works for incoming listens" do _user = insert(:user, ap_id: "http://mastodon.example.org/users/admin") @@ -49,6 +44,14 @@ test "it works for incoming listens" do end test "Funkwhale Audio object" do + Tesla.Mock.mock(fn + %{url: "https://channels.tests.funkwhale.audio/federation/actors/compositions"} -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/funkwhale_channel.json") + } + end) + data = File.read!("test/fixtures/tesla_mock/funkwhale_create_audio.json") |> Poison.decode!() {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) -- cgit v1.2.3 From 36c125a071e1fe5a3c0bb1f33a18ba60965437ab Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 20 Aug 2020 18:41:42 +0200 Subject: Pipeline Ingestion: Event --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- lib/pleroma/web/activity_pub/object_validator.ex | 17 +++- .../object_validators/event_validator.ex | 96 ++++++++++++++++++++++ .../object_validators/note_validator.ex | 11 ++- lib/pleroma/web/activity_pub/side_effects.ex | 2 +- lib/pleroma/web/activity_pub/transmogrifier.ex | 4 +- lib/pleroma/web/mastodon_api/views/status_view.ex | 19 +---- .../transmogrifier/event_handling_test.exs | 40 +++++++++ test/web/mastodon_api/views/status_view_test.exs | 6 ++ 9 files changed, 172 insertions(+), 25 deletions(-) create mode 100644 lib/pleroma/web/activity_pub/object_validators/event_validator.ex create mode 100644 test/web/activity_pub/transmogrifier/event_handling_test.exs diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index db1867494..8c5b7dac2 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -85,7 +85,7 @@ defp increase_replies_count_if_reply(%{ defp increase_replies_count_if_reply(_create_data), do: :noop - @object_types ~w[ChatMessage Question Answer Audio] + @object_types ~w[ChatMessage Question Answer Audio Event] @spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()} def persist(%{"type" => type} = object, meta) when type in @object_types do with {:ok, object} <- Object.create(object) do diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index d770ce1be..b77c06395 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -23,6 +23,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do alias Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator @@ -43,6 +44,16 @@ def validate(%{"type" => type} = object, meta) end end + def validate(%{"type" => "Event"} = object, meta) do + with {:ok, object} <- + object + |> EventValidator.cast_and_validate() + |> Ecto.Changeset.apply_action(:insert) do + object = stringify_keys(object) + {:ok, object, meta} + end + end + def validate(%{"type" => "Follow"} = object, meta) do with {:ok, object} <- object @@ -187,7 +198,7 @@ def validate( %{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity, meta ) - when objtype in ~w[Question Answer Audio] do + when objtype in ~w[Question Answer Audio Event] do with {:ok, object_data} <- cast_and_apply(object), meta = Keyword.put(meta, :object_data, object_data |> stringify_keys), {:ok, create_activity} <- @@ -225,6 +236,10 @@ def cast_and_apply(%{"type" => "Audio"} = object) do AudioValidator.cast_and_apply(object) end + def cast_and_apply(%{"type" => "Event"} = object) do + EventValidator.cast_and_apply(object) + end + def cast_and_apply(o), do: {:error, {:validator_not_set, o}} # is_struct/1 isn't present in Elixir 1.8.x diff --git a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex new file mode 100644 index 000000000..07e4821a4 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex @@ -0,0 +1,96 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do + use Ecto.Schema + + alias Pleroma.EctoType.ActivityPub.ObjectValidators + alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes + alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations + + import Ecto.Changeset + + @primary_key false + @derive Jason.Encoder + + # Extends from NoteValidator + embedded_schema do + field(:id, ObjectValidators.ObjectID, primary_key: true) + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) + # TODO: Write type + field(:tag, {:array, :map}, default: []) + field(:type, :string) + + field(:name, :string) + field(:summary, :string) + field(:content, :string) + + field(:context, :string) + # short identifier for PleromaFE to group statuses by context + field(:context_id, :integer) + + # TODO: Remove actor on objects + field(:actor, ObjectValidators.ObjectID) + + field(:attributedTo, ObjectValidators.ObjectID) + field(:published, ObjectValidators.DateTime) + # TODO: Write type + field(:emoji, :map, default: %{}) + field(:sensitive, :boolean, default: false) + embeds_many(:attachment, AttachmentValidator) + field(:replies_count, :integer, default: 0) + field(:like_count, :integer, default: 0) + field(:announcement_count, :integer, default: 0) + field(:inReplyTo, ObjectValidators.ObjectID) + field(:url, ObjectValidators.Uri) + + field(:likes, {:array, ObjectValidators.ObjectID}, default: []) + field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) + end + + def cast_and_apply(data) do + data + |> cast_data + |> apply_action(:insert) + end + + def cast_and_validate(data) do + data + |> cast_data() + |> validate_data() + end + + def cast_data(data) do + %__MODULE__{} + |> changeset(data) + end + + defp fix(data) do + data + |> CommonFixes.fix_defaults() + |> CommonFixes.fix_attribution() + end + + def changeset(struct, data) do + data = fix(data) + + struct + |> cast(data, __schema__(:fields) -- [:attachment]) + |> cast_embed(:attachment) + end + + def validate_data(data_cng) do + data_cng + |> validate_inclusion(:type, ["Event"]) + |> 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() + |> CommonValidations.validate_host_match() + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex index 3e1f13a88..20e735619 100644 --- a/lib/pleroma/web/activity_pub/object_validators/note_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/note_validator.ex @@ -20,11 +20,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do # TODO: Write type field(:tag, {:array, :map}, default: []) field(:type, :string) + + field(:name, :string) + field(:summary, :string) field(:content, :string) + field(:context, :string) + # short identifier for PleromaFE to group statuses by context + field(:context_id, :integer) + field(:actor, ObjectValidators.ObjectID) field(:attributedTo, ObjectValidators.ObjectID) - field(:summary, :string) field(:published, ObjectValidators.DateTime) # TODO: Write type field(:emoji, :map, default: %{}) @@ -39,9 +45,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do field(:likes, {:array, :string}, default: []) field(:announcements, {:array, :string}, default: []) - - # see if needed - field(:context_id, :string) end def cast_and_validate(data) do diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 3dc66c60b..a5e2323bd 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -341,7 +341,7 @@ def handle_object_creation(%{"type" => "Answer"} = object_map, meta) do end def handle_object_creation(%{"type" => objtype} = object, meta) - when objtype in ~w[Audio Question] do + when objtype in ~w[Audio Question Event] do with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do {:ok, object, meta} end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 7c860af9f..76298c4a0 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -460,7 +460,7 @@ def handle_incoming( %{"type" => "Create", "object" => %{"type" => objtype} = object} = data, options ) - when objtype in ~w{Article Event Note Video Page} do + when objtype in ~w{Article Note Video Page} do actor = Containment.get_actor(data) with nil <- Activity.get_create_by_object_ap_id(object["id"]), @@ -554,7 +554,7 @@ def handle_incoming( %{"type" => "Create", "object" => %{"type" => objtype}} = data, _options ) - when objtype in ~w{Question Answer ChatMessage Audio} do + when objtype in ~w{Question Answer ChatMessage Audio Event} do with {:ok, %User{}} <- ObjectValidator.fetch_actor(data), {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do {:ok, activity} diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 91b41ef59..01b8bb6bb 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -473,23 +473,10 @@ def get_reply_to(%{data: %{"object" => _object}} = activity, _) do end end - def render_content(%{data: %{"type" => object_type}} = object) - when object_type in ["Video", "Event", "Audio"] do - with name when not is_nil(name) and name != "" <- object.data["name"] do - "

#{name}

#{object.data["content"]}" - else - _ -> object.data["content"] || "" - end - end + def render_content(%{data: %{"name" => name}} = object) when not is_nil(name) and name != "" do + url = object.data["url"] || object.data["id"] - def render_content(%{data: %{"type" => object_type}} = object) - when object_type in ["Article", "Page"] do - with summary when not is_nil(summary) and summary != "" <- object.data["name"], - url when is_bitstring(url) <- object.data["url"] do - "

#{summary}

#{object.data["content"]}" - else - _ -> object.data["content"] || "" - end + "

#{name}

#{object.data["content"]}" end def render_content(object), do: object.data["content"] || "" diff --git a/test/web/activity_pub/transmogrifier/event_handling_test.exs b/test/web/activity_pub/transmogrifier/event_handling_test.exs new file mode 100644 index 000000000..7f1ef2cbd --- /dev/null +++ b/test/web/activity_pub/transmogrifier/event_handling_test.exs @@ -0,0 +1,40 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.EventHandlingTest do + use Oban.Testing, repo: Pleroma.Repo + use Pleroma.DataCase + + alias Pleroma.Object.Fetcher + + test "Mobilizon Event object" do + Tesla.Mock.mock(fn + %{url: "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"} -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/mobilizon.org-event.json") + } + + %{url: "https://mobilizon.org/@tcit"} -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/mobilizon.org-user.json") + } + end) + + assert {:ok, object} = + Fetcher.fetch_object_from_id( + "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39" + ) + + assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"] + assert object.data["cc"] == [] + + assert object.data["url"] == + "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39" + + assert object.data["published"] == "2019-12-17T11:33:56Z" + assert object.data["name"] == "Mobilizon Launching Party" + end +end diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs index 8703d5ba7..70d829979 100644 --- a/test/web/mastodon_api/views/status_view_test.exs +++ b/test/web/mastodon_api/views/status_view_test.exs @@ -517,6 +517,12 @@ test "a Mobilizon event" do represented = StatusView.render("show.json", %{for: user, activity: activity}) assert represented[:id] == to_string(activity.id) + + assert represented[:url] == + "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39" + + assert represented[:content] == + "

Mobilizon Launching Party

Mobilizon is now federated! 🎉

You can view this event from other instances if they are subscribed to mobilizon.org, and soon directly from Mastodon and Pleroma. It is possible that you may see some comments from other instances, including Mastodon ones, just below.

With a Mobilizon account on an instance, you may participate at events from other instances and add comments on events.

Of course, it's still a work in progress: if reports made from an instance on events and comments can be federated, you can't block people right now, and moderators actions are rather limited, but this will definitely get fixed over time until first stable version next year.

Anyway, if you want to come up with some feedback, head over to our forum or - if you feel you have technical skills and are familiar with it - on our Gitlab repository.

Also, to people that want to set Mobilizon themselves even though we really don't advise to do that for now, we have a little documentation but it's quite the early days and you'll probably need some help. No worries, you can chat with us on our Forum or though our Matrix channel.

Check our website for more informations and follow us on Twitter or Mastodon.

" end describe "build_tags/1" do -- cgit v1.2.3 From 1f8c32b773b56e950285ce96cb9a62f045f2a225 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Fri, 21 Aug 2020 10:38:56 +0300 Subject: adding actor type in user show --- lib/pleroma/web/admin_api/views/account_view.ex | 3 +- .../controllers/admin_api_controller_test.exs | 72 ++++++++++++++-------- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index 333e72e42..9c477feab 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -79,7 +79,8 @@ def render("show.json", %{user: user}) do "confirmation_pending" => user.confirmation_pending, "approval_pending" => user.approval_pending, "url" => user.uri || user.ap_id, - "registration_reason" => user.registration_reason + "registration_reason" => user.registration_reason, + "actor_type" => user.actor_type } end diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index 2eb698807..dbf478edf 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -381,7 +381,8 @@ test "Show", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } assert expected == json_response(conn, 200) @@ -663,7 +664,8 @@ test "renders users array for the first page", %{conn: conn, admin: admin} do "confirmation_pending" => false, "approval_pending" => false, "url" => admin.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" }, %{ "deactivated" => user.deactivated, @@ -677,7 +679,8 @@ test "renders users array for the first page", %{conn: conn, admin: admin} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" }, %{ "deactivated" => user2.deactivated, @@ -691,7 +694,8 @@ test "renders users array for the first page", %{conn: conn, admin: admin} do "confirmation_pending" => false, "approval_pending" => true, "url" => user2.ap_id, - "registration_reason" => "I'm a chill dude" + "registration_reason" => "I'm a chill dude", + "actor_type" => "Person" } ] |> Enum.sort_by(& &1["nickname"]) @@ -766,7 +770,8 @@ test "regular search", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -794,7 +799,8 @@ test "search by domain", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -822,7 +828,8 @@ test "search by full nickname", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -850,7 +857,8 @@ test "search by display name", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -878,7 +886,8 @@ test "search by email", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -906,7 +915,8 @@ test "regular search with page size", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -929,7 +939,8 @@ test "regular search with page size", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user2.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -964,7 +975,8 @@ test "only local users" do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -992,7 +1004,8 @@ test "only local users with no query", %{conn: conn, admin: old_admin} do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" }, %{ "deactivated" => admin.deactivated, @@ -1006,7 +1019,8 @@ test "only local users with no query", %{conn: conn, admin: old_admin} do "confirmation_pending" => false, "approval_pending" => false, "url" => admin.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" }, %{ "deactivated" => false, @@ -1020,7 +1034,8 @@ test "only local users with no query", %{conn: conn, admin: old_admin} do "confirmation_pending" => false, "approval_pending" => false, "url" => old_admin.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] |> Enum.sort_by(& &1["nickname"]) @@ -1058,7 +1073,8 @@ test "only unapproved users", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => true, "url" => user.ap_id, - "registration_reason" => "Plz let me in!" + "registration_reason" => "Plz let me in!", + "actor_type" => "Person" } ] |> Enum.sort_by(& &1["nickname"]) @@ -1091,7 +1107,8 @@ test "load only admins", %{conn: conn, admin: admin} do "confirmation_pending" => false, "approval_pending" => false, "url" => admin.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" }, %{ "deactivated" => false, @@ -1105,7 +1122,8 @@ test "load only admins", %{conn: conn, admin: admin} do "confirmation_pending" => false, "approval_pending" => false, "url" => second_admin.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] |> Enum.sort_by(& &1["nickname"]) @@ -1140,7 +1158,8 @@ test "load only moderators", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => moderator.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -1168,7 +1187,8 @@ test "load users with tags list", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user1.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" }, %{ "deactivated" => false, @@ -1182,7 +1202,8 @@ test "load users with tags list", %{conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => user2.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] |> Enum.sort_by(& &1["nickname"]) @@ -1245,7 +1266,8 @@ test "it works with multiple filters" do "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -1272,7 +1294,8 @@ test "it omits relay user", %{admin: admin, conn: conn} do "confirmation_pending" => false, "approval_pending" => false, "url" => admin.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } ] } @@ -1357,7 +1380,8 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admi "confirmation_pending" => false, "approval_pending" => false, "url" => user.ap_id, - "registration_reason" => nil + "registration_reason" => nil, + "actor_type" => "Person" } log_entry = Repo.one(ModerationLog) -- cgit v1.2.3 From 6e5678b5af62231bf8c18a15b91fed5ecb30e625 Mon Sep 17 00:00:00 2001 From: Angelina Filippova Date: Mon, 24 Aug 2020 22:43:37 +0300 Subject: Add Pleroma.Web.Preload to description.exs --- config/description.exs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/config/description.exs b/config/description.exs index e27abf40f..ebe1f11c4 100644 --- a/config/description.exs +++ b/config/description.exs @@ -3571,5 +3571,24 @@ ] } ] + }, + %{ + group: :pleroma, + key: Pleroma.Web.Preload, + type: :group, + description: "Preload-related settings", + children: [ + %{ + key: :providers, + type: {:list, :module}, + description: "List of preload providers to enable", + suggestions: [ + Pleroma.Web.Preload.Providers.Instance, + Pleroma.Web.Preload.Providers.User, + Pleroma.Web.Preload.Providers.Timelines, + Pleroma.Web.Preload.Providers.StatusNet + ] + } + ] } ] -- cgit v1.2.3 From 16f777a7b2f6c80f6239834707a41b7cf8064e9a Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 24 Aug 2020 23:13:35 +0200 Subject: clients.md: Remove Nekonium, Twidere-iOS, Feather; Add DashFE and BloatFE --- docs/clients.md | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/docs/clients.md b/docs/clients.md index 2a42c659f..f84295b1f 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -6,11 +6,11 @@ Feel free to contact us to be added to this list! ### Roma for Desktop - Homepage: - Source Code: -- Platforms: Windows, Mac, (Linux?) +- Platforms: Windows, Mac, Linux - Features: Streaming Ready ### Social -- Source Code: +- Source Code: - Contact: [@brainblasted@social.libre.fi](https://social.libre.fi/users/brainblasted) - Platforms: Linux (GNOME) - Note(2019-01-28): Not at a pre-alpha stage yet @@ -35,7 +35,7 @@ Feel free to contact us to be added to this list! - Source Code: - Contact: [@fedilab@framapiaf.org](https://framapiaf.org/users/fedilab) - Platforms: Android -- Features: Streaming Ready, Moderation, Text Formatting +- Features: Streaming Ready, Moderation, Text Formatting ### Kyclos - Source Code: @@ -48,16 +48,9 @@ Feel free to contact us to be added to this list! - Platforms: Android - Features: No Streaming, Emoji Reactions, Text Formatting, FE Stickers -### Nekonium -- Homepage: [F-Droid Repository](https://repo.gdgd.jp.net/), [Google Play](https://play.google.com/store/apps/details?id=com.apps.nekonium), [Amazon](https://www.amazon.co.jp/dp/B076FXPRBC/) -- Source: -- Contact: [@lin@pleroma.gdgd.jp.net](https://pleroma.gdgd.jp.net/users/lin) -- Platforms: Android -- Features: Streaming Ready - ### Fedi - Homepage: -- Source Code: Proprietary, but free +- Source Code: Proprietary, but gratis - Platforms: iOS, Android - Features: Pleroma-specific features like Reactions @@ -70,9 +63,9 @@ Feel free to contact us to be added to this list! ### Twidere - Homepage: -- Source Code: , +- Source Code: - Contact: -- Platform: Android, iOS +- Platform: Android - Features: No Streaming ### Indigenous @@ -89,11 +82,6 @@ Feel free to contact us to be added to this list! - Contact: [@gcupc@glitch.social](https://glitch.social/users/gcupc) - Features: No Streaming -### Feather -- Source Code: -- Contact: [@kaniini@pleroma.site](https://pleroma.site/kaniini) -- Features: No Streaming - ### Halcyon - Source Code: - Contact: [@halcyon@social.csswg.org](https://social.csswg.org/users/halcyon) @@ -107,6 +95,15 @@ Feel free to contact us to be added to this list! - Features: No Streaming ### Sengi +- Homepage: - Source Code: - Contact: [@sengi_app@mastodon.social](https://mastodon.social/users/sengi_app) -- Note(2019-01-28): The development is currently in a early stage. + +### DashFE +- Source Code: +- Contact: [@dashfe@stereophonic.space](https://stereophonic.space/users/dashfe) + +### BloatFE +- Source Code: +- Contact: [@r@freesoftwareextremist.com](https://freesoftwareextremist.com/users/r) +- Features: Does not requires JavaScript -- cgit v1.2.3