diff --git a/engine/apps/api/views/auth.py b/engine/apps/api/views/auth.py index 2282c50e..582918b6 100644 --- a/engine/apps/api/views/auth.py +++ b/engine/apps/api/views/auth.py @@ -1,6 +1,7 @@ import logging from urllib.parse import urljoin +from django.conf import settings from django.contrib.auth import REDIRECT_FIELD_NAME from django.http import HttpResponseRedirect from django.views.decorators.cache import never_cache @@ -25,6 +26,11 @@ def overridden_login_slack_auth(request, backend): # We can't just redirect frontend here because we need to make a API call and pass tokens to this view from JS. # So frontend can't follow our redirect. # So wrapping and returning URL to redirect as a string. + if settings.SLACK_INTEGRATION_MAINTENANCE_ENABLED: + return Response( + "Grafana OnCall is temporary unable to connect your slack account or install OnCall to your slack workspace", + status=400, + ) url_to_redirect_to = do_auth(request.backend, redirect_name=REDIRECT_FIELD_NAME).url return Response(url_to_redirect_to, 200) diff --git a/engine/apps/slack/views.py b/engine/apps/slack/views.py index 3d91d01b..8b016271 100644 --- a/engine/apps/slack/views.py +++ b/engine/apps/slack/views.py @@ -540,20 +540,25 @@ class ResetSlackView(APIView): } def post(self, request): - organization = request.auth.organization - slack_team_identity = organization.slack_team_identity - if slack_team_identity is not None: - clean_slack_integration_leftovers.apply_async((organization.pk,)) - if settings.FEATURE_MULTIREGION_ENABLED: - delete_slack_connector_async.apply_async((slack_team_identity.slack_id,)) - write_chatops_insight_log( - author=request.user, - event_name=ChatOpsEvent.WORKSPACE_DISCONNECTED, - chatops_type=ChatOpsType.SLACK, + if settings.SLACK_INTEGRATION_MAINTENANCE_ENABLED: + response = Response( + "Grafana OnCall is temporary unable to connect your slack account or install OnCall to your slack workspace", + status=400, ) - unpopulate_slack_user_identities(organization.pk, True) - response = Response(status=200) else: - response = Response(status=400) - + organization = request.auth.organization + slack_team_identity = organization.slack_team_identity + if slack_team_identity is not None: + clean_slack_integration_leftovers.apply_async((organization.pk,)) + if settings.FEATURE_MULTIREGION_ENABLED: + delete_slack_connector_async.apply_async((slack_team_identity.slack_id,)) + write_chatops_insight_log( + author=request.user, + event_name=ChatOpsEvent.WORKSPACE_DISCONNECTED, + chatops_type=ChatOpsType.SLACK, + ) + unpopulate_slack_user_identities(organization.pk, True) + response = Response(status=200) + else: + response = Response(status=400) return response diff --git a/engine/settings/base.py b/engine/settings/base.py index 68c36f2e..c647fb51 100644 --- a/engine/settings/base.py +++ b/engine/settings/base.py @@ -517,6 +517,9 @@ SLACK_CLIENT_OAUTH_SECRET = os.environ.get("SLACK_CLIENT_OAUTH_SECRET") SLACK_SLASH_COMMAND_NAME = os.environ.get("SLACK_SLASH_COMMAND_NAME", "/oncall") SLACK_DIRECT_PAGING_SLASH_COMMAND = os.environ.get("SLACK_DIRECT_PAGING_SLASH_COMMAND", "/escalate") +# Controls if slack integration can be installed/uninstalled. +SLACK_INTEGRATION_MAINTENANCE_ENABLED = os.environ.get("SLACK_INTEGRATION_MAINTENANCE_ENABLED", False) + SOCIAL_AUTH_SLACK_LOGIN_KEY = SLACK_CLIENT_OAUTH_ID SOCIAL_AUTH_SLACK_LOGIN_SECRET = SLACK_CLIENT_OAUTH_SECRET diff --git a/grafana-plugin/src/pages/settings/tabs/ChatOps/tabs/SlackSettings/SlackSettings.tsx b/grafana-plugin/src/pages/settings/tabs/ChatOps/tabs/SlackSettings/SlackSettings.tsx index 2c597808..3bad354e 100644 --- a/grafana-plugin/src/pages/settings/tabs/ChatOps/tabs/SlackSettings/SlackSettings.tsx +++ b/grafana-plugin/src/pages/settings/tabs/ChatOps/tabs/SlackSettings/SlackSettings.tsx @@ -17,6 +17,7 @@ import { SlackChannel } from 'models/slack_channel/slack_channel.types'; import { AppFeature } from 'state/features'; import { WithStoreProps } from 'state/types'; import { withMobXProviderContext } from 'state/withStore'; +import { showApiError } from 'utils'; import { UserActions } from 'utils/authorization'; import { DOCS_SLACK_SETUP } from 'utils/consts'; @@ -49,7 +50,7 @@ class SlackSettings extends Component { handleOpenSlackInstructions = () => { const { store } = this.props; - store.slackStore.installSlackIntegration(); + store.slackStore.installSlackIntegration().catch(showApiError); }; update = () => { @@ -213,9 +214,12 @@ class SlackSettings extends Component { removeSlackIntegration = () => { const { store } = this.props; - store.slackStore.removeSlackIntegration().then(() => { - store.teamStore.loadCurrentTeam(); - }); + store.slackStore + .removeSlackIntegration() + .then(() => { + store.teamStore.loadCurrentTeam(); + }) + .catch(showApiError); }; getSlackSettingsChangeHandler = (field: string) => {