total rebase
[anni] / test / support / factory.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Factory do
6   use ExMachina.Ecto, repo: Pleroma.Repo
7
8   require Pleroma.Constants
9
10   alias Pleroma.Object
11   alias Pleroma.User
12
13   @rsa_keys [
14               "test/fixtures/rsa_keys/key_1.pem",
15               "test/fixtures/rsa_keys/key_2.pem",
16               "test/fixtures/rsa_keys/key_3.pem",
17               "test/fixtures/rsa_keys/key_4.pem",
18               "test/fixtures/rsa_keys/key_5.pem"
19             ]
20             |> Enum.map(&File.read!/1)
21
22   def participation_factory do
23     conversation = insert(:conversation)
24     user = insert(:user)
25
26     %Pleroma.Conversation.Participation{
27       conversation: conversation,
28       user: user,
29       read: false
30     }
31   end
32
33   def conversation_factory do
34     %Pleroma.Conversation{
35       ap_id: sequence(:ap_id, &"https://some_conversation/#{&1}")
36     }
37   end
38
39   def user_factory(attrs \\ %{}) do
40     pem = Enum.random(@rsa_keys)
41
42     user = %User{
43       name: sequence(:name, &"Test テスト User #{&1}"),
44       email: sequence(:email, &"user#{&1}@example.com"),
45       nickname: sequence(:nickname, &"nick#{&1}"),
46       password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt("test"),
47       bio: sequence(:bio, &"Tester Number #{&1}"),
48       is_discoverable: true,
49       last_digest_emailed_at: NaiveDateTime.utc_now(),
50       last_refreshed_at: NaiveDateTime.utc_now(),
51       notification_settings: %Pleroma.User.NotificationSetting{},
52       multi_factor_authentication_settings: %Pleroma.MFA.Settings{},
53       keys: pem
54     }
55
56     urls =
57       if attrs[:local] == false do
58         base_domain = attrs[:domain] || Enum.random(["domain1.com", "domain2.com", "domain3.com"])
59
60         ap_id = "https://#{base_domain}/users/#{user.nickname}"
61
62         %{
63           ap_id: ap_id,
64           follower_address: ap_id <> "/followers",
65           following_address: ap_id <> "/following",
66           featured_address: ap_id <> "/collections/featured"
67         }
68       else
69         %{
70           ap_id: User.ap_id(user),
71           follower_address: User.ap_followers(user),
72           following_address: User.ap_following(user),
73           featured_address: User.ap_featured_collection(user)
74         }
75       end
76
77     attrs = Map.delete(attrs, :domain)
78
79     user
80     |> Map.put(:raw_bio, user.bio)
81     |> Map.merge(urls)
82     |> merge_attributes(attrs)
83   end
84
85   def user_relationship_factory(attrs \\ %{}) do
86     source = attrs[:source] || insert(:user)
87     target = attrs[:target] || insert(:user)
88     relationship_type = attrs[:relationship_type] || :block
89
90     %Pleroma.UserRelationship{
91       source_id: source.id,
92       target_id: target.id,
93       relationship_type: relationship_type
94     }
95   end
96
97   def note_factory(attrs \\ %{}) do
98     text = sequence(:text, &"This is :moominmamma: note #{&1}")
99
100     user = attrs[:user] || insert(:user)
101
102     data = %{
103       "type" => "Note",
104       "content" => text,
105       "source" => text,
106       "id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
107       "actor" => user.ap_id,
108       "to" => ["https://www.w3.org/ns/activitystreams#Public"],
109       "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
110       "likes" => [],
111       "like_count" => 0,
112       "context" => "2hu",
113       "summary" => "2hu",
114       "tag" => ["2hu"],
115       "emoji" => %{
116         "2hu" => "corndog.png"
117       }
118     }
119
120     %Pleroma.Object{
121       data: merge_attributes(data, Map.get(attrs, :data, %{}))
122     }
123   end
124
125   def attachment_factory(attrs \\ %{}) do
126     user = attrs[:user] || insert(:user)
127
128     data =
129       attachment_data(user.ap_id, nil)
130       |> Map.put("id", Pleroma.Web.ActivityPub.Utils.generate_object_id())
131
132     %Pleroma.Object{
133       data: merge_attributes(data, Map.get(attrs, :data, %{}))
134     }
135   end
136
137   def attachment_note_factory(attrs \\ %{}) do
138     user = attrs[:user] || insert(:user)
139     {length, attrs} = Map.pop(attrs, :length, 1)
140
141     data = %{
142       "attachment" =>
143         Stream.repeatedly(fn -> attachment_data(user.ap_id, attrs[:href]) end)
144         |> Enum.take(length)
145     }
146
147     build(:note, Map.put(attrs, :data, data))
148   end
149
150   defp attachment_data(ap_id, href) do
151     href = href || sequence(:href, &"#{Pleroma.Web.Endpoint.url()}/media/#{&1}.jpg")
152
153     %{
154       "url" => [
155         %{
156           "href" => href,
157           "type" => "Link",
158           "mediaType" => "image/jpeg"
159         }
160       ],
161       "name" => "some name",
162       "type" => "Document",
163       "actor" => ap_id,
164       "mediaType" => "image/jpeg"
165     }
166   end
167
168   def followers_only_note_factory(attrs \\ %{}) do
169     %Pleroma.Object{data: data} = note_factory(attrs)
170     %Pleroma.Object{data: Map.merge(data, %{"to" => [data["actor"] <> "/followers"]})}
171   end
172
173   def audio_factory(attrs \\ %{}) do
174     text = sequence(:text, &"lain radio episode #{&1}")
175
176     user = attrs[:user] || insert(:user)
177
178     data = %{
179       "type" => "Audio",
180       "id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
181       "artist" => "lain",
182       "title" => text,
183       "album" => "lain radio",
184       "to" => ["https://www.w3.org/ns/activitystreams#Public"],
185       "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
186       "actor" => user.ap_id,
187       "length" => 180_000
188     }
189
190     %Pleroma.Object{
191       data: merge_attributes(data, Map.get(attrs, :data, %{}))
192     }
193   end
194
195   def listen_factory do
196     audio = insert(:audio)
197
198     data = %{
199       "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
200       "type" => "Listen",
201       "actor" => audio.data["actor"],
202       "to" => audio.data["to"],
203       "object" => audio.data,
204       "published" => audio.data["published"]
205     }
206
207     %Pleroma.Activity{
208       data: data,
209       actor: data["actor"],
210       recipients: data["to"]
211     }
212   end
213
214   def direct_note_factory do
215     user2 = insert(:user, local: false, inbox: "http://example.com/inbox")
216
217     %Pleroma.Object{data: data} = note_factory()
218     %Pleroma.Object{data: Map.merge(data, %{"to" => [user2.ap_id]})}
219   end
220
221   def article_factory do
222     %Pleroma.Object{data: data} = note_factory()
223     %Pleroma.Object{data: Map.merge(data, %{"type" => "Article"})}
224   end
225
226   def tombstone_factory do
227     data = %{
228       "type" => "Tombstone",
229       "id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
230       "formerType" => "Note",
231       "deleted" => DateTime.utc_now() |> DateTime.to_iso8601()
232     }
233
234     %Pleroma.Object{
235       data: data
236     }
237   end
238
239   def question_factory(attrs \\ %{}) do
240     user = attrs[:user] || insert(:user)
241
242     data = %{
243       "id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
244       "type" => "Question",
245       "actor" => user.ap_id,
246       "attributedTo" => user.ap_id,
247       "attachment" => [],
248       "to" => ["https://www.w3.org/ns/activitystreams#Public"],
249       "cc" => [user.follower_address],
250       "context" => Pleroma.Web.ActivityPub.Utils.generate_context_id(),
251       "closed" => DateTime.utc_now() |> DateTime.add(86_400) |> DateTime.to_iso8601(),
252       "oneOf" => [
253         %{
254           "type" => "Note",
255           "name" => "chocolate",
256           "replies" => %{"totalItems" => 0, "type" => "Collection"}
257         },
258         %{
259           "type" => "Note",
260           "name" => "vanilla",
261           "replies" => %{"totalItems" => 0, "type" => "Collection"}
262         }
263       ]
264     }
265
266     %Pleroma.Object{
267       data: merge_attributes(data, Map.get(attrs, :data, %{}))
268     }
269   end
270
271   def direct_note_activity_factory do
272     dm = insert(:direct_note)
273
274     data = %{
275       "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
276       "type" => "Create",
277       "actor" => dm.data["actor"],
278       "to" => dm.data["to"],
279       "object" => dm.data,
280       "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
281       "context" => dm.data["context"]
282     }
283
284     %Pleroma.Activity{
285       data: data,
286       actor: data["actor"],
287       recipients: data["to"]
288     }
289   end
290
291   def add_activity_factory(attrs \\ %{}) do
292     featured_collection_activity(attrs, "Add")
293   end
294
295   def remove_activity_factor(attrs \\ %{}) do
296     featured_collection_activity(attrs, "Remove")
297   end
298
299   defp featured_collection_activity(attrs, type) do
300     user = attrs[:user] || insert(:user)
301     note = attrs[:note] || insert(:note, user: user)
302
303     data_attrs =
304       attrs
305       |> Map.get(:data_attrs, %{})
306       |> Map.put(:type, type)
307
308     attrs = Map.drop(attrs, [:user, :note, :data_attrs])
309
310     data =
311       %{
312         "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
313         "target" => user.featured_address,
314         "object" => note.data["object"],
315         "actor" => note.data["actor"],
316         "type" => "Add",
317         "to" => [Pleroma.Constants.as_public()],
318         "cc" => [user.follower_address]
319       }
320       |> Map.merge(data_attrs)
321
322     %Pleroma.Activity{
323       data: data,
324       actor: data["actor"],
325       recipients: data["to"]
326     }
327     |> Map.merge(attrs)
328   end
329
330   def followers_only_note_activity_factory(attrs \\ %{}) do
331     user = attrs[:user] || insert(:user)
332     note = insert(:followers_only_note, user: user)
333
334     data_attrs = attrs[:data_attrs] || %{}
335     attrs = Map.drop(attrs, [:user, :note, :data_attrs])
336
337     data =
338       %{
339         "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
340         "type" => "Create",
341         "actor" => note.data["actor"],
342         "to" => note.data["to"],
343         "object" => note.data,
344         "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
345         "context" => note.data["context"]
346       }
347       |> Map.merge(data_attrs)
348
349     %Pleroma.Activity{
350       data: data,
351       actor: data["actor"],
352       recipients: data["to"]
353     }
354     |> Map.merge(attrs)
355   end
356
357   def note_activity_factory(attrs \\ %{}) do
358     user = attrs[:user] || insert(:user)
359     note = attrs[:note] || insert(:note, user: user)
360
361     data_attrs = attrs[:data_attrs] || %{}
362     attrs = Map.drop(attrs, [:user, :note, :data_attrs])
363
364     data =
365       %{
366         "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
367         "type" => "Create",
368         "actor" => note.data["actor"],
369         "to" => note.data["to"],
370         "object" => note.data["id"],
371         "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
372         "context" => note.data["context"]
373       }
374       |> Map.merge(data_attrs)
375
376     %Pleroma.Activity{
377       data: data,
378       actor: data["actor"],
379       recipients: data["to"]
380     }
381     |> Map.merge(attrs)
382   end
383
384   def article_activity_factory do
385     article = insert(:article)
386
387     data = %{
388       "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
389       "type" => "Create",
390       "actor" => article.data["actor"],
391       "to" => article.data["to"],
392       "object" => article.data,
393       "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
394       "context" => article.data["context"]
395     }
396
397     %Pleroma.Activity{
398       data: data,
399       actor: data["actor"],
400       recipients: data["to"]
401     }
402   end
403
404   def announce_activity_factory(attrs \\ %{}) do
405     note_activity = attrs[:note_activity] || insert(:note_activity)
406     user = attrs[:user] || insert(:user)
407
408     data = %{
409       "type" => "Announce",
410       "actor" => note_activity.actor,
411       "object" => note_activity.data["id"],
412       "to" => [user.follower_address, note_activity.data["actor"]],
413       "cc" => ["https://www.w3.org/ns/activitystreams#Public"],
414       "context" => note_activity.data["context"]
415     }
416
417     %Pleroma.Activity{
418       data: data,
419       actor: user.ap_id,
420       recipients: data["to"]
421     }
422   end
423
424   def like_activity_factory(attrs \\ %{}) do
425     note_activity = attrs[:note_activity] || insert(:note_activity)
426     object = Object.normalize(note_activity, fetch: false)
427     user = insert(:user)
428
429     data =
430       %{
431         "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
432         "actor" => user.ap_id,
433         "type" => "Like",
434         "object" => object.data["id"],
435         "published_at" => DateTime.utc_now() |> DateTime.to_iso8601()
436       }
437       |> Map.merge(attrs[:data_attrs] || %{})
438
439     %Pleroma.Activity{
440       data: data
441     }
442   end
443
444   def follow_activity_factory do
445     follower = insert(:user)
446     followed = insert(:user)
447
448     data = %{
449       "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
450       "actor" => follower.ap_id,
451       "type" => "Follow",
452       "object" => followed.ap_id,
453       "published_at" => DateTime.utc_now() |> DateTime.to_iso8601()
454     }
455
456     %Pleroma.Activity{
457       data: data,
458       actor: follower.ap_id
459     }
460   end
461
462   def report_activity_factory(attrs \\ %{}) do
463     user = attrs[:user] || insert(:user)
464     activity = attrs[:activity] || insert(:note_activity)
465     state = attrs[:state] || "open"
466
467     data = %{
468       "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
469       "actor" => user.ap_id,
470       "type" => "Flag",
471       "object" => [activity.actor, activity.data["id"]],
472       "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
473       "to" => [],
474       "cc" => [activity.actor],
475       "context" => activity.data["context"],
476       "state" => state
477     }
478
479     %Pleroma.Activity{
480       data: data,
481       actor: data["actor"],
482       recipients: data["to"] ++ data["cc"]
483     }
484   end
485
486   def question_activity_factory(attrs \\ %{}) do
487     user = attrs[:user] || insert(:user)
488     question = attrs[:question] || insert(:question, user: user)
489
490     data_attrs = attrs[:data_attrs] || %{}
491     attrs = Map.drop(attrs, [:user, :question, :data_attrs])
492
493     data =
494       %{
495         "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
496         "type" => "Create",
497         "actor" => question.data["actor"],
498         "to" => question.data["to"],
499         "object" => question.data["id"],
500         "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
501         "context" => question.data["context"]
502       }
503       |> Map.merge(data_attrs)
504
505     %Pleroma.Activity{
506       data: data,
507       actor: data["actor"],
508       recipients: data["to"]
509     }
510     |> Map.merge(attrs)
511   end
512
513   def oauth_app_factory do
514     %Pleroma.Web.OAuth.App{
515       client_name: sequence(:client_name, &"Some client #{&1}"),
516       redirect_uris: "https://example.com/callback",
517       scopes: ["read", "write", "follow", "push", "admin"],
518       website: "https://example.com",
519       client_id: Ecto.UUID.generate(),
520       client_secret: "aaa;/&bbb"
521     }
522   end
523
524   def instance_factory do
525     %Pleroma.Instances.Instance{
526       host: "domain.com",
527       unreachable_since: nil
528     }
529   end
530
531   def oauth_token_factory(attrs \\ %{}) do
532     scopes = Map.get(attrs, :scopes, ["read"])
533     oauth_app = Map.get_lazy(attrs, :app, fn -> insert(:oauth_app, scopes: scopes) end)
534     user = Map.get_lazy(attrs, :user, fn -> build(:user) end)
535
536     valid_until =
537       Map.get(attrs, :valid_until, NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10))
538
539     %Pleroma.Web.OAuth.Token{
540       token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),
541       refresh_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),
542       scopes: scopes,
543       user: user,
544       app: oauth_app,
545       valid_until: valid_until
546     }
547   end
548
549   def oauth_admin_token_factory(attrs \\ %{}) do
550     user = Map.get_lazy(attrs, :user, fn -> build(:user, is_admin: true) end)
551
552     scopes =
553       attrs
554       |> Map.get(:scopes, ["admin"])
555       |> Kernel.++(["admin"])
556       |> Enum.uniq()
557
558     attrs = Map.merge(attrs, %{user: user, scopes: scopes})
559     oauth_token_factory(attrs)
560   end
561
562   def oauth_authorization_factory do
563     %Pleroma.Web.OAuth.Authorization{
564       token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false),
565       scopes: ["read", "write", "follow", "push"],
566       valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10),
567       user: build(:user),
568       app: build(:oauth_app)
569     }
570   end
571
572   def push_subscription_factory do
573     %Pleroma.Web.Push.Subscription{
574       user: build(:user),
575       token: build(:oauth_token),
576       endpoint: "https://example.com/example/1234",
577       key_auth: "8eDyX_uCN0XRhSbY5hs7Hg==",
578       key_p256dh:
579         "BCIWgsnyXDv1VkhqL2P7YRBvdeuDnlwAPT2guNhdIoW3IP7GmHh1SMKPLxRf7x8vJy6ZFK3ol2ohgn_-0yP7QQA=",
580       data: %{}
581     }
582   end
583
584   def notification_factory do
585     %Pleroma.Notification{
586       user: build(:user)
587     }
588   end
589
590   def scheduled_activity_factory do
591     %Pleroma.ScheduledActivity{
592       user: build(:user),
593       scheduled_at: NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(60), :millisecond),
594       params: build(:note) |> Map.from_struct() |> Map.get(:data)
595     }
596   end
597
598   def registration_factory do
599     user = insert(:user)
600
601     %Pleroma.Registration{
602       user: user,
603       provider: "twitter",
604       uid: "171799000",
605       info: %{
606         "name" => "John Doe",
607         "email" => "john@doe.com",
608         "nickname" => "johndoe",
609         "description" => "My bio"
610       }
611     }
612   end
613
614   def config_factory(attrs \\ %{}) do
615     %Pleroma.ConfigDB{
616       key: sequence(:key, &String.to_atom("some_key_#{&1}")),
617       group: :pleroma,
618       value:
619         sequence(
620           :value,
621           &%{another_key: "#{&1}somevalue", another: "#{&1}somevalue"}
622         )
623     }
624     |> merge_attributes(attrs)
625   end
626
627   def marker_factory do
628     %Pleroma.Marker{
629       user: build(:user),
630       timeline: "notifications",
631       lock_version: 0,
632       last_read_id: "1"
633     }
634   end
635
636   def mfa_token_factory do
637     %Pleroma.MFA.Token{
638       token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false),
639       authorization: build(:oauth_authorization),
640       valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10),
641       user: build(:user)
642     }
643   end
644
645   def filter_factory do
646     %Pleroma.Filter{
647       user: build(:user),
648       filter_id: sequence(:filter_id, & &1),
649       phrase: "cofe",
650       context: ["home"]
651     }
652   end
653
654   def announcement_factory(params \\ %{}) do
655     data = Map.get(params, :data, %{})
656
657     {_, params} = Map.pop(params, :data)
658
659     %Pleroma.Announcement{
660       data: Map.merge(%{"content" => "test announcement", "all_day" => false}, data)
661     }
662     |> Map.merge(params)
663     |> Pleroma.Announcement.add_rendered_properties()
664   end
665 end