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 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_send_to_member( project: Project, target_identifier: Optional[Union[int, str]] ) -> Mapping[ExternalProviders, Set[User]]: """ No checking for disabled users is done. If a user explicitly specifies a member as a target to send to, it should overwrite the user's personal mail settings. :param project: :param target_identifier: Optional. String or int representation of a user_id. :returns: Mapping[ExternalProvider, Iterable[User]] A mapping of provider to member that a notification should be sent to as a set. """ if target_identifier is None: return {} try: user = (User.objects.filter( id=int(target_identifier), sentry_orgmember_set__teams__projectteam__project=project, ).distinct().get()) except User.DoesNotExist: return {} notification_settings = NotificationSetting.objects.get_for_users_by_parent( NotificationSettingTypes.ISSUE_ALERTS, parent=project, users=[user]) if notification_settings: return { ExternalProviders(notification_setting.provider): {user} for notification_setting in notification_settings } # Fall back to email if there are no settings. return {ExternalProviders.EMAIL: {user}}
def get_send_to_member(self, project, target_identifier): """ No checking for disabled users is done. If a user explicitly specifies a member as a target to send to, it should overwrite the user's personal notification settings. :param target_identifier: :return: Mapping[ExternalProvider, Iterable[int]] Mapping of provider to id of member that a notification should be sent to as a list. """ if target_identifier is None: return {} try: user = (User.objects.filter( id=int(target_identifier), sentry_orgmember_set__teams__projectteam__project=project, ).distinct().get()) except User.DoesNotExist: return {} notification_settings = NotificationSetting.objects.get_for_users_by_parent( NotificationSettingTypes.ISSUE_ALERTS, parent=project, users=[user]) if notification_settings: return { ExternalProviders(notification_setting.provider): [user.id] for notification_setting in notification_settings } # fall back to email if there are no settings return {ExternalProviders.EMAIL: [user.id]}
def delete(self, **kwargs): from sentry.models import NotificationSetting # There is no foreign key relationship so we have to manually cascade. NotificationSetting.objects._filter( target_ids=[self.actor_id], provider=ExternalProviders(self.provider) ).delete() return super().delete(**kwargs)
def delete(self, **kwargs): install = self.integration.get_installation(self.organization_id) install.notify_remove_external_team(external_team=self, team=self.actor.resolve()) install.remove_notification_settings( actor_id=self.actor_id, provider=ExternalProviders(self.provider) ) return super().delete(**kwargs)
def transform_to_notification_settings_by_user( notification_settings: Iterable[Any], users: Iterable[Any], ) -> Mapping[Any, 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[Any, 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 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_send_to_team( project: Project, target_identifier: Optional[Union[str, int]] ) -> Mapping[ExternalProviders, Set[User]]: """ Get a team's notification settings. If not present, get settings for each subscribed user in the team. :param project: :param target_identifier: Optional. String or int representation of a team_id. :returns: Mapping[ExternalProvider, Iterable[User]] A mapping of provider to member that a notification should be sent to as a set. """ if target_identifier is None: return {} try: team = Team.objects.get(id=int(target_identifier), projectteam__project=project) except Team.DoesNotExist: return {} team_notification_settings = NotificationSetting.objects.get_for_recipient_by_parent( NotificationSettingTypes.ISSUE_ALERTS, parent=project, recipients=[team]) if team_notification_settings: team_mapping = { ExternalProviders(notification_setting.provider): {team} for notification_setting in team_notification_settings } return team_mapping # fallback to notifying each subscribed user if there aren't team notification settings member_list = team.member_set.values_list("user_id", flat=True) users = User.objects.filter(id__in=member_list) mapping: Mapping[ ExternalProviders, Set[User]] = NotificationSetting.objects.filter_to_subscribed_users( project, users) return mapping