Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

211 lignes
6.2KB

  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.MastodonAPI.TimelineController do
  5. use Pleroma.Web, :controller
  6. import Pleroma.Web.ControllerHelper,
  7. only: [add_link_headers: 2, add_link_headers: 3]
  8. alias Pleroma.Config
  9. alias Pleroma.Pagination
  10. alias Pleroma.User
  11. alias Pleroma.Web.ActivityPub.ActivityPub
  12. alias Pleroma.Web.Plugs.EnsurePublicOrAuthenticatedPlug
  13. alias Pleroma.Web.Plugs.OAuthScopesPlug
  14. alias Pleroma.Web.Plugs.RateLimiter
  15. plug(Pleroma.Web.ApiSpec.CastAndValidate)
  16. plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action in [:public, :hashtag])
  17. # TODO: Replace with a macro when there is a Phoenix release with the following commit in it:
  18. # https://github.com/phoenixframework/phoenix/commit/2e8c63c01fec4dde5467dbbbf9705ff9e780735e
  19. plug(RateLimiter, [name: :timeline, bucket_name: :direct_timeline] when action == :direct)
  20. plug(RateLimiter, [name: :timeline, bucket_name: :public_timeline] when action == :public)
  21. plug(RateLimiter, [name: :timeline, bucket_name: :home_timeline] when action == :home)
  22. plug(RateLimiter, [name: :timeline, bucket_name: :hashtag_timeline] when action == :hashtag)
  23. plug(RateLimiter, [name: :timeline, bucket_name: :list_timeline] when action == :list)
  24. plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:home, :direct])
  25. plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action == :list)
  26. plug(
  27. OAuthScopesPlug,
  28. %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated}
  29. when action in [:public, :hashtag]
  30. )
  31. plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
  32. defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.TimelineOperation
  33. # GET /api/v1/timelines/home
  34. def home(%{assigns: %{user: user}} = conn, params) do
  35. params =
  36. params
  37. |> Map.put(:type, ["Create", "Announce"])
  38. |> Map.put(:blocking_user, user)
  39. |> Map.put(:muting_user, user)
  40. |> Map.put(:reply_filtering_user, user)
  41. |> Map.put(:announce_filtering_user, user)
  42. |> Map.put(:user, user)
  43. activities =
  44. [user.ap_id | User.following(user)]
  45. |> ActivityPub.fetch_activities(params)
  46. |> Enum.reverse()
  47. conn
  48. |> add_link_headers(activities)
  49. |> render("index.json",
  50. activities: activities,
  51. for: user,
  52. as: :activity
  53. )
  54. end
  55. # GET /api/v1/timelines/direct
  56. def direct(%{assigns: %{user: user}} = conn, params) do
  57. params =
  58. params
  59. |> Map.put(:type, "Create")
  60. |> Map.put(:blocking_user, user)
  61. |> Map.put(:user, user)
  62. |> Map.put(:visibility, "direct")
  63. activities =
  64. [user.ap_id]
  65. |> ActivityPub.fetch_activities_query(params)
  66. |> Pagination.fetch_paginated(params)
  67. conn
  68. |> add_link_headers(activities)
  69. |> render("index.json",
  70. activities: activities,
  71. for: user,
  72. as: :activity
  73. )
  74. end
  75. defp restrict_unauthenticated?(true = _local_only) do
  76. Config.restrict_unauthenticated_access?(:timelines, :local)
  77. end
  78. defp restrict_unauthenticated?(_) do
  79. Config.restrict_unauthenticated_access?(:timelines, :federated)
  80. end
  81. # GET /api/v1/timelines/public
  82. def public(%{assigns: %{user: user}} = conn, params) do
  83. local_only = params[:local]
  84. if is_nil(user) and restrict_unauthenticated?(local_only) do
  85. fail_on_bad_auth(conn)
  86. else
  87. activities =
  88. params
  89. |> Map.put(:type, ["Create"])
  90. |> Map.put(:local_only, local_only)
  91. |> Map.put(:blocking_user, user)
  92. |> Map.put(:muting_user, user)
  93. |> Map.put(:reply_filtering_user, user)
  94. |> ActivityPub.fetch_public_activities()
  95. conn
  96. |> add_link_headers(activities, %{"local" => local_only})
  97. |> render("index.json",
  98. activities: activities,
  99. for: user,
  100. as: :activity
  101. )
  102. end
  103. end
  104. defp fail_on_bad_auth(conn) do
  105. render_error(conn, :unauthorized, "authorization required for timeline view")
  106. end
  107. defp hashtag_fetching(params, user, local_only) do
  108. tags =
  109. [params[:tag], params[:any]]
  110. |> List.flatten()
  111. |> Enum.uniq()
  112. |> Enum.reject(&is_nil/1)
  113. |> Enum.map(&String.downcase/1)
  114. tag_all =
  115. params
  116. |> Map.get(:all, [])
  117. |> Enum.map(&String.downcase/1)
  118. tag_reject =
  119. params
  120. |> Map.get(:none, [])
  121. |> Enum.map(&String.downcase/1)
  122. _activities =
  123. params
  124. |> Map.put(:type, "Create")
  125. |> Map.put(:local_only, local_only)
  126. |> Map.put(:blocking_user, user)
  127. |> Map.put(:muting_user, user)
  128. |> Map.put(:user, user)
  129. |> Map.put(:tag, tags)
  130. |> Map.put(:tag_all, tag_all)
  131. |> Map.put(:tag_reject, tag_reject)
  132. |> ActivityPub.fetch_public_activities()
  133. end
  134. # GET /api/v1/timelines/tag/:tag
  135. def hashtag(%{assigns: %{user: user}} = conn, params) do
  136. local_only = params[:local]
  137. if is_nil(user) and restrict_unauthenticated?(local_only) do
  138. fail_on_bad_auth(conn)
  139. else
  140. activities = hashtag_fetching(params, user, local_only)
  141. conn
  142. |> add_link_headers(activities, %{"local" => local_only})
  143. |> render("index.json",
  144. activities: activities,
  145. for: user,
  146. as: :activity
  147. )
  148. end
  149. end
  150. # GET /api/v1/timelines/list/:list_id
  151. def list(%{assigns: %{user: user}} = conn, %{list_id: id} = params) do
  152. with %Pleroma.List{title: _title, following: following} <- Pleroma.List.get(id, user) do
  153. params =
  154. params
  155. |> Map.put(:type, "Create")
  156. |> Map.put(:blocking_user, user)
  157. |> Map.put(:user, user)
  158. |> Map.put(:muting_user, user)
  159. # we must filter the following list for the user to avoid leaking statuses the user
  160. # does not actually have permission to see (for more info, peruse security issue #270).
  161. user_following = User.following(user)
  162. activities =
  163. following
  164. |> Enum.filter(fn x -> x in user_following end)
  165. |> ActivityPub.fetch_activities_bounded(following, params)
  166. |> Enum.reverse()
  167. render(conn, "index.json",
  168. activities: activities,
  169. for: user,
  170. as: :activity
  171. )
  172. else
  173. _e -> render_error(conn, :forbidden, "Error.")
  174. end
  175. end
  176. end