diff --git a/api/funkwhale_api/federation/activity.py b/api/funkwhale_api/federation/activity.py index 3b7648f10..5a0974011 100644 --- a/api/funkwhale_api/federation/activity.py +++ b/api/funkwhale_api/federation/activity.py @@ -52,7 +52,7 @@ OBJECT_TYPES = [ 'Relationship', 'Tombstone', 'Video', -] +] + ACTIVITY_TYPES def deliver(activity, on_behalf_of, to=[]): from . import actors diff --git a/api/funkwhale_api/federation/actors.py b/api/funkwhale_api/federation/actors.py index 031526f8b..22b231e08 100644 --- a/api/funkwhale_api/federation/actors.py +++ b/api/funkwhale_api/federation/actors.py @@ -243,6 +243,7 @@ class TestActor(SystemActor): # on a follow we: # 1. send the accept answer # 2. follow back + # test_actor = self.get_actor_instance() accept_uuid = uuid.uuid4() accept = activity.get_accept_follow( @@ -254,6 +255,12 @@ class TestActor(SystemActor): accept, to=[ac['actor']], on_behalf_of=test_actor) + # we persist the sender in database + sender.save() + models.Follow.objects.get_or_create( + actor=sender, + target=test_actor, + ) follow_uuid = uuid.uuid4() follow = activity.get_follow( follow_id=follow_uuid, diff --git a/api/funkwhale_api/federation/factories.py b/api/funkwhale_api/federation/factories.py index 6e621c7f3..217b47218 100644 --- a/api/funkwhale_api/federation/factories.py +++ b/api/funkwhale_api/federation/factories.py @@ -53,7 +53,6 @@ class SignedRequestFactory(factory.Factory): @registry.register class ActorFactory(factory.DjangoModelFactory): - public_key = None private_key = None preferred_username = factory.Faker('user_name') @@ -77,6 +76,15 @@ class ActorFactory(factory.DjangoModelFactory): return super()._generate(create, attrs) +@registry.register +class FollowFactory(factory.DjangoModelFactory): + target = factory.SubFactory(ActorFactory) + actor = factory.SubFactory(ActorFactory) + + class Meta: + model = models.Follow + + @registry.register(name='federation.Note') class NoteFactory(factory.Factory): type = 'Note' diff --git a/api/funkwhale_api/federation/migrations/0003_auto_20180403_1921.py b/api/funkwhale_api/federation/migrations/0003_auto_20180403_1921.py new file mode 100644 index 000000000..aadf3257e --- /dev/null +++ b/api/funkwhale_api/federation/migrations/0003_auto_20180403_1921.py @@ -0,0 +1,31 @@ +# Generated by Django 2.0.3 on 2018-04-03 19:21 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('federation', '0002_auto_20180403_1620'), + ] + + operations = [ + migrations.CreateModel( + name='Follow', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, unique=True)), + ('creation_date', models.DateTimeField(default=django.utils.timezone.now)), + ('last_modification_date', models.DateTimeField(default=django.utils.timezone.now)), + ('actor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='emitted_follows', to='federation.Actor')), + ('target', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='received_follows', to='federation.Actor')), + ], + ), + migrations.AlterUniqueTogether( + name='follow', + unique_together={('actor', 'target')}, + ), + ] diff --git a/api/funkwhale_api/federation/models.py b/api/funkwhale_api/federation/models.py index 414bcc50a..875268bca 100644 --- a/api/funkwhale_api/federation/models.py +++ b/api/funkwhale_api/federation/models.py @@ -1,3 +1,5 @@ +import uuid + from django.conf import settings from django.db import models from django.utils import timezone @@ -74,3 +76,23 @@ class Actor(models.Model): from . import actors if self.is_system: return actors.SYSTEM_ACTORS[self.preferred_username] + + +class Follow(models.Model): + uuid = models.UUIDField(default=uuid.uuid4, unique=True) + actor = models.ForeignKey( + Actor, + related_name='emitted_follows', + on_delete=models.CASCADE, + ) + target = models.ForeignKey( + Actor, + related_name='received_follows', + on_delete=models.CASCADE, + ) + creation_date = models.DateTimeField(default=timezone.now) + last_modification_date = models.DateTimeField( + default=timezone.now) + + class Meta: + unique_together = ['actor', 'target'] diff --git a/api/tests/federation/test_actors.py b/api/tests/federation/test_actors.py index f0d8f7840..d50b52ee6 100644 --- a/api/tests/federation/test_actors.py +++ b/api/tests/federation/test_actors.py @@ -313,3 +313,7 @@ def test_test_actor_handles_follow( ) ] deliver.assert_has_calls(expected_calls) + + follow = test_actor.received_follows.first() + assert follow.actor == actor + assert follow.target == test_actor diff --git a/api/tests/federation/test_models.py b/api/tests/federation/test_models.py new file mode 100644 index 000000000..297fe2c58 --- /dev/null +++ b/api/tests/federation/test_models.py @@ -0,0 +1,25 @@ +import pytest + +from django import db + +from funkwhale_api.federation import models + + +def test_cannot_duplicate_actor(factories): + actor = factories['federation.Actor']() + + with pytest.raises(db.IntegrityError): + factories['federation.Actor']( + domain=actor.domain, + preferred_username=actor.preferred_username, + ) + + +def test_cannot_duplicate_follow(factories): + follow = factories['federation.Follow']() + + with pytest.raises(db.IntegrityError): + factories['federation.Follow']( + target=follow.target, + actor=follow.actor, + )