Beispiel #1
0
def startup_notification_subsystem():
    """
    Initialize the Notification subsystem
    """
    try:
        startup.initialize()

        # register the scope resolvers that the runtime will be providing
        # to edx-notifications
        register_user_scope_resolver('course_enrollments', CourseEnrollmentsScopeResolver())
        register_user_scope_resolver('course_group', CourseGroupScopeResolver())
        register_user_scope_resolver('group_project_participants', GroupProjectParticipantsScopeResolver())
        register_user_scope_resolver('group_project_workgroup', GroupProjectParticipantsScopeResolver())
        register_user_scope_resolver('user_email_resolver', StudentEmailScopeResolver())

        # register namespace resolver
        register_namespace_resolver(CourseNamespaceResolver())
    except Exception, ex:
        # Note this will fail when we try to run migrations as manage.py will call startup.py
        # and startup.initialze() will try to manipulate some database tables.
        # We need to research how to identify when we are being started up as part of
        # a migration script
        log.error(
            'There was a problem initializing notifications subsystem. '
            'This could be because the database tables have not yet been created and '
            './manage.py lms syncdb needs to run setup.py. Error was "{err_msg}". Continuing...'.format(err_msg=str(ex))
        )
    def setUp(self):
        """
        start up stuff
        """

        register_user_scope_resolver('list_scope', TestListScopeResolver())

        self.store = notification_store()
        self.msg_type = self.store.save_notification_type(
            NotificationType(
                name='foo.bar',
                renderer='foo',
            )
        )

        msg = NotificationMessage(
            msg_type=self.msg_type,
            payload={'foo': 'bar'},
        )
        msg.add_payload(
            {
                'extra': 'stuff'
            },
            channel_name='other_channel'
        )
        self.msg = self.store.save_notification_message(msg)
Beispiel #3
0
    def setUp(self):
        """
        start up stuff
        """

        register_user_scope_resolver('list_scope', TestListScopeResolver())

        self.store = notification_store()
        self.msg_type = self.store.save_notification_type(
            NotificationType(
                name='foo.bar',
                renderer='foo',
            )
        )

        msg = NotificationMessage(
            msg_type=self.msg_type,
            payload={'foo': 'bar'},
        )
        msg.add_payload(
            {
                'extra': 'stuff'
            },
            channel_name='other_channel'
        )
        self.msg = self.store.save_notification_message(msg)
Beispiel #4
0
    def test_publish_to_scope(self):
        """
        Make sure we can bulk publish to a number of users
        passing in a resultset from a Django ORM query
        """

        register_user_scope_resolver("list_scope", TestListScopeResolver())

        msg = NotificationMessage(namespace='test-runner',
                                  msg_type=self.msg_type,
                                  payload={'foo': 'bar'})

        bulk_publish_notification_to_scope(
            scope_name="list_scope",
            # the TestListScopeResolver expects a "range" property in the context
            scope_context={"range": 5},
            msg=msg)

        for user_id in range(4):
            # have to fudge this a bit as the contract on user_id
            # says > 0 only allowed
            user_id = user_id + 1
            notifications = get_notifications_for_user(user_id)

            self.assertTrue(isinstance(notifications, list))
            self.assertEqual(len(notifications), 1)
            self.assertTrue(isinstance(notifications[0], UserNotification))
