From ffe81291add13de72f74d27c246eaac6ee204639 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Sat, 14 Mar 2020 22:20:01 +0000 Subject: [PATCH] Use database constraint to prevent relationships with yourself. --- fedireads/incoming.py | 5 ++-- .../migrations/0017_auto_20200314_2152.py | 26 +++++++++++++++++++ fedireads/models/user.py | 4 +++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 fedireads/migrations/0017_auto_20200314_2152.py diff --git a/fedireads/incoming.py b/fedireads/incoming.py index b7f874cb..0ccd4807 100644 --- a/fedireads/incoming.py +++ b/fedireads/incoming.py @@ -128,14 +128,15 @@ def handle_incoming_follow(activity): to_follow = models.User.objects.get(actor=activity['object']) # figure out who they are user = get_or_create_remote_user(activity['actor']) - # TODO: allow users to manually approve requests try: request = models.UserFollowRequest.objects.create( user_subject=user, user_object=to_follow, relationship_id=activity['id'] ) - except django.db.utils.IntegrityError: + except django.db.utils.IntegrityError as err: + if err.__cause__.diag.constraint_name != 'userfollowrequest_unique': + raise # Duplicate follow request. Not sure what the correct behaviour is, but # just dropping it works for now. We should perhaps generate the # Accept, but then do we need to match the activity id? diff --git a/fedireads/migrations/0017_auto_20200314_2152.py b/fedireads/migrations/0017_auto_20200314_2152.py new file mode 100644 index 00000000..4de3e23e --- /dev/null +++ b/fedireads/migrations/0017_auto_20200314_2152.py @@ -0,0 +1,26 @@ +# Generated by Django 3.0.3 on 2020-03-14 21:52 + +from django.db import migrations, models +import django.db.models.expressions + + +class Migration(migrations.Migration): + + dependencies = [ + ('fedireads', '0016_auto_20200313_1337'), + ] + + operations = [ + migrations.AddConstraint( + model_name='userblocks', + constraint=models.CheckConstraint(check=models.Q(_negated=True, user_subject=django.db.models.expressions.F('user_object')), name='userblocks_no_self'), + ), + migrations.AddConstraint( + model_name='userfollowrequest', + constraint=models.CheckConstraint(check=models.Q(_negated=True, user_subject=django.db.models.expressions.F('user_object')), name='userfollowrequest_no_self'), + ), + migrations.AddConstraint( + model_name='userfollows', + constraint=models.CheckConstraint(check=models.Q(_negated=True, user_subject=django.db.models.expressions.F('user_object')), name='userfollows_no_self'), + ), + ] diff --git a/fedireads/models/user.py b/fedireads/models/user.py index 3e00970a..7aecd7b2 100644 --- a/fedireads/models/user.py +++ b/fedireads/models/user.py @@ -95,6 +95,10 @@ class UserRelationship(FedireadsModel): models.UniqueConstraint( fields=['user_subject', 'user_object'], name='%(class)s_unique' + ), + models.CheckConstraint( + check=~models.Q(user_subject=models.F('user_object')), + name='%(class)s_no_self' ) ]