factories.py 7.71 KB
Newer Older
Eliot Berriot's avatar
Eliot Berriot committed
1
2
import uuid

3
4
5
import factory
import requests
import requests_http_signature
Eliot Berriot's avatar
Eliot Berriot committed
6
from django.conf import settings
Eliot Berriot's avatar
Eliot Berriot committed
7
from django.utils import timezone
8
from django.utils.http import http_date
9

10
from funkwhale_api.factories import registry
11
from funkwhale_api.users import factories as user_factories
12

Eliot Berriot's avatar
Eliot Berriot committed
13
from . import keys, models
14

Eliot Berriot's avatar
Eliot Berriot committed
15
registry.register(keys.get_key_pair, name="federation.KeyPair")
16
17


Eliot Berriot's avatar
Eliot Berriot committed
18
@registry.register(name="federation.SignatureAuth")
19
class SignatureAuthFactory(factory.Factory):
Eliot Berriot's avatar
Eliot Berriot committed
20
    algorithm = "rsa-sha256"
21
    key = factory.LazyFunction(lambda: keys.get_key_pair()[0])
Eliot Berriot's avatar
Eliot Berriot committed
22
    key_id = factory.Faker("url")
23
    use_auth_header = False
Eliot Berriot's avatar
Eliot Berriot committed
24
25
    headers = ["(request-target)", "user-agent", "host", "date", "content-type"]

26
27
28
29
    class Meta:
        model = requests_http_signature.HTTPSignatureAuth


Eliot Berriot's avatar
Eliot Berriot committed
30
@registry.register(name="federation.SignedRequest")
31
class SignedRequestFactory(factory.Factory):
Eliot Berriot's avatar
Eliot Berriot committed
32
33
    url = factory.Faker("url")
    method = "get"
34
35
36
37
    auth = factory.SubFactory(SignatureAuthFactory)

    class Meta:
        model = requests.Request
38
39
40
41

    @factory.post_generation
    def headers(self, create, extracted, **kwargs):
        default_headers = {
Eliot Berriot's avatar
Eliot Berriot committed
42
43
            "User-Agent": "Test",
            "Host": "test.host",
44
            "Date": http_date(timezone.now().timestamp()),
Eliot Berriot's avatar
Eliot Berriot committed
45
            "Content-Type": "application/activity+json",
46
47
48
49
50
51
        }
        if extracted:
            default_headers.update(extracted)
        self.headers.update(default_headers)


Eliot Berriot's avatar
Eliot Berriot committed
52
@registry.register(name="federation.Link")
Eliot Berriot's avatar
Eliot Berriot committed
53
class LinkFactory(factory.Factory):
Eliot Berriot's avatar
Eliot Berriot committed
54
55
56
    type = "Link"
    href = factory.Faker("url")
    mediaType = "text/html"
Eliot Berriot's avatar
Eliot Berriot committed
57
58
59
60
61

    class Meta:
        model = dict

    class Params:
Eliot Berriot's avatar
Eliot Berriot committed
62
        audio = factory.Trait(mediaType=factory.Iterator(["audio/mp3", "audio/ogg"]))
Eliot Berriot's avatar
Eliot Berriot committed
63
64


65
66
67
68
def create_user(actor):
    return user_factories.UserFactory(actor=actor)


Eliot Berriot's avatar
Eliot Berriot committed
69
70
71
72
@registry.register
class ActorFactory(factory.DjangoModelFactory):
    public_key = None
    private_key = None
Eliot Berriot's avatar
Eliot Berriot committed
73
74
75
    preferred_username = factory.Faker("user_name")
    summary = factory.Faker("paragraph")
    domain = factory.Faker("domain_name")
76
    fid = factory.LazyAttribute(
Eliot Berriot's avatar
Eliot Berriot committed
77
78
79
80
81
82
83
84
        lambda o: "https://{}/users/{}".format(o.domain, o.preferred_username)
    )
    inbox_url = factory.LazyAttribute(
        lambda o: "https://{}/users/{}/inbox".format(o.domain, o.preferred_username)
    )
    outbox_url = factory.LazyAttribute(
        lambda o: "https://{}/users/{}/outbox".format(o.domain, o.preferred_username)
    )
