forked from 00dani/lemoncurry
59 lines
2.3 KiB
Python
59 lines
2.3 KiB
Python
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)
|