forked from mirrors/bookwyrm
Federating lists and shelves
This commit is contained in:
parent
c7914d1394
commit
e53b4e57fa
8 changed files with 74 additions and 29 deletions
|
@ -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'
|
||||
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class Create(Verb):
|
|||
''' Create activity '''
|
||||
to: List
|
||||
cc: List
|
||||
signature: Signature
|
||||
signature: Signature = None
|
||||
type: str = 'Create'
|
||||
|
||||
|
||||
|
|
|
@ -161,16 +161,18 @@ class ActivitypubMixin:
|
|||
''' returns the object wrapped in a Create activity '''
|
||||
activity_object = self.to_activity(**kwargs)
|
||||
|
||||
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')))
|
||||
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')))
|
||||
|
||||
signature = activitypub.Signature(
|
||||
creator='%s#main-key' % user.remote_id,
|
||||
created=activity_object['published'],
|
||||
signatureValue=b64encode(signed_message).decode('utf8')
|
||||
)
|
||||
signature = activitypub.Signature(
|
||||
creator='%s#main-key' % user.remote_id,
|
||||
created=activity_object['published'],
|
||||
signatureValue=b64encode(signed_message).decode('utf8')
|
||||
)
|
||||
|
||||
return activitypub.Create(
|
||||
id=create_id,
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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', '/'))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in a new issue