mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-26 03:21:05 +00:00
search endpoint (user part)
This commit is contained in:
parent
d2d278b475
commit
f7242452fa
6 changed files with 44 additions and 17 deletions
|
@ -19,11 +19,11 @@ def webfinger(request):
|
|||
if not resource and not resource.startswith('acct:'):
|
||||
return HttpResponseBadRequest()
|
||||
ap_id = resource.replace('acct:', '')
|
||||
user = models.User.objects.filter(full_username=ap_id).first()
|
||||
user = models.User.objects.filter(username=ap_id).first()
|
||||
if not user:
|
||||
return HttpResponseNotFound('No account found')
|
||||
return JsonResponse({
|
||||
'subject': 'acct:%s' % (user.full_username),
|
||||
'subject': 'acct:%s' % (user.username),
|
||||
'links': [
|
||||
{
|
||||
'rel': 'self',
|
||||
|
@ -88,6 +88,22 @@ def inbox(request, username):
|
|||
return HttpResponse()
|
||||
|
||||
|
||||
def handle_account_search(query):
|
||||
''' webfingerin' other servers '''
|
||||
domain = query.split('@')[1]
|
||||
try:
|
||||
user = models.User.objects.get(username=query)
|
||||
except models.User.DoesNotExist:
|
||||
url = 'https://%s/.well-known/webfinger' % domain
|
||||
params = {'resource': 'acct:%s' % query}
|
||||
response = requests.get(url, params=params)
|
||||
data = response.json()
|
||||
for link in data['links']:
|
||||
if link['rel'] == 'self':
|
||||
user = get_or_create_remote_user(link['href'])
|
||||
return user
|
||||
|
||||
|
||||
def handle_add(activity):
|
||||
''' receiving an Add activity (to shelve a book) '''
|
||||
# TODO what happens here? If it's a remote over, then I think
|
||||
|
@ -156,7 +172,7 @@ def handle_outgoing_follow(user, to_follow):
|
|||
'summary': '',
|
||||
'type': 'Follow',
|
||||
'actor': user.actor,
|
||||
'object': to_follow,
|
||||
'object': to_follow.actor,
|
||||
}
|
||||
|
||||
broadcast(user, activity, [format_inbox(to_follow)])
|
||||
|
@ -281,6 +297,7 @@ def broadcast(sender, action, recipients):
|
|||
for recipient in recipients:
|
||||
sign_and_send(sender, action, recipient)
|
||||
|
||||
|
||||
def sign_and_send(sender, action, destination):
|
||||
''' crpyto whatever and http junk '''
|
||||
inbox_fragment = '/api/u/%s/inbox' % (sender.username)
|
||||
|
@ -291,7 +308,7 @@ date: %s''' % (inbox_fragment, DOMAIN, now)
|
|||
signer = pkcs1_15.new(RSA.import_key(sender.private_key))
|
||||
signed_message = signer.sign(SHA256.new(message_to_sign.encode('utf8')))
|
||||
|
||||
signature = 'keyId="%s",' % sender.full_username
|
||||
signature = 'keyId="%s",' % sender.username
|
||||
signature += 'headers="(request-target) host date",'
|
||||
signature += 'signature="%s"' % b64encode(signed_message)
|
||||
response = requests.post(
|
||||
|
@ -306,9 +323,9 @@ date: %s''' % (inbox_fragment, DOMAIN, now)
|
|||
if not response.ok:
|
||||
response.raise_for_status()
|
||||
|
||||
def get_or_create_remote_user(activity):
|
||||
|
||||
def get_or_create_remote_user(actor):
|
||||
''' wow, a foreigner '''
|
||||
actor = activity['actor']
|
||||
try:
|
||||
user = models.User.objects.get(actor=actor)
|
||||
except models.User.DoesNotExist:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 3.0.2 on 2020-01-28 02:46
|
||||
# Generated by Django 3.0.2 on 2020-01-28 03:40
|
||||
|
||||
from django.conf import settings
|
||||
import django.contrib.auth.models
|
||||
|
@ -32,7 +32,6 @@ class Migration(migrations.Migration):
|
|||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||
('full_username', models.CharField(blank=True, max_length=255, null=True, unique=True)),
|
||||
('private_key', models.TextField(blank=True, null=True)),
|
||||
('public_key', models.TextField(blank=True, null=True)),
|
||||
('api_key', models.CharField(blank=True, max_length=255, null=True)),
|
||||
|
|
|
@ -10,12 +10,6 @@ import re
|
|||
|
||||
class User(AbstractUser):
|
||||
''' a user who wants to read books '''
|
||||
full_username = models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
null=True,
|
||||
unique=True
|
||||
)
|
||||
private_key = models.TextField(blank=True, null=True)
|
||||
public_key = models.TextField(blank=True, null=True)
|
||||
api_key = models.CharField(max_length=255, blank=True, null=True)
|
||||
|
@ -36,8 +30,8 @@ class User(AbstractUser):
|
|||
|
||||
if self.local and not self.actor:
|
||||
self.actor = 'https://%s/api/u/%s' % (DOMAIN, self.username)
|
||||
if self.local and not self.full_username:
|
||||
self.full_username = '%s@%s' % (self.username, DOMAIN)
|
||||
if self.local and not re.match(r'\w+@\w+.\w+', self.username):
|
||||
self.username = '%s@%s' % (self.username, DOMAIN)
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
<div id="search">
|
||||
<form action="search">
|
||||
<form action="/search/">
|
||||
<input type="text" name="q"></input>
|
||||
<input type="submit" value="🔍"></input>
|
||||
</form>
|
||||
|
|
|
@ -24,10 +24,13 @@ urlpatterns = [
|
|||
path('logout/', views.user_logout),
|
||||
path('user/<str:username>', views.user_profile),
|
||||
path('book/<str:book_identifier>', views.book_page),
|
||||
|
||||
path('review/', views.review),
|
||||
path('shelve/<str:shelf_id>/<int:book_id>', views.shelve),
|
||||
path('follow/', views.follow),
|
||||
path('unfollow/', views.unfollow),
|
||||
path('search/', views.search),
|
||||
|
||||
path('api/u/<str:username>', federation.get_actor),
|
||||
path('api/u/<str:username>/inbox', federation.inbox),
|
||||
path('api/u/<str:username>/outbox', federation.outbox),
|
||||
|
|
|
@ -7,6 +7,7 @@ from django.template.response import TemplateResponse
|
|||
from django.views.decorators.csrf import csrf_exempt
|
||||
from fedireads import models, openlibrary
|
||||
from fedireads import federation as api
|
||||
import re
|
||||
|
||||
@login_required
|
||||
def home(request):
|
||||
|
@ -133,3 +134,16 @@ def unfollow(request):
|
|||
followed.followers.remove(request.user)
|
||||
return redirect('/user/%s' % followed.username)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@login_required
|
||||
def search(request):
|
||||
''' that search bar up top '''
|
||||
query = request.GET.get('q')
|
||||
if re.match(r'\w+@\w+.\w+', query):
|
||||
results = [api.handle_account_search(query)]
|
||||
else:
|
||||
results = []
|
||||
|
||||
return TemplateResponse(request, 'results.html', {'results': results})
|
||||
|
||||
|
|
Loading…
Reference in a new issue