allow overriding User.can_reset_password by hooks (fixes #25534)
This commit introduce the concept of an user flag, this flag can be defined in many places: * globally trough a setting named A2_USER_<FLAG> * on the user object itself if there is a property user.<flag> which is not None * by any hook returning a not None result and named a2_hook_user_<flag> * for all users of an OU if the ou.<flag> is not None
This commit is contained in:
parent
eeb93e79d3
commit
d7a2af17c3
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('a2_rbac', '0016_auto_20171208_1429'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='organizationalunit',
|
||||||
|
name='user_can_reset_password',
|
||||||
|
field=models.NullBooleanField(verbose_name='Users can reset password'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -44,6 +44,9 @@ class OrganizationalUnit(OrganizationalUnitAbstractBase):
|
||||||
content_type_field='target_ct',
|
content_type_field='target_ct',
|
||||||
object_id_field='target_id')
|
object_id_field='target_id')
|
||||||
|
|
||||||
|
user_can_reset_password = models.NullBooleanField(
|
||||||
|
verbose_name=_('Users can reset password'))
|
||||||
|
|
||||||
objects = managers.OrganizationalUnitManager()
|
objects = managers.OrganizationalUnitManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -49,6 +49,14 @@ class AppSettings(object):
|
||||||
add_realms(self.A2_REALMS)
|
add_realms(self.A2_REALMS)
|
||||||
return realms.items()
|
return realms.items()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def A2_USER_CAN_RESET_PASSWORD(self):
|
||||||
|
if hasattr(self.settings, 'A2_USER_CAN_RESET_PASSWORD'):
|
||||||
|
return self.settings.A2_USER_CAN_RESET_PASSWORD
|
||||||
|
if hasattr(self.settings, 'A2_CAN_RESET_PASSWORD'):
|
||||||
|
return self.settings.A2_CAN_RESET_PASSWORD
|
||||||
|
return self.defaults['A2_USER_CAN_RESET_PASSWORD'].default
|
||||||
|
|
||||||
def __getattr__(self, key):
|
def __getattr__(self, key):
|
||||||
if key not in self.defaults:
|
if key not in self.defaults:
|
||||||
raise AttributeError('unknown key %s' % key)
|
raise AttributeError('unknown key %s' % key)
|
||||||
|
@ -107,7 +115,7 @@ default_settings = dict(
|
||||||
definition='Include empty fields in profile view'),
|
definition='Include empty fields in profile view'),
|
||||||
A2_HOMEPAGE_URL = Setting(default=None, definition='IdP has no homepage, '
|
A2_HOMEPAGE_URL = Setting(default=None, definition='IdP has no homepage, '
|
||||||
'redirect to this one.'),
|
'redirect to this one.'),
|
||||||
A2_CAN_RESET_PASSWORD = Setting(default=True, definition='Allow online reset of passwords'),
|
A2_USER_CAN_RESET_PASSWORD = Setting(default=None, definition='Allow online reset of passwords'),
|
||||||
A2_EMAIL_IS_UNIQUE = Setting(default=False,
|
A2_EMAIL_IS_UNIQUE = Setting(default=False,
|
||||||
definition='Email of users must be unique'),
|
definition='Email of users must be unique'),
|
||||||
A2_REGISTRATION_EMAIL_IS_UNIQUE = Setting(default=False,
|
A2_REGISTRATION_EMAIL_IS_UNIQUE = Setting(default=False,
|
||||||
|
|
|
@ -216,6 +216,7 @@ class LDAPUser(get_user_model()):
|
||||||
if hasattr(self, 'keep_pk'):
|
if hasattr(self, 'keep_pk'):
|
||||||
self.pk = pk
|
self.pk = pk
|
||||||
|
|
||||||
|
@property
|
||||||
def can_reset_password(self):
|
def can_reset_password(self):
|
||||||
return self.block['can_reset_password']
|
return self.block['can_reset_password']
|
||||||
|
|
||||||
|
|
|
@ -250,8 +250,5 @@ class User(AbstractBaseUser, PermissionMixin):
|
||||||
attribute.set_value(self, getattr(self, attr_name, None))
|
attribute.set_value(self, getattr(self, attr_name, None))
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
def can_reset_password(self):
|
|
||||||
return self.has_usable_password()
|
|
||||||
|
|
||||||
def can_change_password(self):
|
def can_change_password(self):
|
||||||
return app_settings.A2_REGISTRATION_CAN_CHANGE_PASSWORD
|
return app_settings.A2_REGISTRATION_CAN_CHANGE_PASSWORD
|
||||||
|
|
|
@ -81,7 +81,10 @@ class PasswordResetConfirmView(cbv.RedirectToNextURLViewMixin, FormView):
|
||||||
'or has expired'))
|
'or has expired'))
|
||||||
if not validlink:
|
if not validlink:
|
||||||
return utils.redirect(request, self.get_success_url())
|
return utils.redirect(request, self.get_success_url())
|
||||||
if not self.user.can_reset_password():
|
can_reset_password = utils.get_user_flag(user=self.user,
|
||||||
|
name='can_reset_password',
|
||||||
|
default=self.user.has_usable_password())
|
||||||
|
if not can_reset_password:
|
||||||
messages.warning(request, _('It\'s not possible to reset your password. Please '
|
messages.warning(request, _('It\'s not possible to reset your password. Please '
|
||||||
'contact an administrator.'))
|
'contact an administrator.'))
|
||||||
return utils.redirect(request, self.get_success_url())
|
return utils.redirect(request, self.get_success_url())
|
||||||
|
|
|
@ -1054,3 +1054,26 @@ def send_email_change_email(user, email, request=None, context=None, template_na
|
||||||
def update_model(obj, d):
|
def update_model(obj, d):
|
||||||
for attr, value in d.items():
|
for attr, value in d.items():
|
||||||
setattr(obj, attr, value)
|
setattr(obj, attr, value)
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_flag(user, name, default=None):
|
||||||
|
'''Get a boolean flag settable at user, by a hook, globally or ou wide'''
|
||||||
|
from . import hooks
|
||||||
|
|
||||||
|
setting_value = getattr(app_settings, 'A2_USER_' + name.upper(), None)
|
||||||
|
if setting_value is not None:
|
||||||
|
return bool(setting_value)
|
||||||
|
|
||||||
|
user_value = getattr(user, name, None)
|
||||||
|
if user_value is not None:
|
||||||
|
return user_value
|
||||||
|
|
||||||
|
hook_value = hooks.call_hooks_first_result('user_' + name, user=user)
|
||||||
|
if hook_value is not None:
|
||||||
|
return bool(hook_value)
|
||||||
|
|
||||||
|
if user.ou and hasattr(user.ou, 'user_' + name):
|
||||||
|
ou_value = getattr(user.ou, 'user_' + name, None)
|
||||||
|
if ou_value is not None:
|
||||||
|
return ou_value
|
||||||
|
return default
|
||||||
|
|
|
@ -292,7 +292,7 @@ def login(request, template_name='authentic2/login.html',
|
||||||
|
|
||||||
context_instance = RequestContext(request, {
|
context_instance = RequestContext(request, {
|
||||||
'cancel': nonce is not None,
|
'cancel': nonce is not None,
|
||||||
'can_reset_password': app_settings.A2_CAN_RESET_PASSWORD,
|
'can_reset_password': app_settings.A2_USER_CAN_RESET_PASSWORD is not False,
|
||||||
'registration_authorized': getattr(settings, 'REGISTRATION_OPEN', True),
|
'registration_authorized': getattr(settings, 'REGISTRATION_OPEN', True),
|
||||||
'registration_url': registration_url,
|
'registration_url': registration_url,
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue