Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex b/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
index 64d30a5b7..f885b712a 100644
--- a/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
@@ -67,10 +67,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
object = Object.get_cached_by_ap_id(object_id)
cond do
- is_nil(object) -> [object: "is not an object"]
- object.data["actor"] != actor.ap_id -> [object: "doesn't belong to the actor"]
- meta[:local] -> validate_local_pin(object)
- true -> []
+ is_nil(object) ->
+ [object: {"is not an object", reason: :not_allowed}]
+
+ object.data["actor"] != actor.ap_id ->
+ [object: {"doesn't belong to the actor", reason: :ownership_error}]
+
+ meta[:local] ->
+ validate_local_pin(object)
+
+ true ->
+ []
end
end)
end
@@ -79,8 +86,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
defp validate_local_pin(%Object{data: %{"type" => type}} = object) do
cond do
- type not in ~w(Note Article Question) -> [object: "can't be pinned"]
- !Visibility.public?(object) -> [object: "is not public"]
+ type not in ~w(Note Article Question) -> [object: {"can't be pinned", reason: :not_allowed}]
+ !Visibility.public?(object) -> [object: {"is not public", reason: :non_public_error}]
true -> []
end
end
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 41e8de9c1..a2bcb1fe6 100644
--- a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex
@@ -87,8 +87,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do
if local?(voter, poll) do
case vote_error(answer, voter, poll) do
- nil -> :ok
- message -> {:error, answer |> cast_data() |> add_error(:inReplyTo, message)}
+ nil ->
+ :ok
+
+ {message, reason} ->
+ {:error, answer |> cast_data() |> add_error(:inReplyTo, message, reason: reason)}
end
else
:ok
@@ -101,16 +104,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do
defp vote_error(answer, voter, %Object{data: %{"type" => "Question"}} = poll) do
cond do
- poll.data["actor"] == answer["actor"] -> "poll's author can't vote"
- !Visibility.visible_for_user?(poll, voter) -> "is not visible to the voter"
- closed?(poll) -> "poll has already ended"
- answer["name"] not in option_names(poll) -> "is not a poll option"
- voted?(answer, poll) -> "already voted"
+ poll.data["actor"] == answer["actor"] -> {"poll's author can't vote", :author}
+ !Visibility.visible_for_user?(poll, voter) -> {"is not visible to the voter", :invisible}
+ closed?(poll) -> {"poll has already ended", :closed}
+ answer["name"] not in option_names(poll) -> {"is not a poll option", :unknown_option}
+ voted?(answer, poll) -> {"already voted", :already_voted}
true -> nil
end
end
- defp vote_error(_answer, _voter, _poll), do: "is not a poll"
+ defp vote_error(_answer, _voter, _poll), do: {"is not a poll", :not_a_poll}
defp option_names(%Object{data: data}) do
(List.wrap(data["oneOf"]) ++ List.wrap(data["anyOf"]))
diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex
index fbe58bd25..75cc38436 100644
--- a/lib/pleroma/web/common_api.ex
+++ b/lib/pleroma/web/common_api.ex
@@ -401,18 +401,29 @@ defmodule Pleroma.Web.CommonAPI do
|> Pipeline.common_pipeline(local: true)
|> case do
# TODO: Do preload of Pleroma.Object in Pipeline
- {:ok, activity, _meta} -> {:ok, Activity.normalize(activity.data)}
- {:error, {:validate, {:error, changeset}}} -> {:error, vote_error_message(changeset)}
- error -> error
+ {:ok, activity, _meta} ->
+ {:ok, Activity.normalize(activity.data)}
+
+ {:error, {:validate, {:error, %Ecto.Changeset{} = cng}}} ->
+ {:error, vote_error_message(cng)}
+
+ _ ->
+ {:error, dgettext("errors", "Could not vote")}
end
end
defp vote_error_message(%Ecto.Changeset{errors: errors}) do
- case errors[:inReplyTo] do
- {"poll's author can't vote", _} -> dgettext("errors", "Poll's author can't vote")
- {"poll has already ended", _} -> dgettext("errors", "Poll has already ended")
- {"already voted", _} -> dgettext("errors", "Already voted")
- {"is not a poll option", _} -> dgettext("errors", "Invalid indices")
+ reason =
+ case errors[:inReplyTo] do
+ {_, opts} -> opts[:reason]
+ _ -> nil
+ end
+
+ case reason do
+ :author -> dgettext("errors", "Poll's author can't vote")
+ :closed -> dgettext("errors", "Poll has already ended")
+ :already_voted -> dgettext("errors", "Already voted")
+ :unknown_option -> dgettext("errors", "Invalid indices")
_ -> dgettext("errors", "Could not vote")
end
end
@@ -434,7 +445,11 @@ defmodule Pleroma.Web.CommonAPI do
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)
+ choices =
+ choices
+ |> Enum.map(fn i -> if is_binary(i), do: String.to_integer(i), else: i end)
+ |> Enum.uniq()
+
{options, max_count} = get_options_and_max_count(object)
count = Enum.count(options)
@@ -603,10 +618,10 @@ defmodule Pleroma.Web.CommonAPI do
end
defp pin_error(%Ecto.Changeset{errors: errors}) do
- case errors[:object] do
- {"doesn't belong to the actor", _} -> :ownership_error
- {"can't be pinned", _} -> :not_allowed
- {"is not public", _} -> :non_public_error
+ with {_, opts} <- errors[:object],
+ reason when not is_nil(reason) <- opts[:reason] do
+ reason
+ else
_ -> :not_allowed
end
end
diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs
index 3b13db432..b39da6cd0 100644
--- a/test/pleroma/web/common_api_test.exs
+++ b/test/pleroma/web/common_api_test.exs
@@ -1867,6 +1867,19 @@ defmodule Pleroma.Web.CommonAPITest do
assert {:error, "Already voted"} == CommonAPI.vote(object, other_user, [1])
end
+ test "counts a repeated choice once" do
+ {:ok, activity} =
+ CommonAPI.post(insert(:user), %{
+ status: "?",
+ poll: %{options: ["a", "b"], expires_in: 20, multiple: true}
+ })
+
+ object = Object.normalize(activity, fetch: false)
+
+ assert {:ok, [_], object} = CommonAPI.vote(object, insert(:user), [0, 0])
+ assert [1, 0] == Enum.map(object.data["anyOf"], & &1["replies"]["totalItems"])
+ end
+
test "maps validator errors to readable messages" do
user = insert(:user)

File Metadata

Mime Type
text/x-diff
Expires
Sun, Nov 1, 12:50 AM (12 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1802005
Default Alt Text
(6 KB)

Event Timeline