8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-10 20:06:25 +00:00

Merge branch '217-better-management-of-desactivated-account' into 'dev'

Resolve "Desactivated account unable to log in"

See merge request federez/re2o!434
This commit is contained in:
chirac 2019-09-19 22:59:43 +02:00
commit 3bb010b9b8
9 changed files with 124 additions and 58 deletions

View file

@ -246,9 +246,10 @@ class Facture(BaseInvoice):
def can_change_control(user_request, *_args, **_kwargs): def can_change_control(user_request, *_args, **_kwargs):
""" Returns True if the user can change the 'controlled' status of """ Returns True if the user can change the 'controlled' status of
this invoice """ this invoice """
can = user_request.has_perm('cotisations.change_facture_control')
return ( return (
user_request.has_perm('cotisations.change_facture_control'), can,
_("You don't have the right to edit the \"controlled\" state."), _("You don't have the right to edit the \"controlled\" state.") if not can else None,
('cotisations.change_facture_control',) ('cotisations.change_facture_control',)
) )
@ -746,11 +747,12 @@ class Article(RevMixin, AclMixin, models.Model):
A boolean stating if usage is granted and an explanation A boolean stating if usage is granted and an explanation
message if the boolean is `False`. message if the boolean is `False`.
""" """
can = self.available_for_everyone \
or user.has_perm('cotisations.buy_every_article') \
or user.has_perm('cotisations.add_facture')
return ( return (
self.available_for_everyone can,
or user.has_perm('cotisations.buy_every_article') _("You can't buy this article.") if not can else None,
or user.has_perm('cotisations.add_facture'),
_("You can't buy this article."),
('cotisations.buy_every_article', 'cotisations.add_facture') ('cotisations.buy_every_article', 'cotisations.add_facture')
) )
@ -902,11 +904,12 @@ class Paiement(RevMixin, AclMixin, models.Model):
A boolean stating if usage is granted and an explanation A boolean stating if usage is granted and an explanation
message if the boolean is `False`. message if the boolean is `False`.
""" """
can = self.available_for_everyone \
or user.has_perm('cotisations.use_every_payment') \
or user.has_perm('cotisations.add_facture')
return ( return (
self.available_for_everyone can,
or user.has_perm('cotisations.use_every_payment') _("You can't use this payment method.") if not can else None,
or user.has_perm('cotisations.add_facture'),
_("You can't use this payment method."),
('cotisations.use_every_payment', 'cotisations.add_facture') ('cotisations.use_every_payment', 'cotisations.add_facture')
) )

View file

