From ef0bd78af5b4fffc92df1131de0b299d09d20083 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Thu, 8 Aug 2019 15:35:25 +0200 Subject: [PATCH] Clean up of users app --- .../templates/media}/history.html | 0 media/views.py | 2 +- users/__init__.py | 22 ---- users/admin.py | 8 +- users/decorators.py | 37 ------ users/forms.py | 54 +++------ users/models.py | 19 ++- users/templates/users/aff_clef.html | 4 - users/templates/users/del_right.html | 58 --------- users/templates/users/delete.html | 40 ------- users/urls.py | 9 +- users/views.py | 112 ++++++------------ 12 files changed, 75 insertions(+), 290 deletions(-) rename {med/templates/med => media/templates/media}/history.html (100%) delete mode 100644 users/decorators.py delete mode 100644 users/templates/users/del_right.html delete mode 100644 users/templates/users/delete.html diff --git a/med/templates/med/history.html b/media/templates/media/history.html similarity index 100% rename from med/templates/med/history.html rename to media/templates/media/history.html diff --git a/media/views.py b/media/views.py index c36c456..56473cd 100644 --- a/media/views.py +++ b/media/views.py @@ -358,4 +358,4 @@ def history(request, object, id): except EmptyPage: # If page is out of range (e.g. 9999), deliver last page of results. reversions = paginator.page(paginator.num_pages) - return render(request, 'med/history.html', {'reversions': reversions, 'object': object_instance}) + return render(request, 'media/history.html', {'reversions': reversions, 'object': object_instance}) diff --git a/users/__init__.py b/users/__init__.py index 20abb0d..e69de29 100644 --- a/users/__init__.py +++ b/users/__init__.py @@ -1,22 +0,0 @@ -# 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. - diff --git a/users/admin.py b/users/admin.py index 0b054b0..1d9121a 100644 --- a/users/admin.py +++ b/users/admin.py @@ -7,7 +7,7 @@ from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.utils.translation import ugettext_lazy as _ from reversion.admin import VersionAdmin -from .models import User, Right, Adhesion, ListRight, Clef, Request +from .models import Adhesion, Clef, ListRight, Request, Right, User class RequestAdmin(admin.ModelAdmin): @@ -44,7 +44,8 @@ class IsAdherentFilter(admin.SimpleListFilter): value = self.value() if value == 'Yes': # Get current membership year and list all members - last_adh_year = Adhesion.objects.all().order_by('annee_debut').reverse().first() + last_adh_year = Adhesion.objects.all().order_by('annee_debut')\ + .reverse().first() return last_adh_year.adherent return queryset @@ -69,7 +70,8 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): """ Get current membership year and check if user is there """ - last_adh_year = Adhesion.objects.all().order_by('annee_debut').reverse().first() + last_adh_year = Adhesion.objects.all().order_by('annee_debut')\ + .reverse().first() return last_adh_year and obj in last_adh_year.adherent.all() is_adherent.boolean = True diff --git a/users/decorators.py b/users/decorators.py deleted file mode 100644 index 0046ee6..0000000 --- a/users/decorators.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- mode: python; coding: utf-8 -*- -# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay -# SPDX-License-Identifier: GPL-3.0-or-later - -import ipaddress - -from django.shortcuts import redirect - -from med.settings import AUTHORIZED_IP_RANGE, AUTHORIZED_IP6_RANGE - - -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): - return redirect("/") - 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 74d85c8..0dd319a 100644 --- a/users/forms.py +++ b/users/forms.py @@ -3,18 +3,25 @@ # SPDX-License-Identifier: GPL-3.0-or-later from django import forms -from django.contrib.auth.forms import ReadOnlyPasswordHashField from django.core.validators import MinLengthValidator -from django.forms import ModelForm, Form +from django.forms import ModelForm -from .models import Adhesion, Clef, ListRight, Right, User +from .models import User class PassForm(forms.Form): - passwd1 = forms.CharField(label=u'Nouveau mot de passe', max_length=255, validators=[MinLengthValidator(8)], - widget=forms.PasswordInput) - passwd2 = forms.CharField(label=u'Saisir à nouveau le mot de passe', max_length=255, - validators=[MinLengthValidator(8)], widget=forms.PasswordInput) + passwd1 = forms.CharField( + label=u'Nouveau mot de passe', + max_length=255, + validators=[MinLengthValidator(8)], + widget=forms.PasswordInput, + ) + passwd2 = forms.CharField( + label=u'Saisir à nouveau le mot de passe', + max_length=255, + validators=[MinLengthValidator(8)], + widget=forms.PasswordInput + ) class BaseInfoForm(ModelForm): @@ -41,36 +48,3 @@ class InfoForm(BaseInfoForm): 'address', 'maxemprunt', ] - - -class PasswordForm(ModelForm): - class Meta: - model = User - fields = ['password'] - - -class AdhesionForm(ModelForm): - adherent = forms.ModelMultipleChoiceField(User.objects.all(), widget=forms.CheckboxSelectMultiple, required=False) - - class Meta: - model = Adhesion - fields = '__all__' - - -class RightForm(ModelForm): - def __init__(self, *args, **kwargs): - super(RightForm, self).__init__(*args, **kwargs) - self.fields['right'].label = 'Droit' - self.fields['right'].empty_label = "Choisir un nouveau droit" - - class Meta: - model = Right - fields = ['right'] - - -class DelRightForm(Form): - 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) diff --git a/users/models.py b/users/models.py index 4cf7eac..bb921bd 100644 --- a/users/models.py +++ b/users/models.py @@ -28,7 +28,8 @@ class User(AbstractUser): ) maxemprunt = models.IntegerField( verbose_name=_('maximum borrowed'), - help_text=_('Maximal amount of simultaneous borrowed item authorized.'), + help_text=_('Maximal amount of simultaneous borrowed item ' + 'authorized.'), default=MAX_EMPRUNT, ) comment = models.CharField( @@ -50,7 +51,8 @@ class User(AbstractUser): @property def is_adherent(self): - last_adh_year = Adhesion.objects.all().order_by('annee_debut').reverse().first() + last_adh_year = Adhesion.objects.all().order_by( + 'annee_debut').reverse().first() return last_adh_year and self in last_adh_year.adherent.all() @@ -69,8 +71,8 @@ class Request(models.Model): def save(self): if not self.expires_at: - self.expires_at = timezone.now() \ - + datetime.timedelta(hours=REQ_EXPIRE_HRS) + self.expires_at = timezone.now() + self.expires_at += datetime.timedelta(hours=REQ_EXPIRE_HRS) if not self.token: self.token = str(uuid.uuid4()).replace('-', '') # remove hyphens super().save() @@ -95,7 +97,11 @@ class ListRight(models.Model): PRETTY_NAME = "Liste des droits existants" listright = models.CharField(max_length=255, unique=True) - details = models.CharField(help_text="Description", max_length=255, blank=True) + details = models.CharField( + help_text="Description", + max_length=255, + blank=True, + ) def __str__(self): return self.listright @@ -103,7 +109,8 @@ class ListRight(models.Model): class Clef(models.Model): nom = models.CharField(max_length=255, unique=True) - proprio = models.ForeignKey('User', on_delete=models.PROTECT, blank=True, null=True) + proprio = models.ForeignKey('User', on_delete=models.PROTECT, blank=True, + null=True) commentaire = models.CharField(max_length=255, null=True, blank=True) diff --git a/users/templates/users/aff_clef.html b/users/templates/users/aff_clef.html index 88888f6..72d7b38 100644 --- a/users/templates/users/aff_clef.html +++ b/users/templates/users/aff_clef.html @@ -8,7 +8,6 @@ SPDX-License-Identifier: GPL-3.0-or-later Clef Propriétaire Commentaire - {% for clef in clef_list %} @@ -16,9 +15,6 @@ SPDX-License-Identifier: GPL-3.0-or-later {{ clef.nom }} {{ clef.proprio }} {{ clef.commentaire }} - - {% include 'buttons/history.html' with href='users:history' name='clef' id=clef.id %} - {% endfor %} diff --git a/users/templates/users/del_right.html b/users/templates/users/del_right.html deleted file mode 100644 index 740778a..0000000 --- a/users/templates/users/del_right.html +++ /dev/null @@ -1,58 +0,0 @@ -{% 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/templates/users/delete.html b/users/templates/users/delete.html deleted file mode 100644 index 1ca4061..0000000 --- a/users/templates/users/delete.html +++ /dev/null @@ -1,40 +0,0 @@ -{% extends "media/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 de media{% endblock %} - -{% block content %} - -
- {% csrf_token %} -

