Example #1
0
def _add_user(caller, user, state):
    """
    Adds a user to the course creator table with the specified state.

    If the user is already in the table, this method is a no-op
    (state will not be changed).
    """
    if not caller.is_active or not caller.is_authenticated or not caller.is_staff:
        raise PermissionDenied

    if CourseCreator.objects.filter(user=user).count() == 0:
        entry = CourseCreator(user=user, state=state)
        entry.save()
Example #2
0
    def _set_user_denied(self):
        """
        Sets course creator status to denied in admin table.
        """
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.deny_request = HttpRequest()
        self.deny_request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

        self.table_entry.state = CourseCreator.DENIED
        self.creator_admin.save_model(self.deny_request, self.table_entry, None, True)
Example #3
0
def _add_user(user, state):
    """
    Adds a user to the course creator table with the specified state.

    Returns True if user was added to table, else False.

    If the user is already in the table, this method is a no-op
    (state will not be changed, method will return False).

    If the user is marked as is_staff, this method is a no-op (False will be returned).
    """
    if not user.is_staff and CourseCreator.objects.filter(user=user).count() == 0:
        entry = CourseCreator(user=user, state=state)
        entry.save()
        return True

    return False
Example #4
0
    def setUp(self):
        """ Test case setup """
        self.user = User.objects.create_user('test_user', '*****@*****.**', 'foo')
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.admin = User.objects.create_user('Mark', '*****@*****.**', 'foo')
        self.admin.is_staff = True

        self.request = HttpRequest()
        self.request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

        self.studio_request_email = '*****@*****.**'
        self.enable_creator_group_patch = {
            "ENABLE_CREATOR_GROUP": True,
            "STUDIO_REQUEST_EMAIL": self.studio_request_email
        }
Example #5
0
    def setUp(self):
        """ Test case setup """
        self.user = User.objects.create_user('test_user', '*****@*****.**', 'foo')
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.admin = User.objects.create_user('Mark', '*****@*****.**', 'foo')
        self.admin.is_staff = True

        self.request = HttpRequest()
        self.request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())
Example #6
0
    def setUp(self):
        """ Test case setup """
        self.user = User.objects.create_user('test_user', '*****@*****.**', 'foo')
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.admin = User.objects.create_user('Mark', '*****@*****.**', 'foo')
        self.admin.is_staff = True

        self.request = HttpRequest()
        self.request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

        self.studio_request_email = '*****@*****.**'
        self.enable_creator_group_patch = {
            "ENABLE_CREATOR_GROUP": True,
            "STUDIO_REQUEST_EMAIL": self.studio_request_email
        }