@ -105,9 +105,10 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
A tuple with a boolean stating if edition is allowed and an A tuple with a boolean stating if edition is allowed and an
explanation message. explanation message.
""" """
can = user_request.has_perm('machines.change_machine_user')
return ( return (
user_request.has_perm('machines.change_machine_user'), can,
_("You don't have the right to change the machine's user."), _("You don't have the right to change the machine's user.") if not can else None,
('machines.change_machine_user',) ('machines.change_machine_user',)
) )
@ -803,9 +804,10 @@ class Extension(RevMixin, AclMixin, models.Model):
restrictions restrictions
:param user_request: instance user qui fait l'edition :param user_request: instance user qui fait l'edition
:return: True ou False avec la raison de l'échec le cas échéant""" :return: True ou False avec la raison de l'échec le cas échéant"""
can = user_request.has_perm('machines.use_all_extension')
return ( return (
user_request.has_perm('machines.use_all_extension'), can,
_("You cannot use all extensions."), _("You cannot use all extensions.") if not can else None,
('machines.use_all_extension',) ('machines.use_all_extension',)
) )
@ -1294,9 +1296,10 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
def can_change_machine(user_request, *_args, **_kwargs): def can_change_machine(user_request, *_args, **_kwargs):
"""Check if a user can change the machine associated with an """Check if a user can change the machine associated with an
Interface object """ Interface object """
can = user_request.has_perm('machines.change_interface_machine')
return ( return (
user_request.has_perm('machines.change_interface_machine'), can,
_("Permission required to edit the machine."), _("Permission required to edit the machine.") if not can else None,
('machines.change_interface_machine',) ('machines.change_interface_machine',)
) )
@ -1421,10 +1424,11 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
@staticmethod @staticmethod
def can_change_slaac_ip(user_request, *_args, **_kwargs): def can_change_slaac_ip(user_request, *_args, **_kwargs):
""" Check if a user can change the slaac value """ """ Check if a user can change the slaac value """
can = user_request.has_perm('machines.change_ipv6list_slaac_ip')
return ( return (
user_request.has_perm('machines.change_ipv6list_slaac_ip'), can,
_("Permission required to change the SLAAC value of an IPv6" _("Permission required to change the SLAAC value of an IPv6"
" address"), " address") if not can else None,
('machines.change_ipv6list_slaac_ip',) ('machines.change_ipv6list_slaac_ip',)
) )

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.23 on 2019-09-09 09:50
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('preferences', '0060_auto_20190712_1821'),
]
operations = [
migrations.AddField(
model_name='optionaluser',
name='allow_archived_connexion',
field=models.BooleanField(default=False, help_text='If True, archived users are allowed to connect.'),
),
]

View file

@ -123,6 +123,10 @@ class OptionalUser(AclMixin, PreferencesModel):
help_text=_("If True, all new created and connected users are active." help_text=_("If True, all new created and connected users are active."
" If False, only when a valid registration has been paid.") " If False, only when a valid registration has been paid.")
) )
allow_archived_connexion = models.BooleanField(
default=False,
help_text=_("If True, archived users are allowed to connect.")
)
class Meta: class Meta:
permissions = ( permissions = (

View file

@ -125,6 +125,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<tr> <tr>
<th>{% trans "All users are active by default" %}</th> <th>{% trans "All users are active by default" %}</th>
<td>{{ useroptions.all_users_active|tick }}</td> <td>{{ useroptions.all_users_active|tick }}</td>
<th>{% trans "Allow archived users to log-in" %}</th>
<td>{{ useroptions.allow_archived_connexion|tick }}</td>
</tr> </tr>
</table> </table>

View file

@ -41,6 +41,8 @@ from re2o.utils import get_group_having_permission
def acl_error_message(msg, permissions): def acl_error_message(msg, permissions):
"""Create an error message for msg and permissions.""" """Create an error message for msg and permissions."""
if permissions is None:
return msg
groups = ", ".join([ groups = ", ".join([
g.name for g in get_group_having_permission(*permissions) g.name for g in get_group_having_permission(*permissions)
]) ])
@ -76,9 +78,11 @@ def acl_base_decorator(method_name, *targets, on_instance=True):
permission was granted. This is to allow you to run ACL tests on permission was granted. This is to allow you to run ACL tests on
fields only. If the method exists, it has to return a 2-tuple fields only. If the method exists, it has to return a 2-tuple
`(can, reason, permissions)` with `can` being a boolean stating `(can, reason, permissions)` with `can` being a boolean stating
whether the access is granted, `reason` a message to be whether the access is granted, `reason` an arror message to be
displayed if `can` equals `False` (can be `None`) and `permissions` displayed if `can` equals `False` (can be `None`) and `permissions`
a list of permissions needed for access (can be `None`). a list of permissions needed for access (can be `None`). If can is
True and permission is not `None`, a warning message will be
displayed.
*targets: The targets. Targets are specified like a sequence of models *targets: The targets. Targets are specified like a sequence of models
and fields names. As an example and fields names. As an example
``` ```
@ -172,10 +176,17 @@ ModelC)
yield can_change_fct(request.user, *args, **kwargs) yield can_change_fct(request.user, *args, **kwargs)
error_messages = [] error_messages = []
warning_messages = []
for target, fields in group_targets(): for target, fields in group_targets():
for can, msg, permissions in process_target(target, fields): for can, msg, permissions in process_target(target, fields):
if not can: if not can:
error_messages.append(acl_error_message(msg, permissions)) error_messages.append(acl_error_message(msg, permissions))
elif msg:
warning_messages.append(acl_error_message(msg, permissions))
if warning_messages:
for msg in warning_messages:
messages.warning(request, msg)
if error_messages: if error_messages:
for msg in error_messages: for msg in error_messages:

View file

@ -105,10 +105,11 @@ class AclMixin(object):
:param user_request: instance utilisateur qui fait la requête :param user_request: instance utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec""" :return: soit True, soit False avec la raison de l'échec"""
permission = cls.get_modulename() + '.add_' + cls.get_classname() permission = cls.get_modulename() + '.add_' + cls.get_classname()
can = user_request.has_perm(permission)
return ( return (
user_request.has_perm(permission), can,
_("You don't have the right to create a %s object.") _("You don't have the right to create a %s object.")
% cls.get_classname(), % cls.get_classname() if not can else None,
(permission,) (permission,)
) )
@ -119,10 +120,11 @@ class AclMixin(object):
:param user_request: Utilisateur qui fait la requête :param user_request: Utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec""" :return: soit True, soit False avec la raison de l'échec"""
permission = self.get_modulename() + '.change_' + self.get_classname() permission = self.get_modulename() + '.change_' + self.get_classname()
can = user_request.has_perm(permission)
return ( return (
user_request.has_perm(permission), can,
_("You don't have the right to edit a %s object.") _("You don't have the right to edit a %s object.")
% self.get_classname(), % self.get_classname() if not can else None,
(permission,) (permission,)
) )
@ -133,10 +135,11 @@ class AclMixin(object):
:param user_request: Utilisateur qui fait la requête :param user_request: Utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec""" :return: soit True, soit False avec la raison de l'échec"""
permission = self.get_modulename() + '.delete_' + self.get_classname() permission = self.get_modulename() + '.delete_' + self.get_classname()
can = user_request.has_perm(permission)
return ( return (
user_request.has_perm(permission), can,
_("You don't have the right to delete a %s object.") _("You don't have the right to delete a %s object.")
% self.get_classname(), % self.get_classname() if not can else None,
(permission,) (permission,)
) )
@ -147,10 +150,11 @@ class AclMixin(object):
:param user_request: instance user qui fait l'edition :param user_request: instance user qui fait l'edition
:return: True ou False avec la raison de l'échec le cas échéant""" :return: True ou False avec la raison de l'échec le cas échéant"""
permission = cls.get_modulename() + '.view_' + cls.get_classname() permission = cls.get_modulename() + '.view_' + cls.get_classname()
can = user_request.has_perm(permission)
return ( return (
user_request.has_perm(permission), can,
_("You don't have the right to view every %s object.") _("You don't have the right to view every %s object.")
% cls.get_classname(), % cls.get_classname() if not can else None,
(permission,) (permission,)
) )
@ -161,10 +165,11 @@ class AclMixin(object):
:param user_request: instance user qui fait l'edition :param user_request: instance user qui fait l'edition
:return: True ou False avec la raison de l'échec le cas échéant""" :return: True ou False avec la raison de l'échec le cas échéant"""
permission = self.get_modulename() + '.view_' + self.get_classname() permission = self.get_modulename() + '.view_' + self.get_classname()
can = user_request.has_perm(permission)
return ( return (
user_request.has_perm(permission), can,
_("You don't have the right to view a %s object.") _("You don't have the right to view a %s object.")
% self.get_classname(), % self.get_classname() if not can else None,
(permission,) (permission,)
) )

