Example #1
0
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
Example #2
0
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)
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
 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)
Example #9
0
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
Example #10
0
    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