Commit 90674d49 authored by chirac's avatar chirac

Merge branch 'mail_account' into 'master'

Mail account

See merge request federez/re2o!199
parents 3837084e bc0abb2c
...@@ -495,7 +495,8 @@ class UserSerializer(NamespacedHMSerializer): ...@@ -495,7 +495,8 @@ class UserSerializer(NamespacedHMSerializer):
class Meta: class Meta:
model = users.User model = users.User
fields = ('name', 'pseudo', 'email', 'school', 'shell', 'comment', fields = ('surname', 'pseudo', 'email', 'local_email_redirect',
'local_email_enabled', 'school', 'shell', 'comment',
'state', 'registered', 'telephone', 'solde', 'access', 'state', 'registered', 'telephone', 'solde', 'access',
'end_access', 'uid', 'class_name', 'api_url') 'end_access', 'uid', 'class_name', 'api_url')
extra_kwargs = { extra_kwargs = {
...@@ -512,7 +513,8 @@ class ClubSerializer(NamespacedHMSerializer): ...@@ -512,7 +513,8 @@ class ClubSerializer(NamespacedHMSerializer):
class Meta: class Meta:
model = users.Club model = users.Club
fields = ('name', 'pseudo', 'email', 'school', 'shell', 'comment', fields = ('name', 'pseudo', 'email', 'local_email_redirect',
'local_email_enabled', 'school', 'shell', 'comment',
'state', 'registered', 'telephone', 'solde', 'room', 'state', 'registered', 'telephone', 'solde', 'room',
'access', 'end_access', 'administrators', 'members', 'access', 'end_access', 'administrators', 'members',
'mailing', 'uid', 'api_url') 'mailing', 'uid', 'api_url')
...@@ -529,9 +531,10 @@ class AdherentSerializer(NamespacedHMSerializer): ...@@ -529,9 +531,10 @@ class AdherentSerializer(NamespacedHMSerializer):
class Meta: class Meta:
model = users.Adherent model = users.Adherent
fields = ('name', 'surname', 'pseudo', 'email', 'school', 'shell', fields = ('name', 'surname', 'pseudo', 'email', 'local_email_redirect',
'comment', 'state', 'registered', 'telephone', 'room', 'local_email_enabled', 'school', 'shell', 'comment',
'solde', 'access', 'end_access', 'uid', 'api_url') 'state', 'registered', 'telephone', 'room', 'solde',
'access', 'end_access', 'uid', 'api_url')
extra_kwargs = { extra_kwargs = {
'shell': {'view_name': 'shell-detail'} 'shell': {'view_name': 'shell-detail'}
} }
...@@ -593,6 +596,15 @@ class WhitelistSerializer(NamespacedHMSerializer): ...@@ -593,6 +596,15 @@ class WhitelistSerializer(NamespacedHMSerializer):
fields = ('user', 'raison', 'date_start', 'date_end', 'active', 'api_url') fields = ('user', 'raison', 'date_start', 'date_end', 'active', 'api_url')
class EMailAddressSerializer(NamespacedHMSerializer):
"""Serialize `users.models.EMailAddress` objects.
"""
class Meta:
model = users.EMailAddress
fields = ('user', 'local_part', 'complete_email_address', 'api_url')
# SERVICE REGEN # SERVICE REGEN
...@@ -611,6 +623,21 @@ class ServiceRegenSerializer(NamespacedHMSerializer): ...@@ -611,6 +623,21 @@ class ServiceRegenSerializer(NamespacedHMSerializer):
} }
# LOCAL EMAILS
class LocalEmailUsersSerializer(NamespacedHMSerializer):
email_address = EMailAddressSerializer(
read_only=True,
many=True
)
class Meta:
model = users.User
fields = ('local_email_enabled', 'local_email_redirect',
'email_address')
# DHCP # DHCP
......
...@@ -93,10 +93,13 @@ router.register_viewset(r'users/listright', views.ListRightViewSet) ...@@ -93,10 +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/shell', views.ShellViewSet, base_name='shell')
router.register_viewset(r'users/ban', views.BanViewSet) router.register_viewset(r'users/ban', views.BanViewSet)
router.register_viewset(r'users/whitelist', views.WhitelistViewSet) router.register_viewset(r'users/whitelist', views.WhitelistViewSet)
router.register_viewset(r'users/emailaddress', views.EMailAddressViewSet)
# SERVICE REGEN # SERVICE REGEN
router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen') router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen')
# DHCP # DHCP
router.register_view(r'dhcp/hostmacip', views.HostMacIpView), router.register_view(r'dhcp/hostmacip', views.HostMacIpView),
# LOCAL EMAILS
router.register_view(r'localemail/users', views.LocalEmailUsersView),
# DNS # DNS
router.register_view(r'dns/zones', views.DNSZonesView), router.register_view(r'dns/zones', views.DNSZonesView),
# MAILING # MAILING
......
...@@ -469,6 +469,21 @@ class WhitelistViewSet(viewsets.ReadOnlyModelViewSet): ...@@ -469,6 +469,21 @@ class WhitelistViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = serializers.WhitelistSerializer serializer_class = serializers.WhitelistSerializer
class EMailAddressViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.EMailAddress` objects.
"""
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.EMailAddress.objects
.filter(user__local_email_enabled=True))
else:
return users.EMailAddress.objects.none()
# SERVICE REGEN # SERVICE REGEN
...@@ -489,8 +504,26 @@ class ServiceRegenViewSet(viewsets.ModelViewSet): ...@@ -489,8 +504,26 @@ class ServiceRegenViewSet(viewsets.ModelViewSet):
return queryset return queryset
# LOCAL EMAILS
class LocalEmailUsersView(generics.ListAPIView):
"""Exposes all the aliases of the users that activated the internal address
"""
serializer_class = serializers.LocalEmailUsersSerializer
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 # DHCP
class HostMacIpView(generics.ListAPIView): class HostMacIpView(generics.ListAPIView):
"""Exposes the associations between hostname, mac address and IPv4 in """Exposes the associations between hostname, mac address and IPv4 in
order to build the DHCP lease files. order to build the DHCP lease files.
...@@ -501,6 +534,7 @@ class HostMacIpView(generics.ListAPIView): ...@@ -501,6 +534,7 @@ class HostMacIpView(generics.ListAPIView):
# DNS # DNS
class DNSZonesView(generics.ListAPIView): class DNSZonesView(generics.ListAPIView):
"""Exposes the detailed information about each extension (hostnames, """Exposes the detailed information about each extension (hostnames,
IPs, DNS records, etc.) in order to build the DNS zone files. IPs, DNS records, etc.) in order to build the DNS zone files.
......
# -*- 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_email_address',
field=models.IntegerField(default=15, help_text='Maximum number of local email address for a standard user'),
),
]
...@@ -30,6 +30,7 @@ from django.db import models ...@@ -30,6 +30,7 @@ from django.db import models
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from django.core.cache import cache from django.core.cache import cache
from django.forms import ValidationError
import machines.models import machines.models
from re2o.mixins import AclMixin from re2o.mixins import AclMixin
...@@ -83,12 +84,32 @@ class OptionalUser(AclMixin, PreferencesModel): ...@@ -83,12 +84,32 @@ class OptionalUser(AclMixin, PreferencesModel):
blank=True, blank=True,
null=True null=True
) )
local_email_accounts_enabled = models.BooleanField(
default=False,
help_text="Enable local email accounts for users"
)
local_email_domain = models.CharField(
max_length = 32,
default = "@example.org",
help_text="Domain to use for local email accounts",
)
max_email_address = models.IntegerField(
default = 15,
help_text = "Maximum number of local email address for a standard user"
)
class Meta: class Meta:
permissions = ( permissions = (
("view_optionaluser", "Peut voir les options de l'user"), ("view_optionaluser", "Peut voir les options de l'user"),
) )
def clean(self):
"""Clean model:
Check the mail_extension
"""
if self.local_email_domain[0] != "@":
raise ValidationError("Mail domain must begin with @")
@receiver(post_save, sender=OptionalUser) @receiver(post_save, sender=OptionalUser)
def optionaluser_post_save(**kwargs): def optionaluser_post_save(**kwargs):
......
This diff is collapsed.
...@@ -34,6 +34,7 @@ from reversion.admin import VersionAdmin ...@@ -34,6 +34,7 @@ from reversion.admin import VersionAdmin
from .models import ( from .models import (
User, User,
EMailAddress,
ServiceUser, ServiceUser,
School, School,
ListRight, ListRight,
...@@ -108,6 +109,11 @@ class BanAdmin(VersionAdmin): ...@@ -108,6 +109,11 @@ class BanAdmin(VersionAdmin):
pass pass
class EMailAddressAdmin(VersionAdmin):
"""Gestion des alias mail"""
pass
class WhitelistAdmin(VersionAdmin): class WhitelistAdmin(VersionAdmin):
"""Gestion des whitelist""" """Gestion des whitelist"""
pass pass
...@@ -126,6 +132,8 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): ...@@ -126,6 +132,8 @@ class UserAdmin(VersionAdmin, BaseUserAdmin):
'pseudo', 'pseudo',
'surname', 'surname',
'email', 'email',
'local_email_redirect',
'local_email_enabled',
'school', 'school',
'is_admin', 'is_admin',
'shell' 'shell'
...@@ -211,6 +219,7 @@ admin.site.register(School, SchoolAdmin) ...@@ -211,6 +219,7 @@ admin.site.register(School, SchoolAdmin)
admin.site.register(ListRight, ListRightAdmin) admin.site.register(ListRight, ListRightAdmin)
admin.site.register(ListShell, ListShellAdmin) admin.site.register(ListShell, ListShellAdmin)
admin.site.register(Ban, BanAdmin) admin.site.register(Ban, BanAdmin)
admin.site.register(EMailAddress, EMailAddressAdmin)
admin.site.register(Whitelist, WhitelistAdmin) admin.site.register(Whitelist, WhitelistAdmin)
admin.site.register(Request, RequestAdmin) admin.site.register(Request, RequestAdmin)
# Now register the new UserAdmin... # Now register the new UserAdmin...
......
...@@ -53,6 +53,7 @@ from .models import ( ...@@ -53,6 +53,7 @@ from .models import (
School, School,
ListRight, ListRight,
Whitelist, Whitelist,
EMailAddress,
ListShell, ListShell,
Ban, Ban,
Adherent, Adherent,
...@@ -219,7 +220,7 @@ class UserChangeForm(FormRevMixin, forms.ModelForm): ...@@ -219,7 +220,7 @@ class UserChangeForm(FormRevMixin, forms.ModelForm):
class Meta: class Meta:
model = Adherent model = Adherent
fields = ('pseudo', 'password', 'surname', 'email') fields = ('pseudo', 'password', 'surname')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__) prefix = kwargs.pop('prefix', self.Meta.model.__name__)
...@@ -312,7 +313,6 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): ...@@ -312,7 +313,6 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
'name', 'name',
'surname', 'surname',
'pseudo', 'pseudo',
'email',
'school', 'school',
'comment', 'comment',
'room', 'room',
...@@ -364,7 +364,6 @@ class ClubForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): ...@@ -364,7 +364,6 @@ class ClubForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
fields = [ fields = [
'surname', 'surname',
'pseudo', 'pseudo',
'email',
'school', 'school',
'comment', 'comment',
'room', 'room',
...@@ -590,3 +589,39 @@ class WhitelistForm(FormRevMixin, ModelForm): ...@@ -590,3 +589,39 @@ class WhitelistForm(FormRevMixin, ModelForm):
model = Whitelist model = Whitelist
exclude = ['user'] exclude = ['user']
widgets = {'date_end':DateTimePicker} widgets = {'date_end':DateTimePicker}
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(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 = EMailAddress
exclude = ['user']
class EmailSettingsForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
"""Edit email-related settings"""
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
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 = ['email', 'local_email_redirect', 'local_email_enabled']
# -*- 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):
def create_initial_email_address(apps, schema_editor):
db_alias = schema_editor.connection.alias
User = apps.get_model("users", "User")
EMailAddress = apps.get_model("users", "EMailAddress")
users = User.objects.using(db_alias).all()
for user in users:
EMailAddress.objects.using(db_alias).create(
local_part=user.pseudo,
user=user
)
def delete_all_email_address(apps, schema_editor):
db_alias = schema_editor.connection.alias
EMailAddress = apps.get_model("users", "EMailAddress")
EMailAddress.objects.using(db_alias).delete()
dependencies = [
('users', '0072_auto_20180426_2021'),
]
operations = [
migrations.CreateModel(
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_emailaddress', 'Can see a local email account object'),), 'verbose_name': 'Local email account', 'verbose_name_plural': 'Local email accounts'},
),
migrations.AddField(
model_name='user',
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='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_email_address,
delete_all_email_address),
]
...@@ -148,7 +148,7 @@ class UserManager(BaseUserManager): ...@@ -148,7 +148,7 @@ class UserManager(BaseUserManager):
pseudo=pseudo, pseudo=pseudo,
surname=surname, surname=surname,
name=surname, name=surname,
email=self.normalize_email(email), email=self.normalize_email(mail),
) )
user.set_password(password) user.set_password(password)
...@@ -195,6 +195,14 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ...@@ -195,6 +195,14 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
validators=[linux_user_validator] validators=[linux_user_validator]
) )
email = models.EmailField() email = models.EmailField()
local_email_redirect = models.BooleanField(
default=False,
help_text="Whether or not to redirect the local email messages to the main email."
)
local_email_enabled = models.BooleanField(
default=False,
help_text="Wether or not to enable the local email account."
)
school = models.ForeignKey( school = models.ForeignKey(
'School', 'School',
on_delete=models.PROTECT, on_delete=models.PROTECT,
...@@ -674,6 +682,13 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ...@@ -674,6 +682,13 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
self.pwd_ntlm = hashNT(password) self.pwd_ntlm = hashNT(password)
return return
@cached_property
def email_address(self):
if (OptionalUser.get_cached_value('local_email_accounts_enabled')
and self.local_email_enabled):
return self.emailaddress_set.all()
return EMailAddress.objects.none()
def get_next_domain_name(self): def get_next_domain_name(self):
"""Look for an available name for a new interface for """Look for an available name for a new interface for
this user by trying "pseudo0", "pseudo1", "pseudo2", ... this user by trying "pseudo0", "pseudo1", "pseudo2", ...
...@@ -792,6 +807,32 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ...@@ -792,6 +807,32 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
"Droit requis pour changer le shell" "Droit requis pour changer le shell"
) )
@staticmethod
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('local_email_accounts_enabled'),
"La gestion des comptes mails doit être activée"
)
@staticmethod
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
:returns: a message and a boolean which is True if the user has
the right to change internal address
"""
return (
OptionalUser.get_cached_value('local_email_accounts_enabled'),
"La gestion des comptes mails doit être activée"
)
@staticmethod @staticmethod
def can_change_force(user_request, *_args, **_kwargs): def can_change_force(user_request, *_args, **_kwargs):
""" Check if a user can change a force """ Check if a user can change a force
...@@ -886,9 +927,19 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, ...@@ -886,9 +927,19 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
'shell': self.can_change_shell, 'shell': self.can_change_shell,
'force': self.can_change_force, 'force': self.can_change_force,
'selfpasswd': self.check_selfpasswd, 'selfpasswd': self.check_selfpasswd,
'local_email_redirect': self.can_change_local_email_redirect,
'local_email_enabled' : self.can_change_local_email_enabled,
} }
self.__original_state = self.state 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 (EMailAddress.objects
.filter(local_part=self.pseudo)
.exclude(user=self)):
raise ValidationError("This pseudo is already in use.")
def __str__(self): def __str__(self):
return self.pseudo return self.pseudo
...@@ -1011,9 +1062,11 @@ class Club(User): ...@@ -1011,9 +1062,11 @@ class Club(User):
@receiver(post_save, sender=User) @receiver(post_save, sender=User)
def user_post_save(**kwargs): def user_post_save(**kwargs):
""" Synchronisation post_save : envoie le mail de bienvenue si creation """ Synchronisation post_save : envoie le mail de bienvenue si creation
Synchronise le pseudo, en créant un alias mail correspondant
Synchronise le ldap""" Synchronise le ldap"""
is_created = kwargs['created'] is_created = kwargs['created']
user = kwargs['instance'] user = kwargs['instance']
EMailAddress.objects.get_or_create(local_part=user.pseudo, user=user)
if is_created: if is_created:
user.notif_inscription() user.notif_inscription()
user.state_sync() user.state_sync()
...@@ -1593,3 +1646,124 @@ class LdapServiceUserGroup(ldapdb.models.Model): ...@@ -1593,3 +1646,124 @@ class LdapServiceUserGroup(ldapdb.models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
class EMailAddress(RevMixin, AclMixin, models.Model):
"""Defines a local email account for a user
"""
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
help_text="User of the local email",
)
local_part = models.CharField(
unique=True,
max_length=128,
help_text="Local part of the email address"
)
class Meta:
permissions = (
("view_emailaddress", "Can see a local email account object"),
)
verbose_name = "Local email account"
verbose_name_plural = "Local email accounts"
def __str__(self):
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 a user can create a `EMailAddress` object.
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 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.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_email_address')
)
return True, None
def can_view(self, user_request, *_args, **_kwargs):
"""Check if a user can view the local email account
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_emailaddress'):
return True, None
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 a user can delete the alias
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_emailaddress'):
return True, None
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 a user can edit the alias
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_emailaddress'):
return True, None
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.local_part:
raise ValidationError("The local part cannot contain a @")
super(EMailAddress, self).clean(*args, **kwargs)