View file

@ -86,9 +86,10 @@ class Ticket(AclMixin, models.Model):
@staticmethod @staticmethod
def can_view_all(user_request, *_args, **_kwargs): def can_view_all(user_request, *_args, **_kwargs):
""" Check that the user has access to the list of all tickets""" """ Check that the user has access to the list of all tickets"""
can = user_request.has_perm('tickets.view_tickets')
return( return(
user_request.has_perm('tickets.view_tickets'), can,
_("You don't have the right to view the list of tickets."), _("You don't have the right to view the list of tickets.") if not can else None,
('tickets.view_tickets',) ('tickets.view_tickets',)
) )

View file

@ -333,7 +333,8 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
@property @property
def is_active(self): def is_active(self):
""" Renvoie si l'user est à l'état actif""" """ Renvoie si l'user est à l'état actif"""
return self.state == self.STATE_ACTIVE or self.state == self.STATE_NOT_YET_ACTIVE allow_archived = OptionalUser.get_cached_value('allow_archived_connexion')
return self.state == self.STATE_ACTIVE or self.state == self.STATE_NOT_YET_ACTIVE or (allow_archived and self.state in (self.STATE_ARCHIVE, self.STATE_FULL_ARCHIVE))
def set_active(self): def set_active(self):
"""Enable this user if he subscribed successfully one time before """Enable this user if he subscribed successfully one time before
@ -858,18 +859,23 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
user_request one of its member, or if user_request is self, or if user_request one of its member, or if user_request is self, or if
user_request has the 'cableur' right. user_request has the 'cableur' right.
""" """
if self.state in (self.STATE_ARCHIVE, self.STATE_FULL_ARCHIVE):
warning_message = _("This user is archived.")
else:
warning_message = None
if self.is_class_club and user_request.is_class_adherent: if self.is_class_club and user_request.is_class_adherent:
if (self == user_request or if (self == user_request or
user_request.has_perm('users.change_user') or user_request.has_perm('users.change_user') or
user_request.adherent in self.club.administrators.all()): user_request.adherent in self.club.administrators.all()):
return True, None, None return True, warning_message, None
else: else:
return False, _("You don't have the right to edit this club."), ('users.change_user',) return False, _("You don't have the right to edit this club."), ('users.change_user',)
else: else:
if self == user_request: if self == user_request:
return True, None, None return True, warning_message, None
elif user_request.has_perm('users.change_all_users'): elif user_request.has_perm('users.change_all_users'):
return True, None, None return True, warning_message, None
elif user_request.has_perm('users.change_user'): elif user_request.has_perm('users.change_user'):
if self.groups.filter(listright__critical=True): if self.groups.filter(listright__critical=True):
return ( return (
@ -885,9 +891,9 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
('users.change_all_users', ) ('users.change_all_users', )
) )
else: else:
return True, None, None return True, warning_message, None
elif user_request.has_perm('users.change_all_users'): elif user_request.has_perm('users.change_all_users'):
return True, None, None return True, warning_message, None
else: else:
return ( return (
False, False,
@ -962,9 +968,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
:returns: a message and a boolean which is True if the user has :returns: a message and a boolean which is True if the user has
the right to change a state the right to change a state
""" """
can = user_request.has_perm('users.change_user_state')
return ( return (
user_request.has_perm('users.change_user_state'), can,
_("Permission required to change the state."), _("Permission required to change the state.") if not can else None,
('users.change_user_state',) ('users.change_user_state',)
) )
@ -993,9 +1000,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
:returns: a message and a boolean which is True if the user has :returns: a message and a boolean which is True if the user has
the right to change a redirection the right to change a redirection
""" """
can = OptionalUser.get_cached_value('local_email_accounts_enabled')
return ( return (
OptionalUser.get_cached_value('local_email_accounts_enabled'), can,
_("Local email accounts must be enabled."), _("Local email accounts must be enabled.") if not can else None,
None None
) )
@ -1007,9 +1015,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
:returns: a message and a boolean which is True if the user has :returns: a message and a boolean which is True if the user has
the right to change internal address the right to change internal address
""" """
can = OptionalUser.get_cached_value('local_email_accounts_enabled')
return ( return (
OptionalUser.get_cached_value('local_email_accounts_enabled'), can,
_("Local email accounts must be enabled."), _("Local email accounts must be enabled.") if not can else None,
None None
) )
@ -1021,9 +1030,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
:returns: a message and a boolean which is True if the user has :returns: a message and a boolean which is True if the user has
the right to change a force the right to change a force
""" """
can = user_request.has_perm('users.change_user_force')
return ( return (
user_request.has_perm('users.change_user_force'), can,
_("Permission required to force the move."), _("Permission required to force the move.") if not can else None,
('users.change_user_force',) ('users.change_user_force',)
) )
@ -1035,9 +1045,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
:returns: a message and a boolean which is True if the user has :returns: a message and a boolean which is True if the user has
the right to change a group the right to change a group
""" """
can = user_request.has_perm('users.change_user_grou')
return ( return (
user_request.has_perm('users.change_user_groups'), can,
_("Permission required to edit the user's groups of rights."), _("Permission required to edit the user's groups of rights.") if not can else None,
('users.change_user_groups') ('users.change_user_groups')
) )
@ -1048,9 +1059,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
:param user_request: The user who request :param user_request: The user who request
:returns: a message and a boolean which is True if permission is granted. :returns: a message and a boolean which is True if permission is granted.
""" """
can = user_request.is_superuser
return ( return (
user_request.is_superuser, can,
_("'superuser' right required to edit the superuser flag."), _("'superuser' right required to edit the superuser flag.") if not can else None,
[] []
) )
@ -1093,9 +1105,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
:return: True if the user can view the list and an explanation :return: True if the user can view the list and an explanation
message. message.
""" """
can = user_request.has_perm('use.view_user')
return ( return (
user_request.has_perm('users.view_user'), can,
_("You don't have the right to view the list of users."), _("You don't have the right to view the list of users.") if not can else None,
('users.view_user',) ('users.view_user',)
) )
@ -1107,9 +1120,10 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
:return: True if user_request has the right 'bureau', and a :return: True if user_request has the right 'bureau', and a
message. message.
""" """
can = user_request.has_perm('users.delete_user')
return ( return (
user_request.has_perm('users.delete_user'), can,
_("You don't have the right to delete this user."), _("You don't have the right to delete this user.") if not can else None,
('users.delete_user',) ('users.delete_user',)
) )
@ -1203,9 +1217,10 @@ class Adherent(User):
OptionalUser.get_cached_value('self_adhesion')): OptionalUser.get_cached_value('self_adhesion')):
return True, None, None return True, None, None
else: else:
can = user_request.has_perm('users.add_user')
return ( return (
user_request.has_perm('users.add_user'), can,
_("You don't have the right to create a user."), _("You don't have the right to create a user.") if not can else None,
('users.add_user',) ('users.add_user',)
) )
@ -1259,9 +1274,10 @@ class Club(User):
if OptionalUser.get_cached_value('all_can_create_club'): if OptionalUser.get_cached_value('all_can_create_club'):
return True, None, None return True, None, None
else: else:
can = user_request.has_perm('users.add_user')
return ( return (
user_request.has_perm('users.add_user'), can,
_("You don't have the right to create a club."), _("You don't have the right to create a club.") if not can else None,
('users.add_user',) ('users.add_user',)
) )