Attention, voulez-vous vraiment supprimer cet objet {{ objet_name }} ( {{ objet }} ) ?

- {% bootstrap_button "Confirmer" button_type="submit" icon="trash" %} -
-
-
-
-{% endblock %} diff --git a/users/urls.py b/users/urls.py index 22613b4..098a46a 100644 --- a/users/urls.py +++ b/users/urls.py @@ -9,16 +9,15 @@ from . import views app_name = 'users' urlpatterns = [ url(r'^new_user/$', views.new_user, name='new-user'), - url(r'^edit_info/(?P[0-9]+)$', views.edit_info, name='edit-info'), - url(r'^password/(?P[0-9]+)$', views.password, name='password'), + url(r'^edit_info/(?P[0-9]+)$', views.edit_info, + name='edit-info'), + url(r'^password/(?P[0-9]+)$', views.password, + name='password'), url(r'^profil/(?P[0-9]+)$', views.profil, name='profil'), url(r'^adherer/(?P[0-9]+)$', views.adherer, name='adherer'), url(r'^mon_profil/$', views.mon_profil, name='mon-profil'), url(r'^index_clef/$', views.index_clef, name='index-clef'), - url(r'^history/(?Pclef)/(?P[0-9]+)$', views.history, name='history'), - url(r'^history/(?Padhesion)/(?P[0-9]+)$', views.history, name='history'), url(r'^process/(?P[a-z0-9]{32})/$', views.process, name='process'), - url(r'^history/(?Puser)/(?P[0-9]+)$', views.history, name='history'), url(r'^$', views.index, name='index'), url(r'^index_ajour/$', views.index_ajour, name='index-ajour'), ] diff --git a/users/views.py b/users/views.py index 1447476..a8534a7 100644 --- a/users/views.py +++ b/users/views.py @@ -5,24 +5,21 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required from django.core.mail import send_mail -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.core.urlresolvers import reverse -from django.db import IntegrityError from django.db import transaction -from django.shortcuts import get_object_or_404, render, redirect +from django.shortcuts import get_object_or_404, redirect, render from django.template import loader from django.template.context_processors import csrf from django.utils import timezone from reversion import revisions as reversion -from reversion.models import Version -from med.settings import REQ_EXPIRE_STR, EMAIL_FROM, ASSO_NAME, ASSO_EMAIL, SITE_NAME, PAGINATION_NUMBER +from med.settings import ASSO_EMAIL, ASSO_NAME, EMAIL_FROM, \ + PAGINATION_NUMBER, REQ_EXPIRE_STR, SITE_NAME from media.models import Emprunt -from users.decorators import user_is_in_campus -from users.forms import InfoForm, BaseInfoForm, AdhesionForm +from users.forms import BaseInfoForm, InfoForm from users.forms import PassForm -from users.forms import RightForm, DelRightForm -from users.models import User, Request, ListRight, Right, Clef, Adhesion +from users.models import Adhesion, Clef, Request, Right, User def form(ctx, template, request): @@ -48,7 +45,9 @@ def password_change_action(u_form, user, request, req=False): def reset_passwd_mail(req, request): - """ Prend en argument un request, envoie un mail de réinitialisation de mot de pass """ + """ + Envoie un mail de réinitialisation de mot de passe + """ t = loader.get_template('users/email_passwd_request') c = { 'name': str(req.user.first_name) + ' ' + str(req.user.last_name), @@ -67,7 +66,9 @@ def reset_passwd_mail(req, request): @login_required @permission_required('bureau') def new_user(request): - """ Vue de création d'un nouvel utilisateur, envoie un mail pour le mot de passe""" + """ + Vue de création d'un nouvel utilisateur + """ user = BaseInfoForm(request.POST or None) if user.is_valid(): user = user.save(commit=False) @@ -80,21 +81,29 @@ def new_user(request): req.save() reset_passwd_mail(req, request) messages.success(request, - "L'utilisateur %s a été crée, un mail pour l'initialisation du mot de passe a été envoyé" % user.username) + "L'utilisateur %s a été crée, un mail pour " + "l'initialisation du mot de passe a été " + "envoyé" % user.username) return redirect("/users/profil/" + str(user.id)) return form({'userform': user}, 'users/user.html', request) @login_required def edit_info(request, userid): - """ Edite un utilisateur à partir de son id, si l'id est différent de request.user, vérifie la possession du droit admin """ + """ + Edite un utilisateur à partir de son id, + si l'id est différent de request.user, + vérifie la possession du droit admin + """ try: user = User.objects.get(pk=userid) except User.DoesNotExist: messages.error(request, "Utilisateur inexistant") return redirect("/users/") if not request.user.has_perms(('bureau',)) and user != request.user: - messages.error(request, "Vous ne pouvez pas modifier un autre user que vous sans droit admin") + messages.error(request, + "Vous ne pouvez pas modifier un autre user que vous " + "sans droit admin") return redirect("/users/profil/" + str(request.user.id)) if not request.user.has_perms(('bureau',)): user = BaseInfoForm(request.POST or None, instance=user) @@ -104,7 +113,8 @@ def edit_info(request, userid): with transaction.atomic(), reversion.create_revision(): user.save() reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in user.changed_data)) + reversion.set_comment("Champs modifié(s) : %s" % ', '.join( + field for field in user.changed_data)) messages.success(request, "L'user a bien été modifié") return redirect("/users/profil/" + userid) return form({'userform': user}, 'users/user.html', request) @@ -121,7 +131,9 @@ def password(request, userid): messages.error(request, "Utilisateur inexistant") return redirect("/users/") if not request.user.has_perms(('bureau',)) and user != request.user: - messages.error(request, "Vous ne pouvez pas modifier un autre user que vous sans droit admin") + messages.error(request, + "Vous ne pouvez pas modifier un autre user que vous " + "sans droit admin") return redirect("/users/profil/" + str(request.user.id)) u_form = PassForm(request.POST or None) if u_form.is_valid(): @@ -129,7 +141,8 @@ def password(request, userid): return form({'userform': u_form}, 'users/user.html', request) -@user_is_in_campus +@login_required +@permission_required('perm') def index_clef(request): clef_list = Clef.objects.all().order_by('nom') return render(request, 'users/index_clef.html', {'clef_list': clef_list}) @@ -157,7 +170,8 @@ def index(request): @permission_required('perm') def index_ajour(request): """ Affiche l'ensemble des users, need droit admin """ - users_list = Adhesion.objects.all().order_by('annee_debut').reverse().first().adherent.all().order_by('first_name') + users_list = Adhesion.objects.all().order_by( + 'annee_debut').reverse().first().adherent.all().order_by('first_name') paginator = Paginator(users_list, PAGINATION_NUMBER) page = request.GET.get('page') try: @@ -171,58 +185,6 @@ def index_ajour(request): return render(request, 'users/index.html', {'users_list': users_list}) -@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) - except User.DoesNotExist: - messages.error(request, "Utilisateur inexistant") - return redirect("/users/") - if not request.user.has_perms(('perm',)) and object_instance != request.user: - messages.error(request, - "Vous ne pouvez pas afficher l'historique d'un autre user que vous sans droit admin") - return redirect("/users/profil/" + str(request.user.id)) - elif object == 'clef': - try: - object_instance = Clef.objects.get(pk=id) - except Clef.DoesNotExist: - messages.error(request, "Utilisateur inexistant") - return redirect("/users/") - elif object == 'adhesion': - try: - object_instance = Adhesion.objects.get(pk=id) - except Adhesion.DoesNotExist: - messages.error(request, "Utilisateur inexistant") - return redirect("/users/") - else: - messages.error(request, "Objet inconnu") - return redirect("/users/") - reversions = Version.objects.get_for_object(object_instance) - paginator = Paginator(reversions, PAGINATION_NUMBER) - page = request.GET.get('page') - try: - reversions = paginator.page(page) - except PageNotAnInteger: - # If page is not an integer, deliver first page. - reversions = paginator.page(1) - except EmptyPage: - # If page is out of range (e.g. 9999), deliver last page of results. - reversions = paginator.page(paginator.num_pages) - return render(request, 'med/history.html', {'reversions': reversions, 'object': object_instance}) - - @login_required def mon_profil(request): return redirect("/users/profil/" + str(request.user.id)) @@ -236,7 +198,9 @@ def profil(request, userid): messages.error(request, "Utilisateur inexistant") return redirect("/users/") if not request.user.has_perms(('perm',)) and users != request.user: - messages.error(request, "Vous ne pouvez pas afficher un autre user que vous sans droit perm") + messages.error(request, + "Vous ne pouvez pas afficher un autre user " + "que vous sans droit perm") return redirect("/users/profil/" + str(request.user.id)) emprunts_list = Emprunt.objects.filter(user=users) list_droits = Right.objects.filter(user=users) @@ -259,11 +223,11 @@ def adherer(request, userid): except User.DoesNotExist: messages.error(request, "Utilisateur inexistant") return redirect("/users/") - adh_annee = Adhesion.objects.all().order_by('annee_debut').reverse().first() + adh_year = Adhesion.objects.all().order_by('annee_debut').reverse().first() with transaction.atomic(), reversion.create_revision(): reversion.set_user(request.user) - adh_annee.adherent.add(users) - adh_annee.save() + adh_year.adherent.add(users) + adh_year.save() reversion.set_comment("Adhesion de %s" % users) messages.success(request, "Adhesion effectuee") return redirect("/users/profil/" + userid)