Merge pull request #83 from cthulahoops/approval_table_split
Approval table split
This commit is contained in:
commit
943b793f58
|
@ -201,10 +201,9 @@ def handle_incoming_follow(activity):
|
||||||
user = get_or_create_remote_user(activity['actor'])
|
user = get_or_create_remote_user(activity['actor'])
|
||||||
# TODO: allow users to manually approve requests
|
# TODO: allow users to manually approve requests
|
||||||
try:
|
try:
|
||||||
models.UserRelationship.objects.create(
|
models.UserFollowRequest.objects.create(
|
||||||
user_subject=user,
|
user_subject=user,
|
||||||
user_object=to_follow,
|
user_object=to_follow,
|
||||||
status='follow_request',
|
|
||||||
relationship_id=activity['id']
|
relationship_id=activity['id']
|
||||||
)
|
)
|
||||||
except django.db.utils.IntegrityError:
|
except django.db.utils.IntegrityError:
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
# Generated by Django 3.0.3 on 2020-03-11 12:12
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('fedireads', '0014_status_remote_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserBlocks',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_date', models.DateTimeField(auto_now=True)),
|
||||||
|
('relationship_id', models.CharField(max_length=100)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserFollowRequest',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_date', models.DateTimeField(auto_now=True)),
|
||||||
|
('relationship_id', models.CharField(max_length=100)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserFollows',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_date', models.DateTimeField(auto_now=True)),
|
||||||
|
('relationship_id', models.CharField(max_length=100)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='user',
|
||||||
|
name='followers',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='UserRelationship',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userfollows',
|
||||||
|
name='user_object',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='userfollows_user_object', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userfollows',
|
||||||
|
name='user_subject',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='userfollows_user_subject', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userfollowrequest',
|
||||||
|
name='user_object',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='userfollowrequest_user_object', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userfollowrequest',
|
||||||
|
name='user_subject',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='userfollowrequest_user_subject', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userblocks',
|
||||||
|
name='user_object',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='userblocks_user_object', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userblocks',
|
||||||
|
name='user_subject',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='userblocks_user_subject', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='blocks',
|
||||||
|
field=models.ManyToManyField(related_name='blocked_by', through='fedireads.UserBlocks', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='follow_requests',
|
||||||
|
field=models.ManyToManyField(related_name='follower_requests', through='fedireads.UserFollowRequest', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='following',
|
||||||
|
field=models.ManyToManyField(related_name='followers', through='fedireads.UserFollows', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddConstraint(
|
||||||
|
model_name='userfollows',
|
||||||
|
constraint=models.UniqueConstraint(fields=('user_subject', 'user_object'), name='userfollows_unique'),
|
||||||
|
),
|
||||||
|
migrations.AddConstraint(
|
||||||
|
model_name='userfollowrequest',
|
||||||
|
constraint=models.UniqueConstraint(fields=('user_subject', 'user_object'), name='userfollowrequest_unique'),
|
||||||
|
),
|
||||||
|
migrations.AddConstraint(
|
||||||
|
model_name='userblocks',
|
||||||
|
constraint=models.UniqueConstraint(fields=('user_subject', 'user_object'), name='userblocks_unique'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -2,4 +2,4 @@
|
||||||
from .book import Book, Work, Edition, Author
|
from .book import Book, Work, Edition, Author
|
||||||
from .shelf import Shelf, ShelfBook
|
from .shelf import Shelf, ShelfBook
|
||||||
from .status import Status, Review, Favorite, Tag, Notification
|
from .status import Status, Review, Favorite, Tag, Notification
|
||||||
from .user import User, UserRelationship, FederatedServer
|
from .user import User, FederatedServer, UserFollows, UserFollowRequest, UserBlocks
|
||||||
|
|
|
@ -34,12 +34,26 @@ class User(AbstractUser):
|
||||||
# name is your display name, which you can change at will
|
# name is your display name, which you can change at will
|
||||||
name = models.CharField(max_length=100, blank=True, null=True)
|
name = models.CharField(max_length=100, blank=True, null=True)
|
||||||
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
|
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
|
||||||
followers = models.ManyToManyField(
|
following = models.ManyToManyField(
|
||||||
'self',
|
'self',
|
||||||
symmetrical=False,
|
symmetrical=False,
|
||||||
through='UserRelationship',
|
through='UserFollows',
|
||||||
through_fields=('user_object', 'user_subject'),
|
through_fields=('user_subject', 'user_object'),
|
||||||
related_name='following'
|
related_name='followers'
|
||||||
|
)
|
||||||
|
follow_requests = models.ManyToManyField(
|
||||||
|
'self',
|
||||||
|
symmetrical=False,
|
||||||
|
through='UserFollowRequest',
|
||||||
|
through_fields=('user_subject', 'user_object'),
|
||||||
|
related_name='follower_requests'
|
||||||
|
)
|
||||||
|
blocks = models.ManyToManyField(
|
||||||
|
'self',
|
||||||
|
symmetrical=False,
|
||||||
|
through='UserBlocks',
|
||||||
|
through_fields=('user_subject', 'user_object'),
|
||||||
|
related_name='blocked_by'
|
||||||
)
|
)
|
||||||
favorites = models.ManyToManyField(
|
favorites = models.ManyToManyField(
|
||||||
'Status',
|
'Status',
|
||||||
|
@ -65,22 +79,22 @@ class UserRelationship(FedireadsModel):
|
||||||
user_subject = models.ForeignKey(
|
user_subject = models.ForeignKey(
|
||||||
'User',
|
'User',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='user_subject'
|
related_name='%(class)s_user_subject'
|
||||||
)
|
)
|
||||||
user_object = models.ForeignKey(
|
user_object = models.ForeignKey(
|
||||||
'User',
|
'User',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='user_object'
|
related_name='%(class)s_user_object'
|
||||||
)
|
)
|
||||||
# follow or follow_request for pending TODO: blocking?
|
# follow or follow_request for pending TODO: blocking?
|
||||||
status = models.CharField(max_length=100, default='follows', null=True)
|
|
||||||
relationship_id = models.CharField(max_length=100)
|
relationship_id = models.CharField(max_length=100)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
abstract = True
|
||||||
constraints = [
|
constraints = [
|
||||||
models.UniqueConstraint(
|
models.UniqueConstraint(
|
||||||
fields=['user_subject', 'user_object'],
|
fields=['user_subject', 'user_object'],
|
||||||
name='followers_unique'
|
name='%(class)s_unique'
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -90,6 +104,28 @@ class UserRelationship(FedireadsModel):
|
||||||
base_path = self.user_subject.absolute_id
|
base_path = self.user_subject.absolute_id
|
||||||
return '%s#%s/%d' % (base_path, self.status, self.id)
|
return '%s#%s/%d' % (base_path, self.status, self.id)
|
||||||
|
|
||||||
|
class UserFollows(UserRelationship):
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
return 'follows'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_request(cls, follow_request):
|
||||||
|
return cls(
|
||||||
|
user_subject=follow_request.user_subject,
|
||||||
|
user_object=follow_request.user_object,
|
||||||
|
relationship_id=follow_request.relationship_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
class UserFollowRequest(UserRelationship):
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
return 'follow_request'
|
||||||
|
|
||||||
|
class UserBlocks(UserRelationship):
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
return 'blocks'
|
||||||
|
|
||||||
class FederatedServer(FedireadsModel):
|
class FederatedServer(FedireadsModel):
|
||||||
''' store which server's we federate with '''
|
''' store which server's we federate with '''
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
''' handles all the activity coming out of the server '''
|
''' handles all the activity coming out of the server '''
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError, transaction
|
||||||
from django.http import HttpResponseNotFound, JsonResponse
|
from django.http import HttpResponseNotFound, JsonResponse
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
import requests
|
import requests
|
||||||
|
@ -88,7 +88,7 @@ def handle_outgoing_follow(user, to_follow):
|
||||||
|
|
||||||
def handle_outgoing_unfollow(user, to_unfollow):
|
def handle_outgoing_unfollow(user, to_unfollow):
|
||||||
''' someone local wants to follow someone '''
|
''' someone local wants to follow someone '''
|
||||||
relationship = models.UserRelationship.objects.get(
|
relationship = models.UserFollows.objects.get(
|
||||||
user_subject=user,
|
user_subject=user,
|
||||||
user_object=to_unfollow
|
user_object=to_unfollow
|
||||||
)
|
)
|
||||||
|
@ -101,11 +101,14 @@ def handle_outgoing_unfollow(user, to_unfollow):
|
||||||
|
|
||||||
def handle_outgoing_accept(user, to_follow, request_activity):
|
def handle_outgoing_accept(user, to_follow, request_activity):
|
||||||
''' send an acceptance message to a follow request '''
|
''' send an acceptance message to a follow request '''
|
||||||
relationship = models.UserRelationship.objects.get(
|
with transaction.atomic():
|
||||||
|
follow_request = models.UserFollowRequest.objects.get(
|
||||||
relationship_id=request_activity['id']
|
relationship_id=request_activity['id']
|
||||||
)
|
)
|
||||||
relationship.status = 'follow'
|
relationship = models.UserFollows.from_request(follow_request)
|
||||||
|
follow_request.delete()
|
||||||
relationship.save()
|
relationship.save()
|
||||||
|
|
||||||
activity = activitypub.get_accept(to_follow, request_activity)
|
activity = activitypub.get_accept(to_follow, request_activity)
|
||||||
recipient = get_recipients(to_follow, 'direct', direct_recipients=[user])
|
recipient = get_recipients(to_follow, 'direct', direct_recipients=[user])
|
||||||
broadcast(to_follow, activity, recipient)
|
broadcast(to_follow, activity, recipient)
|
||||||
|
|
Loading…
Reference in New Issue