twitter api: add no_rich_text option to userview for account prefs
[akkoma] / test / user_test.exs
1 defmodule Pleroma.UserTest do
2 alias Pleroma.Builders.UserBuilder
3 alias Pleroma.{User, Repo, Activity}
4 alias Pleroma.Web.OStatus
5 alias Pleroma.Web.Websub.WebsubClientSubscription
6 alias Pleroma.Web.CommonAPI
7 use Pleroma.DataCase
8
9 import Pleroma.Factory
10 import Ecto.Query
11
12 test "ap_id returns the activity pub id for the user" do
13 user = UserBuilder.build()
14
15 expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
16
17 assert expected_ap_id == User.ap_id(user)
18 end
19
20 test "ap_followers returns the followers collection for the user" do
21 user = UserBuilder.build()
22
23 expected_followers_collection = "#{User.ap_id(user)}/followers"
24
25 assert expected_followers_collection == User.ap_followers(user)
26 end
27
28 test "follow takes a user and another user" do
29 user = insert(:user)
30 followed = insert(:user)
31
32 {:ok, user} = User.follow(user, followed)
33
34 user = Repo.get(User, user.id)
35
36 followed = User.get_by_ap_id(followed.ap_id)
37 assert followed.info["follower_count"] == 1
38
39 assert User.ap_followers(followed) in user.following
40 end
41
42 test "can't follow a deactivated users" do
43 user = insert(:user)
44 followed = insert(:user, info: %{"deactivated" => true})
45
46 {:error, _} = User.follow(user, followed)
47 end
48
49 test "can't follow a user who blocked us" do
50 blocker = insert(:user)
51 blockee = insert(:user)
52
53 {:ok, blocker} = User.block(blocker, blockee)
54
55 {:error, _} = User.follow(blockee, blocker)
56 end
57
58 # This is a somewhat useless test.
59 # test "following a remote user will ensure a websub subscription is present" do
60 # user = insert(:user)
61 # {:ok, followed} = OStatus.make_user("shp@social.heldscal.la")
62
63 # assert followed.local == false
64
65 # {:ok, user} = User.follow(user, followed)
66 # assert User.ap_followers(followed) in user.following
67
68 # query = from w in WebsubClientSubscription,
69 # where: w.topic == ^followed.info["topic"]
70 # websub = Repo.one(query)
71
72 # assert websub
73 # end
74
75 test "unfollow takes a user and another user" do
76 followed = insert(:user)
77 user = insert(:user, %{following: [User.ap_followers(followed)]})
78
79 {:ok, user, _activity} = User.unfollow(user, followed)
80
81 user = Repo.get(User, user.id)
82
83 assert user.following == []
84 end
85
86 test "unfollow doesn't unfollow yourself" do
87 user = insert(:user)
88
89 {:error, _} = User.unfollow(user, user)
90
91 user = Repo.get(User, user.id)
92 assert user.following == [user.ap_id]
93 end
94
95 test "test if a user is following another user" do
96 followed = insert(:user)
97 user = insert(:user, %{following: [User.ap_followers(followed)]})
98
99 assert User.following?(user, followed)
100 refute User.following?(followed, user)
101 end
102
103 describe "user registration" do
104 @full_user_data %{
105 bio: "A guy",
106 name: "my name",
107 nickname: "nick",
108 password: "test",
109 password_confirmation: "test",
110 email: "email@example.com"
111 }
112
113 test "it requires an email, name, nickname and password, bio is optional" do
114 @full_user_data
115 |> Map.keys()
116 |> Enum.each(fn key ->
117 params = Map.delete(@full_user_data, key)
118 changeset = User.register_changeset(%User{}, params)
119
120 assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
121 end)
122 end
123
124 test "it sets the password_hash, ap_id and following fields" do
125 changeset = User.register_changeset(%User{}, @full_user_data)
126
127 assert changeset.valid?
128
129 assert is_binary(changeset.changes[:password_hash])
130 assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
131
132 assert changeset.changes[:following] == [
133 User.ap_followers(%User{nickname: @full_user_data.nickname})
134 ]
135
136 assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
137 end
138 end
139
140 describe "fetching a user from nickname or trying to build one" do
141 test "gets an existing user" do
142 user = insert(:user)
143 fetched_user = User.get_or_fetch_by_nickname(user.nickname)
144
145 assert user == fetched_user
146 end
147
148 test "gets an existing user, case insensitive" do
149 user = insert(:user, nickname: "nick")
150 fetched_user = User.get_or_fetch_by_nickname("NICK")
151
152 assert user == fetched_user
153 end
154
155 test "fetches an external user via ostatus if no user exists" do
156 fetched_user = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
157 assert fetched_user.nickname == "shp@social.heldscal.la"
158 end
159
160 test "returns nil if no user could be fetched" do
161 fetched_user = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
162 assert fetched_user == nil
163 end
164
165 test "returns nil for nonexistant local user" do
166 fetched_user = User.get_or_fetch_by_nickname("nonexistant")
167 assert fetched_user == nil
168 end
169
170 test "updates an existing user, if stale" do
171 a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
172
173 orig_user =
174 insert(
175 :user,
176 local: false,
177 nickname: "admin@mastodon.example.org",
178 ap_id: "http://mastodon.example.org/users/admin",
179 last_refreshed_at: a_week_ago
180 )
181
182 assert orig_user.last_refreshed_at == a_week_ago
183
184 user = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
185
186 refute user.last_refreshed_at == orig_user.last_refreshed_at
187 end
188 end
189
190 test "returns an ap_id for a user" do
191 user = insert(:user)
192
193 assert User.ap_id(user) ==
194 Pleroma.Web.Router.Helpers.o_status_url(
195 Pleroma.Web.Endpoint,
196 :feed_redirect,
197 user.nickname
198 )
199 end
200
201 test "returns an ap_followers link for a user" do
202 user = insert(:user)
203
204 assert User.ap_followers(user) ==
205 Pleroma.Web.Router.Helpers.o_status_url(
206 Pleroma.Web.Endpoint,
207 :feed_redirect,
208 user.nickname
209 ) <> "/followers"
210 end
211
212 describe "remote user creation changeset" do
213 @valid_remote %{
214 bio: "hello",
215 name: "Someone",
216 nickname: "a@b.de",
217 ap_id: "http...",
218 info: %{some: "info"},
219 avatar: %{some: "avatar"}
220 }
221
222 test "it confirms validity" do
223 cs = User.remote_user_creation(@valid_remote)
224 assert cs.valid?
225 end
226
227 test "it sets the follower_adress" do
228 cs = User.remote_user_creation(@valid_remote)
229 # remote users get a fake local follower address
230 assert cs.changes.follower_address ==
231 User.ap_followers(%User{nickname: @valid_remote[:nickname]})
232 end
233
234 test "it enforces the fqn format for nicknames" do
235 cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
236 assert cs.changes.local == false
237 assert cs.changes.avatar
238 refute cs.valid?
239 end
240
241 test "it has required fields" do
242 [:name, :ap_id]
243 |> Enum.each(fn field ->
244 cs = User.remote_user_creation(Map.delete(@valid_remote, field))
245 refute cs.valid?
246 end)
247 end
248
249 test "it restricts some sizes" do
250 [bio: 5000, name: 100]
251 |> Enum.each(fn {field, size} ->
252 string = String.pad_leading(".", size)
253 cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
254 assert cs.valid?
255
256 string = String.pad_leading(".", size + 1)
257 cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
258 refute cs.valid?
259 end)
260 end
261 end
262
263 describe "followers and friends" do
264 test "gets all followers for a given user" do
265 user = insert(:user)
266 follower_one = insert(:user)
267 follower_two = insert(:user)
268 not_follower = insert(:user)
269
270 {:ok, follower_one} = User.follow(follower_one, user)
271 {:ok, follower_two} = User.follow(follower_two, user)
272
273 {:ok, res} = User.get_followers(user)
274
275 assert Enum.member?(res, follower_one)
276 assert Enum.member?(res, follower_two)
277 refute Enum.member?(res, not_follower)
278 end
279
280 test "gets all friends (followed users) for a given user" do
281 user = insert(:user)
282 followed_one = insert(:user)
283 followed_two = insert(:user)
284 not_followed = insert(:user)
285
286 {:ok, user} = User.follow(user, followed_one)
287 {:ok, user} = User.follow(user, followed_two)
288
289 {:ok, res} = User.get_friends(user)
290
291 followed_one = User.get_by_ap_id(followed_one.ap_id)
292 followed_two = User.get_by_ap_id(followed_two.ap_id)
293 assert Enum.member?(res, followed_one)
294 assert Enum.member?(res, followed_two)
295 refute Enum.member?(res, not_followed)
296 end
297 end
298
299 describe "updating note and follower count" do
300 test "it sets the info->note_count property" do
301 note = insert(:note)
302
303 user = User.get_by_ap_id(note.data["actor"])
304
305 assert user.info["note_count"] == nil
306
307 {:ok, user} = User.update_note_count(user)
308
309 assert user.info["note_count"] == 1
310 end
311
312 test "it increases the info->note_count property" do
313 note = insert(:note)
314 user = User.get_by_ap_id(note.data["actor"])
315
316 assert user.info["note_count"] == nil
317
318 {:ok, user} = User.increase_note_count(user)
319
320 assert user.info["note_count"] == 1
321
322 {:ok, user} = User.increase_note_count(user)
323
324 assert user.info["note_count"] == 2
325 end
326
327 test "it decreases the info->note_count property" do
328 note = insert(:note)
329 user = User.get_by_ap_id(note.data["actor"])
330
331 assert user.info["note_count"] == nil
332
333 {:ok, user} = User.increase_note_count(user)
334
335 assert user.info["note_count"] == 1
336
337 {:ok, user} = User.decrease_note_count(user)
338
339 assert user.info["note_count"] == 0
340
341 {:ok, user} = User.decrease_note_count(user)
342
343 assert user.info["note_count"] == 0
344 end
345
346 test "it sets the info->follower_count property" do
347 user = insert(:user)
348 follower = insert(:user)
349
350 User.follow(follower, user)
351
352 assert user.info["follower_count"] == nil
353
354 {:ok, user} = User.update_follower_count(user)
355
356 assert user.info["follower_count"] == 1
357 end
358 end
359
360 describe "blocks" do
361 test "it blocks people" do
362 user = insert(:user)
363 blocked_user = insert(:user)
364
365 refute User.blocks?(user, blocked_user)
366
367 {:ok, user} = User.block(user, blocked_user)
368
369 assert User.blocks?(user, blocked_user)
370 end
371
372 test "it unblocks users" do
373 user = insert(:user)
374 blocked_user = insert(:user)
375
376 {:ok, user} = User.block(user, blocked_user)
377 {:ok, user} = User.unblock(user, blocked_user)
378
379 refute User.blocks?(user, blocked_user)
380 end
381
382 test "blocks tear down cyclical follow relationships" do
383 blocker = insert(:user)
384 blocked = insert(:user)
385
386 {:ok, blocker} = User.follow(blocker, blocked)
387 {:ok, blocked} = User.follow(blocked, blocker)
388
389 assert User.following?(blocker, blocked)
390 assert User.following?(blocked, blocker)
391
392 {:ok, blocker} = User.block(blocker, blocked)
393 blocked = Repo.get(User, blocked.id)
394
395 assert User.blocks?(blocker, blocked)
396
397 refute User.following?(blocker, blocked)
398 refute User.following?(blocked, blocker)
399 end
400
401 test "blocks tear down blocker->blocked follow relationships" do
402 blocker = insert(:user)
403 blocked = insert(:user)
404
405 {:ok, blocker} = User.follow(blocker, blocked)
406
407 assert User.following?(blocker, blocked)
408 refute User.following?(blocked, blocker)
409
410 {:ok, blocker} = User.block(blocker, blocked)
411 blocked = Repo.get(User, blocked.id)
412
413 assert User.blocks?(blocker, blocked)
414
415 refute User.following?(blocker, blocked)
416 refute User.following?(blocked, blocker)
417 end
418
419 test "blocks tear down blocked->blocker follow relationships" do
420 blocker = insert(:user)
421 blocked = insert(:user)
422
423 {:ok, blocked} = User.follow(blocked, blocker)
424
425 refute User.following?(blocker, blocked)
426 assert User.following?(blocked, blocker)
427
428 {:ok, blocker} = User.block(blocker, blocked)
429 blocked = Repo.get(User, blocked.id)
430
431 assert User.blocks?(blocker, blocked)
432
433 refute User.following?(blocker, blocked)
434 refute User.following?(blocked, blocker)
435 end
436 end
437
438 describe "domain blocking" do
439 test "blocks domains" do
440 user = insert(:user)
441 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
442
443 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
444
445 assert User.blocks?(user, collateral_user)
446 end
447
448 test "unblocks domains" do
449 user = insert(:user)
450 collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
451
452 {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
453 {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
454
455 refute User.blocks?(user, collateral_user)
456 end
457 end
458
459 test "get recipients from activity" do
460 actor = insert(:user)
461 user = insert(:user, local: true)
462 user_two = insert(:user, local: false)
463 addressed = insert(:user, local: true)
464 addressed_remote = insert(:user, local: false)
465
466 {:ok, activity} =
467 CommonAPI.post(actor, %{
468 "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
469 })
470
471 assert [addressed] == User.get_recipients_from_activity(activity)
472
473 {:ok, user} = User.follow(user, actor)
474 {:ok, _user_two} = User.follow(user_two, actor)
475 recipients = User.get_recipients_from_activity(activity)
476 assert length(recipients) == 2
477 assert user in recipients
478 assert addressed in recipients
479 end
480
481 test ".deactivate deactivates a user" do
482 user = insert(:user)
483 assert false == !!user.info["deactivated"]
484 {:ok, user} = User.deactivate(user)
485 assert true == user.info["deactivated"]
486 end
487
488 test ".delete deactivates a user, all follow relationships and all create activities" do
489 user = insert(:user)
490 followed = insert(:user)
491 follower = insert(:user)
492
493 {:ok, user} = User.follow(user, followed)
494 {:ok, follower} = User.follow(follower, user)
495
496 {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
497 {:ok, activity_two} = CommonAPI.post(follower, %{"status" => "3hu"})
498
499 {:ok, _, _} = CommonAPI.favorite(activity_two.id, user)
500 {:ok, _, _} = CommonAPI.favorite(activity.id, follower)
501 {:ok, _, _} = CommonAPI.repeat(activity.id, follower)
502
503 :ok = User.delete(user)
504
505 followed = Repo.get(User, followed.id)
506 follower = Repo.get(User, follower.id)
507 user = Repo.get(User, user.id)
508
509 assert user.info["deactivated"]
510
511 refute User.following?(user, followed)
512 refute User.following?(followed, follower)
513
514 # TODO: Remove favorites, repeats, delete activities.
515
516 refute Repo.get(Activity, activity.id)
517 end
518
519 test "get_public_key_for_ap_id fetches a user that's not in the db" do
520 assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
521 end
522
523 test "insert or update a user from given data" do
524 user = insert(:user, %{nickname: "nick@name.de"})
525 data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
526
527 assert {:ok, %User{}} = User.insert_or_update_user(data)
528 end
529
530 describe "per-user rich-text filtering" do
531 test "html_filter_policy returns nil when rich-text is enabled" do
532 user = insert(:user)
533
534 assert nil == User.html_filter_policy(user)
535 end
536
537 test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
538 user = insert(:user, %{info: %{"no_rich_text" => true}})
539
540 assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
541 end
542 end
543 end