def update_settings_bulk( self, notification_settings: Sequence[NotificationSetting], user: User | None = None, team: Team | None = None, ) -> None: """ Given a list of _valid_ notification settings as tuples of column values, save them to the DB. This does not execute as a transaction. """ target_id = get_target_id(user, team) for (provider, type, scope_type, scope_identifier, value) in notification_settings: # A missing DB row is equivalent to DEFAULT. if value == NotificationSettingOptionValues.DEFAULT: self._filter(provider, type, scope_type, scope_identifier, [target_id]).delete() else: self._update_settings(provider, type, value, scope_type, scope_identifier, target_id) analytics.record( "notifications.settings_updated", target_type="user" if user else "team", actor_id=target_id, )
def update_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, value: NotificationSettingOptionValues, user: Optional["User"] = None, team: Optional["Team"] = None, project: Optional["Project"] = None, organization: Optional["Organization"] = 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 """ # 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}'") scope_type, scope_identifier = get_scope(user, team, project, organization) target_id = get_target_id(user, team) self._update_settings(provider, type, value, scope_type, scope_identifier, target_id)
def find_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, user: Optional["User"] = None, team: Optional["Team"] = None, project: Optional["Project"] = None, organization: Optional["Organization"] = None, ) -> QuerySet: """Wrapper for .filter that translates object parameters to scopes and targets.""" scope_type, scope_identifier = get_scope(user, team, project, organization) target_id = get_target_id(user, team) return self._filter(provider, type, scope_type, scope_identifier, [target_id])
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 """ # 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) 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)
def find_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, user: Optional[Any] = None, team: Optional[Any] = None, project: Optional[Any] = None, organization: Optional[Any] = None, ) -> QuerySet: """ Wrapper for .filter that translates object parameters to scopes and targets. """ 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) return self._filter(provider, type, scope_type, scope_identifier, [target_id])
def update_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, value: NotificationSettingOptionValues, user: User | None = None, team: Team | None = None, project: Project | None = None, organization: Organization | None = 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 """ target_id = get_target_id(user, team) analytics.record( "notifications.settings_updated", target_type="user" if user else "team", actor_id=target_id, ) # 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}'") scope_type, scope_identifier = get_scope(user, team, project, organization) self._update_settings(provider, type, value, scope_type, scope_identifier, target_id)
def test_get_target_id(self): assert get_target_id(self.user) == self.user.actor_id assert get_target_id(self.team) == self.team.actor_id
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)