diff --git a/src/documents/mixins.py b/src/documents/mixins.py index 4d4e9783f..a031dd50f 100644 --- a/src/documents/mixins.py +++ b/src/documents/mixins.py @@ -1,3 +1,8 @@ +from django.contrib.auth.mixins import AccessMixin +from django.contrib.auth import authenticate, login +import base64 + + class Renderable(object): """ A handy mixin to make it easier/cleaner to print output based on a @@ -7,3 +12,46 @@ class Renderable(object): def _render(self, text, verbosity): if self.verbosity >= verbosity: print(text) + + +class SessionOrBasicAuthMixin(AccessMixin): + """ + Session or Basic Authentication mixin for Django. + It determines if the requester is already logged in or if they have + provided proper http-authorization and returning the view if all goes + well, otherwise responding with a 401. + + Base for mixin found here: https://djangosnippets.org/snippets/3073/ + """ + + def dispatch(self, request, *args, **kwargs): + + # check if user is authenticated via the session + if request.user.is_authenticated: + + # Already logged in, just return the view. + return super(SessionOrBasicAuthMixin, self).dispatch( + request, *args, **kwargs + ) + + # apparently not authenticated via session, maybe via HTTP Basic? + if 'HTTP_AUTHORIZATION' in request.META: + auth = request.META['HTTP_AUTHORIZATION'].split() + if len(auth) == 2: + # NOTE: Support for only basic authentication + if auth[0].lower() == "basic": + authString = base64.b64decode(auth[1]).decode('utf-8') + uname, passwd = authString.split(':') + user = authenticate(username=uname, password=passwd) + if user is not None: + if user.is_active: + login(request, user) + request.user = user + return super( + SessionOrBasicAuthMixin, self + ).dispatch( + request, *args, **kwargs + ) + + # nope, really not authenticated + return self.handle_no_permission() diff --git a/src/documents/views.py b/src/documents/views.py index f271eed9d..3598472af 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -1,4 +1,3 @@ -from django.contrib.auth.mixins import LoginRequiredMixin from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt from django.views.generic import DetailView, FormView, TemplateView @@ -28,6 +27,7 @@ from .serialisers import ( LogSerializer, TagSerializer ) +from .mixins import SessionOrBasicAuthMixin class IndexView(TemplateView): @@ -41,7 +41,7 @@ class IndexView(TemplateView): return TemplateView.get_context_data(self, **kwargs) -class FetchView(LoginRequiredMixin, DetailView): +class FetchView(SessionOrBasicAuthMixin, DetailView): model = Document @@ -74,7 +74,7 @@ class FetchView(LoginRequiredMixin, DetailView): return response -class PushView(LoginRequiredMixin, FormView): +class PushView(SessionOrBasicAuthMixin, FormView): """ A crude REST-ish API for creating documents. """