# What this PR does
Introduces a new class,
`apps.grafana_plugin.ui_url_builder.UIURLBuilder`, which is responsible
for... building UI URLs (😄). The class mainly does two things:
- it will decide if the URL should point to `grafana-oncall-app` or
`grafana-irm-app` based on the value of
`organization.is_grafana_irm_enabled` (**NOTE**: this value isn't yet
being set + defaults to `False`; logic for setting this value will be
done in a subsequent PR)
- Adds `enum`s, `OnCallPage` and `IncidentPage` to DRYify hardcoded UI
URLs (in case we decide to change these slightly in the near future)
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
94 lines
4 KiB
Python
94 lines
4 KiB
Python
import logging
|
|
|
|
from django.conf import settings
|
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
|
from django.http import HttpResponse
|
|
from rest_framework import status
|
|
|
|
from apps.chatops_proxy.utils import can_link_slack_team, link_slack_team
|
|
from apps.grafana_plugin.ui_url_builder import UIURLBuilder
|
|
from apps.slack.installation import SlackInstallationExc, install_slack_integration
|
|
from apps.social_auth.backends import SLACK_INSTALLATION_BACKEND
|
|
from apps.social_auth.exceptions import InstallMultiRegionSlackException
|
|
from common.constants.slack_auth import SLACK_AUTH_SLACK_USER_ALREADY_CONNECTED_ERROR, SLACK_AUTH_WRONG_WORKSPACE_ERROR
|
|
from common.insight_log import ChatOpsEvent, ChatOpsTypePlug, write_chatops_insight_log
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def connect_user_to_slack(response, backend, strategy, user, organization, *args, **kwargs):
|
|
from apps.slack.models import SlackUserIdentity
|
|
|
|
# Continue pipeline step only if it was installation
|
|
if backend.name != "slack-login":
|
|
return
|
|
|
|
slack_team_identity = organization.slack_team_identity
|
|
slack_user_id = response["authed_user"]["id"]
|
|
url_builder = UIURLBuilder(organization)
|
|
|
|
if slack_team_identity is None:
|
|
# means that organization doesn't have slack integration, so user cannot connect their account to slack
|
|
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
if slack_team_identity.slack_id != response["team"]["id"]:
|
|
# means that user authed in another slack workspace that is not connected to their organization
|
|
# change redirect url to show user error message and save it in session param
|
|
strategy.session[REDIRECT_FIELD_NAME] = url_builder.user_profile(
|
|
f"?slack_error={SLACK_AUTH_WRONG_WORKSPACE_ERROR}",
|
|
)
|
|
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
if organization.users.filter(slack_user_identity__slack_id=slack_user_id).exists():
|
|
# means that slack user has already been connected to another user in current organization
|
|
strategy.session[REDIRECT_FIELD_NAME] = url_builder.user_profile(
|
|
f"?slack_error={SLACK_AUTH_SLACK_USER_ALREADY_CONNECTED_ERROR}",
|
|
)
|
|
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
# at this point everything is correct and we can create the SlackUserIdentity
|
|
# be sure to clear any pre-existing sessions, in case the user previously enecountered errors we want
|
|
# to be sure to clear these so they do not see them again
|
|
strategy.session.flush()
|
|
|
|
slack_user_identity, _ = SlackUserIdentity.objects.get_or_create(
|
|
slack_id=slack_user_id,
|
|
slack_team_identity=slack_team_identity,
|
|
defaults={
|
|
"cached_slack_email": response["user"]["email"],
|
|
},
|
|
)
|
|
|
|
write_chatops_insight_log(
|
|
author=user,
|
|
event_name=ChatOpsEvent.USER_LINKED,
|
|
chatops_type=ChatOpsTypePlug.SLACK.value,
|
|
linked_user=user.username,
|
|
linked_user_id=user.public_primary_key,
|
|
)
|
|
user.slack_user_identity = slack_user_identity
|
|
user.save(update_fields=["slack_user_identity"])
|
|
|
|
slack_user_identity.update_profile_info()
|
|
|
|
|
|
def populate_slack_identities(response, backend, user, organization, **kwargs):
|
|
# Continue pipeline step only if it was installation
|
|
if backend.name != SLACK_INSTALLATION_BACKEND:
|
|
return
|
|
|
|
slack_team_id = response["team"]["id"]
|
|
if settings.FEATURE_MULTIREGION_ENABLED and not settings.UNIFIED_SLACK_APP_ENABLED:
|
|
can_link = can_link_slack_team(str(organization.uuid), slack_team_id, settings.ONCALL_BACKEND_REGION)
|
|
if not can_link:
|
|
raise InstallMultiRegionSlackException
|
|
try:
|
|
install_slack_integration(organization, user, response)
|
|
except SlackInstallationExc:
|
|
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
|
|
if settings.FEATURE_MULTIREGION_ENABLED and not settings.UNIFIED_SLACK_APP_ENABLED:
|
|
link_slack_team(str(organization.uuid), slack_team_id)
|
|
|
|
|
|
def delete_slack_auth_token(strategy, *args, **kwargs):
|
|
strategy.request.auth.delete()
|