From f0b7a0e189c924cdceeb90f186adc23890da3fd1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 04:59:47 +0000 Subject: [PATCH 01/19] Bump decode-uri-component from 0.2.0 to 0.2.2 in /grafana-plugin Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2. - [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases) - [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2) --- updated-dependencies: - dependency-name: decode-uri-component dependency-type: indirect ... Signed-off-by: dependabot[bot] --- grafana-plugin/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grafana-plugin/yarn.lock b/grafana-plugin/yarn.lock index b09206b0..4b06ee8c 100644 --- a/grafana-plugin/yarn.lock +++ b/grafana-plugin/yarn.lock @@ -5633,9 +5633,9 @@ decimal.js@^10.2.1: integrity sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== dedent@^0.7.0: version "0.7.0" From 635168afb90204ba5f033f9a531d7d786d737f2d Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Fri, 9 Dec 2022 12:53:20 +0100 Subject: [PATCH 02/19] hide mobile app verification tab in the user settings modal for unauthed users (#970) --- CHANGELOG.md | 4 +++- .../containers/UserSettings/UserSettings.tsx | 7 ++++--- grafana-plugin/src/pages/users/Users.tsx | 17 ++--------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7c8ead8..2e261c31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v1.2.0 (TBD) +## v1.2.0 (2022-12-12) ### Added @@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Got 500 error when saving Outgoing Webhook ([#890](https://github.com/grafana/oncall/issues/890)) - v1.0.13 helm chart - update the OnCall backend pods image pull policy to "Always" (and explicitly set tag to `latest`). This should resolve some recent issues experienced where the frontend/backend versions are not aligned. +- Mobile App Verification tab in the user settings modal is now hidden for users that do not have proper + permissions to use it ### Changed diff --git a/grafana-plugin/src/containers/UserSettings/UserSettings.tsx b/grafana-plugin/src/containers/UserSettings/UserSettings.tsx index 2e237915..b66aa7de 100644 --- a/grafana-plugin/src/containers/UserSettings/UserSettings.tsx +++ b/grafana-plugin/src/containers/UserSettings/UserSettings.tsx @@ -7,7 +7,9 @@ import { useMediaQuery } from 'react-responsive'; import { Tabs, TabsContent } from 'containers/UserSettings/parts'; import { User as UserType } from 'models/user/user.types'; +import { AppFeature } from 'state/features'; import { useStore } from 'state/useStore'; +import { isUserActionAllowed, UserActions } from 'utils/authorization'; import { BREAKPOINT_TABS } from 'utils/consts'; import { UserSettingsTab } from './UserSettings.types'; @@ -19,13 +21,12 @@ const cx = cn.bind(styles); interface UserFormProps { onHide: () => void; id: UserType['pk'] | 'new'; - showMobileAppScreen: boolean; onCreate?: (data: UserType) => void; onUpdate?: () => void; tab?: UserSettingsTab; } -const UserSettings = observer(({ id, showMobileAppScreen, onHide, tab = UserSettingsTab.UserInfo }: UserFormProps) => { +const UserSettings = observer(({ id, onHide, tab = UserSettingsTab.UserInfo }: UserFormProps) => { const store = useStore(); const { userStore, teamStore } = store; @@ -59,7 +60,7 @@ const UserSettings = observer(({ id, showMobileAppScreen, onHide, tab = UserSett !isDesktopOrLaptop, isCurrent && teamStore.currentTeam?.slack_team_identity && !storeUser.slack_user_identity, isCurrent && !storeUser.telegram_configuration, - showMobileAppScreen, + isCurrent && store.hasFeature(AppFeature.MobileApp) && isUserActionAllowed(UserActions.UserSettingsWrite), ]; return ( diff --git a/grafana-plugin/src/pages/users/Users.tsx b/grafana-plugin/src/pages/users/Users.tsx index d61fee49..924ad5a0 100644 --- a/grafana-plugin/src/pages/users/Users.tsx +++ b/grafana-plugin/src/pages/users/Users.tsx @@ -21,7 +21,6 @@ import UserSettings from 'containers/UserSettings/UserSettings'; import { WithPermissionControl } from 'containers/WithPermissionControl/WithPermissionControl'; import { User as UserType } from 'models/user/user.types'; import { pages } from 'pages'; -import { AppFeature } from 'state/features'; import { PageProps, WithStoreProps } from 'state/types'; import { withMobXProviderContext } from 'state/withStore'; import LocationHelper from 'utils/LocationHelper'; @@ -117,11 +116,7 @@ class Users extends React.Component { render() { const { usersFilters, userPkToEdit, page, errorData } = this.state; - const { - store, - query, - query: { id }, - } = this.props; + const { store, query } = this.props; const { userStore } = store; const columns = [ @@ -162,8 +157,6 @@ class Users extends React.Component { }); const { count, results } = userStore.getSearchResult(); - const showMobileAppScreen: boolean = - id !== undefined && id !== 'me' && id === userStore.currentUserPk && store.hasFeature(AppFeature.MobileApp); return ( @@ -239,13 +232,7 @@ class Users extends React.Component { /> )} - {userPkToEdit && ( - - )} + {userPkToEdit && } )} From 67ac47ff32e9469dddeb65f7f290d43227ea2a3b Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Fri, 9 Dec 2022 12:48:19 -0300 Subject: [PATCH 03/19] Update SCHEDULES_WRITE fallback role to EDITOR --- engine/apps/api/permissions/__init__.py | 2 +- engine/apps/api/tests/test_oncall_shift.py | 8 ++++---- engine/apps/api/tests/test_schedules.py | 8 ++++---- grafana-plugin/src/plugin.json | 1 + grafana-plugin/src/utils/authorization/index.ts | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/engine/apps/api/permissions/__init__.py b/engine/apps/api/permissions/__init__.py index 1b9409c5..00311d75 100644 --- a/engine/apps/api/permissions/__init__.py +++ b/engine/apps/api/permissions/__init__.py @@ -109,7 +109,7 @@ class RBACPermission(permissions.BasePermission): Resources.SCHEDULES, Actions.READ, LegacyAccessControlRole.VIEWER ) SCHEDULES_WRITE = LegacyAccessControlCompatiblePermission( - Resources.SCHEDULES, Actions.WRITE, LegacyAccessControlRole.ADMIN + Resources.SCHEDULES, Actions.WRITE, LegacyAccessControlRole.EDITOR ) SCHEDULES_EXPORT = LegacyAccessControlCompatiblePermission( Resources.SCHEDULES, Actions.EXPORT, LegacyAccessControlRole.EDITOR diff --git a/engine/apps/api/tests/test_oncall_shift.py b/engine/apps/api/tests/test_oncall_shift.py index 0235775d..23e23079 100644 --- a/engine/apps/api/tests/test_oncall_shift.py +++ b/engine/apps/api/tests/test_oncall_shift.py @@ -926,7 +926,7 @@ def test_create_on_call_shift_override_invalid_data(on_call_shift_internal_api_s "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_201_CREATED), - (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), + (LegacyAccessControlRole.EDITOR, status.HTTP_201_CREATED), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), ], ) @@ -958,7 +958,7 @@ def test_on_call_shift_create_permissions( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), - (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), + (LegacyAccessControlRole.EDITOR, status.HTTP_200_OK), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), ], ) @@ -1080,7 +1080,7 @@ def test_on_call_shift_retrieve_permissions( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_204_NO_CONTENT), - (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), + (LegacyAccessControlRole.EDITOR, status.HTTP_204_NO_CONTENT), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), ], ) @@ -1185,7 +1185,7 @@ def test_on_call_shift_days_options_permissions( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), - (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), + (LegacyAccessControlRole.EDITOR, status.HTTP_200_OK), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), ], ) diff --git a/engine/apps/api/tests/test_schedules.py b/engine/apps/api/tests/test_schedules.py index 64185118..e0f73002 100644 --- a/engine/apps/api/tests/test_schedules.py +++ b/engine/apps/api/tests/test_schedules.py @@ -1204,7 +1204,7 @@ def test_filter_events_invalid_type( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), - (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), + (LegacyAccessControlRole.EDITOR, status.HTTP_200_OK), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), ], ) @@ -1242,7 +1242,7 @@ def test_schedule_create_permissions( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), - (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), + (LegacyAccessControlRole.EDITOR, status.HTTP_200_OK), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), ], ) @@ -1360,7 +1360,7 @@ def test_schedule_retrieve_permissions( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_204_NO_CONTENT), - (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), + (LegacyAccessControlRole.EDITOR, status.HTTP_204_NO_CONTENT), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), ], ) @@ -1436,7 +1436,7 @@ def test_events_permissions( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), - (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), + (LegacyAccessControlRole.EDITOR, status.HTTP_200_OK), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), ], ) diff --git a/grafana-plugin/src/plugin.json b/grafana-plugin/src/plugin.json index 776b809c..22d3f50b 100644 --- a/grafana-plugin/src/plugin.json +++ b/grafana-plugin/src/plugin.json @@ -250,6 +250,7 @@ { "action": "grafana-oncall-app.escalation-chains:read" }, { "action": "grafana-oncall-app.schedules:read" }, + { "action": "grafana-oncall-app.schedules:write" }, { "action": "grafana-oncall-app.schedules:export" }, { "action": "grafana-oncall-app.chatops:read" }, diff --git a/grafana-plugin/src/utils/authorization/index.ts b/grafana-plugin/src/utils/authorization/index.ts index a5709e7e..215f58b2 100644 --- a/grafana-plugin/src/utils/authorization/index.ts +++ b/grafana-plugin/src/utils/authorization/index.ts @@ -122,7 +122,7 @@ export const UserActions: { [action in Actions]: UserAction } = { EscalationChainsWrite: constructAction(Resource.ESCALATION_CHAINS, Action.WRITE, OrgRole.Admin), SchedulesRead: constructAction(Resource.SCHEDULES, Action.READ, OrgRole.Viewer), - SchedulesWrite: constructAction(Resource.SCHEDULES, Action.WRITE, OrgRole.Admin), + SchedulesWrite: constructAction(Resource.SCHEDULES, Action.WRITE, OrgRole.Editor), SchedulesExport: constructAction(Resource.SCHEDULES, Action.WRITE, OrgRole.Editor), ChatOpsRead: constructAction(Resource.CHATOPS, Action.READ, OrgRole.Viewer), From 5036d719d7491c669fb9499883b5f35f6489b03d Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Fri, 9 Dec 2022 15:16:33 -0300 Subject: [PATCH 04/19] Update CHANGELOG.md --- CHANGELOG.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e261c31..aeb3f63f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v1.2.0 (2022-12-12) +## v1.1.7 (2022-12-09) + +### Fixed + +- Update fallback role for schedule write RBAC permission +- Mobile App Verification tab in the user settings modal is now hidden for users that do not have proper + permissions to use it + +## v1.1.6 (2022-12-09) ### Added @@ -21,8 +29,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Got 500 error when saving Outgoing Webhook ([#890](https://github.com/grafana/oncall/issues/890)) - v1.0.13 helm chart - update the OnCall backend pods image pull policy to "Always" (and explicitly set tag to `latest`). This should resolve some recent issues experienced where the frontend/backend versions are not aligned. -- Mobile App Verification tab in the user settings modal is now hidden for users that do not have proper - permissions to use it ### Changed From 52d6009c2a6599dc600a5f9af822bca6175b502b Mon Sep 17 00:00:00 2001 From: Michael Derynck Date: Mon, 12 Dec 2022 15:40:32 +0000 Subject: [PATCH 05/19] Remove unused parameter from gcom call (#975) # What this PR does Remove unused parameter from gcom call ## Which issue(s) this PR fixes ## Checklist - [ ] Tests updated - [ ] Documentation added - [ ] `CHANGELOG.md` updated --- engine/apps/grafana_plugin/helpers/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/apps/grafana_plugin/helpers/client.py b/engine/apps/grafana_plugin/helpers/client.py index 9244a1ce..44316e22 100644 --- a/engine/apps/grafana_plugin/helpers/client.py +++ b/engine/apps/grafana_plugin/helpers/client.py @@ -191,7 +191,7 @@ class GcomAPIClient(APIClient): super().__init__(settings.GRAFANA_COM_API_URL, api_token) def get_instance_info(self, stack_id: str) -> Optional[GCOMInstanceInfo]: - data, _ = self.api_get(f"instances/{stack_id}?config=true") + data, _ = self.api_get(f"instances/{stack_id}") return data def get_instances(self, query: str): From 8c0eba46b9def4fb0fd6f3d680b84e50c03068a0 Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Mon, 12 Dec 2022 17:05:44 +0100 Subject: [PATCH 06/19] remove is_rbac_permissions_enabled logic from check_gcom_permission function (#976) this field will be addressed in a subsequent sync call it is not necessary here --- engine/apps/grafana_plugin/helpers/gcom.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/engine/apps/grafana_plugin/helpers/gcom.py b/engine/apps/grafana_plugin/helpers/gcom.py index f4b5b47b..3a595a44 100644 --- a/engine/apps/grafana_plugin/helpers/gcom.py +++ b/engine/apps/grafana_plugin/helpers/gcom.py @@ -44,8 +44,6 @@ def check_gcom_permission(token_string: str, context) -> Optional["GcomToken"]: if not instance_info or str(instance_info["orgId"]) != org_id: raise InvalidToken - rbac_is_enabled = client.is_rbac_enabled_for_organization() - if not organization: DynamicSetting = apps.get_model("base", "DynamicSetting") allow_signup = DynamicSetting.objects.get_or_create( @@ -62,7 +60,6 @@ def check_gcom_permission(token_string: str, context) -> Optional["GcomToken"]: region_slug=instance_info["regionSlug"], gcom_token=token_string, gcom_token_org_last_time_synced=timezone.now(), - is_rbac_permissions_enabled=rbac_is_enabled, ) else: organization.stack_slug = instance_info["slug"] @@ -72,7 +69,6 @@ def check_gcom_permission(token_string: str, context) -> Optional["GcomToken"]: organization.grafana_url = instance_info["url"] organization.gcom_token = token_string organization.gcom_token_org_last_time_synced = timezone.now() - organization.is_rbac_permissions_enabled = rbac_is_enabled organization.save( update_fields=[ "stack_slug", @@ -82,7 +78,6 @@ def check_gcom_permission(token_string: str, context) -> Optional["GcomToken"]: "grafana_url", "gcom_token", "gcom_token_org_last_time_synced", - "is_rbac_permissions_enabled", ] ) logger.debug(f"Finish authenticate by making request to gcom api for org={org_id}, stack_id={stack_id}") From 3625b757918e34bf76b431133d66d25ac08f3a78 Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Mon, 12 Dec 2022 18:25:56 +0100 Subject: [PATCH 07/19] fix cloud sync related issue (#977) this PR reverts [this change](https://github.com/grafana/oncall/commit/9e598385f492df6d7fd336c0ef441762fc4f3a72#diff-a74aa8f07a8fdc31af66559390f0fc77b66692d43e6d3c5f94311ef7eed5efabL19-L55) and removes the `str` casting that was done on the `orgId` field returned from the Grafana COM API --- engine/apps/user_management/sync.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/engine/apps/user_management/sync.py b/engine/apps/user_management/sync.py index 740b3332..9a04a261 100644 --- a/engine/apps/user_management/sync.py +++ b/engine/apps/user_management/sync.py @@ -17,18 +17,7 @@ def sync_organization(organization): rbac_is_enabled = client.is_rbac_enabled_for_organization() organization.is_rbac_permissions_enabled = rbac_is_enabled - if organization.gcom_token: - gcom_client = GcomAPIClient(organization.gcom_token) - instance_info = gcom_client.get_instance_info(organization.stack_id) - if not instance_info or str(instance_info["orgId"]) != organization.org_id: - return - - organization.stack_slug = instance_info["slug"] - organization.org_slug = instance_info["orgSlug"] - organization.org_title = instance_info["orgName"] - organization.region_slug = instance_info["regionSlug"] - organization.grafana_url = instance_info["url"] - organization.gcom_token_org_last_time_synced = timezone.now() + _sync_instance_info(organization) api_users = client.get_users(rbac_is_enabled) @@ -53,6 +42,22 @@ def sync_organization(organization): ) +def _sync_instance_info(organization): + if organization.gcom_token: + gcom_client = GcomAPIClient(organization.gcom_token) + instance_info, _ = gcom_client.get_instance_info(organization.stack_id) + + if not instance_info or instance_info["orgId"] != organization.org_id: + return + + organization.stack_slug = instance_info["slug"] + organization.org_slug = instance_info["orgSlug"] + organization.org_title = instance_info["orgName"] + organization.region_slug = instance_info["regionSlug"] + organization.grafana_url = instance_info["url"] + organization.gcom_token_org_last_time_synced = timezone.now() + + def sync_users_and_teams(client, api_users, organization): # check if api_users are shaped correctly. e.g. for paused instance, the response is not a list. if not api_users or not isinstance(api_users, (tuple, list)): From b66dd1a30c05ffdb6868cdc974eda2ebc613ede2 Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Mon, 12 Dec 2022 18:48:26 +0100 Subject: [PATCH 08/19] fix sync.. again (#978) --- engine/apps/user_management/sync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/apps/user_management/sync.py b/engine/apps/user_management/sync.py index 9a04a261..2334c5c5 100644 --- a/engine/apps/user_management/sync.py +++ b/engine/apps/user_management/sync.py @@ -45,7 +45,7 @@ def sync_organization(organization): def _sync_instance_info(organization): if organization.gcom_token: gcom_client = GcomAPIClient(organization.gcom_token) - instance_info, _ = gcom_client.get_instance_info(organization.stack_id) + instance_info = gcom_client.get_instance_info(organization.stack_id) if not instance_info or instance_info["orgId"] != organization.org_id: return From 9931105cc270843ed7c3187c5ba6ce03bfa98f7f Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Mon, 12 Dec 2022 15:39:27 -0300 Subject: [PATCH 09/19] Add additional logging info for slack API event endpoint requests --- engine/apps/slack/views.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/engine/apps/slack/views.py b/engine/apps/slack/views.py index 439a8f64..d7df72e9 100644 --- a/engine/apps/slack/views.py +++ b/engine/apps/slack/views.py @@ -143,6 +143,15 @@ class SlackEventApiEndpointView(APIView): if isinstance(payload, str): payload = json.JSONDecoder().decode(payload) + logger.info( + "team_id: %s channel_id: %s user_id: %s command: %s event: %s", + payload.get("team_id"), + payload.get("channel_id"), + payload.get("user_id"), + payload.get("command"), + payload.get("event", {}).get("type"), + ) + # Checking if it's repeated Slack request if "HTTP_X_SLACK_RETRY_NUM" in request.META and int(request.META["HTTP_X_SLACK_RETRY_NUM"]) > 1: logger.critical( From b8c77e4b30f8cc274029e419c8ccfb19b257dfa1 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Mon, 12 Dec 2022 16:30:24 -0300 Subject: [PATCH 10/19] Fix schedules types UI confusion --- .../components/NewScheduleSelector/NewScheduleSelector.tsx | 2 +- .../src/components/SchedulesFilters_NEW/SchedulesFilters.tsx | 4 ++-- grafana-plugin/src/models/schedule/schedule.types.ts | 4 ++-- grafana-plugin/src/pages/schedules/Schedules.tsx | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/grafana-plugin/src/components/NewScheduleSelector/NewScheduleSelector.tsx b/grafana-plugin/src/components/NewScheduleSelector/NewScheduleSelector.tsx index fdbce3d4..b9beecb3 100644 --- a/grafana-plugin/src/components/NewScheduleSelector/NewScheduleSelector.tsx +++ b/grafana-plugin/src/components/NewScheduleSelector/NewScheduleSelector.tsx @@ -50,7 +50,7 @@ const NewScheduleSelector: FC = (props) => { - diff --git a/grafana-plugin/src/components/SchedulesFilters_NEW/SchedulesFilters.tsx b/grafana-plugin/src/components/SchedulesFilters_NEW/SchedulesFilters.tsx index 2b7f6a0b..cc6ee209 100644 --- a/grafana-plugin/src/components/SchedulesFilters_NEW/SchedulesFilters.tsx +++ b/grafana-plugin/src/components/SchedulesFilters_NEW/SchedulesFilters.tsx @@ -72,7 +72,7 @@ const SchedulesFilters = (props: SchedulesFiltersProps) => { { label: 'All', value: undefined }, { label: 'Web', - value: ScheduleType.Calendar, + value: ScheduleType.API, }, { label: 'ICal', @@ -80,7 +80,7 @@ const SchedulesFilters = (props: SchedulesFiltersProps) => { }, { label: 'API', - value: ScheduleType.API, + value: ScheduleType.Calendar, }, ]} value={value?.type} diff --git a/grafana-plugin/src/models/schedule/schedule.types.ts b/grafana-plugin/src/models/schedule/schedule.types.ts index c38a69eb..8b703377 100644 --- a/grafana-plugin/src/models/schedule/schedule.types.ts +++ b/grafana-plugin/src/models/schedule/schedule.types.ts @@ -6,9 +6,9 @@ import { User } from 'models/user/user.types'; import { UserGroup } from 'models/user_group/user_group.types'; export enum ScheduleType { - 'API', - 'Ical', 'Calendar', + 'Ical', + 'API', } export interface RotationFormLiveParams { diff --git a/grafana-plugin/src/pages/schedules/Schedules.tsx b/grafana-plugin/src/pages/schedules/Schedules.tsx index 699108ae..e0750a76 100644 --- a/grafana-plugin/src/pages/schedules/Schedules.tsx +++ b/grafana-plugin/src/pages/schedules/Schedules.tsx @@ -209,7 +209,7 @@ class SchedulesPage extends React.Component { - if (data.type === ScheduleType.Calendar) { + if (data.type === ScheduleType.API) { LocationHelper.update({ page: 'schedule', id: data.id }, 'partial'); } }; From 5967d5af635dbfb989ae2277fa0567940d6e61fc Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Tue, 13 Dec 2022 13:00:59 +0100 Subject: [PATCH 11/19] remove apns + fix django-push-notifications migrations (#984) - removes APNS support - changes the `django-push-notification` library from the `iskhakov` fork to the [`grafana` fork](https://github.com/grafana/django-push-notifications). This new fork basically just patches an issue which affected the database migrations of this django app (previously the library would not respect the `USER_MODEL` setting when creating its tables and would instead reference the `auth_user` table.. which we don't want) - add `--no-cache` flag to the `make build` command **NOTE** A migration should be applied as follows: ```bash # remove the four push_notifications tables, which have improper foreign key references python manage.py migrate push_notifications zero # recreate the tables with the proper foreign key references python manage.py migrate ``` --- CHANGELOG.md | 11 ++++++ Makefile | 2 +- engine/apps/api/urls.py | 6 --- engine/apps/api/views/user.py | 66 +------------------------------ engine/apps/mobile_app/backend.py | 3 +- engine/apps/mobile_app/tasks.py | 20 +--------- engine/apps/mobile_app/urls.py | 3 +- engine/apps/mobile_app/views.py | 5 --- engine/requirements.txt | 3 +- engine/settings/base.py | 6 --- 10 files changed, 18 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aeb3f63f..3540c1c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v1.1.8 (TBD) + +### Changed + +- removed APNS support +- changed the `django-push-notification` library from the `iskhakov` fork to the [`grafana` fork](https://github.com/grafana/django-push-notifications). + This new fork basically patches an issue which affected the database migrations of this django app (previously the + library would not respect the `USER_MODEL` setting when creating its tables and would instead reference the + `auth_user` table.. which we don't want) +- add `--no-cache` flag to the `make build` command + ## v1.1.7 (2022-12-09) ### Fixed diff --git a/Makefile b/Makefile index 52efd02e..44864c4f 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ restart: $(call run_docker_compose_command,restart) build: - $(call run_docker_compose_command,build) + $(call run_docker_compose_command,build --no-cache) cleanup: stop docker system prune --filter label="$(DOCKER_COMPOSE_DEV_LABEL)" --all --volumes diff --git a/engine/apps/api/urls.py b/engine/apps/api/urls.py index 05d87b75..96f05f71 100644 --- a/engine/apps/api/urls.py +++ b/engine/apps/api/urls.py @@ -1,7 +1,5 @@ -from django.conf import settings from django.urls import include, path, re_path -from apps.mobile_app.views import APNSDeviceAuthorizedViewSet from common.api_helpers.optional_slash_router import OptionalSlashRouter, optional_slash_path from .views import UserNotificationPolicyView, auth @@ -68,10 +66,6 @@ router.register(r"tokens", PublicApiTokenView, basename="api_token") router.register(r"live_settings", LiveSettingViewSet, basename="live_settings") router.register(r"oncall_shifts", OnCallShiftView, basename="oncall_shifts") -# TODO: remove this when the hackathon app is deprecated (APNSDeviceAuthorizedViewSet is registered in mobile_app) -if settings.FEATURE_MOBILE_APP_INTEGRATION_ENABLED: - router.register(r"device/apns", APNSDeviceAuthorizedViewSet) - urlpatterns = [ path("", include(router.urls)), optional_slash_path("user", CurrentUserView.as_view(), name="api-user"), diff --git a/engine/apps/api/views/user.py b/engine/apps/api/views/user.py index f54d58be..34155272 100644 --- a/engine/apps/api/views/user.py +++ b/engine/apps/api/views/user.py @@ -28,8 +28,7 @@ from apps.auth_token.constants import SCHEDULE_EXPORT_TOKEN_NAME from apps.auth_token.models import UserScheduleExportAuthToken from apps.base.messaging import get_messaging_backend_from_id from apps.base.utils import live_settings -from apps.mobile_app.auth import MobileAppAuthTokenAuthentication, MobileAppVerificationTokenAuthentication -from apps.mobile_app.models import MobileAppAuthToken +from apps.mobile_app.auth import MobileAppAuthTokenAuthentication from apps.telegram.client import TelegramClient from apps.telegram.models import TelegramVerificationCode from apps.twilioapp.phone_manager import PhoneManager @@ -128,7 +127,6 @@ class UserView( "unlink_backend": [RBACPermission.Permissions.USER_SETTINGS_WRITE], "make_test_call": [RBACPermission.Permissions.USER_SETTINGS_WRITE], "export_token": [RBACPermission.Permissions.USER_SETTINGS_WRITE], - "mobile_app_auth_token": [RBACPermission.Permissions.USER_SETTINGS_WRITE], } rbac_object_permissions = { @@ -149,7 +147,6 @@ class UserView( "unlink_backend", "make_test_call", "export_token", - "mobile_app_auth_token", ], } @@ -471,64 +468,3 @@ class UserView( except UserScheduleExportAuthToken.DoesNotExist: raise NotFound return Response(status=status.HTTP_204_NO_CONTENT) - - @action( - methods=["get", "post", "delete"], - detail=False, - authentication_classes=(MobileAppVerificationTokenAuthentication,), - ) - def mobile_app_auth_token(self, request): - """ - TODO: remove after hackathon app is deprecated (see apps.mobile_app.views.MobileAppAuthTokenAPIView) - """ - DynamicSetting = apps.get_model("base", "DynamicSetting") - - if not settings.FEATURE_MOBILE_APP_INTEGRATION_ENABLED: - return Response(status=status.HTTP_404_NOT_FOUND) - - mobile_app_settings = DynamicSetting.objects.get_or_create( - name="mobile_app_settings", - defaults={ - "json_value": { - "org_ids": [], - } - }, - )[0] - if self.request.auth.organization.pk not in mobile_app_settings.json_value["org_ids"]: - return Response(status=status.HTTP_404_NOT_FOUND) - - if self.request.method == "GET": - try: - token = MobileAppAuthToken.objects.get(user=self.request.user) - except MobileAppAuthToken.DoesNotExist: - raise NotFound - - response = { - "token_id": token.id, - "user_id": token.user_id, - "organization_id": token.organization_id, - "created_at": token.created_at, - "revoked_at": token.revoked_at, - } - return Response(response, status=status.HTTP_200_OK) - - if self.request.method == "POST": - # If token already exists revoke it - try: - token = MobileAppAuthToken.objects.get(user=self.request.user) - token.delete() - except MobileAppAuthToken.DoesNotExist: - pass - - instance, token = MobileAppAuthToken.create_auth_token(self.request.user, self.request.user.organization) - data = {"id": instance.pk, "token": token, "created_at": instance.created_at} - return Response(data, status=status.HTTP_201_CREATED) - - if self.request.method == "DELETE": - try: - token = MobileAppAuthToken.objects.get(user=self.request.user) - token.delete() - except MobileAppAuthToken.DoesNotExist: - raise NotFound - - return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/engine/apps/mobile_app/backend.py b/engine/apps/mobile_app/backend.py index 40663216..db518de0 100644 --- a/engine/apps/mobile_app/backend.py +++ b/engine/apps/mobile_app/backend.py @@ -1,7 +1,7 @@ import json from django.conf import settings -from push_notifications.models import APNSDevice, GCMDevice +from push_notifications.models import GCMDevice from apps.base.messaging import BaseMessagingBackend from apps.mobile_app.tasks import notify_user_async @@ -35,7 +35,6 @@ class MobileAppBackend(BaseMessagingBackend): token.delete() # delete push notification related info for user - APNSDevice.objects.filter(user=user).delete() GCMDevice.objects.filter(user=user).delete() def serialize_user(self, user): diff --git a/engine/apps/mobile_app/tasks.py b/engine/apps/mobile_app/tasks.py index e6a6a4bf..0c45751c 100644 --- a/engine/apps/mobile_app/tasks.py +++ b/engine/apps/mobile_app/tasks.py @@ -1,6 +1,6 @@ from celery.utils.log import get_task_logger from django.conf import settings -from push_notifications.models import APNSDevice, GCMDevice +from push_notifications.models import GCMDevice from apps.alerts.models import AlertGroup from apps.mobile_app.alert_rendering import get_push_notification_message @@ -34,12 +34,10 @@ def notify_user_async(user_pk, alert_group_pk, notification_policy_pk, critical) logger.warning(f"User notification policy {notification_policy_pk} does not exist") return - # APNS is for notifying iOS devices, GCM for Android - apns_devices_to_notify = APNSDevice.objects.filter(user=user) gcm_devices_to_notify = GCMDevice.objects.filter(user=user) # create an error log in case user has no devices set up - if not apns_devices_to_notify.exists() and not gcm_devices_to_notify.exists(): + if not gcm_devices_to_notify.exists(): UserNotificationPolicyLogRecord.objects.create( author=user, type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED, @@ -67,20 +65,6 @@ def notify_user_async(user_pk, alert_group_pk, notification_policy_pk, critical) "sound": "bingbong.aiff", } - apns_devices_to_notify.send_message( - message, - thread_id=thread_id, - category="USER_NEW_INCIDENT", # TODO: rename to USER_NEW_ALERT_GROUP - extra={ - "orgId": alert_group.channel.organization.public_primary_key, - "orgName": alert_group.channel.organization.stack_slug, - "alertGroupId": alert_group.public_primary_key, - "incidentId": alert_group.public_primary_key, # TODO: remove after hackathon app is deprecated - "status": alert_group.status, - "aps": aps, - }, - ) - gcm_devices_to_notify.send_message( message, thread_id=thread_id, diff --git a/engine/apps/mobile_app/urls.py b/engine/apps/mobile_app/urls.py index 5af825a9..8b14dc7c 100644 --- a/engine/apps/mobile_app/urls.py +++ b/engine/apps/mobile_app/urls.py @@ -1,13 +1,12 @@ from django.conf import settings from apps.mobile_app.fcm_relay import FCMRelayView -from apps.mobile_app.views import APNSDeviceAuthorizedViewSet, FCMDeviceAuthorizedViewSet, MobileAppAuthTokenAPIView +from apps.mobile_app.views import FCMDeviceAuthorizedViewSet, MobileAppAuthTokenAPIView from common.api_helpers.optional_slash_router import OptionalSlashRouter, optional_slash_path app_name = "mobile_app" router = OptionalSlashRouter() -router.register("apns", APNSDeviceAuthorizedViewSet, basename="apns") router.register("fcm", FCMDeviceAuthorizedViewSet, basename="fcm") urlpatterns = [ diff --git a/engine/apps/mobile_app/views.py b/engine/apps/mobile_app/views.py index a9290f85..b0188b3e 100644 --- a/engine/apps/mobile_app/views.py +++ b/engine/apps/mobile_app/views.py @@ -1,4 +1,3 @@ -from push_notifications.api.rest_framework import APNSDeviceAuthorizedViewSet as BaseAPNSDeviceAuthorizedViewSet from push_notifications.api.rest_framework import GCMDeviceAuthorizedViewSet, GCMDeviceSerializer from rest_framework import status from rest_framework.exceptions import NotFound @@ -10,10 +9,6 @@ from apps.mobile_app.auth import MobileAppAuthTokenAuthentication, MobileAppVeri from apps.mobile_app.models import MobileAppAuthToken -class APNSDeviceAuthorizedViewSet(BaseAPNSDeviceAuthorizedViewSet): - authentication_classes = (MobileAppAuthTokenAuthentication,) - - class FCMDeviceAuthorizedViewSet(GCMDeviceAuthorizedViewSet): class FCMDeviceSerializer(GCMDeviceSerializer): """ diff --git a/engine/requirements.txt b/engine/requirements.txt index 5e41b01d..3e45d9a4 100644 --- a/engine/requirements.txt +++ b/engine/requirements.txt @@ -33,12 +33,11 @@ django-log-request-id==1.6.0 django-polymorphic==3.0.0 django-rest-polymorphic==0.1.9 pre-commit==2.15.0 -https://github.com/iskhakov/django-push-notifications/archive/refs/tags/3.0.0-fix-migration.tar.gz +https://github.com/grafana/django-push-notifications/archive/refs/tags/3.0.0-fix-migration.tar.gz django-mirage-field==1.3.0 django-mysql==4.6.0 PyMySQL==1.0.2 psycopg2-binary==2.9.3 emoji==1.7.0 -apns2==0.7.2 regex==2021.11.2 psutil==5.9.4 diff --git a/engine/settings/base.py b/engine/settings/base.py index 680b8249..e5aac426 100644 --- a/engine/settings/base.py +++ b/engine/settings/base.py @@ -556,12 +556,6 @@ PUSH_NOTIFICATIONS_SETTINGS = { "FCM_POST_URL": os.getenv("FCM_POST_URL", default="https://fcm.googleapis.com/fcm/send"), "USER_MODEL": "user_management.User", "UPDATE_ON_DUPLICATE_REG_ID": True, - # TODO: remove APNS related endpoints after the hackathon app is deprecated - "APNS_AUTH_KEY_PATH": os.environ.get("APNS_AUTH_KEY_PATH", None), - "APNS_TOPIC": os.environ.get("APNS_TOPIC", None), - "APNS_AUTH_KEY_ID": os.environ.get("APNS_AUTH_KEY_ID", None), - "APNS_TEAM_ID": os.environ.get("APNS_TEAM_ID", None), - "APNS_USE_SANDBOX": getenv_boolean("APNS_USE_SANDBOX", True), } FCM_RELAY_ENABLED = getenv_boolean("FCM_RELAY_ENABLED", default=False) From 66b2ed5c648efdb74477a4deeda6458cf8dc131e Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Tue, 13 Dec 2022 14:06:56 +0100 Subject: [PATCH 12/19] add more logging to push notification celery task (#986) --- engine/apps/mobile_app/tasks.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/engine/apps/mobile_app/tasks.py b/engine/apps/mobile_app/tasks.py index 0c45751c..fc9341d9 100644 --- a/engine/apps/mobile_app/tasks.py +++ b/engine/apps/mobile_app/tasks.py @@ -65,15 +65,21 @@ def notify_user_async(user_pk, alert_group_pk, notification_policy_pk, critical) "sound": "bingbong.aiff", } - gcm_devices_to_notify.send_message( - message, - thread_id=thread_id, - category="USER_NEW_INCIDENT", # TODO: rename to USER_NEW_ALERT_GROUP - extra={ - "orgId": alert_group.channel.organization.public_primary_key, - "orgName": alert_group.channel.organization.stack_slug, - "alertGroupId": alert_group.public_primary_key, - "status": alert_group.status, - "aps": aps, - }, + extra = { + "orgId": alert_group.channel.organization.public_primary_key, + "orgName": alert_group.channel.organization.stack_slug, + "alertGroupId": alert_group.public_primary_key, + "status": alert_group.status, + "aps": aps, + } + + logger.info(f"Sending push notification with message: {message}; thread-id: {thread_id}; extra: {extra}") + + # TODO: rename category to USER_NEW_ALERT_GROUP + fcm_response = gcm_devices_to_notify.send_message( + message, thread_id=thread_id, category="USER_NEW_INCIDENT", extra=extra ) + + # NOTE: we may want to further handle the response from FCM, but for now lets simply log it out + # https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream + logger.info(f"FCM response was: {fcm_response}") From 684375a3eb6dc411fd3c15ab11f56df50b28b752 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Tue, 13 Dec 2022 10:16:59 -0300 Subject: [PATCH 13/19] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3540c1c3..60b667e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `auth_user` table.. which we don't want) - add `--no-cache` flag to the `make build` command +### Fixed + +- fix schedule UI types and permissions + ## v1.1.7 (2022-12-09) ### Fixed From 2b763f376e986e1bb10b07abf561cb20d0b2e43b Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Tue, 13 Dec 2022 10:18:18 -0300 Subject: [PATCH 14/19] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b667e6..7a190f47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v1.1.8 (TBD) +## v1.1.8 (2022-12-13) ### Changed From ed4be171f67e85eb8476a4fe5a24040ac6f85b01 Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Wed, 14 Dec 2022 09:36:35 +0100 Subject: [PATCH 15/19] add make command to configure mobile app feature (#988) Adds a make command, `enable-mobile-app-feature-flags`, which sets the backend feature flag in `./dev/.env.dev`, and updates a record in the `base_dynamicsetting` database table, which are needed to enable the mobile app backend features. --- CHANGELOG.md | 6 +++++ Makefile | 6 +++++ dev/README.md | 4 +++ dev/add_env_var.sh | 26 +++++++++++++++++++ .../management/commands/enable_mobile_app.py | 21 +++++++++++++++ 5 files changed, 63 insertions(+) create mode 100755 dev/add_env_var.sh create mode 100644 engine/engine/management/commands/enable_mobile_app.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a190f47..3120bf88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## v1.1.8 (2022-12-13) +### Added + +- Added a `make` command, `enable-mobile-app-feature-flags`, which sets the backend feature flag in `./dev/.env.dev`, + and updates a record in the `base_dynamicsetting` database table, which are needed to enable the mobile + app backend features. + ### Changed - removed APNS support diff --git a/Makefile b/Makefile index 44864c4f..4ada9540 100644 --- a/Makefile +++ b/Makefile @@ -126,6 +126,12 @@ engine-manage: exec-engine: docker exec -it oncall_engine bash +_enable-mobile-app-feature-flags: + $(shell ./dev/add_env_var.sh FEATURE_MOBILE_APP_INTEGRATION_ENABLED True $(DEV_ENV_FILE)) + $(call run_engine_docker_command,python manage.py enable_mobile_app) + +enable-mobile-app-feature-flags: _enable-mobile-app-feature-flags stop start + # The below commands are useful for running backend services outside of docker define backend_command export `grep -v '^#' $(DEV_ENV_FILE) | xargs -0` && \ diff --git a/dev/README.md b/dev/README.md index 5fd5dbea..4ffbfebc 100644 --- a/dev/README.md +++ b/dev/README.md @@ -120,6 +120,10 @@ make build # rebuild images (e.g. when changing requirements.txt) # run Django's `manage.py` script, inside of a docker container, passing `$CMD` as arguments. # e.g. `make engine-manage CMD="makemigrations"` - https://docs.djangoproject.com/en/4.1/ref/django-admin/#django-admin-makemigrations make engine-manage CMD="..." +# sets a feature flag, related to mobile app backend functionality, in your ./dev/.env.dev +# and sets the necessary database values +# NOTE: you need to enable, and configure, the plugin before running this command +make enable-mobile-app-feature-flags # this will remove all of the images, containers, volumes, and networks # associated with your local OnCall developer setup diff --git a/dev/add_env_var.sh b/dev/add_env_var.sh new file mode 100755 index 00000000..ab3e7c6c --- /dev/null +++ b/dev/add_env_var.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# https://gist.github.com/maxpoletaev/4ed25183427a2cd7e57a + +case "$OSTYPE" in + darwin*) PLATFORM="OSX" ;; + linux*) PLATFORM="LINUX" ;; + bsd*) PLATFORM="BSD" ;; + *) PLATFORM="UNKNOWN" ;; +esac + +replace() { + if [[ "$PLATFORM" == "OSX" || "$PLATFORM" == "BSD" ]]; then + sed -i "" "$1" "$2" + elif [ "$PLATFORM" == "LINUX" ]; then + sed -i "$1" "$2" + fi +} + +if grep -q $1 $3; then + # file contains string, lets replace it + # https://stackoverflow.com/a/42667816 - why we need the -i '' + replace "s~$1=.*~$1=$2~g" $3 +else + # file doesn't contain string, lets append it + echo "$1=$2" >> $3 +fi diff --git a/engine/engine/management/commands/enable_mobile_app.py b/engine/engine/management/commands/enable_mobile_app.py new file mode 100644 index 00000000..01208147 --- /dev/null +++ b/engine/engine/management/commands/enable_mobile_app.py @@ -0,0 +1,21 @@ +from django.core.management.base import BaseCommand, CommandError + +from apps.base.models.dynamic_setting import DynamicSetting +from apps.user_management.models.organization import Organization + + +class Command(BaseCommand): + note = "Note: you will also need to set the appropriate environment variables in your ./dev/.env.dev file." + help = f"Handles the database portion of enabling the mobile app related features. {note}" + + def handle(self, *args, **options): + org = Organization.objects.first() + + if not org: + raise CommandError("No organization exists. Have you enabled, and configured, the plugin?") + + DynamicSetting.objects.update_or_create( + name="mobile_app_settings", defaults={"json_value": {"org_ids": [org.pk]}} + ) + + self.stdout.write(self.style.SUCCESS(f"Mobile app successfully enabled.")) From f16c4b26c6d7e240d5f174a9824e8bd8209fe4c5 Mon Sep 17 00:00:00 2001 From: Gilberto Junior Date: Fri, 16 Dec 2022 08:09:04 -0300 Subject: [PATCH 16/19] Increasing library default timeout (#1005) # What this PR does ## Which issue(s) this PR fixes Issues: https://github.com/grafana/oncall/issues/990 ## Checklist - [X] Tests updated --- tools/pagerduty-migrator/migrator/__main__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/pagerduty-migrator/migrator/__main__.py b/tools/pagerduty-migrator/migrator/__main__.py index c71fc34d..14f73691 100644 --- a/tools/pagerduty-migrator/migrator/__main__.py +++ b/tools/pagerduty-migrator/migrator/__main__.py @@ -34,6 +34,7 @@ from migrator.resources.users import ( def main() -> None: session = APISession(PAGERDUTY_API_TOKEN) + session.timeout = 20 print("▶ Fetching users...") users = session.list_all("users", params={"include[]": "notification_rules"}) From 275aa94c71b18c6b14c9037247234ff76145ba39 Mon Sep 17 00:00:00 2001 From: Matvey Kukuy Date: Fri, 16 Dec 2022 17:23:21 +0200 Subject: [PATCH 17/19] Small wording fix (Incident -> AG) (#1009) Small wording fix (Incident -> AG) --- grafana-plugin/src/pages/incident/Incident.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grafana-plugin/src/pages/incident/Incident.tsx b/grafana-plugin/src/pages/incident/Incident.tsx index 4be78be1..b155f4c4 100644 --- a/grafana-plugin/src/pages/incident/Incident.tsx +++ b/grafana-plugin/src/pages/incident/Incident.tsx @@ -276,7 +276,7 @@ class IncidentPage extends React.Component {showLinkTo && ( )} From 41f886b31ee733cf8d7331d8ed0808c00dca6ab2 Mon Sep 17 00:00:00 2001 From: Innokentii Konstantinov Date: Sat, 17 Dec 2022 19:34:13 +0800 Subject: [PATCH 18/19] Speedup seach alertgroup --- engine/apps/alerts/models/alert_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/apps/alerts/models/alert_group.py b/engine/apps/alerts/models/alert_group.py index 2b7659c5..8a00fb83 100644 --- a/engine/apps/alerts/models/alert_group.py +++ b/engine/apps/alerts/models/alert_group.py @@ -74,7 +74,7 @@ class AlertGroupQuerySet(models.QuerySet): # Try to return the last open group # Note that (channel, channel_filter, distinction, is_open_for_grouping) is in unique_together try: - return self.get(**search_params, is_open_for_grouping=True), False + return self.get(**search_params, is_open_for_grouping__isnull=False), False except self.model.DoesNotExist: pass From 5595480d3a0be004be12193c1625491257668fa1 Mon Sep 17 00:00:00 2001 From: Rares Mardare <40542072+teodosii@users.noreply.github.com> Date: Mon, 19 Dec 2022 13:15:32 +0200 Subject: [PATCH 19/19] add qr code class with white background (#1012) # What this PR does - Adds white border around the QR code + small margin below --- .../MobileAppVerification/MobileAppVerification.module.scss | 5 +++++ .../MobileAppVerification/MobileAppVerification.tsx | 2 +- .../__snapshots__/MobileAppVerification.test.tsx.snap | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/grafana-plugin/src/containers/MobileAppVerification/MobileAppVerification.module.scss b/grafana-plugin/src/containers/MobileAppVerification/MobileAppVerification.module.scss index cd4af8f4..94dbd47f 100644 --- a/grafana-plugin/src/containers/MobileAppVerification/MobileAppVerification.module.scss +++ b/grafana-plugin/src/containers/MobileAppVerification/MobileAppVerification.module.scss @@ -39,6 +39,11 @@ opacity: 0.2; } +.qr-code { + background-color: #fff; + margin-bottom: 12px; +} + .qr-loader { position: absolute; z-index: 10; diff --git a/grafana-plugin/src/containers/MobileAppVerification/MobileAppVerification.tsx b/grafana-plugin/src/containers/MobileAppVerification/MobileAppVerification.tsx index ed634a9f..ed8baee3 100644 --- a/grafana-plugin/src/containers/MobileAppVerification/MobileAppVerification.tsx +++ b/grafana-plugin/src/containers/MobileAppVerification/MobileAppVerification.tsx @@ -133,7 +133,7 @@ const MobileAppVerification = observer(({ userPk }: Props) => { Open Grafana IRM mobile application and scan this code to sync it with your account.
- + {isQRBlurry && }
diff --git a/grafana-plugin/src/containers/MobileAppVerification/__snapshots__/MobileAppVerification.test.tsx.snap b/grafana-plugin/src/containers/MobileAppVerification/__snapshots__/MobileAppVerification.test.tsx.snap index e471869c..ac791478 100644 --- a/grafana-plugin/src/containers/MobileAppVerification/__snapshots__/MobileAppVerification.test.tsx.snap +++ b/grafana-plugin/src/containers/MobileAppVerification/__snapshots__/MobileAppVerification.test.tsx.snap @@ -109,7 +109,7 @@ exports[`MobileAppVerification if we disconnect the app, it disconnects and fetc class="u-width-100 u-flex u-flex-center u-position-relative" >