logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

poll_controller.ex (2739B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.MastodonAPI.PollController do
  5. use Pleroma.Web, :controller
  6. import Pleroma.Web.ControllerHelper, only: [try_render: 3, json_response: 3]
  7. alias Pleroma.Activity
  8. alias Pleroma.Object
  9. alias Pleroma.Web.ActivityPub.Visibility
  10. alias Pleroma.Web.CommonAPI
  11. alias Pleroma.Web.Plugs.OAuthScopesPlug
  12. action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
  13. plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
  14. plug(
  15. OAuthScopesPlug,
  16. %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated} when action == :show
  17. )
  18. plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :vote)
  19. defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PollOperation
  20. @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
  21. @doc "GET /api/v1/polls/:id"
  22. def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
  23. with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
  24. %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
  25. true <- Visibility.visible_for_user?(activity, user) do
  26. try_render(conn, "show.json", %{object: object, for: user})
  27. else
  28. error when is_nil(error) or error == false ->
  29. render_error(conn, :not_found, "Record not found")
  30. end
  31. end
  32. @doc "POST /api/v1/polls/:id/votes"
  33. def vote(
  34. %{
  35. assigns: %{user: user},
  36. private: %{open_api_spex: %{body_params: %{choices: choices}, params: %{id: id}}}
  37. } = conn,
  38. _
  39. ) do
  40. with %Object{data: %{"type" => "Question"}} = object <- Object.get_by_id(id),
  41. %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
  42. true <- Visibility.visible_for_user?(activity, user),
  43. {:ok, _activities, object} <- get_cached_vote_or_vote(user, object, choices) do
  44. try_render(conn, "show.json", %{object: object, for: user})
  45. else
  46. nil -> render_error(conn, :not_found, "Record not found")
  47. false -> render_error(conn, :not_found, "Record not found")
  48. {:error, message} -> json_response(conn, :unprocessable_entity, %{error: message})
  49. end
  50. end
  51. defp get_cached_vote_or_vote(user, object, choices) do
  52. idempotency_key = "polls:#{user.id}:#{object.data["id"]}"
  53. @cachex.fetch!(:idempotency_cache, idempotency_key, fn _ ->
  54. case CommonAPI.vote(user, object, choices) do
  55. {:error, _message} = res -> {:ignore, res}
  56. res -> {:commit, res}
  57. end
  58. end)
  59. end
  60. end