diff --git a/engine/apps/api/views/live_setting.py b/engine/apps/api/views/live_setting.py index d2c77ab0..8040ee48 100644 --- a/engine/apps/api/views/live_setting.py +++ b/engine/apps/api/views/live_setting.py @@ -38,40 +38,40 @@ class LiveSettingViewSet(PublicPrimaryKeyMixin, viewsets.ModelViewSet): return queryset def perform_update(self, serializer): + name = serializer.instance.name old_value = serializer.instance.value new_value = serializer.validated_data["value"] super().perform_update(serializer) if new_value != old_value: - self._post_update_hook(old_value) + self._post_update_hook(name, old_value) def perform_destroy(self, instance): + name = instance.name old_value = instance.value new_value = instance.default_value super().perform_destroy(instance) if new_value != old_value: - self._post_update_hook(old_value) + self._post_update_hook(name, old_value) - def _post_update_hook(self, old_value): - instance = self.get_object() - - if instance.name == "TELEGRAM_TOKEN": + def _post_update_hook(self, name, old_value): + if name == "TELEGRAM_TOKEN": self._reset_telegram_integration(old_token=old_value) register_telegram_webhook.delay() - if instance.name == "TELEGRAM_WEBHOOK_HOST": + if name == "TELEGRAM_WEBHOOK_HOST": register_telegram_webhook.delay() - if instance.name in ["SLACK_CLIENT_OAUTH_ID", "SLACK_CLIENT_OAUTH_SECRET"]: + if name in ["SLACK_CLIENT_OAUTH_ID", "SLACK_CLIENT_OAUTH_SECRET"]: organization = self.request.auth.organization slack_team_identity = organization.slack_team_identity if slack_team_identity is not None: unpopulate_slack_user_identities.delay(organization_pk=organization.pk, force=True) - if instance.name == "GRAFANA_CLOUD_ONCALL_TOKEN": + if name == "GRAFANA_CLOUD_ONCALL_TOKEN": from apps.oss_installation.models import CloudConnector CloudConnector.remove_sync() diff --git a/engine/apps/base/models/live_setting.py b/engine/apps/base/models/live_setting.py index 770e3eb4..f69c25a3 100644 --- a/engine/apps/base/models/live_setting.py +++ b/engine/apps/base/models/live_setting.py @@ -87,22 +87,22 @@ class LiveSetting(models.Model): "here for more info. Required." ), "TWILIO_API_KEY_SID": ( - "Twilio API key SID/username to allow OnCall to send SMSes and make phone calls, see" + "Twilio API key SID/username to allow OnCall to send SMSes and make phone calls, see " "" "here for more info. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required." ), "TWILIO_API_KEY_SECRET": ( - "Twilio API key secret/password to allow OnCall to send SMSes and make phone calls, see" + "Twilio API key secret/password to allow OnCall to send SMSes and make phone calls, see " "" "here for more info. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required." ), "TWILIO_AUTH_TOKEN": ( - "Twilio password to allow OnCall to send SMSes and make calls, " + "Twilio password to allow OnCall to send SMSes and make calls, see " "" "here for more info. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required." ), "TWILIO_NUMBER": ( - "Number from which you will receive calls and SMS, " + "Number from which you will receive calls and SMSes, " "more info." ), "TWILIO_VERIFY_SERVICE_SID": ( @@ -140,6 +140,8 @@ class LiveSetting(models.Model): SECRET_SETTING_NAMES = ( "TWILIO_ACCOUNT_SID", "TWILIO_AUTH_TOKEN", + "TWILIO_API_KEY_SID", + "TWILIO_API_KEY_SECRET", "TWILIO_VERIFY_SERVICE_SID", "SENDGRID_API_KEY", "SENDGRID_SECRET_KEY", @@ -186,8 +188,21 @@ class LiveSetting(models.Model): settings_in_db = cls.objects.filter(name__in=cls.AVAILABLE_NAMES).values_list("name", flat=True) setting_names_to_populate = set(cls.AVAILABLE_NAMES) - set(settings_in_db) + revalidate_twilio = False for setting_name in setting_names_to_populate: - cls.objects.create(name=setting_name, value=cls._get_setting_from_setting_file(setting_name)) + setting = cls.objects.create(name=setting_name, value=cls._get_setting_from_setting_file(setting_name)) + if setting.name.startswith("TWILIO"): + revalidate_twilio = True + + if revalidate_twilio: + cls.revalidate_twilio() + + @classmethod + def revalidate_twilio(cls): + twilio_settings = cls.objects.filter(name__startswith="TWILIO") + for setting in twilio_settings: + setting.error = LiveSettingValidator(live_setting=setting).get_error() + setting.save(update_fields=["error"]) @staticmethod def _get_setting_from_setting_file(setting_name): diff --git a/engine/apps/base/utils.py b/engine/apps/base/utils.py index e57a78d7..377dd443 100644 --- a/engine/apps/base/utils.py +++ b/engine/apps/base/utils.py @@ -34,13 +34,20 @@ live_settings = LiveSettingProxy() class LiveSettingValidator: + + EMPTY_VALID_NAMES = ( + "TWILIO_AUTH_TOKEN", + "TWILIO_API_KEY_SID", + "TWILIO_API_KEY_SECRET", + ) + def __init__(self, live_setting): self.live_setting = live_setting def get_error(self): check_fn_name = f"_check_{self.live_setting.name.lower()}" - if self.live_setting.value is None: + if self.live_setting.value is None and self.live_setting.name not in self.EMPTY_VALID_NAMES: return "Empty" # skip validation if there's no handler for it