From 060d3011f7361db03e3d5c70e788f7b58d87f2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Bru=CC=88ggemann?= Date: Sun, 8 Jan 2017 20:09:51 +0100 Subject: [PATCH 1/3] The /fetch endpoint can be authenticated via session or via HTTP basic now. --- src/documents/mixins.py | 43 +++++++++++++++++++++++++++++++++++++++++ src/documents/views.py | 6 +++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/documents/mixins.py b/src/documents/mixins.py index 4d4e9783f..740f9f232 100644 --- a/src/documents/mixins.py +++ b/src/documents/mixins.py @@ -1,3 +1,7 @@ +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 +11,42 @@ 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": + uname, passwd = base64.b64decode(auth[1]).decode('utf-8').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. """ From a698c69b4d473d32189622d1cc8a336d6662b1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Bru=CC=88ggemann?= Date: Sun, 8 Jan 2017 20:33:33 +0100 Subject: [PATCH 2/3] Fix pep8 style --- src/documents/mixins.py | 67 ++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/documents/mixins.py b/src/documents/mixins.py index 740f9f232..d17275908 100644 --- a/src/documents/mixins.py +++ b/src/documents/mixins.py @@ -2,6 +2,7 @@ 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 @@ -12,41 +13,45 @@ class Renderable(object): 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. + """ + 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/ - """ + Base for mixin found here: https://djangosnippets.org/snippets/3073/ + """ - def dispatch(self, request, *args, **kwargs): + def dispatch(self, request, *args, **kwargs): - # check if user is authenticated via the session - if request.user.is_authenticated: + # 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 - ) + # 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": - uname, passwd = base64.b64decode(auth[1]).decode('utf-8').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 - ) + # 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() + # nope, really not authenticated + return self.handle_no_permission() From afb4e317f0b7ec58054127e9501e242ffdaec367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Bru=CC=88ggemann?= Date: Sun, 8 Jan 2017 20:36:51 +0100 Subject: [PATCH 3/3] Another indentation fix --- src/documents/mixins.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/documents/mixins.py b/src/documents/mixins.py index d17275908..a031dd50f 100644 --- a/src/documents/mixins.py +++ b/src/documents/mixins.py @@ -48,8 +48,8 @@ class SessionOrBasicAuthMixin(AccessMixin): login(request, user) request.user = user return super( - SessionOrBasicAuthMixin, self - ).dispatch( + SessionOrBasicAuthMixin, self + ).dispatch( request, *args, **kwargs )