From 7fc044b68f6938b51826df2d0badc273f4c8bf56 Mon Sep 17 00:00:00 2001 From: Med Date: Sun, 16 Jul 2017 02:41:44 +0200 Subject: [PATCH] =?UTF-8?q?Permet=20l'=C3=A9dition=20des=20clefs=20depuis?= =?UTF-8?q?=20le=20campus=20sans=20auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- users/decorators.py | 53 +++++++++++++++++++++++++ users/forms.py | 11 +++++- users/models.py | 2 +- users/templates/users/aff_clef.html | 2 +- users/templates/users/del_right.html | 58 ++++++++++++++++++++++++++++ users/views.py | 51 +++++++++++++++--------- 6 files changed, 156 insertions(+), 21 deletions(-) create mode 100644 users/decorators.py create mode 100644 users/templates/users/del_right.html diff --git a/users/decorators.py b/users/decorators.py new file mode 100644 index 0000000..1cc6837 --- /dev/null +++ b/users/decorators.py @@ -0,0 +1,53 @@ +# Re2o est un logiciel d'administration développé initiallement au rezometz. Il +# se veut agnostique au réseau considéré, de manière à être installable en +# quelques clics. +# +# Copyright © 2017 Gabriel Détraz +# Copyright © 2017 Goulven Kermarec +# Copyright © 2017 Augustin Lemesle +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# App de gestion des users pour med +# Goulven Kermarec, Gabriel Détraz, Lemesle Augustin +# Gplv2 + + +from django.core.exceptions import PermissionDenied +from med.settings import AUTHORIZED_IP_RANGE, AUTHORIZED_IP6_RANGE +import ipaddress + +def user_is_in_campus(function): + def wrap(request, *args, **kwargs): + if not request.user.is_authenticated: + remote_ip = get_ip(request) + if not ipaddress.ip_address(remote_ip) in ipaddress.ip_network(AUTHORIZED_IP_RANGE) and not ipaddress.ip_address(remote_ip) in ipaddress.ip_network(AUTHORIZED_IP6_RANGE): + raise PermissionDenied + return function(request, *args, **kwargs) + wrap.__doc__ = function.__doc__ + wrap.__name__ = function.__name__ + return wrap + +def get_ip(request): + """Returns the IP of the request, accounting for the possibility of being + behind a proxy. + """ + ip = request.META.get("HTTP_X_FORWARDED_FOR", None) + if ip: + # X_FORWARDED_FOR returns client1, proxy1, proxy2,... + ip = ip.split(", ")[0] + else: + ip = request.META.get("REMOTE_ADDR", "") + return ip diff --git a/users/forms.py b/users/forms.py index fc393ed..d054db5 100644 --- a/users/forms.py +++ b/users/forms.py @@ -145,6 +145,12 @@ class ClefForm(ModelForm): model = Clef fields = '__all__' +class BaseClefForm(ClefForm): + class Meta(ClefForm.Meta): + fields = [ + 'commentaire', + ] + class AdhesionForm(ModelForm): adherent = forms.ModelMultipleChoiceField(User.objects.all(), widget=forms.CheckboxSelectMultiple, required=False) @@ -164,8 +170,11 @@ class RightForm(ModelForm): class DelRightForm(Form): - rights = forms.ModelMultipleChoiceField(queryset=Right.objects.all(), label="Droits actuels", widget=forms.CheckboxSelectMultiple) + rights = forms.ModelMultipleChoiceField(queryset=Right.objects.all(), widget=forms.CheckboxSelectMultiple) + def __init__(self, right, *args, **kwargs): + super(DelRightForm, self).__init__(*args, **kwargs) + self.fields['rights'].queryset = Right.objects.filter(right=right) class ListRightForm(ModelForm): class Meta: diff --git a/users/models.py b/users/models.py index 0baa68f..03b9dcd 100644 --- a/users/models.py +++ b/users/models.py @@ -199,7 +199,7 @@ class Right(models.Model): unique_together = ("user", "right") def __str__(self): - return str(self.user) + " - " + str(self.right) + return str(self.user) class ListRight(models.Model): PRETTY_NAME = "Liste des droits existants" diff --git a/users/templates/users/aff_clef.html b/users/templates/users/aff_clef.html index 5a478a5..6034ad9 100644 --- a/users/templates/users/aff_clef.html +++ b/users/templates/users/aff_clef.html @@ -37,8 +37,8 @@ with this program; if not, write to the Free Software Foundation, Inc., {{ clef.proprio }} {{ clef.commentaire }} - {% if is_bureau %} {% include 'buttons/edit.html' with href='users:edit-clef' id=clef.id %} + {% if is_bureau %} {% include 'buttons/suppr.html' with href='users:del-clef' id=clef.id %} {% endif %} {% include 'buttons/history.html' with href='users:history' name='clef' id=clef.id %} diff --git a/users/templates/users/del_right.html b/users/templates/users/del_right.html new file mode 100644 index 0000000..740778a --- /dev/null +++ b/users/templates/users/del_right.html @@ -0,0 +1,58 @@ +{% extends "users/sidebar.html" %} +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2017 Gabriel Détraz +Copyright © 2017 Goulven Kermarec +Copyright © 2017 Augustin Lemesle + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} + +{% load bootstrap3 %} + +{% block title %}Création et modification d'utilisateur{% endblock %} + + +{% block content %} + +

