Add support for blocking the changing of password for specify users.
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -118,6 +118,7 @@
|
||||
- Interpret ALLOWED_HOSTS as YAML.
|
||||
- Don't show the document types of an index instance.
|
||||
- Add the tag created and tag edited events.
|
||||
- Add support for blocking the changing of password for specify users.
|
||||
|
||||
3.0.3 (2018-08-17)
|
||||
==================
|
||||
|
||||
@@ -7,8 +7,11 @@ from navigation import Link
|
||||
from .icons import icon_logout, icon_password_change
|
||||
|
||||
|
||||
def has_usable_password(context):
|
||||
return context['request'].user.has_usable_password
|
||||
def has_usable_password_and_can_change_password(context):
|
||||
return (
|
||||
context['request'].user.has_usable_password and
|
||||
not context['request'].user.user_options.block_password_change
|
||||
)
|
||||
|
||||
|
||||
link_logout = Link(
|
||||
@@ -16,6 +19,7 @@ link_logout = Link(
|
||||
text=_('Logout'), view='authentication:logout_view'
|
||||
)
|
||||
link_password_change = Link(
|
||||
condition=has_usable_password, icon_class=icon_password_change,
|
||||
text=_('Change password'), view='authentication:password_change_view'
|
||||
condition=has_usable_password_and_can_change_password,
|
||||
icon_class=icon_password_change, text=_('Change password'),
|
||||
view='authentication:password_change_view'
|
||||
)
|
||||
|
||||
@@ -2,13 +2,14 @@ from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
|
||||
from django.contrib.auth.views import (
|
||||
login, password_change, password_reset, password_reset_confirm,
|
||||
password_reset_complete, password_reset_done
|
||||
)
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import redirect, resolve_url
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
from django.utils.http import is_safe_url
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@@ -77,6 +78,14 @@ def password_change_view(request):
|
||||
"""
|
||||
extra_context = {'title': _('Current user password change')}
|
||||
|
||||
if request.user.user_options.block_password_change:
|
||||
messages.error(
|
||||
request, _(
|
||||
'Changing the password is not allowed for this account.'
|
||||
)
|
||||
)
|
||||
return HttpResponseRedirect(reverse(settings.HOME_VIEW))
|
||||
|
||||
return password_change(
|
||||
request, extra_context=extra_context,
|
||||
template_name='appearance/generic_form.html',
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.apps import apps
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db.models.signals import post_save
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from acls import ModelPermission
|
||||
@@ -14,12 +15,13 @@ from metadata import MetadataLookup
|
||||
from navigation import SourceColumn
|
||||
from rest_api.fields import DynamicSerializerField
|
||||
|
||||
from .handlers import handler_initialize_new_user_options
|
||||
from .links import (
|
||||
link_group_add, link_group_delete, link_group_edit, link_group_list,
|
||||
link_group_members, link_group_setup, link_user_add, link_user_delete,
|
||||
link_user_edit, link_user_groups, link_user_list,
|
||||
link_user_multiple_delete, link_user_multiple_set_password,
|
||||
link_user_set_password, link_user_setup
|
||||
link_user_set_options, link_user_set_password, link_user_setup
|
||||
)
|
||||
from .permissions import (
|
||||
permission_group_delete, permission_group_edit,
|
||||
@@ -116,12 +118,13 @@ class UserManagementApp(MayanAppConfig):
|
||||
sources=(Group,)
|
||||
)
|
||||
menu_object.bind_links(
|
||||
links=(link_acl_list, link_group_delete,), position=99, sources=(Group,)
|
||||
links=(link_acl_list, link_group_delete,), position=99,
|
||||
sources=(Group,)
|
||||
)
|
||||
menu_object.bind_links(
|
||||
links=(
|
||||
link_user_edit, link_user_set_password, link_user_groups,
|
||||
link_acl_list, link_user_delete
|
||||
link_user_set_options, link_acl_list, link_user_delete
|
||||
), sources=(User,)
|
||||
)
|
||||
menu_secondary.bind_links(
|
||||
@@ -140,5 +143,10 @@ class UserManagementApp(MayanAppConfig):
|
||||
)
|
||||
menu_setup.bind_links(links=(link_user_setup, link_group_setup))
|
||||
|
||||
post_save.connect(
|
||||
dispatch_uid='user_management_handler_initialize_new_user_options',
|
||||
receiver=handler_initialize_new_user_options,
|
||||
sender=User
|
||||
)
|
||||
registry.register(Group)
|
||||
registry.register(User)
|
||||
|
||||
@@ -6,5 +6,7 @@ from django.contrib.auth import get_user_model
|
||||
|
||||
class UserForm(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = (
|
||||
'username', 'first_name', 'last_name', 'email', 'is_active',
|
||||
)
|
||||
model = get_user_model()
|
||||
fields = ('username', 'first_name', 'last_name', 'email', 'is_active',)
|
||||
|
||||
12
mayan/apps/user_management/handlers.py
Normal file
12
mayan/apps/user_management/handlers.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import apps
|
||||
|
||||
|
||||
def handler_initialize_new_user_options(sender, instance, **kwargs):
|
||||
UserOptions = apps.get_model(
|
||||
app_label='user_management', model_name='UserOptions'
|
||||
)
|
||||
|
||||
if kwargs['created']:
|
||||
UserOptions.objects.create(user=instance)
|
||||
@@ -63,6 +63,10 @@ link_user_multiple_set_password = Link(
|
||||
permissions=(permission_user_edit,), text=_('Set password'),
|
||||
view='user_management:user_multiple_set_password'
|
||||
)
|
||||
link_user_set_options = Link(
|
||||
args='object.id', permissions=(permission_user_edit,),
|
||||
text=_('User options'), view='user_management:user_options',
|
||||
)
|
||||
link_user_set_password = Link(
|
||||
args='object.id', permissions=(permission_user_edit,),
|
||||
text=_('Set password'), view='user_management:user_set_password',
|
||||
|
||||
55
mayan/apps/user_management/migrations/0001_initial.py
Normal file
55
mayan/apps/user_management/migrations/0001_initial.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.11 on 2018-08-26 10:01
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
def add_user_options_to_existing_users(apps, schema_editor):
|
||||
User = apps.get_model(settings.AUTH_USER_MODEL)
|
||||
UserOptions = apps.get_model(
|
||||
app_label='user_management', model_name='UserOptions'
|
||||
)
|
||||
|
||||
for user in User.objects.all():
|
||||
UserOptions.objects.create(user=user)
|
||||
|
||||
|
||||
def remove_user_options_from_existing_users(apps, schema_editor):
|
||||
User = apps.get_model(settings.AUTH_USER_MODEL)
|
||||
UserOptions = apps.get_model(
|
||||
app_label='user_management', model_name='UserOptions'
|
||||
)
|
||||
|
||||
for user in User.objects.all():
|
||||
UserOptions.objects.filter(user=user).delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserOptions',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('block_password_change', models.BooleanField(default=False, verbose_name='Forbid this user from changing their password.')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='user_options', to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'User settings',
|
||||
'verbose_name_plural': 'Users settings',
|
||||
},
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=add_user_options_to_existing_users,
|
||||
reverse_code=remove_user_options_from_existing_users
|
||||
),
|
||||
]
|
||||
0
mayan/apps/user_management/migrations/__init__.py
Normal file
0
mayan/apps/user_management/migrations/__init__.py
Normal file
24
mayan/apps/user_management/models.py
Normal file
24
mayan/apps/user_management/models.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class UserOptions(models.Model):
|
||||
user = models.OneToOneField(
|
||||
on_delete=models.CASCADE, related_name='user_options',
|
||||
to=settings.AUTH_USER_MODEL, unique=True, verbose_name=_('User')
|
||||
)
|
||||
block_password_change = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_('Forbid this user from changing their password.')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('User settings')
|
||||
verbose_name_plural = _('Users settings')
|
||||
|
||||
def natural_key(self):
|
||||
return self.user.natural_key()
|
||||
natural_key.dependencies = [settings.AUTH_USER_MODEL]
|
||||
@@ -9,7 +9,7 @@ from .api_views import (
|
||||
from .views import (
|
||||
GroupCreateView, GroupDeleteView, GroupEditView, GroupListView,
|
||||
GroupMembersView, UserCreateView, UserDeleteView, UserEditView,
|
||||
UserGroupsView, UserListView, UserSetPasswordView
|
||||
UserGroupsView, UserListView, UserOptionsEditView, UserSetPasswordView
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
@@ -51,6 +51,11 @@ urlpatterns = [
|
||||
r'^user/(?P<pk>\d+)/groups/$', UserGroupsView.as_view(),
|
||||
name='user_groups'
|
||||
),
|
||||
url(
|
||||
r'^user/(?P<pk>\d+)/options/$',
|
||||
UserOptionsEditView.as_view(),
|
||||
name='user_options'
|
||||
),
|
||||
]
|
||||
|
||||
api_urls = [
|
||||
|
||||
@@ -133,8 +133,10 @@ class UserCreateView(SingleObjectCreateView):
|
||||
|
||||
|
||||
class UserDeleteView(MultipleObjectConfirmActionView):
|
||||
model = get_user_model()
|
||||
object_permission = permission_user_delete
|
||||
queryset = get_user_model().objects.filter(
|
||||
is_superuser=False, is_staff=False
|
||||
)
|
||||
success_message = _('User delete request performed on %(count)d user')
|
||||
success_message_plural = _(
|
||||
'User delete request performed on %(count)d users'
|
||||
@@ -216,8 +218,11 @@ class UserGroupsView(AssignRemoveView):
|
||||
'title': _('Groups of user: %s') % self.get_object()
|
||||
}
|
||||
|
||||
def get_object(self):
|
||||
return get_object_or_404(get_user_model(), pk=self.kwargs['pk'])
|
||||
return get_object_or_404(
|
||||
get_user_model().objects.filter(
|
||||
is_superuser=False, is_staff=False
|
||||
), pk=self.kwargs['pk']
|
||||
)
|
||||
|
||||
def left_list(self):
|
||||
return AssignRemoveView.generate_choices(
|
||||
@@ -248,6 +253,31 @@ class UserListView(SingleObjectListView):
|
||||
).exclude(is_staff=True).order_by('last_name', 'first_name')
|
||||
|
||||
|
||||
class UserOptionsEditView(SingleObjectEditView):
|
||||
fields = ('block_password_change',)
|
||||
object_permission = permission_user_edit
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
'title': _(
|
||||
'Edit options for user: %s'
|
||||
) % self.get_user()
|
||||
}
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return self.get_user().user_options
|
||||
|
||||
def get_post_action_redirect(self):
|
||||
return reverse('user_management:user_list')
|
||||
|
||||
def get_user(self):
|
||||
return get_object_or_404(
|
||||
get_user_model().objects.filter(
|
||||
is_superuser=False, is_staff=False
|
||||
), pk=self.kwargs['pk']
|
||||
)
|
||||
|
||||
|
||||
class UserSetPasswordView(MultipleObjectFormActionView):
|
||||
form_class = SetPasswordForm
|
||||
model = get_user_model()
|
||||
|
||||
Reference in New Issue
Block a user