diff --git a/logs/admin.py b/logs/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/logs/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/logs/migrations/__init__.py b/logs/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/logs/models.py b/logs/models.py deleted file mode 100644 index 71a8362..0000000 --- a/logs/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/logs/templatetags/logs_extra.py b/logs/templatetags/logs_extra.py index 3ea14bf..03c2189 100644 --- a/logs/templatetags/logs_extra.py +++ b/logs/templatetags/logs_extra.py @@ -1,29 +1,12 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from django import template register = template.Library() + @register.filter def classname(obj): return obj.__class__.__name__ diff --git a/logs/tests.py b/logs/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/logs/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/logs/urls.py b/logs/urls.py index 63929bf..f0661ac 100644 --- a/logs/urls.py +++ b/logs/urls.py @@ -1,24 +1,6 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from django.conf.urls import url diff --git a/logs/views.py b/logs/views.py index 6168b32..985ded9 100644 --- a/logs/views.py +++ b/logs/views.py @@ -1,58 +1,30 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -# App de gestion des statistiques pour re2o -# Gabriel Détraz -# Gplv2 -from django.http import HttpResponse -from django.shortcuts import render, redirect -from django.shortcuts import get_object_or_404 -from django.template.context_processors import csrf -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from django.template import Context, RequestContext, loader from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required -from django.db.models import ProtectedError -from django.forms import ValidationError -from django.db import transaction +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.db.models import Count - +from django.shortcuts import redirect, render +from django.template.context_processors import csrf from reversion.models import Revision -from reversion.models import Version -from users.models import User from med.settings import PAGINATION_NUMBER as pagination_number +from users.models import User -from django.utils import timezone def form(ctx, template, request): c = ctx c.update(csrf(request)) return render(request, template, c) + @login_required @permission_required('perm') def index(request): - revisions = Revision.objects.all().order_by('date_created').reverse().select_related('user').prefetch_related('version_set__object') + revisions = Revision.objects.all().order_by('date_created').reverse().select_related('user').prefetch_related( + 'version_set__object') paginator = Paginator(revisions, pagination_number) page = request.GET.get('page') try: @@ -61,10 +33,11 @@ def index(request): # If page is not an integer, deliver first page. revisions = paginator.page(1) except EmptyPage: - # If page is out of range (e.g. 9999), deliver last page of results. + # If page is out of range (e.g. 9999), deliver last page of results. revisions = paginator.page(paginator.num_pages) return render(request, 'logs/index.html', {'revisions_list': revisions}) + @login_required @permission_required('bureau') def revert_action(request, revision_id): @@ -72,20 +45,20 @@ def revert_action(request, revision_id): try: revision = Revision.objects.get(id=revision_id) except Revision.DoesNotExist: - messages.error(request, u"Revision inexistante" ) + messages.error(request, u"Revision inexistante") if request.method == "POST": revision.revert() messages.success(request, "L'action a été supprimée") return redirect("/logs/") - return form({'objet': revision, 'objet_name': revision.__class__.__name__ }, 'logs/delete.html', request) + return form({'objet': revision, 'objet_name': revision.__class__.__name__}, 'logs/delete.html', request) + @login_required @permission_required('perm') def stats_actions(request): - onglet = request.GET.get('onglet') stats = { - 'Utilisateur' : { - 'Action' : User.objects.annotate(num=Count('revision')).order_by('-num')[:40], - }, + 'Utilisateur': { + 'Action': User.objects.annotate(num=Count('revision')).order_by('-num')[:40], + }, } return render(request, 'logs/stats_users.html', {'stats_list': stats}) diff --git a/med/__init__.py b/med/__init__.py index 20abb0d..e69de29 100644 --- a/med/__init__.py +++ b/med/__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/med/context_processors.py b/med/context_processors.py index ad6ea7c..040a070 100644 --- a/med/context_processors.py +++ b/med/context_processors.py @@ -1,33 +1,16 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from .settings import SITE_NAME + def context_user(request): user = request.user is_perm = user.has_perms(['perm']) is_bureau = user.has_perms(['bureau']) return { - 'is_perm' : is_perm, + 'is_perm': is_perm, 'is_bureau': is_bureau, 'request_user': user, 'site_name': SITE_NAME, diff --git a/med/login.py b/med/login.py index c320d9a..d940f6d 100644 --- a/med/login.py +++ b/med/login.py @@ -1,18 +1,17 @@ -# -*- coding: utf-8 -*- -# Module d'authentification -# David Sinquin, Gabriel Détraz, Goulven Kermarec +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -import hashlib import binascii +import hashlib import os -from base64 import encodestring from base64 import decodestring +from base64 import encodestring from collections import OrderedDict from django.contrib.auth import hashers - ALGO_NAME = "{SSHA}" ALGO_LEN = len(ALGO_NAME + "$") DIGEST_LEN = 20 @@ -24,6 +23,7 @@ def makeSecret(password): h.update(salt) return ALGO_NAME + "$" + encodestring(h.digest() + salt).decode()[:-1] + def checkPassword(challenge_password, password): challenge_bytes = decodestring(challenge_password[ALGO_LEN:].encode()) digest = challenge_bytes[:DIGEST_LEN] @@ -37,6 +37,7 @@ def checkPassword(challenge_password, password): valid_password &= i == j return valid_password + class SSHAPasswordHasher(hashers.BasePasswordHasher): """ SSHA password hashing to allow for LDAP auth compatibility @@ -70,8 +71,8 @@ class SSHAPasswordHasher(hashers.BasePasswordHasher): return OrderedDict([ ('algorithm', self.algorithm), ('iterations', 0), - ('salt', hashers.mask_hash(hash[2*DIGEST_LEN:], show=2)), - ('hash', hashers.mask_hash(hash[:2*DIGEST_LEN])), + ('salt', hashers.mask_hash(hash[2 * DIGEST_LEN:], show=2)), + ('hash', hashers.mask_hash(hash[:2 * DIGEST_LEN])), ]) def harden_runtime(self, password, encoded): @@ -81,4 +82,3 @@ class SSHAPasswordHasher(hashers.BasePasswordHasher): As we are not using multiple iterations the method is pretty useless """ pass - diff --git a/med/settings.py b/med/settings.py index bbdc225..de2ef98 100644 --- a/med/settings.py +++ b/med/settings.py @@ -1,5 +1,5 @@ # -*- mode: python; coding: utf-8 -*- -# Copyright (C) 2018-2019 by BDE ENS Paris-Saclay +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later import os @@ -103,16 +103,20 @@ DATABASES = { AUTH_PASSWORD_VALIDATORS = [ { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + 'NAME': 'django.contrib.auth.' + 'password_validation.UserAttributeSimilarityValidator', }, { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + 'NAME': 'django.contrib.auth.' + 'password_validation.MinimumLengthValidator', }, { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + 'NAME': 'django.contrib.auth.' + 'password_validation.CommonPasswordValidator', }, { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + 'NAME': 'django.contrib.auth.' + 'password_validation.NumericPasswordValidator', }, ] diff --git a/med/settings_local.example.py b/med/settings_local.example.py index 4fa2d27..aac1333 100644 --- a/med/settings_local.example.py +++ b/med/settings_local.example.py @@ -1,5 +1,5 @@ # -*- mode: python; coding: utf-8 -*- -# Copyright (C) 2018-2019 by BDE ENS Paris-Saclay +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later # Needed to filter which host are trusted diff --git a/med/test b/med/test deleted file mode 100644 index 90fffb5..0000000 --- a/med/test +++ /dev/null @@ -1 +0,0 @@ -create allowed_guests bitmap:ip range 10.231.137.0-10.231.137.255 diff --git a/med/urls.py b/med/urls.py index 26cefa0..18cefaf 100644 --- a/med/urls.py +++ b/med/urls.py @@ -1,39 +1,7 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -"""med URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.8/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') -Including another URLconf - 1. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) -""" from django.conf.urls import include, url from django.contrib import admin from django.contrib.auth import views as auth_views diff --git a/med/views.py b/med/views.py index e58ee37..00f8c19 100644 --- a/med/views.py +++ b/med/views.py @@ -1,36 +1,19 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from django.shortcuts import render -from django.shortcuts import get_object_or_404 from django.template.context_processors import csrf -from django.template import Context, RequestContext, loader + from med.settings import services_urls + def form(ctx, template, request): c = ctx c.update(csrf(request)) return render(request, template, c) + def index(request): i = 0 services = [{}] diff --git a/med/wsgi.py b/med/wsgi.py index 54eb303..db9e1f3 100644 --- a/med/wsgi.py +++ b/med/wsgi.py @@ -1,24 +1,6 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later """ WSGI config for med project. @@ -30,10 +12,10 @@ https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ """ import os -from django.core.wsgi import get_wsgi_application -from os.path import dirname import sys +from os.path import dirname +from django.core.wsgi import get_wsgi_application sys.path.append(dirname(dirname(__file__))) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "med.settings") diff --git a/media/admin.py b/media/admin.py index fc4416f..240a210 100644 --- a/media/admin.py +++ b/media/admin.py @@ -1,21 +1,28 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -from reversion.admin import VersionAdmin from django.contrib import admin -from django.contrib.auth.models import Group +from reversion.admin import VersionAdmin from .models import Auteur, Emprunt, Media, Jeu + class AuteurAdmin(VersionAdmin): list_display = ('nom',) + class MediaAdmin(VersionAdmin): - list_display = ('titre','cote') + list_display = ('titre', 'cote') + class EmpruntAdmin(VersionAdmin): - list_display = ('media','user','date_emprunt', 'date_rendu', 'permanencier_emprunt', 'permanencier_rendu') + list_display = ('media', 'user', 'date_emprunt', 'date_rendu', 'permanencier_emprunt', 'permanencier_rendu') + class JeuAdmin(VersionAdmin): - list_display = ('nom','proprietaire', 'duree', 'nombre_joueurs_min', 'nombre_joueurs_max', 'comment') + list_display = ('nom', 'proprietaire', 'duree', 'nombre_joueurs_min', 'nombre_joueurs_max', 'comment') + admin.site.register(Auteur, AuteurAdmin) admin.site.register(Media, MediaAdmin) diff --git a/media/forms.py b/media/forms.py index 44799ce..cd53d1d 100644 --- a/media/forms.py +++ b/media/forms.py @@ -1,34 +1,19 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -from django.forms import ModelForm, Form, ValidationError from django import forms +from django.forms import ModelForm + from .models import Auteur, Media, Jeu, Emprunt + class AuteurForm(ModelForm): class Meta: model = Auteur fields = '__all__' + class MediaForm(ModelForm): auteur = forms.ModelMultipleChoiceField(Auteur.objects.all(), widget=forms.CheckboxSelectMultiple, required=False) @@ -36,6 +21,7 @@ class MediaForm(ModelForm): model = Media fields = '__all__' + class JeuForm(ModelForm): class Meta: model = Jeu @@ -46,11 +32,13 @@ class JeuForm(ModelForm): raise forms.ValidationError("Max ne peut être inférieur à min") return self.cleaned_data['nombre_joueurs_max'] + class EmpruntForm(ModelForm): class Meta: model = Emprunt fields = ['media'] + class EditEmpruntForm(ModelForm): class Meta: model = Emprunt diff --git a/media/locale/fr/LC_MESSAGES/django.po b/media/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..260d53d --- /dev/null +++ b/media/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-08-02 14:47+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: models.py:13 +msgid "author" +msgstr "" + +#: models.py:14 +msgid "authors" +msgstr "" + +#: models.py:26 +msgid "medium" +msgstr "" + +#: models.py:27 +msgid "media" +msgstr "" + +#: models.py:44 +msgid "borrowed item" +msgstr "" + +#: models.py:45 +msgid "borrowed items" +msgstr "" + +#: models.py:68 +msgid "game" +msgstr "" + +#: models.py:69 +msgid "games" +msgstr "" diff --git a/media/models.py b/media/models.py index ff5d0bf..35b27a5 100644 --- a/media/models.py +++ b/media/models.py @@ -1,5 +1,11 @@ -from django.db import models +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + from django.core.validators import MinValueValidator +from django.db import models +from django.utils.translation import gettext_lazy as _ + class Auteur(models.Model): nom = models.CharField(max_length=255, unique=True) @@ -7,39 +13,53 @@ class Auteur(models.Model): def __str__(self): return self.nom + class Meta: + verbose_name = _("author") + verbose_name_plural = _("authors") + + class Media(models.Model): titre = models.CharField(max_length=255) cote = models.CharField(max_length=31) - auteur = models.ManyToManyField('Auteur') -# type = TODO + auteur = models.ManyToManyField('Auteur') def __str__(self): return str(self.titre) + ' - ' + str(self.auteur.all().first()) + class Meta: + verbose_name = _("medium") + verbose_name_plural = _("media") + + class Emprunt(models.Model): - media = models.ForeignKey('Media', on_delete=models.PROTECT) - user = models.ForeignKey('users.User', on_delete=models.PROTECT) + media = models.ForeignKey('Media', on_delete=models.PROTECT) + user = models.ForeignKey('users.User', on_delete=models.PROTECT) date_emprunt = models.DateTimeField(help_text='%d/%m/%y %H:%M:%S') date_rendu = models.DateTimeField(help_text='%d/%m/%y %H:%M:%S', blank=True, null=True) - permanencier_emprunt = models.ForeignKey('users.User', on_delete=models.PROTECT, related_name='user_permanencier_emprunt') - permanencier_rendu = models.ForeignKey('users.User', on_delete=models.PROTECT, related_name='user_permanencier_rendu', blank=True, null=True) + permanencier_emprunt = models.ForeignKey('users.User', on_delete=models.PROTECT, + related_name='user_permanencier_emprunt') + permanencier_rendu = models.ForeignKey('users.User', on_delete=models.PROTECT, + related_name='user_permanencier_rendu', blank=True, null=True) def __str__(self): return str(self.media) + str(self.user) - + + class Meta: + verbose_name = _("borrowed item") + verbose_name_plural = _("borrowed items") + class Jeu(models.Model): DUREE = ( - ('-1h', '-1h'), - ('1-2h', '1-2h'), - ('2-3h', '2-3h'), - ('3-4h', '3-4h'), - ('4h+', '4h+'), - ) - + ('-1h', '-1h'), + ('1-2h', '1-2h'), + ('2-3h', '2-3h'), + ('3-4h', '3-4h'), + ('4h+', '4h+'), + ) nom = models.CharField(max_length=255) - proprietaire = models.ForeignKey('users.User', on_delete=models.PROTECT) + proprietaire = models.ForeignKey('users.User', on_delete=models.PROTECT) duree = models.CharField(choices=DUREE, max_length=255) nombre_joueurs_min = models.IntegerField(validators=[MinValueValidator(1)]) nombre_joueurs_max = models.IntegerField(validators=[MinValueValidator(1)]) @@ -47,3 +67,7 @@ class Jeu(models.Model): def __str__(self): return str(self.nom) + + class Meta: + verbose_name = _("game") + verbose_name_plural = _("games") diff --git a/media/tests.py b/media/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/media/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/media/urls.py b/media/urls.py index cfc21f4..75d1d88 100644 --- a/media/urls.py +++ b/media/urls.py @@ -1,24 +1,6 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from django.conf.urls import url diff --git a/media/views.py b/media/views.py index ac5ac5e..c36c456 100644 --- a/media/views.py +++ b/media/views.py @@ -1,28 +1,29 @@ -from django.shortcuts import render, redirect -from django.http import HttpResponse -from django.shortcuts import get_object_or_404 -from django.template.context_processors import csrf -from django.template import Context, RequestContext, loader +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from django.contrib.auth import authenticate, login -from django.views.decorators.csrf import csrf_exempt -from django.utils import timezone -from .forms import AuteurForm, MediaForm, JeuForm, EmpruntForm, EditEmpruntForm -from .models import Auteur, Media, Jeu, Emprunt -from users.models import User from django.db import transaction +from django.shortcuts import render, redirect +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 PAGINATION_NUMBER +from users.models import User +from .forms import AuteurForm, MediaForm, JeuForm, EmpruntForm, EditEmpruntForm +from .models import Auteur, Media, Jeu, Emprunt + def form(ctx, template, request): c = ctx c.update(csrf(request)) return render(request, template, c) + @login_required @permission_required('perm') def add_auteur(request): @@ -36,13 +37,14 @@ def add_auteur(request): return redirect("/media/index_auteurs/") return form({'mediaform': auteur}, 'media/media.html', request) + @login_required @permission_required('perm') def edit_auteur(request, auteurid): try: auteur_instance = Auteur.objects.get(pk=auteurid) except Auteur.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_auteurs/") auteur = AuteurForm(request.POST or None, instance=auteur_instance) if auteur.is_valid(): @@ -54,13 +56,14 @@ def edit_auteur(request, auteurid): return redirect("/media/index_auteurs/") return form({'mediaform': auteur}, 'media/media.html', request) + @login_required @permission_required('perm') def del_auteur(request, auteurid): try: auteur_instance = Auteur.objects.get(pk=auteurid) except Auteur.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_auteurs/") if request.method == "POST": with transaction.atomic(), reversion.create_revision(): @@ -84,13 +87,14 @@ def add_media(request): return redirect("/media/index_medias/") return form({'mediaform': media}, 'media/media.html', request) + @login_required @permission_required('perm') def edit_media(request, mediaid): try: media_instance = Media.objects.get(pk=mediaid) except Media.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_medias/") media = MediaForm(request.POST or None, instance=media_instance) if media.is_valid(): @@ -102,13 +106,14 @@ def edit_media(request, mediaid): return redirect("/media/index_medias/") return form({'mediaform': media}, 'media/media.html', request) + @login_required @permission_required('perm') def del_media(request, mediaid): try: media_instance = Media.objects.get(pk=mediaid) except Media.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_medias/") if request.method == "POST": with transaction.atomic(), reversion.create_revision(): @@ -118,6 +123,7 @@ def del_media(request, mediaid): return redirect("/media/index_medias") return form({'objet': media_instance, 'objet_name': 'media'}, 'media/delete.html', request) + @login_required @permission_required('perm') def add_jeu(request): @@ -131,13 +137,14 @@ def add_jeu(request): return redirect("/media/index_jeux/") return form({'mediaform': jeu}, 'media/media.html', request) + @login_required @permission_required('perm') def edit_jeu(request, jeuid): try: jeu_instance = Jeu.objects.get(pk=jeuid) except Jeu.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_jeux/") jeu = JeuForm(request.POST or None, instance=jeu_instance) if jeu.is_valid(): @@ -149,13 +156,14 @@ def edit_jeu(request, jeuid): return redirect("/media/index_jeux/") return form({'mediaform': jeu}, 'media/media.html', request) + @login_required @permission_required('perm') def del_jeu(request, jeuid): try: jeu_instance = Jeu.objects.get(pk=jeuid) except Jeu.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_jeux/") if request.method == "POST": with transaction.atomic(), reversion.create_revision(): @@ -165,13 +173,14 @@ def del_jeu(request, jeuid): return redirect("/media/index_jeux") return form({'objet': jeu_instance, 'objet_name': 'jeu'}, 'media/delete.html', request) + @login_required @permission_required('perm') def add_emprunt(request, userid): try: user = User.objects.get(pk=userid) except User.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_emprunts/") emprunts_en_cours = Emprunt.objects.filter(date_rendu=None, user=user).count() if emprunts_en_cours >= user.maxemprunt: @@ -191,13 +200,14 @@ def add_emprunt(request, userid): return redirect("/media/index_emprunts/") return form({'mediaform': emprunt}, 'media/media.html', request) + @login_required @permission_required('perm') def edit_emprunt(request, empruntid): try: emprunt_instance = Emprunt.objects.get(pk=empruntid) except Emprunt.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_emprunts/") emprunt = EditEmpruntForm(request.POST or None, instance=emprunt_instance) if emprunt.is_valid(): @@ -209,13 +219,14 @@ def edit_emprunt(request, empruntid): return redirect("/media/index_emprunts/") return form({'mediaform': emprunt}, 'media/media.html', request) + @login_required @permission_required('perm') def retour_emprunt(request, empruntid): try: emprunt_instance = Emprunt.objects.get(pk=empruntid) except Emprunt.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_emprunts/") with transaction.atomic(), reversion.create_revision(): emprunt_instance.permanencier_rendu = request.user @@ -225,13 +236,14 @@ def retour_emprunt(request, empruntid): messages.success(request, "Retour enregistré") return redirect("/media/index_emprunts/") + @login_required @permission_required('perm') def del_emprunt(request, empruntid): try: emprunt_instance = Emprunt.objects.get(pk=empruntid) except Emprunt.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/media/index_emprunts/") if request.method == "POST": with transaction.atomic(), reversion.create_revision(): @@ -242,8 +254,6 @@ def del_emprunt(request, empruntid): return form({'objet': emprunt_instance, 'objet_name': 'emprunt'}, 'media/delete.html', request) - - @login_required def index_jeux(request): jeux_list = Jeu.objects.all() @@ -257,7 +267,8 @@ def index_jeux(request): except EmptyPage: # If page is out of range (e.g. 9999), deliver last page of results. jeux_list = paginator.page(paginator.num_pages) - return render(request, 'media/index_jeux.html', {'jeux_list':jeux_list}) + return render(request, 'media/index_jeux.html', {'jeux_list': jeux_list}) + @login_required def index_auteurs(request): @@ -272,7 +283,8 @@ def index_auteurs(request): except EmptyPage: # If page is out of range (e.g. 9999), deliver last page of results. auteurs_list = paginator.page(paginator.num_pages) - return render(request, 'media/index_auteurs.html', {'auteurs_list':auteurs_list}) + return render(request, 'media/index_auteurs.html', {'auteurs_list': auteurs_list}) + @login_required def index_medias(request): @@ -287,7 +299,7 @@ def index_medias(request): except EmptyPage: # If page is out of range (e.g. 9999), deliver last page of results. medias_list = paginator.page(paginator.num_pages) - return render(request, 'media/index_medias.html', {'medias_list':medias_list}) + return render(request, 'media/index_medias.html', {'medias_list': medias_list}) @login_required @@ -306,35 +318,35 @@ def index(request): except EmptyPage: # If page is out of range (e.g. 9999), deliver last page of results. emprunts_list = paginator.page(paginator.num_pages) - return render(request, 'media/index_emprunts.html', {'emprunts_list':emprunts_list}) + return render(request, 'media/index_emprunts.html', {'emprunts_list': emprunts_list}) @login_required def history(request, object, id): if object == 'auteur': try: - object_instance = Auteur.objects.get(pk=id) + object_instance = Auteur.objects.get(pk=id) except Auteur.DoesNotExist: - messages.error(request, "Auteur inexistant") - return redirect("/media/index_auteurs") + messages.error(request, "Auteur inexistant") + return redirect("/media/index_auteurs") elif object == 'media': try: - object_instance = Media.objects.get(pk=id) + object_instance = Media.objects.get(pk=id) except Media.DoesNotExist: - messages.error(request, "Media inexistant") - return redirect("/media/index_medias") + messages.error(request, "Media inexistant") + return redirect("/media/index_medias") elif object == 'emprunt': try: - object_instance = Emprunt.objects.get(pk=id) + object_instance = Emprunt.objects.get(pk=id) except Emprunt.DoesNotExist: - messages.error(request, "Emprunt inexistant") - return redirect("/media/index_emprunts") + messages.error(request, "Emprunt inexistant") + return redirect("/media/index_emprunts") elif object == 'jeu': try: - object_instance = Jeu.objects.get(pk=id) + object_instance = Jeu.objects.get(pk=id) except Jeu.DoesNotExist: - messages.error(request, "Jeu inexistant") - return redirect("/media/index_jeux") + messages.error(request, "Jeu inexistant") + return redirect("/media/index_jeux") reversions = Version.objects.get_for_object(object_instance) paginator = Paginator(reversions, PAGINATION_NUMBER) page = request.GET.get('page') @@ -347,4 +359,3 @@ def history(request, object, id): # 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}) - diff --git a/search/admin.py b/search/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/search/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/search/forms.py b/search/forms.py index 18f8ffe..47bac83 100644 --- a/search/forms.py +++ b/search/forms.py @@ -1,29 +1,9 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -from django.db import models from django import forms from django.forms import Form -from django.forms import ModelForm CHOICES = ( ('0', 'Actifs'), @@ -37,14 +17,18 @@ CHOICES2 = ( ('2', 'Emprunts'), ('3', 'Jeu'), ) - + class SearchForm(Form): - search_field = forms.CharField(label = 'Search', max_length = 100) + search_field = forms.CharField(label='Search', max_length=100) + class SearchFormPlus(Form): - search_field = forms.CharField(label = 'Search', max_length = 100, required=False) - filtre = forms.MultipleChoiceField(label="Filtre utilisateurs", required=False, widget =forms.CheckboxSelectMultiple,choices=CHOICES) - affichage = forms.MultipleChoiceField(label="Filtre affichage", required=False, widget =forms.CheckboxSelectMultiple,choices=CHOICES2) - date_deb = forms.DateField(required=False, label="Date de début", help_text='DD/MM/YYYY', input_formats=['%d/%m/%Y']) + search_field = forms.CharField(label='Search', max_length=100, required=False) + filtre = forms.MultipleChoiceField(label="Filtre utilisateurs", required=False, widget=forms.CheckboxSelectMultiple, + choices=CHOICES) + affichage = forms.MultipleChoiceField(label="Filtre affichage", required=False, widget=forms.CheckboxSelectMultiple, + choices=CHOICES2) + date_deb = forms.DateField(required=False, label="Date de début", help_text='DD/MM/YYYY', + input_formats=['%d/%m/%Y']) date_fin = forms.DateField(required=False, help_text='DD/MM/YYYY', input_formats=['%d/%m/%Y'], label="Date de fin") diff --git a/search/migrations/__init__.py b/search/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/search/models.py b/search/models.py deleted file mode 100644 index 71a8362..0000000 --- a/search/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/search/tests.py b/search/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/search/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/search/urls.py b/search/urls.py index bee0785..0ad67f6 100644 --- a/search/urls.py +++ b/search/urls.py @@ -1,24 +1,6 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from django.conf.urls import url diff --git a/search/views.py b/search/views.py index d73bf9d..1b0e00d 100644 --- a/search/views.py +++ b/search/views.py @@ -1,60 +1,37 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -# App de recherche pour re2o -# Augustin lemesle, Gabriel Détraz, Goulven Kermarec -# Gplv2 -from django.shortcuts import render -from django.shortcuts import get_object_or_404 -from django.template.context_processors import csrf -from django.template import Context, RequestContext, loader from django.contrib.auth.decorators import login_required - from django.db.models import Q -from users.models import User -from search.forms import SearchForm, SearchFormPlus +from django.shortcuts import render +from django.template.context_processors import csrf from med.settings import SEARCH_DISPLAY_PAGE - from media.models import Media, Jeu, Emprunt +from search.forms import SearchForm, SearchFormPlus +from users.models import User + def form(ctx, template, request): c = ctx c.update(csrf(request)) return render(request, template, c) + def search_result(search, type, request): date_deb = None date_fin = None - states=[] - aff=[] - if(type): + states = [] + aff = [] + if (type): aff = search.cleaned_data['affichage'] states = search.cleaned_data['filtre'] date_deb = search.cleaned_data['date_deb'] date_fin = search.cleaned_data['date_fin'] date_query = Q() - if aff==[]: - aff = ['0','1','2','3'] + if aff == []: + aff = ['0', '1', '2', '3'] if date_deb != None: date_query = date_query & Q(date_emprunt__gte=date_deb) if date_fin != None: @@ -62,32 +39,36 @@ def search_result(search, type, request): search = search.cleaned_data['search_field'] query1 = Q() for s in states: - query1 = query1 | Q(state = s) - - connexion = [] - - recherche = {'users_list': None, 'emprunts_list' : None, 'medias_list' : None, 'jeux_list': None} + query1 = query1 | Q(state=s) + + connexion = [] + + recherche = {'users_list': None, 'emprunts_list': None, 'medias_list': None, 'jeux_list': None} if request.user.has_perms(('perm',)): - query = Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search) + query = Q(user__pseudo__icontains=search) | Q(user__name__icontains=search) | Q(user__surname__icontains=search) else: - query = (Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search)) & Q(user = request.user) - + query = (Q(user__pseudo__icontains=search) | Q(user__name__icontains=search) | Q( + user__surname__icontains=search)) & Q(user=request.user) for i in aff: if i == '0': - query_user_list = Q(pseudo__icontains = search) | Q(name__icontains = search) | Q(surname__icontains = search) & query1 + query_user_list = Q(pseudo__icontains=search) | Q(name__icontains=search) | Q( + surname__icontains=search) & query1 if request.user.has_perms(('perm',)): recherche['users_list'] = User.objects.filter(query_user_list).order_by('state', 'surname') - else : - recherche['users_list'] = User.objects.filter(query_user_list & Q(id=request.user.id)).order_by('state', 'surname') + else: + recherche['users_list'] = User.objects.filter(query_user_list & Q(id=request.user.id)).order_by('state', + 'surname') if i == '1': recherche['emprunts_list'] = Emprunt.objects.filter(query & date_query).order_by('date_emprunt').reverse() if i == '2': - recherche['medias_list'] = Media.objects.filter(Q(auteur__nom__icontains = search) | Q(titre__icontains = search)) + recherche['medias_list'] = Media.objects.filter( + Q(auteur__nom__icontains=search) | Q(titre__icontains=search)) if i == '3': - recherche['jeux_list'] = Jeu.objects.filter(Q(nom__icontains = search) | Q(proprietaire__pseudo__icontains = search) | Q(proprietaire__name__icontains = search) | Q(proprietaire__surname__icontains = search)) - + recherche['jeux_list'] = Jeu.objects.filter( + Q(nom__icontains=search) | Q(proprietaire__pseudo__icontains=search) | Q( + proprietaire__name__icontains=search) | Q(proprietaire__surname__icontains=search)) for r in recherche: if recherche[r] != None: @@ -97,17 +78,18 @@ def search_result(search, type, request): return recherche + @login_required def search(request): search = SearchForm(request.POST or None) if search.is_valid(): - return form(search_result(search, False, request), 'search/index.html',request) - return form({'searchform' : search}, 'search/search.html', request) + return form(search_result(search, False, request), 'search/index.html', request) + return form({'searchform': search}, 'search/search.html', request) + @login_required def searchp(request): search = SearchFormPlus(request.POST or None) if search.is_valid(): - return form(search_result(search, True, request), 'search/index.html',request) - return form({'searchform' : search}, 'search/search.html', request) - + return form(search_result(search, True, request), 'search/index.html', request) + return form({'searchform': search}, 'search/search.html', request) diff --git a/users/admin.py b/users/admin.py index a50c430..9d4a61b 100644 --- a/users/admin.py +++ b/users/admin.py @@ -1,32 +1,14 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from django.contrib import admin -from django.contrib.auth.models import Group from django.contrib.auth.admin import UserAdmin as BaseUserAdmin +from django.contrib.auth.models import Group from reversion.admin import VersionAdmin -from .models import User, Right, Adhesion, ListRight, Clef, Request from .forms import UserChangeForm, UserCreationForm +from .models import User, Right, Adhesion, ListRight, Clef, Request class UserAdmin(admin.ModelAdmin): @@ -37,23 +19,29 @@ class UserAdmin(admin.ModelAdmin): 'email', 'state' ) - search_fields = ('name','surname','pseudo') + search_fields = ('name', 'surname', 'pseudo') + class RequestAdmin(admin.ModelAdmin): list_display = ('user', 'type', 'created_at', 'expires_at') + class RightAdmin(VersionAdmin): list_display = ('user', 'right') + class ClefAdmin(VersionAdmin): list_display = ('proprio', 'nom') + class AdhesionAdmin(VersionAdmin): list_display = ('annee_debut', 'annee_fin') + class ListRightAdmin(VersionAdmin): list_display = ('listright',) + class UserAdmin(VersionAdmin, BaseUserAdmin): # The forms to add and change user instances form = UserChangeForm @@ -67,7 +55,7 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): fieldsets = ( (None, {'fields': ('pseudo', 'password')}), ('Personal info', {'fields': ('name', 'surname', 'email')}), - ('Permissions', {'fields': ('is_admin', )}), + ('Permissions', {'fields': ('is_admin',)}), ) # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin # overrides get_fieldsets to use this attribute when creating a user. @@ -75,12 +63,13 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): (None, { 'classes': ('wide',), 'fields': ('pseudo', 'name', 'surname', 'email', 'is_admin', 'password1', 'password2')} - ), + ), ) search_fields = ('pseudo',) ordering = ('pseudo',) filter_horizontal = () + admin.site.register(User, UserAdmin) admin.site.register(Request, RequestAdmin) admin.site.register(ListRight, ListRightAdmin) diff --git a/users/decorators.py b/users/decorators.py index c71a6e8..0046ee6 100644 --- a/users/decorators.py +++ b/users/decorators.py @@ -1,46 +1,29 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -# App de gestion des users pour med -# Goulven Kermarec, Gabriel Détraz, Lemesle Augustin -# Gplv2 - - -from django.core.exceptions import PermissionDenied -from django.shortcuts import redirect -from med.settings import AUTHORIZED_IP_RANGE, AUTHORIZED_IP6_RANGE 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): + 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. diff --git a/users/forms.py b/users/forms.py index d054db5..742d4c2 100644 --- a/users/forms.py +++ b/users/forms.py @@ -1,46 +1,29 @@ -# 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. - -# -*- coding: utf-8 -*- - +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from django import forms -from django.forms import ModelForm, Form from django.contrib.auth.forms import ReadOnlyPasswordHashField from django.core.validators import MinLengthValidator -from django.utils import timezone +from django.forms import ModelForm, Form + +from .models import Adhesion, Clef, ListRight, Right, User -from .models import Adhesion, Clef, ListRight, Right, Request, 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 UserCreationForm(forms.ModelForm): """A form for creating new users. Includes all the required fields, plus a repeated password.""" - password1 = forms.CharField(label='Password', widget=forms.PasswordInput, validators=[MinLengthValidator(8)], max_length=255) - password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput, validators=[MinLengthValidator(8)], max_length=255) + password1 = forms.CharField(label='Password', widget=forms.PasswordInput, validators=[MinLengthValidator(8)], + max_length=255) + password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput, + validators=[MinLengthValidator(8)], max_length=255) is_admin = forms.BooleanField(label='is admin') class Meta: @@ -95,16 +78,18 @@ class UserChangeForm(forms.ModelForm): user.save() return user + class ResetPasswordForm(forms.Form): pseudo = forms.CharField(label=u'Pseudo', max_length=255) email = forms.EmailField(max_length=255) + class BaseInfoForm(ModelForm): def __init__(self, *args, **kwargs): super(BaseInfoForm, self).__init__(*args, **kwargs) self.fields['name'].label = 'Prénom' self.fields['surname'].label = 'Nom' - #self.fields['comment'].label = 'Commentaire' + # self.fields['comment'].label = 'Commentaire' class Meta: model = User @@ -117,9 +102,10 @@ class BaseInfoForm(ModelForm): 'adresse', ] + class InfoForm(BaseInfoForm): class Meta(BaseInfoForm.Meta): - fields = [ + fields = [ 'name', 'pseudo', 'surname', @@ -135,22 +121,26 @@ class PasswordForm(ModelForm): model = User fields = ['password'] + class StateForm(ModelForm): class Meta: model = User fields = ['state'] + class ClefForm(ModelForm): class Meta: model = Clef fields = '__all__' + class BaseClefForm(ClefForm): class Meta(ClefForm.Meta): - fields = [ + fields = [ 'commentaire', ] + class AdhesionForm(ModelForm): adherent = forms.ModelMultipleChoiceField(User.objects.all(), widget=forms.CheckboxSelectMultiple, required=False) @@ -158,6 +148,7 @@ class AdhesionForm(ModelForm): model = Adhesion fields = '__all__' + class RightForm(ModelForm): def __init__(self, *args, **kwargs): super(RightForm, self).__init__(*args, **kwargs) @@ -170,12 +161,13 @@ class RightForm(ModelForm): class DelRightForm(Form): - rights = forms.ModelMultipleChoiceField(queryset=Right.objects.all(), 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: model = ListRight @@ -185,11 +177,12 @@ class ListRightForm(ModelForm): super(ListRightForm, self).__init__(*args, **kwargs) self.fields['listright'].label = 'Nom du droit/groupe' + class NewListRightForm(ListRightForm): class Meta(ListRightForm.Meta): fields = '__all__' + class DelListRightForm(Form): - listrights = forms.ModelMultipleChoiceField(queryset=ListRight.objects.all(), label="Droits actuels", widget=forms.CheckboxSelectMultiple) - - + listrights = forms.ModelMultipleChoiceField(queryset=ListRight.objects.all(), label="Droits actuels", + widget=forms.CheckboxSelectMultiple) diff --git a/users/locale/fr/LC_MESSAGES/django.po b/users/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..3f0fd52 --- /dev/null +++ b/users/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,22 @@ +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-08-02 14:42+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: models.py:195 +msgid "right" +msgstr "" + +#: models.py:196 +msgid "rights" +msgstr "" diff --git a/users/models.py b/users/models.py index 65a99e8..6895b24 100644 --- a/users/models.py +++ b/users/models.py @@ -1,39 +1,16 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later +import datetime +import uuid + +from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from django.db import models -from django.db.models import Q -from django.db.models.signals import post_save, post_delete -from django.dispatch import receiver -from django.utils.functional import cached_property - +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ from med.settings import MAX_EMPRUNT, REQ_EXPIRE_HRS -import re, uuid -import datetime - -from django.utils import timezone -from django.contrib.auth.models import AbstractBaseUser, BaseUserManager -import subprocess class UserManager(BaseUserManager): @@ -75,23 +52,23 @@ class User(AbstractBaseUser): STATE_DISABLED = 1 STATE_ARCHIVE = 2 STATES = ( - (0, 'STATE_ACTIVE'), - (1, 'STATE_DISABLED'), - (2, 'STATE_ARCHIVE'), - ) + (0, 'STATE_ACTIVE'), + (1, 'STATE_DISABLED'), + (2, 'STATE_ARCHIVE'), + ) name = models.CharField(max_length=255) surname = models.CharField(max_length=255) email = models.EmailField() telephone = models.CharField(max_length=15, null=True, blank=True) adresse = models.CharField(max_length=255, null=True, blank=True) - maxemprunt = models.IntegerField(default=MAX_EMPRUNT, help_text="Maximum d'emprunts autorisés") + maxemprunt = models.IntegerField(default=MAX_EMPRUNT, help_text="Maximum d'emprunts autorisés") state = models.IntegerField(choices=STATES, default=STATE_ACTIVE) - pseudo = models.CharField(max_length=32, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets. ") + pseudo = models.CharField(max_length=32, unique=True, + help_text="Doit contenir uniquement des lettres, chiffres, ou tirets. ") comment = models.CharField(help_text="Commentaire, promo", max_length=255, blank=True) registered = models.DateTimeField(auto_now_add=True) - USERNAME_FIELD = 'pseudo' REQUIRED_FIELDS = ['name', 'surname', 'email'] @@ -150,16 +127,16 @@ class User(AbstractBaseUser): def get_admin_right(self): admin, created = ListRight.objects.get_or_create(listright="admin") - return admin + return admin def make_admin(self): """ Make User admin """ user_admin_right = Right(user=self, right=self.get_admin_right()) user_admin_right.save() - + def un_admin(self): try: - user_right = Right.objects.get(user=self,right=self.get_admin_right()) + user_right = Right.objects.get(user=self, right=self.get_admin_right()) except Right.DoesNotExist: return user_right.delete() @@ -184,40 +161,44 @@ class Request(models.Model): def save(self): if not self.expires_at: self.expires_at = timezone.now() \ - + datetime.timedelta(hours=REQ_EXPIRE_HRS) + + datetime.timedelta(hours=REQ_EXPIRE_HRS) if not self.token: self.token = str(uuid.uuid4()).replace('-', '') # remove hyphens super(Request, self).save() + class Right(models.Model): PRETTY_NAME = "Droits affectés à des users" - + user = models.ForeignKey('User', on_delete=models.PROTECT) right = models.ForeignKey('ListRight', on_delete=models.PROTECT) - + class Meta: + verbose_name = _("right") + verbose_name_plural = _("rights") unique_together = ("user", "right") - + def __str__(self): return str(self.user) + 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) - + def __str__(self): return self.listright + class Clef(models.Model): nom = models.CharField(max_length=255, unique=True) proprio = models.ForeignKey('User', on_delete=models.PROTECT, blank=True, null=True) commentaire = models.CharField(max_length=255, null=True, blank=True) + class Adhesion(models.Model): annee_debut = models.IntegerField(unique=True) annee_fin = models.IntegerField(unique=True) adherent = models.ManyToManyField('User', blank=True) - - diff --git a/users/tests.py b/users/tests.py deleted file mode 100644 index 21fa6d2..0000000 --- a/users/tests.py +++ /dev/null @@ -1,25 +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. - -from django.test import TestCase - -# Create your tests here. diff --git a/users/urls.py b/users/urls.py index c924679..b75132f 100644 --- a/users/urls.py +++ b/users/urls.py @@ -1,24 +1,6 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later from django.conf.urls import url @@ -56,5 +38,3 @@ urlpatterns = [ 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 3dd1894..bae086a 100644 --- a/users/views.py +++ b/users/views.py @@ -1,52 +1,29 @@ -# 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. +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later -# App de gestion des users pour med -# Goulven Kermarec, Gabriel Détraz, Lemesle Augustin -# Gplv2 -from django.shortcuts import get_object_or_404, render, redirect -from django.template.context_processors import csrf -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from django.template import Context, RequestContext, loader from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required -from django.contrib.auth.signals import user_logged_in -from django.db.models import Max, ProtectedError -from django.db import IntegrityError from django.core.mail import send_mail -from django.utils import timezone +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.urlresolvers import reverse +from django.db import IntegrityError from django.db import transaction - -from reversion.models import Version +from django.db.models import ProtectedError +from django.shortcuts import get_object_or_404, render, redirect +from django.template import loader +from django.template.context_processors import csrf +from django.utils import timezone from reversion import revisions as reversion -from users.forms import DelListRightForm, NewListRightForm, ListRightForm, RightForm, DelRightForm -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 reversion.models import Version from med.settings import REQ_EXPIRE_STR, EMAIL_FROM, ASSO_NAME, ASSO_EMAIL, SITE_NAME, PAGINATION_NUMBER +from media.models import Emprunt +from users.decorators import user_is_in_campus +from users.forms import DelListRightForm, NewListRightForm, ListRightForm, RightForm, DelRightForm +from users.forms import InfoForm, BaseInfoForm, StateForm, ClefForm, AdhesionForm +from users.forms import PassForm, ResetPasswordForm +from users.models import User, Request, ListRight, Right, Clef, Adhesion def form(ctx, template, request): @@ -54,6 +31,7 @@ def form(ctx, template, request): c.update(csrf(request)) return render(request, template, c) + def password_change_action(u_form, user, request, req=False): """ Fonction qui effectue le changeemnt de mdp bdd""" if u_form.cleaned_data['passwd1'] != u_form.cleaned_data['passwd2']: @@ -69,20 +47,21 @@ def password_change_action(u_form, user, request, req=False): return redirect("/") return redirect("/users/profil/" + str(user.id)) + def reset_passwd_mail(req, request): """ Prend en argument un request, envoie un mail de réinitialisation de mot de pass """ t = loader.get_template('users/email_passwd_request') c = { - 'name': str(req.user.name) + ' ' + str(req.user.surname), - 'asso': ASSO_NAME, - 'asso_mail': ASSO_EMAIL, - 'site_name': SITE_NAME, - 'url': request.build_absolute_uri( - reverse('users:process', kwargs={'token': req.token})), - 'expire_in': REQ_EXPIRE_STR, + 'name': str(req.user.name) + ' ' + str(req.user.surname), + 'asso': ASSO_NAME, + 'asso_mail': ASSO_EMAIL, + 'site_name': SITE_NAME, + 'url': request.build_absolute_uri( + reverse('users:process', kwargs={'token': req.token})), + 'expire_in': REQ_EXPIRE_STR, } send_mail('Votre compte %s' % SITE_NAME, t.render(c), - EMAIL_FROM, [req.user.email], fail_silently=False) + EMAIL_FROM, [req.user.email], fail_silently=False) return @@ -101,10 +80,12 @@ def new_user(request): req.user = user 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.pseudo) + messages.success(request, + "L'utilisateur %s a été crée, un mail pour l'initialisation du mot de passe a été envoyé" % user.pseudo) 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 """ @@ -129,6 +110,7 @@ def edit_info(request, userid): return redirect("/users/profil/" + userid) return form({'userform': user}, 'users/user.html', request) + @login_required @permission_required('bureau') def state(request, userid): @@ -148,6 +130,7 @@ def state(request, userid): return redirect("/users/profil/" + userid) return form({'userform': state}, 'users/user.html', request) + @login_required def password(request, userid): """ Reinitialisation d'un mot de passe à partir de l'userid, @@ -166,6 +149,7 @@ def password(request, userid): return password_change_action(u_form, user, request) return form({'userform': u_form}, 'users/user.html', request) + @login_required @permission_required('bureau') def add_listright(request): @@ -181,6 +165,7 @@ def add_listright(request): return redirect("/users/index_listright/") return form({'userform': listright}, 'users/user.html', request) + @login_required @permission_required('bureau') def edit_listright(request, listrightid): @@ -188,7 +173,7 @@ def edit_listright(request, listrightid): try: listright_instance = ListRight.objects.get(pk=listrightid) except ListRight.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/users/") listright = ListRightForm(request.POST or None, instance=listright_instance) if listright.is_valid(): @@ -200,6 +185,7 @@ def edit_listright(request, listrightid): return redirect("/users/index_listright/") return form({'userform': listright}, 'users/user.html', request) + @login_required @permission_required('bureau') def del_listright(request): @@ -221,6 +207,7 @@ def del_listright(request): return redirect("/users/index_listright/") return form({'userform': listright}, 'users/user.html', request) + @login_required @permission_required('bureau') def add_right(request, userid): @@ -245,30 +232,34 @@ def add_right(request, userid): return redirect("/users/profil/" + userid) return form({'userform': right}, 'users/user.html', request) + @login_required @permission_required('bureau') def del_right(request): """ Supprimer un droit à un user, need droit bureau """ user_right_list = dict() for right in ListRight.objects.all(): - user_right_list[right]= DelRightForm(right, request.POST or None) + 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)) + 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') def index_listright(request): """ Affiche l'ensemble des droits , need droit perm """ listright_list = ListRight.objects.order_by('listright') - return render(request, 'users/index_listright.html', {'listright_list':listright_list}) + return render(request, 'users/index_listright.html', {'listright_list': listright_list}) + @login_required @permission_required('bureau') @@ -283,12 +274,13 @@ def add_clef(request): return redirect("/users/index_clef/") return form({'userform': clef}, 'users/user.html', request) + @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" ) + messages.error(request, u"Entrée inexistante") return redirect("/users/index_clef/") clef = ClefForm(request.POST or None, instance=clef_instance) if clef.is_valid(): @@ -301,13 +293,14 @@ def edit_clef(request, clefid): return redirect("/users/index_clef/") return form({'userform': clef}, 'users/user.html', request) + @login_required @permission_required('bureau') def del_clef(request, clefid): try: clef_instance = Clef.objects.get(pk=clefid) except Clef.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/users/index_clef/") if request.method == "POST": with transaction.atomic(), reversion.create_revision(): @@ -317,10 +310,12 @@ def del_clef(request, clefid): return redirect("/users/index_clef") return form({'objet': clef_instance, 'objet_name': 'clef'}, 'users/delete.html', request) + @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}) + return render(request, 'users/index_clef.html', {'clef_list': clef_list}) + @login_required @permission_required('bureau') @@ -335,13 +330,14 @@ def add_adhesion(request): return redirect("/users/index_adhesion/") return form({'userform': adhesion}, 'users/user.html', request) + @login_required @permission_required('bureau') def edit_adhesion(request, adhesionid): try: adhesion_instance = Adhesion.objects.get(pk=adhesionid) except Adhesion.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/users/index_adhesion/") adhesion = AdhesionForm(request.POST or None, instance=adhesion_instance) if adhesion.is_valid(): @@ -353,13 +349,14 @@ def edit_adhesion(request, adhesionid): return redirect("/users/index_adhesion/") return form({'userform': adhesion}, 'users/user.html', request) + @login_required @permission_required('bureau') def del_adhesion(request, adhesionid): try: adhesion_instance = Adhesion.objects.get(pk=adhesionid) except Adhesion.DoesNotExist: - messages.error(request, u"Entrée inexistante" ) + messages.error(request, u"Entrée inexistante") return redirect("/users/index_adhesion/") if request.method == "POST": with transaction.atomic(), reversion.create_revision(): @@ -369,10 +366,12 @@ def del_adhesion(request, adhesionid): return redirect("/users/index_adhesion") return form({'objet': adhesion_instance, 'objet_name': 'adhesion'}, 'users/delete.html', request) + @login_required def index_adhesion(request): adhesion_list = Adhesion.objects.all() - return render(request, 'users/index_adhesion.html', {'adhesion_list':adhesion_list}) + return render(request, 'users/index_adhesion.html', {'adhesion_list': adhesion_list}) + @login_required @permission_required('perm') @@ -391,6 +390,7 @@ def index(request): users_list = paginator.page(paginator.num_pages) return render(request, 'users/index.html', {'users_list': users_list}) + @login_required @permission_required('perm') def index_ajour(request): @@ -408,46 +408,48 @@ def index_ajour(request): users_list = paginator.page(paginator.num_pages) 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) + object_instance = Clef.objects.get(pk=id) except Clef.DoesNotExist: - messages.error(request, "Utilisateur inexistant") - return redirect("/users/") + 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) + object_instance = User.objects.get(pk=id) except User.DoesNotExist: - messages.error(request, "Utilisateur inexistant") - return redirect("/users/") + 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)) + 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) + object_instance = Clef.objects.get(pk=id) except Clef.DoesNotExist: - messages.error(request, "Utilisateur inexistant") - return redirect("/users/") + messages.error(request, "Utilisateur inexistant") + return redirect("/users/") elif object == 'adhesion': try: - object_instance = Adhesion.objects.get(pk=id) + object_instance = Adhesion.objects.get(pk=id) except Adhesion.DoesNotExist: - messages.error(request, "Utilisateur inexistant") - return redirect("/users/") + messages.error(request, "Utilisateur inexistant") + return redirect("/users/") elif object == 'listright': try: - object_instance = ListRight.objects.get(pk=id) + object_instance = ListRight.objects.get(pk=id) except ListRight.DoesNotExist: - messages.error(request, "Droit inexistant") - return redirect("/users/") + messages.error(request, "Droit inexistant") + return redirect("/users/") else: messages.error(request, "Objet inconnu") return redirect("/users/") @@ -464,10 +466,12 @@ def history(request, object, id): 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)) + @login_required def profil(request, userid): try: @@ -486,10 +490,11 @@ def profil(request, userid): { 'user': users, 'emprunts_list': emprunts_list, - 'list_droits': list_droits, + 'list_droits': list_droits, } ) + @login_required @permission_required('bureau') def adherer(request, userid): @@ -506,13 +511,13 @@ def adherer(request, userid): reversion.set_comment("Adhesion de %s" % users) messages.success(request, "Adhesion effectuee") return redirect("/users/profil/" + userid) - + def reset_password(request): userform = ResetPasswordForm(request.POST or None) if userform.is_valid(): try: - user = User.objects.get(pseudo=userform.cleaned_data['pseudo'],email=userform.cleaned_data['email']) + user = User.objects.get(pseudo=userform.cleaned_data['pseudo'], email=userform.cleaned_data['email']) except User.DoesNotExist: messages.error(request, "Cet utilisateur n'existe pas") return form({'userform': userform}, 'users/user.html', request) @@ -525,6 +530,7 @@ def reset_password(request): redirect("/") return form({'userform': userform}, 'users/user.html', request) + def process(request, token): valid_reqs = Request.objects.filter(expires_at__gt=timezone.now()) req = get_object_or_404(valid_reqs, token=token) @@ -537,6 +543,7 @@ def process(request, token): messages.error(request, "Entrée incorrecte, contactez un admin") redirect("/") + def process_passwd(request, req): u_form = PassForm(request.POST or None) user = req.user