############################################################################# ## ## Copyright (C) 2019 Luxoft Sweden AB ## Copyright (C) 2018 Pelagicore AG ## Contact: https://www.qt.io/licensing/ ## ## This file is part of the Neptune Deployment Server ## ## $QT_BEGIN_LICENSE:GPL-QTAS$ ## Commercial License Usage ## Licensees holding valid commercial Qt Automotive Suite licenses may use ## this file in accordance with the commercial license agreement provided ## with the Software or, alternatively, in accordance with the terms ## contained in a written agreement between you and The Qt Company. For ## licensing terms and conditions see https://www.qt.io/terms-conditions. ## For further information use the contact form at https://www.qt.io/contact-us. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 3 or (at your option) any later version ## approved by the KDE Free Qt Foundation. The licenses are as published by ## the Free Software Foundation and appearing in the file LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ## SPDX-License-Identifier: GPL-3.0 ## ############################################################################# # Code taken from: https://www.djangosnippets.org/snippets/243/ # Reuse and licensing is permitted by TOS: https://www.djangosnippets.org/about/tos/ import base64 from django.http import HttpResponse from django.contrib.auth import authenticate, login ############################################################################# def view_or_basicauth(view, request, test_func, realm="", *args, **kwargs): """ This is a helper function used by both 'logged_in_or_basicauth' and 'has_perm_or_basicauth' that does the service of determining if they are already logged in or if they have provided proper http-authorization and returning the view if all goes well, otherwise responding with a 401. """ if test_func(request.user): # Already logged in, just return the view. # return view(request, *args, **kwargs) # They are not logged in. See if they provided login credentials # if 'HTTP_AUTHORIZATION' in request.META: auth = request.META['HTTP_AUTHORIZATION'].split() if len(auth) == 2: # NOTE: We are only support basic authentication for now. # if auth[0].lower() == "basic": uname, passwd = base64.b64decode(auth[1].encode('utf-8')).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 if test_func(request.user): return view(request, *args, **kwargs) # Either they did not provide an authorization header or # something in the authorization attempt failed. Send a 401 # back to them to ask them to authenticate. # response = HttpResponse() response.status_code = 401 response['WWW-Authenticate'] = 'Basic realm="%s"' % realm return response ############################################################################# def logged_in_or_basicauth(realm=""): """ A simple decorator that requires a user to be logged in and in staff group. If they are not logged in the request is examined for a 'authorization' header. If the header is present it is tested for basic authentication and the user is logged in with the provided credentials. If the header is not present a http 401 is sent back to the requester to provide credentials. The purpose of this is that in several django projects I have needed several specific views that need to support basic authentication, yet the web site as a whole used django's provided authentication. The uses for this are for urls that are access programmatically such as by rss feed readers, yet the view requires a user to be logged in. Many rss readers support supplying the authentication credentials via http basic auth (and they do NOT support a redirect to a form where they post a username/password.) Use is simple: @logged_in_or_basicauth def your_view: ... You can provide the name of the realm to ask for authentication within. """ def view_decorator(func): def wrapper(request, *args, **kwargs): return view_or_basicauth(func, request, lambda u: u.is_authenticated, realm, *args, **kwargs) return wrapper return view_decorator def is_staff_member(): def view_decorator(func): def wrapper(request, *args, **kwargs): if request.user.is_staff: return func(request, *args, **kwargs) else: response = HttpResponse() response.status_code = 403 return response return wrapper return view_decorator