Eliot Berriot's avatar
Eliot Berriot committed
85
86
87
88

    class Meta:
        model = models.Actor

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
    @factory.post_generation
    def local(self, create, extracted, **kwargs):
        if not extracted and not kwargs:
            return
        from funkwhale_api.users.factories import UserFactory

        self.domain = settings.FEDERATION_HOSTNAME
        self.save(update_fields=["domain"])
        if not create:
            if extracted and hasattr(extracted, "pk"):
                extracted.actor = self
            else:
                UserFactory.build(actor=self, **kwargs)
        if extracted and hasattr(extracted, "pk"):
            extracted.actor = self
            extracted.save(update_fields=["user"])
        else:
            self.user = UserFactory(actor=self, **kwargs)

    @factory.post_generation
    def keys(self, create, extracted, **kwargs):
        if not create:
            # Simple build, do nothing.
            return
        if not extracted:
114
            private, public = keys.get_key_pair()
115
116
            self.private_key = private.decode("utf-8")
            self.public_key = public.decode("utf-8")
117
118


Eliot Berriot's avatar
Eliot Berriot committed
119
120
121
122
123
124
125
126
@registry.register
class FollowFactory(factory.DjangoModelFactory):
    target = factory.SubFactory(ActorFactory)
    actor = factory.SubFactory(ActorFactory)

    class Meta:
        model = models.Follow

Eliot Berriot's avatar
Eliot Berriot committed
127
    class Params:
Eliot Berriot's avatar
Eliot Berriot committed
128
        local = factory.Trait(actor=factory.SubFactory(ActorFactory, local=True))
Eliot Berriot's avatar
Eliot Berriot committed
129

Eliot Berriot's avatar
Eliot Berriot committed
130

131
@registry.register
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
class MusicLibraryFactory(factory.django.DjangoModelFactory):
    actor = factory.SubFactory(ActorFactory)
    privacy_level = "me"
    name = factory.Faker("sentence")
    description = factory.Faker("sentence")
    files_count = 0

    class Meta:
        model = "music.Library"

    @factory.post_generation
    def fid(self, create, extracted, **kwargs):
        if not create:
            # Simple build, do nothing.
            return

        self.fid = extracted or self.get_federation_id()

    @factory.post_generation
    def followers_url(self, create, extracted, **kwargs):
        if not create:
            # Simple build, do nothing.
            return

        self.followers_url = extracted or self.fid + "/followers"


@registry.register
class LibraryScan(factory.django.DjangoModelFactory):
    library = factory.SubFactory(MusicLibraryFactory)
    actor = factory.SubFactory(ActorFactory)
    total_files = factory.LazyAttribute(lambda o: o.library.files_count)

    class Meta:
        model = "music.LibraryScan"


@registry.register
class ActivityFactory(factory.django.DjangoModelFactory):
171
    actor = factory.SubFactory(ActorFactory)
Eliot Berriot's avatar
Eliot Berriot committed
172
    url = factory.Faker("url")
173
    payload = factory.LazyFunction(lambda: {"type": "Create"})
174
175

    class Meta:
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
        model = "federation.Activity"


@registry.register
class InboxItemFactory(factory.django.DjangoModelFactory):
    actor = factory.SubFactory(ActorFactory)
    activity = factory.SubFactory(ActivityFactory)
    type = "to"

    class Meta:
        model = "federation.InboxItem"


@registry.register
class LibraryFollowFactory(factory.DjangoModelFactory):
    target = factory.SubFactory(MusicLibraryFactory)
    actor = factory.SubFactory(ActorFactory)

    class Meta:
        model = "federation.LibraryFollow"
196
197


198
class ArtistMetadataFactory(factory.Factory):
Eliot Berriot's avatar
Eliot Berriot committed
199
    name = factory.Faker("name")
200
201
202
203
204

    class Meta:
        model = dict

    class Params:
