Add user and group events
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -100,6 +100,8 @@
|
||||
* Backport sidebar code.
|
||||
* CSS updates to maximize usable width.
|
||||
* Improve partial navigation error messages and display.
|
||||
* Add user created and user edited events.
|
||||
* Add group created and group edited events.
|
||||
|
||||
3.1.11 (2019-04-XX)
|
||||
===================
|
||||
|
||||
@@ -132,6 +132,8 @@ Other changes
|
||||
* Backport sidebar code.
|
||||
* CSS updates to maximize usable width.
|
||||
* Improve partial navigation error messages and display.
|
||||
* Add user created and user edited events.
|
||||
* Add group created and group edited events.
|
||||
|
||||
Removals
|
||||
--------
|
||||
|
||||
@@ -14,10 +14,18 @@ from mayan.apps.common.menus import (
|
||||
menu_user
|
||||
)
|
||||
from mayan.apps.common.widgets import TwoStateWidget
|
||||
from mayan.apps.events.classes import ModelEventType
|
||||
from mayan.apps.events.links import (
|
||||
link_events_for_object, link_object_event_types_user_subcriptions_list
|
||||
)
|
||||
from mayan.apps.metadata import MetadataLookup
|
||||
from mayan.apps.navigation import SourceColumn
|
||||
from mayan.apps.rest_api.fields import DynamicSerializerField
|
||||
|
||||
from .events import (
|
||||
event_group_created, event_group_edited, event_user_created,
|
||||
event_user_edited
|
||||
)
|
||||
from .handlers import handler_initialize_new_user_options
|
||||
from .links import (
|
||||
link_current_user_details, link_current_user_edit, link_group_create,
|
||||
@@ -28,6 +36,10 @@ from .links import (
|
||||
link_user_set_password, link_user_setup, separator_user_label,
|
||||
text_user_label
|
||||
)
|
||||
from .methods import (
|
||||
get_method_group_save, get_method_user_save, method_user_get_absolute_url
|
||||
)
|
||||
|
||||
from .permissions import (
|
||||
permission_group_delete, permission_group_edit,
|
||||
permission_group_view, permission_user_delete, permission_user_edit,
|
||||
@@ -70,6 +82,13 @@ class UserManagementApp(MayanAppConfig):
|
||||
serializer_class='mayan.apps.user_management.serializers.UserSerializer'
|
||||
)
|
||||
|
||||
# Silence UnorderedObjectListWarning
|
||||
# "Pagination may yield inconsistent result"
|
||||
# TODO: Remove on Django 2.x
|
||||
Group._meta.ordering = ('name',)
|
||||
|
||||
Group.add_to_class(name='save', value=get_method_group_save())
|
||||
|
||||
MetadataLookup(
|
||||
description=_('All the groups.'), name='groups',
|
||||
value=get_groups
|
||||
@@ -78,6 +97,15 @@ class UserManagementApp(MayanAppConfig):
|
||||
description=_('All the users.'), name='users',
|
||||
value=get_users
|
||||
)
|
||||
|
||||
ModelEventType.register(
|
||||
event_types=(event_group_created, event_group_edited), model=Group
|
||||
)
|
||||
|
||||
ModelEventType.register(
|
||||
event_types=(event_user_created, event_user_edited), model=User
|
||||
)
|
||||
|
||||
ModelPermission.register(
|
||||
model=Group, permissions=(
|
||||
permission_acl_edit, permission_acl_view,
|
||||
@@ -115,14 +143,28 @@ class UserManagementApp(MayanAppConfig):
|
||||
).render()
|
||||
)
|
||||
|
||||
# Silence UnorderedObjectListWarning
|
||||
# "Pagination may yield inconsistent result"
|
||||
# TODO: Remove on Django 2.x
|
||||
User._meta.ordering = ('pk',)
|
||||
|
||||
User.add_to_class(
|
||||
name='get_absolute_url', value=method_user_get_absolute_url
|
||||
)
|
||||
User.add_to_class(name='save', value=get_method_user_save())
|
||||
|
||||
menu_list_facet.bind_links(
|
||||
links=(
|
||||
link_acl_list, link_group_members
|
||||
link_acl_list, link_events_for_object,
|
||||
link_object_event_types_user_subcriptions_list,
|
||||
link_group_members,
|
||||
), sources=(Group,)
|
||||
)
|
||||
menu_list_facet.bind_links(
|
||||
links=(
|
||||
link_acl_list, link_user_groups, link_user_set_options
|
||||
link_acl_list, link_events_for_object,
|
||||
link_object_event_types_user_subcriptions_list,
|
||||
link_user_groups, link_user_set_options
|
||||
), sources=(User,)
|
||||
)
|
||||
menu_multi_item.bind_links(
|
||||
|
||||
23
mayan/apps/user_management/events.py
Normal file
23
mayan/apps/user_management/events.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mayan.apps.events import EventTypeNamespace
|
||||
|
||||
namespace = EventTypeNamespace(
|
||||
label=_('User management'), name='user_management'
|
||||
)
|
||||
|
||||
event_group_created = namespace.add_event_type(
|
||||
label=_('Group created'), name='group_created'
|
||||
)
|
||||
event_group_edited = namespace.add_event_type(
|
||||
label=_('Group edited'), name='group_edited'
|
||||
)
|
||||
|
||||
event_user_created = namespace.add_event_type(
|
||||
label=_('User created'), name='user_created'
|
||||
)
|
||||
event_user_edited = namespace.add_event_type(
|
||||
label=_('User edited'), name='user_edited'
|
||||
)
|
||||
60
mayan/apps/user_management/methods.py
Normal file
60
mayan/apps/user_management/methods.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import apps
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import transaction
|
||||
from django.shortcuts import reverse
|
||||
|
||||
from .events import (
|
||||
event_group_created, event_group_edited, event_user_created,
|
||||
event_user_edited
|
||||
)
|
||||
|
||||
|
||||
def get_method_group_save():
|
||||
Group = apps.get_model(app_label='auth', model_name='Group')
|
||||
group_save_original = Group.save
|
||||
|
||||
def method_group_save(self, *args, **kwargs):
|
||||
_user = kwargs.pop('_user', None)
|
||||
|
||||
with transaction.atomic():
|
||||
is_new = not self.pk
|
||||
group_save_original(self, *args, **kwargs)
|
||||
if is_new:
|
||||
event_group_created.commit(
|
||||
actor=_user, target=self
|
||||
)
|
||||
else:
|
||||
event_group_edited.commit(
|
||||
actor=_user, target=self
|
||||
)
|
||||
|
||||
return method_group_save
|
||||
|
||||
|
||||
def method_user_get_absolute_url(self):
|
||||
return reverse(
|
||||
viewname='user_management:user_details', kwargs={'pk': self.pk}
|
||||
)
|
||||
|
||||
|
||||
def get_method_user_save():
|
||||
user_save_original = get_user_model().save
|
||||
|
||||
def method_user_save(self, *args, **kwargs):
|
||||
_user = kwargs.pop('_user', None)
|
||||
|
||||
with transaction.atomic():
|
||||
is_new = not self.pk
|
||||
user_save_original(self, *args, **kwargs)
|
||||
if is_new:
|
||||
event_user_created.commit(
|
||||
actor=_user, target=self
|
||||
)
|
||||
else:
|
||||
event_user_edited.commit(
|
||||
actor=_user, target=self
|
||||
)
|
||||
|
||||
return method_user_save
|
||||
@@ -14,11 +14,15 @@ from .literals import (
|
||||
|
||||
class GroupAPITestMixin(object):
|
||||
def _request_test_group_create_api_view(self):
|
||||
return self.post(
|
||||
result = self.post(
|
||||
viewname='rest_api:group-list', data={
|
||||
'name': TEST_GROUP_NAME
|
||||
}
|
||||
)
|
||||
if 'id' in result.json():
|
||||
self.test_group = Group.objects.get(pk=result.json()['id'])
|
||||
|
||||
return result
|
||||
|
||||
def _request_test_group_delete_api_view(self):
|
||||
return self.delete(
|
||||
|
||||
121
mayan/apps/user_management/tests/test_events.py
Normal file
121
mayan/apps/user_management/tests/test_events.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from actstream.models import Action
|
||||
|
||||
from mayan.apps.common.tests import GenericViewTestCase
|
||||
from mayan.apps.rest_api.tests import BaseAPITestCase
|
||||
|
||||
from ..permissions import (
|
||||
permission_group_create, permission_group_edit, permission_user_create,
|
||||
permission_user_edit
|
||||
)
|
||||
|
||||
from ..events import (
|
||||
event_group_created, event_group_edited, event_user_created,
|
||||
event_user_edited
|
||||
)
|
||||
|
||||
from .mixins import (
|
||||
GroupAPITestMixin, GroupTestMixin, GroupViewTestMixin, UserAPITestMixin,
|
||||
UserTestMixin, UserViewTestMixin
|
||||
)
|
||||
|
||||
|
||||
class GroupEventsTestCase(GroupTestMixin, GroupViewTestMixin, UserTestMixin, GenericViewTestCase):
|
||||
def test_group_create_event(self):
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_permission(
|
||||
permission=permission_group_create
|
||||
)
|
||||
self._request_test_group_create_view()
|
||||
|
||||
self.assertEqual(Action.objects.last().target, self.test_group)
|
||||
self.assertEqual(Action.objects.last().verb, event_group_created.id)
|
||||
|
||||
def test_group_edit_event(self):
|
||||
self._create_test_group()
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_access(
|
||||
obj=self.test_group, permission=permission_group_edit
|
||||
)
|
||||
self._request_test_group_edit_view()
|
||||
|
||||
self.assertEqual(Action.objects.last().target, self.test_group)
|
||||
self.assertEqual(Action.objects.last().verb, event_group_edited.id)
|
||||
|
||||
|
||||
class GroupEventsAPITestCase(GroupAPITestMixin, GroupTestMixin, GroupViewTestMixin, BaseAPITestCase):
|
||||
def test_group_create_event_from_api_view(self):
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_permission(
|
||||
permission=permission_group_create
|
||||
)
|
||||
self._request_test_group_create_api_view()
|
||||
|
||||
self.assertEqual(Action.objects.last().target, self.test_group)
|
||||
self.assertEqual(Action.objects.last().verb, event_group_created.id)
|
||||
|
||||
def test_group_edit_event_from_api_view(self):
|
||||
self._create_test_group()
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_access(
|
||||
obj=self.test_group, permission=permission_group_edit
|
||||
)
|
||||
self._request_test_group_edit_patch_api_view()
|
||||
|
||||
self.assertEqual(Action.objects.last().target, self.test_group)
|
||||
self.assertEqual(Action.objects.last().verb, event_group_edited.id)
|
||||
|
||||
|
||||
class UserEventsTestCase(UserAPITestMixin, UserTestMixin, UserViewTestMixin, GenericViewTestCase):
|
||||
def test_user_create_event_from_view(self):
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_permission(
|
||||
permission=permission_user_create
|
||||
)
|
||||
self._request_test_user_create_view()
|
||||
|
||||
self.assertEqual(Action.objects.last().target, self.test_user)
|
||||
self.assertEqual(Action.objects.last().verb, event_user_created.id)
|
||||
|
||||
def test_user_edit_event_from_view(self):
|
||||
self._create_test_user()
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_access(
|
||||
obj=self.test_user, permission=permission_user_edit
|
||||
)
|
||||
self._request_test_user_edit_view()
|
||||
|
||||
self.assertEqual(Action.objects.last().target, self.test_user)
|
||||
self.assertEqual(Action.objects.last().verb, event_user_edited.id)
|
||||
|
||||
|
||||
class UserEventsAPITestCase(UserAPITestMixin, UserTestMixin, UserViewTestMixin, BaseAPITestCase):
|
||||
def test_user_create_event_from_api_view(self):
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_permission(
|
||||
permission=permission_user_create
|
||||
)
|
||||
self._request_test_user_create_api_view()
|
||||
|
||||
self.assertEqual(Action.objects.last().target, self.test_user)
|
||||
self.assertEqual(Action.objects.last().verb, event_user_created.id)
|
||||
|
||||
def test_user_edit_event_from_api_view(self):
|
||||
self._create_test_user()
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_access(
|
||||
obj=self.test_user, permission=permission_user_edit
|
||||
)
|
||||
self._request_test_user_edit_patch_api_view()
|
||||
|
||||
self.assertEqual(Action.objects.last().target, self.test_user)
|
||||
self.assertEqual(Action.objects.last().verb, event_user_edited.id)
|
||||
Reference in New Issue
Block a user