Commit 9def8c31 authored by Jean-Baptiste's avatar Jean-Baptiste

update: extensible webfinger

parent f1b10be1
Pipeline #4956 passed with stage
in 1 minute and 21 seconds
import re
from importlib import import_module
from django.conf import settings
class WebFinger(object):
def response(self, response_dict, rel, acct):
return response_dict
for package in settings.DJANGOLDP_PACKAGES:
try:
import_module('{}.endpoints.webfinger'.format(package))
except ModuleNotFoundError:
pass
model_classes = {cls.__name__: cls for cls in WebFinger.__subclasses__()}
ACCT_RE = re.compile(
r'(?:acct:)?(?P<userinfo>[\w.!#$%&\'*+-/=?^_`{|}~]+)@(?P<host>[\w.:-]+)')
class Acct(object):
def __init__(self, acct):
m = ACCT_RE.match(acct)
if not m:
raise ValueError('invalid acct format')
(userinfo, host) = m.groups()
self.userinfo = userinfo
self.host = host
class WebFingerEndpoint(object):
"""
WebFinger endpoint
See https://tools.ietf.org/html/rfc7033
"""
def __init__(self, request):
self.request = request
self.params = {}
self.acct = None
self._extract_params()
def _extract_params(self):
# Because in this endpoint we handle both GET
# and POST request.
query_dict = (self.request.POST if self.request.method == 'POST'
else self.request.GET)
self.params['resource'] = query_dict.get('resource', None)
self.params['rel'] = query_dict.get('rel', '')
def validate_params(self):
"""
A resource must be set.
"""
if self.params['resource'] is None:
raise WebFingerError('invalid_request')
try:
self.acct = Acct(self.params['resource'])
except ValueError:
raise WebFingerError('invalid_acct_format')
def response(self):
"""
This endpoint only reply to rel="http://openid.net/specs/connect/1.0/issuer"
:return: a dict representing the Json response
"""
dict = {
'subject': self.params['resource'],
'links': []
}
for class_name in model_classes:
webfinger = class_name()
dict = webfinger.response(dict, self.params['rel'], self.acct)
return dict
class WebFingerError(Exception):
_errors = {
'invalid_request': "The request provider parameter must contains an url or an email",
'invalid_acct_format': "Invalid acct format"
}
def __init__(self, error=None, dict=None):
if dict is None:
self.error = error
self.description = self._errors.get(error)
else:
self.error = dict['error']
self.description = dict['error_description']
def create_dict(self):
dic = {
'error': self.error,
'error_description': self.description,
}
return dic
......@@ -5,7 +5,7 @@ from django.conf.urls import url, include
from djangoldp.models import LDPSource, Model
from djangoldp.permissions import LDPPermissions
from djangoldp.views import LDPSourceViewSet
from djangoldp.views import LDPSourceViewSet, WebFingerView
def __clean_path(path):
......@@ -19,6 +19,7 @@ def __clean_path(path):
urlpatterns = [
url(r'^sources/(?P<federation>\w+)/', LDPSourceViewSet.urls(model=LDPSource, fields=['federation', 'container'],
permission_classes=[LDPPermissions], )),
url(r'^\.well-known/webfinger/?$', WebFingerView.as_view()),
]
for package in settings.DJANGOLDP_PACKAGES:
......
......@@ -4,8 +4,10 @@ from django.conf.urls import url, include
from django.contrib.auth import get_user_model
from django.core.exceptions import FieldDoesNotExist
from django.core.urlresolvers import get_resolver
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from django.utils.decorators import classonlymethod
from django.views import View
from pyld import jsonld
from rest_framework import status
from rest_framework.authentication import SessionAuthentication
......@@ -14,6 +16,7 @@ from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from djangoldp.endpoints.webfinger import WebFingerEndpoint, WebFingerError
from djangoldp.models import LDPSource, Model
from djangoldp.permissions import LDPPermissions
......@@ -278,3 +281,24 @@ class LDPSourceViewSet(LDPViewSet):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(federation=self.kwargs['federation'])
class WebFingerView(View):
endpoint_class = WebFingerEndpoint
def get(self, request, *args, **kwargs):
return self.on_request(request)
def on_request(self, request):
endpoint = self.endpoint_class(request)
try:
endpoint.validate_params()
return JsonResponse(endpoint.response())
except WebFingerError as error:
return JsonResponse(error.create_dict(), status=400)
def post(self, request, *args, **kwargs):
return self.on_request(request)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment