Commit 43fb83ec authored by Maël Kervella's avatar Maël Kervella

Cleanup for local email accounts

parent bd19b279
......@@ -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
......
......@@ -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
......
......@@ -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.
......
# -*- 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'),
),
]
# -*- 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"),
),
]
# -*- 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 = [
]
......@@ -8,13 +8,23 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('preferences', '0034_auto_20180416_1120'),
('preferences', '0045_remove_unused_payment_fields'),
]
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),
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'),
),
]
......@@ -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):
......
This diff is collapsed.
......@@ -29,6 +29,7 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(
r'^edit_options/(?P<section>OptionalUser)$',
......
......@@ -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('.')
......
......@@ -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...
......
......@@ -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']
......@@ -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),
),
]
# -*- 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),
]
This diff is collapsed.
......@@ -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 %}
<table class="table table-striped">
<thead>
<tr>
<th>Alias</th>
<th></th>
</tr>
</thead>
{% for alias in alias_list %}
<td>{{ alias }}</td>
<td class="text-right">
{% 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 %}
<table class="table table-striped">
<thead>
<tr>
<th>Local email address</th>
<th></th>
</tr>
</thead>
{% for localemailaccount in localemailaccount_list %}
<td>{{ localemailaccount.complete_email_address }}</td>
<td class="text-right">
{% can_delete localemailaccount %}
{% include 'buttons/suppr.html' with href='users:del-localemailaccount' id=localemailaccount.id %}
{% acl_end %}
{% can_edit localemailaccount %}
{% include 'buttons/edit.html' with href='users:edit-localemailaccount' id=localemailaccount.id %}
{% acl_end %}
{% include 'buttons/history.html' with href='users:history' name='mailalias' id=alias.id %}
{% history_button localemailaccount %}
</td>
</tr>
{% endfor %}
</table>
{% if alias_list.paginator %}
{% if localemailaccount_list.paginator %}
{% include "pagination.html" with list=alias_list %}
{% endif %}
......@@ -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 %}
<h2>Alias</h2>
{% include "users/aff_alias.html" with alias_list=alias_list %}
<br />
<br />
<br />
<h2>Local email accounts</h2>
{% include "users/aff_localemailaccounts.html" with localemailaccount_list=localemailaccount_list %}
{% endblock %}
......@@ -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.,
</div>
<div class="panel panel-default">
<div class="panel-heading clearfix" data-parent="#accordion" data-toggle="collapse" data-target="#collapse7">
<h3 class="panel-title pull-left">
<i class="fa fa-envelope"></i>
Paramètres mail
</h3>
<h3 class="panel-title pull-left">
<i class="fa fa-envelope"></i> Email settings
</h3>
</div>
<div id="collapse7" class="panel-collapse collapse">
<div class="panel-body">
{% can_edit users %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-mail' users.id %}">
<i class="fa fa-plus-square"></i>
Modifier les options mail
</a>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-email-settings' users.id %}">
<i class="fa fa-pencil-alt"></i> Edit email settings
</a>
{% acl_end %}
{% if mail_accounts %}
<div class="table-responsive">
<table class="table">
<tr>
<th>Adresse mail externe</th>
<th>Compte mail {{ asso_name }}</th>
<th>Adresse mail de contact</th>
</tr>
<tr>
<td>{{ users.external_mail }}</td>
<td>{{ users.internal_address|yesno:"Activé,Désactivé" }}</td>
<td>{{ users.get_mail }}</td>
</table>
<div class="alert alert-info" role="alert">
Vous pouvez bénéficier d'une adresse mail {{ asso_name }}.
Vous pouvez également la rediriger vers une adresse externe en modifiant les options mail.
</div>
</div>
{% if users.internal_address %}
{% can_create MailAlias users.id %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-mailalias' users.id %}">
<i class="fa fa-plus-square"></i>
Ajouter un alias mail
</a>
</div>
<div class="panel-body">
{% if local_email_accounts_enabled %}
<div class="table-responsive">
<table class="table">
<tr>
<th colspan="2">Contact email address</th>
<td colspan="2">{{ users.email }}</td>
</tr>
<tr>
<th>Enable the local email account</th>
<td>{{ users.local_email_enabled | tick }}</td>
<th>Enable the local email redirection</th>
<td>{{ users.local_email_redirect | tick }}</td>
</tr>
</table>
</div>
{% if users.local_email_enabled %}
{% can_create LocalEmailAccount users.id %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-localemailaccount' users.id %}">
<i class="fa fa-plus-square"></i> Add a local email account