Beispiel #5
0
def startup_notification_subsystem():
    """
    Initialize the Notification subsystem
    """
    try:
        startup.initialize()

        # register the scope resolvers that the runtime will be providing
        # to edx-notifications
        register_user_scope_resolver('course_enrollments',
                                     CourseEnrollmentsScopeResolver())
        register_user_scope_resolver('course_group',
                                     CourseGroupScopeResolver())
        register_user_scope_resolver('group_project_participants',
                                     GroupProjectParticipantsScopeResolver())
        register_user_scope_resolver('group_project_workgroup',
                                     GroupProjectParticipantsScopeResolver())
        register_user_scope_resolver('user_email_resolver',
                                     StudentEmailScopeResolver())

        # register namespace resolver
        register_namespace_resolver(CourseNamespaceResolver())
    except Exception, ex:
        # Note this will fail when we try to run migrations as manage.py will call startup.py
        # and startup.initialze() will try to manipulate some database tables.
        # We need to research how to identify when we are being started up as part of
        # a migration script
        log.error(
            'There was a problem initializing notifications subsystem. '
            'This could be because the database tables have not yet been created and '
            './manage.py lms syncdb needs to run setup.py. Error was "{err_msg}". Continuing...'
            .format(err_msg=str(ex)))
    def test_cant_no_scope(self):
        """
        Asserts that if a scope cannot be resolved, then nothing is sent
        """

        self.timer_for_group.context['distribution_scope'][
            'scope_name'] = 'nonexisting'

        results = self.callback.notification_timer_callback(
            self.timer_for_group)

        self.assertIsNotNone(results)
        self.assertEqual(results['num_dispatched'], 0)
        self.assertEqual(len(results['errors']), 1)
        self.assertIsNone(results['reschedule_in_mins'])

        register_user_scope_resolver('nonexisting', TestListScopeResolver())

        results = self.callback.notification_timer_callback(
            self.timer_for_group)

        self.assertIsNotNone(results)
        self.assertEqual(results['num_dispatched'], 0)
        self.assertEqual(len(results['errors']), 1)
        self.assertIsNone(results['reschedule_in_mins'])
    def test_publish_to_scope(self):
        """
        Make sure we can bulk publish to a number of users
        passing in a resultset from a Django ORM query
        """

        register_user_scope_resolver("list_scope", TestListScopeResolver())

        msg = NotificationMessage(namespace="test-runner", msg_type=self.msg_type, payload={"foo": "bar"})

        bulk_publish_notification_to_scope(
            scope_name="list_scope",
            # the TestListScopeResolver expects a "range" property in the context
            scope_context={"range": 5},
            msg=msg,
        )

        for user_id in range(4):
            # have to fudge this a bit as the contract on user_id
            # says > 0 only allowed
            user_id = user_id + 1
            notifications = get_notifications_for_user(user_id)

            self.assertTrue(isinstance(notifications, list))
            self.assertEqual(len(notifications), 1)
            self.assertTrue(isinstance(notifications[0], UserNotification))
Beispiel #8
0
    def test_no_resolution(self):
        """
        Asserts that None is returned if the Resolvers can resolve
        """

        register_user_scope_resolver('none_resolver', TestListScopeResolver())

        self.assertIsNone(resolve_user_scope('none_resolver', {}))
    def test_no_resolution(self):
        """
        Asserts that None is returned if the Resolvers can resolve
        """

        register_user_scope_resolver('none_resolver', TestListScopeResolver())

        self.assertIsNone(resolve_user_scope('none_resolver', {}))
    def test_bad_return_type(self):
        """
        Asserts that we can't allow for an illegal type to
        be returned
        """

        register_user_scope_resolver('badtype_scope', TestListScopeResolver())

        with self.assertRaises(TypeError):
            resolve_user_scope('badtype_scope', {})
Beispiel #11
0
    def test_bad_return_type(self):
        """
        Asserts that we can't allow for an illegal type to
        be returned
        """

        register_user_scope_resolver('badtype_scope', TestListScopeResolver())

        with self.assertRaises(TypeError):
            resolve_user_scope('badtype_scope', {})
    def test_no_instantiation(self):
        """
        Asserts that NotificationScopeResolver is an abstract base clas
        """

        with self.assertRaises(TypeError):
            NotificationUserScopeResolver()

        register_user_scope_resolver('bad_scope', BadTestScopeResolver())

        with self.assertRaises(NotImplementedError):
            resolve_user_scope('bad_scope', {})
