diff --git a/keystone/identity/controllers.py b/keystone/identity/controllers.py index 808bd1e7ea..9e8ba6fcf8 100644 --- a/keystone/identity/controllers.py +++ b/keystone/identity/controllers.py @@ -255,7 +255,8 @@ class UserV3(controller.V3Controller): @controller.protected(callback=_check_user_and_group_protection) def add_user_to_group(self, context, user_id, group_id): - self.identity_api.add_user_to_group(user_id, group_id) + initiator = notifications._get_request_audit_info(context) + self.identity_api.add_user_to_group(user_id, group_id, initiator) @controller.protected(callback=_check_user_and_group_protection) def check_user_in_group(self, context, user_id, group_id): @@ -263,7 +264,8 @@ class UserV3(controller.V3Controller): @controller.protected(callback=_check_user_and_group_protection) def remove_user_from_group(self, context, user_id, group_id): - self.identity_api.remove_user_from_group(user_id, group_id) + initiator = notifications._get_request_audit_info(context) + self.identity_api.remove_user_from_group(user_id, group_id, initiator) @controller.protected() def delete_user(self, context, user_id): diff --git a/keystone/identity/core.py b/keystone/identity/core.py index 4145bf04c1..34490e8126 100644 --- a/keystone/identity/core.py +++ b/keystone/identity/core.py @@ -1061,7 +1061,7 @@ class Manager(manager.Manager): @domains_configured @exception_translated('group') - def add_user_to_group(self, user_id, group_id): + def add_user_to_group(self, user_id, group_id, initiator=None): @exception_translated('user') def get_entity_info_for_user(public_id): return self._get_domain_driver_and_entity_id(public_id) @@ -1081,10 +1081,12 @@ class Manager(manager.Manager): # Invalidate user role assignments cache region, as it may now need to # include role assignments from the specified group to its users assignment.COMPUTED_ASSIGNMENTS_REGION.invalidate() + notifications.Audit.added_to(self._GROUP, group_id, self._USER, + user_id, initiator) @domains_configured @exception_translated('group') - def remove_user_from_group(self, user_id, group_id): + def remove_user_from_group(self, user_id, group_id, initiator=None): @exception_translated('user') def get_entity_info_for_user(public_id): return self._get_domain_driver_and_entity_id(public_id) @@ -1105,6 +1107,8 @@ class Manager(manager.Manager): # Invalidate user role assignments cache region, as it may be caching # role assignments expanded from this group to this user assignment.COMPUTED_ASSIGNMENTS_REGION.invalidate() + notifications.Audit.removed_from(self._GROUP, group_id, self._USER, + user_id, initiator) @notifications.internal(notifications.INVALIDATE_USER_TOKEN_PERSISTENCE) def emit_invalidate_user_token_persistence(self, user_id): diff --git a/keystone/tests/unit/common/test_notifications.py b/keystone/tests/unit/common/test_notifications.py index 38931d4e74..e66ec38b37 100644 --- a/keystone/tests/unit/common/test_notifications.py +++ b/keystone/tests/unit/common/test_notifications.py @@ -722,6 +722,28 @@ class NotificationsForEntities(BaseNotificationTest): # No audit event should have occurred self.assertEqual(0, len(self._audits)) + def test_add_user_to_group(self): + user_ref = unit.new_user_ref(domain_id=self.domain_id) + user_ref = self.identity_api.create_user(user_ref) + group_ref = unit.new_group_ref(domain_id=self.domain_id) + group_ref = self.identity_api.create_group(group_ref) + self.identity_api.add_user_to_group(user_ref['id'], group_ref['id']) + self._assert_last_note(group_ref['id'], UPDATED_OPERATION, 'group', + actor_id=user_ref['id'], actor_type='user', + actor_operation='added') + + def test_remove_user_from_group(self): + user_ref = unit.new_user_ref(domain_id=self.domain_id) + user_ref = self.identity_api.create_user(user_ref) + group_ref = unit.new_group_ref(domain_id=self.domain_id) + group_ref = self.identity_api.create_group(group_ref) + self.identity_api.add_user_to_group(user_ref['id'], group_ref['id']) + self.identity_api.remove_user_from_group(user_ref['id'], + group_ref['id']) + self._assert_last_note(group_ref['id'], UPDATED_OPERATION, 'group', + actor_id=user_ref['id'], actor_type='user', + actor_operation='removed') + class CADFNotificationsForEntities(NotificationsForEntities): diff --git a/releasenotes/notes/notify-on-user-group-membership-8c0136ee0484e255.yaml b/releasenotes/notes/notify-on-user-group-membership-8c0136ee0484e255.yaml new file mode 100644 index 0000000000..d80ab82668 --- /dev/null +++ b/releasenotes/notes/notify-on-user-group-membership-8c0136ee0484e255.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - Support has now been added to send notification events + on user/group membership. When a user is added or removed + from a group a notification will be sent including the + identifiers of both the user and the group.