diff --git a/fedireads/broadcast.py b/fedireads/broadcast.py index afd73ab4..49fbeb7f 100644 --- a/fedireads/broadcast.py +++ b/fedireads/broadcast.py @@ -38,7 +38,7 @@ def broadcast(sender, activity, recipients): errors = [] for recipient in recipients: try: - response = sign_and_send(sender, activity, recipient) + sign_and_send(sender, activity, recipient) except requests.exceptions.HTTPError as e: # TODO: maybe keep track of users who cause errors errors.append({ diff --git a/fedireads/incoming.py b/fedireads/incoming.py index 6adde34a..786163f2 100644 --- a/fedireads/incoming.py +++ b/fedireads/incoming.py @@ -36,17 +36,18 @@ def shared_inbox(request): if activity['type'] == 'Add': response = handle_incoming_shelve(activity) - if activity['type'] == 'Follow': + elif activity['type'] == 'Follow': response = handle_incoming_follow(activity) - if activity['type'] == 'Create': + elif activity['type'] == 'Create': response = handle_incoming_create(activity) - if activity['type'] == 'Accept': + elif activity['type'] == 'Accept': response = handle_incoming_follow_accept(activity) - return response + # TODO: Undo, Remove, etc + return response def verify_signature(request): @@ -156,8 +157,6 @@ def get_status(request, username, status_id): return JsonResponse(status.activity) - - @csrf_exempt def get_followers(request, username): ''' return a list of followers for an actor ''' @@ -194,6 +193,7 @@ def format_follow_info(user, page, follow_queryset): 'first': '%s?page=1' % id_slug, }) + def get_follow_page(user_list, id_slug, page): ''' format a list of followers/following ''' page = int(page) @@ -243,15 +243,7 @@ def handle_incoming_shelve(activity): def handle_incoming_follow(activity): - ''' - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://friend.camp/768222ce-a1c7-479c-a544-c93b8b67fb54", - "type": "Follow", - "actor": "https://friend.camp/users/tripofmice", - "object": "https://ff2cb3e9.ngrok.io/api/u/mouse" - } - ''' + ''' someone wants to follow a local user ''' # figure out who they want to follow to_follow = models.User.objects.get(actor=activity['object']) # figure out who they are @@ -267,7 +259,6 @@ def handle_incoming_follow(activity): return HttpResponse() - def handle_incoming_follow_accept(activity): ''' hurray, someone remote accepted a follow request ''' # figure out who they want to follow @@ -320,7 +311,6 @@ def handle_incoming_create(activity): return response - def handle_incoming_accept(activity): ''' someone is accepting a follow request ''' # our local user diff --git a/fedireads/outgoing.py b/fedireads/outgoing.py index 016aa703..72e906f5 100644 --- a/fedireads/outgoing.py +++ b/fedireads/outgoing.py @@ -1,4 +1,8 @@ ''' handles all the activity coming out of the server ''' +from base64 import b64encode +from Crypto.PublicKey import RSA +from Crypto.Signature import pkcs1_15 +from Crypto.Hash import SHA256 from datetime import datetime from django.http import HttpResponseNotFound, JsonResponse from django.views.decorators.csrf import csrf_exempt @@ -224,11 +228,12 @@ def handle_review(user, book, name, content, rating): (DOMAIN, user.localname, review.id) book_path = 'https://%s/book/%s' % (DOMAIN, review.book.openlibrary_key) + now = datetime.utcnow().isoformat() #TODO: should this be http_date? review_activity = { 'id': review_path, 'url': review_path, 'inReplyTo': book_path, - 'published': datetime.utcnow().isoformat(), + 'published': now, 'attributedTo': user.actor, # TODO: again, assuming all posts are public 'to': ['https://www.w3.org/ns/activitystreams#Public'], @@ -255,19 +260,26 @@ def handle_review(user, book, name, content, rating): review.activity = review_activity review.save() + signer = pkcs1_15.new(RSA.import_key(user.private_key)) + signed_message = signer.sign(SHA256.new(content.encode('utf8'))) create_activity = { '@context': 'https://www.w3.org/ns/activitystreams', 'id': '%s/activity' % review_path, 'type': 'Create', 'actor': user.actor, - 'published': datetime.utcnow().isoformat(), + 'published': now, 'to': ['%s/followers' % user.actor], 'cc': ['https://www.w3.org/ns/activitystreams#Public'], 'object': review_activity, - # TODO: signature + 'signature': { + 'type': 'RsaSignature2017', + 'creator': 'https://%s/user/%s#main-key' % (DOMAIN, user.localname), + 'created': now, + 'signatureValue': b64encode(signed_message).decode('utf8'), + } } recipients = get_recipients(user, 'public') diff --git a/fedireads/templates/feed.html b/fedireads/templates/feed.html index dd2fb873..6b8f2689 100644 --- a/fedireads/templates/feed.html +++ b/fedireads/templates/feed.html @@ -86,6 +86,9 @@ {% elif activity.activity_type == 'Follow' %} started following someone + {% elif activity.activity_type == 'Note' %} + posted + {{ activity.content.object.content | safe }} {% else %} {# generic handling for a misc activity, which perhaps should not be displayed at all #} did {{ activity.activity_type }}