users: Soften assumptions that all bots have owners.

Imported Slack bots currently do not have owners (#23145).  Soften the
deactivation codepath to allow them to be successfully deactivated
despite this.

Co-authored-by: Mateusz Mandera <mateusz.mandera@zulip.com>
This commit is contained in:
Alex Vandiver 2024-08-20 21:15:19 +00:00 committed by Tim Abbott
parent 7ebeffbcdc
commit 989d425023
2 changed files with 54 additions and 5 deletions

View File

@ -1128,12 +1128,14 @@ def bot_owner_user_ids(user_profile: UserProfile) -> set[int]:
user_profile.default_events_register_stream
and user_profile.default_events_register_stream.invite_only
)
assert user_profile.bot_owner_id is not None
if is_private_bot:
return {user_profile.bot_owner_id}
if user_profile.bot_owner_id is not None:
return {user_profile.bot_owner_id}
return set()
else:
users = {user.id for user in user_profile.realm.get_human_admin_users()}
users.add(user_profile.bot_owner_id)
if user_profile.bot_owner_id is not None:
users.add(user_profile.bot_owner_id)
return users

View File

@ -8,7 +8,7 @@ from django.core import mail
from django.test import override_settings
from zulip_bots.custom_exceptions import ConfigValidationError
from zerver.actions.bots import do_change_bot_owner
from zerver.actions.bots import do_change_bot_owner, do_change_default_sending_stream
from zerver.actions.realm_settings import do_set_realm_user_default_setting
from zerver.actions.streams import do_change_stream_permission
from zerver.actions.users import do_change_can_create_users, do_change_user_role, do_deactivate_user
@ -17,11 +17,12 @@ from zerver.lib.bot_lib import get_bot_handler
from zerver.lib.integrations import EMBEDDED_BOTS, WebhookIntegration
from zerver.lib.test_classes import UploadSerializeMixin, ZulipTestCase
from zerver.lib.test_helpers import avatar_disk_path, get_test_image_file
from zerver.lib.utils import assert_is_not_none
from zerver.models import RealmUserDefault, Service, Subscription, UserProfile
from zerver.models.bots import get_bot_services
from zerver.models.realms import BotCreationPolicyEnum, get_realm
from zerver.models.streams import get_stream
from zerver.models.users import get_user, is_cross_realm_bot_email
from zerver.models.users import bot_owner_user_ids, get_user, is_cross_realm_bot_email
# A test validator
@ -590,6 +591,32 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
self.assert_json_error(result, "No such bot")
self.assert_num_bots_equal(1)
def test_deactivate_bot_with_no_owners(self) -> None:
iago = self.example_user("iago")
self.login("iago")
self.create_bot()
self.assert_num_bots_equal(1)
# Set up the bot to be a private bot, as otherwise realm admins
# are used as default owners in the absence of .bot_owner_id.
stream = get_stream("Denmark", get_realm("zulip"))
do_change_stream_permission(
stream,
invite_only=True,
history_public_to_subscribers=False,
is_web_public=False,
acting_user=iago,
)
new_bot = assert_is_not_none(UserProfile.objects.last())
do_change_default_sending_stream(new_bot, stream, acting_user=iago)
new_bot.bot_owner_id = None
new_bot.save()
result = self.client_delete(f"/json/bots/{new_bot.id}")
self.assert_json_success(result)
self.assert_num_bots_equal(0)
def test_deactivate_bot_with_owner_deactivation(self) -> None:
user = self.example_user("hamlet")
self.login_user(user)
@ -1833,6 +1860,26 @@ class BotTest(ZulipTestCase, UploadSerializeMixin):
self.assertTrue(is_cross_realm_bot_email("random-bot@zulip.com"))
self.assertFalse(is_cross_realm_bot_email("notification-bot@zulip.com"))
def test_private_bot_empty_bot_owner_user_ids(self) -> None:
hamlet = self.example_user("hamlet")
self.login("hamlet")
self.create_bot()
stream = get_stream("Denmark", get_realm("zulip"))
do_change_stream_permission(
stream,
invite_only=True,
history_public_to_subscribers=False,
is_web_public=False,
acting_user=hamlet,
)
new_bot = assert_is_not_none(UserProfile.objects.last())
do_change_default_sending_stream(new_bot, stream, acting_user=hamlet)
new_bot.bot_owner_id = None
new_bot.save()
self.assertEqual(bot_owner_user_ids(new_bot), set())
@patch("zerver.lib.integrations.WEBHOOK_INTEGRATIONS", stripe_sample_config_options)
def test_create_incoming_webhook_bot_with_service_name_and_with_keys(self) -> None:
self.login("hamlet")