diff --git a/CHANGELOG.md b/CHANGELOG.md index 0035ba4f..b57054c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Enable Grafana Alerting V2 feature flag by default - Allow configuration of outgoing webhook timeout via `OUTGOING_WEBHOOK_TIMEOUT` environment variable @kevindw-fluxys ([#3801](https://github.com/grafana/oncall/pull/3801)) +### Fixed + +- Handle alert group does not exist on telegram button press ([#3814](https://github.com/grafana/oncall/pull/3814)) + ## v1.3.98 (2024-02-01) ### Fixed diff --git a/engine/apps/telegram/tests/test_button_update_handler.py b/engine/apps/telegram/tests/test_button_update_handler.py index 657c9e46..f6ca9863 100644 --- a/engine/apps/telegram/tests/test_button_update_handler.py +++ b/engine/apps/telegram/tests/test_button_update_handler.py @@ -54,9 +54,17 @@ def test_get_action_context( Action.SILENCE: [silence_data_with_action_name, silence_data_with_action_code], Action.UNSILENCE: [unsilence_data_with_action_name, unsilence_data_with_action_code], } - action_context = handler._get_action_context(ack_data_with_action_name) for action, data_strings in ACTION_TO_DATA_STR.items(): for data_str in data_strings: action_context = handler._get_action_context(data_str) assert action_context.action.value == action.value + + # not existing alert group + data_strings = [ + f"1234:acknowledge:oncall-uuid{organization.uuid}", + f"1234:5:oncall-uuid{organization.uuid}", + ] + for data_str in data_strings: + action_context = handler._get_action_context(data_str) + assert action_context is None diff --git a/engine/apps/telegram/tests/test_update_handlers.py b/engine/apps/telegram/tests/test_update_handlers.py index d74bcb53..bb8b7994 100644 --- a/engine/apps/telegram/tests/test_update_handlers.py +++ b/engine/apps/telegram/tests/test_update_handlers.py @@ -7,7 +7,7 @@ from telegram import CallbackQuery, Chat, Message, Update, User from apps.telegram.client import TelegramClient from apps.telegram.renderers.keyboard import Action from apps.telegram.updates.update_handlers import ChannelVerificationCodeHandler, StartMessageHandler -from apps.telegram.updates.update_handlers.button_press import ButtonPressHandler +from apps.telegram.updates.update_handlers.button_press import NOT_FOUND_ERROR, ButtonPressHandler from apps.telegram.updates.update_handlers.start_message import START_TEXT from apps.telegram.updates.update_handlers.verification.channel import ( VERIFICATION_FAILED_DISCUSSION_GROUP_ALREADY_REGISTERED, @@ -40,13 +40,13 @@ def generate_channel_verification_code_message(verification_code: str, discussio return update -def generate_button_press_ack_message(chat_id, alert_group) -> Update: +def generate_button_press_ack_message(chat_id, alert_group_pk) -> Update: user = User(id=chat_id, first_name="Test", is_bot=False) callback_query = CallbackQuery( id=0, from_user=user, chat_instance=Chat(id=chat_id, type=Chat.PRIVATE), - data=CallbackQueryFactory.encode_data(alert_group.pk, Action.ACKNOWLEDGE.value), + data=CallbackQueryFactory.encode_data(alert_group_pk, Action.ACKNOWLEDGE.value), ) update = Update(update_id=0, callback_query=callback_query) return update @@ -114,10 +114,31 @@ def test_button_press_handler_gets_user( alert_group = make_alert_group(alert_receive_channel=alert_receive_channel) make_alert(alert_group, "") - update = generate_button_press_ack_message(chat_id, alert_group) + update = generate_button_press_ack_message(chat_id, alert_group.pk) handler = ButtonPressHandler(update=update) handler.process_update() alert_group.refresh_from_db() assert alert_group.acknowledged assert alert_group.acknowledged_by_user == user_2 + + +@pytest.mark.django_db +def test_button_press_handler_non_existing_alert_group( + make_organization, + make_user_for_organization, + make_telegram_user_connector, +): + organization = make_organization() + + chat_id = 123 + user_1 = make_user_for_organization(organization) + make_telegram_user_connector(user_1, telegram_chat_id=chat_id) + + update = generate_button_press_ack_message(chat_id, 1234) + handler = ButtonPressHandler(update=update) + + with patch.object(update.callback_query, "answer") as mock_answer: + handler.process_update() + + mock_answer.assert_called_once_with(NOT_FOUND_ERROR, show_alert=True) diff --git a/engine/apps/telegram/updates/update_handlers/button_press.py b/engine/apps/telegram/updates/update_handlers/button_press.py index 0c8c13f8..3df55e93 100644 --- a/engine/apps/telegram/updates/update_handlers/button_press.py +++ b/engine/apps/telegram/updates/update_handlers/button_press.py @@ -13,6 +13,7 @@ from apps.user_management.models import User logger = logging.getLogger(__name__) +NOT_FOUND_ERROR = "Alert group not found" PERMISSION_DENIED = """You don't have a permission to perform this action! Consider connecting your Telegram account on user settings page ⚙""" @@ -32,6 +33,9 @@ class ButtonPressHandler(UpdateHandler): def process_update(self) -> None: data = self.update.callback_query.data action_context = self._get_action_context(data) + if action_context is None: + self.update.callback_query.answer(NOT_FOUND_ERROR, show_alert=True) + return fn, fn_kwargs = self._map_action_context_to_fn(action_context) user = self._get_user(action_context) @@ -77,7 +81,11 @@ class ButtonPressHandler(UpdateHandler): if alert_group is None: alert_group_pk = args[0] - alert_group = AlertGroup.objects.get(pk=alert_group_pk) + try: + alert_group = AlertGroup.objects.get(pk=alert_group_pk) + except AlertGroup.DoesNotExist: + logger.info(f"Alert group {alert_group_pk} does not exist") + return action_value = args[1] try: