Federating lists and shelves

This commit is contained in:
Mouse Reeve 2021-02-02 09:37:46 -08:00
parent c7914d1394
commit e53b4e57fa
8 changed files with 74 additions and 29 deletions

View file

@ -1,5 +1,5 @@
''' defines activitypub collections (lists) '''
from dataclasses import dataclass
from dataclasses import dataclass, field
from typing import List
from .base_activity import ActivityObject
@ -10,9 +10,12 @@ class OrderedCollection(ActivityObject):
''' structure of an ordered collection activity '''
totalItems: int
first: str
last: str = ''
name: str = ''
owner: str = ''
last: str = None
name: str = None
summary: str = None
owner: str = None
to: List[str] = field(default_factory=lambda: [])
cc: List[str] = field(default_factory=lambda: [])
type: str = 'OrderedCollection'

View file

@ -18,7 +18,7 @@ class Create(Verb):
''' Create activity '''
to: List
cc: List
signature: Signature
signature: Signature = None
type: str = 'Create'

View file

@ -161,10 +161,12 @@ class ActivitypubMixin:
''' returns the object wrapped in a Create activity '''
activity_object = self.to_activity(**kwargs)
signature = None
create_id = self.remote_id + '/activity'
if 'content' in activity_object:
signer = pkcs1_15.new(RSA.import_key(user.key_pair.private_key))
content = activity_object['content']
signed_message = signer.sign(SHA256.new(content.encode('utf8')))
create_id = self.remote_id + '/activity'
signature = activitypub.Signature(
creator='%s#main-key' % user.remote_id,

View file

@ -19,12 +19,9 @@ class List(OrderedCollectionMixin, BookWyrmModel):
name = fields.CharField(max_length=100)
user = fields.ForeignKey(
'User', on_delete=models.PROTECT, activitypub_field='owner')
description = fields.TextField(blank=True, null=True)
privacy = fields.CharField(
max_length=255,
default='public',
choices=fields.PrivacyLevels.choices
)
description = fields.TextField(
blank=True, null=True, activitypub_field='summary')
privacy = fields.PrivacyField()
curation = fields.CharField(
max_length=255,
default='closed',

View file

@ -15,11 +15,7 @@ class Shelf(OrderedCollectionMixin, BookWyrmModel):
user = fields.ForeignKey(
'User', on_delete=models.PROTECT, activitypub_field='owner')
editable = models.BooleanField(default=True)
privacy = fields.CharField(
max_length=255,
default='public',
choices=fields.PrivacyLevels.choices
)
privacy = fields.PrivacyField()
books = models.ManyToManyField(
'Edition',
symmetrical=False,

View file

@ -71,10 +71,15 @@ class Goal(View):
broadcast(
request.user,
status.to_create_activity(request.user),
privacy=status.privacy,
software='bookwyrm')
# re-format the activity for non-bookwyrm servers
remote_activity = status.to_create_activity(request.user, pure=True)
broadcast(request.user, remote_activity, software='other')
broadcast(
request.user,
remote_activity,
privacy=status.privacy,
software='other')
return redirect(request.headers.get('Referer', '/'))

View file

@ -11,6 +11,7 @@ from django.views.decorators.http import require_POST
from bookwyrm import forms, models
from bookwyrm.activitypub import ActivitypubResponse
from bookwyrm.broadcast import broadcast
from bookwyrm.connectors import connector_manager
from .helpers import is_api_request, object_visible_to_user, privacy_filter
from .helpers import get_user_from_username
@ -48,6 +49,14 @@ class Lists(View):
if not form.is_valid():
return redirect('lists')
book_list = form.save()
# let the world know
broadcast(
request.user,
book_list.to_create_activity(request.user),
privacy=book_list.privacy,
software='bookwyrm'
)
return redirect(book_list.local_path)
class UserLists(View):
@ -128,6 +137,13 @@ class List(View):
if not form.is_valid():
return redirect('list', book_list.id)
book_list = form.save()
# let the world know
broadcast(
request.user,
book_list.to_update_activity(request.user),
privacy=book_list.privacy,
software='bookwyrm'
)
return redirect(book_list.local_path)
@ -161,6 +177,13 @@ class Curate(View):
if approved:
suggestion.approved = True
suggestion.save()
# let the world know
broadcast(
request.user,
suggestion.to_add_activity(request.user),
privacy=book_list.privacy,
software='bookwyrm'
)
else:
suggestion.delete()
return redirect('list-curate', book_list.id)
@ -177,11 +200,18 @@ def add_book(request, list_id):
# do you have permission to add to the list?
if request.user == book_list.user or book_list.curation == 'open':
# go ahead and add it
models.ListItem.objects.create(
item = models.ListItem.objects.create(
book=book,
book_list=book_list,
added_by=request.user,
)
# let the world know
broadcast(
request.user,
item.to_add_activity(request.user),
privacy=book_list.privacy,
software='bookwyrm'
)
elif book_list.curation == 'curated':
# make a pending entry
models.ListItem.objects.create(
@ -206,5 +236,13 @@ def remove_book(request, list_id):
if not book_list.user == request.user and not item.added_by == request.user:
return HttpResponseNotFound()
activity = item.to_remove_activity(request.user)
item.delete()
# let the world know
broadcast(
request.user,
activity,
privacy=book_list.privacy,
software='bookwyrm'
)
return redirect('list', list_id)

View file

@ -138,7 +138,12 @@ def shelve(request):
pass
shelfbook = models.ShelfBook.objects.create(
book=book, shelf=desired_shelf, added_by=request.user)
broadcast(request.user, shelfbook.to_add_activity(request.user))
broadcast(
request.user,
shelfbook.to_add_activity(request.user),
privacy=shelfbook.shelf.privacy,
software='bookwyrm'
)
# post about "want to read" shelves
if desired_shelf.identifier == 'to-read':
@ -146,7 +151,6 @@ def shelve(request):
request.user,
desired_shelf,
book,
privacy=desired_shelf.privacy
)
return redirect('/')
@ -169,4 +173,4 @@ def handle_unshelve(user, book, shelf):
activity = row.to_remove_activity(user)
row.delete()
broadcast(user, activity)
broadcast(user, activity, privacy=shelf.privacy, software='bookwyrm')