from django.http import HttpResponseBadRequest, HttpResponseRedirect from urllib.parse import urlencode, urlparse from users.models import User AVATAR = 'http://webfinger.net/rel/avatar' 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): """ 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: return HttpResponseBadRequest('resource parameter missing') resource = request.GET['resource'] try: res = urlparse(resource) except ValueError: return HttpResponseBadRequest('resource parameter malformed') if res.scheme in ('mailto', 'xmpp'): try: resource = https_resource_matching(res) except User.DoesNotExist: pass query = urlencode({'resource': resource}) return HttpResponseRedirect(BRIDGY_FED + '?' + query)