Beispiel #13
0
    def test_no_instantiation(self):
        """
        Asserts that NotificationScopeResolver is an abstract base clas
        """

        with self.assertRaises(TypeError):
            NotificationUserScopeResolver()  # pylint: disable=abstract-class-instantiated

        register_user_scope_resolver('bad_scope', BadTestScopeResolver())

        with self.assertRaises(NotImplementedError):
            resolve_user_scope('bad_scope', {})
    def setUp(self):
        """
        start up stuff
        """

        register_user_scope_resolver('list_scope', TestListScopeResolver())

        self.store = notification_store()
        self.callback = NotificationDispatchMessageCallback()

        self.msg_type = self.store.save_notification_type(
            NotificationType(
                name='foo.bar',
                renderer='foo',
            )
        )

        self.msg = self.store.save_notification_message(
            NotificationMessage(
                msg_type=self.msg_type,
                payload={'foo': 'bar'},
            )
        )

        self.timer_for_user = NotificationCallbackTimer(
            context={
                'msg_id': self.msg.id,
                'distribution_scope': {
                    'scope_name': 'user',
                    'scope_context': {
                        'user_id': 1
                    }
                }
            }
        )

        self.timer_for_group = NotificationCallbackTimer(
            context={
                'msg_id': self.msg.id,
                'distribution_scope': {
                    'scope_name': 'list_scope',
                    'scope_context': {
                        'range': 5
                    }
                }
            }
        )
    def setUp(self):
        """
        start up stuff
        """

        register_user_scope_resolver('list_scope', TestListScopeResolver())

        self.store = notification_store()
        self.callback = NotificationDispatchMessageCallback()

        self.msg_type = self.store.save_notification_type(
            NotificationType(
                name='foo.bar',
                renderer='foo',
            ))

        self.msg = self.store.save_notification_message(
            NotificationMessage(
                msg_type=self.msg_type,
                payload={'foo': 'bar'},
            ))

        self.timer_for_user = NotificationCallbackTimer(
            context={
                'msg_id': self.msg.id,
                'distribution_scope': {
                    'scope_name': 'user',
                    'scope_context': {
                        'user_id': 1
                    }
                }
            })

        self.timer_for_group = NotificationCallbackTimer(
            context={
                'msg_id': self.msg.id,
                'distribution_scope': {
                    'scope_name': 'list_scope',
                    'scope_context': {
                        'range': 5
                    }
                }
            })
    def setUp(self):
        clear_user_scope_resolvers()
        register_user_scope_resolver('list_scope', TestListScopeResolver())
        register_user_scope_resolver('generator_scope', TestGeneratorScopeResolver())
        register_user_scope_resolver('values_list_query_set', DjangoORMResolver())
        register_user_scope_resolver('values_query_set', DjangoORMResolver())

        # create a test user in the Django ORM

        self.test_user = User(username='******', email='*****@*****.**', first_name='Foo', last_name='Bar')
        self.test_user.is_active = True
        self.test_user.save()
    def setUp(self):
        clear_user_scope_resolvers()
        register_user_scope_resolver('list_scope', TestListScopeResolver())
        register_user_scope_resolver('generator_scope', TestGeneratorScopeResolver())
        register_user_scope_resolver('values_list_query_set', DjangoORMResolver())
        register_user_scope_resolver('values_query_set', DjangoORMResolver())

        # create a test user in the Django ORM

        self.test_user = User(username='******', email='*****@*****.**', first_name='Foo', last_name='Bar')
        self.test_user.is_active = True
        self.test_user.save()
    def setUp(self):
        """
        Test setup
        """
        startup.initialize()
        register_user_scope_resolver('user_email_resolver', TestUserResolver())
        self.store = notification_store()

        self.msg_type = self.store.get_notification_type(name='open-edx.lms.discussions.reply-to-thread')

        self.msg = NotificationMessage(
            namespace='test-runner',
            msg_type=self.msg_type,
            payload={
                '_schema_version': 1,
                '_click_link': 'http://localhost',
                'original_poster_id': 1,
                'action_username': '******',
                'thread_title': 'A demo posting to the discussion forums',
            }
        )
    def setUp(self):
        """
        Test setup
        """
        startup.initialize()
        register_user_scope_resolver("user_email_resolver", TestUserResolver())
        self.store = notification_store()

        self.msg_type = self.store.get_notification_type(name="open-edx.lms.discussions.reply-to-thread")

        self.msg = NotificationMessage(
            namespace="test-runner",
            msg_type=self.msg_type,
            payload={
                "_schema_version": 1,
                "_click_link": "http://localhost",
                "original_poster_id": 1,
                "action_username": "******",
                "thread_title": "A demo posting to the discussion forums",
            },
        )
    def test_cant_no_scope(self):
        """
        Asserts that if a scope cannot be resolved, then nothing is sent
        """

        self.timer_for_group.context['distribution_scope']['scope_name'] = 'nonexisting'

        results = self.callback.notification_timer_callback(self.timer_for_group)

        self.assertIsNotNone(results)
        self.assertEqual(results['num_dispatched'], 0)
        self.assertEqual(len(results['errors']), 1)
        self.assertIsNone(results['reschedule_in_mins'])

        register_user_scope_resolver('nonexisting', TestListScopeResolver())

        results = self.callback.notification_timer_callback(self.timer_for_group)

        self.assertIsNotNone(results)
        self.assertEqual(results['num_dispatched'], 0)
        self.assertEqual(len(results['errors']), 1)
        self.assertIsNone(results['reschedule_in_mins'])
