From 27464ffa6f213f51031414de3f120afa2bd864f6 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Tue, 26 Jun 2018 16:46:57 +0000 Subject: [PATCH 01/24] =?UTF-8?q?Cr=C3=A9e=20des=20comptes=20mail=20et=20d?= =?UTF-8?q?es=20alias=20mail?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/forms.py | 1 + machines/models.py | 4 + re2o/templatetags/acl.py | 1 - users/admin.py | 2 + users/forms.py | 14 +++ users/models.py | 117 ++++++++++++++++++++++++- users/templates/users/aff_alias.html | 53 +++++++++++ users/templates/users/index_alias.html | 37 ++++++++ users/urls.py | 3 + users/views.py | 60 +++++++++++++ 10 files changed, 289 insertions(+), 3 deletions(-) create mode 100644 users/templates/users/aff_alias.html create mode 100644 users/templates/users/index_alias.html diff --git a/machines/forms.py b/machines/forms.py index 23c2aa39..241ce303 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -262,6 +262,7 @@ class ExtensionForm(FormRevMixin, ModelForm): self.fields['origin'].label = 'Enregistrement A origin' self.fields['origin_v6'].label = 'Enregistrement AAAA origin' self.fields['soa'].label = 'En-tête SOA à utiliser' + self.fielss['mail_extension'].label = 'Utilisable comme extension mail' class DelExtensionForm(FormRevMixin, Form): diff --git a/machines/models.py b/machines/models.py index 7be76e74..c8dccadf 100644 --- a/machines/models.py +++ b/machines/models.py @@ -546,6 +546,10 @@ class Extension(RevMixin, AclMixin, models.Model): 'SOA', on_delete=models.CASCADE ) + mail_extension = models.BooleanField( + default=False, + help_text="Determine si l'extension peut être utilisée comme extension mail interne" + ) class Meta: permissions = ( diff --git a/re2o/templatetags/acl.py b/re2o/templatetags/acl.py index fe13c5ac..9a439f88 100644 --- a/re2o/templatetags/acl.py +++ b/re2o/templatetags/acl.py @@ -79,7 +79,6 @@ from django.contrib.contenttypes.models import ContentType register = template.Library() - def get_model(model_name): """Retrieve the model object from its name""" splitted = model_name.split('.') diff --git a/users/admin.py b/users/admin.py index a902d2e2..5f4c197b 100644 --- a/users/admin.py +++ b/users/admin.py @@ -34,6 +34,8 @@ from reversion.admin import VersionAdmin from .models import ( User, + Mail, + MailAlias, ServiceUser, School, ListRight, diff --git a/users/forms.py b/users/forms.py index 670fbb98..ba8e137e 100644 --- a/users/forms.py +++ b/users/forms.py @@ -53,6 +53,7 @@ from .models import ( School, ListRight, Whitelist, + MailAlias, ListShell, Ban, Adherent, @@ -590,3 +591,16 @@ class WhitelistForm(FormRevMixin, ModelForm): model = Whitelist exclude = ['user'] widgets = {'date_end':DateTimePicker} + + +class MailAliasForm(FormRevMixin, ModelForm): + """Creation, edition d'un objet alias mail""" + def __init__(self, *args, **kwargs): + prefix = kwargs.pop('prefix', self.Meta.model.__name__) + super(MailAliasForm, self).__init__(*args, prefix=prefix, **kwargs) + self.fields['valeur'].label = 'nom de l\'adresse mail' + self.fields['extension'].label = 'extension de l\'adresse mail' + + class Meta: + model = MailAlias + exclude = ['mail'] diff --git a/users/models.py b/users/models.py index 067a0346..61f58920 100644 --- a/users/models.py +++ b/users/models.py @@ -79,7 +79,7 @@ from re2o.field_permissions import FieldPermissionModelMixin from re2o.mixins import AclMixin, RevMixin from cotisations.models import Cotisation, Facture, Paiement, Vente -from machines.models import Domain, Interface, Machine, regen +from machines.models import Domain, Interface, Machine, regen, Extension from preferences.models import GeneralOption, AssoOption, OptionalUser from preferences.models import OptionalMachine, MailMessageOption @@ -195,6 +195,12 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, validators=[linux_user_validator] ) email = models.EmailField() + """ + email= models.OneToOneField( + Mail, + on_delete=models.PROTECT + ) + """ school = models.ForeignKey( 'School', on_delete=models.PROTECT, @@ -246,7 +252,9 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ("view_user", "Peut voir un objet user quelquonque"), ) - + + + @cached_property def name(self): """Si il s'agit d'un adhérent, on renvoie le prénom""" @@ -674,6 +682,15 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, self.pwd_ntlm = hashNT(password) return + def get_mail(self): + """ + Return the mail address choosen by the user + """ + if not self.mail.internal_activated: + return(self.mail.external) + else: + return(self.mail.mailalias_set.first()) + def get_next_domain_name(self): """Look for an available name for a new interface for this user by trying "pseudo0", "pseudo1", "pseudo2", ... @@ -1593,3 +1610,99 @@ class LdapServiceUserGroup(ldapdb.models.Model): def __str__(self): return self.name + + +class Mail(RevMixin, AclMixin, models.Model): + """ + Mail account of a user + + Compte mail d'un utilisateur + """ + external_mail = models.EmailField(help_text="Mail externe") + user = models.ForeignKey( + 'User', + on_delete=models.CASCADE, + help_text="Object mail d'un User" + ) + redirection = models.BooleanField( + default=False + ) + internal_address = models.BooleanField( + default=False + ) + + def __str__(self): + return self.mail + + +class MailAlias(RevMixin, AclMixin, models.Model): + """ + Define a alias for a user Mail + + Définit un aliase pour un Mail d'utilisateur + """ + mail = models.ForeignKey( + 'Mail', + on_delete=models.CASCADE, + help_text="Objects Mail associé" + ) + valeur = models.CharField( + max_length=64, + help_text="username de l'adresse mail" + ) + extension = models.ForeignKey( + 'Extension', + on_delete=models.CASCADE, + help_text="Extension mail interne" + ) + + class Meta: + unique_together = ('valeur', 'extension',) + + def __str__(self): + return self.valeur + "@" + self.extension + + def can_view(self, user_request, *_args, **_kwargs): + """ + Check if the user can view the aliases + """ + + if user_request.has_perm('users.view_mailalias') or user.request == self.mail.user: + return True, None + else: + return False, "Vous n'avais pas les droits suffisants et n'êtes pas propriétaire de ces alias" + + def can_delete(self, user_request, *_args, **_kwargs): + """ + Check if the user can delete the alias + """ + + if user_request.has_perm('users.delete_mailalias'): + return True, None + else: + if user_request == self.mail.user: + if self.id != 0: + return True, None + else: + return False, "Vous ne pouvez pas supprimer l'alias lié à votre pseudo" + else: + return False, "Vous n'avez pas les droits suffisants et n'êtes pas propriétairs de ces alias" + + def can_edit(self, user_request, *_args, **_kwargs): + """ + Check if the user can edit the alias + """ + + if user_request.has_perm('users.change_mailalias'): + return True, None + else: + if user_request == self.mail.user: + if self.id != 0: + return True, None + else: + return False, "Vous ne pouvez pas modifier l'alias lié à votre pseudo" + else: + return False, "Vous n'avez pas les droits suffisants et n'êtes pas propriétairs de cet alias" + + + diff --git a/users/templates/users/aff_alias.html b/users/templates/users/aff_alias.html new file mode 100644 index 00000000..59a9b6f1 --- /dev/null +++ b/users/templates/users/aff_alias.html @@ -0,0 +1,53 @@ +{% 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 acl %} +{% if alias_list.paginator %} +{% include "pagination.html" with list=alias_list %} +{% endif %} + + + + + + + + + {% for alias in alias_list %} + + + + {% endfor %} +
Alias
{{ alias }} + {% can_delete alias %} + {% include 'buttons/suppr.html' with href='users:del-alias' id=alias.id %} + {% acl_end %} + {% can_edit alias %} + {% include 'buttons/edit.html' with href='users:edit-alias' id=alias.id %} + {% acl_end %} + {% include 'buttons/history.html' with href='users:history' name='alias' id=alias.id %} +
+ +{% if alias_list.paginator %} +{% include "pagination.html" with list=alias_list %} +{% endif %} diff --git a/users/templates/users/index_alias.html b/users/templates/users/index_alias.html new file mode 100644 index 00000000..dc9af095 --- /dev/null +++ b/users/templates/users/index_alias.html @@ -0,0 +1,37 @@ +{% 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 %}Utilisateurs{% endblock %} + +{% block content %} +

Alias

+ {% include "users/aff_alias.html" with alias_list=alias_list %} +
+
+
+{% endblock %} + diff --git a/users/urls.py b/users/urls.py index 6bb374c3..c8284d4e 100644 --- a/users/urls.py +++ b/users/urls.py @@ -64,6 +64,9 @@ urlpatterns = [ url(r'^del_whitelist/(?P[0-9]+)$', views.del_whitelist, name='del-whitelist'), + url(r'^add_mailalias/(?P[0-9]+)$', views.add_mailalias, name='add-mailalias'), + url(r'^edit_mailalias/(?P[0-9]+)$', views.edit_mailalias, name='edit-mailalias'), + url(r'^del-mailalias/(?P[0-9]+)$', views.del_mailalias, name='del-mailalias'), url(r'^add_school/$', views.add_school, name='add-school'), url(r'^edit_school/(?P[0-9]+)$', views.edit_school, diff --git a/users/views.py b/users/views.py index a6444e33..b2a83dbe 100644 --- a/users/views.py +++ b/users/views.py @@ -492,6 +492,66 @@ def del_whitelist(request, whitelist, **_kwargs): ) +@login_required +@can_create(MailAlias) +@can_edit(User) +def add_mailalias(request, user, userid): + """ Créer un alias """ + mailalias_instance = MailAlias(mail=user.mail) + whitelist = WhitelistForm( + request.POST or None, + instance=whitelist_instance + ) + if whitelist.is_valid(): + whitelist.save() + messages.success(request, "Alias créé") + return redirect(reverse( + 'users:profil', + kwargs={'userid': str(userid)} + )) + + return form( + {'userform': mailalias, 'action_name': 'Ajouter un alias mail'}, + 'users/user.html', + request + ) + +@login_required +@can_edit(MailAlias) +def edit_mailalias(request, mailalias_instance, **_kwargs): + """ Editer un alias mail""" + mailalias = MailAliasForm( + request.POST or None, + instance=mailalias_instance + ) + if whitelist.is_valid(): + if whitelist.changed_data: + whitelist.save() + messages.success(request, "Alias modifiée") + return redirect(reverse('users:index')) + return form( + {'userform': mailalias, 'action_name': 'Editer un alias mail'}, + 'users/user.html', + request + ) + +@login_required +@can_delete(MailAlias) +def del_mailalias(request, mailalias, **_kwargs): + """ Supprime un alias mail""" + if request.method == "POST": + mailalias.delete() + messages.success(request, "L'alias a été supprimé") + return redirect(reverse( + 'users:profil', + kwargs={'userid': str(mailalias.mail.user.id)} + )) + return form( + {'objet': mailalias, 'objet_name': 'mailalias'}, + 'users/delete.html', + request + ) + @login_required @can_create(School) def add_school(request): From 7c1a67449138665df8c1a149db3888dd3ef04738 Mon Sep 17 00:00:00 2001 From: Charlie Jacomme Date: Tue, 26 Jun 2018 18:59:15 +0200 Subject: [PATCH 02/24] fix mailalias model --- users/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/users/models.py b/users/models.py index 61f58920..f5e2039f 100644 --- a/users/models.py +++ b/users/models.py @@ -1651,7 +1651,7 @@ class MailAlias(RevMixin, AclMixin, models.Model): help_text="username de l'adresse mail" ) extension = models.ForeignKey( - 'Extension', + 'machines.Extension', on_delete=models.CASCADE, help_text="Extension mail interne" ) From 099e7ff875aca08c863df8392c154d37825f7108 Mon Sep 17 00:00:00 2001 From: grisel-davy Date: Tue, 26 Jun 2018 22:27:33 +0200 Subject: [PATCH 03/24] Ajout de l'extension mail dans preference et debut de frontend --- machines/forms.py | 1 - machines/models.py | 4 -- .../0035_optionaluser_mail_extension.py | 20 ++++++++ preferences/models.py | 15 ++++++ .../preferences/display_preferences.html | 4 ++ users/admin.py | 4 +- users/forms.py | 6 +-- users/migrations/0073_mail_mailalias.py | 38 +++++++++++++++ users/migrations/0074_transfermail.py | 36 +++++++++++++++ users/models.py | 46 +++++++------------ users/views.py | 2 + 11 files changed, 134 insertions(+), 42 deletions(-) create mode 100644 preferences/migrations/0035_optionaluser_mail_extension.py create mode 100644 users/migrations/0073_mail_mailalias.py create mode 100644 users/migrations/0074_transfermail.py diff --git a/machines/forms.py b/machines/forms.py index 241ce303..23c2aa39 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -262,7 +262,6 @@ class ExtensionForm(FormRevMixin, ModelForm): self.fields['origin'].label = 'Enregistrement A origin' self.fields['origin_v6'].label = 'Enregistrement AAAA origin' self.fields['soa'].label = 'En-tête SOA à utiliser' - self.fielss['mail_extension'].label = 'Utilisable comme extension mail' class DelExtensionForm(FormRevMixin, Form): diff --git a/machines/models.py b/machines/models.py index c8dccadf..7be76e74 100644 --- a/machines/models.py +++ b/machines/models.py @@ -546,10 +546,6 @@ class Extension(RevMixin, AclMixin, models.Model): 'SOA', on_delete=models.CASCADE ) - mail_extension = models.BooleanField( - default=False, - help_text="Determine si l'extension peut être utilisée comme extension mail interne" - ) class Meta: permissions = ( diff --git a/preferences/migrations/0035_optionaluser_mail_extension.py b/preferences/migrations/0035_optionaluser_mail_extension.py new file mode 100644 index 00000000..3d1b42b4 --- /dev/null +++ b/preferences/migrations/0035_optionaluser_mail_extension.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-26 19:31 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0034_auto_20180416_1120'), + ] + + operations = [ + migrations.AddField( + model_name='optionaluser', + name='mail_extension', + field=models.CharField(default='@example.org', help_text='Extension principale pour les mails internes', max_length=32), + ), + ] diff --git a/preferences/models.py b/preferences/models.py index d39b9f8e..516de515 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -31,6 +31,8 @@ from django.db.models.signals import post_save from django.dispatch import receiver from django.core.cache import cache +from django.forms import ValidationError +import cotisations.models import machines.models from re2o.mixins import AclMixin @@ -83,12 +85,25 @@ class OptionalUser(AclMixin, PreferencesModel): blank=True, null=True ) + mail_extension = models.CharField( + max_length = 32, + default = "@example.org", + help_text="Extension principale pour les mails internes", + ) class Meta: permissions = ( ("view_optionaluser", "Peut voir les options de l'user"), ) + def clean(self): + """Clean du model: + Creation du mode de paiement par solde + Vérifie que l'extension mail commence bien par @ + """ + if self.mail_extension[0] != "@": + raise ValidationError("L'extension mail doit commencer par un @") + @receiver(post_save, sender=OptionalUser) def optionaluser_post_save(**kwargs): diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html index 34417695..c232f13c 100755 --- a/preferences/templates/preferences/display_preferences.html +++ b/preferences/templates/preferences/display_preferences.html @@ -56,6 +56,10 @@ with this program; if not, write to the Free Software Foundation, Inc., Creations de clubs par tous {{ useroptions.all_can_create_club|tick }} + + Extension mail interne + {{ useroptions.mail_extension }} + diff --git a/users/admin.py b/users/admin.py index 5f4c197b..92528455 100644 --- a/users/admin.py +++ b/users/admin.py @@ -127,7 +127,6 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): list_display = ( 'pseudo', 'surname', - 'email', 'school', 'is_admin', 'shell' @@ -141,7 +140,7 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): 'Personal info', { 'fields': - ('surname', 'email', 'school', 'shell', 'uid_number') + ('surname', 'school', 'shell', 'uid_number') } ), ('Permissions', {'fields': ('is_admin', )}), @@ -156,7 +155,6 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): 'fields': ( 'pseudo', 'surname', - 'email', 'school', 'is_admin', 'password1', diff --git a/users/forms.py b/users/forms.py index ba8e137e..a3459eac 100644 --- a/users/forms.py +++ b/users/forms.py @@ -140,7 +140,7 @@ class UserCreationForm(FormRevMixin, forms.ModelForm): class Meta: model = Adherent - fields = ('pseudo', 'surname', 'email') + fields = ('pseudo', 'surname') def clean_password2(self): """Verifie que password1 et 2 sont identiques""" @@ -220,7 +220,7 @@ class UserChangeForm(FormRevMixin, forms.ModelForm): class Meta: model = Adherent - fields = ('pseudo', 'password', 'surname', 'email') + fields = ('pseudo', 'password', 'surname') def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) @@ -313,7 +313,6 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): 'name', 'surname', 'pseudo', - 'email', 'school', 'comment', 'room', @@ -365,7 +364,6 @@ class ClubForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): fields = [ 'surname', 'pseudo', - 'email', 'school', 'comment', 'room', diff --git a/users/migrations/0073_mail_mailalias.py b/users/migrations/0073_mail_mailalias.py new file mode 100644 index 00000000..ce676464 --- /dev/null +++ b/users/migrations/0073_mail_mailalias.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-26 19:07 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import re2o.mixins + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0072_auto_20180426_2021'), + ] + + operations = [ + migrations.CreateModel( + name='Mail', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('external_mail', models.EmailField(help_text='Mail externe', max_length=254)), + ('redirection', models.BooleanField(default=False)), + ('internal_address', models.BooleanField(default=False)), + ('user', models.OneToOneField(help_text="Object mail d'un User", on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), + ), + migrations.CreateModel( + name='MailAlias', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('valeur', models.CharField(help_text="username de l'adresse mail", max_length=64, unique=True)), + ('mail', models.ForeignKey(help_text='Objects Mail associé', on_delete=django.db.models.deletion.CASCADE, to='users.Mail')), + ], + bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), + ), + ] diff --git a/users/migrations/0074_transfermail.py b/users/migrations/0074_transfermail.py new file mode 100644 index 00000000..dbf6adca --- /dev/null +++ b/users/migrations/0074_transfermail.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-26 18:34 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0073_mail_mailalias'), + ] + + def create_mail(apps, schema_editor): + db_alias = schema_editor.connection.alias + user = apps.get_model('users','User') + mail = apps.get_model('users','Mail') + mailalias = apps.get_model('users','MailAlias') + users = user.objects.using(db_alias).all() + for us in users: + ma = mail() + ma.user=us + ma.external_mail = us.email + ma.save() + al = mailalias() + al.mail = ma + al.valeur = us.pseudo + al.save() + + def uncreatemail(apps,schema_editor): + pass + + operations = [ + migrations.RunPython(create_mail, uncreatemail) + ] diff --git a/users/models.py b/users/models.py index f5e2039f..bbdbef58 100644 --- a/users/models.py +++ b/users/models.py @@ -79,7 +79,7 @@ from re2o.field_permissions import FieldPermissionModelMixin from re2o.mixins import AclMixin, RevMixin from cotisations.models import Cotisation, Facture, Paiement, Vente -from machines.models import Domain, Interface, Machine, regen, Extension +from machines.models import Domain, Interface, Machine, regen from preferences.models import GeneralOption, AssoOption, OptionalUser from preferences.models import OptionalMachine, MailMessageOption @@ -134,7 +134,6 @@ class UserManager(BaseUserManager): self, pseudo, surname, - email, password=None, su=False ): @@ -148,7 +147,6 @@ class UserManager(BaseUserManager): pseudo=pseudo, surname=surname, name=surname, - email=self.normalize_email(email), ) user.set_password(password) @@ -157,19 +155,19 @@ class UserManager(BaseUserManager): user.save(using=self._db) return user - def create_user(self, pseudo, surname, email, password=None): + def create_user(self, pseudo, surname, password=None): """ Creates and saves a User with the given pseudo, name, surname, email, and password. """ - return self._create_user(pseudo, surname, email, password, False) + return self._create_user(pseudo, surname, password, False) - def create_superuser(self, pseudo, surname, email, password): + def create_superuser(self, pseudo, surname, password): """ Creates and saves a superuser with the given pseudo, name, surname, email, and password. """ - return self._create_user(pseudo, surname, email, password, True) + return self._create_user(pseudo, surname, password, True) class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, @@ -188,19 +186,13 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ) surname = models.CharField(max_length=255) + email = models.EmailField() pseudo = models.CharField( max_length=32, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator] ) - email = models.EmailField() - """ - email= models.OneToOneField( - Mail, - on_delete=models.PROTECT - ) - """ school = models.ForeignKey( 'School', on_delete=models.PROTECT, @@ -233,7 +225,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ) USERNAME_FIELD = 'pseudo' - REQUIRED_FIELDS = ['surname', 'email'] + REQUIRED_FIELDS = ['surname'] objects = UserManager() @@ -686,10 +678,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, """ Return the mail address choosen by the user """ - if not self.mail.internal_activated: - return(self.mail.external) + if not self.mail.internal_address: + return self.mail.external_mail else: - return(self.mail.mailalias_set.first()) + return self.mail.mailalias_set.get(valeur=pseudo) def get_next_domain_name(self): """Look for an available name for a new interface for @@ -1619,7 +1611,7 @@ class Mail(RevMixin, AclMixin, models.Model): Compte mail d'un utilisateur """ external_mail = models.EmailField(help_text="Mail externe") - user = models.ForeignKey( + user = models.OneToOneField( 'User', on_delete=models.CASCADE, help_text="Object mail d'un User" @@ -1632,7 +1624,7 @@ class Mail(RevMixin, AclMixin, models.Model): ) def __str__(self): - return self.mail + return self.user.get_mail() class MailAlias(RevMixin, AclMixin, models.Model): @@ -1647,20 +1639,14 @@ class MailAlias(RevMixin, AclMixin, models.Model): help_text="Objects Mail associé" ) valeur = models.CharField( + unique=True, max_length=64, help_text="username de l'adresse mail" ) - extension = models.ForeignKey( - 'machines.Extension', - on_delete=models.CASCADE, - help_text="Extension mail interne" - ) - class Meta: - unique_together = ('valeur', 'extension',) def __str__(self): - return self.valeur + "@" + self.extension + return self.valeur + OptionalUser.get_cached_value('mail_extension') def can_view(self, user_request, *_args, **_kwargs): """ @@ -1681,7 +1667,7 @@ class MailAlias(RevMixin, AclMixin, models.Model): return True, None else: if user_request == self.mail.user: - if self.id != 0: + if self.valeur == self.mail.user.pseudo: return True, None else: return False, "Vous ne pouvez pas supprimer l'alias lié à votre pseudo" @@ -1697,7 +1683,7 @@ class MailAlias(RevMixin, AclMixin, models.Model): return True, None else: if user_request == self.mail.user: - if self.id != 0: + if self.valeur == self.mail.user.pseudo: return True, None else: return False, "Vous ne pouvez pas modifier l'alias lié à votre pseudo" diff --git a/users/views.py b/users/views.py index b2a83dbe..c8061040 100644 --- a/users/views.py +++ b/users/views.py @@ -81,6 +81,8 @@ from .models import ( Adherent, Club, ListShell, + MailAlias, + Mail, ) from .forms import ( BanForm, From ec3cb33a69910ac83cadcbfbcc0a74a8dbf21c7c Mon Sep 17 00:00:00 2001 From: grisel-davy Date: Wed, 27 Jun 2018 23:13:43 +0200 Subject: [PATCH 04/24] Affichage et modification du compte mail et des alias mail --- users/forms.py | 15 ++++++++++- users/models.py | 12 ++++++++- users/templates/users/aff_alias.html | 5 ++-- users/templates/users/profil.html | 40 ++++++++++++++++++++++++++++ users/urls.py | 1 + users/views.py | 38 +++++++++++++++++++++----- 6 files changed, 99 insertions(+), 12 deletions(-) diff --git a/users/forms.py b/users/forms.py index a3459eac..91b8d6dc 100644 --- a/users/forms.py +++ b/users/forms.py @@ -53,6 +53,7 @@ from .models import ( School, ListRight, Whitelist, + Mail, MailAlias, ListShell, Ban, @@ -597,8 +598,20 @@ class MailAliasForm(FormRevMixin, ModelForm): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(MailAliasForm, self).__init__(*args, prefix=prefix, **kwargs) self.fields['valeur'].label = 'nom de l\'adresse mail' - self.fields['extension'].label = 'extension de l\'adresse mail' class Meta: model = MailAlias exclude = ['mail'] + +class MailForm(FormRevMixin, ModelForm): + """Creation, edition d'un objet mail""" + def __init__(self, *args, **kwargs): + prefix = kwargs.pop('prefix', self.Meta.model.__name__) + super(MailForm, self).__init__(*args, prefix=prefix, **kwargs) + self.fields['external_mail'].label = 'Adresse mail externe' + self.fields['redirection'].label = 'Activation de la redirection vers l\'adress externe' + self.fields['internal_address'].label = 'Adresse mail interne' + + class Meta: + model = Mail + exclude = ['user'] diff --git a/users/models.py b/users/models.py index bbdbef58..018e1994 100644 --- a/users/models.py +++ b/users/models.py @@ -681,7 +681,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, if not self.mail.internal_address: return self.mail.external_mail else: - return self.mail.mailalias_set.get(valeur=pseudo) + return self.mail.mailalias_set.get(valeur=self.pseudo) def get_next_domain_name(self): """Look for an available name for a new interface for @@ -1626,6 +1626,16 @@ class Mail(RevMixin, AclMixin, models.Model): def __str__(self): return self.user.get_mail() + def can_edit(self, user_request, *_args, **_kwargs): + """ + Check if the user can edit the mail + """ + + if user_request.has_perm('users.change_mail') or user_request == self.user: + return True, None + else: + return False, "Vous n'avez pas les droits suffisants et n'êtes pas propriétairs de cet alias" + class MailAlias(RevMixin, AclMixin, models.Model): """ diff --git a/users/templates/users/aff_alias.html b/users/templates/users/aff_alias.html index 59a9b6f1..ec5b7313 100644 --- a/users/templates/users/aff_alias.html +++ b/users/templates/users/aff_alias.html @@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc., {% if alias_list.paginator %} {% include "pagination.html" with list=alias_list %} {% endif %} - @@ -37,10 +36,10 @@ with this program; if not, write to the Free Software Foundation, Inc., diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 6e960fc2..acc2c1c9 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -406,6 +406,46 @@ with this program; if not, write to the Free Software Foundation, Inc., +
+
+

+ + Gestion des mails +

+
+
+
+ {% can_edit user.mail %} + + + Modifier les options mail + + {% acl_end %} +
+
{{ alias }} {% can_delete alias %} - {% include 'buttons/suppr.html' with href='users:del-alias' id=alias.id %} + {% include 'buttons/suppr.html' with href='users:del-mailalias' id=alias.id %} {% acl_end %} {% can_edit alias %} - {% include 'buttons/edit.html' with href='users:edit-alias' id=alias.id %} + {% include 'buttons/edit.html' with href='users:edit-mailalias' id=alias.id %} {% acl_end %} {% include 'buttons/history.html' with href='users:history' name='alias' id=alias.id %}
+ + + + + + + + + +
Adresse mail externeCompte mail {{ asso_name }}Adresse mail de contact
{{ user.mail.external_mail }}{{ user.mail.internal_address|yesno:"Activé,Désactivé" }}{{ user.mail.external_mail }}
+ + {% can_create MailAlias %} + + + Ajouter un alias mail + + {% acl_end %} + {% if alias_list %} + {% include "users/aff_alias.html" with alias_list=alias_list %} + {% endif %} + + +

diff --git a/users/urls.py b/users/urls.py index c8284d4e..5aaf893e 100644 --- a/users/urls.py +++ b/users/urls.py @@ -67,6 +67,7 @@ urlpatterns = [ url(r'^add_mailalias/(?P[0-9]+)$', views.add_mailalias, name='add-mailalias'), url(r'^edit_mailalias/(?P[0-9]+)$', views.edit_mailalias, name='edit-mailalias'), url(r'^del-mailalias/(?P[0-9]+)$', views.del_mailalias, name='del-mailalias'), + url(r'^edit_mail/(?P[0-9]+)$', views.edit_mail, name='edit-mail'), url(r'^add_school/$', views.add_school, name='add-school'), url(r'^edit_school/(?P[0-9]+)$', views.edit_school, diff --git a/users/views.py b/users/views.py index c8061040..a6a79093 100644 --- a/users/views.py +++ b/users/views.py @@ -87,6 +87,8 @@ from .models import ( from .forms import ( BanForm, WhitelistForm, + MailAliasForm, + MailForm, DelSchoolForm, DelListRightForm, NewListRightForm, @@ -500,12 +502,12 @@ def del_whitelist(request, whitelist, **_kwargs): def add_mailalias(request, user, userid): """ Créer un alias """ mailalias_instance = MailAlias(mail=user.mail) - whitelist = WhitelistForm( + mailalias = MailAliasForm( request.POST or None, - instance=whitelist_instance + instance=mailalias_instance ) - if whitelist.is_valid(): - whitelist.save() + if mailalias.is_valid(): + mailalias.save() messages.success(request, "Alias créé") return redirect(reverse( 'users:profil', @@ -526,9 +528,9 @@ def edit_mailalias(request, mailalias_instance, **_kwargs): request.POST or None, instance=mailalias_instance ) - if whitelist.is_valid(): - if whitelist.changed_data: - whitelist.save() + if mailalias.is_valid(): + if mailalias.changed_data: + mailalias.save() messages.success(request, "Alias modifiée") return redirect(reverse('users:index')) return form( @@ -554,6 +556,25 @@ def del_mailalias(request, mailalias, **_kwargs): request ) +@login_required +@can_edit(Mail) +def edit_mail(request, mail_instance, **_kwargs): + """ Editer un compte mail""" + mail = MailForm( + request.POST or None, + instance=mail_instance + ) + if mail.is_valid(): + if mail.changed_data: + mail.save() + messages.success(request, "Compte mail modifiée") + return redirect(reverse('users:index')) + return form( + {'userform': mail, 'action_name': 'Editer un compte mail'}, + 'users/user.html', + request + ) + @login_required @can_create(School) def add_school(request): @@ -977,6 +998,9 @@ def profil(request, users, **_kwargs): 'user_solde': user_solde, 'solde_activated': Paiement.objects.filter(is_balance=True).exists(), 'asso_name': AssoOption.objects.first().name + 'allow_online_payment': allow_online_payment, + 'asso_name': AssoOption.objects.first().name, + 'alias_list': users.mail.mailalias_set.all() } ) From 283cdcace3cde830ca24622e1e3f18621f5e9ab7 Mon Sep 17 00:00:00 2001 From: chirac Date: Fri, 29 Jun 2018 17:45:21 +0200 Subject: [PATCH 05/24] =?UTF-8?q?Fix=20erreurs,=20cr=C3=A9ation=20alias=20?= =?UTF-8?q?mails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- users/forms.py | 2 +- users/migrations/0074_auto_20180629_1717.py | 27 +++++++++++++++++++++ users/models.py | 22 ++++++++++------- users/urls.py | 2 +- users/views.py | 8 +++--- 5 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 users/migrations/0074_auto_20180629_1717.py diff --git a/users/forms.py b/users/forms.py index 91b8d6dc..fb29e73f 100644 --- a/users/forms.py +++ b/users/forms.py @@ -597,7 +597,7 @@ class MailAliasForm(FormRevMixin, ModelForm): def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(MailAliasForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['valeur'].label = 'nom de l\'adresse mail' + self.fields['valeur'].label = "Prefixe de l'alias mail. Ne peut contenir de @" class Meta: model = MailAlias diff --git a/users/migrations/0074_auto_20180629_1717.py b/users/migrations/0074_auto_20180629_1717.py new file mode 100644 index 00000000..446a2cdd --- /dev/null +++ b/users/migrations/0074_auto_20180629_1717.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-29 15:17 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0073_auto_20180629_1614'), + ] + + operations = [ + migrations.AlterField( + model_name='mailalias', + name='user', + field=models.ForeignKey(help_text='Utilisateur associé', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='mailalias', + name='valeur', + field=models.CharField(help_text="Valeur de l'alias mail", max_length=64, unique=True), + ), + ] diff --git a/users/models.py b/users/models.py index 018e1994..ab0d623b 100644 --- a/users/models.py +++ b/users/models.py @@ -53,6 +53,7 @@ from django.db import models from django.db.models import Q from django import forms from django.db.models.signals import post_save, post_delete, m2m_changed +from django.forms import ValidationError from django.dispatch import receiver from django.utils.functional import cached_property from django.template import Context, loader @@ -97,7 +98,7 @@ def linux_user_validator(login): """ Retourne une erreur de validation si le login ne respecte pas les contraintes unix (maj, min, chiffres ou tiret)""" if not linux_user_check(login): - raise forms.ValidationError( + raise ValidationError( ", ce pseudo ('%(label)s') contient des carractères interdits", params={'label': login}, ) @@ -1646,12 +1647,12 @@ class MailAlias(RevMixin, AclMixin, models.Model): mail = models.ForeignKey( 'Mail', on_delete=models.CASCADE, - help_text="Objects Mail associé" + help_text="Compte mail", ) valeur = models.CharField( unique=True, max_length=64, - help_text="username de l'adresse mail" + help_text="Valeur de l'alias mail" ) @@ -1663,7 +1664,7 @@ class MailAlias(RevMixin, AclMixin, models.Model): Check if the user can view the aliases """ - if user_request.has_perm('users.view_mailalias') or user.request == self.mail.user: + if user_request.has_perm('users.view_mailalias') or user.request == self.user: return True, None else: return False, "Vous n'avais pas les droits suffisants et n'êtes pas propriétaire de ces alias" @@ -1676,8 +1677,8 @@ class MailAlias(RevMixin, AclMixin, models.Model): if user_request.has_perm('users.delete_mailalias'): return True, None else: - if user_request == self.mail.user: - if self.valeur == self.mail.user.pseudo: + if user_request == self.user: + if self.valeur != self.user.pseudo: return True, None else: return False, "Vous ne pouvez pas supprimer l'alias lié à votre pseudo" @@ -1692,13 +1693,16 @@ class MailAlias(RevMixin, AclMixin, models.Model): if user_request.has_perm('users.change_mailalias'): return True, None else: - if user_request == self.mail.user: - if self.valeur == self.mail.user.pseudo: + if user_request == self.user: + if self.valeur != self.user.pseudo: return True, None else: return False, "Vous ne pouvez pas modifier l'alias lié à votre pseudo" else: return False, "Vous n'avez pas les droits suffisants et n'êtes pas propriétairs de cet alias" - + def clean(self, *args, **kwargs): + if "@" in self.valeur: + raise ValidationError("Cet alias ne peut contenir un @") + super(MailAlias, self).clean(*args, **kwargs) diff --git a/users/urls.py b/users/urls.py index 5aaf893e..9289d6c2 100644 --- a/users/urls.py +++ b/users/urls.py @@ -67,7 +67,7 @@ urlpatterns = [ url(r'^add_mailalias/(?P[0-9]+)$', views.add_mailalias, name='add-mailalias'), url(r'^edit_mailalias/(?P[0-9]+)$', views.edit_mailalias, name='edit-mailalias'), url(r'^del-mailalias/(?P[0-9]+)$', views.del_mailalias, name='del-mailalias'), - url(r'^edit_mail/(?P[0-9]+)$', views.edit_mail, name='edit-mail'), + url(r'^edit_mail/(?P[0-9]+)$', views.edit_mail, name='edit-mail'), url(r'^add_school/$', views.add_school, name='add-school'), url(r'^edit_school/(?P[0-9]+)$', views.edit_school, diff --git a/users/views.py b/users/views.py index a6a79093..acc3c1d7 100644 --- a/users/views.py +++ b/users/views.py @@ -513,7 +513,6 @@ def add_mailalias(request, user, userid): 'users:profil', kwargs={'userid': str(userid)} )) - return form( {'userform': mailalias, 'action_name': 'Ajouter un alias mail'}, 'users/user.html', @@ -532,7 +531,10 @@ def edit_mailalias(request, mailalias_instance, **_kwargs): if mailalias.changed_data: mailalias.save() messages.success(request, "Alias modifiée") - return redirect(reverse('users:index')) + return redirect(reverse( + 'users:profil', + kwargs={'userid': str(mailalias_instance.user.id)} + )) return form( {'userform': mailalias, 'action_name': 'Editer un alias mail'}, 'users/user.html', @@ -548,7 +550,7 @@ def del_mailalias(request, mailalias, **_kwargs): messages.success(request, "L'alias a été supprimé") return redirect(reverse( 'users:profil', - kwargs={'userid': str(mailalias.mail.user.id)} + kwargs={'userid': str(mailalias.user.id)} )) return form( {'objet': mailalias, 'objet_name': 'mailalias'}, From bf189f4c4fca702975f27744ff8f48ba10d9ee48 Mon Sep 17 00:00:00 2001 From: chirac Date: Fri, 29 Jun 2018 18:48:27 +0200 Subject: [PATCH 06/24] Affichage des champs supp de mail que si compte mails actifs --- users/forms.py | 10 ++++++---- users/models.py | 32 ++++++++++++++++++++++++++++++-- users/views.py | 8 ++++++-- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/users/forms.py b/users/forms.py index fb29e73f..ebc4b945 100644 --- a/users/forms.py +++ b/users/forms.py @@ -603,14 +603,16 @@ class MailAliasForm(FormRevMixin, ModelForm): model = MailAlias exclude = ['mail'] -class MailForm(FormRevMixin, ModelForm): - """Creation, edition d'un objet mail""" +class MailForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): + """Creation, edition des paramètres mail""" def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(MailForm, self).__init__(*args, prefix=prefix, **kwargs) self.fields['external_mail'].label = 'Adresse mail externe' - self.fields['redirection'].label = 'Activation de la redirection vers l\'adress externe' - self.fields['internal_address'].label = 'Adresse mail interne' + if 'redirection' in self.fields: + self.fields['redirection'].label = 'Activation de la redirection vers l\'adress externe' + if 'internal_address' in self.fields: + self.fields['internal_address'].label = 'Adresse mail interne' class Meta: model = Mail diff --git a/users/models.py b/users/models.py index ab0d623b..37204a45 100644 --- a/users/models.py +++ b/users/models.py @@ -679,8 +679,8 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, """ Return the mail address choosen by the user """ - if not self.mail.internal_address: - return self.mail.external_mail + if not OptionalUser.get_cached_value('mail_accounts') or not self.internal_address: + return self.external_mail else: return self.mail.mailalias_set.get(valeur=self.pseudo) @@ -802,6 +802,32 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, "Droit requis pour changer le shell" ) + @staticmethod + def can_change_redirection(user_request, *_args, **_kwargs): + """ Check if a user can change redirection. + + :param user_request: The user who request + :returns: a message and a boolean which is True if the user has + the right to change a redirection + """ + return ( + OptionalUser.get_cached_value('mail_accounts'), + "La gestion des comptes mails doit être activée" + ) + + @staticmethod + def can_change_internal_address(user_request, *_args, **_kwargs): + """ Check if a user can change internal address . + + :param user_request: The user who request + :returns: a message and a boolean which is True if the user has + the right to change internal address + """ + return ( + OptionalUser.get_cached_value('mail_accounts'), + "La gestion des comptes mails doit être activée" + ) + @staticmethod def can_change_force(user_request, *_args, **_kwargs): """ Check if a user can change a force @@ -896,6 +922,8 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, 'shell': self.can_change_shell, 'force': self.can_change_force, 'selfpasswd': self.check_selfpasswd, + 'redirection': self.can_change_redirection, + 'internal_address' : self.can_change_internal_address, } self.__original_state = self.state diff --git a/users/views.py b/users/views.py index acc3c1d7..4ee03458 100644 --- a/users/views.py +++ b/users/views.py @@ -564,13 +564,17 @@ def edit_mail(request, mail_instance, **_kwargs): """ Editer un compte mail""" mail = MailForm( request.POST or None, - instance=mail_instance + instance=user_instance, + user=request.user ) if mail.is_valid(): if mail.changed_data: mail.save() messages.success(request, "Compte mail modifiée") - return redirect(reverse('users:index')) + return redirect(reverse( + 'users:profil', + kwargs={'userid': str(user_instance.id)} + )) return form( {'userform': mail, 'action_name': 'Editer un compte mail'}, 'users/user.html', From 7bb62daf42467d3c20d23037b7b751aeef82700f Mon Sep 17 00:00:00 2001 From: chirac Date: Fri, 29 Jun 2018 18:53:39 +0200 Subject: [PATCH 07/24] Fix compte mail , get_mail si redirection --- users/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/users/models.py b/users/models.py index 37204a45..f9445753 100644 --- a/users/models.py +++ b/users/models.py @@ -679,10 +679,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, """ Return the mail address choosen by the user """ - if not OptionalUser.get_cached_value('mail_accounts') or not self.internal_address: - return self.external_mail + if not OptionalUser.get_cached_value('mail_accounts') or not self.internal_address or self.redirection: + return str(self.external_mail) else: - return self.mail.mailalias_set.get(valeur=self.pseudo) + return str(self.mailalias_set.get(valeur=self.pseudo)) def get_next_domain_name(self): """Look for an available name for a new interface for From 1a7c6edc4dd7bb57f19e15c8204dad0a6c99acda Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Sat, 30 Jun 2018 02:53:19 +0200 Subject: [PATCH 08/24] =?UTF-8?q?Sync=20du=20pseudo=20et=20mailalias=20?= =?UTF-8?q?=C3=A0=20la=20creation=20de=20l'user?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- users/models.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/users/models.py b/users/models.py index f9445753..bc83b997 100644 --- a/users/models.py +++ b/users/models.py @@ -927,6 +927,12 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, } self.__original_state = self.state + def clean(self, *args, **kwargs): + """Check if this pseudo is already used by any mailalias. + Better than raising an error in post-save and catching it""" + if MailAlias.objects.filter(valeur=self.pseudo).exclude(user=self): + raise ValidationError("Ce pseudo est déjà utilisé") + def __str__(self): return self.pseudo @@ -1049,9 +1055,11 @@ class Club(User): @receiver(post_save, sender=User) def user_post_save(**kwargs): """ Synchronisation post_save : envoie le mail de bienvenue si creation + Synchronise le pseudo, en créant un alias mail correspondant Synchronise le ldap""" is_created = kwargs['created'] user = kwargs['instance'] + mail_alias, created = MailAlias.objects.get_or_create(valeur=user.pseudo, user=user) if is_created: user.notif_inscription() user.state_sync() From ec9471391de5c151b77f45bff1f885425c7bb28e Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Sat, 30 Jun 2018 03:22:46 +0200 Subject: [PATCH 09/24] Augmente la valeur de l'alias --- users/migrations/0074_auto_20180629_1717.py | 2 +- users/models.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/users/migrations/0074_auto_20180629_1717.py b/users/migrations/0074_auto_20180629_1717.py index 446a2cdd..ad450b5d 100644 --- a/users/migrations/0074_auto_20180629_1717.py +++ b/users/migrations/0074_auto_20180629_1717.py @@ -22,6 +22,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='mailalias', name='valeur', - field=models.CharField(help_text="Valeur de l'alias mail", max_length=64, unique=True), + field=models.CharField(help_text="Valeur de l'alias mail", max_length=128, unique=True), ), ] diff --git a/users/models.py b/users/models.py index bc83b997..8f0e88a2 100644 --- a/users/models.py +++ b/users/models.py @@ -936,7 +936,6 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, def __str__(self): return self.pseudo - class Adherent(User): """ A class representing a member (it's a user with special informations) """ @@ -1687,7 +1686,7 @@ class MailAlias(RevMixin, AclMixin, models.Model): ) valeur = models.CharField( unique=True, - max_length=64, + max_length=128, help_text="Valeur de l'alias mail" ) From 024d7a073cd439911497d95ea8c1deda058bef64 Mon Sep 17 00:00:00 2001 From: grisel-davy Date: Sat, 30 Jun 2018 14:14:53 +0200 Subject: [PATCH 10/24] frontend sur l'affichage des options mail --- .../preferences/display_preferences.html | 8 ++- users/templates/users/profil.html | 54 +++++++++++++------ users/views.py | 7 +-- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html index c232f13c..fcc889c3 100755 --- a/preferences/templates/preferences/display_preferences.html +++ b/preferences/templates/preferences/display_preferences.html @@ -56,9 +56,13 @@ with this program; if not, write to the Free Software Foundation, Inc., Creations de clubs par tous {{ useroptions.all_can_create_club|tick }} +
{% if useroptions.mail_accounts %}Comptes mails{% else %}Comptes mails{% endif%}
+ - - + + + +
Extension mail interne{{ useroptions.mail_extension }}Gestion des comptes mails{{ useroptions.mail_accounts }}Extension mail interne{{ useroptions.mail_extension }}
diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index acc2c1c9..d1f25c29 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -408,10 +408,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
-

+

- Gestion des mails -

+ Paramètres mail +
@@ -421,19 +421,26 @@ with this program; if not, write to the Free Software Foundation, Inc., Modifier les options mail {% acl_end %} -
- - - - - - - - - - -
Adresse mail externeCompte mail {{ asso_name }}Adresse mail de contact
{{ user.mail.external_mail }}{{ user.mail.internal_address|yesno:"Activé,Désactivé" }}{{ user.mail.external_mail }}
-
+ {% if mail_accounts %} +
+ + + + + + + + + + +
Adresse mail externeCompte mail {{ asso_name }}Adresse mail de contact
{{ user.external_mail }}{{ user.internal_address|yesno:"Activé,Désactivé" }}{{ user.get_mail }}
+ +
+ {% if user.internal_address %} + {% can_create MailAlias %} @@ -443,7 +450,20 @@ with this program; if not, write to the Free Software Foundation, Inc., {% if alias_list %} {% include "users/aff_alias.html" with alias_list=alias_list %} {% endif %} -
+ {% endif %} + {% else %} +
+ + + + + + + +
Adresse mail
{{ user.external_mail }}
+
+ {% endif %} +
diff --git a/users/views.py b/users/views.py index 4ee03458..ab428853 100644 --- a/users/views.py +++ b/users/views.py @@ -570,13 +570,13 @@ def edit_mail(request, mail_instance, **_kwargs): if mail.is_valid(): if mail.changed_data: mail.save() - messages.success(request, "Compte mail modifiée") + messages.success(request, "Option mail modifiée") return redirect(reverse( 'users:profil', kwargs={'userid': str(user_instance.id)} )) return form( - {'userform': mail, 'action_name': 'Editer un compte mail'}, + {'userform': mail, 'action_name': 'Editer les options mail'}, 'users/user.html', request ) @@ -1006,7 +1006,8 @@ def profil(request, users, **_kwargs): 'asso_name': AssoOption.objects.first().name 'allow_online_payment': allow_online_payment, 'asso_name': AssoOption.objects.first().name, - 'alias_list': users.mail.mailalias_set.all() + 'alias_list': users.mailalias_set.all(), + 'mail_accounts': OptionalUser.objects.first().mail_accounts } ) From b7977f493ba9d53a7814a52bf3f5dfc4964e8595 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Sat, 30 Jun 2018 15:18:08 +0200 Subject: [PATCH 11/24] Serialisation des alias mail --- api/serializers.py | 17 ++++++++++++++++- api/urls.py | 1 + api/views.py | 7 +++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/api/serializers.py b/api/serializers.py index c8cdffd9..e5e92c24 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -492,10 +492,12 @@ class UserSerializer(NamespacedHMSerializer): """ access = serializers.BooleanField(source='has_access') uid = serializers.IntegerField(source='uid_number') + email = serializers.CharField(source='get_mail') class Meta: model = users.User fields = ('name', 'pseudo', 'email', 'school', 'shell', 'comment', + 'external_mail', 'redirection', 'internal_address', 'state', 'registered', 'telephone', 'solde', 'access', 'end_access', 'uid', 'class_name', 'api_url') extra_kwargs = { @@ -509,10 +511,12 @@ class ClubSerializer(NamespacedHMSerializer): name = serializers.CharField(source='surname') access = serializers.BooleanField(source='has_access') uid = serializers.IntegerField(source='uid_number') + email = serializers.CharField(source='get_mail') class Meta: model = users.Club fields = ('name', 'pseudo', 'email', 'school', 'shell', 'comment', + 'external_mail', 'redirection', 'internal_address', 'state', 'registered', 'telephone', 'solde', 'room', 'access', 'end_access', 'administrators', 'members', 'mailing', 'uid', 'api_url') @@ -526,10 +530,12 @@ class AdherentSerializer(NamespacedHMSerializer): """ access = serializers.BooleanField(source='has_access') uid = serializers.IntegerField(source='uid_number') + email = serializers.CharField(source='get_mail') class Meta: model = users.Adherent - fields = ('name', 'surname', 'pseudo', 'email', 'school', 'shell', + fields = ('name', 'surname', 'pseudo', 'email', 'redirection', 'internal_address', + 'external_mail', 'school', 'shell', 'comment', 'state', 'registered', 'telephone', 'room', 'solde', 'access', 'end_access', 'uid', 'api_url') extra_kwargs = { @@ -593,6 +599,15 @@ class WhitelistSerializer(NamespacedHMSerializer): fields = ('user', 'raison', 'date_start', 'date_end', 'active', 'api_url') +class MailAliasSerializer(NamespacedHMSerializer): + """Serialize `users.models.MailAlias` objects. + """ + + class Meta: + model = users.MailAlias + fields = ('user', 'valeur', 'complete_mail') + + # SERVICE REGEN diff --git a/api/urls.py b/api/urls.py index 67302789..80194bf5 100644 --- a/api/urls.py +++ b/api/urls.py @@ -93,6 +93,7 @@ router.register_viewset(r'users/listright', views.ListRightViewSet) router.register_viewset(r'users/shell', views.ShellViewSet, base_name='shell') router.register_viewset(r'users/ban', views.BanViewSet) router.register_viewset(r'users/whitelist', views.WhitelistViewSet) +router.register_viewset(r'users/mailalias', views.MailAliasViewSet) # SERVICE REGEN router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen') # DHCP diff --git a/api/views.py b/api/views.py index 7b01b0c3..bd5c8f8b 100644 --- a/api/views.py +++ b/api/views.py @@ -469,6 +469,13 @@ class WhitelistViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.WhitelistSerializer +class MailAliasViewSet(viewsets.ReadOnlyModelViewSet): + """Exposes list and details of `users.models.MailAlias` objects. + """ + queryset = users.MailAlias.objects.all() + serializer_class = serializers.MailAliasSerializer + + # SERVICE REGEN From cc2dcefa8fb3f9b7217d758918d70d6ffb34bc99 Mon Sep 17 00:00:00 2001 From: grisel-davy Date: Sat, 30 Jun 2018 14:46:35 +0200 Subject: [PATCH 12/24] ajout du nombre d'alias max --- .../0037_optionaluser_max_mail_alias.py | 20 ++++++++++++++++ preferences/models.py | 4 ++++ .../preferences/display_preferences.html | 24 ++++++++++--------- users/models.py | 17 +++++++++++++ users/templates/users/profil.html | 17 +++++++------ 5 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 preferences/migrations/0037_optionaluser_max_mail_alias.py diff --git a/preferences/migrations/0037_optionaluser_max_mail_alias.py b/preferences/migrations/0037_optionaluser_max_mail_alias.py new file mode 100644 index 00000000..8d6ca609 --- /dev/null +++ b/preferences/migrations/0037_optionaluser_max_mail_alias.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-30 12:32 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0036_optionaluser_mail_accounts'), + ] + + operations = [ + migrations.AddField( + model_name='optionaluser', + name='max_mail_alias', + field=models.IntegerField(default=15, help_text="Nombre maximal d'alias pour un utilisateur lambda"), + ), + ] diff --git a/preferences/models.py b/preferences/models.py index 516de515..42c22d53 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -90,6 +90,10 @@ class OptionalUser(AclMixin, PreferencesModel): default = "@example.org", help_text="Extension principale pour les mails internes", ) + max_mail_alias = models.IntegerField( + default = 15, + help_text = "Nombre maximal d'alias pour un utilisateur lambda" + ) class Meta: permissions = ( diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html index fcc889c3..83ce10bb 100755 --- a/preferences/templates/preferences/display_preferences.html +++ b/preferences/templates/preferences/display_preferences.html @@ -64,17 +64,19 @@ with this program; if not, write to the Free Software Foundation, Inc., Extension mail interne {{ useroptions.mail_extension }} - - - -

Préférences machines

-
- - Editer - -

-

- + + + +
Nombre d'alias maximum{{ useroption.max_mail_alias }} +
+

Préférences machines

+ + + Editer + +

+

+ diff --git a/users/models.py b/users/models.py index 8f0e88a2..ba7fda3a 100644 --- a/users/models.py +++ b/users/models.py @@ -1694,6 +1694,23 @@ class MailAlias(RevMixin, AclMixin, models.Model): def __str__(self): return self.valeur + OptionalUser.get_cached_value('mail_extension') + @staticmethod + def can_create(user_request, userid, *_args, **_kwargs): + """Check if an user can create an mailalias object. + + :param user_request: The user who wants to create a mailalias object. + :return: a message and a boolean which is True if the user can create + an user or if the `options.all_can_create` is set. + """ + if not user_request.has_perm('users.add_mailalias'): + if int(user_request.id) != int(userid): + return False, 'Vous n\'avez pas le droit d\'ajouter un alias à une autre personne' + elif user_request.mailalias_set.all().count() >= OptionalUser.get_cached_value('max_mail_alias'): + return False, "Vous avez atteint la limite de {} alias".format(OptionalUser.get_cached_value('max_mail_alias')) + else: + return True, None + return True, None + def can_view(self, user_request, *_args, **_kwargs): """ Check if the user can view the aliases diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index d1f25c29..b6e3c848 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -415,8 +415,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
- {% can_edit user.mail %} - + {% can_edit users %} + Modifier les options mail @@ -430,18 +430,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
- - - + + +
Mot de passe par machine {{ machineoptions.password_machine|tick }} Adresse mail de contact
{{ user.external_mail }}{{ user.internal_address|yesno:"Activé,Désactivé" }}{{ user.get_mail }}{{ users.external_mail }}{{ users.internal_address|yesno:"Activé,Désactivé" }}{{ users.get_mail }}
- {% if user.internal_address %} - - {% can_create MailAlias %} + {% if users.internal_address %} + {% can_create MailAlias users.id %} Ajouter un alias mail @@ -458,7 +457,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Adresse mail - {{ user.external_mail }} + {{ users.external_mail }} From 5c433acd792f523aefc945e114f2e170d0356c16 Mon Sep 17 00:00:00 2001 From: grisel-davy Date: Sat, 30 Jun 2018 22:56:34 +0200 Subject: [PATCH 13/24] bug fix historique alias --- users/admin.py | 6 ++++++ users/models.py | 4 ++-- .../templates/users/{aff_alias.html => aff_mailalias.html} | 2 +- users/templates/users/profil.html | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) rename users/templates/users/{aff_alias.html => aff_mailalias.html} (97%) diff --git a/users/admin.py b/users/admin.py index 92528455..ce02aa09 100644 --- a/users/admin.py +++ b/users/admin.py @@ -110,6 +110,11 @@ class BanAdmin(VersionAdmin): pass +class MailAliasAdmin(VersionAdmin): + """Gestion des alias mail""" + pass + + class WhitelistAdmin(VersionAdmin): """Gestion des whitelist""" pass @@ -211,6 +216,7 @@ admin.site.register(School, SchoolAdmin) admin.site.register(ListRight, ListRightAdmin) admin.site.register(ListShell, ListShellAdmin) admin.site.register(Ban, BanAdmin) +admin.site.register(MailAlias, MailAliasAdmin) admin.site.register(Whitelist, WhitelistAdmin) admin.site.register(Request, RequestAdmin) # Now register the new UserAdmin... diff --git a/users/models.py b/users/models.py index ba7fda3a..91995d61 100644 --- a/users/models.py +++ b/users/models.py @@ -1677,7 +1677,7 @@ class MailAlias(RevMixin, AclMixin, models.Model): """ Define a alias for a user Mail - Définit un aliase pour un Mail d'utilisateur + Définit un alias pour un Mail d'utilisateur """ mail = models.ForeignKey( 'Mail', @@ -1713,7 +1713,7 @@ class MailAlias(RevMixin, AclMixin, models.Model): def can_view(self, user_request, *_args, **_kwargs): """ - Check if the user can view the aliases + Check if the user can view the alias """ if user_request.has_perm('users.view_mailalias') or user.request == self.user: diff --git a/users/templates/users/aff_alias.html b/users/templates/users/aff_mailalias.html similarity index 97% rename from users/templates/users/aff_alias.html rename to users/templates/users/aff_mailalias.html index ec5b7313..a441b9e9 100644 --- a/users/templates/users/aff_alias.html +++ b/users/templates/users/aff_mailalias.html @@ -41,7 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% can_edit alias %} {% include 'buttons/edit.html' with href='users:edit-mailalias' id=alias.id %} {% acl_end %} - {% include 'buttons/history.html' with href='users:history' name='alias' id=alias.id %} + {% include 'buttons/history.html' with href='users:history' name='mailalias' id=alias.id %} {% endfor %} diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index b6e3c848..2a67934a 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -447,7 +447,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% acl_end %} {% if alias_list %} - {% include "users/aff_alias.html" with alias_list=alias_list %} + {% include "users/aff_mailalias.html" with alias_list=alias_list %} {% endif %} {% endif %} {% else %} From 04de9db6d4e278e461e19afbc11ba1f3543dcfba Mon Sep 17 00:00:00 2001 From: root Date: Sun, 15 Jul 2018 20:31:42 +0000 Subject: [PATCH 14/24] =?UTF-8?q?serialisation=20des=20alias=20mail=20des?= =?UTF-8?q?=20users=20ayant=20activ=C3=A9=20l'adresse=20interne?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/serializers.py | 14 ++++++++++++++ api/urls.py | 2 ++ api/views.py | 11 +++++++++++ users/models.py | 6 ++++++ 4 files changed, 33 insertions(+) mode change 100644 => 100755 api/serializers.py mode change 100644 => 100755 api/urls.py mode change 100644 => 100755 api/views.py mode change 100644 => 100755 users/models.py diff --git a/api/serializers.py b/api/serializers.py old mode 100644 new mode 100755 index e5e92c24..c9825f32 --- a/api/serializers.py +++ b/api/serializers.py @@ -608,6 +608,9 @@ class MailAliasSerializer(NamespacedHMSerializer): fields = ('user', 'valeur', 'complete_mail') + + + # SERVICE REGEN @@ -624,6 +627,17 @@ class ServiceRegenSerializer(NamespacedHMSerializer): extra_kwargs = { 'api_url': {'view_name': 'serviceregen-detail'} } + +# Configuration mail + + +class UserMailAliasSerializer(NamespacedHMSerializer): + get_mail_aliases = MailAliasSerializer(read_only=True, many=True) + + class Meta: + model = users.User + fields = ('pseudo', 'get_mail_aliases') + # DHCP diff --git a/api/urls.py b/api/urls.py old mode 100644 new mode 100755 index 80194bf5..049d99bf --- a/api/urls.py +++ b/api/urls.py @@ -98,6 +98,8 @@ router.register_viewset(r'users/mailalias', views.MailAliasViewSet) router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen') # DHCP router.register_view(r'dhcp/hostmacip', views.HostMacIpView), +# Mail config +router.register_view(r'mail/alias', views.UserMailAliasView), # DNS router.register_view(r'dns/zones', views.DNSZonesView), # MAILING diff --git a/api/views.py b/api/views.py old mode 100644 new mode 100755 index bd5c8f8b..4d5cae27 --- a/api/views.py +++ b/api/views.py @@ -496,6 +496,17 @@ class ServiceRegenViewSet(viewsets.ModelViewSet): return queryset +# Server mail config + + +class UserMailAliasView(generics.ListAPIView): + """Expose all the aliases of the users that activated the internal address + """ + + queryset = users.User.objects.filter(internal_address=True) + serializer_class = serializers.UserMailAliasSerializer + + # DHCP class HostMacIpView(generics.ListAPIView): diff --git a/users/models.py b/users/models.py old mode 100644 new mode 100755 index 91995d61..d6607623 --- a/users/models.py +++ b/users/models.py @@ -684,6 +684,12 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, else: return str(self.mailalias_set.get(valeur=self.pseudo)) + @cached_property + def get_mail_aliases(self): + if self.internal_address: + return self.mailalias_set.all() + return None + def get_next_domain_name(self): """Look for an available name for a new interface for this user by trying "pseudo0", "pseudo1", "pseudo2", ... From da87579f81ed40487c1aa39405441fcc8c1c09d0 Mon Sep 17 00:00:00 2001 From: chirac Date: Fri, 29 Jun 2018 16:36:04 +0200 Subject: [PATCH 15/24] Les champs mails sont dans users --- users/admin.py | 5 +- users/forms.py | 8 +-- users/migrations/0073_auto_20180629_1614.py | 46 +++++++++++++++ users/migrations/0073_mail_mailalias.py | 38 ------------ users/migrations/0074_transfermail.py | 36 ------------ users/models.py | 64 +++++++-------------- users/views.py | 7 +-- 7 files changed, 75 insertions(+), 129 deletions(-) create mode 100644 users/migrations/0073_auto_20180629_1614.py delete mode 100644 users/migrations/0073_mail_mailalias.py delete mode 100644 users/migrations/0074_transfermail.py diff --git a/users/admin.py b/users/admin.py index ce02aa09..ee71713c 100644 --- a/users/admin.py +++ b/users/admin.py @@ -34,7 +34,6 @@ from reversion.admin import VersionAdmin from .models import ( User, - Mail, MailAlias, ServiceUser, School, @@ -132,6 +131,7 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): list_display = ( 'pseudo', 'surname', + 'external_mail', 'school', 'is_admin', 'shell' @@ -145,7 +145,7 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): 'Personal info', { 'fields': - ('surname', 'school', 'shell', 'uid_number') + ('surname', 'external_mail', 'school', 'shell', 'uid_number') } ), ('Permissions', {'fields': ('is_admin', )}), @@ -160,6 +160,7 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): 'fields': ( 'pseudo', 'surname', + 'external_mail', 'school', 'is_admin', 'password1', diff --git a/users/forms.py b/users/forms.py index ebc4b945..144d5ecc 100644 --- a/users/forms.py +++ b/users/forms.py @@ -53,7 +53,6 @@ from .models import ( School, ListRight, Whitelist, - Mail, MailAlias, ListShell, Ban, @@ -307,7 +306,6 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): self.fields['room'].label = 'Chambre' self.fields['room'].empty_label = "Pas de chambre" self.fields['school'].empty_label = "Séléctionner un établissement" - class Meta: model = Adherent fields = [ @@ -601,7 +599,7 @@ class MailAliasForm(FormRevMixin, ModelForm): class Meta: model = MailAlias - exclude = ['mail'] + exclude = ['user'] class MailForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): """Creation, edition des paramètres mail""" @@ -615,5 +613,5 @@ class MailForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): self.fields['internal_address'].label = 'Adresse mail interne' class Meta: - model = Mail - exclude = ['user'] + model = User + fields = ['external_mail', 'redirection', 'internal_address'] diff --git a/users/migrations/0073_auto_20180629_1614.py b/users/migrations/0073_auto_20180629_1614.py new file mode 100644 index 00000000..681cb722 --- /dev/null +++ b/users/migrations/0073_auto_20180629_1614.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-29 14:14 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import re2o.mixins + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0072_auto_20180426_2021'), + ] + + operations = [ + migrations.CreateModel( + name='MailAlias', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('valeur', models.CharField(help_text="username de l'adresse mail", max_length=64, unique=True)), + ], + bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), + ), + migrations.RenameField( + model_name='user', + old_name='email', + new_name='external_mail', + ), + migrations.AddField( + model_name='user', + name='internal_address', + field=models.BooleanField(default=False, help_text="Activer ou non l'utilisation de l'adresse mail interne"), + ), + migrations.AddField( + model_name='user', + name='redirection', + field=models.BooleanField(default=False, help_text='Activer ou non la redirection du mail interne vers le mail externe'), + ), + migrations.AddField( + model_name='mailalias', + name='user', + field=models.ForeignKey(blank=True, help_text='Utilisateur associé', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/users/migrations/0073_mail_mailalias.py b/users/migrations/0073_mail_mailalias.py deleted file mode 100644 index ce676464..00000000 --- a/users/migrations/0073_mail_mailalias.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2018-06-26 19:07 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import re2o.mixins - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0072_auto_20180426_2021'), - ] - - operations = [ - migrations.CreateModel( - name='Mail', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('external_mail', models.EmailField(help_text='Mail externe', max_length=254)), - ('redirection', models.BooleanField(default=False)), - ('internal_address', models.BooleanField(default=False)), - ('user', models.OneToOneField(help_text="Object mail d'un User", on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), - ), - migrations.CreateModel( - name='MailAlias', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('valeur', models.CharField(help_text="username de l'adresse mail", max_length=64, unique=True)), - ('mail', models.ForeignKey(help_text='Objects Mail associé', on_delete=django.db.models.deletion.CASCADE, to='users.Mail')), - ], - bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), - ), - ] diff --git a/users/migrations/0074_transfermail.py b/users/migrations/0074_transfermail.py deleted file mode 100644 index dbf6adca..00000000 --- a/users/migrations/0074_transfermail.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2018-06-26 18:34 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0073_mail_mailalias'), - ] - - def create_mail(apps, schema_editor): - db_alias = schema_editor.connection.alias - user = apps.get_model('users','User') - mail = apps.get_model('users','Mail') - mailalias = apps.get_model('users','MailAlias') - users = user.objects.using(db_alias).all() - for us in users: - ma = mail() - ma.user=us - ma.external_mail = us.email - ma.save() - al = mailalias() - al.mail = ma - al.valeur = us.pseudo - al.save() - - def uncreatemail(apps,schema_editor): - pass - - operations = [ - migrations.RunPython(create_mail, uncreatemail) - ] diff --git a/users/models.py b/users/models.py index d6607623..4f0b2794 100755 --- a/users/models.py +++ b/users/models.py @@ -135,6 +135,7 @@ class UserManager(BaseUserManager): self, pseudo, surname, + external_mail, password=None, su=False ): @@ -148,6 +149,7 @@ class UserManager(BaseUserManager): pseudo=pseudo, surname=surname, name=surname, + external_mail=external_mail, ) user.set_password(password) @@ -156,19 +158,19 @@ class UserManager(BaseUserManager): user.save(using=self._db) return user - def create_user(self, pseudo, surname, password=None): + def create_user(self, pseudo, surname, external_mail, password=None): """ Creates and saves a User with the given pseudo, name, surname, email, and password. """ - return self._create_user(pseudo, surname, password, False) + return self._create_user(pseudo, surname, external_mail, password, False) - def create_superuser(self, pseudo, surname, password): + def create_superuser(self, pseudo, surname, external_mail, password): """ Creates and saves a superuser with the given pseudo, name, surname, email, and password. """ - return self._create_user(pseudo, surname, password, True) + return self._create_user(pseudo, surname, external_mail, password, True) class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, @@ -187,13 +189,21 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ) surname = models.CharField(max_length=255) - email = models.EmailField() pseudo = models.CharField( max_length=32, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator] ) + external_mail = models.EmailField() + redirection = models.BooleanField( + default=False, + help_text='Activer ou non la redirection du mail interne vers le mail externe' + ) + internal_address = models.BooleanField( + default=False, + help_text='Activer ou non l\'utilisation de l\'adresse mail interne' + ) school = models.ForeignKey( 'School', on_delete=models.PROTECT, @@ -226,7 +236,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ) USERNAME_FIELD = 'pseudo' - REQUIRED_FIELDS = ['surname'] + REQUIRED_FIELDS = ['surname', 'external_mail'] objects = UserManager() @@ -526,7 +536,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, user_ldap.sn = self.pseudo user_ldap.dialupAccess = str(self.has_access()) user_ldap.home_directory = '/home/' + self.pseudo - user_ldap.mail = self.email + user_ldap.mail = self.get_mail() user_ldap.given_name = self.surname.lower() + '_'\ + self.name.lower()[:3] user_ldap.gid = LDAP['user_gid'] @@ -1646,49 +1656,16 @@ class LdapServiceUserGroup(ldapdb.models.Model): return self.name -class Mail(RevMixin, AclMixin, models.Model): - """ - Mail account of a user - - Compte mail d'un utilisateur - """ - external_mail = models.EmailField(help_text="Mail externe") - user = models.OneToOneField( - 'User', - on_delete=models.CASCADE, - help_text="Object mail d'un User" - ) - redirection = models.BooleanField( - default=False - ) - internal_address = models.BooleanField( - default=False - ) - - def __str__(self): - return self.user.get_mail() - - def can_edit(self, user_request, *_args, **_kwargs): - """ - Check if the user can edit the mail - """ - - if user_request.has_perm('users.change_mail') or user_request == self.user: - return True, None - else: - return False, "Vous n'avez pas les droits suffisants et n'êtes pas propriétairs de cet alias" - - class MailAlias(RevMixin, AclMixin, models.Model): """ Define a alias for a user Mail Définit un alias pour un Mail d'utilisateur """ - mail = models.ForeignKey( - 'Mail', + user = models.ForeignKey( + User, on_delete=models.CASCADE, - help_text="Compte mail", + help_text="Utilisateur associé", ) valeur = models.CharField( unique=True, @@ -1696,7 +1673,6 @@ class MailAlias(RevMixin, AclMixin, models.Model): help_text="Valeur de l'alias mail" ) - def __str__(self): return self.valeur + OptionalUser.get_cached_value('mail_extension') diff --git a/users/views.py b/users/views.py index ab428853..09590be6 100644 --- a/users/views.py +++ b/users/views.py @@ -82,7 +82,6 @@ from .models import ( Club, ListShell, MailAlias, - Mail, ) from .forms import ( BanForm, @@ -501,7 +500,7 @@ def del_whitelist(request, whitelist, **_kwargs): @can_edit(User) def add_mailalias(request, user, userid): """ Créer un alias """ - mailalias_instance = MailAlias(mail=user.mail) + mailalias_instance = MailAlias(user=user) mailalias = MailAliasForm( request.POST or None, instance=mailalias_instance @@ -559,8 +558,8 @@ def del_mailalias(request, mailalias, **_kwargs): ) @login_required -@can_edit(Mail) -def edit_mail(request, mail_instance, **_kwargs): +@can_edit(User) +def edit_mail(request, user_instance, **_kwargs): """ Editer un compte mail""" mail = MailForm( request.POST or None, From 98a95da9a02dc9bd085ec7c9f5d7ccceb47c59df Mon Sep 17 00:00:00 2001 From: chirac Date: Fri, 29 Jun 2018 19:28:55 +0200 Subject: [PATCH 16/24] Initialise les alias pour les bases existantes --- users/migrations/0074_auto_20180629_1717.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/users/migrations/0074_auto_20180629_1717.py b/users/migrations/0074_auto_20180629_1717.py index ad450b5d..7574ea09 100644 --- a/users/migrations/0074_auto_20180629_1717.py +++ b/users/migrations/0074_auto_20180629_1717.py @@ -13,6 +13,19 @@ class Migration(migrations.Migration): ('users', '0073_auto_20180629_1614'), ] + def transfer_pseudo(apps, schema_editor): + db_alias = schema_editor.connection.alias + users = apps.get_model("users", "User") + mailalias = apps.get_model("users", "MailAlias") + users_list = users.objects.using(db_alias).all() + for user in users_list: + mailalias.objects.using(db_alias).create(valeur=user.pseudo, user=user) + + def untransfer_pseudo(apps, schema_editor): + db_alias = schema_editor.connection.alias + mailalias = apps.get_model("users", "MailAlias") + mailalias.objects.using(db_alias).delete() + operations = [ migrations.AlterField( model_name='mailalias', @@ -24,4 +37,5 @@ class Migration(migrations.Migration): name='valeur', field=models.CharField(help_text="Valeur de l'alias mail", max_length=128, unique=True), ), + migrations.RunPython(transfer_pseudo, untransfer_pseudo), ] From 751b30f1bd49b548f6bc6288c149bf0af18d090e Mon Sep 17 00:00:00 2001 From: chirac Date: Fri, 29 Jun 2018 17:45:21 +0200 Subject: [PATCH 17/24] =?UTF-8?q?Fix=20erreurs,=20cr=C3=A9ation=20alias=20?= =?UTF-8?q?mails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- users/migrations/0074_auto_20180629_1717.py | 1 + 1 file changed, 1 insertion(+) diff --git a/users/migrations/0074_auto_20180629_1717.py b/users/migrations/0074_auto_20180629_1717.py index 7574ea09..4700e34c 100644 --- a/users/migrations/0074_auto_20180629_1717.py +++ b/users/migrations/0074_auto_20180629_1717.py @@ -26,6 +26,7 @@ class Migration(migrations.Migration): mailalias = apps.get_model("users", "MailAlias") mailalias.objects.using(db_alias).delete() + operations = [ migrations.AlterField( model_name='mailalias', From 58e0d28110cb406dc139a8987b7362e55c9a70dd Mon Sep 17 00:00:00 2001 From: chirac Date: Mon, 23 Jul 2018 11:51:25 +0000 Subject: [PATCH 18/24] =?UTF-8?q?Adapte=20nouveau=20syst=C3=A8me=20histori?= =?UTF-8?q?que?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- preferences/urls.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/preferences/urls.py b/preferences/urls.py index ec35cc41..cd3bbc2c 100644 --- a/preferences/urls.py +++ b/preferences/urls.py @@ -29,7 +29,6 @@ from django.conf.urls import url from . import views - urlpatterns = [ url( r'^edit_options/(?P
OptionalUser)$', @@ -72,6 +71,6 @@ urlpatterns = [ views.edit_service, name='edit-service' ), - url(r'^del_services/$', views.del_services, name='del-services'), + url(r'^del_services/$', views.del_service, name='del-service'), url(r'^$', views.display_options, name='display-options'), ] From 1de27e51bb75e9781bbf34ad352ae34958c250e8 Mon Sep 17 00:00:00 2001 From: chirac Date: Fri, 29 Jun 2018 18:20:25 +0200 Subject: [PATCH 19/24] Boolean compte mail actif/inactif --- .../0036_optionaluser_mail_accounts.py | 20 +++++++++++++++++++ preferences/models.py | 4 ++++ .../preferences/display_preferences.html | 12 ++++++----- 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 preferences/migrations/0036_optionaluser_mail_accounts.py diff --git a/preferences/migrations/0036_optionaluser_mail_accounts.py b/preferences/migrations/0036_optionaluser_mail_accounts.py new file mode 100644 index 00000000..c3bf4fa8 --- /dev/null +++ b/preferences/migrations/0036_optionaluser_mail_accounts.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-29 16:01 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0035_optionaluser_mail_extension'), + ] + + operations = [ + migrations.AddField( + model_name='optionaluser', + name='mail_accounts', + field=models.BooleanField(default=False, help_text='Activation des comptes mails pour les utilisateurs'), + ), + ] diff --git a/preferences/models.py b/preferences/models.py index 42c22d53..ebfae5fe 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -85,6 +85,10 @@ class OptionalUser(AclMixin, PreferencesModel): blank=True, null=True ) + mail_accounts = models.BooleanField( + default=False, + help_text="Activation des comptes mails pour les utilisateurs" + ) mail_extension = models.CharField( max_length = 32, default = "@example.org", diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html index 83ce10bb..7e503021 100755 --- a/preferences/templates/preferences/display_preferences.html +++ b/preferences/templates/preferences/display_preferences.html @@ -33,11 +33,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,

Préférences utilisateur

- Editer - -

-

- + Editer + +

+

+
Généralités
+
@@ -69,6 +70,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Téléphone obligatoirement requis {{ useroptions.is_tel_mandatory|tick }}{{ useroption.max_mail_alias }}
+

Préférences machines

From 5b28887b3ada6056f760505e908ef9ff641655e5 Mon Sep 17 00:00:00 2001 From: chirac Date: Mon, 23 Jul 2018 12:17:10 +0000 Subject: [PATCH 20/24] Merge les migrations --- .../migrations/0046_merge_20180723_1413.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 preferences/migrations/0046_merge_20180723_1413.py diff --git a/preferences/migrations/0046_merge_20180723_1413.py b/preferences/migrations/0046_merge_20180723_1413.py new file mode 100644 index 00000000..b3dfaca6 --- /dev/null +++ b/preferences/migrations/0046_merge_20180723_1413.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-07-23 12:13 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0037_optionaluser_max_mail_alias'), + ('preferences', '0045_remove_unused_payment_fields'), + ] + + operations = [ + ] From 13aa05a109cad986a29ad36cdf7806cbcedfba66 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Sun, 29 Jul 2018 18:24:41 +0200 Subject: [PATCH 21/24] Del services --- preferences/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/preferences/urls.py b/preferences/urls.py index cd3bbc2c..c94d0758 100644 --- a/preferences/urls.py +++ b/preferences/urls.py @@ -71,6 +71,6 @@ urlpatterns = [ views.edit_service, name='edit-service' ), - url(r'^del_services/$', views.del_service, name='del-service'), + url(r'^del_services/$', views.del_services, name='del-services'), url(r'^$', views.display_options, name='display-options'), ] From bd19b27914f07ec948a4a396bae59eee1c37e44e Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Sun, 29 Jul 2018 19:13:09 +0200 Subject: [PATCH 22/24] Fix synthax + english --- .../0035_optionaluser_mail_extension.py | 2 +- .../0036_optionaluser_mail_accounts.py | 2 +- .../0037_optionaluser_max_mail_alias.py | 2 +- preferences/models.py | 13 ++++++------- users/forms.py | 12 ++++++------ users/templates/users/index_alias.html | 2 +- users/views.py | 17 ++++++++--------- 7 files changed, 24 insertions(+), 26 deletions(-) diff --git a/preferences/migrations/0035_optionaluser_mail_extension.py b/preferences/migrations/0035_optionaluser_mail_extension.py index 3d1b42b4..dd26f433 100644 --- a/preferences/migrations/0035_optionaluser_mail_extension.py +++ b/preferences/migrations/0035_optionaluser_mail_extension.py @@ -15,6 +15,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='optionaluser', name='mail_extension', - field=models.CharField(default='@example.org', help_text='Extension principale pour les mails internes', max_length=32), + field=models.CharField(default='@example.org', help_text='Main extension for internal address', max_length=32), ), ] diff --git a/preferences/migrations/0036_optionaluser_mail_accounts.py b/preferences/migrations/0036_optionaluser_mail_accounts.py index c3bf4fa8..db604287 100644 --- a/preferences/migrations/0036_optionaluser_mail_accounts.py +++ b/preferences/migrations/0036_optionaluser_mail_accounts.py @@ -15,6 +15,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='optionaluser', name='mail_accounts', - field=models.BooleanField(default=False, help_text='Activation des comptes mails pour les utilisateurs'), + field=models.BooleanField(default=False, help_text='Enable mail accounts for users'), ), ] diff --git a/preferences/migrations/0037_optionaluser_max_mail_alias.py b/preferences/migrations/0037_optionaluser_max_mail_alias.py index 8d6ca609..f5198177 100644 --- a/preferences/migrations/0037_optionaluser_max_mail_alias.py +++ b/preferences/migrations/0037_optionaluser_max_mail_alias.py @@ -15,6 +15,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='optionaluser', name='max_mail_alias', - field=models.IntegerField(default=15, help_text="Nombre maximal d'alias pour un utilisateur lambda"), + field=models.IntegerField(default=15, help_text="Max alias mail for a lambda user"), ), ] diff --git a/preferences/models.py b/preferences/models.py index ebfae5fe..aa1a662b 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -87,16 +87,16 @@ class OptionalUser(AclMixin, PreferencesModel): ) mail_accounts = models.BooleanField( default=False, - help_text="Activation des comptes mails pour les utilisateurs" + help_text="Enable mail accounts for users" ) mail_extension = models.CharField( max_length = 32, default = "@example.org", - help_text="Extension principale pour les mails internes", + help_text="Main extension for internal address", ) max_mail_alias = models.IntegerField( default = 15, - help_text = "Nombre maximal d'alias pour un utilisateur lambda" + help_text = "Max alias mail for a lambda user" ) class Meta: @@ -105,12 +105,11 @@ class OptionalUser(AclMixin, PreferencesModel): ) def clean(self): - """Clean du model: - Creation du mode de paiement par solde - Vérifie que l'extension mail commence bien par @ + """Clean model: + Check the mail_extension """ if self.mail_extension[0] != "@": - raise ValidationError("L'extension mail doit commencer par un @") + raise ValidationError("Mail extension must begin with @") @receiver(post_save, sender=OptionalUser) diff --git a/users/forms.py b/users/forms.py index 144d5ecc..14a630bd 100644 --- a/users/forms.py +++ b/users/forms.py @@ -591,26 +591,26 @@ class WhitelistForm(FormRevMixin, ModelForm): class MailAliasForm(FormRevMixin, ModelForm): - """Creation, edition d'un objet alias mail""" + """Create and edit a mailalias""" def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(MailAliasForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['valeur'].label = "Prefixe de l'alias mail. Ne peut contenir de @" + self.fields['valeur'].label = "Prefix of mailalias. Can't contain @" class Meta: model = MailAlias exclude = ['user'] class MailForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): - """Creation, edition des paramètres mail""" + """Edit mail settings""" def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(MailForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['external_mail'].label = 'Adresse mail externe' + self.fields['external_mail'].label = 'External mail address' if 'redirection' in self.fields: - self.fields['redirection'].label = 'Activation de la redirection vers l\'adress externe' + self.fields['redirection'].label = 'Enable redirect to external address' if 'internal_address' in self.fields: - self.fields['internal_address'].label = 'Adresse mail interne' + self.fields['internal_address'].label = 'Internal mail address' class Meta: model = User diff --git a/users/templates/users/index_alias.html b/users/templates/users/index_alias.html index dc9af095..52c68733 100644 --- a/users/templates/users/index_alias.html +++ b/users/templates/users/index_alias.html @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} -{% block title %}Utilisateurs{% endblock %} +{% block title %}Users{% endblock %} {% block content %}

Alias

diff --git a/users/views.py b/users/views.py index 09590be6..3a2b11f7 100644 --- a/users/views.py +++ b/users/views.py @@ -499,7 +499,7 @@ def del_whitelist(request, whitelist, **_kwargs): @can_create(MailAlias) @can_edit(User) def add_mailalias(request, user, userid): - """ Créer un alias """ + """ Create a new alias""" mailalias_instance = MailAlias(user=user) mailalias = MailAliasForm( request.POST or None, @@ -507,13 +507,13 @@ def add_mailalias(request, user, userid): ) if mailalias.is_valid(): mailalias.save() - messages.success(request, "Alias créé") + messages.success(request, "Alias created") return redirect(reverse( 'users:profil', kwargs={'userid': str(userid)} )) return form( - {'userform': mailalias, 'action_name': 'Ajouter un alias mail'}, + {'userform': mailalias, 'action_name': 'Add an alias mail'}, 'users/user.html', request ) @@ -521,7 +521,7 @@ def add_mailalias(request, user, userid): @login_required @can_edit(MailAlias) def edit_mailalias(request, mailalias_instance, **_kwargs): - """ Editer un alias mail""" + """ Edit a mailalias""" mailalias = MailAliasForm( request.POST or None, instance=mailalias_instance @@ -529,13 +529,13 @@ def edit_mailalias(request, mailalias_instance, **_kwargs): if mailalias.is_valid(): if mailalias.changed_data: mailalias.save() - messages.success(request, "Alias modifiée") + messages.success(request, "Alias modified") return redirect(reverse( 'users:profil', kwargs={'userid': str(mailalias_instance.user.id)} )) return form( - {'userform': mailalias, 'action_name': 'Editer un alias mail'}, + {'userform': mailalias, 'action_name': 'Edit a mailalias'}, 'users/user.html', request ) @@ -543,10 +543,10 @@ def edit_mailalias(request, mailalias_instance, **_kwargs): @login_required @can_delete(MailAlias) def del_mailalias(request, mailalias, **_kwargs): - """ Supprime un alias mail""" + """Delete a mail alias""" if request.method == "POST": mailalias.delete() - messages.success(request, "L'alias a été supprimé") + messages.success(request, "Alias deleted") return redirect(reverse( 'users:profil', kwargs={'userid': str(mailalias.user.id)} @@ -1002,7 +1002,6 @@ def profil(request, users, **_kwargs): 'white_list': whitelists, 'user_solde': user_solde, 'solde_activated': Paiement.objects.filter(is_balance=True).exists(), - 'asso_name': AssoOption.objects.first().name 'allow_online_payment': allow_online_payment, 'asso_name': AssoOption.objects.first().name, 'alias_list': users.mailalias_set.all(), From 43fb83ec121323b651393b67a4357b5191a354bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Mon, 30 Jul 2018 15:00:41 +0000 Subject: [PATCH 23/24] Cleanup for local email accounts --- api/serializers.py | 46 ++- api/urls.py | 6 +- api/views.py | 34 +- .../0035_optionaluser_mail_extension.py | 20 - .../0036_optionaluser_mail_accounts.py | 20 - .../0037_optionaluser_max_mail_alias.py | 20 - .../migrations/0046_merge_20180723_1413.py | 16 - .../0046_optionaluser_mail_extension.py | 30 ++ preferences/models.py | 21 +- .../preferences/display_preferences.html | 342 +++++++++--------- preferences/urls.py | 1 + re2o/templatetags/acl.py | 1 + users/admin.py | 14 +- users/forms.py | 42 ++- users/migrations/0073_auto_20180629_1614.py | 42 ++- users/migrations/0074_auto_20180629_1717.py | 42 --- users/models.py | 219 ++++++----- ...alias.html => aff_localemailaccounts.html} | 40 +- ...lias.html => index_localemailaccount.html} | 9 +- users/templates/users/profil.html | 94 +++-- users/urls.py | 16 +- users/views.py | 111 +++--- 22 files changed, 587 insertions(+), 599 deletions(-) mode change 100755 => 100644 api/serializers.py mode change 100755 => 100644 api/urls.py mode change 100755 => 100644 api/views.py delete mode 100644 preferences/migrations/0035_optionaluser_mail_extension.py delete mode 100644 preferences/migrations/0036_optionaluser_mail_accounts.py delete mode 100644 preferences/migrations/0037_optionaluser_max_mail_alias.py delete mode 100644 preferences/migrations/0046_merge_20180723_1413.py create mode 100644 preferences/migrations/0046_optionaluser_mail_extension.py mode change 100755 => 100644 preferences/templates/preferences/display_preferences.html delete mode 100644 users/migrations/0074_auto_20180629_1717.py rename users/templates/users/{aff_mailalias.html => aff_localemailaccounts.html} (60%) rename users/templates/users/{index_alias.html => index_localemailaccount.html} (85%) diff --git a/api/serializers.py b/api/serializers.py old mode 100755 new mode 100644 index c9825f32..d07cb9fe --- a/api/serializers.py +++ b/api/serializers.py @@ -492,12 +492,11 @@ class UserSerializer(NamespacedHMSerializer): """ access = serializers.BooleanField(source='has_access') uid = serializers.IntegerField(source='uid_number') - email = serializers.CharField(source='get_mail') class Meta: model = users.User - fields = ('name', 'pseudo', 'email', 'school', 'shell', 'comment', - 'external_mail', 'redirection', 'internal_address', + fields = ('surname', 'pseudo', 'email', 'local_email_redirect', + 'local_email_enabled', 'school', 'shell', 'comment', 'state', 'registered', 'telephone', 'solde', 'access', 'end_access', 'uid', 'class_name', 'api_url') extra_kwargs = { @@ -511,12 +510,11 @@ class ClubSerializer(NamespacedHMSerializer): name = serializers.CharField(source='surname') access = serializers.BooleanField(source='has_access') uid = serializers.IntegerField(source='uid_number') - email = serializers.CharField(source='get_mail') class Meta: model = users.Club - fields = ('name', 'pseudo', 'email', 'school', 'shell', 'comment', - 'external_mail', 'redirection', 'internal_address', + fields = ('name', 'pseudo', 'email', 'local_email_redirect', + 'local_email_enabled', 'school', 'shell', 'comment', 'state', 'registered', 'telephone', 'solde', 'room', 'access', 'end_access', 'administrators', 'members', 'mailing', 'uid', 'api_url') @@ -530,14 +528,13 @@ class AdherentSerializer(NamespacedHMSerializer): """ access = serializers.BooleanField(source='has_access') uid = serializers.IntegerField(source='uid_number') - email = serializers.CharField(source='get_mail') class Meta: model = users.Adherent - fields = ('name', 'surname', 'pseudo', 'email', 'redirection', 'internal_address', - 'external_mail', 'school', 'shell', - 'comment', 'state', 'registered', 'telephone', 'room', - 'solde', 'access', 'end_access', 'uid', 'api_url') + fields = ('name', 'surname', 'pseudo', 'email', 'local_email_redirect', + 'local_email_enabled', 'school', 'shell', 'comment', + 'state', 'registered', 'telephone', 'room', 'solde', + 'access', 'end_access', 'uid', 'api_url') extra_kwargs = { 'shell': {'view_name': 'shell-detail'} } @@ -599,16 +596,13 @@ class WhitelistSerializer(NamespacedHMSerializer): fields = ('user', 'raison', 'date_start', 'date_end', 'active', 'api_url') -class MailAliasSerializer(NamespacedHMSerializer): - """Serialize `users.models.MailAlias` objects. +class LocalEmailAccountSerializer(NamespacedHMSerializer): + """Serialize `users.models.LocalEmailAccount` objects. """ class Meta: - model = users.MailAlias - fields = ('user', 'valeur', 'complete_mail') - - - + model = users.LocalEmailAccount + fields = ('user', 'local_part', 'complete_email_address', 'api_url') # SERVICE REGEN @@ -627,17 +621,21 @@ class ServiceRegenSerializer(NamespacedHMSerializer): extra_kwargs = { 'api_url': {'view_name': 'serviceregen-detail'} } - -# Configuration mail -class UserMailAliasSerializer(NamespacedHMSerializer): - get_mail_aliases = MailAliasSerializer(read_only=True, many=True) +# LOCAL EMAILS + + +class LocalEmailUsersSerializer(NamespacedHMSerializer): + local_email_accounts = LocalEmailAccountSerializer( + read_only=True, + many=True + ) class Meta: model = users.User - fields = ('pseudo', 'get_mail_aliases') - + fields = ('local_email_enabled', 'local_email_redirect', + 'local_email_accounts') # DHCP diff --git a/api/urls.py b/api/urls.py old mode 100755 new mode 100644 index 049d99bf..88211c4b --- a/api/urls.py +++ b/api/urls.py @@ -93,13 +93,13 @@ router.register_viewset(r'users/listright', views.ListRightViewSet) router.register_viewset(r'users/shell', views.ShellViewSet, base_name='shell') router.register_viewset(r'users/ban', views.BanViewSet) router.register_viewset(r'users/whitelist', views.WhitelistViewSet) -router.register_viewset(r'users/mailalias', views.MailAliasViewSet) +router.register_viewset(r'users/localemailaccount', views.LocalEmailAccountViewSet) # SERVICE REGEN router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen') # DHCP router.register_view(r'dhcp/hostmacip', views.HostMacIpView), -# Mail config -router.register_view(r'mail/alias', views.UserMailAliasView), +# LOCAL EMAILS +router.register_view(r'localemail/users', views.LocalEmailUsersView), # DNS router.register_view(r'dns/zones', views.DNSZonesView), # MAILING diff --git a/api/views.py b/api/views.py old mode 100755 new mode 100644 index 4d5cae27..04c7a461 --- a/api/views.py +++ b/api/views.py @@ -469,11 +469,19 @@ class WhitelistViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.WhitelistSerializer -class MailAliasViewSet(viewsets.ReadOnlyModelViewSet): - """Exposes list and details of `users.models.MailAlias` objects. +class LocalEmailAccountViewSet(viewsets.ReadOnlyModelViewSet): + """Exposes list and details of `users.models.LocalEmailAccount` objects. """ - queryset = users.MailAlias.objects.all() - serializer_class = serializers.MailAliasSerializer + serializer_class = serializers.LocalEmailAccountSerializer + queryset = users.LocalEmailAccount.objects.none() + + def get_queryset(self): + if preferences.OptionalUser.get_cached_value( + 'local_email_accounts_enabled'): + return (users.LocalEmailAccount.objects + .filter(user__local_email_enabled=True)) + else: + return users.LocalEmailAccount.objects.none() # SERVICE REGEN @@ -496,19 +504,26 @@ class ServiceRegenViewSet(viewsets.ModelViewSet): return queryset -# Server mail config +# LOCAL EMAILS -class UserMailAliasView(generics.ListAPIView): - """Expose all the aliases of the users that activated the internal address +class LocalEmailUsersView(generics.ListAPIView): + """Exposes all the aliases of the users that activated the internal address """ + serializer_class = serializers.LocalEmailUsersSerializer - queryset = users.User.objects.filter(internal_address=True) - serializer_class = serializers.UserMailAliasSerializer + def get_queryset(self): + if preferences.OptionalUser.get_cached_value( + 'local_email_accounts_enabled'): + return (users.User.objects + .filter(local_email_enabled=True)) + else: + return users.User.objects.none() # DHCP + class HostMacIpView(generics.ListAPIView): """Exposes the associations between hostname, mac address and IPv4 in order to build the DHCP lease files. @@ -519,6 +534,7 @@ class HostMacIpView(generics.ListAPIView): # DNS + class DNSZonesView(generics.ListAPIView): """Exposes the detailed information about each extension (hostnames, IPs, DNS records, etc.) in order to build the DNS zone files. diff --git a/preferences/migrations/0035_optionaluser_mail_extension.py b/preferences/migrations/0035_optionaluser_mail_extension.py deleted file mode 100644 index dd26f433..00000000 --- a/preferences/migrations/0035_optionaluser_mail_extension.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2018-06-26 19:31 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('preferences', '0034_auto_20180416_1120'), - ] - - operations = [ - migrations.AddField( - model_name='optionaluser', - name='mail_extension', - field=models.CharField(default='@example.org', help_text='Main extension for internal address', max_length=32), - ), - ] diff --git a/preferences/migrations/0036_optionaluser_mail_accounts.py b/preferences/migrations/0036_optionaluser_mail_accounts.py deleted file mode 100644 index db604287..00000000 --- a/preferences/migrations/0036_optionaluser_mail_accounts.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2018-06-29 16:01 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('preferences', '0035_optionaluser_mail_extension'), - ] - - operations = [ - migrations.AddField( - model_name='optionaluser', - name='mail_accounts', - field=models.BooleanField(default=False, help_text='Enable mail accounts for users'), - ), - ] diff --git a/preferences/migrations/0037_optionaluser_max_mail_alias.py b/preferences/migrations/0037_optionaluser_max_mail_alias.py deleted file mode 100644 index f5198177..00000000 --- a/preferences/migrations/0037_optionaluser_max_mail_alias.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2018-06-30 12:32 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('preferences', '0036_optionaluser_mail_accounts'), - ] - - operations = [ - migrations.AddField( - model_name='optionaluser', - name='max_mail_alias', - field=models.IntegerField(default=15, help_text="Max alias mail for a lambda user"), - ), - ] diff --git a/preferences/migrations/0046_merge_20180723_1413.py b/preferences/migrations/0046_merge_20180723_1413.py deleted file mode 100644 index b3dfaca6..00000000 --- a/preferences/migrations/0046_merge_20180723_1413.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2018-07-23 12:13 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('preferences', '0037_optionaluser_max_mail_alias'), - ('preferences', '0045_remove_unused_payment_fields'), - ] - - operations = [ - ] diff --git a/preferences/migrations/0046_optionaluser_mail_extension.py b/preferences/migrations/0046_optionaluser_mail_extension.py new file mode 100644 index 00000000..5fc6c5e0 --- /dev/null +++ b/preferences/migrations/0046_optionaluser_mail_extension.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-26 19:31 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0045_remove_unused_payment_fields'), + ] + + operations = [ + migrations.AddField( + model_name='optionaluser', + name='local_email_accounts_enabled', + field=models.BooleanField(default=False, help_text='Enable local email accounts for users'), + ), + migrations.AddField( + model_name='optionaluser', + name='local_email_domain', + field=models.CharField(default='@example.org', help_text='Domain to use for local email accounts', max_length=32), + ), + migrations.AddField( + model_name='optionaluser', + name='max_local_email_accounts', + field=models.IntegerField(default=15, help_text='Maximum number of local email accounts for a standard user'), + ), + ] diff --git a/preferences/models.py b/preferences/models.py index aa1a662b..5f13bc4b 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -30,9 +30,8 @@ from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver from django.core.cache import cache - from django.forms import ValidationError -import cotisations.models + import machines.models from re2o.mixins import AclMixin @@ -85,18 +84,18 @@ class OptionalUser(AclMixin, PreferencesModel): blank=True, null=True ) - mail_accounts = models.BooleanField( + local_email_accounts_enabled = models.BooleanField( default=False, - help_text="Enable mail accounts for users" + help_text="Enable local email accounts for users" ) - mail_extension = models.CharField( + local_email_domain = models.CharField( max_length = 32, default = "@example.org", - help_text="Main extension for internal address", + help_text="Domain to use for local email accounts", ) - max_mail_alias = models.IntegerField( + max_local_email_accounts = models.IntegerField( default = 15, - help_text = "Max alias mail for a lambda user" + help_text = "Maximum number of local email accounts for a standard user" ) class Meta: @@ -108,9 +107,9 @@ class OptionalUser(AclMixin, PreferencesModel): """Clean model: Check the mail_extension """ - if self.mail_extension[0] != "@": - raise ValidationError("Mail extension must begin with @") - + if self.local_email_domain[0] != "@": + raise ValidationError("Mail domain must begin with @") + @receiver(post_save, sender=OptionalUser) def optionaluser_post_save(**kwargs): diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html old mode 100755 new mode 100644 index 7e503021..c6f11734 --- a/preferences/templates/preferences/display_preferences.html +++ b/preferences/templates/preferences/display_preferences.html @@ -32,206 +32,204 @@ with this program; if not, write to the Free Software Foundation, Inc., {% block content %}

Préférences utilisateur

- - Editer - -

-

-
Généralités
- - - - - - - - - - - - - - - - - - - -
{% if useroptions.mail_accounts %}Comptes mails{% else %}Comptes mails{% endif%}
-
Téléphone obligatoirement requis{{ useroptions.is_tel_mandatory|tick }}Auto inscription{{ useroptions.self_adhesion|tick }}
Champ gpg fingerprint{{ useroptions.gpg_fingerprint|tick }}Shell par défaut des utilisateurs{{ useroptions.shell_default }}
Creations d'adhérents par tous{{ useroptions.all_can_create_adherent|tick }}Creations de clubs par tous{{ useroptions.all_can_create_club|tick }}
- - - - - - - - - -
Gestion des comptes mails{{ useroptions.mail_accounts }}Extension mail interne{{ useroptions.mail_extension }}
Nombre d'alias maximum{{ useroption.max_mail_alias }} -
+ Editer + -

Préférences machines

- - - Editer - -

-

- - - - - - - - - - - - - - - - - +
Généralités
+
Mot de passe par machine{{ machineoptions.password_machine|tick }}Machines/interfaces autorisées par utilisateurs{{ machineoptions.max_lambdauser_interfaces }}
Alias dns autorisé par utilisateur{{ machineoptions.max_lambdauser_aliases }}Support de l'ipv6{{ machineoptions.ipv6_mode }}
Creation de machines{{ machineoptions.create_machine|tick }}
+ + + + + + + + + + + + + + + + + +
Téléphone obligatoirement requis{{ useroptions.is_tel_mandatory|tick }}Auto inscription{{ useroptions.self_adhesion|tick }}
Champ gpg fingerprint{{ useroptions.gpg_fingerprint|tick }}Shell par défaut des utilisateurs{{ useroptions.shell_default }}
Creations d'adhérents par tous{{ useroptions.all_can_create_adherent|tick }}Creations de clubs par tous{{ useroptions.all_can_create_club|tick }}
+ +
Comptes mails
+ + + + + + + + + + + +
Gestion des comptes mails{{ useroptions.local_email_accounts_enabled | tick }}Extension mail interne{{ useroptions.local_email_domain }}
Nombre de comptes maximum{{ useroptions.max_local_email_accounts }}
+ + +

Préférences machines

+ + Editer + + + + + + + + + + + + + + + + + + +
Mot de passe par machine{{ machineoptions.password_machine|tick }}Machines/interfaces autorisées par utilisateurs{{ machineoptions.max_lambdauser_interfaces }}
Alias dns autorisé par utilisateur{{ machineoptions.max_lambdauser_aliases }}Support de l'ipv6{{ machineoptions.ipv6_mode }}
Creation de machines{{ machineoptions.create_machine|tick }}
+ +

Préférences topologie

- - Editer + Editer -

-

- - - - - - - - - - - - + + + + + + + + + + + +
Politique générale de placement de vlan{{ topologieoptions.radius_general_policy }} Ce réglage défini la politique vlan après acceptation radius : soit sur le vlan de la plage d'ip de la machine, soit sur un vlan prédéfini dans "Vlan où placer les machines après acceptation RADIUS"
Vlan où placer les machines après acceptation RADIUS{{ topologieoptions.vlan_decision_ok }}Vlan où placer les machines après rejet RADIUS{{ topologieoptions.vlan_decision_nok }}
Politique générale de placement de vlan{{ topologieoptions.radius_general_policy }} + Ce réglage défini la politique vlan après acceptation radius : + soit sur le vlan de la plage d'ip de la machine, soit sur un + vlan prédéfini dans "Vlan où placer les machines après acceptation + RADIUS" +
Vlan où placer les machines après acceptation RADIUS{{ topologieoptions.vlan_decision_ok }}Vlan où placer les machines après rejet RADIUS{{ topologieoptions.vlan_decision_nok }}
+ +

Préférences generales

- - Editer + Editer -

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +
Nom du site web{{ generaloptions.site_name }}Adresse mail d'expedition automatique{{ generaloptions.email_from }}
Affichage de résultats dans le champ de recherche{{ generaloptions.search_display_page }}Nombre d'items affichés en liste (taille normale){{ generaloptions.pagination_number }}
Nombre d'items affichés en liste (taille élevée){{ generaloptions.pagination_large_number }}Temps avant expiration du lien de reinitialisation de mot de passe (en heures){{ generaloptions.req_expire_hrs }}
Message global affiché sur le site{{ generaloptions.general_message }}Résumé des CGU{{ generaloptions.GTU_sum_up }}
CGU{{generaloptions.GTU}} -
Nom du site web{{ generaloptions.site_name }}Adresse mail d'expedition automatique{{ generaloptions.email_from }}
Affichage de résultats dans le champ de recherche{{ generaloptions.search_display_page }}Nombre d'items affichés en liste (taille normale){{ generaloptions.pagination_number }}
Nombre d'items affichés en liste (taille élevée){{ generaloptions.pagination_large_number }}Temps avant expiration du lien de reinitialisation de mot de passe (en heures){{ generaloptions.req_expire_hrs }}
Message global affiché sur le site{{ generaloptions.general_message }}Résumé des CGU{{ generaloptions.GTU_sum_up }}
CGU{{generaloptions.GTU}} +
+ +

Données de l'association

- - Editer + Editer -

-

- - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +
Nom{{ assooptions.name }}SIRET{{ assooptions.siret }}
Adresse{{ assooptions.adresse1 }}
- {{ assooptions.adresse2 }}
Contact mail{{ assooptions.contact }}
Telephone{{ assooptions.telephone }}Pseudo d'usage{{ assooptions.pseudo }}
Objet utilisateur de l'association{{ assooptions.utilisateur_asso }}Description de l'association{{ assooptions.description | safe }}
Nom{{ assooptions.name }}SIRET{{ assooptions.siret }}
Adresse{{ assooptions.adresse1 }}
+ {{ assooptions.adresse2 }}
Contact mail{{ assooptions.contact }}
Telephone{{ assooptions.telephone }}Pseudo d'usage{{ assooptions.pseudo }}
Objet utilisateur de l'association{{ assooptions.utilisateur_asso }}Description de l'association{{ assooptions.description | safe }}
+ +

Messages personalisé dans les mails

- - Editer + Editer -

-

- - - - - - - - + + + + + + + +
Mail de bienvenue (Français){{ mailmessageoptions.welcome_mail_fr | safe }}
Mail de bienvenue (Anglais){{ mailmessageoptions.welcome_mail_en | safe }}
Mail de bienvenue (Français){{ mailmessageoptions.welcome_mail_fr | safe }}
Mail de bienvenue (Anglais){{ mailmessageoptions.welcome_mail_en | safe }}
-

Liste des services et préférences page d'accueil

+ + +

Liste des services et préférences page d'accueil

{% can_create preferences.Service%} - Ajouter un service + + Ajouter un service + {% acl_end %} - Supprimer un ou plusieurs service + + Supprimer un ou plusieurs service + {% include "preferences/aff_service.html" with service_list=service_list %} - - Editer + Editer -

- - - - - - - - - - - + + + + + + + + + +
Url du compte twitter{{ homeoptions.twitter_url }}Nom utilisé pour afficher le compte{{ homeoptions.twitter_account_name }}
Url du compte facebook{{ homeoptions.facebook_url }}
Url du compte twitter{{ homeoptions.twitter_url }}Nom utilisé pour afficher le compte{{ homeoptions.twitter_account_name }}
Url du compte facebook{{ homeoptions.facebook_url }}
-
-
-
{% endblock %} diff --git a/preferences/urls.py b/preferences/urls.py index c94d0758..ec35cc41 100644 --- a/preferences/urls.py +++ b/preferences/urls.py @@ -29,6 +29,7 @@ from django.conf.urls import url from . import views + urlpatterns = [ url( r'^edit_options/(?P

OptionalUser)$', diff --git a/re2o/templatetags/acl.py b/re2o/templatetags/acl.py index 9a439f88..fe13c5ac 100644 --- a/re2o/templatetags/acl.py +++ b/re2o/templatetags/acl.py @@ -79,6 +79,7 @@ from django.contrib.contenttypes.models import ContentType register = template.Library() + def get_model(model_name): """Retrieve the model object from its name""" splitted = model_name.split('.') diff --git a/users/admin.py b/users/admin.py index ee71713c..bc1670a7 100644 --- a/users/admin.py +++ b/users/admin.py @@ -34,7 +34,7 @@ from reversion.admin import VersionAdmin from .models import ( User, - MailAlias, + LocalEmailAccount, ServiceUser, School, ListRight, @@ -109,7 +109,7 @@ class BanAdmin(VersionAdmin): pass -class MailAliasAdmin(VersionAdmin): +class LocalEmailAccountAdmin(VersionAdmin): """Gestion des alias mail""" pass @@ -131,7 +131,9 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): list_display = ( 'pseudo', 'surname', - 'external_mail', + 'email', + 'local_email_redirect', + 'local_email_enabled', 'school', 'is_admin', 'shell' @@ -145,7 +147,7 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): 'Personal info', { 'fields': - ('surname', 'external_mail', 'school', 'shell', 'uid_number') + ('surname', 'email', 'school', 'shell', 'uid_number') } ), ('Permissions', {'fields': ('is_admin', )}), @@ -160,7 +162,7 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): 'fields': ( 'pseudo', 'surname', - 'external_mail', + 'email', 'school', 'is_admin', 'password1', @@ -217,7 +219,7 @@ admin.site.register(School, SchoolAdmin) admin.site.register(ListRight, ListRightAdmin) admin.site.register(ListShell, ListShellAdmin) admin.site.register(Ban, BanAdmin) -admin.site.register(MailAlias, MailAliasAdmin) +admin.site.register(LocalEmailAccount, LocalEmailAccountAdmin) admin.site.register(Whitelist, WhitelistAdmin) admin.site.register(Request, RequestAdmin) # Now register the new UserAdmin... diff --git a/users/forms.py b/users/forms.py index 14a630bd..7b17a5ec 100644 --- a/users/forms.py +++ b/users/forms.py @@ -53,7 +53,7 @@ from .models import ( School, ListRight, Whitelist, - MailAlias, + LocalEmailAccount, ListShell, Ban, Adherent, @@ -140,7 +140,7 @@ class UserCreationForm(FormRevMixin, forms.ModelForm): class Meta: model = Adherent - fields = ('pseudo', 'surname') + fields = ('pseudo', 'surname', 'email') def clean_password2(self): """Verifie que password1 et 2 sont identiques""" @@ -306,6 +306,7 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): self.fields['room'].label = 'Chambre' self.fields['room'].empty_label = "Pas de chambre" self.fields['school'].empty_label = "Séléctionner un établissement" + class Meta: model = Adherent fields = [ @@ -590,28 +591,37 @@ class WhitelistForm(FormRevMixin, ModelForm): widgets = {'date_end':DateTimePicker} -class MailAliasForm(FormRevMixin, ModelForm): - """Create and edit a mailalias""" +class LocalEmailAccountForm(FormRevMixin, ModelForm): + """Create and edit a local email account""" def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) - super(MailAliasForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['valeur'].label = "Prefix of mailalias. Can't contain @" + super(LocalEmailAccountForm, self).__init__(*args, prefix=prefix, **kwargs) + self.fields['local_part'].label = "Local part of the email" + self.fields['local_part'].help_text = "Can't contain @" class Meta: - model = MailAlias + model = LocalEmailAccount exclude = ['user'] -class MailForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): - """Edit mail settings""" + +class EmailSettingsForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): + """Edit email-related settings""" def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) - super(MailForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['external_mail'].label = 'External mail address' - if 'redirection' in self.fields: - self.fields['redirection'].label = 'Enable redirect to external address' - if 'internal_address' in self.fields: - self.fields['internal_address'].label = 'Internal mail address' + super(EmailSettingsForm, self).__init__(*args, prefix=prefix, **kwargs) + self.fields['email'].label = "Contact email address" + if 'local_email_redirect' in self.fields: + self.fields['local_email_redirect'].label = "Redirect local emails" + self.fields['local_email_redirect'].help_text = ( + "Enable the automated redirection of the local email address " + "to the contact email address" + ) + if 'local_email_enabled' in self.fields: + self.fields['local_email_enabled'].label = "Use local emails" + self.fields['local_email_enabled'].help_text = ( + "Enable the use of the local email account" + ) class Meta: model = User - fields = ['external_mail', 'redirection', 'internal_address'] + fields = ['email', 'local_email_redirect', 'local_email_enabled'] diff --git a/users/migrations/0073_auto_20180629_1614.py b/users/migrations/0073_auto_20180629_1614.py index 681cb722..6b976f88 100644 --- a/users/migrations/0073_auto_20180629_1614.py +++ b/users/migrations/0073_auto_20180629_1614.py @@ -10,37 +10,49 @@ import re2o.mixins class Migration(migrations.Migration): + def create_initial_local_email_account(apps, schema_editor): + db_alias = schema_editor.connection.alias + User = apps.get_model("users", "User") + LocalEmailAccount = apps.get_model("users", "LocalEmailAccount") + users = User.objects.using(db_alias).all() + for user in users: + LocalEmailAccount.objects.using(db_alias).create( + local_part=user.pseudo, + user=user + ) + + def delete_all_local_email_accounts(apps, schema_editor): + db_alias = schema_editor.connection.alias + LocalEmailAccount = apps.get_model("users", "LocalEmailAccount") + LocalEmailAccount.objects.using(db_alias).delete() + dependencies = [ ('users', '0072_auto_20180426_2021'), ] operations = [ migrations.CreateModel( - name='MailAlias', + name='LocalEmailAccount', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('valeur', models.CharField(help_text="username de l'adresse mail", max_length=64, unique=True)), + ('local_part', models.CharField(help_text="Local part of the email address", max_length=128, unique=True)), + ('user', models.ForeignKey(help_text='User of the local email', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), - ), - migrations.RenameField( - model_name='user', - old_name='email', - new_name='external_mail', + options={'permissions': (('view_localemailaccount', 'Can see a local email account object'),), 'verbose_name': 'Local email account', 'verbose_name_plural': 'Local email accounts'}, ), migrations.AddField( model_name='user', - name='internal_address', - field=models.BooleanField(default=False, help_text="Activer ou non l'utilisation de l'adresse mail interne"), + name='local_email_enabled', + field=models.BooleanField(default=False, help_text="Wether or not to enable the local email account."), ), migrations.AddField( model_name='user', - name='redirection', - field=models.BooleanField(default=False, help_text='Activer ou non la redirection du mail interne vers le mail externe'), + name='local_email_redirect', + field=models.BooleanField(default=False, help_text='Whether or not to redirect the local email messages to the main email.'), ), - migrations.AddField( - model_name='mailalias', - name='user', - field=models.ForeignKey(blank=True, help_text='Utilisateur associé', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + migrations.RunPython(create_initial_local_email_account, + delete_all_local_email_accounts), ), ] + diff --git a/users/migrations/0074_auto_20180629_1717.py b/users/migrations/0074_auto_20180629_1717.py deleted file mode 100644 index 4700e34c..00000000 --- a/users/migrations/0074_auto_20180629_1717.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2018-06-29 15:17 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0073_auto_20180629_1614'), - ] - - def transfer_pseudo(apps, schema_editor): - db_alias = schema_editor.connection.alias - users = apps.get_model("users", "User") - mailalias = apps.get_model("users", "MailAlias") - users_list = users.objects.using(db_alias).all() - for user in users_list: - mailalias.objects.using(db_alias).create(valeur=user.pseudo, user=user) - - def untransfer_pseudo(apps, schema_editor): - db_alias = schema_editor.connection.alias - mailalias = apps.get_model("users", "MailAlias") - mailalias.objects.using(db_alias).delete() - - - operations = [ - migrations.AlterField( - model_name='mailalias', - name='user', - field=models.ForeignKey(help_text='Utilisateur associé', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='mailalias', - name='valeur', - field=models.CharField(help_text="Valeur de l'alias mail", max_length=128, unique=True), - ), - migrations.RunPython(transfer_pseudo, untransfer_pseudo), - ] diff --git a/users/models.py b/users/models.py index 4f0b2794..f7e51703 100755 --- a/users/models.py +++ b/users/models.py @@ -53,7 +53,6 @@ from django.db import models from django.db.models import Q from django import forms from django.db.models.signals import post_save, post_delete, m2m_changed -from django.forms import ValidationError from django.dispatch import receiver from django.utils.functional import cached_property from django.template import Context, loader @@ -98,7 +97,7 @@ def linux_user_validator(login): """ Retourne une erreur de validation si le login ne respecte pas les contraintes unix (maj, min, chiffres ou tiret)""" if not linux_user_check(login): - raise ValidationError( + raise forms.ValidationError( ", ce pseudo ('%(label)s') contient des carractères interdits", params={'label': login}, ) @@ -135,7 +134,7 @@ class UserManager(BaseUserManager): self, pseudo, surname, - external_mail, + email, password=None, su=False ): @@ -149,7 +148,7 @@ class UserManager(BaseUserManager): pseudo=pseudo, surname=surname, name=surname, - external_mail=external_mail, + email=self.normalize_email(mail), ) user.set_password(password) @@ -158,19 +157,19 @@ class UserManager(BaseUserManager): user.save(using=self._db) return user - def create_user(self, pseudo, surname, external_mail, password=None): + def create_user(self, pseudo, surname, email, password=None): """ Creates and saves a User with the given pseudo, name, surname, email, and password. """ - return self._create_user(pseudo, surname, external_mail, password, False) + return self._create_user(pseudo, surname, email, password, False) - def create_superuser(self, pseudo, surname, external_mail, password): + def create_superuser(self, pseudo, surname, email, password): """ Creates and saves a superuser with the given pseudo, name, surname, email, and password. """ - return self._create_user(pseudo, surname, external_mail, password, True) + return self._create_user(pseudo, surname, email, password, True) class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, @@ -195,14 +194,14 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator] ) - external_mail = models.EmailField() - redirection = models.BooleanField( + email = models.EmailField() + local_email_redirect = models.BooleanField( default=False, - help_text='Activer ou non la redirection du mail interne vers le mail externe' + help_text="Whether or not to redirect the local email messages to the main email." ) - internal_address = models.BooleanField( + local_email_enabled = models.BooleanField( default=False, - help_text='Activer ou non l\'utilisation de l\'adresse mail interne' + help_text="Wether or not to enable the local email account." ) school = models.ForeignKey( 'School', @@ -236,7 +235,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ) USERNAME_FIELD = 'pseudo' - REQUIRED_FIELDS = ['surname', 'external_mail'] + REQUIRED_FIELDS = ['surname', 'email'] objects = UserManager() @@ -255,9 +254,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ("view_user", "Peut voir un objet user quelquonque"), ) - - - + @cached_property def name(self): """Si il s'agit d'un adhérent, on renvoie le prénom""" @@ -536,7 +533,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, user_ldap.sn = self.pseudo user_ldap.dialupAccess = str(self.has_access()) user_ldap.home_directory = '/home/' + self.pseudo - user_ldap.mail = self.get_mail() + user_ldap.mail = self.email user_ldap.given_name = self.surname.lower() + '_'\ + self.name.lower()[:3] user_ldap.gid = LDAP['user_gid'] @@ -685,20 +682,12 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, self.pwd_ntlm = hashNT(password) return - def get_mail(self): - """ - Return the mail address choosen by the user - """ - if not OptionalUser.get_cached_value('mail_accounts') or not self.internal_address or self.redirection: - return str(self.external_mail) - else: - return str(self.mailalias_set.get(valeur=self.pseudo)) - @cached_property - def get_mail_aliases(self): - if self.internal_address: - return self.mailalias_set.all() - return None + def local_email_accounts(self): + if (OptionalUser.get_cached_value('local_email_accounts_enabled') + and self.local_email_enabled): + return self.localemailaccount_set.all() + return LocalEmailAccount.objects.none() def get_next_domain_name(self): """Look for an available name for a new interface for @@ -819,20 +808,20 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ) @staticmethod - def can_change_redirection(user_request, *_args, **_kwargs): - """ Check if a user can change redirection. + def can_change_local_email_redirect(user_request, *_args, **_kwargs): + """ Check if a user can change local_email_redirect. :param user_request: The user who request :returns: a message and a boolean which is True if the user has the right to change a redirection """ return ( - OptionalUser.get_cached_value('mail_accounts'), + OptionalUser.get_cached_value('local_email_accounts_enabled'), "La gestion des comptes mails doit être activée" ) @staticmethod - def can_change_internal_address(user_request, *_args, **_kwargs): + def can_change_local_email_enabled(user_request, *_args, **_kwargs): """ Check if a user can change internal address . :param user_request: The user who request @@ -840,9 +829,9 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, the right to change internal address """ return ( - OptionalUser.get_cached_value('mail_accounts'), + OptionalUser.get_cached_value('local_email_accounts_enabled'), "La gestion des comptes mails doit être activée" - ) + ) @staticmethod def can_change_force(user_request, *_args, **_kwargs): @@ -938,20 +927,23 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, 'shell': self.can_change_shell, 'force': self.can_change_force, 'selfpasswd': self.check_selfpasswd, - 'redirection': self.can_change_redirection, - 'internal_address' : self.can_change_internal_address, + 'local_email_redirect': self.can_change_local_email_redirect, + 'local_email_enabled' : self.can_change_local_email_enabled, } self.__original_state = self.state def clean(self, *args, **kwargs): """Check if this pseudo is already used by any mailalias. Better than raising an error in post-save and catching it""" - if MailAlias.objects.filter(valeur=self.pseudo).exclude(user=self): - raise ValidationError("Ce pseudo est déjà utilisé") + if (LocalEmailAccount.objects + .filter(local_part=self.pseudo) + .exclude(user=self)): + raise ValidationError("This pseudo is already in use.") def __str__(self): return self.pseudo + class Adherent(User): """ A class representing a member (it's a user with special informations) """ @@ -1074,7 +1066,7 @@ def user_post_save(**kwargs): Synchronise le ldap""" is_created = kwargs['created'] user = kwargs['instance'] - mail_alias, created = MailAlias.objects.get_or_create(valeur=user.pseudo, user=user) + LocalEmailAccount.objects.get_or_create(local_part=user.pseudo, user=user) if is_created: user.notif_inscription() user.state_sync() @@ -1656,87 +1648,122 @@ class LdapServiceUserGroup(ldapdb.models.Model): return self.name -class MailAlias(RevMixin, AclMixin, models.Model): - """ - Define a alias for a user Mail - - Définit un alias pour un Mail d'utilisateur +class LocalEmailAccount(RevMixin, AclMixin, models.Model): + """Defines a local email account for a user """ user = models.ForeignKey( User, on_delete=models.CASCADE, - help_text="Utilisateur associé", + help_text="User of the local email", ) - valeur = models.CharField( + local_part = models.CharField( unique=True, max_length=128, - help_text="Valeur de l'alias mail" + help_text="Local part of the email address" ) + class Meta: + permissions = ( + ("view_localemailaccount", "Can see a local email account object"), + ) + verbose_name = "Local email account" + verbose_name_plural = "Local email accounts" + def __str__(self): - return self.valeur + OptionalUser.get_cached_value('mail_extension') + return self.local_part + OptionalUser.get_cached_value('local_email_domain') + + @cached_property + def complete_email_address(self): + return self.local_part + OptionalUser.get_cached_value('local_email_domain') @staticmethod def can_create(user_request, userid, *_args, **_kwargs): - """Check if an user can create an mailalias object. + """Check if a user can create a `LocalEmailAccount` object. - :param user_request: The user who wants to create a mailalias object. - :return: a message and a boolean which is True if the user can create - an user or if the `options.all_can_create` is set. + Args: + user_request: The user who wants to create the object. + userid: The id of the user to whom the account is to be created + + Returns: + a message and a boolean which is True if the user can create + a local email account. """ - if not user_request.has_perm('users.add_mailalias'): - if int(user_request.id) != int(userid): - return False, 'Vous n\'avez pas le droit d\'ajouter un alias à une autre personne' - elif user_request.mailalias_set.all().count() >= OptionalUser.get_cached_value('max_mail_alias'): - return False, "Vous avez atteint la limite de {} alias".format(OptionalUser.get_cached_value('max_mail_alias')) - else: - return True, None + if user_request.has_perm('users.add_localemailaccount'): + return True, None + if not OptionalUser.get_cached_value('local_email_accounts_enabled'): + return False, "The local email accounts are not enabled." + if int(user_request.id) != int(userid): + return False, "You don't have the right to add a local email account to another user." + elif user_request.local_email_accounts.count() >= OptionalUser.get_cached_value('max_local_email_accounts'): + return False, "You have reached the limit of {} local email account.".format( + OptionalUser.get_cached_value('max_local_email_accounts') + ) return True, None def can_view(self, user_request, *_args, **_kwargs): - """ - Check if the user can view the alias - """ + """Check if a user can view the local email account - if user_request.has_perm('users.view_mailalias') or user.request == self.user: + Args: + user_request: The user who wants to view the object. + + Returns: + a message and a boolean which is True if the user can see + the local email account. + """ + if user_request.has_perm('users.view_localemailaccount'): return True, None - else: - return False, "Vous n'avais pas les droits suffisants et n'êtes pas propriétaire de ces alias" - + if not OptionalUser.get_cached_value('local_email_accounts_enabled'): + return False, "The local email accounts are not enabled." + if user_request == self.user: + return True, None + return False, "You don't have the right to edit someone else's local email account." + def can_delete(self, user_request, *_args, **_kwargs): - """ - Check if the user can delete the alias - """ + """Check if a user can delete the alias - if user_request.has_perm('users.delete_mailalias'): + Args: + user_request: The user who wants to delete the object. + + Returns: + a message and a boolean which is True if the user can delete + the local email account. + """ + if self.local_part == self.user.pseudo: + return False, ("You cannot delete a local email account whose " + "local part is the same as the username.") + if user_request.has_perm('users.delete_localemailaccount'): return True, None - else: - if user_request == self.user: - if self.valeur != self.user.pseudo: - return True, None - else: - return False, "Vous ne pouvez pas supprimer l'alias lié à votre pseudo" - else: - return False, "Vous n'avez pas les droits suffisants et n'êtes pas propriétairs de ces alias" + if not OptionalUser.get_cached_value('local_email_accounts_enabled'): + return False, "The local email accounts are not enabled." + if user_request == self.user: + return True, None + return False, ("You don't have the right to delete someone else's " + "local email account") def can_edit(self, user_request, *_args, **_kwargs): - """ - Check if the user can edit the alias - """ + """Check if a user can edit the alias - if user_request.has_perm('users.change_mailalias'): + Args: + user_request: The user who wants to edit the object. + + Returns: + a message and a boolean which is True if the user can edit + the local email account. + """ + if self.local_part == self.user.pseudo: + return False, ("You cannot edit a local email account whose " + "local part is the same as the username.") + if user_request.has_perm('users.change_localemailaccount'): return True, None - else: - if user_request == self.user: - if self.valeur != self.user.pseudo: - return True, None - else: - return False, "Vous ne pouvez pas modifier l'alias lié à votre pseudo" - else: - return False, "Vous n'avez pas les droits suffisants et n'êtes pas propriétairs de cet alias" + if not OptionalUser.get_cached_value('local_email_accounts_enabled'): + return False, "The local email accounts are not enabled." + if user_request == self.user: + return True, None + return False, ("You don't have the right to edit someone else's " + "local email account") def clean(self, *args, **kwargs): - if "@" in self.valeur: - raise ValidationError("Cet alias ne peut contenir un @") - super(MailAlias, self).clean(*args, **kwargs) + if "@" in self.local_part: + raise ValidationError("The local part cannot contain a @") + super(LocalEmailAccount, self).clean(*args, **kwargs) diff --git a/users/templates/users/aff_mailalias.html b/users/templates/users/aff_localemailaccounts.html similarity index 60% rename from users/templates/users/aff_mailalias.html rename to users/templates/users/aff_localemailaccounts.html index a441b9e9..f129d8ab 100644 --- a/users/templates/users/aff_mailalias.html +++ b/users/templates/users/aff_localemailaccounts.html @@ -21,32 +21,36 @@ 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 acl %} -{% if alias_list.paginator %} +{% load logs_extra %} + +{% if localemailaccount_list.paginator %} {% include "pagination.html" with list=alias_list %} {% endif %} - - - - - - - - {% for alias in alias_list %} - - - - + +
Alias
{{ alias }} - {% can_delete alias %} - {% include 'buttons/suppr.html' with href='users:del-mailalias' id=alias.id %} - {% acl_end %} - {% can_edit alias %} - {% include 'buttons/edit.html' with href='users:edit-mailalias' id=alias.id %} + + + + + + + + + {% for localemailaccount in localemailaccount_list %} + + {% endfor %}
Local email address
{{ localemailaccount.complete_email_address }} + {% can_delete localemailaccount %} + {% include 'buttons/suppr.html' with href='users:del-localemailaccount' id=localemailaccount.id %} {% acl_end %} - {% include 'buttons/history.html' with href='users:history' name='mailalias' id=alias.id %} + {% can_edit localemailaccount %} + {% include 'buttons/edit.html' with href='users:edit-localemailaccount' id=localemailaccount.id %} + {% acl_end %} + {% history_button localemailaccount %}
-{% if alias_list.paginator %} +{% if localemailaccount_list.paginator %} {% include "pagination.html" with list=alias_list %} {% endif %} diff --git a/users/templates/users/index_alias.html b/users/templates/users/index_localemailaccount.html similarity index 85% rename from users/templates/users/index_alias.html rename to users/templates/users/index_localemailaccount.html index 52c68733..8ebdb9ec 100644 --- a/users/templates/users/index_alias.html +++ b/users/templates/users/index_localemailaccount.html @@ -25,13 +25,10 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} -{% block title %}Users{% endblock %} +{% block title %}Local email accounts{% endblock %} {% block content %} -