Gestion des droits

+ +
+ {% csrf_token %} + + + + {% for key, values in userform.items %} + + {% endfor %} + + + + {% for key, values in userform.items %} + {% bootstrap_form_errors values %} + + {% endfor %} + +
{{ key }}
{{ values.rights }}
+ {% bootstrap_button "Modifier" button_type="submit" icon="star" %} +
+ +
+
+
+{% endblock %} diff --git a/users/views.py b/users/views.py index f4de0b5..25ba09a 100644 --- a/users/views.py +++ b/users/views.py @@ -40,9 +40,10 @@ from django.db import transaction from reversion.models import Version from reversion import revisions as reversion from users.forms import DelListRightForm, NewListRightForm, ListRightForm, RightForm, DelRightForm -from users.forms import InfoForm, BaseInfoForm, StateForm, ClefForm, AdhesionForm +from users.forms import InfoForm, BaseInfoForm, StateForm, ClefForm, BaseClefForm, AdhesionForm from users.models import User, Request, ListRight, Right, Clef, Adhesion from users.forms import PassForm, ResetPasswordForm +from users.decorators import user_is_in_campus from media.models import Emprunt from med.settings import REQ_EXPIRE_STR, EMAIL_FROM, ASSO_NAME, ASSO_EMAIL, SITE_NAME, PAGINATION_NUMBER @@ -248,16 +249,19 @@ def add_right(request, userid): @permission_required('bureau') def del_right(request): """ Supprimer un droit à un user, need droit bureau """ - user_right_list = DelRightForm(request.POST or None) - if user_right_list.is_valid(): - right_del = user_right_list.cleaned_data['rights'] - with transaction.atomic(), reversion.create_revision(): - reversion.set_user(request.user) - reversion.set_comment("Retrait des droit %s" % ','.join(str(deleted_right) for deleted_right in right_del)) - right_del.delete() - messages.success(request, "Droit retiré avec succès") - return redirect("/users/") - return form({'userform': user_right_list}, 'users/user.html', request) + user_right_list = dict() + for right in ListRight.objects.all(): + user_right_list[right]= DelRightForm(right, request.POST or None) + for keys, right_item in user_right_list.items(): + if right_item.is_valid(): + right_del = right_item.cleaned_data['rights'] + with transaction.atomic(), reversion.create_revision(): + reversion.set_user(request.user) + reversion.set_comment("Retrait des droit %s" % ','.join(str(deleted_right) for deleted_right in right_del)) + right_del.delete() + messages.success(request, "Droit retiré avec succès") + return redirect("/users/") + return form({'userform': user_right_list}, 'users/del_right.html', request) @login_required @permission_required('perm') @@ -279,19 +283,22 @@ def add_clef(request): return redirect("/users/index_clef/") return form({'userform': clef}, 'users/user.html', request) -@login_required -@permission_required('bureau') +@user_is_in_campus def edit_clef(request, clefid): try: clef_instance = Clef.objects.get(pk=clefid) except Clef.DoesNotExist: messages.error(request, u"Entrée inexistante" ) return redirect("/users/index_clef/") - clef = ClefForm(request.POST or None, instance=clef_instance) + if request.user.has_perms(('bureau',)): + clef = ClefForm(request.POST or None, instance=clef_instance) + else: + clef = BaseClefForm(request.POST or None, instance=clef_instance) if clef.is_valid(): with transaction.atomic(), reversion.create_revision(): clef.save() - reversion.set_user(request.user) + if request.user.is_authenticated: + reversion.set_user(request.user) reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in clef.changed_data)) messages.success(request, "Clef modifié") return redirect("/users/index_clef/") @@ -313,12 +320,11 @@ def del_clef(request, clefid): return redirect("/users/index_clef") return form({'objet': clef_instance, 'objet_name': 'clef'}, 'users/delete.html', request) -@login_required +@user_is_in_campus def index_clef(request): clef_list = Clef.objects.all().order_by('nom') return render(request, 'users/index_clef.html', {'clef_list':clef_list}) - @login_required @permission_required('bureau') def add_adhesion(request): @@ -405,10 +411,19 @@ def index_ajour(request): users_list = paginator.page(paginator.num_pages) return render(request, 'users/index.html', {'users_list': users_list}) -@login_required +@user_is_in_campus def history(request, object, id): """ Affichage de l'historique : (acl, argument) user : self, userid""" + if object == 'clef': + try: + object_instance = Clef.objects.get(pk=id) + except Clef.DoesNotExist: + messages.error(request, "Utilisateur inexistant") + return redirect("/users/") + elif not request.user.is_authenticated: + messages.error(request, "Permission denied") + return redirect("/users/") if object == 'user': try: object_instance = User.objects.get(pk=id)