test_permissions.py 5.62 KB
Newer Older
1 2 3
"""
Test CRUD for authorization.
"""
4 5
import copy

6
from django.contrib.auth.models import User
7 8 9

from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from contentstore.tests.utils import AjaxEnabledTestClient
10
from opaque_keys.edx.locations import SlashSeparatedCourseKey
11
from contentstore.utils import reverse_url, reverse_course_url
12
from student.roles import CourseInstructorRole, CourseStaffRole, OrgStaffRole, OrgInstructorRole
13 14
from contentstore.views.access import has_course_access
from student import auth
15 16 17 18 19 20 21 22 23 24 25 26


class TestCourseAccess(ModuleStoreTestCase):
    """
    Course-based access (as opposed to access of a non-course xblock)
    """
    def setUp(self):
        """
        Create a staff user and log them in (creating the client).

        Create a pool of users w/o granting them any permissions
        """
27
        user_password = super(TestCourseAccess, self).setUp()
28 29

        self.client = AjaxEnabledTestClient()
30
        self.client.login(username=self.user.username, password=user_password)
31 32

        # create a course via the view handler which has a different strategy for permissions than the factory
33 34 35
        self.course_key = SlashSeparatedCourseKey('myu', 'mydept.mycourse', 'myrun')
        course_url = reverse_url('course_handler')
        self.client.ajax_post(course_url,
36
            {
37 38
                'org': self.course_key.org,
                'number': self.course_key.course,
39
                'display_name': 'My favorite course',
40
                'run': self.course_key.run,
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
            }
        )

        self.users = self._create_users()

    def _create_users(self):
        """
        Create 8 users and return them
        """
        users = []
        for i in range(8):
            username = "user{}".format(i)
            email = "test+user{}@edx.org".format(i)
            user = User.objects.create_user(username, email, 'foo')
            user.is_active = True
            user.save()
            users.append(user)
        return users

    def tearDown(self):
        """
        Reverse the setup
        """
        self.client.logout()
        ModuleStoreTestCase.tearDown(self)

    def test_get_all_users(self):
        """
        Test getting all authors for a course where their permissions run the gamut of allowed group
        types.
        """
72 73
        # first check the course creator.has explicit access (don't use has_access as is_staff
        # will trump the actual test)
74
        self.assertTrue(
75
            CourseInstructorRole(self.course_key).has_user(self.user),
76 77 78
            "Didn't add creator as instructor."
        )
        users = copy.copy(self.users)
79
        # doesn't use role.users_with_role b/c it's verifying the roles.py behavior
80 81
        user_by_role = {}
        # add the misc users to the course in different groups
82
        for role in [CourseInstructorRole, CourseStaffRole, OrgStaffRole, OrgInstructorRole]:
83
            user_by_role[role] = []
84 85 86 87 88
            # Org-based roles are created via org name, rather than course_key
            if (role is OrgStaffRole) or (role is OrgInstructorRole):
                group = role(self.course_key.org)
            else:
                group = role(self.course_key)
89 90 91
            # NOTE: this loop breaks the roles.py abstraction by purposely assigning
            # users to one of each possible groupname in order to test that has_course_access
            # and remove_user work
92 93 94 95 96 97 98
            user = users.pop()
            group.add_users(user)
            user_by_role[role].append(user)
            self.assertTrue(has_course_access(user, self.course_key), "{} does not have access".format(user))

        course_team_url = reverse_course_url('course_team_handler', self.course_key)
        response = self.client.get_html(course_team_url)
99
        for role in [CourseInstructorRole, CourseStaffRole]:  # Global and org-based roles don't appear on this page
100 101
            for user in user_by_role[role]:
                self.assertContains(response, user.email)
102

103
        # test copying course permissions
104
        copy_course_key = SlashSeparatedCourseKey('copyu', 'copydept.mycourse', 'myrun')
105 106 107 108 109
        for role in [CourseInstructorRole, CourseStaffRole, OrgStaffRole, OrgInstructorRole]:
            if (role is OrgStaffRole) or (role is OrgInstructorRole):
                auth.add_users(
                    self.user,
                    role(copy_course_key.org),
110 111
                    *role(self.course_key.org).users_with_role()
                )
112 113 114 115 116 117
            else:
                auth.add_users(
                    self.user,
                    role(copy_course_key),
                    *role(self.course_key).users_with_role()
                )
118 119
        # verify access in copy course and verify that removal from source course w/ the various
        # groupnames works
120
        for role in [CourseInstructorRole, CourseStaffRole, OrgStaffRole, OrgInstructorRole]:
121
            for user in user_by_role[role]:
122 123 124
                # forcefully decache the groups: premise is that any real request will not have
                # multiple objects repr the same user but this test somehow uses different instance
                # in above add_users call
125 126
                if hasattr(user, '_roles'):
                    del user._roles
127

128
                self.assertTrue(has_course_access(user, copy_course_key), "{} no copy access".format(user))
129 130 131 132
                if (role is OrgStaffRole) or (role is OrgInstructorRole):
                    auth.remove_users(self.user, role(self.course_key.org), user)
                else:
                    auth.remove_users(self.user, role(self.course_key), user)
133
                self.assertFalse(has_course_access(user, self.course_key), "{} remove didn't work".format(user))