diff --git a/engine/apps/alerts/incident_appearance/renderers/telegram_renderer.py b/engine/apps/alerts/incident_appearance/renderers/telegram_renderer.py
index b3364810..9b3ad515 100644
--- a/engine/apps/alerts/incident_appearance/renderers/telegram_renderer.py
+++ b/engine/apps/alerts/incident_appearance/renderers/telegram_renderer.py
@@ -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""
+ text = f""
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"
diff --git a/engine/apps/api/views/organization.py b/engine/apps/api/views/organization.py
index 86bae0bc..bce742b1 100644
--- a/engine/apps/api/views/organization.py
+++ b/engine/apps/api/views/organization.py
@@ -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
)
diff --git a/engine/apps/api/views/user.py b/engine/apps/api/views/user.py
index be7ff475..f54d58be 100644
--- a/engine/apps/api/views/user.py
+++ b/engine/apps/api/views/user.py
@@ -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"])
diff --git a/engine/apps/telegram/models/verification/channel.py b/engine/apps/telegram/models/verification/channel.py
index 8d80f03a..1b24bb6e 100644
--- a/engine/apps/telegram/models/verification/channel.py
+++ b/engine/apps/telegram/models/verification/channel.py
@@ -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:
diff --git a/engine/apps/telegram/models/verification/personal.py b/engine/apps/telegram/models/verification/personal.py
index 299c9993..323b990a 100644
--- a/engine/apps/telegram/models/verification/personal.py
+++ b/engine/apps/telegram/models/verification/personal.py
@@ -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:
diff --git a/engine/apps/telegram/renderers/keyboard.py b/engine/apps/telegram/renderers/keyboard.py
index 997f5473..d580dc26 100644
--- a/engine/apps/telegram/renderers/keyboard.py
+++ b/engine/apps/telegram/renderers/keyboard.py
@@ -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
diff --git a/engine/apps/telegram/tests/test_keyboard_renderer.py b/engine/apps/telegram/tests/test_keyboard_renderer.py
index 50d769d8..89b1182d 100644
--- a/engine/apps/telegram/tests/test_keyboard_renderer.py
+++ b/engine/apps/telegram/tests/test_keyboard_renderer.py
@@ -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}",
)
],
]
diff --git a/engine/apps/telegram/tests/test_message_renderer.py b/engine/apps/telegram/tests/test_message_renderer.py
index 7d800975..862d1c50 100644
--- a/engine/apps/telegram/tests/test_message_renderer.py
+++ b/engine/apps/telegram/tests/test_message_renderer.py
@@ -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"🔴 #{alert_group.inside_organization_number}, {alert_receive_channel.config.tests['telegram']['title']}\n"
+ f"🔴 #{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"🟠#{alert_group.inside_organization_number}, {alert_receive_channel.config.tests['telegram']['title']}\n"
+ f"🟠#{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"
diff --git a/engine/apps/telegram/tests/test_models.py b/engine/apps/telegram/tests/test_models.py
index 0a9497e4..16a22b93 100644
--- a/engine/apps/telegram/tests/test_models.py
+++ b/engine/apps/telegram/tests/test_models.py
@@ -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
diff --git a/engine/apps/telegram/updates/update_handlers/button_press.py b/engine/apps/telegram/updates/update_handlers/button_press.py
index 005460fe..91d2002e 100644
--- a/engine/apps/telegram/updates/update_handlers/button_press.py
+++ b/engine/apps/telegram/updates/update_handlers/button_press.py
@@ -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 = {
diff --git a/engine/apps/telegram/utils.py b/engine/apps/telegram/utils.py
index 18640c58..be878e7a 100644
--- a/engine/apps/telegram/utils.py
+++ b/engine/apps/telegram/utils.py
@@ -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:
diff --git a/engine/apps/user_management/migrations/0006_organization_uuid.py b/engine/apps/user_management/migrations/0006_organization_uuid.py
new file mode 100644
index 00000000..63d16ded
--- /dev/null
+++ b/engine/apps/user_management/migrations/0006_organization_uuid.py
@@ -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),
+ ),
+ ]
diff --git a/engine/apps/user_management/models/organization.py b/engine/apps/user_management/models/organization.py
index f428b32d..1a571b1f 100644
--- a/engine/apps/user_management/models/organization.py
+++ b/engine/apps/user_management/models/organization.py
@@ -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}"
diff --git a/engine/common/oncall_gateway/oncall_gateway_client.py b/engine/common/oncall_gateway/oncall_gateway_client.py
index 63d48613..77af439d 100644
--- a/engine/common/oncall_gateway/oncall_gateway_client.py
+++ b/engine/common/oncall_gateway/oncall_gateway_client.py
@@ -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,
diff --git a/grafana-plugin/src/containers/UserSettings/parts/tabs/TelegramInfo/TelegramInfo.tsx b/grafana-plugin/src/containers/UserSettings/parts/tabs/TelegramInfo/TelegramInfo.tsx
index 3c186429..efc94642 100644
--- a/grafana-plugin/src/containers/UserSettings/parts/tabs/TelegramInfo/TelegramInfo.tsx
+++ b/grafana-plugin/src/containers/UserSettings/parts/tabs/TelegramInfo/TelegramInfo.tsx
@@ -39,13 +39,13 @@ const TelegramInfo = observer((_props: TelegramInfoProps) => {
<>
{telegramConfigured || !store.hasFeature(AppFeature.LiveSettings) ? (
- Connect personal Telegram
+ {/* Connect personal Telegram
Connect Telegram automatically
-
+ */}
Manual connection