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