Beispiel #21
0
def initialize(namespace_resolver=None, register_system_types=True):
    """
    Startup entry point for the Notification subsystem
    """

    # alert the application tiers that they should register their
    # notification types, but this optional (default=True)
    if register_system_types:
        perform_type_registrations.send(sender=None)

    # alert the application tiers that they should register their
    # notification timers/callbacks
    perform_timer_registrations.send(sender=None)

    # install the system-defined Notification Preferences
    create_default_notification_preferences()

    register_user_scope_resolver('user', SingleUserScopeResolver(), {})

    if not namespace_resolver:
        namespace_resolver = DefaultNotificationNamespaceResolver()

    register_namespace_resolver(namespace_resolver, None)
Beispiel #22
0
def initialize(namespace_resolver=None, register_system_types=True):
    """
    Startup entry point for the Notification subsystem
    """

    # alert the application tiers that they should register their
    # notification types, but this optional (default=True)
    if register_system_types:
        perform_type_registrations.send(sender=None)

    # alert the application tiers that they should register their
    # notification timers/callbacks
    perform_timer_registrations.send(sender=None)

    # install the system-defined Notification Preferences
    create_default_notification_preferences()

    register_user_scope_resolver('user', SingleUserScopeResolver(), {})

    if not namespace_resolver:
        namespace_resolver = DefaultNotificationNamespaceResolver()

    register_namespace_resolver(namespace_resolver, None)
Beispiel #23
0
def index(request):
    """
    Returns a basic HTML snippet rendering of a notification count
    """
    global NAMESPACE

    if request.method == 'POST':

        register_user_scope_resolver('user_email_resolver', TestUserResolver(request.user))

        if request.POST.get('change_namespace'):
            namespace_str = request.POST['namespace']
            NAMESPACE = namespace_str if namespace_str != "None" else None
        elif request.POST.get('send_digest'):
            send_digest(request, request.POST.get('digest_email'))
        else:
            type_name = request.POST['notification_type']
            channel_name = request.POST['notification_channel']
            if not channel_name:
                channel_name = None
            msg_type = get_notification_type(type_name)

            msg = NotificationMessage(
                msg_type=msg_type,
                namespace=NAMESPACE,
                payload=CANNED_TEST_PAYLOAD[type_name],
            )

            if type_name == 'testserver.msg-with-resolved-click-link':
                msg.add_click_link_params({
                    'param1': 'param_val1',
                    'param2': 'param_val2',
                })

            publish_notification_to_user(request.user.id, msg, preferred_channel=channel_name)

    template = loader.get_template('index.html')


    # call to the helper method to build up all the context we need
    # to render the "notification_widget" that is embedded in our
    # test page
    context_dict = get_notifications_widget_context({
        'user': request.user,
        'notification_types': get_all_notification_types(),
        'global_variables': {
            'app_name': 'Notification Test Server',
            'hide_link_is_visible': settings.HIDE_LINK_IS_VISIBLE,
            'always_show_dates_on_unread': True,
            'notification_preference_tab_is_visible': settings.NOTIFICATION_PREFERENCES_IS_VISIBLE,
        },
        # for test purposes, set up a short-poll which contacts the server
        # every 10 seconds to see if there is a new notification
        #
        # NOTE: short-poll technique should not be used in a production setting with
        # any reasonable number of concurrent users. This is just for
        # testing purposes.
        #
        'refresh_watcher': {
            'name': 'short-poll',
            'args': {
                'poll_period_secs': 10,
            },
        },
        'include_framework_js': True,
        'namespace': NAMESPACE,
    })

    return HttpResponse(template.render(RequestContext(request, context_dict)))