def test_bad_provider_config(self):
        """
        Make sure we are throwing exceptions on poor configuration
        """

        with self.assertRaises(ImproperlyConfigured):
            get_notification_channel(self.test_user_id, self.test_msg_type)
Beispiel #2
0
    def test_bad_provider_config(self):
        """
        Make sure we are throwing exceptions on poor configuration
        """

        with self.assertRaises(ImproperlyConfigured):
            get_notification_channel(self.test_user_id, self.test_msg_type)
Beispiel #3
0
    def test_missing_global_mapping(self):
        """
        Make sure we are throwing exceptions when global mapping is missing
        """

        with self.assertRaises(ImproperlyConfigured):
            get_notification_channel(self.test_user_id, self.test_msg_type)
    def test_missing_global_mapping(self):
        """
        Make sure we are throwing exceptions when global mapping is missing
        """

        with self.assertRaises(ImproperlyConfigured):
            get_notification_channel(self.test_user_id, self.test_msg_type)
Beispiel #5
0
    def test_bad_mapping(self):
        """
        Make sure we are throwing exceptions when a msg type is mapped to a channel name
        that does not exist
        """

        with self.assertRaises(ImproperlyConfigured):
            get_notification_channel(self.test_user_id, self.test_msg_type)
    def test_bad_mapping(self):
        """
        Make sure we are throwing exceptions when a msg type is mapped to a channel name
        that does not exist
        """

        with self.assertRaises(ImproperlyConfigured):
            get_notification_channel(self.test_user_id, self.test_msg_type)
Beispiel #7
0
    def test_get_provider(self):
        """
        Makes sure we get an instance of the registered store provider
        """

        provider = get_notification_channel(self.test_user_id, self.test_msg_type)

        self.assertIsNotNone(provider)
        self.assertTrue(isinstance(provider, BaseDurableNotificationChannel))

        self.assertEqual(provider.name, 'channel6')
        self.assertEqual(provider.display_name, 'channel_name6')
        self.assertEqual(provider.display_description, 'channel_description6')

        # now verify that the wildcard hierarchy rules
        # work, by making a msg_type name which will match one of
        # the intermediate items in the hierarchy

        provider = get_notification_channel(
            self.test_user_id,
            NotificationType(
                name='edx_notifications.channels.tests.another_one',
                renderer='foo.renderer',
            )
        )

        self.assertEqual(provider.name, 'channel3')
        self.assertEqual(provider.display_name, 'channel_name3')
        self.assertEqual(provider.display_description, 'channel_description3')

        provider = get_notification_channel(
            self.test_user_id,
            NotificationType(
                name='edx_notifications.channels.diff_subpath.diff_leaf',
                renderer='foo.renderer',
            )
        )

        self.assertEqual(provider.name, 'channel2')
        self.assertEqual(provider.display_name, 'channel_name2')
        self.assertEqual(provider.display_description, 'channel_description2')
    def test_get_provider(self):
        """
        Makes sure we get an instance of the registered store provider
        """

        provider = get_notification_channel(self.test_user_id, self.test_msg_type)

        self.assertIsNotNone(provider)
        self.assertTrue(isinstance(provider, BaseDurableNotificationChannel))

        self.assertEqual(provider.name, 'channel6')
        self.assertEqual(provider.display_name, 'channel_name6')
        self.assertEqual(provider.display_description, 'channel_description6')

        # now verify that the wildcard hierarchy rules
        # work, by making a msg_type name which will match one of
        # the intermediate items in the hierarchy

        provider = get_notification_channel(
            self.test_user_id,
            NotificationType(
                name='edx_notifications.channels.tests.another_one',
                renderer='foo.renderer',
            )
        )

        self.assertEqual(provider.name, 'channel3')
        self.assertEqual(provider.display_name, 'channel_name3')
        self.assertEqual(provider.display_description, 'channel_description3')

        provider = get_notification_channel(
            self.test_user_id,
            NotificationType(
                name='edx_notifications.channels.diff_subpath.diff_leaf',
                renderer='foo.renderer',
            )
        )

        self.assertEqual(provider.name, 'channel2')
        self.assertEqual(provider.display_name, 'channel_name2')
        self.assertEqual(provider.display_description, 'channel_description2')
Beispiel #9
0
def publish_notification_to_user(user_id,
                                 msg,
                                 preferred_channel=None,
                                 channel_context=None):
    """
    This top level API method will publish a notification
    to a user.

    Ultimately this method will look up the user's preference
    to which NotificationChannel to distribute this over.

    ARGS:
        - user_id: An unconstrained identifier to some user identity
        - msg: A NotificationMessage

    RETURNS:
        A new instance of UserNotification that includes any auto-generated
        fields
    """

    log_msg = (
        'Publishing Notification to user_id {user_id} with message: {msg}'
    ).format(user_id=user_id, msg=msg)
    log.info(log_msg)

    # validate the msg, this will raise a ValidationError if there
    # is something malformatted or missing in the NotificationMessage
    msg.validate()

    # get the notification channel associated
    # for this message type as well as this user
    # as users will be able to choose how to
    # receive their notifications per type.
    #
    # This call will never return None, if there is
    # a problem, it will throw an exception
    channel = get_notification_channel(user_id,
                                       msg.msg_type,
                                       preferred_channel=preferred_channel)

    # Get the proper message - aka payload - for the given channel
    _msg = msg.get_message_for_channel(channel.name)

    user_msg = channel.dispatch_notification_to_user(
        user_id, _msg, channel_context=channel_context)

    return user_msg
Beispiel #10
0
    def test_null_channel(self):
        """
        Makes sure that the NullNotificationChannel doesn't do anythign what so ever
        """

        test_msg_type = NotificationType(
            name='edx_notifications.channels.tests.test_channel.channeltests.null',
            renderer='foo.renderer',
        )

        provider = get_notification_channel(self.test_user_id, test_msg_type)

        self.assertIsNotNone(provider)
        self.assertTrue(isinstance(provider, NullNotificationChannel))

        self.assertIsNone(provider.dispatch_notification_to_user(None, None))
        self.assertEqual(provider.bulk_dispatch_notification(None, None), 0)

        self.assertIsNone(provider.resolve_msg_link(None, None, None))
    def test_null_channel(self):
        """
        Makes sure that the NullNotificationChannel doesn't do anythign what so ever
        """

        test_msg_type = NotificationType(
            name='edx_notifications.channels.tests.test_channel.channeltests.null',
            renderer='foo.renderer',
        )

        provider = get_notification_channel(self.test_user_id, test_msg_type)

        self.assertIsNotNone(provider)
        self.assertTrue(isinstance(provider, NullNotificationChannel))

        self.assertIsNone(provider.dispatch_notification_to_user(None, None))
        self.assertEqual(provider.bulk_dispatch_notification(None, None), 0)

        self.assertIsNone(provider.resolve_msg_link(None, None, None))
def publish_notification_to_user(user_id, msg, preferred_channel=None, channel_context=None):
    """
    This top level API method will publish a notification
    to a user.

    Ultimately this method will look up the user's preference
    to which NotificationChannel to distribute this over.

    ARGS:
        - user_id: An unconstrained identifier to some user identity
        - msg: A NotificationMessage

    RETURNS:
        A new instance of UserNotification that includes any auto-generated
        fields
    """

    log_msg = (
        'Publishing Notification to user_id {user_id} with message: {msg}'
    ).format(user_id=user_id, msg=msg)
    log.info(log_msg)

    # validate the msg, this will raise a ValidationError if there
    # is something malformatted or missing in the NotificationMessage
    msg.validate()

    # get the notification channel associated
    # for this message type as well as this user
    # as users will be able to choose how to
    # receive their notifications per type.
    #
    # This call will never return None, if there is
    # a problem, it will throw an exception
    channel = get_notification_channel(user_id, msg.msg_type, preferred_channel=preferred_channel)

    # Get the proper message - aka payload - for the given channel
    _msg = msg.get_message_for_channel(channel.name)

    user_msg = channel.dispatch_notification_to_user(user_id, _msg, channel_context=channel_context)

    return user_msg
Beispiel #13
0
def bulk_publish_notification_to_users(user_ids,
                                       msg,
                                       exclude_user_ids=None,
                                       preferred_channel=None,
                                       channel_context=None):
    """
    This top level API method will publish a notification
    to a group (potentially large). We have a distinct entry
    point to consider any optimizations that might be possible
    when doing bulk operations

    Ultimately this method will look up the user's preference
    to which NotificationChannel to distribute this over.

    ARGS:
        - user_ids: an iterator that we can enumerate over, say a list or a generator or a ORM resultset
        - msg: A NotificationMessage

    IMPORTANT: If caller wishes to send in a resutset from a Django ORM query, you must
    only select the 'id' column and flatten the results. For example, to send a notification
    to everyone in the Users table, do:

        num_sent = bulk_publish_notification_to_users(
            User.objects.values_list('id', flat=True).all(),
            msg
        )

    """

    log.info('Publishing bulk Notification with message: %s', msg)

    # validate the msg, this will raise a ValidationError if there
    # is something malformatted or missing in the NotificationMessage
    msg.validate()

    if (not isinstance(user_ids, list)
            and not isinstance(user_ids, types.GeneratorType)
            and not isinstance(user_ids, QuerySet)):

        err_msg = (
            'bulk_publish_notification_to_users() can only be called with a user_ids argument '
            'of type list, GeneratorType, or QuerySet. Type {arg_type} was passed in!'
            .format(arg_type=type(user_ids)))
        raise TypeError(err_msg)

    # validate the msg, this will raise a ValidationError if there
    # is something malformatted or missing in the NotificationMessage
    msg.validate()

    # get the system defined msg_type -> channel mapping
    # note, when we enable user preferences, we will
    # have to change this
    channel = get_notification_channel(None,
                                       msg.msg_type,
                                       preferred_channel=preferred_channel)

    # Get the proper message - aka payload - for the given channel
    _msg = msg.get_message_for_channel(channel.name)

    num_sent = channel.bulk_dispatch_notification(
        user_ids,
        _msg,
        exclude_user_ids=exclude_user_ids,
        channel_context=channel_context)

    return num_sent
def bulk_publish_notification_to_users(user_ids, msg, exclude_user_ids=None,
                                       preferred_channel=None, channel_context=None):
    """
    This top level API method will publish a notification
    to a group (potentially large). We have a distinct entry
    point to consider any optimizations that might be possible
    when doing bulk operations

    Ultimately this method will look up the user's preference
    to which NotificationChannel to distribute this over.

    ARGS:
        - user_ids: an iterator that we can enumerate over, say a list or a generator or a ORM resultset
        - msg: A NotificationMessage

    IMPORTANT: If caller wishes to send in a resutset from a Django ORM query, you must
    only select the 'id' column and flatten the results. For example, to send a notification
    to everyone in the Users table, do:

        num_sent = bulk_publish_notification_to_users(
            User.objects.values_list('id', flat=True).all(),
            msg
        )

    """

    log.info('Publishing bulk Notification with message: {msg}'.format(msg=msg))

    # validate the msg, this will raise a ValidationError if there
    # is something malformatted or missing in the NotificationMessage
    msg.validate()

    if (not isinstance(user_ids, list) and
            not isinstance(user_ids, types.GeneratorType) and
            not isinstance(user_ids, ValuesListQuerySet) and
            not isinstance(user_ids, ValuesQuerySet)):

        err_msg = (
            'bulk_publish_notification_to_users() can only be called with a user_ids argument '
            'of type list, GeneratorType, or ValuesQuerySet/ValuesListQuerySet. Type {arg_type} was passed in!'
            .format(arg_type=type(user_ids))
        )
        raise TypeError(err_msg)

    # validate the msg, this will raise a ValidationError if there
    # is something malformatted or missing in the NotificationMessage
    msg.validate()

    # get the system defined msg_type -> channel mapping
    # note, when we enable user preferences, we will
    # have to change this
    channel = get_notification_channel(None, msg.msg_type, preferred_channel=preferred_channel)

    # Get the proper message - aka payload - for the given channel
    _msg = msg.get_message_for_channel(channel.name)

    num_sent = channel.bulk_dispatch_notification(
        user_ids,
        _msg,
        exclude_user_ids=exclude_user_ids,
        channel_context=channel_context
    )

    return num_sent