Handle slack uninstall event from chatops-proxy (#4510)

This commit is contained in:
Innokentii Konstantinov 2024-06-14 15:46:14 +08:00 committed by GitHub
parent bc1544cc01
commit 6c63f53889
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 78 additions and 13 deletions

View file

@ -3,10 +3,16 @@ import typing
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__)
@ -23,7 +29,7 @@ class Handler(ABC):
pass
class SlackInstallationHandler(Handler):
class SlackInstallHandler(Handler):
@classmethod
def match(cls, event: Event) -> bool:
return (
@ -48,3 +54,29 @@ class SlackInstallationHandler(Handler):
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,
)

View file

@ -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__)
@ -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:
"""

View file

@ -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

View file

@ -4,10 +4,10 @@ import pytest
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",
@ -17,6 +17,15 @@ installation_event = {
},
}
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": {
@ -37,7 +46,8 @@ invalid_schema_event = {
@pytest.mark.parametrize(
"payload,is_handled",
[
(installation_event, True),
(install_event, True),
(uninstall_event, True),
(unknown_event, False),
(invalid_schema_event, False),
],
@ -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 = SlackInstallationHandler()
h = SlackInstallHandler()
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(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 = SlackUninstallHandler()
assert h.match(unknown_event) is False
assert h.match(invalid_schema_event) is False
assert h.match(uninstall_event) is True
h.handle(uninstall_event["data"])
assert mock_uninstall_slack_integration.call_args.args == (organization, user)