User groups, group users views to AddRemoveView

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2019-04-25 03:24:33 -04:00
parent 510cdf894c
commit fb1f5dbfe3
6 changed files with 157 additions and 107 deletions

View File

@@ -150,6 +150,14 @@
* Add AddRemoveView to replace AssignRemoveView
* Update the group roles view to use the new AddRemoveView.
* Add role create and edit events.
* Sort users by lastname, firstname.
* Switch user groups and group users views to AddRemoveView.
* Commit user edit event when an user is added or removed
from a group.
* Commit the group edit event when a group is added or remove
from an user.
* Require dual permissions when add or removing users to and
from group. Same with group to users.
3.1.11 (2019-04-XX)
===================

View File

@@ -182,6 +182,14 @@ Other changes
* Add AddRemoveView to replace AssignRemoveView
* Update the group roles view to use the new AddRemoveView.
* Add role create and edit events.
* Sort users by lastname, firstname.
* Switch user groups and group users views to AddRemoveView.
* Commit user edit event when an user is added or removed
from a group.
* Commit the group edit event when a group is added or remove
from an user.
* Require dual permissions when add or removing users to and
from group. Same with group to users.
Removals
--------

View File

@@ -37,7 +37,9 @@ from .links import (
text_user_label
)
from .methods import (
get_method_group_save, get_method_user_save, method_user_get_absolute_url
get_method_group_save, get_method_user_save, method_user_get_absolute_url,
method_group_get_users, method_group_users_add, method_group_users_remove,
method_user_get_groups, method_user_groups_add, method_user_groups_remove
)
from .permissions import (
@@ -89,6 +91,15 @@ class UserManagementApp(MayanAppConfig):
Group._meta.verbose_name = _('Group')
Group._meta.verbose_name_plural = _('Groups')
Group.add_to_class(
name='get_users', value=method_group_get_users
)
Group.add_to_class(
name='users_add', value=method_group_users_add
)
Group.add_to_class(
name='users_remove', value=method_group_users_remove
)
Group.add_to_class(name='save', value=get_method_group_save())
MetadataLookup(
@@ -161,10 +172,20 @@ class UserManagementApp(MayanAppConfig):
User._meta.ordering = ('pk',)
User._meta.verbose_name = _('User')
User._meta.verbose_name_plural = _('Users')
User._meta.ordering = ('last_name', 'first_name')
User.add_to_class(
name='get_absolute_url', value=method_user_get_absolute_url
)
User.add_to_class(
name='get_groups', value=method_user_get_groups
)
User.add_to_class(
name='groups_add', value=method_user_groups_add
)
User.add_to_class(
name='groups_remove', value=method_user_groups_remove
)
User.add_to_class(name='save', value=get_method_user_save())
menu_list_facet.bind_links(

View File

@@ -9,6 +9,8 @@ from .events import (
event_group_created, event_group_edited, event_user_created,
event_user_edited
)
from .permissions import permission_group_view, permission_user_view
from .querysets import get_user_queryset
def get_method_group_save():
@@ -33,12 +35,82 @@ def get_method_group_save():
return method_group_save
def method_group_get_users(self, user, permission=permission_user_view):
AccessControlList = apps.get_model(
app_label='acls', model_name='AccessControlList'
)
return AccessControlList.objects.filter_by_access(
permission=permission, queryset=get_user_queryset().filter(
id__in=self.user_set.all()
), user=user
)
def method_group_users_add(self, queryset, _user):
with transaction.atomic():
event_group_edited.commit(
actor=_user, target=self
)
for user in queryset:
self.user_set.add(user)
event_user_edited.commit(
actor=_user, target=user
)
def method_group_users_remove(self, queryset, _user):
with transaction.atomic():
event_group_edited.commit(
actor=_user, target=self
)
for user in queryset:
self.user_set.remove(user)
event_user_edited.commit(
actor=_user, target=user
)
def method_user_get_absolute_url(self):
return reverse(
viewname='user_management:user_details', kwargs={'pk': self.pk}
)
def method_user_get_groups(self, user, permission=permission_group_view):
AccessControlList = apps.get_model(
app_label='acls', model_name='AccessControlList'
)
return AccessControlList.objects.filter_by_access(
permission=permission, queryset=self.groups.all(), user=user
)
def method_user_groups_add(self, queryset, _user):
with transaction.atomic():
event_user_edited.commit(
actor=_user, target=self
)
for group in queryset:
self.groups.add(group)
event_group_edited.commit(
actor=_user, target=group
)
def method_user_groups_remove(self, queryset, _user):
with transaction.atomic():
event_user_edited.commit(
actor=_user, target=self
)
for group in queryset:
self.groups.remove(group)
event_group_edited.commit(
actor=_user, target=group
)
def get_method_user_save():
user_save_original = get_user_model().save

View File

@@ -115,7 +115,7 @@ class GroupViewsTestCase(GroupTestMixin, GroupViewTestMixin, UserTestMixin, Gene
self.test_user.groups.add(self.test_group)
response = self._request_test_group_members_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_group_members_view_with_group_access(self):
self._create_test_user()
@@ -141,7 +141,7 @@ class GroupViewsTestCase(GroupTestMixin, GroupViewTestMixin, UserTestMixin, Gene
response = self._request_test_group_members_view()
self.assertNotContains(
response=response, text=self.test_group.name, status_code=403
response=response, text=self.test_group.name, status_code=404
)
def test_group_members_view_with_full_access(self):
@@ -311,7 +311,7 @@ class UserGroupViewTestCase(GroupTestMixin, UserTestMixin, UserViewTestMixin, Ge
self.test_user.groups.add(self.test_group)
response = self._request_test_user_groups_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_user_groups_view_with_group_access(self):
self._create_test_user()
@@ -323,7 +323,7 @@ class UserGroupViewTestCase(GroupTestMixin, UserTestMixin, UserViewTestMixin, Ge
response = self._request_test_user_groups_view()
self.assertNotContains(
response=response, text=self.test_user.username, status_code=403
response=response, text=self.test_user.username, status_code=404
)
def test_user_groups_view_with_user_access(self):

View File

@@ -4,7 +4,6 @@ from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import SetPasswordForm
from django.contrib.auth.models import Group
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
@@ -12,12 +11,11 @@ from django.template import RequestContext
from django.urls import reverse, reverse_lazy
from django.utils.translation import ungettext, ugettext_lazy as _
from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.generics import AddRemoveView
from mayan.apps.common.views import (
AssignRemoveView, MultipleObjectConfirmActionView,
MultipleObjectFormActionView, SingleObjectCreateView,
SingleObjectDeleteView, SingleObjectDetailView, SingleObjectEditView,
SingleObjectListView
MultipleObjectConfirmActionView, MultipleObjectFormActionView,
SingleObjectCreateView, SingleObjectDeleteView, SingleObjectDetailView,
SingleObjectEditView, SingleObjectListView
)
from .forms import UserForm
@@ -28,6 +26,7 @@ from .permissions import (
permission_group_view, permission_user_create, permission_user_delete,
permission_user_edit, permission_user_view
)
from .querysets import get_user_queryset
class CurrentUserDetailsView(SingleObjectDetailView):
@@ -126,62 +125,31 @@ class GroupDeleteView(SingleObjectDeleteView):
}
class GroupUsersView(AssignRemoveView):
decode_content_type = True
left_list_title = _('Available users')
right_list_title = _('Users in group')
object_permission = permission_group_edit
class GroupUsersView(AddRemoveView):
action_add_method = 'users_add'
action_remove_method = 'users_remove'
main_object_model = Group
main_object_permission = permission_group_edit
main_object_pk_url_kwarg = 'pk'
secondary_object_permission = permission_user_edit
secondary_object_source_queryset = get_user_queryset()
list_available_title = _('Available users')
list_added_title = _('Group users')
@staticmethod
def generate_choices(choices):
results = []
for choice in choices:
ct = ContentType.objects.get_for_model(choice)
label = choice.get_full_name() if choice.get_full_name() else choice
results.append(('%s,%s' % (ct.model, choice.pk), '%s' % (label)))
# Sort results by the label not the key value
return sorted(results, key=lambda x: x[1])
def add(self, item):
self.get_object().user_set.add(item)
def get_actions_extra_kwargs(self):
return {'_user': self.request.user}
def get_extra_context(self):
return {
'object': self.get_object(),
'title': _('Users of group: %s') % self.get_object()
'object': self.main_object,
'title': _('Users of group: %s') % self.main_object,
}
def get_object(self):
return get_object_or_404(klass=Group, pk=self.kwargs['pk'])
def get_choices_queryset(self):
return AccessControlList.objects.filter_by_access(
permission=permission_user_edit,
queryset=get_user_model().objects.exclude(
is_staff=True
).exclude(is_superuser=True),
user=self.request.user
def get_list_added_queryset(self):
return self.main_object.get_users(
permission=permission_user_edit, user=self.request.user
)
def left_list(self):
return GroupUsersView.generate_choices(
self.get_choices_queryset().exclude(
groups=self.get_object()
)
)
def right_list(self):
return GroupUsersView.generate_choices(
self.get_choices_queryset().filter(
pk__in=self.get_object().user_set.all()
)
)
def remove(self, item):
self.get_object().user_set.remove(item)
class UserCreateView(SingleObjectCreateView):
extra_context = {
@@ -199,16 +167,13 @@ class UserCreateView(SingleObjectCreateView):
)
)
def get_save_extra_data(self):
return {'_user': self.request.user}
class UserDeleteView(MultipleObjectConfirmActionView):
object_permission = permission_user_delete
queryset = get_user_model().objects.filter(
is_superuser=False, is_staff=False
)
queryset = get_user_queryset()
success_message = _('User delete request performed on %(count)d user')
success_message_plural = _(
'User delete request performed on %(count)d users'
@@ -267,9 +232,7 @@ class UserDetailsView(SingleObjectDetailView):
)
object_permission = permission_user_view
pk_url_kwarg = 'pk'
queryset = get_user_model().objects.filter(
is_superuser=False, is_staff=False
)
queryset = get_user_queryset()
def get_extra_context(self, **kwargs):
return {
@@ -284,9 +247,7 @@ class UserEditView(SingleObjectEditView):
post_action_redirect = reverse_lazy(
viewname='user_management:user_list'
)
queryset = get_user_model().objects.filter(
is_superuser=False, is_staff=False
)
queryset = get_user_queryset()
def get_extra_context(self):
return {
@@ -298,47 +259,31 @@ class UserEditView(SingleObjectEditView):
return {'_user': self.request.user}
class UserGroupsView(AssignRemoveView):
decode_content_type = True
left_list_title = _('Available groups')
right_list_title = _('Groups joined')
object_permission = permission_user_edit
class UserGroupsView(AddRemoveView):
action_add_method = 'groups_add'
action_remove_method = 'groups_remove'
main_object_permission = permission_user_edit
main_object_source_queryset = get_user_queryset()
main_object_pk_url_kwarg = 'pk'
secondary_object_model = Group
secondary_object_permission = permission_group_edit
list_available_title = _('Available groups')
list_added_title = _('User groups')
def add(self, item):
item.user_set.add(self.get_object())
def get_actions_extra_kwargs(self):
return {'_user': self.request.user}
def get_extra_context(self):
return {
'object': self.get_object(),
'title': _('Groups of user: %s') % self.get_object()
'object': self.main_object,
'title': _('Groups of user: %s') % self.main_object,
}
def get_object(self):
return get_object_or_404(
klass=get_user_model().objects.filter(
is_superuser=False, is_staff=False
), pk=self.kwargs['pk']
)
def get_choices_queryset(self):
return AccessControlList.objects.filter_by_access(
queryset=Group.objects.filter(user=self.get_object()),
def get_list_added_queryset(self):
return self.main_object.get_groups(
permission=permission_group_edit, user=self.request.user
)
def left_list(self):
return AssignRemoveView.generate_choices(
self.get_choices_queryset().exclude(user=self.get_object())
)
def right_list(self):
return AssignRemoveView.generate_choices(
self.get_choices_queryset().filter(user=self.get_object())
)
def remove(self, item):
item.user_set.remove(self.get_object())
class UserListView(SingleObjectListView):
object_permission = permission_user_view
@@ -360,9 +305,7 @@ class UserListView(SingleObjectListView):
}
def get_object_list(self):
return get_user_model().objects.exclude(
is_superuser=True
).exclude(is_staff=True).order_by('last_name', 'first_name')
return get_user_queryset()
class UserOptionsEditView(SingleObjectEditView):
@@ -385,9 +328,7 @@ class UserOptionsEditView(SingleObjectEditView):
def get_user(self):
return get_object_or_404(
klass=get_user_model().objects.filter(
is_superuser=False, is_staff=False
), pk=self.kwargs['pk']
klass=get_user_queryset(), pk=self.kwargs['pk']
)