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