Skip to content

Commit

Permalink
Handle slack uninstall event from chatops-proxy (#4510)
Browse files Browse the repository at this point in the history
  • Loading branch information
Konstantinov-Innokentii authored Jun 14, 2024
1 parent bc1544c commit 6c63f53
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 13 deletions.
38 changes: 35 additions & 3 deletions engine/apps/chatops_proxy/events/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
from abc import ABC, abstractmethod

from apps.chatops_proxy.client import PROVIDER_TYPE_SLACK
from apps.slack.installation import SlackInstallationExc, install_slack_integration
from apps.slack.installation import SlackInstallationExc, install_slack_integration, uninstall_slack_integration
from apps.user_management.models import Organization

from .types import INTEGRATION_INSTALLED_EVENT_TYPE, Event, IntegrationInstalledData
from .types import (
INTEGRATION_INSTALLED_EVENT_TYPE,
INTEGRATION_UNINSTALLED_EVENT_TYPE,
Event,
IntegrationInstalledData,
IntegrationUninstalledData,
)

logger = logging.getLogger(__name__)

Expand All @@ -23,7 +29,7 @@ def handle(cls, event_data: dict) -> None:
pass


class SlackInstallationHandler(Handler):
class SlackInstallHandler(Handler):
@classmethod
def match(cls, event: Event) -> bool:
return (
Expand All @@ -48,3 +54,29 @@ def handle(cls, data: dict) -> None:
f'msg="SlackInstallationHandler: Failed to install Slack integration: %s" org_id={organization.id} stack_id={stack_id}',
e,
)


class SlackUninstallHandler(Handler):
@classmethod
def match(cls, event: Event) -> bool:
return (
event.get("event_type") == INTEGRATION_UNINSTALLED_EVENT_TYPE
and event.get("data", {}).get("provider_type") == PROVIDER_TYPE_SLACK
)

@classmethod
def handle(cls, data: dict) -> None:
data = typing.cast(IntegrationUninstalledData, data)

stack_id = data.get("stack_id")
user_id = data.get("grafana_user_id")

organization = Organization.objects.get(stack_id=stack_id)
user = organization.users.get(user_id=user_id)
try:
uninstall_slack_integration(organization, user)
except SlackInstallationExc as e:
logger.exception(
f'msg="SlackInstallationHandler: Failed to uninstall Slack integration: %s" org_id={organization.id} stack_id={stack_id}',
e,
)
4 changes: 2 additions & 2 deletions engine/apps/chatops_proxy/events/root_handler.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import typing

from .handlers import Handler, SlackInstallationHandler
from .handlers import Handler, SlackInstallHandler, SlackUninstallHandler
from .types import Event

logger = logging.getLogger(__name__)
Expand All @@ -12,7 +12,7 @@ class ChatopsEventsHandler:
ChatopsEventsHandler is a root handler which receives event from Chatops-Proxy and chooses the handler to process it.
"""

HANDLERS: typing.List[typing.Type[Handler]] = [SlackInstallationHandler]
HANDLERS: typing.List[typing.Type[Handler]] = [SlackInstallHandler, SlackUninstallHandler]

def handle(self, event_data: Event) -> bool:
"""
Expand Down
6 changes: 6 additions & 0 deletions engine/apps/chatops_proxy/events/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ class IntegrationInstalledData(typing.TypedDict):
stack_id: int
grafana_user_id: int
payload: dict


class IntegrationUninstalledData(typing.TypedDict):
provider_type: str
stack_id: int
grafana_user_id: int
43 changes: 35 additions & 8 deletions engine/apps/chatops_proxy/tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from django.test import override_settings

from apps.chatops_proxy.events import ChatopsEventsHandler
from apps.chatops_proxy.events.handlers import SlackInstallationHandler
from apps.chatops_proxy.events.handlers import SlackInstallHandler, SlackUninstallHandler
from common.constants.slack_auth import SLACK_OAUTH_ACCESS_RESPONSE

installation_event = {
install_event = {
"event_type": "integration_installed",
"data": {
"provider_type": "slack",
Expand All @@ -17,6 +17,15 @@
},
}

uninstall_event = {
"event_type": "integration_uninstalled",
"data": {
"provider_type": "slack",
"stack_id": "stack_id",
"grafana_user_id": "grafana_user_id",
},
}

unknown_event = {
"event_type": "unknown_event",
"data": {
Expand All @@ -37,7 +46,8 @@
@pytest.mark.parametrize(
"payload,is_handled",
[
(installation_event, True),
(install_event, True),
(uninstall_event, True),
(unknown_event, False),
(invalid_schema_event, False),
],
Expand All @@ -54,13 +64,30 @@ def test_root_event_handler(mock_exec, payload, is_handled):
def test_slack_installation_handler(mock_install_slack_integration, make_organization_and_user):
organization, user = make_organization_and_user()

installation_event["data"].update({"stack_id": organization.stack_id, "grafana_user_id": user.user_id})
install_event["data"].update({"stack_id": organization.stack_id, "grafana_user_id": user.user_id})

h = SlackInstallHandler()

assert h.match(unknown_event) is False
assert h.match(invalid_schema_event) is False

assert h.match(install_event) is True
h.handle(install_event["data"])
assert mock_install_slack_integration.call_args.args == (organization, user, install_event["data"]["payload"])


@patch("apps.chatops_proxy.events.handlers.uninstall_slack_integration", return_value=None)
@pytest.mark.django_db
def test_slack_uninstall_handler(mock_uninstall_slack_integration, make_organization_and_user):
organization, user = make_organization_and_user()

uninstall_event["data"].update({"stack_id": organization.stack_id, "grafana_user_id": user.user_id})

h = SlackInstallationHandler()
h = SlackUninstallHandler()

assert h.match(unknown_event) is False
assert h.match(invalid_schema_event) is False

assert h.match(installation_event) is True
h.handle(installation_event["data"])
assert mock_install_slack_integration.call_args.args == (organization, user, installation_event["data"]["payload"])
assert h.match(uninstall_event) is True
h.handle(uninstall_event["data"])
assert mock_uninstall_slack_integration.call_args.args == (organization, user)

0 comments on commit 6c63f53

Please sign in to comment.