|
| 1 | +import json |
| 2 | +from unittest.mock import call, patch |
| 3 | + |
| 4 | +import pytest |
| 5 | +from django.conf import settings |
| 6 | +from rest_framework import status |
| 7 | +from rest_framework.test import APIClient |
| 8 | + |
| 9 | +from apps.slack.scenarios.scenario_step import PAYLOAD_TYPE_BLOCK_ACTIONS |
| 10 | + |
| 11 | +EVENT_TRIGGER_ID = "5333959822612.4122782784722.4734ff484b2ac4d36a185bb242ee9932" |
| 12 | +WARNING_TEXT = ( |
| 13 | + "OnCall is not able to process this action because one of the following scenarios: \n" |
| 14 | + "1. The Slack chatops integration was disconnected from the instance that the Alert Group belongs " |
| 15 | + "to, BUT the Slack workspace is still connected to another instance as well. In this case, simply log " |
| 16 | + "in to the OnCall web interface and re-install the Slack Integration with this workspace again.\n" |
| 17 | + "2. (Less likely) The Grafana instance belonging to this Alert Group was deleted. In this case the Alert Group is orphaned and cannot be acted upon." |
| 18 | +) |
| 19 | + |
| 20 | +SLACK_TEAM_ID = "T043LP0P2M8" |
| 21 | +SLACK_ACCESS_TOKEN = "asdfasdf" |
| 22 | +SLACK_BOT_ACCESS_TOKEN = "cmncvmnvcnm" |
| 23 | +SLACK_BOT_USER_ID = "mncvnmvcmnvcmncv,,cx," |
| 24 | + |
| 25 | +SLACK_USER_ID = "iurtiurituritu" |
| 26 | + |
| 27 | + |
| 28 | +def _make_request(payload): |
| 29 | + return APIClient().post( |
| 30 | + "/slack/interactive_api_endpoint/", |
| 31 | + format="json", |
| 32 | + data=payload, |
| 33 | + **{ |
| 34 | + "HTTP_X_SLACK_SIGNATURE": "asdfasdf", |
| 35 | + "HTTP_X_SLACK_REQUEST_TIMESTAMP": "xxcxcvx", |
| 36 | + }, |
| 37 | + ) |
| 38 | + |
| 39 | + |
| 40 | +@pytest.fixture |
| 41 | +def slack_team_identity(make_slack_team_identity): |
| 42 | + return make_slack_team_identity( |
| 43 | + slack_id=SLACK_TEAM_ID, |
| 44 | + detected_token_revoked=None, |
| 45 | + access_token=SLACK_ACCESS_TOKEN, |
| 46 | + bot_access_token=SLACK_BOT_ACCESS_TOKEN, |
| 47 | + bot_user_id=SLACK_BOT_USER_ID, |
| 48 | + ) |
| 49 | + |
| 50 | + |
| 51 | +@patch("apps.slack.views.SlackEventApiEndpointView.verify_signature", return_value=True) |
| 52 | +@patch("apps.slack.views.SlackEventApiEndpointView._open_warning_window_if_needed") |
| 53 | +@pytest.mark.django_db |
| 54 | +def test_organization_not_found_scenario_properly_handled( |
| 55 | + mock_open_warning_window_if_needed, |
| 56 | + _mock_verify_signature, |
| 57 | + make_organization, |
| 58 | + make_slack_user_identity, |
| 59 | + slack_team_identity, |
| 60 | +): |
| 61 | + # SCENARIO 1 |
| 62 | + # two orgs connected to same slack workspace, the one belonging to the alert group/slack message |
| 63 | + # is no longer connected to the slack workspace, but another org still is |
| 64 | + make_slack_user_identity(slack_team_identity=slack_team_identity, slack_id=SLACK_USER_ID) |
| 65 | + |
| 66 | + make_organization(slack_team_identity=slack_team_identity) |
| 67 | + org2 = make_organization() |
| 68 | + event_payload_actions = [ |
| 69 | + { |
| 70 | + "value": json.dumps({"organization_id": org2.id}), |
| 71 | + } |
| 72 | + ] |
| 73 | + |
| 74 | + event_payload = { |
| 75 | + "type": PAYLOAD_TYPE_BLOCK_ACTIONS, |
| 76 | + "trigger_id": EVENT_TRIGGER_ID, |
| 77 | + "user": { |
| 78 | + "id": SLACK_USER_ID, |
| 79 | + }, |
| 80 | + "team": { |
| 81 | + "id": SLACK_TEAM_ID, |
| 82 | + }, |
| 83 | + "actions": event_payload_actions, |
| 84 | + } |
| 85 | + |
| 86 | + response = _make_request(event_payload) |
| 87 | + assert response.status_code == status.HTTP_200_OK |
| 88 | + |
| 89 | + # SCENARIO 2 |
| 90 | + # the org that was associated w/ the alert group, has since been deleted |
| 91 | + # and the slack message is now orphaned |
| 92 | + org2.hard_delete() |
| 93 | + |
| 94 | + response = _make_request(event_payload) |
| 95 | + assert response.status_code == status.HTTP_200_OK |
| 96 | + |
| 97 | + mock_call = call(event_payload, slack_team_identity, WARNING_TEXT) |
| 98 | + mock_open_warning_window_if_needed.assert_has_calls([mock_call, mock_call]) |
| 99 | + |
| 100 | + |
| 101 | +@patch("apps.slack.views.SlackEventApiEndpointView.verify_signature", return_value=True) |
| 102 | +@patch("apps.slack.views.SlackEventApiEndpointView._open_warning_window_if_needed") |
| 103 | +@pytest.mark.django_db |
| 104 | +def test_organization_not_found_scenario_doesnt_break_slash_commands( |
| 105 | + mock_open_warning_window_if_needed, |
| 106 | + _mock_verify_signature, |
| 107 | + make_organization, |
| 108 | + make_slack_user_identity, |
| 109 | + slack_team_identity, |
| 110 | +): |
| 111 | + |
| 112 | + make_organization(slack_team_identity=slack_team_identity) |
| 113 | + make_slack_user_identity(slack_team_identity=slack_team_identity, slack_id=SLACK_USER_ID) |
| 114 | + |
| 115 | + response = _make_request( |
| 116 | + { |
| 117 | + "token": "axvnc,mvc,mv,mcvmnxcmnxc", |
| 118 | + "team_id": SLACK_TEAM_ID, |
| 119 | + "team_domain": "testingtest-nim4013", |
| 120 | + "channel_id": "C043HQ70QMB", |
| 121 | + "channel_name": "testy-testing", |
| 122 | + "user_id": "U043HQ3VABF", |
| 123 | + "user_name": "bob.smith", |
| 124 | + "command": settings.SLACK_DIRECT_PAGING_SLASH_COMMAND, |
| 125 | + "text": "potato", |
| 126 | + "api_app_id": "A0909234092340293402934234234234234234", |
| 127 | + "is_enterprise_install": "false", |
| 128 | + "response_url": "https://hooks.slack.com/commands/cvcv/cvcv/cvcv", |
| 129 | + "trigger_id": "asdfasdf.4122782784722.cvcv", |
| 130 | + } |
| 131 | + ) |
| 132 | + |
| 133 | + assert response.status_code == status.HTTP_200_OK |
| 134 | + mock_open_warning_window_if_needed.assert_not_called() |
0 commit comments