Do not serve RSS/Atom feeds when instance is private
[akkoma] / test / web / feed / user_controller_test.exs
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
5 defmodule Pleroma.Web.Feed.UserControllerTest do
6 use Pleroma.Web.ConnCase
7
8 import Pleroma.Factory
9 import SweetXml
10
11 alias Pleroma.Config
12 alias Pleroma.Object
13 alias Pleroma.User
14 alias Pleroma.Web.CommonAPI
15
16 setup do: clear_config([:instance, :federating], true)
17
18 describe "feed" do
19 setup do: clear_config([:feed])
20
21 test "gets an atom feed", %{conn: conn} do
22 Config.put(
23 [:feed, :post_title],
24 %{max_length: 10, omission: "..."}
25 )
26
27 activity = insert(:note_activity)
28
29 note =
30 insert(:note,
31 data: %{
32 "content" => "This is :moominmamma: note ",
33 "attachment" => [
34 %{
35 "url" => [
36 %{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
37 ]
38 }
39 ],
40 "inReplyTo" => activity.data["id"]
41 }
42 )
43
44 note_activity = insert(:note_activity, note: note)
45 user = User.get_cached_by_ap_id(note_activity.data["actor"])
46
47 note2 =
48 insert(:note,
49 user: user,
50 data: %{
51 "content" => "42 This is :moominmamma: note ",
52 "inReplyTo" => activity.data["id"]
53 }
54 )
55
56 note_activity2 = insert(:note_activity, note: note2)
57 object = Object.normalize(note_activity)
58
59 resp =
60 conn
61 |> put_req_header("accept", "application/atom+xml")
62 |> get(user_feed_path(conn, :feed, user.nickname))
63 |> response(200)
64
65 activity_titles =
66 resp
67 |> SweetXml.parse()
68 |> SweetXml.xpath(~x"//entry/title/text()"l)
69
70 assert activity_titles == ['42 This...', 'This is...']
71 assert resp =~ object.data["content"]
72
73 resp =
74 conn
75 |> put_req_header("accept", "application/atom+xml")
76 |> get("/users/#{user.nickname}/feed", %{"max_id" => note_activity2.id})
77 |> response(200)
78
79 activity_titles =
80 resp
81 |> SweetXml.parse()
82 |> SweetXml.xpath(~x"//entry/title/text()"l)
83
84 assert activity_titles == ['This is...']
85 end
86
87 test "gets a rss feed", %{conn: conn} do
88 Pleroma.Config.put(
89 [:feed, :post_title],
90 %{max_length: 10, omission: "..."}
91 )
92
93 activity = insert(:note_activity)
94
95 note =
96 insert(:note,
97 data: %{
98 "content" => "This is :moominmamma: note ",
99 "attachment" => [
100 %{
101 "url" => [
102 %{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
103 ]
104 }
105 ],
106 "inReplyTo" => activity.data["id"]
107 }
108 )
109
110 note_activity = insert(:note_activity, note: note)
111 user = User.get_cached_by_ap_id(note_activity.data["actor"])
112
113 note2 =
114 insert(:note,
115 user: user,
116 data: %{
117 "content" => "42 This is :moominmamma: note ",
118 "inReplyTo" => activity.data["id"]
119 }
120 )
121
122 note_activity2 = insert(:note_activity, note: note2)
123 object = Object.normalize(note_activity)
124
125 resp =
126 conn
127 |> put_req_header("accept", "application/rss+xml")
128 |> get("/users/#{user.nickname}/feed.rss")
129 |> response(200)
130
131 activity_titles =
132 resp
133 |> SweetXml.parse()
134 |> SweetXml.xpath(~x"//item/title/text()"l)
135
136 assert activity_titles == ['42 This...', 'This is...']
137 assert resp =~ object.data["content"]
138
139 resp =
140 conn
141 |> put_req_header("accept", "application/rss+xml")
142 |> get("/users/#{user.nickname}/feed.rss", %{"max_id" => note_activity2.id})
143 |> response(200)
144
145 activity_titles =
146 resp
147 |> SweetXml.parse()
148 |> SweetXml.xpath(~x"//item/title/text()"l)
149
150 assert activity_titles == ['This is...']
151 end
152
153 test "returns 404 for a missing feed", %{conn: conn} do
154 conn =
155 conn
156 |> put_req_header("accept", "application/atom+xml")
157 |> get(user_feed_path(conn, :feed, "nonexisting"))
158
159 assert response(conn, 404)
160 end
161
162 test "returns feed with public and unlisted activities", %{conn: conn} do
163 user = insert(:user)
164
165 {:ok, _} = CommonAPI.post(user, %{status: "public", visibility: "public"})
166 {:ok, _} = CommonAPI.post(user, %{status: "direct", visibility: "direct"})
167 {:ok, _} = CommonAPI.post(user, %{status: "unlisted", visibility: "unlisted"})
168 {:ok, _} = CommonAPI.post(user, %{status: "private", visibility: "private"})
169
170 resp =
171 conn
172 |> put_req_header("accept", "application/atom+xml")
173 |> get(user_feed_path(conn, :feed, user.nickname))
174 |> response(200)
175
176 activity_titles =
177 resp
178 |> SweetXml.parse()
179 |> SweetXml.xpath(~x"//entry/title/text()"l)
180 |> Enum.sort()
181
182 assert activity_titles == ['public', 'unlisted']
183 end
184
185 test "returns 404 when the user is remote", %{conn: conn} do
186 user = insert(:user, local: false)
187
188 {:ok, _} = CommonAPI.post(user, %{status: "test"})
189
190 assert conn
191 |> put_req_header("accept", "application/atom+xml")
192 |> get(user_feed_path(conn, :feed, user.nickname))
193 |> response(404)
194 end
195 end
196
197 # Note: see ActivityPubControllerTest for JSON format tests
198 describe "feed_redirect" do
199 test "with html format, it redirects to user feed", %{conn: conn} do
200 note_activity = insert(:note_activity)
201 user = User.get_cached_by_ap_id(note_activity.data["actor"])
202
203 response =
204 conn
205 |> get("/users/#{user.nickname}")
206 |> response(200)
207
208 assert response ==
209 Fallback.RedirectController.redirector_with_meta(
210 conn,
211 %{user: user}
212 ).resp_body
213 end
214
215 test "with html format, it returns error when user is not found", %{conn: conn} do
216 response =
217 conn
218 |> get("/users/jimm")
219 |> json_response(404)
220
221 assert response == %{"error" => "Not found"}
222 end
223
224 test "with non-html / non-json format, it redirects to user feed in atom format", %{
225 conn: conn
226 } do
227 note_activity = insert(:note_activity)
228 user = User.get_cached_by_ap_id(note_activity.data["actor"])
229
230 conn =
231 conn
232 |> put_req_header("accept", "application/xml")
233 |> get("/users/#{user.nickname}")
234
235 assert conn.status == 302
236 assert redirected_to(conn) == "#{Pleroma.Web.base_url()}/users/#{user.nickname}/feed.atom"
237 end
238
239 test "with non-html / non-json format, it returns error when user is not found", %{conn: conn} do
240 response =
241 conn
242 |> put_req_header("accept", "application/xml")
243 |> get(user_feed_path(conn, :feed, "jimm"))
244 |> response(404)
245
246 assert response == ~S({"error":"Not found"})
247 end
248 end
249
250 describe "private instance" do
251 setup do: clear_config([:instance, :public])
252
253 test "returns 404 for user feed", %{conn: conn} do
254 Config.put([:instance, :public], false)
255 user = insert(:user)
256
257 {:ok, _} = CommonAPI.post(user, %{status: "test"})
258
259 assert conn
260 |> put_req_header("accept", "application/atom+xml")
261 |> get(user_feed_path(conn, :feed, user.nickname))
262 |> response(404)
263 end
264 end
265 end