def remove_legacy_option(type: Optional[NotificationSettingTypes] = None, **kwargs: Any) -> None: from sentry.models.useroption import UserOption if type: kwargs["key"] = get_legacy_key(type) else: kwargs["key__in"] = KEYS_TO_LEGACY_KEYS.values() UserOption.objects.filter(**kwargs).delete()
def remove_settings_for_user(self, user, type: NotificationSettingTypes = None): if type: # We don't need a transaction because this is only used in tests. UserOption.objects.filter(user=user, key=get_legacy_key(type)).delete() self.filter(target=user.actor, type=type.value).delete() else: UserOption.objects.filter( user=user, key__in=KEYS_TO_LEGACY_KEYS.values()).delete() self.filter(target=user.actor).delete()
def get_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, user=None, team=None, project=None, organization=None, ): """ In this temporary implementation, always read EMAIL settings from UserOptions. One and only one of (user, team, project, or organization) must not be null. This function automatically translates a missing DB row to NotificationSettingOptionValues.DEFAULT. :param provider: ExternalProviders enum :param type: NotificationSetting.type enum :param user: (optional) A User object :param team: (optional) A Team object :param project: (optional) A Project object :param organization: (optional) An Organization object :return: NotificationSettingOptionValues enum """ user_id_option = getattr(user, "id", None) scope_type, scope_identifier = _get_scope(user_id_option, project=project, organization=organization) target = _get_target(user, team) value = ( # NOQA self.filter( provider=provider.value, type=type.value, scope_type=scope_type, scope_identifier=scope_identifier, target=target, ).first() or NotificationSettingOptionValues.DEFAULT) legacy_value = UserOption.objects.get_value(user, get_legacy_key(type), project=project, organization=organization) # TODO(mgaeta): This line will be valid after the "copy migration". # assert value == legacy_value return legacy_value
def remove_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, user: Optional[Any] = None, team: Optional[Any] = None, project: Optional[Any] = None, organization: Optional[Any] = None, ) -> None: """ We don't anticipate this function will be used by the API but is useful for tests. This can also be called by `update_settings` when attempting to set a notification preference to DEFAULT. """ from sentry.models.useroption import UserOption with transaction.atomic(): self.find_settings(provider, type, user, team, project, organization).delete() UserOption.objects.unset_value(user, project, get_legacy_key(type))
def get_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, user: Optional[Any] = None, team: Optional[Any] = None, project: Optional[Any] = None, organization: Optional[Any] = None, ) -> NotificationSettingOptionValues: """ In this temporary implementation, always read EMAIL settings from UserOptions. One and only one of (user, team, project, or organization) must not be null. This function automatically translates a missing DB row to NotificationSettingOptionValues.DEFAULT. """ from sentry.models.useroption import UserOption # The `unique_together` constraint should guarantee 0 or 1 rows, but # using `list()` rather than `.first()` to prevent Django from adding an # ordering that could make the query slow. settings = list( self.find_settings(provider, type, user, team, project, organization))[:1] value = (NotificationSettingOptionValues(settings[0].value) if settings else NotificationSettingOptionValues.DEFAULT) legacy_value = UserOption.objects.get_value(user, get_legacy_key(type), project=project, organization=organization) expected_legacy_value = get_legacy_value(type, value) assert expected_legacy_value == str(legacy_value), ( expected_legacy_value, legacy_value) return value
def remove_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, user=None, team=None, project=None, organization=None, ): """ We don't anticipate this function will be used by the API but is useful for tests. This can also be called by `update_settings` when attempting to set a notification preference to DEFAULT. :param provider: ExternalProviders enum :param type: NotificationSettingTypes enum :param user: (Optional) User object :param team: (Optional) Team object :param project: (Optional) Project object :param organization: (Optional) Organization object """ user_id_option = getattr(user, "id", None) scope_type, scope_identifier = _get_scope(user_id_option, project=project, organization=organization) target = _get_target(user, team) with transaction.atomic(): self.filter( provider=provider.value, type=type.value, scope_type=scope_type, scope_identifier=scope_identifier, target=target, ).delete() UserOption.objects.unset_value(user, project, get_legacy_key(type))
def update_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, value: NotificationSettingOptionValues, user: Optional[Any] = None, team: Optional[Any] = None, project: Optional[Any] = None, organization: Optional[Any] = None, ) -> None: """ Save a target's notification preferences. Examples: * Updating a user's org-independent preferences * Updating a user's per-project preferences * Updating a user's per-organization preferences """ from sentry.models.useroption import UserOption # A missing DB row is equivalent to DEFAULT. if value == NotificationSettingOptionValues.DEFAULT: return self.remove_settings( provider, type, user=user, team=team, project=project, organization=organization, ) if not validate(type, value): raise Exception(f"value '{value}' is not valid for type '{type}'") user_id_option = getattr(user, "id", None) scope_type, scope_identifier = get_scope(user_id_option, project=project, organization=organization) target_id = get_target_id(user, team) key = get_legacy_key(type) legacy_value: Union[str, int] = get_legacy_value(type, value) # Annoying HACK to translate "subscribe_by_default" if type == NotificationSettingTypes.ISSUE_ALERTS: legacy_value = int(legacy_value) if project is None: key = "subscribe_by_default" with transaction.atomic(): setting, created = self.get_or_create( provider=provider.value, type=type.value, scope_type=scope_type.value, scope_identifier=scope_identifier, target_id=target_id, defaults={"value": value.value}, ) if not created and setting.value != value.value: setting.update(value=value.value) if not team: UserOption.objects.set_value(user, key=key, value=legacy_value, project=project, organization=organization)