Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
4.7KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.OStatus.OStatusController do
  5. use Pleroma.Web, :controller
  6. alias Pleroma.Activity
  7. alias Pleroma.Object
  8. alias Pleroma.User
  9. alias Pleroma.Web.ActivityPub.ActivityPubController
  10. alias Pleroma.Web.ActivityPub.Visibility
  11. alias Pleroma.Web.Endpoint
  12. alias Pleroma.Web.Fallback.RedirectController
  13. alias Pleroma.Web.Metadata.PlayerView
  14. alias Pleroma.Web.Plugs.RateLimiter
  15. alias Pleroma.Web.Router
  16. plug(Pleroma.Web.Plugs.EnsureAuthenticatedPlug,
  17. unless_func: &Pleroma.Web.Plugs.FederatingPlug.federating?/1
  18. )
  19. plug(
  20. RateLimiter,
  21. [name: :ap_routes, params: ["uuid"]] when action in [:object, :activity]
  22. )
  23. plug(
  24. Pleroma.Web.Plugs.SetFormatPlug
  25. when action in [:object, :activity, :notice]
  26. )
  27. action_fallback(:errors)
  28. def object(%{assigns: %{format: format}} = conn, _params)
  29. when format in ["json", "activity+json"] do
  30. ActivityPubController.call(conn, :object)
  31. end
  32. def object(%{assigns: %{format: format}} = conn, _params) do
  33. with id <- Endpoint.url() <> conn.request_path,
  34. {_, %Activity{} = activity} <-
  35. {:activity, Activity.get_create_by_object_ap_id_with_object(id)},
  36. {_, true} <- {:public?, Visibility.is_public?(activity)} do
  37. case format do
  38. _ -> redirect(conn, to: "/notice/#{activity.id}")
  39. end
  40. else
  41. reason when reason in [{:public?, false}, {:activity, nil}] ->
  42. {:error, :not_found}
  43. e ->
  44. e
  45. end
  46. end
  47. def activity(%{assigns: %{format: format}} = conn, _params)
  48. when format in ["json", "activity+json"] do
  49. ActivityPubController.call(conn, :activity)
  50. end
  51. def activity(%{assigns: %{format: format}} = conn, _params) do
  52. with id <- Endpoint.url() <> conn.request_path,
  53. {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
  54. {_, true} <- {:public?, Visibility.is_public?(activity)} do
  55. case format do
  56. _ -> redirect(conn, to: "/notice/#{activity.id}")
  57. end
  58. else
  59. reason when reason in [{:public?, false}, {:activity, nil}] ->
  60. {:error, :not_found}
  61. e ->
  62. e
  63. end
  64. end
  65. def notice(%{assigns: %{format: format}} = conn, %{"id" => id}) do
  66. with {_, %Activity{} = activity} <- {:activity, Activity.get_by_id_with_object(id)},
  67. {_, true} <- {:public?, Visibility.is_public?(activity)},
  68. %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
  69. cond do
  70. format in ["json", "activity+json"] ->
  71. if activity.local do
  72. %{data: %{"id" => redirect_url}} = Object.normalize(activity)
  73. redirect(conn, external: redirect_url)
  74. else
  75. {:error, :not_found}
  76. end
  77. activity.data["type"] == "Create" ->
  78. %Object{} = object = Object.normalize(activity)
  79. RedirectController.redirector_with_meta(
  80. conn,
  81. %{
  82. activity_id: activity.id,
  83. object: object,
  84. url: Router.Helpers.o_status_url(Endpoint, :notice, activity.id),
  85. user: user
  86. }
  87. )
  88. true ->
  89. RedirectController.redirector(conn, nil)
  90. end
  91. else
  92. reason when reason in [{:public?, false}, {:activity, nil}] ->
  93. conn
  94. |> put_status(404)
  95. |> RedirectController.redirector(nil, 404)
  96. e ->
  97. e
  98. end
  99. end
  100. # Returns an HTML embedded <audio> or <video> player suitable for embed iframes.
  101. def notice_player(conn, %{"id" => id}) do
  102. with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id_with_object(id),
  103. true <- Visibility.is_public?(activity),
  104. %Object{} = object <- Object.normalize(activity),
  105. %{data: %{"attachment" => [%{"url" => [url | _]} | _]}} <- object,
  106. true <- String.starts_with?(url["mediaType"], ["audio", "video"]) do
  107. conn
  108. |> put_layout(:metadata_player)
  109. |> put_resp_header("x-frame-options", "ALLOW")
  110. |> put_resp_header(
  111. "content-security-policy",
  112. "default-src 'none';style-src 'self' 'unsafe-inline';img-src 'self' data: https:; media-src 'self' https:;"
  113. )
  114. |> put_view(PlayerView)
  115. |> render("player.html", url)
  116. else
  117. _error ->
  118. conn
  119. |> put_status(404)
  120. |> RedirectController.redirector(nil, 404)
  121. end
  122. end
  123. defp errors(conn, {:error, :not_found}) do
  124. render_error(conn, :not_found, "Not found")
  125. end
  126. defp errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
  127. defp errors(conn, _) do
  128. render_error(conn, :internal_server_error, "Something went wrong")
  129. end
  130. end