def test_update_group(self, logger_mock): with self.subTest("Successful"): self.sync_service.update_group( "new_group", GSuiteSyncService.GroupData( "new_group", "some description", False, ["alias2"], [f"test2@{settings.GSUITE_DOMAIN}"], ), ) self.directory_api.groups().update.assert_called_once_with( body={ "email": f"new_group@{settings.GSUITE_DOMAIN}", "name": "new_group", "description": "some description", }, groupKey=f"new_group@{settings.GSUITE_DOMAIN}", ) self.settings_api.groups().update.assert_called_once_with( groupUniqueId=f"new_group@{settings.GSUITE_DOMAIN}", body=self.sync_service._group_settings(False), ) self.directory_api.members().list.assert_called() self.directory_api.groups().aliases().list.assert_called() self.settings_api.reset_mock() self.directory_api.reset_mock() with self.subTest("Failure"): self.directory_api.groups().update( ).execute.side_effect = HttpError(Response({"status": 500}), bytes()) self.sync_service.update_group( "new_group", GSuiteSyncService.GroupData( "new_group", "some description", False, ["alias2"], [f"test2@{settings.GSUITE_DOMAIN}"], ), ) self.directory_api.members().list.assert_not_called() self.directory_api.groups().aliases().list.assert_not_called() logger_mock.error.assert_called_once_with( "Could not update list %s: %s", "new_group", bytes())
def test_mailinglist_to_group(self): group = GSuiteSyncService.mailinglist_to_group(self.mailinglist) self.assertEqual( group, GSuiteSyncService.GroupData( "new_group", "some description", False, ["alias2"], [f"test2@{settings.GSUITE_DOMAIN}"], ), )
def pre_mailinglist_save(instance, **kwargs): sync_service = GSuiteSyncService() group = sync_service.mailinglist_to_group(instance) old_list = MailingList.objects.filter(pk=instance.pk).first() try: if old_list is None: sync_service.create_group(group) else: sync_service.update_group(old_list.name, group) except HttpError: # Cannot do direct create or update, do full sync for list sync_service.sync_mailinglists([group])
def pre_mailinglist_save(instance, **kwargs): if settings.GSUITE_ADMIN_CREDENTIALS == {}: logger.warning( "Cannot sync mailinglists because there are no GSuite credentials available" ) return sync_service = GSuiteSyncService() group = sync_service.mailinglist_to_group(instance) old_list = MailingList.objects.filter(pk=instance.pk).first() try: if old_list is None: sync_service.create_group(group) else: sync_service.update_group(old_list.name, group) except HttpError: # Cannot do direct create or update, do full sync for list sync_service.sync_mailinglists([group])
def test_automatic_to_group(self): group = GSuiteSyncService._automatic_to_group({ "moderated": False, "name": "new_group", "description": "some description", "aliases": ["alias1"], "addresses": [f"test1@{settings.GSUITE_DOMAIN}"], }) self.assertEqual( group, GSuiteSyncService.GroupData( "new_group", "some description", False, ["alias1"], [f"test1@{settings.GSUITE_DOMAIN}"], ), )
def setUpTestData(cls): cls.settings_api = MagicMock() cls.directory_api = MagicMock() cls.sync_service = GSuiteSyncService(cls.settings_api, cls.directory_api) cls.mailinglist = MailingList.objects.create( name="new_group", description="some description", moderated=False) ListAlias.objects.create(mailinglist=cls.mailinglist, alias="alias2") VerbatimAddress.objects.create( mailinglist=cls.mailinglist, address=f"test2@{settings.GSUITE_DOMAIN}")
def handle(self, *args, **options): """Sync all mailing lists""" sync_service = GSuiteSyncService() sync_service.sync_mailinglists()
def test_sync_mailinglists(self, logger_mock): original_create = self.sync_service.create_group original_update = self.sync_service.update_group original_delete = self.sync_service.delete_group self.sync_service.create_group = MagicMock() self.sync_service.update_group = MagicMock() self.sync_service.delete_group = MagicMock() with self.subTest("Error getting existing list"): self.directory_api.groups().list().execute.side_effect = HttpError( Response({"status": 500}), bytes()) self.sync_service.sync_mailinglists() logger_mock.error.assert_called_once_with( "Could not get the existing groups: %s", bytes()) self.directory_api.reset_mock() with self.subTest("Successful"): existing_groups = [ { "name": "deleteme", "directMembersCount": "3" }, { "name": "already_synced", "directMembersCount": "2" }, { "name": "ignore", "directMembersCount": "0" }, ] self.directory_api.groups().list().execute.side_effect = [ { "groups": existing_groups[:1], "nextPageToken": "some_token" }, { "groups": existing_groups[1:] }, ] self.sync_service.sync_mailinglists([ GSuiteSyncService.GroupData(name="syncme", addresses=["someone"]), GSuiteSyncService.GroupData(name="already_synced", addresses=["someone"]), GSuiteSyncService.GroupData(name="ignore2", addresses=[]), ]) self.sync_service.create_group.assert_called_with( GSuiteSyncService.GroupData(name="syncme", addresses=["someone"])) self.sync_service.update_group.assert_called_with( "already_synced", GSuiteSyncService.GroupData(name="already_synced", addresses=["someone"]), ) self.sync_service.delete_group.assert_called_with("deleteme") self.sync_service.create_group.assert_not_called_with( GSuiteSyncService.GroupData(name="ignore2", addresses=[])) self.sync_service.update_group.assert_not_called_with( "ignore2", GSuiteSyncService.GroupData(name="ignore2", addresses=[])) self.sync_service.delete_group.assert_not_called_with("ignore2") self.sync_service.create_group = original_create self.sync_service.update_group = original_update self.sync_service.delete_group = original_delete
def test_update_group_members(self, logger_mock): with self.subTest("Error getting existing list"): self.directory_api.members( ).list().execute.side_effect = HttpError(Response({"status": 500}), bytes()) self.sync_service._update_group_members( GSuiteSyncService.GroupData(name="update_group")) logger_mock.error.assert_called_once_with( "Could not obtain list member data: %s", bytes()) self.directory_api.reset_mock() with self.subTest("Successful with some errors"): group_data = GSuiteSyncService.GroupData( name="update_group", addresses=[ "*****@*****.**", "*****@*****.**", "*****@*****.**", ], ) existing_aliases = [ { "email": "*****@*****.**", "role": "MEMBER" }, { "email": "*****@*****.**", "role": "MEMBER" }, { "email": "*****@*****.**", "role": "MEMBER" }, { "email": "*****@*****.**", "role": "MANAGER" }, ] self.directory_api.members().list().execute.side_effect = [ { "members": existing_aliases[:1], "nextPageToken": "some_token" }, { "members": existing_aliases[1:] }, ] self.directory_api.members().insert().execute.side_effect = [ "success", HttpError(Response({"status": 500}), bytes()), ] self.directory_api.members().delete().execute.side_effect = [ "success", HttpError(Response({"status": 500}), bytes()), ] self.sync_service._update_group_members(group_data) self.directory_api.members().insert.assert_any_call( groupKey=f"update_group@{settings.GSUITE_DOMAIN}", body={ "email": "*****@*****.**", "role": "MEMBER" }, ) self.directory_api.members().delete.assert_any_call( groupKey=f"update_group@{settings.GSUITE_DOMAIN}", memberKey="*****@*****.**", ) self.directory_api.members().delete.assert_not_called_with( groupKey=f"update_group@{settings.GSUITE_DOMAIN}", memberKey="*****@*****.**", ) logger_mock.error.assert_any_call( "Could not insert list member %s in %s: %s", "*****@*****.**", "update_group", bytes(), ) logger_mock.error.assert_any_call( "Could not remove list member %s from %s: %s", "*****@*****.**", "update_group", bytes(), )
def test_update_group_aliases(self, logger_mock): with self.subTest("Error getting existing list"): self.directory_api.groups().aliases( ).list().execute.side_effect = HttpError(Response({"status": 500}), bytes()) self.sync_service._update_group_aliases( GSuiteSyncService.GroupData(name="update_group")) logger_mock.error.assert_called_once_with( "Could not obtain existing aliases for list %s: %s", "update_group", bytes(), ) self.directory_api.reset_mock() with self.subTest("Successful with some errors"): group_data = GSuiteSyncService.GroupData( name="update_group", aliases=["not_synced", "not_synced_error", "already_synced"], ) existing_aliases = [ { "alias": f"deleteme@{settings.GSUITE_DOMAIN}" }, { "alias": f"deleteme_error@{settings.GSUITE_DOMAIN}" }, { "alias": f"already_synced@{settings.GSUITE_DOMAIN}" }, ] self.directory_api.groups().aliases().list( ).execute.side_effect = [{ "aliases": existing_aliases }] self.directory_api.groups().aliases().insert( ).execute.side_effect = [ "success", HttpError(Response({"status": 500}), bytes()), ] self.directory_api.groups().aliases().delete( ).execute.side_effect = [ "success", HttpError(Response({"status": 500}), bytes()), ] self.sync_service._update_group_aliases(group_data) self.directory_api.groups().aliases().insert.assert_any_call( groupKey=f"update_group@{settings.GSUITE_DOMAIN}", body={"alias": f"not_synced@{settings.GSUITE_DOMAIN}"}, ) self.directory_api.groups().aliases().delete.assert_any_call( groupKey=f"update_group@{settings.GSUITE_DOMAIN}", alias=f"deleteme@{settings.GSUITE_DOMAIN}", ) logger_mock.error.assert_any_call( "Could not insert alias %s for list %s: %s", f"not_synced_error@{settings.GSUITE_DOMAIN}", "update_group", bytes(), ) logger_mock.error.assert_any_call( "Could not remove alias %s for list %s: %s", f"deleteme_error@{settings.GSUITE_DOMAIN}", "update_group", bytes(), )