From 3e96932a5b32a95fdc6e9ba37268f6c7a450ce49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Fri, 19 Aug 2016 06:20:37 +0200 Subject: [PATCH] Authentification K-Psul MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Si une (des) permission(s) sont nécessaires pour enregistrer/annuler des opérations, une demande d'authentification apparaît où l'utilisateur doit mettre le mot de passe d'un compte ayant la (les) permission(s) requise(s). Ce mot de passe est envoyé dans la requête AJAX via le header `KFetPassword`. Le middleware `KFetAuthenticationPassword` est appelée à chaque requête. Il appelle lui même le backend `KFetBackend` qui est chargé de retrouver le user dont le compte K-Fêt correspond au mot de passe défini dans le header `KFETPASSWORD`. Si le header n'est pas présent ou qu'aucun utilisateur ne correspond à ce mot de passe, le middleware ne fait... rien ! Dans le cas où un user est trouvé, il est "chargé" dans `request.user` permettant ainsi de connecter l'utilisateur pour ce cycle requête/réponse sans déconnecter l'utilisateur connecté de manière normale. --- cof/settings_dev.py | 1 + kfet/backends.py | 18 ++++++++++ kfet/middleware.py | 8 +++++ kfet/templates/kfet/kpsul.html | 66 ++++++++++++++++++++++++++++------ 4 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 kfet/backends.py create mode 100644 kfet/middleware.py diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 7124ed46..717e36a0 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -60,6 +60,7 @@ MIDDLEWARE_CLASSES = ( 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'kfet.middleware.KFetAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', diff --git a/kfet/backends.py b/kfet/backends.py new file mode 100644 index 00000000..b9f8c374 --- /dev/null +++ b/kfet/backends.py @@ -0,0 +1,18 @@ +import hashlib + +from kfet.models import Account + +class KFetBackend(object): + def authenticate(self, request): + password = request.META.get('HTTP_KFETPASSWORD') + if not password: + return None + + try: + password_sha1 = hashlib.sha1(password.encode()).hexdigest() + account = Account.objects.get(password=password_sha1) + user = account.cofprofile.user + except Account.DoesNotExist: + return None + + return user diff --git a/kfet/middleware.py b/kfet/middleware.py new file mode 100644 index 00000000..13c01293 --- /dev/null +++ b/kfet/middleware.py @@ -0,0 +1,8 @@ +from kfet.backends import KFetBackend + +class KFetAuthenticationMiddleware(object): + def process_request(self, request): + kfet_backend = KFetBackend() + temp_request_user = kfet_backend.authenticate(request) + if temp_request_user: + request.user = temp_request_user diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index d3c8c548..4516b990 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -305,6 +305,33 @@ $(document).ready(function() { retrieveCheckoutData(checkoutInput.val()); }); + // ----- + // Auth + // ----- + + function requestAuth(data, callback) { + $.confirm({ + title: 'Authentification requise', + content: '', + backgroundDismiss: true, + animation:'top', + closeAnimation:'bottom', + keyboardEnabled: true, + confirm: function() { + var password = this.$content.find('input').val(); + callback(password); + }, + onOpen: function() { + var that = this + this.$content.find('input').on('keypress', function(e) { + if (e.keyCode == 13) + that.$confirmButton.click(); + }); + }, + onClose: function() { this._lastFocused = articleSelect; } + }); + } + // ----- // Perform operations // ----- @@ -313,20 +340,29 @@ $(document).ready(function() { var operationGroup = $('#operationgroup_form'); var operations = $('#operation_formset'); - function performOperations() { + function performOperations(password = '') { var data = operationGroup.serialize() + '&' + operations.serialize(); $.ajax({ dataType: "json", url : "{% url 'kfet.kpsul.perform_operations' %}", method : "POST", data : data, + beforeSend: function ($xhr) { + $xhr.setRequestHeader("X-CSRFToken", csrftoken); + if (password != '') + $xhr.setRequestHeader("KFetPassword", password); + }, }) .done(function(data) { - console.log(data); + coolReset(); }) .fail(function($xhr) { var data = $xhr.responseJSON; - console.log(data); + switch ($xhr.status) { + case 403: + requestAuth(data, performOperations); + break; + } }); } @@ -342,21 +378,33 @@ $(document).ready(function() { var cancelButton = $('#cancel_operations'); var cancelForm = $('#cancel_form'); - function cancelOperations(opes_array) { + function cancelOperations(opes_array, password = '') { var data = { 'operations' : opes_array } $.ajax({ dataType: "json", url : "{% url 'kfet.kpsul.cancel_operations' %}", method : "POST", data : data, + beforeSend: function ($xhr) { + $xhr.setRequestHeader("X-CSRFToken", csrftoken); + if (password != '') + $xhr.setRequestHeader("KFetPassword", password); + }, + }) .done(function(data) { - console.log(data); - history_container.find('.ui-selected').removeClass('ui-selected'); + coolReset(); }) .fail(function($xhr) { var data = $xhr.responseJSON; - console.log(data); + switch ($xhr.status) { + case 403: + requestAuth(data, function(password) { + cancelOperations(opes_array, password); + }); + break; + } + }); } @@ -510,10 +558,8 @@ $(document).ready(function() { var text = articleSelect.val(); // Comportement normal pour ces touches if (normalKeys.test(e.keyCode) || e.ctrlKey) { - if (text == '' && e.keyCode == 13) { + if (text == '' && e.keyCode == 13) performOperations(); - coolReset(); - } if (e.keyCode == 8) updateMatchedArticles(text.substring(0,text.length-1), commit=false); if (e.charCode == 97 && e.ctrlKey) {