Replace the previous WebFinger implementation with a fairly simple forwarder to Bridgy Fed, so that Bridgy Fed will work eventually
This commit is contained in:
parent
9f3cbac3c4
commit
46c2224a4f
2 changed files with 50 additions and 37 deletions
|
@ -84,7 +84,11 @@ class User(ModelMeta, AbstractUser):
|
||||||
return '{0} {1}'.format(self.first_name, self.last_name)
|
return '{0} {1}'.format(self.first_name, self.last_name)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return self.url
|
return self.absolute_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def absolute_url(self):
|
||||||
|
return self.full_url
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def full_url(self):
|
def full_url(self):
|
||||||
|
|
|
@ -1,50 +1,59 @@
|
||||||
from django.http import HttpResponseBadRequest, HttpResponseNotFound
|
from django.http import HttpResponseBadRequest, HttpResponseRedirect
|
||||||
from django.http import JsonResponse
|
from urllib.parse import urlencode, urlparse
|
||||||
|
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from django.shortcuts import get_object_or_404
|
|
||||||
from urllib.parse import urlparse, urljoin
|
|
||||||
from lemoncurry.utils import origin
|
|
||||||
|
|
||||||
AVATAR = 'http://webfinger.net/rel/avatar'
|
AVATAR = 'http://webfinger.net/rel/avatar'
|
||||||
PROFILE_PAGE = 'http://webfinger.net/rel/profile-page'
|
PROFILE_PAGE = 'http://webfinger.net/rel/profile-page'
|
||||||
|
BRIDGY_FED = 'https://fed.brid.gy/.well-known/webfinger'
|
||||||
|
|
||||||
|
|
||||||
|
def https_resource_matching(resource):
|
||||||
|
"""
|
||||||
|
Takes a `urllib.parse.urlparse` tuple representing a WebFinger resource and
|
||||||
|
translates ``mailto:`` and ``xmpp:`` resources to an equivalent ``https:``
|
||||||
|
resource, if a user with matching email or XMPP address exists locally.
|
||||||
|
Will throw `User.DoesNotExist` if no such user exists.
|
||||||
|
"""
|
||||||
|
if resource.scheme == 'mailto':
|
||||||
|
query = {'email': resource.path}
|
||||||
|
else:
|
||||||
|
query = {'xmpp': resource.path}
|
||||||
|
return User.objects.get(**query).absolute_url
|
||||||
|
|
||||||
|
|
||||||
def webfinger(request):
|
def webfinger(request):
|
||||||
|
"""
|
||||||
|
A thin wrapper around Bridgy Fed's implementation of WebFinger.
|
||||||
|
|
||||||
|
In most cases, this view simply redirects to the same endpoint at Bridgy.
|
||||||
|
However, Bridgy does not support the ``mailto:`` and ``xmpp:`` resource
|
||||||
|
schemes - quite reasonably, since there's no possible way to discover the
|
||||||
|
``acct:`` they go with! - so resources with those schemes are translated
|
||||||
|
locally into an ``https:`` URL representing the same person, and *then*
|
||||||
|
redirected to Bridgy.
|
||||||
|
|
||||||
|
Additionally, WebFinger requests with a missing or malformed resource will
|
||||||
|
be rejected immediately rather than passed on to Bridgy.
|
||||||
|
|
||||||
|
Note that the translation step will only be applied if there exists a
|
||||||
|
:model:`users.User` with matching email or XMPP address. Otherwise, the
|
||||||
|
original resource will be preserved in the redirect - and likely fail to
|
||||||
|
find anything at Bridgy's end either.
|
||||||
|
"""
|
||||||
if 'resource' not in request.GET:
|
if 'resource' not in request.GET:
|
||||||
return HttpResponseBadRequest('resource parameter missing')
|
return HttpResponseBadRequest('resource parameter missing')
|
||||||
|
resource = request.GET['resource']
|
||||||
try:
|
try:
|
||||||
resource = urlparse(request.GET['resource'])
|
res = urlparse(resource)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return HttpResponseBadRequest('resource parameter malformed')
|
return HttpResponseBadRequest('resource parameter malformed')
|
||||||
|
|
||||||
if resource.scheme in ('mailto', 'acct', 'xmpp'):
|
if res.scheme in ('mailto', 'xmpp'):
|
||||||
user = get_object_or_404(User, email=resource.path)
|
try:
|
||||||
elif resource.scheme in ('http', 'https'):
|
resource = https_resource_matching(res)
|
||||||
user = get_object_or_404(User, pk=1)
|
except User.DoesNotExist:
|
||||||
else:
|
pass
|
||||||
return HttpResponseNotFound('resource not found on this server')
|
|
||||||
|
|
||||||
base = origin(request)
|
query = urlencode({'resource': resource})
|
||||||
|
return HttpResponseRedirect(BRIDGY_FED + '?' + query)
|
||||||
def link(rel, href, type):
|
|
||||||
return {'rel': rel, 'href': urljoin(base, href), 'type': type}
|
|
||||||
|
|
||||||
key_links = tuple(link(
|
|
||||||
rel='pgpkey',
|
|
||||||
href=key.file.url,
|
|
||||||
type='application/pgp-keys',
|
|
||||||
) for key in user.keys.all())
|
|
||||||
|
|
||||||
info = {
|
|
||||||
'subject': 'acct:' + user.email,
|
|
||||||
'aliases': (
|
|
||||||
urljoin(base, user.url),
|
|
||||||
'mailto:' + user.email,
|
|
||||||
'xmpp:' + user.xmpp,
|
|
||||||
),
|
|
||||||
'links': (
|
|
||||||
link(rel=AVATAR, href=user.avatar.url, type='image/png'),
|
|
||||||
link(rel=PROFILE_PAGE, href=user.url, type='text/html'),
|
|
||||||
) + key_links,
|
|
||||||
}
|
|
||||||
return JsonResponse(info, content_type='application/jrd+json')
|
|
||||||
|
|
Loading…
Reference in a new issue