Example #7
0
class CourseCreatorAdminTest(TestCase):
    """
    Tests for course creator admin.
    """
    def setUp(self):
        """ Test case setup """
        super(CourseCreatorAdminTest, self).setUp()
        self.user = User.objects.create_user('test_user',
                                             '*****@*****.**',
                                             'foo')
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.admin = User.objects.create_user('Mark', '*****@*****.**',
                                              'foo')
        self.admin.is_staff = True

        self.request = HttpRequest()
        self.request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

        self.studio_request_email = '*****@*****.**'
        self.enable_creator_group_patch = {
            "ENABLE_CREATOR_GROUP": True,
            "STUDIO_REQUEST_EMAIL": self.studio_request_email
        }

    @mock.patch('course_creators.admin.render_to_string',
                mock.Mock(side_effect=mock_render_to_string, autospec=True))
    @mock.patch('django.contrib.auth.models.User.email_user')
    def test_change_status(self, email_user):
        """
        Tests that updates to state impact the creator group maintained in authz.py and that e-mails are sent.
        """
        def change_state_and_verify_email(state, is_creator):
            """ Changes user state, verifies creator status, and verifies e-mail is sent based on transition """
            self._change_state(state)
            self.assertEqual(
                is_creator, auth.user_has_role(self.user, CourseCreatorRole()))

            context = {'studio_request_email': self.studio_request_email}
            if state == CourseCreator.GRANTED:
                template = 'emails/course_creator_granted.txt'
            elif state == CourseCreator.DENIED:
                template = 'emails/course_creator_denied.txt'
            else:
                template = 'emails/course_creator_revoked.txt'
            email_user.assert_called_with(
                mock_render_to_string('emails/course_creator_subject.txt',
                                      context),
                mock_render_to_string(template, context),
                self.studio_request_email)

        with mock.patch.dict('django.conf.settings.FEATURES',
                             self.enable_creator_group_patch):

            # User is initially unrequested.
            self.assertFalse(auth.user_has_role(self.user,
                                                CourseCreatorRole()))

            change_state_and_verify_email(CourseCreator.GRANTED, True)

            change_state_and_verify_email(CourseCreator.DENIED, False)

            change_state_and_verify_email(CourseCreator.GRANTED, True)

            change_state_and_verify_email(CourseCreator.PENDING, False)

            change_state_and_verify_email(CourseCreator.GRANTED, True)

            change_state_and_verify_email(CourseCreator.UNREQUESTED, False)

            change_state_and_verify_email(CourseCreator.DENIED, False)

    @mock.patch('course_creators.admin.render_to_string',
                mock.Mock(side_effect=mock_render_to_string, autospec=True))
    def test_mail_admin_on_pending(self):
        """
        Tests that the admin account is notified when a user is in the 'pending' state.
        """
        def check_admin_message_state(state, expect_sent_to_admin,
                                      expect_sent_to_user):
            """ Changes user state and verifies e-mail sent to admin address only when pending. """
            mail.outbox = []
            self._change_state(state)

            # If a message is sent to the user about course creator status change, it will be the first
            # message sent. Admin message will follow.
            base_num_emails = 1 if expect_sent_to_user else 0
            if expect_sent_to_admin:
                context = {
                    'user_name': "test_user",
                    'user_email': u'*****@*****.**'
                }
                self.assertEquals(base_num_emails + 1, len(mail.outbox),
                                  'Expected admin message to be sent')
                sent_mail = mail.outbox[base_num_emails]
                self.assertEquals(
                    mock_render_to_string(
                        'emails/course_creator_admin_subject.txt', context),
                    sent_mail.subject)
                self.assertEquals(
                    mock_render_to_string(
                        'emails/course_creator_admin_user_pending.txt',
                        context), sent_mail.body)
                self.assertEquals(self.studio_request_email,
                                  sent_mail.from_email)
                self.assertEqual([self.studio_request_email], sent_mail.to)
            else:
                self.assertEquals(base_num_emails, len(mail.outbox))

        with mock.patch.dict('django.conf.settings.FEATURES',
                             self.enable_creator_group_patch):
            # E-mail message should be sent to admin only when new state is PENDING, regardless of what
            # previous state was (unless previous state was already PENDING).
            # E-mail message sent to user only on transition into and out of GRANTED state.
            check_admin_message_state(CourseCreator.UNREQUESTED,
                                      expect_sent_to_admin=False,
                                      expect_sent_to_user=False)
            check_admin_message_state(CourseCreator.PENDING,
                                      expect_sent_to_admin=True,
                                      expect_sent_to_user=False)
            check_admin_message_state(CourseCreator.GRANTED,
                                      expect_sent_to_admin=False,
                                      expect_sent_to_user=True)
            check_admin_message_state(CourseCreator.DENIED,
                                      expect_sent_to_admin=False,
                                      expect_sent_to_user=True)
            check_admin_message_state(CourseCreator.GRANTED,
                                      expect_sent_to_admin=False,
                                      expect_sent_to_user=True)
            check_admin_message_state(CourseCreator.PENDING,
                                      expect_sent_to_admin=True,
                                      expect_sent_to_user=True)
            check_admin_message_state(CourseCreator.PENDING,
                                      expect_sent_to_admin=False,
                                      expect_sent_to_user=False)
            check_admin_message_state(CourseCreator.DENIED,
                                      expect_sent_to_admin=False,
                                      expect_sent_to_user=True)

    def _change_state(self, state):
        """ Helper method for changing state """
        self.table_entry.state = state
        self.creator_admin.save_model(self.request, self.table_entry, None,
                                      True)

    def test_add_permission(self):
        """
        Tests that staff cannot add entries
        """
        self.assertFalse(self.creator_admin.has_add_permission(self.request))

    def test_delete_permission(self):
        """
        Tests that staff cannot delete entries
        """
        self.assertFalse(self.creator_admin.has_delete_permission(
            self.request))

    def test_change_permission(self):
        """
        Tests that only staff can change entries
        """
        self.assertTrue(self.creator_admin.has_change_permission(self.request))

        self.request.user = self.user
        self.assertFalse(self.creator_admin.has_change_permission(
            self.request))

    def test_rate_limit_login(self):
        with mock.patch.dict('django.conf.settings.FEATURES',
                             {'ENABLE_CREATOR_GROUP': True}):
            post_params = {
                'username': self.user.username,
                'password': '******'
            }
            # try logging in 30 times, the default limit in the number of failed
            # login attempts in one 5 minute period before the rate gets limited
            for _ in xrange(30):
                response = self.client.post('/admin/login/', post_params)
                self.assertEquals(response.status_code, 200)

            response = self.client.post('/admin/login/', post_params)
            # Since we are using the default rate limit behavior, we are
            # expecting this to return a 403 error to indicate that there have
            # been too many attempts
            self.assertEquals(response.status_code, 403)
Example #8
0
class CourseCreatorAdminTest(TestCase):
    """
    Tests for course creator admin.
    """

    def setUp(self):
        """ Test case setup """
        self.user = User.objects.create_user('test_user', '*****@*****.**', 'foo')
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.admin = User.objects.create_user('Mark', '*****@*****.**', 'foo')
        self.admin.is_staff = True

        self.request = HttpRequest()
        self.request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

        self.studio_request_email = '*****@*****.**'
        self.enable_creator_group_patch = {
            "ENABLE_CREATOR_GROUP": True,
            "STUDIO_REQUEST_EMAIL": self.studio_request_email
        }

    @mock.patch('course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True))
    @mock.patch('django.contrib.auth.models.User.email_user')
    def test_change_status(self, email_user):
        """
        Tests that updates to state impact the creator group maintained in authz.py and that e-mails are sent.
        """

        def change_state_and_verify_email(state, is_creator):
            """ Changes user state, verifies creator status, and verifies e-mail is sent based on transition """
            self._change_state(state)
            self.assertEqual(is_creator, auth.has_access(self.user, CourseCreatorRole()))

            context = {'studio_request_email': self.studio_request_email}
            if state == CourseCreator.GRANTED:
                template = 'emails/course_creator_granted.txt'
            elif state == CourseCreator.DENIED:
                template = 'emails/course_creator_denied.txt'
            else:
                template = 'emails/course_creator_revoked.txt'
            email_user.assert_called_with(
                mock_render_to_string('emails/course_creator_subject.txt', context),
                mock_render_to_string(template, context),
                self.studio_request_email
            )

        with mock.patch.dict('django.conf.settings.FEATURES', self.enable_creator_group_patch):

            # User is initially unrequested.
            self.assertFalse(auth.has_access(self.user, CourseCreatorRole()))

            change_state_and_verify_email(CourseCreator.GRANTED, True)

            change_state_and_verify_email(CourseCreator.DENIED, False)

            change_state_and_verify_email(CourseCreator.GRANTED, True)

            change_state_and_verify_email(CourseCreator.PENDING, False)

            change_state_and_verify_email(CourseCreator.GRANTED, True)

            change_state_and_verify_email(CourseCreator.UNREQUESTED, False)

            change_state_and_verify_email(CourseCreator.DENIED, False)

    @mock.patch('course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True))
    def test_mail_admin_on_pending(self):
        """
        Tests that the admin account is notified when a user is in the 'pending' state.
        """

        def check_admin_message_state(state, expect_sent_to_admin, expect_sent_to_user):
            """ Changes user state and verifies e-mail sent to admin address only when pending. """
            mail.outbox = []
            self._change_state(state)

            # If a message is sent to the user about course creator status change, it will be the first
            # message sent. Admin message will follow.
            base_num_emails = 1 if expect_sent_to_user else 0
            if expect_sent_to_admin:
                context = {'user_name': "test_user", 'user_email': '*****@*****.**'}
                self.assertEquals(base_num_emails + 1, len(mail.outbox), 'Expected admin message to be sent')
                sent_mail = mail.outbox[base_num_emails]
                self.assertEquals(
                    mock_render_to_string('emails/course_creator_admin_subject.txt', context),
                    sent_mail.subject
                )
                self.assertEquals(
                    mock_render_to_string('emails/course_creator_admin_user_pending.txt', context),
                    sent_mail.body
                )
                self.assertEquals(self.studio_request_email, sent_mail.from_email)
                self.assertEqual([self.studio_request_email], sent_mail.to)
            else:
                self.assertEquals(base_num_emails, len(mail.outbox))

        with mock.patch.dict('django.conf.settings.FEATURES', self.enable_creator_group_patch):
            # E-mail message should be sent to admin only when new state is PENDING, regardless of what
            # previous state was (unless previous state was already PENDING).
            # E-mail message sent to user only on transition into and out of GRANTED state.
            check_admin_message_state(CourseCreator.UNREQUESTED, expect_sent_to_admin=False, expect_sent_to_user=False)
            check_admin_message_state(CourseCreator.PENDING, expect_sent_to_admin=True, expect_sent_to_user=False)
            check_admin_message_state(CourseCreator.GRANTED, expect_sent_to_admin=False, expect_sent_to_user=True)
            check_admin_message_state(CourseCreator.DENIED, expect_sent_to_admin=False, expect_sent_to_user=True)
            check_admin_message_state(CourseCreator.GRANTED, expect_sent_to_admin=False, expect_sent_to_user=True)
            check_admin_message_state(CourseCreator.PENDING, expect_sent_to_admin=True, expect_sent_to_user=True)
            check_admin_message_state(CourseCreator.PENDING, expect_sent_to_admin=False, expect_sent_to_user=False)
            check_admin_message_state(CourseCreator.DENIED, expect_sent_to_admin=False, expect_sent_to_user=True)

    def _change_state(self, state):
        """ Helper method for changing state """
        self.table_entry.state = state
        self.creator_admin.save_model(self.request, self.table_entry, None, True)

    def test_add_permission(self):
        """
        Tests that staff cannot add entries
        """
        self.assertFalse(self.creator_admin.has_add_permission(self.request))

    def test_delete_permission(self):
        """
        Tests that staff cannot delete entries
        """
        self.assertFalse(self.creator_admin.has_delete_permission(self.request))

    def test_change_permission(self):
        """
        Tests that only staff can change entries
        """
        self.assertTrue(self.creator_admin.has_change_permission(self.request))

        self.request.user = self.user
        self.assertFalse(self.creator_admin.has_change_permission(self.request))

    def test_rate_limit_login(self):
        with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_CREATOR_GROUP': True}):
            post_params = {'username': self.user.username, 'password': '******'}
            # try logging in 30 times, the default limit in the number of failed
            # login attempts in one 5 minute period before the rate gets limited
            for _ in xrange(30):
                response = self.client.post('/admin/', post_params)
                self.assertEquals(response.status_code, 200)

            response = self.client.post('/admin/', post_params)
            # Since we are using the default rate limit behavior, we are
            # expecting this to return a 403 error to indicate that there have
            # been too many attempts
            self.assertEquals(response.status_code, 403)
Example #9
0
class IndexCourseCreatorTests(CourseTestCase):
    """
    Tests the various permutations of course creator status.
    """
    def setUp(self):
        super(IndexCourseCreatorTests, self).setUp()

        self.index_url = reverse("index")
        self.request_access_url = reverse("request_course_creator")

        # Disable course creation takes precedence over enable creator group. I have enabled the
        # latter to make this clear.
        self.disable_course_creation = {
            "DISABLE_COURSE_CREATION": True,
            "ENABLE_CREATOR_GROUP": True,
            'STAFF_EMAIL': '*****@*****.**',
        }

        self.enable_creator_group = {"ENABLE_CREATOR_GROUP": True}

        self.admin = User.objects.create_user('Mark', '*****@*****.**', 'foo')
        self.admin.is_staff = True

    def test_get_course_creator_status_disable_creation(self):
        # DISABLE_COURSE_CREATION is True (this is the case on edx, where we have a marketing site).
        # Only edx staff can create courses.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.disable_course_creation):
            self.assertTrue(self.user.is_staff)
            self.assertEquals('granted', _get_course_creator_status(self.user))
            self._set_user_non_staff()
            self.assertFalse(self.user.is_staff)
            self.assertEquals('disallowed_for_this_site', _get_course_creator_status(self.user))

    def test_get_course_creator_status_default_cause(self):
        # Neither ENABLE_CREATOR_GROUP nor DISABLE_COURSE_CREATION are enabled. Anyone can create a course.
        self.assertEquals('granted', _get_course_creator_status(self.user))
        self._set_user_non_staff()
        self.assertEquals('granted', _get_course_creator_status(self.user))

    def test_get_course_creator_status_creator_group(self):
        # ENABLE_CREATOR_GROUP is True. This is the case on edge.
        # Only staff members and users who have been granted access can create courses.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.enable_creator_group):
            # Staff members can always create courses.
            self.assertEquals('granted', _get_course_creator_status(self.user))
            # Non-staff must request access.
            self._set_user_non_staff()
            self.assertEquals('unrequested', _get_course_creator_status(self.user))
            # Staff user requests access.
            self.client.post(self.request_access_url)
            self.assertEquals('pending', _get_course_creator_status(self.user))

    def test_get_course_creator_status_creator_group_granted(self):
        # ENABLE_CREATOR_GROUP is True. This is the case on edge.
        # Check return value for a non-staff user who has been granted access.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.enable_creator_group):
            self._set_user_non_staff()
            add_user_with_status_granted(self.admin, self.user)
            self.assertEquals('granted', _get_course_creator_status(self.user))

    def test_get_course_creator_status_creator_group_denied(self):
        # ENABLE_CREATOR_GROUP is True. This is the case on edge.
        # Check return value for a non-staff user who has been denied access.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.enable_creator_group):
            self._set_user_non_staff()
            self._set_user_denied()
            self.assertEquals('denied', _get_course_creator_status(self.user))

    def test_disable_course_creation_enabled_non_staff(self):
        # Test index page content when DISABLE_COURSE_CREATION is True, non-staff member.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.disable_course_creation):
            self._set_user_non_staff()
            self._assert_cannot_create()

    def test_disable_course_creation_enabled_staff(self):
        # Test index page content when DISABLE_COURSE_CREATION is True, staff member.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.disable_course_creation):
            resp = self._assert_can_create()
            self.assertFalse('Email staff to create course' in resp.content)

    def test_can_create_by_default(self):
        # Test index page content with neither ENABLE_CREATOR_GROUP nor DISABLE_COURSE_CREATION enabled.
        # Anyone can create a course.
        self._assert_can_create()
        self._set_user_non_staff()
        self._assert_can_create()

    def test_course_creator_group_enabled(self):
        # Test index page content with ENABLE_CREATOR_GROUP True.
        # Staff can always create a course, others must request access.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.enable_creator_group):
            # Staff members can always create courses.
            self._assert_can_create()

            # Non-staff case.
            self._set_user_non_staff()
            resp = self._assert_cannot_create()
            self.assertTrue(self.request_access_url in resp.content)

            # Now request access.
            self.client.post(self.request_access_url)

            # Still cannot create a course, but the "request access button" is no longer there.
            resp = self._assert_cannot_create()
            self.assertFalse(self.request_access_url in resp.content)
            self.assertTrue('has-status is-pending' in resp.content)

    def test_course_creator_group_granted(self):
        # Test index page content with ENABLE_CREATOR_GROUP True, non-staff member with access granted.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.enable_creator_group):
            self._set_user_non_staff()
            add_user_with_status_granted(self.admin, self.user)
            self._assert_can_create()

    def test_course_creator_group_denied(self):
        # Test index page content with ENABLE_CREATOR_GROUP True, non-staff member with access denied.
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', self.enable_creator_group):
            self._set_user_non_staff()
            self._set_user_denied()
            resp = self._assert_cannot_create()
            self.assertFalse(self.request_access_url in resp.content)
            self.assertTrue('has-status is-denied' in resp.content)

    def _assert_can_create(self):
        """
        Helper method that posts to the index page and checks that the user can create a course.

        Returns the response from the post.
        """
        resp = self.client.post(self.index_url)
        self.assertTrue('new-course-button' in resp.content)
        self.assertFalse(self.request_access_url in resp.content)
        self.assertFalse('Email staff to create course' in resp.content)
        return resp

    def _assert_cannot_create(self):
        """
        Helper method that posts to the index page and checks that the user cannot create a course.

        Returns the response from the post.
        """
        resp = self.client.post(self.index_url)
        self.assertFalse('new-course-button' in resp.content)
        return resp

    def _set_user_non_staff(self):
        """
        Sets user as non-staff.
        """
        self.user.is_staff = False
        self.user.save()

    def _set_user_denied(self):
        """
        Sets course creator status to denied in admin table.
        """
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.deny_request = HttpRequest()
        self.deny_request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

        self.table_entry.state = CourseCreator.DENIED
        self.creator_admin.save_model(self.deny_request, self.table_entry, None, True)
Example #10
0
class CourseCreatorAdminTest(TestCase):
    """
    Tests for course creator admin.
    """

    def setUp(self):
        """ Test case setup """
        self.user = User.objects.create_user('test_user', '*****@*****.**', 'foo')
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.admin = User.objects.create_user('Mark', '*****@*****.**', 'foo')
        self.admin.is_staff = True

        self.request = HttpRequest()
        self.request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

    @mock.patch('course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True))
    @mock.patch('django.contrib.auth.models.User.email_user')
    def test_change_status(self, email_user):
        """
        Tests that updates to state impact the creator group maintained in authz.py and that e-mails are sent.
        """
        STUDIO_REQUEST_EMAIL = '*****@*****.**' 
        
        def change_state(state, is_creator):
            """ Helper method for changing state """
            self.table_entry.state = state
            self.creator_admin.save_model(self.request, self.table_entry, None, True)
            self.assertEqual(is_creator, is_user_in_creator_group(self.user))
            
            context = {'studio_request_email': STUDIO_REQUEST_EMAIL}
            if state == CourseCreator.GRANTED:
                template = 'emails/course_creator_granted.txt'
            elif state == CourseCreator.DENIED:
                template = 'emails/course_creator_denied.txt'
            else:
                template = 'emails/course_creator_revoked.txt'
            email_user.assert_called_with(
                mock_render_to_string('emails/course_creator_subject.txt', context),
                mock_render_to_string(template, context),
                STUDIO_REQUEST_EMAIL
            )

        with mock.patch.dict(
            'django.conf.settings.MITX_FEATURES',
            {
                "ENABLE_CREATOR_GROUP": True,
                "STUDIO_REQUEST_EMAIL": STUDIO_REQUEST_EMAIL
            }):

            # User is initially unrequested.
            self.assertFalse(is_user_in_creator_group(self.user))

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.DENIED, False)

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.PENDING, False)

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.UNREQUESTED, False)

    def test_add_permission(self):
        """
        Tests that staff cannot add entries
        """
        self.assertFalse(self.creator_admin.has_add_permission(self.request))

    def test_delete_permission(self):
        """
        Tests that staff cannot delete entries
        """
        self.assertFalse(self.creator_admin.has_delete_permission(self.request))

    def test_change_permission(self):
        """
        Tests that only staff can change entries
        """
        self.assertTrue(self.creator_admin.has_change_permission(self.request))

        self.request.user = self.user
        self.assertFalse(self.creator_admin.has_change_permission(self.request))
Example #11
0
class CourseCreatorAdminTest(TestCase):
    """
    Tests for course creator admin.
    """

    def setUp(self):
        """ Test case setup """
        self.user = User.objects.create_user('test_user', '*****@*****.**', 'foo')
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.admin = User.objects.create_user('Mark', '*****@*****.**', 'foo')
        self.admin.is_staff = True

        self.request = HttpRequest()
        self.request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

    @mock.patch('course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True))
    @mock.patch('django.contrib.auth.models.User.email_user')
    def test_change_status(self, email_user):
        """
        Tests that updates to state impact the creator group maintained in authz.py and that e-mails are sent.
        """
        STUDIO_REQUEST_EMAIL = '*****@*****.**'

        def change_state(state, is_creator):
            """ Helper method for changing state """
            self.table_entry.state = state
            self.creator_admin.save_model(self.request, self.table_entry, None, True)
            self.assertEqual(is_creator, is_user_in_creator_group(self.user))

            context = {'studio_request_email': STUDIO_REQUEST_EMAIL}
            if state == CourseCreator.GRANTED:
                template = 'emails/course_creator_granted.txt'
            elif state == CourseCreator.DENIED:
                template = 'emails/course_creator_denied.txt'
            else:
                template = 'emails/course_creator_revoked.txt'
            email_user.assert_called_with(
                mock_render_to_string('emails/course_creator_subject.txt', context),
                mock_render_to_string(template, context),
                STUDIO_REQUEST_EMAIL
            )

        with mock.patch.dict(
            'django.conf.settings.MITX_FEATURES',
            {
                "ENABLE_CREATOR_GROUP": True,
                "STUDIO_REQUEST_EMAIL": STUDIO_REQUEST_EMAIL
            }
        ):

            # User is initially unrequested.
            self.assertFalse(is_user_in_creator_group(self.user))

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.DENIED, False)

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.PENDING, False)

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.UNREQUESTED, False)

    def test_add_permission(self):
        """
        Tests that staff cannot add entries
        """
        self.assertFalse(self.creator_admin.has_add_permission(self.request))

    def test_delete_permission(self):
        """
        Tests that staff cannot delete entries
        """
        self.assertFalse(self.creator_admin.has_delete_permission(self.request))

    def test_change_permission(self):
        """
        Tests that only staff can change entries
        """
        self.assertTrue(self.creator_admin.has_change_permission(self.request))

        self.request.user = self.user
        self.assertFalse(self.creator_admin.has_change_permission(self.request))

    def test_rate_limit_login(self):
        with mock.patch.dict('django.conf.settings.MITX_FEATURES', {'ENABLE_CREATOR_GROUP': True}):
            post_params = {'username': self.user.username, 'password': '******'}
            # try logging in 30 times, the default limit in the number of failed
            # login attempts in one 5 minute period before the rate gets limited
            for _ in xrange(30):
                response = self.client.post('/admin/', post_params)
                self.assertEquals(response.status_code, 200)

            response = self.client.post('/admin/', post_params)
            # Since we are using the default rate limit behavior, we are
            # expecting this to return a 403 error to indicate that there have
            # been too many attempts
            self.assertEquals(response.status_code, 403)
Example #12
0
class CourseCreatorAdminTest(TestCase):
    """
    Tests for course creator admin.
    """

    def setUp(self):
        """ Test case setup """
        self.user = User.objects.create_user('test_user', '*****@*****.**', 'foo')
        self.table_entry = CourseCreator(user=self.user)
        self.table_entry.save()

        self.admin = User.objects.create_user('Mark', '*****@*****.**', 'foo')
        self.admin.is_staff = True

        self.request = HttpRequest()
        self.request.user = self.admin

        self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite())

    def test_change_status(self):
        """
        Tests that updates to state impact the creator group maintained in authz.py.
        """
        def change_state(state, is_creator):
            """ Helper method for changing state """
            self.table_entry.state = state
            self.creator_admin.save_model(self.request, self.table_entry, None, True)
            self.assertEqual(is_creator, is_user_in_creator_group(self.user))

        with mock.patch.dict('django.conf.settings.MITX_FEATURES', {"ENABLE_CREATOR_GROUP": True}):
            # User is initially unrequested.
            self.assertFalse(is_user_in_creator_group(self.user))

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.DENIED, False)

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.PENDING, False)

            change_state(CourseCreator.GRANTED, True)

            change_state(CourseCreator.UNREQUESTED, False)

    def test_add_permission(self):
        """
        Tests that staff cannot add entries
        """
        self.assertFalse(self.creator_admin.has_add_permission(self.request))

    def test_delete_permission(self):
        """
        Tests that staff cannot delete entries
        """
        self.assertFalse(self.creator_admin.has_delete_permission(self.request))

    def test_change_permission(self):
        """
        Tests that only staff can change entries
        """
        self.assertTrue(self.creator_admin.has_change_permission(self.request))

        self.request.user = self.user
        self.assertFalse(self.creator_admin.has_change_permission(self.request))