Adds username/localname fields
This commit is contained in:
parent
8dfad68ca7
commit
b2b651a22f
|
@ -41,7 +41,7 @@ def get_actor(request, username):
|
||||||
if request.method != 'GET':
|
if request.method != 'GET':
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
user = models.User.objects.get(username=username)
|
user = models.User.objects.get(localname=username)
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
|
@ -50,7 +50,7 @@ def get_actor(request, username):
|
||||||
|
|
||||||
'id': user.actor,
|
'id': user.actor,
|
||||||
'type': 'Person',
|
'type': 'Person',
|
||||||
'preferredUsername': user.username,
|
'preferredUsername': user.localname,
|
||||||
'inbox': format_inbox(user),
|
'inbox': format_inbox(user),
|
||||||
'followers': '%s/followers' % user.actor,
|
'followers': '%s/followers' % user.actor,
|
||||||
'publicKey': {
|
'publicKey': {
|
||||||
|
@ -95,9 +95,11 @@ def handle_account_search(query):
|
||||||
try:
|
try:
|
||||||
user = models.User.objects.get(username=query)
|
user = models.User.objects.get(username=query)
|
||||||
except models.User.DoesNotExist:
|
except models.User.DoesNotExist:
|
||||||
url = 'https://%s/.well-known/webfinger' % domain
|
url = 'https://%s/.well-known/webfinger?resource=acct:%s' % \
|
||||||
params = {'resource': 'acct:%s' % query}
|
(domain, query)
|
||||||
response = requests.get(url, params=params)
|
response = requests.get(url)
|
||||||
|
if not response.ok:
|
||||||
|
response.raise_for_status()
|
||||||
data = response.json()
|
data = response.json()
|
||||||
for link in data['links']:
|
for link in data['links']:
|
||||||
if link['rel'] == 'self':
|
if link['rel'] == 'self':
|
||||||
|
@ -148,7 +150,7 @@ def handle_incoming_follow(activity):
|
||||||
)
|
)
|
||||||
to_follow = models.User.objects.get(username=to_follow)
|
to_follow = models.User.objects.get(username=to_follow)
|
||||||
# figure out who they are
|
# figure out who they are
|
||||||
user = get_or_create_remote_user(activity)
|
user = get_or_create_remote_user(activity['actor'])
|
||||||
to_follow.followers.add(user)
|
to_follow.followers.add(user)
|
||||||
# verify uuid and accept the request
|
# verify uuid and accept the request
|
||||||
models.FollowActivity(
|
models.FollowActivity(
|
||||||
|
@ -184,6 +186,7 @@ def handle_outgoing_follow(user, to_follow):
|
||||||
models.FollowActivity(
|
models.FollowActivity(
|
||||||
uuid=uuid,
|
uuid=uuid,
|
||||||
user=user,
|
user=user,
|
||||||
|
followed=to_follow,
|
||||||
content=activity,
|
content=activity,
|
||||||
).save()
|
).save()
|
||||||
|
|
||||||
|
@ -279,7 +282,7 @@ def handle_review(user, book, name, content, rating):
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def outbox(request, username):
|
def outbox(request, username):
|
||||||
''' outbox for the requested user '''
|
''' outbox for the requested user '''
|
||||||
user = models.User.objects.get(username=username)
|
user = models.User.objects.get(localname=username)
|
||||||
size = models.Review.objects.filter(user=user).count()
|
size = models.Review.objects.filter(user=user).count()
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# list of activities
|
# list of activities
|
||||||
|
@ -305,7 +308,7 @@ def broadcast(sender, action, recipients):
|
||||||
|
|
||||||
def sign_and_send(sender, action, destination):
|
def sign_and_send(sender, action, destination):
|
||||||
''' crpyto whatever and http junk '''
|
''' crpyto whatever and http junk '''
|
||||||
inbox_fragment = '/api/u/%s/inbox' % (sender.username)
|
inbox_fragment = '/api/u/%s/inbox' % (sender.localname)
|
||||||
now = datetime.utcnow().isoformat()
|
now = datetime.utcnow().isoformat()
|
||||||
message_to_sign = '''(request-target): post %s
|
message_to_sign = '''(request-target): post %s
|
||||||
host: https://%s
|
host: https://%s
|
||||||
|
@ -313,7 +316,7 @@ date: %s''' % (inbox_fragment, DOMAIN, now)
|
||||||
signer = pkcs1_15.new(RSA.import_key(sender.private_key))
|
signer = pkcs1_15.new(RSA.import_key(sender.private_key))
|
||||||
signed_message = signer.sign(SHA256.new(message_to_sign.encode('utf8')))
|
signed_message = signer.sign(SHA256.new(message_to_sign.encode('utf8')))
|
||||||
|
|
||||||
signature = 'keyId="%s",' % sender.username
|
signature = 'keyId="%s",' % sender.localname
|
||||||
signature += 'headers="(request-target) host date",'
|
signature += 'headers="(request-target) host date",'
|
||||||
signature += 'signature="%s"' % b64encode(signed_message)
|
signature += 'signature="%s"' % b64encode(signed_message)
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 3.0.2 on 2020-01-28 03:40
|
# Generated by Django 3.0.2 on 2020-01-28 04:47
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
|
@ -37,6 +37,7 @@ class Migration(migrations.Migration):
|
||||||
('api_key', models.CharField(blank=True, max_length=255, null=True)),
|
('api_key', models.CharField(blank=True, max_length=255, null=True)),
|
||||||
('actor', models.CharField(max_length=255)),
|
('actor', models.CharField(max_length=255)),
|
||||||
('local', models.BooleanField(default=True)),
|
('local', models.BooleanField(default=True)),
|
||||||
|
('localname', models.CharField(blank=True, max_length=255, null=True, unique=True)),
|
||||||
('created_date', models.DateTimeField(auto_now_add=True)),
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('updated_date', models.DateTimeField(auto_now=True)),
|
('updated_date', models.DateTimeField(auto_now=True)),
|
||||||
('followers', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
|
('followers', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
|
||||||
|
|
|
@ -15,6 +15,12 @@ class User(AbstractUser):
|
||||||
api_key = models.CharField(max_length=255, blank=True, null=True)
|
api_key = models.CharField(max_length=255, blank=True, null=True)
|
||||||
actor = models.CharField(max_length=255)
|
actor = models.CharField(max_length=255)
|
||||||
local = models.BooleanField(default=True)
|
local = models.BooleanField(default=True)
|
||||||
|
localname = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
unique=True
|
||||||
|
)
|
||||||
# TODO: a field for if non-local users are readers or others
|
# TODO: a field for if non-local users are readers or others
|
||||||
followers = models.ManyToManyField('self', symmetrical=False)
|
followers = models.ManyToManyField('self', symmetrical=False)
|
||||||
created_date = models.DateTimeField(auto_now_add=True)
|
created_date = models.DateTimeField(auto_now_add=True)
|
||||||
|
@ -28,11 +34,16 @@ class User(AbstractUser):
|
||||||
self.private_key = key.export_key().decode('utf8')
|
self.private_key = key.export_key().decode('utf8')
|
||||||
self.public_key = key.publickey().export_key().decode('utf8')
|
self.public_key = key.publickey().export_key().decode('utf8')
|
||||||
|
|
||||||
if self.local and not self.actor:
|
|
||||||
self.actor = 'https://%s/api/u/%s' % (DOMAIN, self.username)
|
|
||||||
if self.local and not re.match(r'\w+@\w+.\w+', self.username):
|
if self.local and not re.match(r'\w+@\w+.\w+', self.username):
|
||||||
|
# set your local username that doesn't have the domain
|
||||||
self.username = '%s@%s' % (self.username, DOMAIN)
|
self.username = '%s@%s' % (self.username, DOMAIN)
|
||||||
|
|
||||||
|
if self.local and not self.localname:
|
||||||
|
self.localname = self.username.replace('@%s' % DOMAIN, '')
|
||||||
|
|
||||||
|
if self.local and not self.actor:
|
||||||
|
self.actor = 'https://%s/api/u/%s' % (DOMAIN, self.localname)
|
||||||
|
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,7 +148,7 @@ class Shelf(models.Model):
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.identifier:
|
if not self.identifier:
|
||||||
self.identifier = '%s_%s' % (
|
self.identifier = '%s_%s' % (
|
||||||
self.user.username,
|
self.user.localname,
|
||||||
re.sub(r'\W', '-', self.name).lower()
|
re.sub(r'\W', '-', self.name).lower()
|
||||||
)
|
)
|
||||||
if not self.activitypub_id:
|
if not self.activitypub_id:
|
||||||
|
|
|
@ -27,7 +27,7 @@ DEBUG = True
|
||||||
|
|
||||||
|
|
||||||
DOMAIN = 'bd352ee8.ngrok.io'
|
DOMAIN = 'bd352ee8.ngrok.io'
|
||||||
ALLOWED_HOSTS = ['localhost', DOMAIN]
|
ALLOWED_HOSTS = ['*']
|
||||||
OL_URL = 'https://openlibrary.org'
|
OL_URL = 'https://openlibrary.org'
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.template.response import TemplateResponse
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from fedireads import models, openlibrary
|
from fedireads import models, openlibrary
|
||||||
from fedireads import federation as api
|
from fedireads import federation as api
|
||||||
|
from fedireads.settings import DOMAIN
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -147,3 +148,7 @@ def search(request):
|
||||||
|
|
||||||
return TemplateResponse(request, 'results.html', {'results': results})
|
return TemplateResponse(request, 'results.html', {'results': results})
|
||||||
|
|
||||||
|
|
||||||
|
def simplify_local_username(user):
|
||||||
|
''' helper for getting the short username for local users '''
|
||||||
|
return user.username.replace('@%s' % DOMAIN, '')
|
||||||
|
|
Loading…
Reference in New Issue