Ejemplo n.º 1
0
def can_view_courses_for_username(requesting_user, target_username):
    """
    Determine whether `requesting_user` has permission to view courses available
    to the user identified by `target_username`.

    Arguments:
        requesting_user (User): The user requesting permission to view another
        target_username (string):
            The name of the user `requesting_user` would like
            to access.

    Return value:
        Boolean:
            `True` if `requesting_user` is authorized to view courses as
            `target_username`.  Otherwise, `False`
    Raises:
        TypeError if target_username is empty or None.
    """

    # AnonymousUser has no username, so we test for requesting_user's own
    # username before prohibiting an empty target_username.
    if requesting_user.username == target_username:
        return True
    elif not target_username:
        raise TypeError("target_username must be specified")
    else:
        staff = GlobalStaff()
        return staff.has_user(requesting_user)
Ejemplo n.º 2
0
    def test_staff_course_listing(self, default_store, mongo_calls):
        """
        Create courses and verify they take certain amount of mongo calls to call get_courses_accessible_to_user.
        Also verify that fetch accessible courses list for staff user returns CourseSummary instances.
        """

        # Assign & verify staff role to the user
        GlobalStaff().add_users(self.user)
        self.assertTrue(GlobalStaff().has_user(self.user))

        with self.store.default_store(default_store):
            # Create few courses
            for num in range(TOTAL_COURSES_COUNT):
                course_location = self.store.make_course_key('Org', 'CreatedCourse' + str(num), 'Run')
                self._create_course_with_access_groups(course_location, self.user, default_store)

        # Fetch accessible courses list & verify their count
        courses_list_by_staff, __ = get_courses_accessible_to_user(self.request)
        self.assertEqual(len(list(courses_list_by_staff)), TOTAL_COURSES_COUNT)

        # Verify fetched accessible courses list is a list of CourseSummery instances
        self.assertTrue(all(isinstance(course, CourseSummary) for course in courses_list_by_staff))

        # Now count the db queries for staff
        with check_mongo_calls(mongo_calls):
            list(_accessible_courses_summary_iter(self.request))
Ejemplo n.º 3
0
def user_has_role(user, role):
    """
    Check whether this user has access to this role (either direct or implied)
    :param user:
    :param role: an AccessRole
    """
    if not user.is_active:
        return False
    # Do cheapest check first even though it's not the direct one
    if GlobalStaff().has_user(user):
        return True
    # CourseCreator is odd b/c it can be disabled via config
    if isinstance(role, CourseCreatorRole):
        # completely shut down course creation setting
        if settings.FEATURES.get('DISABLE_COURSE_CREATION', False):
            return False
        # wide open course creation setting
        if not settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
            return True

    if role.has_user(user):
        return True
    # If not, then check inferred permissions
    if (isinstance(role, (CourseStaffRole, CourseBetaTesterRole)) and
            CourseInstructorRole(role.course_key).has_user(user)):
        return True

    return False
Ejemplo n.º 4
0
 def wrapped(request, *args, **kwargs):
     if GlobalStaff().has_user(request.user):
         return func(request, *args, **kwargs)
     else:
         return HttpResponseForbidden(
             "Must be {platform_name} staff to perform this action.".format(
                 platform_name=settings.PLATFORM_NAME))
Ejemplo n.º 5
0
def get_user_permissions(user, course_key, org=None):
    """
    Get the bitmask of permissions that this user has in the given course context.
    Can also set course_key=None and pass in an org to get the user's
    permissions for that organization as a whole.
    """
    if org is None:
        org = course_key.org
        course_key = course_key.for_branch(None)
    else:
        assert course_key is None
    # No one has studio permissions for CCX courses
    if is_ccx_course(course_key):
        return STUDIO_NO_PERMISSIONS
    all_perms = STUDIO_EDIT_ROLES | STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT
    # global staff, org instructors, and course instructors have all permissions:
    if GlobalStaff().has_user(user) or OrgInstructorRole(org=org).has_user(user):
        return all_perms
    if course_key and user_has_role(user, CourseInstructorRole(course_key)):
        return all_perms
    # Staff have all permissions except EDIT_ROLES:
    if OrgStaffRole(org=org).has_user(user) or (course_key and user_has_role(user, CourseStaffRole(course_key))):
        return STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT
    # Otherwise, for libraries, users can view only:
    if course_key and isinstance(course_key, LibraryLocator):
        if OrgLibraryUserRole(org=org).has_user(user) or user_has_role(user, LibraryUserRole(course_key)):
            return STUDIO_VIEW_USERS | STUDIO_VIEW_CONTENT
    return STUDIO_NO_PERMISSIONS
Ejemplo n.º 6
0
    def setUp(self):
        """
        Add courses with the end date set to various values
        """
        super().setUp()

        # Base course has no end date (so is active)
        self.course.end = None
        self.course.display_name = 'Active Course 1'
        self.ORG = self.course.location.org
        self.save_course()

        # Active course has end date set to tomorrow
        self.active_course = CourseFactory.create(
            display_name='Active Course 2',
            org=self.ORG,
            end=self.TOMORROW,
        )

        # Archived course has end date set to yesterday
        self.archived_course = CourseFactory.create(
            display_name='Archived Course',
            org=self.ORG,
            end=self.YESTERDAY,
        )

        # Base user has global staff access
        self.assertTrue(GlobalStaff().has_user(self.user))

        # Staff user just has course staff access
        self.staff, self.staff_password = self.create_non_staff_user()
        for course in (self.course, self.active_course, self.archived_course):
            CourseStaffRole(course.id).add_users(self.staff)
Ejemplo n.º 7
0
def get_child_locations(section_desc, request, course_id):
    """
    Returns all child locations for a section. If user is learner or masquerading as learner,
    staff only blocks are excluded.
    """
    is_staff_user = GlobalStaff().has_user(request.user) if request else False

    def is_masquerading_as_student():
        """
        Return True if user is masquerading as learner.
        """
        masquerade_settings = request.session.get(MASQUERADE_SETTINGS_KEY, {})
        course_info = masquerade_settings.get(course_id)
        return masquerade_settings and course_info and getattr(
            course_info, 'role', '') == 'student'

    def is_user_staff_and_not_masquerading_learner():
        """
        Return True if user is staff and not masquerading as learner.
        """
        return is_staff_user and not is_masquerading_as_student()

    def is_child_appendable(child_instance):
        """
        Return True if child is appendable based on request and request's user type.
        """
        return (request and is_user_staff_and_not_masquerading_learner()
                ) or not child_instance.visible_to_staff_only

    child_locs = []
    for child in section_desc.get_children():
        if not is_child_appendable(child):
            continue
        child_locs.append(child.location)
    return child_locs
Ejemplo n.º 8
0
def all_permissions_for_user_in_course(user, course_id):
    """
    Returns all the permissions the user has in the given course.
    """
    if not user.is_authenticated:
        return {}

    course = modulestore().get_course(course_id)
    if course is None:
        raise ItemNotFoundError(course_id)

    roles = Role.objects.filter(users=user, course_id=course_id)
    role_names = {role.name for role in roles}

    permission_names = set()
    for role in roles:
        # Intentional n+1 query pattern to get permissions for each role because
        # Aurora's query optimizer can't handle the join proplerly on 30M+ row
        # tables (EDUCATOR-3374). Fortunately, there are very few forum roles.
        for permission in role.permissions.all():
            if not permission_blacked_out(course, role_names, permission.name):
                permission_names.add(permission.name)

    # Prevent a circular import
    from openedx.core.djangoapps.django_comment_common.utils import GLOBAL_STAFF_ROLE_PERMISSIONS

    if GlobalStaff().has_user(user):
        for permission in GLOBAL_STAFF_ROLE_PERMISSIONS:
            permission_names.add(permission)

    return permission_names
Ejemplo n.º 9
0
def user_permissions_for_course(course, user):
    """
    Return the user's permissions over the discussion configuration of the course.
    """
    return {
        "change_provider":
        not course.has_started() or GlobalStaff().has_user(user),
    }
Ejemplo n.º 10
0
 def check_staff():
     """
     Checks for staff access
     """
     if perm != 'global':
         debug("Deny: invalid permission '%s'", perm)
         return ACCESS_DENIED
     return ACCESS_GRANTED if GlobalStaff().has_user(user) else ACCESS_DENIED
Ejemplo n.º 11
0
 def has_permission(self, request, view):
     """Returns true if the user is enrolled or is staff."""
     course_key = CourseKey.from_string(view.kwargs.get('course_id'))
     return (GlobalStaff().has_user(request.user)
             or CourseStaffRole(course_key).has_user(request.user)
             or CourseInstructorRole(course_key).has_user(request.user)
             or CourseEnrollment.is_enrolled(request.user, course_key)
             or has_discussion_privileges(request.user, course_key))
Ejemplo n.º 12
0
 def check_support():
     """Check that the user has access to the support UI. """
     if perm != 'global':
         return ACCESS_DENIED
     return (
         ACCESS_GRANTED if GlobalStaff().has_user(user) or SupportStaffRole().has_user(user)
         else ACCESS_DENIED
     )
Ejemplo n.º 13
0
    def has_permission(self, request, view):
        course_key_string = view.kwargs.get('course_id')
        course_key = validate_course_key(course_key_string)

        if GlobalStaff().has_user(request.user):
            return True

        return (CourseInstructorRole(course_key).has_user(request.user)
                or CourseStaffRole(course_key).has_user(request.user))
Ejemplo n.º 14
0
def can_call_public_api(requesting_user, course_key):
    """
    Global staff can always call the public API. Otherwise, check waffle flag.

    This is only intended for rollout purposes, and eventually everyone will be
    able to call the public API for all courses.
    """
    return GlobalStaff().has_user(
        requesting_user) or USE_FOR_OUTLINES.is_enabled(course_key)
Ejemplo n.º 15
0
def can_see_all_content(requesting_user, course_key):
    """
    Global staff, course staff, and instructors can see everything.

    There's no need to run processors to restrict results for these users.
    """
    return (GlobalStaff().has_user(requesting_user)
            or CourseStaffRole(course_key).has_user(requesting_user)
            or CourseInstructorRole(course_key).has_user(requesting_user))
Ejemplo n.º 16
0
    def setUp(self):
        """
        Add a student & teacher
        """
        super(TestCourseListing, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments

        self.student = UserFactory()
        self.teacher = UserFactory()
        GlobalStaff().add_users(self.teacher)
        self.client = Client()
        self.client.login(username=self.teacher.username, password='******')
Ejemplo n.º 17
0
    def get_user_roles(self) -> str:
        """
        Returns comma-separated roles for the given user
        """
        basic_role = self.DEFAULT_ROLE

        if GlobalStaff().has_user(self.request.user):
            basic_role = self.ADMIN_ROLE

        all_roles = [basic_role]
        return ','.join(all_roles)
Ejemplo n.º 18
0
    def is_enrolled_or_staff(self, request, program_uuid):
        """Returns true if the user is enrolled in the program or staff"""

        if GlobalStaff().has_user(request.user):
            return True

        try:
            get_program_enrollment(program_uuid=program_uuid, user=request.user)
        except ObjectDoesNotExist:
            return False
        return True
    def setUp(self):
        """
        Add a student & teacher
        """
        super().setUp()

        self.student = UserFactory()
        self.teacher = UserFactory()
        GlobalStaff().add_users(self.teacher)
        self.client = Client()
        self.client.login(username=self.teacher.username, password='******')
Ejemplo n.º 20
0
 def has_permission(self, request, view):
     """Returns true if the user is admin or staff and request method is GET."""
     course_key = CourseKey.from_string(view.kwargs.get('course_id'))
     user_roles = get_user_role_names(request.user, course_key)
     is_user_staff = bool(
         user_roles & {
             FORUM_ROLE_ADMINISTRATOR,
             FORUM_ROLE_MODERATOR,
             FORUM_ROLE_COMMUNITY_TA,
         })
     return (GlobalStaff().has_user(request.user) or request.user.is_staff
             or is_user_staff and request.method == "GET")
Ejemplo n.º 21
0
def is_user_staff_or_instructor_in_course(user, course_key):
    """
    Determines if a user is an Instructor or part of the given course's course staff.

    Also returns true for GlobalStaff.
    """
    if not isinstance(course_key, CourseKey):
        course_key = CourseKey.from_string(course_key)

    return (GlobalStaff().has_user(user)
            or CourseStaffRole(course_key).has_user(user)
            or CourseInstructorRole(course_key).has_user(user))
Ejemplo n.º 22
0
def administrative_accesses_to_course_for_user(user, course_key):
    """
    Returns types of access a user have for given course.
    """
    global_staff = GlobalStaff().has_user(user)

    staff_access = (CourseStaffRole(course_key).has_user(user)
                    or OrgStaffRole(course_key.org).has_user(user))

    instructor_access = (CourseInstructorRole(course_key).has_user(user)
                         or OrgInstructorRole(course_key.org).has_user(user))

    return global_staff, staff_access, instructor_access
Ejemplo n.º 23
0
def user_can_preview_themes(user):
    """
    Returns true if the specified user is allowed to preview themes.
    """
    if not user or user.is_anonymous:
        return False

    # In development mode, all users can preview themes
    if settings.DEBUG:
        return True

    # Otherwise, only global staff can preview themes
    return GlobalStaff().has_user(user)
    def get_jwt_token(self, request, suffix=''):
        """Generate JWT token for SSO authorization"""
        annoto_auth = self.get_annoto_settings()
        if not annoto_auth:
            msg = self.i18n_service.gettext(
                'Annoto authorization is not provided in "LTI Passports".')
            return self._json_resp({'status': 'error', 'msg': msg})

        user = self._get_user()
        if not user:
            msg = self.i18n_service.gettext('Requested user does not exists.')
            return self._json_resp({'status': 'error', 'msg': msg})

        profile_name = hasattr(
            user, 'profile') and user.profile and user.profile.name
        name = profile_name or user.get_full_name() or user.username
        photo = self._build_absolute_uri(
            request,
            get_profile_image_urls_for_user(user)['small'])

        roles = user.courseaccessrole_set.filter(
            course_id=self.course_id).values_list('role', flat=True)

        if CourseStaffRole.ROLE in roles or GlobalStaff().has_user(user):
            scope = 'super-mod'
        elif CourseInstructorRole.ROLE in roles:
            scope = 'moderator'
        else:
            scope = 'user'

        payload = {
            'exp': int(time.time() + 60 * 20),
            'iss': annoto_auth['client_id'],
            'jti': user.id,
            'name': name,
            'email': user.email,
            'photoUrl': photo,
            'scope': scope
        }

        token = jwt.encode(payload,
                           annoto_auth['client_secret'],
                           algorithm='HS256')
        return self._json_resp({
            'status':
            'ok',
            'token':
            getattr(token, 'decode', lambda: token)()
        })
Ejemplo n.º 25
0
def _check_caller_authority(caller, role):
    """
    Internal function to check whether the caller has authority to manipulate this role
    :param caller: a user
    :param role: an AccessRole
    """
    if not (caller.is_authenticated and caller.is_active):
        raise PermissionDenied
    # superuser
    if GlobalStaff().has_user(caller):
        return

    if isinstance(role, (GlobalStaff, CourseCreatorRole, OrgContentCreatorRole)):  # lint-amnesty, pylint: disable=no-else-raise
        raise PermissionDenied
    elif isinstance(role, CourseRole):  # instructors can change the roles w/in their course
        if not user_has_role(caller, CourseInstructorRole(role.course_key)):
            raise PermissionDenied
Ejemplo n.º 26
0
def get_ability(course_id, content, user):
    """
    Return a dictionary of forums-oriented actions and the user's permission to perform them
    """
    (user_group_id, content_user_group_id) = get_user_group_ids(course_id, content, user)
    return {
        'editable': check_permissions_by_view(
            user,
            course_id,
            content,
            "update_thread" if content['type'] == 'thread' else "update_comment",
            user_group_id,
            content_user_group_id
        ),
        'can_reply': check_permissions_by_view(
            user, course_id, content, "create_comment" if content['type'] == 'thread' else "create_sub_comment",
        ),
        'can_delete': check_permissions_by_view(
            user,
            course_id,
            content,
            "delete_thread" if content['type'] == 'thread' else "delete_comment",
            user_group_id,
            content_user_group_id
        ),
        'can_openclose': check_permissions_by_view(
            user,
            course_id,
            content,
            "openclose_thread" if content['type'] == 'thread' else False,
            user_group_id,
            content_user_group_id
        ),
        'can_vote': not is_content_authored_by(content, user) and check_permissions_by_view(
            user,
            course_id,
            content,
            "vote_for_thread" if content['type'] == 'thread' else "vote_for_comment"
        ),
        'can_report': not is_content_authored_by(content, user) and (check_permissions_by_view(
            user,
            course_id,
            content,
            "flag_abuse_for_thread" if content['type'] == 'thread' else "flag_abuse_for_comment"
        ) or GlobalStaff().has_user(user))
    }
Ejemplo n.º 27
0
def get_user_permissions(user, course_key, org=None):
    """
    Get the bitmask of permissions that this user has in the given course context.
    Can also set course_key=None and pass in an org to get the user's
    permissions for that organization as a whole.
    """
    if org is None:
        org = course_key.org
        course_key = course_key.for_branch(None)
    else:
        assert course_key is None
    # No one has studio permissions for CCX courses
    if is_ccx_course(course_key):
        return STUDIO_NO_PERMISSIONS
    all_perms = STUDIO_EDIT_ROLES | STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT

    # mcdaniel dec-2020: all approved course creators receive all_perms to the course templates.
    if str(course_key)[-8:] == 'Template':
        log.info(
            'common.djangoapps.student.auth.get_user_permissions() - template found. granting all_perms on: {course_key}'
            .format(course_key=course_key))
        return all_perms

    # global staff, org instructors, and course instructors have all permissions:
    if GlobalStaff().has_user(user) or OrgInstructorRole(
            org=org).has_user(user):
        return all_perms
    if course_key and user_has_role(user, CourseInstructorRole(course_key)):
        return all_perms
    # Staff have all permissions except EDIT_ROLES:
    if OrgStaffRole(org=org).has_user(user) or (course_key and user_has_role(
            user, CourseStaffRole(course_key))):
        return STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT
    # Otherwise, for libraries, users can view only:
    if course_key and isinstance(course_key, LibraryLocator):
        if OrgLibraryUserRole(org=org).has_user(user) or user_has_role(
                user, LibraryUserRole(course_key)):
            return STUDIO_VIEW_USERS | STUDIO_VIEW_CONTENT
    return STUDIO_NO_PERMISSIONS
Ejemplo n.º 28
0
    def get(self, request):
        """Gets a list of all course enrollments for a user.

        Returns a list for the currently logged in user, or for the user named by the 'user' GET
        parameter. If the username does not match that of the currently logged in user, only
        courses for which the currently logged in user has the Staff or Admin role are listed.
        As a result, a course team member can find out which of their own courses a particular
        learner is enrolled in.

        Only the Staff or Admin role (granted on the Django administrative console as the staff
        or instructor permission) in individual courses gives the requesting user access to
        enrollment data. Permissions granted at the organizational level do not give a user
        access to enrollment data for all of that organization's courses.

        Users who have the global staff permission can access all enrollment data for all
        courses.
        """
        username = request.GET.get('user', request.user.username)
        try:
            enrollment_data = api.get_enrollments(username)
        except CourseEnrollmentError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    "message":
                    ("An error occurred while retrieving enrollments for user '{username}'"
                     ).format(username=username)
                })
        if username == request.user.username or GlobalStaff().has_user(request.user) or \
                self.has_api_key_permissions(request):
            return Response(enrollment_data)
        filtered_data = []
        for enrollment in enrollment_data:
            course_key = CourseKey.from_string(
                enrollment["course_details"]["course_id"])
            if user_has_role(request.user, CourseStaffRole(course_key)):
                filtered_data.append(enrollment)
        return Response(filtered_data)
def has_staff_roles(user, course_key):
    """
    Return true if a user has any of the following roles
    Staff, Instructor, Beta Tester, Forum Community TA, Forum Group Moderator, Forum Moderator, Forum Administrator
    """
    forum_roles = [
        FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_GROUP_MODERATOR,
        FORUM_ROLE_MODERATOR, FORUM_ROLE_ADMINISTRATOR
    ]
    is_staff = CourseStaffRole(course_key).has_user(user)
    is_instructor = CourseInstructorRole(course_key).has_user(user)
    is_beta_tester = CourseBetaTesterRole(course_key).has_user(user)
    is_org_staff = OrgStaffRole(course_key.org).has_user(user)
    is_org_instructor = OrgInstructorRole(course_key.org).has_user(user)
    is_global_staff = GlobalStaff().has_user(user)
    has_forum_role = Role.user_has_role_for_course(user, course_key,
                                                   forum_roles)
    if any([
            is_staff, is_instructor, is_beta_tester, is_org_staff,
            is_org_instructor, is_global_staff, has_forum_role
    ]):
        return True
    return False
def list_course_keys(request, username, role):
    """
    Yield all available CourseKeys for the user having the given role.

    The courses returned include those for which the user identified by
    `username` has the given role.  Additionally, the logged in user
    should have permission to view courses available to that user.

    Note: This function does not use branding to determine courses.

    Arguments:
        request (HTTPRequest):
            Used to identify the logged-in user and to instantiate the course
            module to retrieve the course about description
        username (string):
            The name of the user the logged-in user would like to be
            identified as

    Keyword Arguments:
        role (string):
            Course keys are filtered such that only those for which the
            user has the specified role are returned.

    Return value:
        Yield `CourseKey` objects representing the collection of courses.

    """
    user = get_effective_user(request.user, username)

    all_course_keys = CourseOverview.get_all_course_keys()

    # Global staff have access to all courses. Filter courses for non-global staff.
    if GlobalStaff().has_user(user):
        return all_course_keys

    if role == 'staff':
        # This short-circuit implementation bypasses has_access() which we think is too slow for some users when
        # evaluating staff-level course access for Insights.  Various tickets have context on this issue: CR-2487,
        # TNL-7448, DESUPPORT-416, and probably more.
        #
        # This is a simplified implementation that does not consider org-level access grants (e.g. when course_id is
        # empty).
        filtered_course_keys = (
            CourseAccessRole.objects.filter(
                user=user,
                # Having the instructor role implies staff access.
                role__in=['staff', 'instructor'],
            )
            # We need to check against CourseOverview so that we don't return any Libraries.
            .extra(tables=['course_overviews_courseoverview'],
                   where=['course_id = course_overviews_courseoverview.id'])
            # For good measure, make sure we don't return empty course IDs.
            .exclude(course_id=CourseKeyField.Empty).order_by(
                'course_id').values_list('course_id', flat=True).distinct())
    else:
        # This is the original implementation which still covers the case where role = "instructor":
        filtered_course_keys = LazySequence(
            (course_key for course_key in all_course_keys
             if has_access(user, role, course_key)),
            est_len=len(all_course_keys))
    return filtered_course_keys