Alias

- {% include "users/aff_alias.html" with alias_list=alias_list %} -
-
-
+

Local email accounts

+ {% include "users/aff_localemailaccounts.html" with localemailaccount_list=localemailaccount_list %} {% endblock %} diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 2a67934a..450494af 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load acl %} {% load logs_extra %} +{% load design %} {% block title %}Profil{% endblock %} @@ -408,65 +409,56 @@ with this program; if not, write to the Free Software Foundation, Inc.,
-

- - Paramètres mail -

+

+ Email settings +

{% can_edit users %} - - - Modifier les options mail - + + Edit email settings + {% acl_end %} - {% if mail_accounts %} -
- - - - - - - - - - -
Adresse mail externeCompte mail {{ asso_name }}Adresse mail de contact
{{ users.external_mail }}{{ users.internal_address|yesno:"Activé,Désactivé" }}{{ users.get_mail }}
- -
- {% if users.internal_address %} - {% can_create MailAlias users.id %} - - - Ajouter un alias mail - +
+
+ {% if local_email_accounts_enabled %} +
+ + + + + + + + + + + +
Contact email address{{ users.email }}
Enable the local email account{{ users.local_email_enabled | tick }}Enable the local email redirection{{ users.local_email_redirect | tick }}
+
+ {% if users.local_email_enabled %} + {% can_create LocalEmailAccount users.id %} + + Add a local email account + {% acl_end %} - {% if alias_list %} - {% include "users/aff_mailalias.html" with alias_list=alias_list %} + {% if localemailaccount_list %} + {% include "users/aff_localemailaccounts.html" with localemailaccount_list=localemailaccount_list %} {% endif %} - {% endif %} - {% else %} -
- - - - - - - -
Adresse mail
{{ users.external_mail }}
-
- {% endif %} -
+ {% endif %} + {% else %} +
+ + + + + +
Contact email address{{ users.email }}
+
+ {% endif %} +
-
-
-
{% endblock %} diff --git a/users/urls.py b/users/urls.py index 9289d6c2..0dd4e246 100644 --- a/users/urls.py +++ b/users/urls.py @@ -64,10 +64,18 @@ urlpatterns = [ url(r'^del_whitelist/(?P[0-9]+)$', views.del_whitelist, name='del-whitelist'), - url(r'^add_mailalias/(?P[0-9]+)$', views.add_mailalias, name='add-mailalias'), - url(r'^edit_mailalias/(?P[0-9]+)$', views.edit_mailalias, name='edit-mailalias'), - url(r'^del-mailalias/(?P[0-9]+)$', views.del_mailalias, name='del-mailalias'), - url(r'^edit_mail/(?P[0-9]+)$', views.edit_mail, name='edit-mail'), + url(r'^add_localemailaccount/(?P[0-9]+)$', + views.add_localemailaccount, + name='add-localemailaccount'), + url(r'^edit_localemailaccount/(?P[0-9]+)$', + views.edit_localemailaccount, + name='edit-localemailaccount'), + url(r'^del_localemailaccount/(?P[0-9]+)$', + views.del_localemailaccount, + name='del-localemailaccount'), + url(r'^edit_email_settings/(?P[0-9]+)$', + views.edit_email_settings, + name='edit-email-settings'), url(r'^add_school/$', views.add_school, name='add-school'), url(r'^edit_school/(?P[0-9]+)$', views.edit_school, diff --git a/users/views.py b/users/views.py index 3a2b11f7..402cee08 100644 --- a/users/views.py +++ b/users/views.py @@ -81,13 +81,13 @@ from .models import ( Adherent, Club, ListShell, - MailAlias, + LocalEmailAccount, ) from .forms import ( BanForm, WhitelistForm, - MailAliasForm, - MailForm, + LocalEmailAccountForm, + EmailSettingsForm, DelSchoolForm, DelListRightForm, NewListRightForm, @@ -496,90 +496,100 @@ def del_whitelist(request, whitelist, **_kwargs): @login_required -@can_create(MailAlias) +@can_create(LocalEmailAccount) @can_edit(User) -def add_mailalias(request, user, userid): - """ Create a new alias""" - mailalias_instance = MailAlias(user=user) - mailalias = MailAliasForm( +def add_localemailaccount(request, user, userid): + """ Create a new local email account""" + localemailaccount_instance = LocalEmailAccount(user=user) + localemailaccount = LocalEmailAccountForm( request.POST or None, - instance=mailalias_instance + instance=localemailaccount_instance ) - if mailalias.is_valid(): - mailalias.save() - messages.success(request, "Alias created") + if localemailaccount.is_valid(): + localemailaccount.save() + messages.success(request, "Local email account created") return redirect(reverse( 'users:profil', kwargs={'userid': str(userid)} )) return form( - {'userform': mailalias, 'action_name': 'Add an alias mail'}, + {'userform': localemailaccount, + 'showCGU': False, + 'action_name': 'Add a local email account'}, 'users/user.html', request ) + @login_required -@can_edit(MailAlias) -def edit_mailalias(request, mailalias_instance, **_kwargs): - """ Edit a mailalias""" - mailalias = MailAliasForm( +@can_edit(LocalEmailAccount) +def edit_localemailaccount(request, localemailaccount_instance, **_kwargs): + """ Edit a local email account""" + localemailaccount = LocalEmailAccountForm( request.POST or None, - instance=mailalias_instance + instance=localemailaccount_instance ) - if mailalias.is_valid(): - if mailalias.changed_data: - mailalias.save() - messages.success(request, "Alias modified") + if localemailaccount.is_valid(): + if localemailaccount.changed_data: + localemailaccount.save() + messages.success(request, "Local email account modified") return redirect(reverse( 'users:profil', - kwargs={'userid': str(mailalias_instance.user.id)} + kwargs={'userid': str(localemailaccount_instance.user.id)} )) return form( - {'userform': mailalias, 'action_name': 'Edit a mailalias'}, + {'userform': localemailaccount, + 'showCGU': False, + 'action_name': 'Edit a local email account'}, 'users/user.html', request ) + @login_required -@can_delete(MailAlias) -def del_mailalias(request, mailalias, **_kwargs): - """Delete a mail alias""" - if request.method == "POST": - mailalias.delete() - messages.success(request, "Alias deleted") - return redirect(reverse( - 'users:profil', - kwargs={'userid': str(mailalias.user.id)} - )) - return form( - {'objet': mailalias, 'objet_name': 'mailalias'}, - 'users/delete.html', - request - ) +@can_delete(LocalEmailAccount) +def del_localemailaccount(request, localemailaccount, **_kwargs): + """Delete a local email account""" + if request.method == "POST": + localemailaccount.delete() + messages.success(request, "Local email account deleted") + return redirect(reverse( + 'users:profil', + kwargs={'userid': str(localemailaccount.user.id)} + )) + return form( + {'objet': localemailaccount, 'objet_name': 'localemailaccount'}, + 'users/delete.html', + request + ) + @login_required @can_edit(User) -def edit_mail(request, user_instance, **_kwargs): - """ Editer un compte mail""" - mail = MailForm( +def edit_email_settings(request, user_instance, **_kwargs): + """Edit the email settings of a user""" + email_settings = EmailSettingsForm( request.POST or None, instance=user_instance, user=request.user ) - if mail.is_valid(): - if mail.changed_data: - mail.save() - messages.success(request, "Option mail modifiée") + if email_settings.is_valid(): + if email_settings.changed_data: + email_settings.save() + messages.success(request, "Email settings updated") return redirect(reverse( 'users:profil', kwargs={'userid': str(user_instance.id)} )) return form( - {'userform': mail, 'action_name': 'Editer les options mail'}, + {'userform': email_settings, + 'showCGU': False, + 'action_name': 'Edit the email settings'}, 'users/user.html', request ) + @login_required @can_create(School) def add_school(request): @@ -1002,10 +1012,11 @@ def profil(request, users, **_kwargs): 'white_list': whitelists, 'user_solde': user_solde, 'solde_activated': Paiement.objects.filter(is_balance=True).exists(), - 'allow_online_payment': allow_online_payment, 'asso_name': AssoOption.objects.first().name, - 'alias_list': users.mailalias_set.all(), - 'mail_accounts': OptionalUser.objects.first().mail_accounts + 'localemailaccount_list': users.local_email_accounts, + 'local_email_accounts_enabled': ( + OptionalUser.objects.first().local_email_accounts_enabled + ) } ) From bc0abb2c0a604a38184f3b5ad0e2ce012f24dd23 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 1 Aug 2018 13:06:25 +0200 Subject: [PATCH 24/24] =?UTF-8?q?Renomme=20le=20mod=C3=A8le=20des=20addres?= =?UTF-8?q?ses=20mails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/serializers.py | 10 ++-- api/urls.py | 2 +- api/views.py | 12 ++--- .../0046_optionaluser_mail_extension.py | 4 +- preferences/models.py | 4 +- .../preferences/display_preferences.html | 4 +- users/admin.py | 6 +-- users/forms.py | 10 ++-- users/migrations/0073_auto_20180629_1614.py | 21 ++++---- users/models.py | 30 +++++------ ...ailaccounts.html => aff_emailaddress.html} | 24 ++++----- ...ilaccount.html => index_emailaddress.html} | 2 +- users/templates/users/profil.html | 20 ++++---- users/urls.py | 18 +++---- users/views.py | 50 +++++++++---------- 15 files changed, 108 insertions(+), 109 deletions(-) rename users/templates/users/{aff_localemailaccounts.html => aff_emailaddress.html} (71%) rename users/templates/users/{index_localemailaccount.html => index_emailaddress.html} (91%) diff --git a/api/serializers.py b/api/serializers.py index d07cb9fe..398f2b19 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -596,12 +596,12 @@ class WhitelistSerializer(NamespacedHMSerializer): fields = ('user', 'raison', 'date_start', 'date_end', 'active', 'api_url') -class LocalEmailAccountSerializer(NamespacedHMSerializer): - """Serialize `users.models.LocalEmailAccount` objects. +class EMailAddressSerializer(NamespacedHMSerializer): + """Serialize `users.models.EMailAddress` objects. """ class Meta: - model = users.LocalEmailAccount + model = users.EMailAddress fields = ('user', 'local_part', 'complete_email_address', 'api_url') @@ -627,7 +627,7 @@ class ServiceRegenSerializer(NamespacedHMSerializer): class LocalEmailUsersSerializer(NamespacedHMSerializer): - local_email_accounts = LocalEmailAccountSerializer( + email_address = EMailAddressSerializer( read_only=True, many=True ) @@ -635,7 +635,7 @@ class LocalEmailUsersSerializer(NamespacedHMSerializer): class Meta: model = users.User fields = ('local_email_enabled', 'local_email_redirect', - 'local_email_accounts') + 'email_address') # DHCP diff --git a/api/urls.py b/api/urls.py index 88211c4b..7ee36073 100644 --- a/api/urls.py +++ b/api/urls.py @@ -93,7 +93,7 @@ router.register_viewset(r'users/listright', views.ListRightViewSet) router.register_viewset(r'users/shell', views.ShellViewSet, base_name='shell') router.register_viewset(r'users/ban', views.BanViewSet) router.register_viewset(r'users/whitelist', views.WhitelistViewSet) -router.register_viewset(r'users/localemailaccount', views.LocalEmailAccountViewSet) +router.register_viewset(r'users/emailaddress', views.EMailAddressViewSet) # SERVICE REGEN router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen') # DHCP diff --git a/api/views.py b/api/views.py index 04c7a461..ef083edf 100644 --- a/api/views.py +++ b/api/views.py @@ -469,19 +469,19 @@ class WhitelistViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.WhitelistSerializer -class LocalEmailAccountViewSet(viewsets.ReadOnlyModelViewSet): - """Exposes list and details of `users.models.LocalEmailAccount` objects. +class EMailAddressViewSet(viewsets.ReadOnlyModelViewSet): + """Exposes list and details of `users.models.EMailAddress` objects. """ - serializer_class = serializers.LocalEmailAccountSerializer - queryset = users.LocalEmailAccount.objects.none() + serializer_class = serializers.EMailAddressSerializer + queryset = users.EMailAddress.objects.none() def get_queryset(self): if preferences.OptionalUser.get_cached_value( 'local_email_accounts_enabled'): - return (users.LocalEmailAccount.objects + return (users.EMailAddress.objects .filter(user__local_email_enabled=True)) else: - return users.LocalEmailAccount.objects.none() + return users.EMailAddress.objects.none() # SERVICE REGEN diff --git a/preferences/migrations/0046_optionaluser_mail_extension.py b/preferences/migrations/0046_optionaluser_mail_extension.py index 5fc6c5e0..9de1608a 100644 --- a/preferences/migrations/0046_optionaluser_mail_extension.py +++ b/preferences/migrations/0046_optionaluser_mail_extension.py @@ -24,7 +24,7 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name='optionaluser', - name='max_local_email_accounts', - field=models.IntegerField(default=15, help_text='Maximum number of local email accounts for a standard user'), + name='max_email_address', + field=models.IntegerField(default=15, help_text='Maximum number of local email address for a standard user'), ), ] diff --git a/preferences/models.py b/preferences/models.py index 5f13bc4b..c2d6aa74 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -93,9 +93,9 @@ class OptionalUser(AclMixin, PreferencesModel): default = "@example.org", help_text="Domain to use for local email accounts", ) - max_local_email_accounts = models.IntegerField( + max_email_address = models.IntegerField( default = 15, - help_text = "Maximum number of local email accounts for a standard user" + help_text = "Maximum number of local email address for a standard user" ) class Meta: diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html index c6f11734..a3f2dbc3 100644 --- a/preferences/templates/preferences/display_preferences.html +++ b/preferences/templates/preferences/display_preferences.html @@ -66,8 +66,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{{ useroptions.local_email_domain }}
Nombre de comptes maximum{{ useroptions.max_local_email_accounts }}Nombre d'alias mail max{{ useroptions.max_email_address }}
diff --git a/users/admin.py b/users/admin.py index bc1670a7..e7dd3240 100644 --- a/users/admin.py +++ b/users/admin.py @@ -34,7 +34,7 @@ from reversion.admin import VersionAdmin from .models import ( User, - LocalEmailAccount, + EMailAddress, ServiceUser, School, ListRight, @@ -109,7 +109,7 @@ class BanAdmin(VersionAdmin): pass -class LocalEmailAccountAdmin(VersionAdmin): +class EMailAddressAdmin(VersionAdmin): """Gestion des alias mail""" pass @@ -219,7 +219,7 @@ admin.site.register(School, SchoolAdmin) admin.site.register(ListRight, ListRightAdmin) admin.site.register(ListShell, ListShellAdmin) admin.site.register(Ban, BanAdmin) -admin.site.register(LocalEmailAccount, LocalEmailAccountAdmin) +admin.site.register(EMailAddress, EMailAddressAdmin) admin.site.register(Whitelist, WhitelistAdmin) admin.site.register(Request, RequestAdmin) # Now register the new UserAdmin... diff --git a/users/forms.py b/users/forms.py index 7b17a5ec..cbffd961 100644 --- a/users/forms.py +++ b/users/forms.py @@ -53,7 +53,7 @@ from .models import ( School, ListRight, Whitelist, - LocalEmailAccount, + EMailAddress, ListShell, Ban, Adherent, @@ -591,16 +591,16 @@ class WhitelistForm(FormRevMixin, ModelForm): widgets = {'date_end':DateTimePicker} -class LocalEmailAccountForm(FormRevMixin, ModelForm): - """Create and edit a local email account""" +class EMailAddressForm(FormRevMixin, ModelForm): + """Create and edit a local email address""" def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) - super(LocalEmailAccountForm, self).__init__(*args, prefix=prefix, **kwargs) + super(EMailAddressForm, self).__init__(*args, prefix=prefix, **kwargs) self.fields['local_part'].label = "Local part of the email" self.fields['local_part'].help_text = "Can't contain @" class Meta: - model = LocalEmailAccount + model = EMailAddress exclude = ['user'] diff --git a/users/migrations/0073_auto_20180629_1614.py b/users/migrations/0073_auto_20180629_1614.py index 6b976f88..72ebffe6 100644 --- a/users/migrations/0073_auto_20180629_1614.py +++ b/users/migrations/0073_auto_20180629_1614.py @@ -10,21 +10,21 @@ import re2o.mixins class Migration(migrations.Migration): - def create_initial_local_email_account(apps, schema_editor): + def create_initial_email_address(apps, schema_editor): db_alias = schema_editor.connection.alias User = apps.get_model("users", "User") - LocalEmailAccount = apps.get_model("users", "LocalEmailAccount") + EMailAddress = apps.get_model("users", "EMailAddress") users = User.objects.using(db_alias).all() for user in users: - LocalEmailAccount.objects.using(db_alias).create( + EMailAddress.objects.using(db_alias).create( local_part=user.pseudo, user=user ) - def delete_all_local_email_accounts(apps, schema_editor): + def delete_all_email_address(apps, schema_editor): db_alias = schema_editor.connection.alias - LocalEmailAccount = apps.get_model("users", "LocalEmailAccount") - LocalEmailAccount.objects.using(db_alias).delete() + EMailAddress = apps.get_model("users", "EMailAddress") + EMailAddress.objects.using(db_alias).delete() dependencies = [ ('users', '0072_auto_20180426_2021'), @@ -32,14 +32,14 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='LocalEmailAccount', + name='EMailAddress', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('local_part', models.CharField(help_text="Local part of the email address", max_length=128, unique=True)), ('user', models.ForeignKey(help_text='User of the local email', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), - options={'permissions': (('view_localemailaccount', 'Can see a local email account object'),), 'verbose_name': 'Local email account', 'verbose_name_plural': 'Local email accounts'}, + options={'permissions': (('view_emailaddress', 'Can see a local email account object'),), 'verbose_name': 'Local email account', 'verbose_name_plural': 'Local email accounts'}, ), migrations.AddField( model_name='user', @@ -51,8 +51,7 @@ class Migration(migrations.Migration): name='local_email_redirect', field=models.BooleanField(default=False, help_text='Whether or not to redirect the local email messages to the main email.'), ), - migrations.RunPython(create_initial_local_email_account, - delete_all_local_email_accounts), - ), + migrations.RunPython(create_initial_email_address, + delete_all_email_address), ] diff --git a/users/models.py b/users/models.py index f7e51703..bdc37142 100755 --- a/users/models.py +++ b/users/models.py @@ -683,11 +683,11 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, return @cached_property - def local_email_accounts(self): + def email_address(self): if (OptionalUser.get_cached_value('local_email_accounts_enabled') and self.local_email_enabled): - return self.localemailaccount_set.all() - return LocalEmailAccount.objects.none() + return self.emailaddress_set.all() + return EMailAddress.objects.none() def get_next_domain_name(self): """Look for an available name for a new interface for @@ -935,7 +935,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, def clean(self, *args, **kwargs): """Check if this pseudo is already used by any mailalias. Better than raising an error in post-save and catching it""" - if (LocalEmailAccount.objects + if (EMailAddress.objects .filter(local_part=self.pseudo) .exclude(user=self)): raise ValidationError("This pseudo is already in use.") @@ -1066,7 +1066,7 @@ def user_post_save(**kwargs): Synchronise le ldap""" is_created = kwargs['created'] user = kwargs['instance'] - LocalEmailAccount.objects.get_or_create(local_part=user.pseudo, user=user) + EMailAddress.objects.get_or_create(local_part=user.pseudo, user=user) if is_created: user.notif_inscription() user.state_sync() @@ -1648,7 +1648,7 @@ class LdapServiceUserGroup(ldapdb.models.Model): return self.name -class LocalEmailAccount(RevMixin, AclMixin, models.Model): +class EMailAddress(RevMixin, AclMixin, models.Model): """Defines a local email account for a user """ user = models.ForeignKey( @@ -1664,7 +1664,7 @@ class LocalEmailAccount(RevMixin, AclMixin, models.Model): class Meta: permissions = ( - ("view_localemailaccount", "Can see a local email account object"), + ("view_emailaddress", "Can see a local email account object"), ) verbose_name = "Local email account" verbose_name_plural = "Local email accounts" @@ -1678,7 +1678,7 @@ class LocalEmailAccount(RevMixin, AclMixin, models.Model): @staticmethod def can_create(user_request, userid, *_args, **_kwargs): - """Check if a user can create a `LocalEmailAccount` object. + """Check if a user can create a `EMailAddress` object. Args: user_request: The user who wants to create the object. @@ -1688,15 +1688,15 @@ class LocalEmailAccount(RevMixin, AclMixin, models.Model): a message and a boolean which is True if the user can create a local email account. """ - if user_request.has_perm('users.add_localemailaccount'): + if user_request.has_perm('users.add_emailaddress'): return True, None if not OptionalUser.get_cached_value('local_email_accounts_enabled'): return False, "The local email accounts are not enabled." if int(user_request.id) != int(userid): return False, "You don't have the right to add a local email account to another user." - elif user_request.local_email_accounts.count() >= OptionalUser.get_cached_value('max_local_email_accounts'): + elif user_request.email_address.count() >= OptionalUser.get_cached_value('max_email_address'): return False, "You have reached the limit of {} local email account.".format( - OptionalUser.get_cached_value('max_local_email_accounts') + OptionalUser.get_cached_value('max_email_address') ) return True, None @@ -1710,7 +1710,7 @@ class LocalEmailAccount(RevMixin, AclMixin, models.Model): a message and a boolean which is True if the user can see the local email account. """ - if user_request.has_perm('users.view_localemailaccount'): + if user_request.has_perm('users.view_emailaddress'): return True, None if not OptionalUser.get_cached_value('local_email_accounts_enabled'): return False, "The local email accounts are not enabled." @@ -1731,7 +1731,7 @@ class LocalEmailAccount(RevMixin, AclMixin, models.Model): if self.local_part == self.user.pseudo: return False, ("You cannot delete a local email account whose " "local part is the same as the username.") - if user_request.has_perm('users.delete_localemailaccount'): + if user_request.has_perm('users.delete_emailaddress'): return True, None if not OptionalUser.get_cached_value('local_email_accounts_enabled'): return False, "The local email accounts are not enabled." @@ -1753,7 +1753,7 @@ class LocalEmailAccount(RevMixin, AclMixin, models.Model): if self.local_part == self.user.pseudo: return False, ("You cannot edit a local email account whose " "local part is the same as the username.") - if user_request.has_perm('users.change_localemailaccount'): + if user_request.has_perm('users.change_emailaddress'): return True, None if not OptionalUser.get_cached_value('local_email_accounts_enabled'): return False, "The local email accounts are not enabled." @@ -1765,5 +1765,5 @@ class LocalEmailAccount(RevMixin, AclMixin, models.Model): def clean(self, *args, **kwargs): if "@" in self.local_part: raise ValidationError("The local part cannot contain a @") - super(LocalEmailAccount, self).clean(*args, **kwargs) + super(EMailAddress, self).clean(*args, **kwargs) diff --git a/users/templates/users/aff_localemailaccounts.html b/users/templates/users/aff_emailaddress.html similarity index 71% rename from users/templates/users/aff_localemailaccounts.html rename to users/templates/users/aff_emailaddress.html index f129d8ab..14156ac9 100644 --- a/users/templates/users/aff_localemailaccounts.html +++ b/users/templates/users/aff_emailaddress.html @@ -25,32 +25,32 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load acl %} {% load logs_extra %} -{% if localemailaccount_list.paginator %} -{% include "pagination.html" with list=alias_list %} +{% if emailaddress_list.paginator %} +{% include "pagination.html" with list=emailaddress_list %} {% endif %} - + - {% for localemailaccount in localemailaccount_list %} - + {% for emailaddress in emailaddress_list %} + {% endfor %}
Local email addressEmail address
{{ localemailaccount.complete_email_address }}{{ emailaddress.complete_email_address }} - {% can_delete localemailaccount %} - {% include 'buttons/suppr.html' with href='users:del-localemailaccount' id=localemailaccount.id %} + {% can_delete emailaddress %} + {% include 'buttons/suppr.html' with href='users:del-emailaddress' id=emailaddress.id %} {% acl_end %} - {% can_edit localemailaccount %} - {% include 'buttons/edit.html' with href='users:edit-localemailaccount' id=localemailaccount.id %} + {% can_edit emailaddress %} + {% include 'buttons/edit.html' with href='users:edit-emailaddress' id=emailaddress.id %} {% acl_end %} - {% history_button localemailaccount %} + {% history_button emailaddress %}
-{% if localemailaccount_list.paginator %} -{% include "pagination.html" with list=alias_list %} +{% if emailaddress_list.paginator %} +{% include "pagination.html" with list=emailaddress_list %} {% endif %} diff --git a/users/templates/users/index_localemailaccount.html b/users/templates/users/index_emailaddress.html similarity index 91% rename from users/templates/users/index_localemailaccount.html rename to users/templates/users/index_emailaddress.html index 8ebdb9ec..6976e168 100644 --- a/users/templates/users/index_localemailaccount.html +++ b/users/templates/users/index_emailaddress.html @@ -29,6 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc., {% block content %}

Local email accounts

- {% include "users/aff_localemailaccounts.html" with localemailaccount_list=localemailaccount_list %} + {% include "users/aff_emailaddress.html" with emailaddress_list=emailaddress_list %} {% endblock %} diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 450494af..1e1926cc 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -433,18 +433,18 @@ with this program; if not, write to the Free Software Foundation, Inc., Enable the local email account {{ users.local_email_enabled | tick }} Enable the local email redirection - {{ users.local_email_redirect | tick }} - - - - {% if users.local_email_enabled %} - {% can_create LocalEmailAccount users.id %} - - Add a local email account + {{ users.local_email_redirect | tick }} + + + + {% if users.local_email_enabled %} + {% can_create EMailAddress users.id %} + + Add an email address {% acl_end %} - {% if localemailaccount_list %} - {% include "users/aff_localemailaccounts.html" with localemailaccount_list=localemailaccount_list %} + {% if emailaddress_list %} + {% include "users/aff_emailaddress.html" with emailaddress_list=emailaddress_list %} {% endif %} {% endif %} {% else %} diff --git a/users/urls.py b/users/urls.py index 0dd4e246..f5114600 100644 --- a/users/urls.py +++ b/users/urls.py @@ -64,15 +64,15 @@ urlpatterns = [ url(r'^del_whitelist/(?P[0-9]+)$', views.del_whitelist, name='del-whitelist'), - url(r'^add_localemailaccount/(?P[0-9]+)$', - views.add_localemailaccount, - name='add-localemailaccount'), - url(r'^edit_localemailaccount/(?P[0-9]+)$', - views.edit_localemailaccount, - name='edit-localemailaccount'), - url(r'^del_localemailaccount/(?P[0-9]+)$', - views.del_localemailaccount, - name='del-localemailaccount'), + url(r'^add_emailaddress/(?P[0-9]+)$', + views.add_emailaddress, + name='add-emailaddress'), + url(r'^edit_emailaddress/(?P[0-9]+)$', + views.edit_emailaddress, + name='edit-emailaddress'), + url(r'^del_emailaddress/(?P[0-9]+)$', + views.del_emailaddress, + name='del-emailaddress'), url(r'^edit_email_settings/(?P[0-9]+)$', views.edit_email_settings, name='edit-email-settings'), diff --git a/users/views.py b/users/views.py index 402cee08..a4f4ea83 100644 --- a/users/views.py +++ b/users/views.py @@ -81,12 +81,12 @@ from .models import ( Adherent, Club, ListShell, - LocalEmailAccount, + EMailAddress, ) from .forms import ( BanForm, WhitelistForm, - LocalEmailAccountForm, + EMailAddressForm, EmailSettingsForm, DelSchoolForm, DelListRightForm, @@ -496,24 +496,24 @@ def del_whitelist(request, whitelist, **_kwargs): @login_required -@can_create(LocalEmailAccount) +@can_create(EMailAddress) @can_edit(User) -def add_localemailaccount(request, user, userid): +def add_emailaddress(request, user, userid): """ Create a new local email account""" - localemailaccount_instance = LocalEmailAccount(user=user) - localemailaccount = LocalEmailAccountForm( + emailaddress_instance = EMailAddress(user=user) + emailaddress = EMailAddressForm( request.POST or None, - instance=localemailaccount_instance + instance=emailaddress_instance ) - if localemailaccount.is_valid(): - localemailaccount.save() + if emailaddress.is_valid(): + emailaddress.save() messages.success(request, "Local email account created") return redirect(reverse( 'users:profil', kwargs={'userid': str(userid)} )) return form( - {'userform': localemailaccount, + {'userform': emailaddress, 'showCGU': False, 'action_name': 'Add a local email account'}, 'users/user.html', @@ -522,23 +522,23 @@ def add_localemailaccount(request, user, userid): @login_required -@can_edit(LocalEmailAccount) -def edit_localemailaccount(request, localemailaccount_instance, **_kwargs): +@can_edit(EMailAddress) +def edit_emailaddress(request, emailaddress_instance, **_kwargs): """ Edit a local email account""" - localemailaccount = LocalEmailAccountForm( + emailaddress = EMailAddressForm( request.POST or None, - instance=localemailaccount_instance + instance=emailaddress_instance ) - if localemailaccount.is_valid(): - if localemailaccount.changed_data: - localemailaccount.save() + if emailaddress.is_valid(): + if emailaddress.changed_data: + emailaddress.save() messages.success(request, "Local email account modified") return redirect(reverse( 'users:profil', - kwargs={'userid': str(localemailaccount_instance.user.id)} + kwargs={'userid': str(emailaddress_instance.user.id)} )) return form( - {'userform': localemailaccount, + {'userform': emailaddress, 'showCGU': False, 'action_name': 'Edit a local email account'}, 'users/user.html', @@ -547,18 +547,18 @@ def edit_localemailaccount(request, localemailaccount_instance, **_kwargs): @login_required -@can_delete(LocalEmailAccount) -def del_localemailaccount(request, localemailaccount, **_kwargs): +@can_delete(EMailAddress) +def del_emailaddress(request, emailaddress, **_kwargs): """Delete a local email account""" if request.method == "POST": - localemailaccount.delete() + emailaddress.delete() messages.success(request, "Local email account deleted") return redirect(reverse( 'users:profil', - kwargs={'userid': str(localemailaccount.user.id)} + kwargs={'userid': str(emailaddress.user.id)} )) return form( - {'objet': localemailaccount, 'objet_name': 'localemailaccount'}, + {'objet': emailaddress, 'objet_name': 'emailaddress'}, 'users/delete.html', request ) @@ -1013,7 +1013,7 @@ def profil(request, users, **_kwargs): 'user_solde': user_solde, 'solde_activated': Paiement.objects.filter(is_balance=True).exists(), 'asso_name': AssoOption.objects.first().name, - 'localemailaccount_list': users.local_email_accounts, + 'emailaddress_list': users.email_address, 'local_email_accounts_enabled': ( OptionalUser.objects.first().local_email_accounts_enabled )