def transform_to_notification_settings_by_parent_id( notification_settings: Iterable[Any], user_default: Optional[NotificationSettingOptionValues] = None, ) -> Tuple[Mapping[ExternalProviders, Mapping[ int, NotificationSettingOptionValues]], Mapping[ ExternalProviders, Optional[NotificationSettingOptionValues]], ]: """ Given a unorganized list of notification settings, create a mapping of providers to a mapping parents (projects or organizations) to setting values. Return this mapping as a tuple with a mapping of provider to the user's parent-independent notification preference. """ notification_settings_by_parent_id: Dict[ExternalProviders, Dict[ int, NotificationSettingOptionValues]] = defaultdict(dict) # This is the user's default value for any projects or organizations that # don't have the option value specifically recorded. notification_setting_user_default: Dict[ ExternalProviders, Optional[NotificationSettingOptionValues]] = defaultdict( lambda: user_default) for notification_setting in notification_settings: scope_type = NotificationScopeType(notification_setting.scope_type) provider = ExternalProviders(notification_setting.provider) value = NotificationSettingOptionValues(notification_setting.value) if scope_type == NotificationScopeType.USER: notification_setting_user_default[provider] = value else: key = int(notification_setting.scope_identifier) notification_settings_by_parent_id[provider][key] = value return notification_settings_by_parent_id, notification_setting_user_default
def get_legacy_object( notification_setting: Any, actor_mapping: Mapping[int, Any], parent_mapping: Mapping[int, Any], organization_mapping: Mapping[int, Any], ) -> Any: type = NotificationSettingTypes(notification_setting.type) value = NotificationSettingOptionValues(notification_setting.value) scope_type = NotificationScopeType(notification_setting.scope_type) key = get_legacy_key(type, scope_type) data = { "key": key, "value": get_legacy_value(type, value), "user": actor_mapping.get(notification_setting.target_id), "project": None, "organization": None, } if scope_type == NotificationScopeType.PROJECT: data["project"] = parent_mapping.get( notification_setting.scope_identifier) if scope_type == NotificationScopeType.ORGANIZATION: data["organization"] = organization_mapping.get( notification_setting.scope_identifier) return LegacyUserOptionClone(**data)
def transform_to_notification_settings_by_recipient( notification_settings: Iterable[NotificationSetting], recipients: Iterable[Team | User], ) -> Mapping[ Team | User, Mapping[NotificationScopeType, Mapping[ExternalProviders, NotificationSettingOptionValues]], ]: """ Given an unsorted list of notification settings, create a mapping of users to a map of notification scopes to setting values. """ actor_mapping = {recipient.actor_id: recipient for recipient in recipients} notification_settings_by_recipient: MutableMapping[ Team | User, MutableMapping[ NotificationScopeType, MutableMapping[ExternalProviders, NotificationSettingOptionValues], ], ] = defaultdict(lambda: defaultdict(dict)) for notification_setting in notification_settings: recipient = actor_mapping.get(notification_setting.target_id) scope_type = NotificationScopeType(notification_setting.scope_type) value = NotificationSettingOptionValues(notification_setting.value) provider = ExternalProviders(notification_setting.provider) notification_settings_by_recipient[recipient][scope_type][provider] = value return notification_settings_by_recipient
def validate_value( type: NotificationSettingTypes, value_param: str, context: Optional[List[str]] = None ) -> NotificationSettingOptionValues: try: value = NotificationSettingOptionValues(value_param) except ValueError: raise ParameterValidationError(f"Unknown value: {value_param}", context) if not helper_validate(type, value): raise ParameterValidationError(f"Invalid value for type {type}: {value}", context) return value
def transform_to_notification_settings_by_parent_id( notification_settings: Iterable[Any], ) -> Tuple[Mapping[int, NotificationSettingOptionValues], Optional[NotificationSettingOptionValues]]: """ Given a unorganized list of notification settings, create a mapping of parents (projects or organizations) to setting values. Return this mapping as a tuple with the user's parent-independent notification preference. """ notification_settings_by_parent_id = {} notification_setting_user_default = None for notification_setting in notification_settings: if notification_setting.scope_type == NotificationScopeType.USER.value: notification_setting_user_default = NotificationSettingOptionValues( notification_setting.value) else: key = int(notification_setting.scope_identifier) notification_settings_by_parent_id[ key] = NotificationSettingOptionValues( notification_setting.value) return notification_settings_by_parent_id, notification_setting_user_default
def transform_to_notification_settings_by_user( notification_settings: Iterable[Any], users: Iterable[Any], ) -> Mapping[Any, Mapping[NotificationScopeType, NotificationSettingOptionValues]]: """ Given a unorganized list of notification settings, create a mapping of users to a map of notification scopes to setting values. """ actor_mapping = {user.actor_id: user for user in users} notification_settings_by_user: Dict[ Any, Dict[NotificationScopeType, NotificationSettingOptionValues]] = defaultdict(dict) for notification_setting in notification_settings: user = actor_mapping.get(notification_setting.target_id) notification_settings_by_user[user][NotificationScopeType( notification_setting.scope_type )] = NotificationSettingOptionValues(notification_setting.value) return notification_settings_by_user
def transform_to_notification_settings_by_user( notification_settings: Iterable["NotificationSetting"], users: Iterable["User"], ) -> Mapping["User", Mapping[NotificationScopeType, Mapping[ ExternalProviders, NotificationSettingOptionValues]], ]: """ Given a unorganized list of notification settings, create a mapping of users to a map of notification scopes to setting values. """ actor_mapping = {user.actor_id: user for user in users} notification_settings_by_user: Dict[ "User", Dict[NotificationScopeType, Dict[ExternalProviders, NotificationSettingOptionValues]], ] = defaultdict( lambda: defaultdict(dict)) for notification_setting in notification_settings: user = actor_mapping.get(notification_setting.target_id) scope_type = NotificationScopeType(notification_setting.scope_type) value = NotificationSettingOptionValues(notification_setting.value) provider = ExternalProviders(notification_setting.provider) notification_settings_by_user[user][scope_type][provider] = value return notification_settings_by_user
def get_settings( self, provider: ExternalProviders, type: NotificationSettingTypes, user: User | None = None, team: Team | None = None, project: Project | None = None, organization: Organization | None = None, ) -> NotificationSettingOptionValues: """ 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. """ # 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] return (NotificationSettingOptionValues(settings[0].value) if settings else NotificationSettingOptionValues.DEFAULT)
def transform_to_notification_settings_by_scope( notification_settings: Iterable["NotificationSetting"], ) -> Mapping[NotificationScopeType, Mapping[int, Mapping[ ExternalProviders, NotificationSettingOptionValues]], ]: """ Given an unsorted list of notification settings, create a mapping of scopes (user or parent) and their IDs to a map of provider to notifications setting values. """ notification_settings_by_scopes: Dict[NotificationScopeType, Dict[ int, Dict[ExternalProviders, NotificationSettingOptionValues]]] = defaultdict( lambda: defaultdict(lambda: dict())) for notification_setting in notification_settings: scope_type = NotificationScopeType(notification_setting.scope_type) scope_id = notification_setting.scope_identifier provider = ExternalProviders(notification_setting.provider) value = NotificationSettingOptionValues(notification_setting.value) notification_settings_by_scopes[scope_type][scope_id][provider] = value return notification_settings_by_scopes
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