cf8ccf18781186af63704843dafeeeb2912a17df
[akkoma] / test / pleroma / web / mastodon_api / update_credentials_test.exs
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.MastodonAPI.UpdateCredentialsTest do
6 alias Pleroma.Repo
7 alias Pleroma.User
8
9 use Pleroma.Web.ConnCase
10
11 import Mock
12 import Pleroma.Factory
13
14 describe "updating credentials" do
15 setup do: oauth_access(["write:accounts"])
16 setup :request_content_type
17
18 test "sets user settings in a generic way", %{conn: conn} do
19 res_conn =
20 patch(conn, "/api/v1/accounts/update_credentials", %{
21 "pleroma_settings_store" => %{
22 pleroma_fe: %{
23 theme: "bla"
24 }
25 }
26 })
27
28 assert user_data = json_response_and_validate_schema(res_conn, 200)
29 assert user_data["pleroma"]["settings_store"] == %{"pleroma_fe" => %{"theme" => "bla"}}
30
31 user = Repo.get(User, user_data["id"])
32
33 res_conn =
34 conn
35 |> assign(:user, user)
36 |> patch("/api/v1/accounts/update_credentials", %{
37 "pleroma_settings_store" => %{
38 soapbox_fe: %{
39 themeMode: "bla"
40 }
41 }
42 })
43
44 assert user_data = json_response_and_validate_schema(res_conn, 200)
45
46 assert user_data["pleroma"]["settings_store"] ==
47 %{
48 "pleroma_fe" => %{"theme" => "bla"},
49 "soapbox_fe" => %{"themeMode" => "bla"}
50 }
51
52 user = Repo.get(User, user_data["id"])
53
54 clear_config([:instance, :federating], true)
55
56 with_mock Pleroma.Web.Federator,
57 publish: fn _activity -> :ok end do
58 res_conn =
59 conn
60 |> assign(:user, user)
61 |> patch("/api/v1/accounts/update_credentials", %{
62 "pleroma_settings_store" => %{
63 soapbox_fe: %{
64 themeMode: "blub"
65 }
66 }
67 })
68
69 assert user_data = json_response_and_validate_schema(res_conn, 200)
70
71 assert user_data["pleroma"]["settings_store"] ==
72 %{
73 "pleroma_fe" => %{"theme" => "bla"},
74 "soapbox_fe" => %{"themeMode" => "blub"}
75 }
76
77 assert_called(Pleroma.Web.Federator.publish(:_))
78 end
79 end
80
81 test "updates the user's bio", %{conn: conn} do
82 user2 = insert(:user)
83
84 raw_bio = "I drink #cofe with @#{user2.nickname}\n\nsuya.."
85
86 conn = patch(conn, "/api/v1/accounts/update_credentials", %{"note" => raw_bio})
87
88 assert user_data = json_response_and_validate_schema(conn, 200)
89
90 assert user_data["note"] ==
91 ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a class="u-url mention" data-user="#{
92 user2.id
93 }" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..)
94
95 assert user_data["source"]["note"] == raw_bio
96
97 user = Repo.get(User, user_data["id"])
98
99 assert user.raw_bio == raw_bio
100 end
101
102 test "updates the user's locking status", %{conn: conn} do
103 conn = patch(conn, "/api/v1/accounts/update_credentials", %{locked: "true"})
104
105 assert user_data = json_response_and_validate_schema(conn, 200)
106 assert user_data["locked"] == true
107 end
108
109 test "updates the user's chat acceptance status", %{conn: conn} do
110 conn = patch(conn, "/api/v1/accounts/update_credentials", %{accepts_chat_messages: "false"})
111
112 assert user_data = json_response_and_validate_schema(conn, 200)
113 assert user_data["pleroma"]["accepts_chat_messages"] == false
114 end
115
116 test "updates the user's allow_following_move", %{user: user, conn: conn} do
117 assert user.allow_following_move == true
118
119 conn = patch(conn, "/api/v1/accounts/update_credentials", %{allow_following_move: "false"})
120
121 assert refresh_record(user).allow_following_move == false
122 assert user_data = json_response_and_validate_schema(conn, 200)
123 assert user_data["pleroma"]["allow_following_move"] == false
124 end
125
126 test "updates the user's default scope", %{conn: conn} do
127 conn = patch(conn, "/api/v1/accounts/update_credentials", %{default_scope: "unlisted"})
128
129 assert user_data = json_response_and_validate_schema(conn, 200)
130 assert user_data["source"]["privacy"] == "unlisted"
131 end
132
133 test "updates the user's privacy", %{conn: conn} do
134 conn = patch(conn, "/api/v1/accounts/update_credentials", %{source: %{privacy: "unlisted"}})
135
136 assert user_data = json_response_and_validate_schema(conn, 200)
137 assert user_data["source"]["privacy"] == "unlisted"
138 end
139
140 test "updates the user's hide_followers status", %{conn: conn} do
141 conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_followers: "true"})
142
143 assert user_data = json_response_and_validate_schema(conn, 200)
144 assert user_data["pleroma"]["hide_followers"] == true
145 end
146
147 test "updates the user's discoverable status", %{conn: conn} do
148 assert %{"source" => %{"pleroma" => %{"discoverable" => true}}} =
149 conn
150 |> patch("/api/v1/accounts/update_credentials", %{discoverable: "true"})
151 |> json_response_and_validate_schema(:ok)
152
153 assert %{"source" => %{"pleroma" => %{"discoverable" => false}}} =
154 conn
155 |> patch("/api/v1/accounts/update_credentials", %{discoverable: "false"})
156 |> json_response_and_validate_schema(:ok)
157 end
158
159 test "updates the user's hide_followers_count and hide_follows_count", %{conn: conn} do
160 conn =
161 patch(conn, "/api/v1/accounts/update_credentials", %{
162 hide_followers_count: "true",
163 hide_follows_count: "true"
164 })
165
166 assert user_data = json_response_and_validate_schema(conn, 200)
167 assert user_data["pleroma"]["hide_followers_count"] == true
168 assert user_data["pleroma"]["hide_follows_count"] == true
169 end
170
171 test "updates the user's skip_thread_containment option", %{user: user, conn: conn} do
172 response =
173 conn
174 |> patch("/api/v1/accounts/update_credentials", %{skip_thread_containment: "true"})
175 |> json_response_and_validate_schema(200)
176
177 assert response["pleroma"]["skip_thread_containment"] == true
178 assert refresh_record(user).skip_thread_containment
179 end
180
181 test "updates the user's hide_follows status", %{conn: conn} do
182 conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_follows: "true"})
183
184 assert user_data = json_response_and_validate_schema(conn, 200)
185 assert user_data["pleroma"]["hide_follows"] == true
186 end
187
188 test "updates the user's hide_favorites status", %{conn: conn} do
189 conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_favorites: "true"})
190
191 assert user_data = json_response_and_validate_schema(conn, 200)
192 assert user_data["pleroma"]["hide_favorites"] == true
193 end
194
195 test "updates the user's show_role status", %{conn: conn} do
196 conn = patch(conn, "/api/v1/accounts/update_credentials", %{show_role: "false"})
197
198 assert user_data = json_response_and_validate_schema(conn, 200)
199 assert user_data["source"]["pleroma"]["show_role"] == false
200 end
201
202 test "updates the user's no_rich_text status", %{conn: conn} do
203 conn = patch(conn, "/api/v1/accounts/update_credentials", %{no_rich_text: "true"})
204
205 assert user_data = json_response_and_validate_schema(conn, 200)
206 assert user_data["source"]["pleroma"]["no_rich_text"] == true
207 end
208
209 test "updates the user's name", %{conn: conn} do
210 conn =
211 patch(conn, "/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
212
213 assert user_data = json_response_and_validate_schema(conn, 200)
214 assert user_data["display_name"] == "markorepairs"
215
216 update_activity = Repo.one(Pleroma.Activity)
217 assert update_activity.data["type"] == "Update"
218 assert update_activity.data["object"]["name"] == "markorepairs"
219 end
220
221 test "updates the user's AKAs", %{conn: conn} do
222 conn =
223 patch(conn, "/api/v1/accounts/update_credentials", %{
224 "also_known_as" => ["https://mushroom.kingdom/users/mario"]
225 })
226
227 assert user_data = json_response_and_validate_schema(conn, 200)
228 assert user_data["pleroma"]["also_known_as"] == ["https://mushroom.kingdom/users/mario"]
229 end
230
231 test "doesn't update non-url akas", %{conn: conn} do
232 conn =
233 patch(conn, "/api/v1/accounts/update_credentials", %{
234 "also_known_as" => ["aReallyCoolGuy"]
235 })
236
237 assert json_response_and_validate_schema(conn, 403)
238 end
239
240 test "updates the user's avatar", %{user: user, conn: conn} do
241 new_avatar = %Plug.Upload{
242 content_type: "image/jpeg",
243 path: Path.absname("test/fixtures/image.jpg"),
244 filename: "an_image.jpg"
245 }
246
247 assert user.avatar == %{}
248
249 res = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
250
251 assert user_response = json_response_and_validate_schema(res, 200)
252 assert user_response["avatar"] != User.avatar_url(user)
253
254 user = User.get_by_id(user.id)
255 refute user.avatar == %{}
256
257 # Also resets it
258 _res = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => ""})
259
260 user = User.get_by_id(user.id)
261 assert user.avatar == nil
262 end
263
264 test "updates the user's banner", %{user: user, conn: conn} do
265 new_header = %Plug.Upload{
266 content_type: "image/jpeg",
267 path: Path.absname("test/fixtures/image.jpg"),
268 filename: "an_image.jpg"
269 }
270
271 res = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header})
272
273 assert user_response = json_response_and_validate_schema(res, 200)
274 assert user_response["header"] != User.banner_url(user)
275
276 # Also resets it
277 _res = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => ""})
278
279 user = User.get_by_id(user.id)
280 assert user.banner == nil
281 end
282
283 test "updates the user's background", %{conn: conn, user: user} do
284 new_header = %Plug.Upload{
285 content_type: "image/jpeg",
286 path: Path.absname("test/fixtures/image.jpg"),
287 filename: "an_image.jpg"
288 }
289
290 res =
291 patch(conn, "/api/v1/accounts/update_credentials", %{
292 "pleroma_background_image" => new_header
293 })
294
295 assert user_response = json_response_and_validate_schema(res, 200)
296 assert user_response["pleroma"]["background_image"]
297 #
298 # Also resets it
299 _res =
300 patch(conn, "/api/v1/accounts/update_credentials", %{"pleroma_background_image" => ""})
301
302 user = User.get_by_id(user.id)
303 assert user.background == nil
304 end
305
306 test "requires 'write:accounts' permission" do
307 token1 = insert(:oauth_token, scopes: ["read"])
308 token2 = insert(:oauth_token, scopes: ["write", "follow"])
309
310 for token <- [token1, token2] do
311 conn =
312 build_conn()
313 |> put_req_header("content-type", "multipart/form-data")
314 |> put_req_header("authorization", "Bearer #{token.token}")
315 |> patch("/api/v1/accounts/update_credentials", %{})
316
317 if token == token1 do
318 assert %{"error" => "Insufficient permissions: write:accounts."} ==
319 json_response_and_validate_schema(conn, 403)
320 else
321 assert json_response_and_validate_schema(conn, 200)
322 end
323 end
324 end
325
326 test "updates profile emojos", %{user: user, conn: conn} do
327 note = "*sips :blank:*"
328 name = "I am :firefox:"
329
330 ret_conn =
331 patch(conn, "/api/v1/accounts/update_credentials", %{
332 "note" => note,
333 "display_name" => name
334 })
335
336 assert json_response_and_validate_schema(ret_conn, 200)
337
338 conn = get(conn, "/api/v1/accounts/#{user.id}")
339
340 assert user_data = json_response_and_validate_schema(conn, 200)
341
342 assert user_data["note"] == note
343 assert user_data["display_name"] == name
344 assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = user_data["emojis"]
345 end
346
347 test "update fields", %{conn: conn} do
348 fields = [
349 %{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "<script>bar</script>"},
350 %{"name" => "link.io", "value" => "cofe.io"}
351 ]
352
353 account_data =
354 conn
355 |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
356 |> json_response_and_validate_schema(200)
357
358 assert account_data["fields"] == [
359 %{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
360 %{
361 "name" => "link.io",
362 "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)
363 }
364 ]
365
366 assert account_data["source"]["fields"] == [
367 %{
368 "name" => "<a href=\"http://google.com\">foo</a>",
369 "value" => "<script>bar</script>"
370 },
371 %{"name" => "link.io", "value" => "cofe.io"}
372 ]
373 end
374
375 test "emojis in fields labels", %{conn: conn} do
376 fields = [
377 %{"name" => ":firefox:", "value" => "is best 2hu"},
378 %{"name" => "they wins", "value" => ":blank:"}
379 ]
380
381 account_data =
382 conn
383 |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
384 |> json_response_and_validate_schema(200)
385
386 assert account_data["fields"] == [
387 %{"name" => ":firefox:", "value" => "is best 2hu"},
388 %{"name" => "they wins", "value" => ":blank:"}
389 ]
390
391 assert account_data["source"]["fields"] == [
392 %{"name" => ":firefox:", "value" => "is best 2hu"},
393 %{"name" => "they wins", "value" => ":blank:"}
394 ]
395
396 assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = account_data["emojis"]
397 end
398
399 test "update fields via x-www-form-urlencoded", %{conn: conn} do
400 fields =
401 [
402 "fields_attributes[1][name]=link",
403 "fields_attributes[1][value]=http://cofe.io",
404 "fields_attributes[0][name]=foo",
405 "fields_attributes[0][value]=bar"
406 ]
407 |> Enum.join("&")
408
409 account =
410 conn
411 |> put_req_header("content-type", "application/x-www-form-urlencoded")
412 |> patch("/api/v1/accounts/update_credentials", fields)
413 |> json_response_and_validate_schema(200)
414
415 assert account["fields"] == [
416 %{"name" => "foo", "value" => "bar"},
417 %{
418 "name" => "link",
419 "value" => ~S(<a href="http://cofe.io" rel="ugc">http://cofe.io</a>)
420 }
421 ]
422
423 assert account["source"]["fields"] == [
424 %{"name" => "foo", "value" => "bar"},
425 %{"name" => "link", "value" => "http://cofe.io"}
426 ]
427 end
428
429 test "update fields with empty name", %{conn: conn} do
430 fields = [
431 %{"name" => "foo", "value" => ""},
432 %{"name" => "", "value" => "bar"}
433 ]
434
435 account =
436 conn
437 |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
438 |> json_response_and_validate_schema(200)
439
440 assert account["fields"] == [
441 %{"name" => "foo", "value" => ""}
442 ]
443 end
444
445 test "update fields when invalid request", %{conn: conn} do
446 name_limit = Pleroma.Config.get([:instance, :account_field_name_length])
447 value_limit = Pleroma.Config.get([:instance, :account_field_value_length])
448
449 long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join()
450 long_value = Enum.map(0..value_limit, fn _ -> "x" end) |> Enum.join()
451
452 fields = [%{"name" => "foo", "value" => long_value}]
453
454 assert %{"error" => "Invalid request"} ==
455 conn
456 |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
457 |> json_response_and_validate_schema(403)
458
459 fields = [%{"name" => long_name, "value" => "bar"}]
460
461 assert %{"error" => "Invalid request"} ==
462 conn
463 |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
464 |> json_response_and_validate_schema(403)
465
466 clear_config([:instance, :max_account_fields], 1)
467
468 fields = [
469 %{"name" => "foo", "value" => "bar"},
470 %{"name" => "link", "value" => "cofe.io"}
471 ]
472
473 assert %{"error" => "Invalid request"} ==
474 conn
475 |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
476 |> json_response_and_validate_schema(403)
477 end
478 end
479
480 describe "Mark account as bot" do
481 setup do: oauth_access(["write:accounts"])
482 setup :request_content_type
483
484 test "changing actor_type to Service makes account a bot", %{conn: conn} do
485 account =
486 conn
487 |> patch("/api/v1/accounts/update_credentials", %{actor_type: "Service"})
488 |> json_response_and_validate_schema(200)
489
490 assert account["bot"]
491 assert account["source"]["pleroma"]["actor_type"] == "Service"
492 end
493
494 test "changing actor_type to Person makes account a human", %{conn: conn} do
495 account =
496 conn
497 |> patch("/api/v1/accounts/update_credentials", %{actor_type: "Person"})
498 |> json_response_and_validate_schema(200)
499
500 refute account["bot"]
501 assert account["source"]["pleroma"]["actor_type"] == "Person"
502 end
503
504 test "changing actor_type to Application causes error", %{conn: conn} do
505 response =
506 conn
507 |> patch("/api/v1/accounts/update_credentials", %{actor_type: "Application"})
508 |> json_response_and_validate_schema(403)
509
510 assert %{"error" => "Invalid request"} == response
511 end
512
513 test "changing bot field to true changes actor_type to Service", %{conn: conn} do
514 account =
515 conn
516 |> patch("/api/v1/accounts/update_credentials", %{bot: "true"})
517 |> json_response_and_validate_schema(200)
518
519 assert account["bot"]
520 assert account["source"]["pleroma"]["actor_type"] == "Service"
521 end
522
523 test "changing bot field to false changes actor_type to Person", %{conn: conn} do
524 account =
525 conn
526 |> patch("/api/v1/accounts/update_credentials", %{bot: "false"})
527 |> json_response_and_validate_schema(200)
528
529 refute account["bot"]
530 assert account["source"]["pleroma"]["actor_type"] == "Person"
531 end
532
533 test "actor_type field has a higher priority than bot", %{conn: conn} do
534 account =
535 conn
536 |> patch("/api/v1/accounts/update_credentials", %{
537 actor_type: "Person",
538 bot: "true"
539 })
540 |> json_response_and_validate_schema(200)
541
542 refute account["bot"]
543 assert account["source"]["pleroma"]["actor_type"] == "Person"
544 end
545 end
546 end