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 test_get_scope(self): scope_type, scope_identifier = get_scope(self.user.id, project=None, organization=None) assert scope_type == NotificationScopeType.USER assert scope_identifier == self.user.id scope_type, scope_identifier = get_scope( self.user.id, project=self.project, organization=None ) assert scope_type == NotificationScopeType.PROJECT assert scope_identifier == self.project.id scope_type, scope_identifier = get_scope( self.user.id, project=None, organization=self.organization ) assert scope_type == NotificationScopeType.ORGANIZATION assert scope_identifier == self.organization.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 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)
def test_get_scope_organization(self): organization = Organization(id=1) scope_type, scope_identifier = get_scope(self.user, organization=organization) assert scope_type == NotificationScopeType.ORGANIZATION assert scope_identifier == organization.id
def test_get_scope_project(self): project = Project(id=1) scope_type, scope_identifier = get_scope(self.user, project=project) assert scope_type == NotificationScopeType.PROJECT assert scope_identifier == project.id
def test_get_scope_team(self): team = Team(id=1) scope_type, scope_identifier = get_scope(team=team) assert scope_type == NotificationScopeType.TEAM assert scope_identifier == team.id
def test_get_scope_user(self): scope_type, scope_identifier = get_scope(self.user) assert scope_type == NotificationScopeType.USER assert scope_identifier == self.user.id