forked from mirrors/bookwyrm
Merge pull request #174 from mouse-reeve/remote-user
Fixes remote user code
This commit is contained in:
commit
b54c6f7855
4 changed files with 101 additions and 13 deletions
|
@ -90,6 +90,7 @@ def shared_inbox(request):
|
|||
|
||||
|
||||
def get_public_key(key_actor):
|
||||
''' try a stored key or load it from remote '''
|
||||
try:
|
||||
user = models.User.objects.get(remote_id=key_actor)
|
||||
public_key = user.public_key
|
||||
|
|
|
@ -4,6 +4,7 @@ from uuid import uuid4
|
|||
import requests
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.db import transaction
|
||||
|
||||
from fedireads import models
|
||||
from fedireads.status import create_review_from_activity
|
||||
|
@ -12,7 +13,7 @@ from fedireads.status import create_review_from_activity
|
|||
def get_or_create_remote_user(actor):
|
||||
''' look up a remote user or add them '''
|
||||
try:
|
||||
return models.User.objects.get(actor=actor)
|
||||
return models.User.objects.get(remote_id=actor)
|
||||
except models.User.DoesNotExist:
|
||||
pass
|
||||
|
||||
|
@ -25,37 +26,50 @@ def get_or_create_remote_user(actor):
|
|||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
# the webfinger format for the username.
|
||||
# make sure our actor is who they say they are
|
||||
assert actor == data['id']
|
||||
|
||||
actor_parts = urlparse(actor)
|
||||
with transaction.atomic():
|
||||
user = create_remote_user(data)
|
||||
user.federated_server = get_or_create_remote_server(actor_parts.netloc)
|
||||
user.save()
|
||||
|
||||
avatar = get_avatar(data)
|
||||
user.avatar.save(*avatar)
|
||||
|
||||
if user.fedireads_user:
|
||||
get_remote_reviews(user)
|
||||
return user
|
||||
|
||||
|
||||
def create_remote_user(data):
|
||||
''' parse the activitypub actor data into a user '''
|
||||
actor = data['id']
|
||||
actor_parts = urlparse(actor)
|
||||
|
||||
# the webfinger format for the username.
|
||||
username = '%s@%s' % (actor_parts.path.split('/')[-1], actor_parts.netloc)
|
||||
|
||||
shared_inbox = data.get('endpoints').get('sharedInbox') if \
|
||||
data.get('endpoints') else None
|
||||
|
||||
server = get_or_create_remote_server(actor_parts.netloc)
|
||||
avatar = get_avatar(data)
|
||||
|
||||
# throws a key error if it can't find any of these fields
|
||||
user = models.User.objects.create_user(
|
||||
return models.User.objects.create_user(
|
||||
username,
|
||||
'', '', # email and passwords are left blank
|
||||
actor=actor,
|
||||
remote_id=actor,
|
||||
name=data.get('name'),
|
||||
summary=data.get('summary'),
|
||||
inbox=data['inbox'], #fail if there's no inbox
|
||||
outbox=data['outbox'], # fail if there's no outbox
|
||||
shared_inbox=shared_inbox,
|
||||
# TODO: I'm never actually using this for remote users
|
||||
public_key=data.get('publicKey').get('publicKeyPem'),
|
||||
local=False,
|
||||
fedireads_user=data.get('fedireadsUser', False),
|
||||
manually_approves_followers=data.get(
|
||||
'manuallyApprovesFollowers', False),
|
||||
federated_server=server,
|
||||
)
|
||||
user.avatar.save(*avatar)
|
||||
if user.fedireads_user:
|
||||
get_remote_reviews(user)
|
||||
return user
|
||||
|
||||
|
||||
def get_avatar(data):
|
||||
|
|
36
fedireads/tests/data/ap_user.json
Normal file
36
fedireads/tests/data/ap_user.json
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"schema": "http://schema.org#",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"value": "schema:value"
|
||||
}
|
||||
],
|
||||
"id": "https://example.com/user/mouse",
|
||||
"type": "Person",
|
||||
"preferredUsername": "mouse",
|
||||
"name": "MOUSE?? MOUSE!!",
|
||||
"inbox": "https://example.com/user/mouse/inbox",
|
||||
"outbox": "https://example.com/user/mouse/outbox",
|
||||
"followers": "https://example.com/user/mouse/followers",
|
||||
"following": "https://example.com/user/mouse/following",
|
||||
"summary": "",
|
||||
"publicKey": {
|
||||
"id": "https://example.com/user/mouse/#main-key",
|
||||
"owner": "https://example.com/user/mouse",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6QisDrjOQvkRo/MqNmSYPwqtt\nCxg/8rCW+9jKbFUKvqjTeKVotEE85122v/DCvobCCdfQuYIFdVMk+dB1xJ0iPGPg\nyU79QHY22NdV9mFKA2qtXVVxb5cxpA4PlwOHM6PM/k8B+H09OUrop2aPUAYwy+vg\n+MXyz8bAXrIS1kq6fQIDAQAB\n-----END PUBLIC KEY-----"
|
||||
},
|
||||
"endpoints": {
|
||||
"sharedInbox": "https://example.com/inbox"
|
||||
},
|
||||
"fedireadsUser": true,
|
||||
"manuallyApprovesFollowers": false,
|
||||
"icon": {
|
||||
"type": "Image",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://example.com/images/avatars/AL-2-crop-50.png"
|
||||
}
|
||||
}
|
37
fedireads/tests/test_remote_user.py
Normal file
37
fedireads/tests/test_remote_user.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
from django.test import TestCase
|
||||
import json
|
||||
import pathlib
|
||||
|
||||
from fedireads import models, remote_user
|
||||
|
||||
|
||||
class RemoteUser(TestCase):
|
||||
''' not too much going on in the books model but here we are '''
|
||||
def setUp(self):
|
||||
self.remote_user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.com', 'mouseword',
|
||||
local=False,
|
||||
remote_id='https://example.com/users/mouse',
|
||||
inbox='https://example.com/users/mouse/inbox',
|
||||
outbox='https://example.com/users/mouse/outbox',
|
||||
)
|
||||
|
||||
def test_get_remote_user(self):
|
||||
actor = 'https://example.com/users/mouse'
|
||||
user = remote_user.get_or_create_remote_user(actor)
|
||||
self.assertEqual(user, self.remote_user)
|
||||
|
||||
|
||||
def test_create_remote_user(self):
|
||||
datafile = pathlib.Path(__file__).parent.joinpath('data/ap_user.json')
|
||||
data = json.loads(datafile.read_bytes())
|
||||
user = remote_user.create_remote_user(data)
|
||||
self.assertEqual(user.username, 'mouse@example.com')
|
||||
self.assertEqual(user.name, 'MOUSE?? MOUSE!!')
|
||||
self.assertEqual(user.inbox, 'https://example.com/user/mouse/inbox')
|
||||
self.assertEqual(user.outbox, 'https://example.com/user/mouse/outbox')
|
||||
self.assertEqual(user.shared_inbox, 'https://example.com/inbox')
|
||||
self.assertEqual(user.public_key, data['publicKey']['publicKeyPem'])
|
||||
self.assertEqual(user.local, False)
|
||||
self.assertEqual(user.fedireads_user, True)
|
||||
self.assertEqual(user.manually_approves_followers, False)
|
Loading…
Reference in a new issue