Eliot Berriot's avatar
Eliot Berriot committed
205
        musicbrainz = factory.Trait(musicbrainz_id=factory.Faker("uuid4"))
206
207
208


class ReleaseMetadataFactory(factory.Factory):
Eliot Berriot's avatar
Eliot Berriot committed
209
    title = factory.Faker("sentence")
210
211
212
213
214

    class Meta:
        model = dict

    class Params:
Eliot Berriot's avatar
Eliot Berriot committed
215
        musicbrainz = factory.Trait(musicbrainz_id=factory.Faker("uuid4"))
216
217
218


class RecordingMetadataFactory(factory.Factory):
Eliot Berriot's avatar
Eliot Berriot committed
219
    title = factory.Faker("sentence")
220
221
222
223
224

    class Meta:
        model = dict

    class Params:
Eliot Berriot's avatar
Eliot Berriot committed
225
        musicbrainz = factory.Trait(musicbrainz_id=factory.Faker("uuid4"))
226
227


Eliot Berriot's avatar
Eliot Berriot committed
228
@registry.register(name="federation.LibraryTrackMetadata")
229
230
231
232
233
234
235
236
237
class LibraryTrackMetadataFactory(factory.Factory):
    artist = factory.SubFactory(ArtistMetadataFactory)
    recording = factory.SubFactory(RecordingMetadataFactory)
    release = factory.SubFactory(ReleaseMetadataFactory)

    class Meta:
        model = dict


Eliot Berriot's avatar
Eliot Berriot committed
238
@registry.register(name="federation.Note")
239
class NoteFactory(factory.Factory):
Eliot Berriot's avatar
Eliot Berriot committed
240
241
242
    type = "Note"
    id = factory.Faker("url")
    published = factory.LazyFunction(lambda: timezone.now().isoformat())
243
    inReplyTo = None
Eliot Berriot's avatar
Eliot Berriot committed
244
    content = factory.Faker("sentence")
245
246
247

    class Meta:
        model = dict
Eliot Berriot's avatar
Eliot Berriot committed
248
249


Eliot Berriot's avatar
Eliot Berriot committed
250
@registry.register(name="federation.AudioMetadata")
Eliot Berriot's avatar
Eliot Berriot committed
251
252
class AudioMetadataFactory(factory.Factory):
    recording = factory.LazyAttribute(
Eliot Berriot's avatar
Eliot Berriot committed
253
        lambda o: "https://musicbrainz.org/recording/{}".format(uuid.uuid4())
Eliot Berriot's avatar
Eliot Berriot committed
254
255
    )
    artist = factory.LazyAttribute(
Eliot Berriot's avatar
Eliot Berriot committed
256
        lambda o: "https://musicbrainz.org/artist/{}".format(uuid.uuid4())
Eliot Berriot's avatar
Eliot Berriot committed
257
258
    )
    release = factory.LazyAttribute(
Eliot Berriot's avatar
Eliot Berriot committed
259
        lambda o: "https://musicbrainz.org/release/{}".format(uuid.uuid4())
Eliot Berriot's avatar
Eliot Berriot committed
260
    )
261
262
263
    bitrate = 42
    length = 43
    size = 44
Eliot Berriot's avatar
Eliot Berriot committed
264
265
266
267
268

    class Meta:
        model = dict


Eliot Berriot's avatar
Eliot Berriot committed
269
@registry.register(name="federation.Audio")
Eliot Berriot's avatar
Eliot Berriot committed
270
class AudioFactory(factory.Factory):
Eliot Berriot's avatar
Eliot Berriot committed
271
272
273
274
    type = "Audio"
    id = factory.Faker("url")
    published = factory.LazyFunction(lambda: timezone.now().isoformat())
    actor = factory.Faker("url")
Eliot Berriot's avatar
Eliot Berriot committed
275
    url = factory.SubFactory(LinkFactory, audio=True)
276
    metadata = factory.SubFactory(LibraryTrackMetadataFactory)
Eliot Berriot's avatar
Eliot Berriot committed
277
278
279

    class Meta:
        model = dict