Introduce org uuid (#947)
* Introduce org uuid * Rename uuid_with_org_id to uuid_with_org_uuid Co-authored-by: Joey Orlando <joey.orlando@grafana.com>
This commit is contained in:
parent
e52af4858c
commit
7341641b3f
15 changed files with 65 additions and 35 deletions
|
|
@ -51,7 +51,7 @@ class AlertGroupTelegramRenderer(AlertGroupBaseRenderer):
|
|||
status_verbose = self.alert_group.get_acknowledge_text()
|
||||
# First line in the invisible link with id of organization.
|
||||
# It is needed to add info about organization to the telegram message for the oncall-gateway.
|
||||
text = f"<a href='{self.alert_group.channel.organization.web_link_with_id}'>‍</a>"
|
||||
text = f"<a href='{self.alert_group.channel.organization.web_link_with_uuid}'>‍</a>"
|
||||
text += f"{status_emoji} #{self.alert_group.inside_organization_number}, {title}\n"
|
||||
text += f"{status_verbose}, alerts: {alerts_count_str}\n"
|
||||
text += f"Source: {self.alert_group.channel.short_name}\n"
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class GetTelegramVerificationCode(APIView):
|
|||
bot_username = telegram_client.api_client.username
|
||||
bot_link = f"https://t.me/{bot_username}"
|
||||
return Response(
|
||||
{"telegram_code": str(new_code.uuid_with_org_id), "bot_link": bot_link}, status=status.HTTP_200_OK
|
||||
{"telegram_code": str(new_code.uuid_with_org_uuid), "bot_link": bot_link}, status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ class UserView(
|
|||
bot_link = f"https://t.me/{bot_username}"
|
||||
|
||||
return Response(
|
||||
{"telegram_code": str(new_code.uuid_with_org_id), "bot_link": bot_link}, status=status.HTTP_200_OK
|
||||
{"telegram_code": str(new_code.uuid_with_org_uuid), "bot_link": bot_link}, status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
@action(detail=True, methods=["post"])
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ class TelegramChannelVerificationCode(models.Model):
|
|||
return self.datetime + timezone.timedelta(days=1) < timezone.now()
|
||||
|
||||
@property
|
||||
def uuid_with_org_id(self) -> str:
|
||||
return f"{self.organization.public_primary_key}_{self.uuid}"
|
||||
def uuid_with_org_uuid(self) -> str:
|
||||
return f"{self.organization.uuid}_{self.uuid}"
|
||||
|
||||
@classmethod
|
||||
def uuid_without_org_id(cls, verification_code: str) -> str:
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ class TelegramVerificationCode(models.Model):
|
|||
return self.datetime + timezone.timedelta(days=1) < timezone.now()
|
||||
|
||||
@property
|
||||
def uuid_with_org_id(self) -> str:
|
||||
return f"{self.user.organization.public_primary_key}_{self.uuid}"
|
||||
def uuid_with_org_uuid(self) -> str:
|
||||
return f"{self.user.organization.uuid}_{self.uuid}"
|
||||
|
||||
@classmethod
|
||||
def uuid_without_org_id(cls, verification_code: str) -> str:
|
||||
|
|
|
|||
|
|
@ -83,10 +83,10 @@ class TelegramKeyboardRenderer:
|
|||
callback_data_args = [self.alert_group.pk, action.value]
|
||||
if action_data is not None:
|
||||
callback_data_args.append(action_data)
|
||||
# Add org id with 'x-oncall-org-id' prefix to callback data.
|
||||
# Add org id with 'oncall-uuid' prefix to callback data.
|
||||
# It's a workaroung to pass org_id to the oncall-gateway while proxying requests.
|
||||
# TODO: switch to json str instead of ':' separated string.
|
||||
callback_data_args.append(f"x-oncall-org-id{self.alert_group.channel.organization.public_primary_key}")
|
||||
callback_data_args.append(f"oncall-uuid{self.alert_group.channel.organization.uuid}")
|
||||
button = InlineKeyboardButton(text=text, callback_data=CallbackQueryFactory.encode_data(*callback_data_args))
|
||||
|
||||
return button
|
||||
|
|
|
|||
|
|
@ -49,27 +49,27 @@ def test_actions_keyboard_alerting(make_organization, make_alert_receive_channel
|
|||
[
|
||||
InlineKeyboardButton(
|
||||
text="Acknowledge",
|
||||
callback_data=f"{alert_group.pk}:acknowledge:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:acknowledge:oncall-uuid{organization.uuid}",
|
||||
)
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="Resolve",
|
||||
callback_data=f"{alert_group.pk}:resolve:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:resolve:oncall-uuid{organization.uuid}",
|
||||
)
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="🔕 forever",
|
||||
callback_data=f"{alert_group.pk}:silence:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:silence:oncall-uuid{organization.uuid}",
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
text="... for 1h",
|
||||
callback_data=f"{alert_group.pk}:silence:3600:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:silence:3600:oncall-uuid{organization.uuid}",
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
text="... for 4h",
|
||||
callback_data=f"{alert_group.pk}:silence:14400:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:silence:14400:oncall-uuid{organization.uuid}",
|
||||
),
|
||||
],
|
||||
]
|
||||
|
|
@ -97,13 +97,13 @@ def test_actions_keyboard_acknowledged(
|
|||
[
|
||||
InlineKeyboardButton(
|
||||
text="Unacknowledge",
|
||||
callback_data=f"{alert_group.pk}:unacknowledge:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:unacknowledge:oncall-uuid{organization.uuid}",
|
||||
)
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="Resolve",
|
||||
callback_data=f"{alert_group.pk}:resolve:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:resolve:oncall-uuid{organization.uuid}",
|
||||
)
|
||||
],
|
||||
]
|
||||
|
|
@ -131,7 +131,7 @@ def test_actions_keyboard_resolved(
|
|||
[
|
||||
InlineKeyboardButton(
|
||||
text="Unresolve",
|
||||
callback_data=f"{alert_group.pk}:unresolve:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:unresolve:oncall-uuid{organization.uuid}",
|
||||
)
|
||||
],
|
||||
]
|
||||
|
|
@ -159,19 +159,19 @@ def test_actions_keyboard_silenced(
|
|||
[
|
||||
InlineKeyboardButton(
|
||||
text="Acknowledge",
|
||||
callback_data=f"{alert_group.pk}:acknowledge:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:acknowledge:oncall-uuid{organization.uuid}",
|
||||
)
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="Resolve",
|
||||
callback_data=f"{alert_group.pk}:resolve:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:resolve:oncall-uuid{organization.uuid}",
|
||||
)
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="Unsilence",
|
||||
callback_data=f"{alert_group.pk}:unsilence:x-oncall-org-id{organization.public_primary_key}",
|
||||
callback_data=f"{alert_group.pk}:unsilence:oncall-uuid{organization.uuid}",
|
||||
)
|
||||
],
|
||||
]
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ def test_alert_group_message(make_organization, make_alert_receive_channel, make
|
|||
renderer = TelegramMessageRenderer(alert_group=alert_group)
|
||||
text = renderer.render_alert_group_message()
|
||||
assert text == (
|
||||
f"<a href='{organization.web_link_with_id}'>‍</a>🔴 #{alert_group.inside_organization_number}, {alert_receive_channel.config.tests['telegram']['title']}\n"
|
||||
f"<a href='{organization.web_link_with_uuid}'>‍</a>🔴 #{alert_group.inside_organization_number}, {alert_receive_channel.config.tests['telegram']['title']}\n"
|
||||
"Alerting, alerts: 1\n"
|
||||
"Source: Test integration - Grafana\n"
|
||||
f"{alert_group.web_link}\n\n"
|
||||
|
|
@ -156,7 +156,7 @@ def test_personal_message(
|
|||
text = renderer.render_personal_message()
|
||||
|
||||
assert text == (
|
||||
f"<a href='{organization.web_link_with_id}'>‍</a>🟠 #{alert_group.inside_organization_number}, {alert_receive_channel.config.tests['telegram']['title']}\n"
|
||||
f"<a href='{organization.web_link_with_uuid}'>‍</a>🟠 #{alert_group.inside_organization_number}, {alert_receive_channel.config.tests['telegram']['title']}\n"
|
||||
f"Acknowledged by {user_name}, alerts: 1\n"
|
||||
"Source: Test integration - Grafana\n"
|
||||
f"{alert_group.web_link}\n\n"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ def test_user_verification_handler_process_update_another_account_already_linked
|
|||
|
||||
user_2 = make_user_for_organization(organization)
|
||||
code = make_telegram_verification_code(user_2)
|
||||
connector, created = TelegramVerificationCode.verify_user(code.uuid_with_org_id, chat_id, "nickname")
|
||||
connector, created = TelegramVerificationCode.verify_user(code.uuid_with_org_uuid, chat_id, "nickname")
|
||||
|
||||
assert created
|
||||
assert connector.telegram_chat_id == chat_id
|
||||
|
|
@ -38,7 +38,7 @@ def test_user_verification_handler_process_update_user_already_linked(
|
|||
|
||||
other_chat_id = 321
|
||||
code = make_telegram_verification_code(user_1)
|
||||
connector, created = TelegramVerificationCode.verify_user(code.uuid_with_org_id, other_chat_id, "nickname")
|
||||
connector, created = TelegramVerificationCode.verify_user(code.uuid_with_org_uuid, other_chat_id, "nickname")
|
||||
|
||||
assert created is False
|
||||
assert connector.user == user_1
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ class ButtonPressHandler(UpdateHandler):
|
|||
has_permission = user_is_authorized(user, [RBACPermission.Permissions.CHATOPS_WRITE])
|
||||
return user.organization == alert_group.channel.organization and has_permission
|
||||
|
||||
@staticmethod
|
||||
def _get_action_context(data: str) -> ActionContext:
|
||||
@classmethod
|
||||
def _get_action_context(cls, data: str) -> ActionContext:
|
||||
args = CallbackQueryFactory.decode_data(data)
|
||||
|
||||
alert_group_pk = args[0]
|
||||
|
|
@ -71,10 +71,16 @@ class ButtonPressHandler(UpdateHandler):
|
|||
action_name = args[1]
|
||||
action = Action(action_name)
|
||||
|
||||
action_data = args[2] if len(args) >= 3 and not args[2].startswith("x-oncall-org-id") else None
|
||||
action_data = args[2] if len(args) >= 3 and not cls._is_oncall_identifier(args[2]) else None
|
||||
|
||||
return ActionContext(alert_group=alert_group, action=action, action_data=action_data)
|
||||
|
||||
@staticmethod
|
||||
def _is_oncall_identifier(string: str) -> bool:
|
||||
# determines if piece of data passed via callback_data is oncall_identifier
|
||||
# x-oncall-org-id is kept here for backward compatibility.
|
||||
return string.startswith("x-oncall-org-id") or string.startswith("oncall-uuid")
|
||||
|
||||
@staticmethod
|
||||
def _map_action_context_to_fn(action_context: ActionContext) -> Tuple[Callable, dict]:
|
||||
action_to_fn = {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import re
|
||||
from typing import List, Union
|
||||
|
||||
TELEGRAM_VERIFICATION_CODE_REGEX = "^[A-Z0-9]*_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
||||
uuid_regex = "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"
|
||||
TELEGRAM_VERIFICATION_CODE_REGEX = f"^{uuid_regex}_{uuid_regex}$"
|
||||
|
||||
|
||||
def is_verification_message(text: str) -> bool:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 3.2.16 on 2022-12-05 07:00
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user_management', '0005_rbac_permissions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False),
|
||||
),
|
||||
]
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import logging
|
||||
import typing
|
||||
import uuid
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from django.apps import apps
|
||||
|
|
@ -129,6 +130,9 @@ class Organization(MaintainableObject):
|
|||
# Slack specific field with general log channel id
|
||||
general_log_channel_id = models.CharField(max_length=100, null=True, default=None)
|
||||
|
||||
# uuid used to unuqie identify organization in different clusters
|
||||
uuid = models.UUIDField(default=uuid.uuid4, editable=False)
|
||||
|
||||
# Organization Settings configured from slack
|
||||
(
|
||||
ACKNOWLEDGE_REMIND_NEVER,
|
||||
|
|
@ -282,9 +286,9 @@ class Organization(MaintainableObject):
|
|||
return urljoin(self.grafana_url, "a/grafana-oncall-app/")
|
||||
|
||||
@property
|
||||
def web_link_with_id(self):
|
||||
# It's a workaround to pass org id to the oncall gateway while proxying telegram requests
|
||||
return urljoin(self.grafana_url, f"a/grafana-oncall-app/?x-oncall-org-id={self.public_primary_key}")
|
||||
def web_link_with_uuid(self):
|
||||
# It's a workaround to pass some unique identifier to the oncall gateway while proxying telegram requests
|
||||
return urljoin(self.grafana_url, f"a/grafana-oncall-app/?oncall-uuid={self.uuid}")
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.pk}: {self.org_title}"
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ class OnCallGatewayAPIClient:
|
|||
response = self._post(url=self._slack_connectors_url, json=d)
|
||||
response_data = response.json()
|
||||
return (
|
||||
OnCallConnector(
|
||||
response_data["oncall_org_id"],
|
||||
SlackConnector(
|
||||
response_data["slack_team_id"],
|
||||
response_data["backend"],
|
||||
),
|
||||
response,
|
||||
|
|
|
|||
|
|
@ -39,13 +39,13 @@ const TelegramInfo = observer((_props: TelegramInfoProps) => {
|
|||
<>
|
||||
{telegramConfigured || !store.hasFeature(AppFeature.LiveSettings) ? (
|
||||
<VerticalGroup>
|
||||
<Text.Title level={5}>Connect personal Telegram</Text.Title>
|
||||
{/* <Text.Title level={5}>Connect personal Telegram</Text.Title>
|
||||
<Block bordered withBackground className={cx('automatic-connect-telegram-block')}>
|
||||
<Text type="secondary">Connect Telegram automatically</Text>
|
||||
<a href={`${botLink}/?start=${verificationCode}`} target="_blank" rel="noreferrer">
|
||||
<Button size="sm">Connect account</Button>
|
||||
</a>
|
||||
</Block>
|
||||
</Block> */}
|
||||
<Text.Title level={5}>Manual connection</Text.Title>
|
||||
|
||||
<Text type="secondary">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue