def check_start_date(user, days_early_for_beta, start, course_key, display_error_to_user=True): """ Verifies whether the given user is allowed access given the start date and the Beta offset for the given course. Arguments: display_error_to_user: If True, display this error to users in the UI. Returns: AccessResponse: Either ACCESS_GRANTED or StartDateError. """ start_dates_disabled = settings.FEATURES['DISABLE_START_DATES'] masquerading_as_student = is_masquerading_as_student(user, course_key) if start_dates_disabled and not masquerading_as_student: return ACCESS_GRANTED else: now = datetime.now(UTC) if start is None or in_preview_mode() or get_course_masquerade(user, course_key): return ACCESS_GRANTED effective_start = adjust_start_date(user, days_early_for_beta, start, course_key) if now > effective_start: return ACCESS_GRANTED return StartDateError(start, display_error_to_user=display_error_to_user)
def can_load(): """ NOTE: This does not check that the student is enrolled in the course that contains this module. We may or may not want to allow non-enrolled students to see modules. If not, views should check the course, so we don't have to hit the enrollments table on every module load. """ # If start dates are off, can always load if settings.MITX_FEATURES[ 'DISABLE_START_DATES'] and not is_masquerading_as_student( user): debug("Allow: DISABLE_START_DATES") return True # Check start date if descriptor.lms.start is not None: now = time.gmtime() effective_start = _adjust_start_date_for_beta_testers( user, descriptor) if now > effective_start: # after start date, everyone can see it debug("Allow: now > effective start date") return True # otherwise, need staff access return _has_staff_access_to_descriptor(user, descriptor, course_context) # No start date, so can always load. debug("Allow: no start date") return True
def can_load(): """ NOTE: This does not check that the student is enrolled in the course that contains this module. We may or may not want to allow non-enrolled students to see modules. If not, views should check the course, so we don't have to hit the enrollments table on every module load. """ if descriptor.visible_to_staff_only and not _has_staff_access_to_descriptor(user, descriptor, course_key): return False # If start dates are off, can always load if settings.FEATURES['DISABLE_START_DATES'] and not is_masquerading_as_student(user): debug("Allow: DISABLE_START_DATES") return True # Check start date if 'detached' not in descriptor._class_tags and descriptor.start is not None: now = datetime.now(UTC()) effective_start = _adjust_start_date_for_beta_testers( user, descriptor, course_key=course_key ) if now > effective_start: # after start date, everyone can see it debug("Allow: now > effective start date") return True # otherwise, need staff access return _has_staff_access_to_descriptor(user, descriptor, course_key) # No start date, so can always load. debug("Allow: no start date") return True
def _can_access_descriptor_with_start_date(user, descriptor, course_key): # pylint: disable=invalid-name """ Checks if a user has access to a descriptor based on its start date. If there is no start date specified, grant access. Else, check if we're past the start date. Note: We do NOT check whether the user is staff or if the descriptor is detached... it is assumed both of these are checked by the caller. Arguments: user (User): the user whose descriptor access we are checking. descriptor (AType): the descriptor for which we are checking access. where AType is any descriptor that has the attributes .location and .days_early_for_beta """ start_dates_disabled = settings.FEATURES['DISABLE_START_DATES'] if start_dates_disabled and not is_masquerading_as_student(user, course_key): return True else: now = datetime.now(UTC()) effective_start = _adjust_start_date_for_beta_testers( user, descriptor, course_key=course_key ) return ( descriptor.start is None or now > effective_start or in_preview_mode() )
def _can_access_descriptor_with_start_date(user, descriptor, course_key): # pylint: disable=invalid-name """ Checks if a user has access to a descriptor based on its start date. If there is no start date specified, grant access. Else, check if we're past the start date. Note: We do NOT check whether the user is staff or if the descriptor is detached... it is assumed both of these are checked by the caller. Arguments: user (User): the user whose descriptor access we are checking. descriptor (AType): the descriptor for which we are checking access, where AType is CourseDescriptor, CourseOverview, or any other class that represents a descriptor and has the attributes .location, .id, .start, and .days_early_for_beta. Returns: AccessResponse: The result of this access check. Possible results are ACCESS_GRANTED or a StartDateError. """ start_dates_disabled = settings.FEATURES['DISABLE_START_DATES'] if start_dates_disabled and not is_masquerading_as_student( user, course_key): return ACCESS_GRANTED else: now = datetime.now(UTC()) effective_start = _adjust_start_date_for_beta_testers( user, descriptor, course_key=course_key) if (descriptor.start is None or now > effective_start or in_preview_mode()): return ACCESS_GRANTED return StartDateError(descriptor.start)
def check_start_date(user, days_early_for_beta, start, course_key, display_error_to_user=True): """ Verifies whether the given user is allowed access given the start date and the Beta offset for the given course. Arguments: display_error_to_user: If True, display this error to users in the UI. Returns: AccessResponse: Either ACCESS_GRANTED or StartDateError. """ start_dates_disabled = settings.FEATURES['DISABLE_START_DATES'] masquerading_as_student = is_masquerading_as_student(user, course_key) if start_dates_disabled and not masquerading_as_student: return ACCESS_GRANTED else: now = datetime.now(UTC) if start is None or in_preview_mode() or get_course_masquerade( user, course_key): return ACCESS_GRANTED effective_start = adjust_start_date(user, days_early_for_beta, start, course_key) if now > effective_start: return ACCESS_GRANTED return StartDateError(start, display_error_to_user=display_error_to_user)
def _is_masquerading_as_generic_student(self, user, course_key): """ Checks if user is masquerading as a generic student. """ return ( is_masquerading_as_student(user, course_key) and not is_masquerading_as_specific_student(user, course_key) )
def has_staff_access_to_preview_mode(user, course_key): """ Checks if given user can access course in preview mode. A user can access a course in preview mode only if User has staff access to course. """ has_admin_access_to_course = any(administrative_accesses_to_course_for_user(user, course_key)) return has_admin_access_to_course or is_masquerading_as_student(user, course_key)
def _has_access_to_location(user, location, access_level, course_context): ''' Returns True if the given user has access_level (= staff or instructor) access to a location. For now this is equivalent to having staff / instructor access to the course location.course. This means that user is in the staff_* group or instructor_* group, or is an overall admin. TODO (vshnayder): this needs to be changed to allow per-course_id permissions, not per-course (e.g. staff in 2012 is different from 2013, but maybe some people always have access) course is a string: the course field of the location being accessed. location = location access_level = string, either "staff" or "instructor" ''' if user is None or (not user.is_authenticated()): debug("Deny: no user or anon user") return False if is_masquerading_as_student(user): return False if user.is_staff: debug("Allow: user.is_staff") return True # If not global staff, is the user in the Auth group for this class? user_groups = [g.name for g in user.groups.all()] if access_level == 'staff': staff_groups = group_names_for_staff(location, course_context) + \ [_course_org_staff_group_name(location, course_context)] for staff_group in staff_groups: if staff_group in user_groups: debug("Allow: user in group %s", staff_group) return True debug("Deny: user not in groups %s", staff_groups) if access_level == 'instructor' or access_level == 'staff': # instructors get staff privileges instructor_groups = group_names_for_instructor(location, course_context) + \ [_course_org_instructor_group_name(location, course_context)] for instructor_group in instructor_groups: if instructor_group in user_groups: debug("Allow: user in group %s", instructor_group) return True debug("Deny: user not in groups %s", instructor_groups) else: log.debug( "Error in access._has_access_to_location access_level=%s unknown" % access_level) return False
def get_user_role(user, course_key): """ Return corresponding string if user has staff, instructor or student course role in LMS. """ if is_masquerading_as_student(user): return 'student' elif has_access(user, 'instructor', course_key): return 'instructor' elif has_access(user, 'staff', course_key): return 'staff' else: return 'student'
def _has_access_to_location(user, location, access_level, course_context): ''' Returns True if the given user has access_level (= staff or instructor) access to a location. For now this is equivalent to having staff / instructor access to the course location.course. This means that user is in the staff_* group or instructor_* group, or is an overall admin. TODO (vshnayder): this needs to be changed to allow per-course_id permissions, not per-course (e.g. staff in 2012 is different from 2013, but maybe some people always have access) course is a string: the course field of the location being accessed. location = location access_level = string, either "staff" or "instructor" ''' if user is None or (not user.is_authenticated()): debug("Deny: no user or anon user") return False if is_masquerading_as_student(user): return False if GlobalStaff().has_user(user): debug("Allow: user.is_staff") return True if access_level not in ('staff', 'instructor'): log.debug("Error in access._has_access_to_location access_level=%s unknown", access_level) debug("Deny: unknown access level") return False staff_access = ( CourseStaffRole(location, course_context).has_user(user) or OrgStaffRole(location).has_user(user) ) if staff_access and access_level == 'staff': debug("Allow: user has course staff access") return True instructor_access = ( CourseInstructorRole(location, course_context).has_user(user) or OrgInstructorRole(location).has_user(user) ) if instructor_access and access_level in ('staff', 'instructor'): debug("Allow: user has course instructor access") return True debug("Deny: user did not have correct access") return False
def _has_access_to_location(user, location, access_level, course_context): """ Returns True if the given user has access_level (= staff or instructor) access to a location. For now this is equivalent to having staff / instructor access to the course location.course. This means that user is in the staff_* group or instructor_* group, or is an overall admin. TODO (vshnayder): this needs to be changed to allow per-course_id permissions, not per-course (e.g. staff in 2012 is different from 2013, but maybe some people always have access) course is a string: the course field of the location being accessed. location = location access_level = string, either "staff" or "instructor" """ if user is None or (not user.is_authenticated()): debug("Deny: no user or anon user") return False if is_masquerading_as_student(user): return False if user.is_staff: debug("Allow: user.is_staff") return True # If not global staff, is the user in the Auth group for this class? user_groups = [g.name for g in user.groups.all()] if access_level == "staff": staff_groups = group_names_for_staff(location, course_context) + [ _course_org_staff_group_name(location, course_context) ] for staff_group in staff_groups: if staff_group in user_groups: debug("Allow: user in group %s", staff_group) return True debug("Deny: user not in groups %s", staff_groups) if access_level == "instructor" or access_level == "staff": # instructors get staff privileges instructor_groups = group_names_for_instructor(location, course_context) + [ _course_org_instructor_group_name(location, course_context) ] for instructor_group in instructor_groups: if instructor_group in user_groups: debug("Allow: user in group %s", instructor_group) return True debug("Deny: user not in groups %s", instructor_groups) else: log.debug("Error in access._has_access_to_location access_level=%s unknown" % access_level) return False
def get_user_role(user, course_id): """ Return corresponding string if user has staff, instructor or student course role in LMS. """ from courseware.courses import get_course course = get_course(course_id) if is_masquerading_as_student(user): return 'student' elif has_access(user, course, 'instructor'): return 'instructor' elif has_access(user, course, 'staff'): return 'staff' else: return 'student'
def _has_access_to_course(user, access_level, course_key): """ Returns True if the given user has access_level (= staff or instructor) access to the course with the given course_key. This ensures the user is authenticated and checks if global staff or has staff / instructor access. access_level = string, either "staff" or "instructor" """ if user is None or (not user.is_authenticated()): debug("Deny: no user or anon user") return ACCESS_DENIED if is_masquerading_as_student(user, course_key): return ACCESS_DENIED global_staff, staff_access, instructor_access = administrative_accesses_to_course_for_user( user, course_key) if global_staff: debug("Allow: user.is_staff") return ACCESS_GRANTED if access_level not in ('staff', 'instructor'): log.debug( "Error in access._has_access_to_course access_level=%s unknown", access_level) debug("Deny: unknown access level") return ACCESS_DENIED org_user = OrganizationUser.objects.filter( active=True, organization__short_name=course_key.org, user_id=user.id).values().first() staff_access = (CourseStaffRole(course_key).has_user(user) or OrgStaffRole(course_key.org).has_user(user) or (org_user and org_user['is_staff'])) if staff_access and access_level == 'staff': debug("Allow: user has course staff access") return ACCESS_GRANTED if instructor_access and access_level in ('staff', 'instructor'): debug("Allow: user has course instructor access") return ACCESS_GRANTED debug("Deny: user did not have correct access") return ACCESS_DENIED
def _has_access_to_course(user, access_level, course_key): ''' Returns True if the given user has access_level (= staff or instructor) access to the course with the given course_key. This ensures the user is authenticated and checks if global staff or has staff / instructor access. access_level = string, either "staff" or "instructor" ''' if user is None or (not user.is_authenticated()): debug("Deny: no user or anon user") return False if is_masquerading_as_student(user): return False if GlobalStaff().has_user(user): debug("Allow: user.is_staff") return True if access_level not in ('staff', 'instructor'): log.debug("Error in access._has_access_to_course access_level=%s unknown", access_level) debug("Deny: unknown access level") return False staff_access = ( CourseStaffRole(course_key).has_user(user) or OrgStaffRole(course_key.org).has_user(user) ) if staff_access and access_level == 'staff': debug("Allow: user has course staff access") return True instructor_access = ( CourseInstructorRole(course_key).has_user(user) or OrgInstructorRole(course_key.org).has_user(user) ) if instructor_access and access_level in ('staff', 'instructor'): debug("Allow: user has course instructor access") return True debug("Deny: user did not have correct access") return False
def check_start_date(user, days_early_for_beta, start, course_key): """ Verifies whether the given user is allowed access given the start date and the Beta offset for the given course. Returns: AccessResponse: Either ACCESS_GRANTED or StartDateError. """ start_dates_disabled = settings.FEATURES['DISABLE_START_DATES'] if start_dates_disabled and not is_masquerading_as_student(user, course_key): return ACCESS_GRANTED else: now = datetime.now(UTC()) effective_start = adjust_start_date(user, days_early_for_beta, start, course_key) if start is None or now > effective_start or in_preview_mode(): return ACCESS_GRANTED return StartDateError(start)
def can_load(): """ NOTE: This does not check that the student is enrolled in the course that contains this module. We may or may not want to allow non-enrolled students to see modules. If not, views should check the course, so we don't have to hit the enrollments table on every module load. """ if descriptor.visible_to_staff_only and not _has_staff_access_to_descriptor( user, descriptor, course_key): return False # enforce group access if not _has_group_access(descriptor, user, course_key): # if group_access check failed, deny access unless the requestor is staff, # in which case immediately grant access. return _has_staff_access_to_descriptor(user, descriptor, course_key) # If start dates are off, can always load if settings.FEATURES[ 'DISABLE_START_DATES'] and not is_masquerading_as_student( user, course_key): debug("Allow: DISABLE_START_DATES") return True # Check start date if 'detached' not in descriptor._class_tags and descriptor.start is not None: now = datetime.now(UTC()) effective_start = _adjust_start_date_for_beta_testers( user, descriptor, course_key=course_key) if in_preview_mode() or now > effective_start: # after start date, everyone can see it debug("Allow: now > effective start date") return True # otherwise, need staff access return _has_staff_access_to_descriptor(user, descriptor, course_key) # No start date, so can always load. debug("Allow: no start date") return True
def _has_access_to_course(user, access_level, course_key): """ Returns True if the given user has access_level (= staff or instructor) access to the course with the given course_key. This ensures the user is authenticated and checks if global staff or has staff / instructor access. access_level = string, either "staff" or "instructor" """ if user is None or (not user.is_authenticated()): debug("Deny: no user or anon user") return ACCESS_DENIED if is_masquerading_as_student(user, course_key): return ACCESS_DENIED global_staff, staff_access, instructor_access = administrative_accesses_to_course_for_user( user, course_key) if global_staff: debug("Allow: user.is_staff") return ACCESS_GRANTED if access_level not in ('staff', 'instructor'): log.debug( "Error in access._has_access_to_course access_level=%s unknown", access_level) debug("Deny: unknown access level") return ACCESS_DENIED if staff_access and access_level == 'staff': debug("Allow: user has course staff access") return ACCESS_GRANTED if instructor_access and access_level in ('staff', 'instructor'): debug("Allow: user has course instructor access") return ACCESS_GRANTED debug("Deny: user did not have correct access") return ACCESS_DENIED
def can_load(): """ NOTE: This does not check that the student is enrolled in the course that contains this module. We may or may not want to allow non-enrolled students to see modules. If not, views should check the course, so we don't have to hit the enrollments table on every module load. """ if descriptor.visible_to_staff_only and not _has_staff_access_to_descriptor(user, descriptor, course_key): return False # enforce group access if not _has_group_access(descriptor, user, course_key): # if group_access check failed, deny access unless the requestor is staff, # in which case immediately grant access. return _has_staff_access_to_descriptor(user, descriptor, course_key) # If start dates are off, can always load if settings.FEATURES['DISABLE_START_DATES'] and not is_masquerading_as_student(user, course_key): debug("Allow: DISABLE_START_DATES") return True # Check start date if 'detached' not in descriptor._class_tags and descriptor.start is not None: now = datetime.now(UTC()) effective_start = _adjust_start_date_for_beta_testers( user, descriptor, course_key=course_key ) if now > effective_start: # after start date, all registered users can see it # nonregistered users shouldn't be able to access certain descriptor types debug("Allow: now > effective start date") return UserProfile.has_registered(user) or _can_load_descriptor_nonregistered(descriptor) # otherwise, need staff access return _has_staff_access_to_descriptor(user, descriptor, course_key) # No start date, so can always load. debug("Allow: no start date") return True
def _can_access_descriptor_with_start_date(user, descriptor, course_key): # pylint: disable=invalid-name """ Checks if a user has access to a descriptor based on its start date. If there is no start date specified, grant access. Else, check if we're past the start date. Note: We do NOT check whether the user is staff or if the descriptor is detached... it is assumed both of these are checked by the caller. Arguments: user (User): the user whose descriptor access we are checking. descriptor (AType): the descriptor for which we are checking access, where AType is CourseDescriptor, CourseOverview, or any other class that represents a descriptor and has the attributes .location, .id, .start, and .days_early_for_beta. Returns: AccessResponse: The result of this access check. Possible results are ACCESS_GRANTED or a StartDateError. """ start_dates_disabled = settings.FEATURES['DISABLE_START_DATES'] if start_dates_disabled and not is_masquerading_as_student(user, course_key): return ACCESS_GRANTED else: now = datetime.now(UTC()) effective_start = _adjust_start_date_for_beta_testers( user, descriptor, course_key=course_key ) if ( descriptor.start is None or now > effective_start or in_preview_mode() ): return ACCESS_GRANTED return StartDateError(descriptor.start)
def check_start_date(user, days_early_for_beta, start, course_key): """ Verifies whether the given user is allowed access given the start date and the Beta offset for the given course. Returns: AccessResponse: Either ACCESS_GRANTED or StartDateError. """ start_dates_disabled = settings.FEATURES['DISABLE_START_DATES'] masquerading_as_student = is_masquerading_as_student(user, course_key) masquerading_as_specific_student = is_masquerading_as_specific_student( user, course_key) if start_dates_disabled and not masquerading_as_student: return ACCESS_GRANTED else: now = datetime.now(UTC) if start is None or in_preview_mode(): return ACCESS_GRANTED effective_start = adjust_start_date(user, days_early_for_beta, start, course_key) if now > effective_start: return ACCESS_GRANTED if get_course_masquerade(user, course_key): if masquerading_as_student or ( masquerading_as_specific_student and not has_staff_roles(user, course_key)): request = get_current_request() PageLevelMessages.register_warning_message( request, HTML( _('This user does not have access to this content due to the content start date' )), once_only=True) return ACCESS_GRANTED return StartDateError(start)
def _has_access_to_course(user, access_level, course_key): """ Returns True if the given user has access_level (= staff or instructor) access to the course with the given course_key. This ensures the user is authenticated and checks if global staff or has staff / instructor access. access_level = string, either "staff" or "instructor" """ if user is None or (not user.is_authenticated()): debug("Deny: no user or anon user") return ACCESS_DENIED if is_masquerading_as_student(user, course_key): return ACCESS_DENIED global_staff, staff_access, instructor_access = administrative_accesses_to_course_for_user(user, course_key) if global_staff: debug("Allow: user.is_staff") return ACCESS_GRANTED if access_level not in ('staff', 'instructor'): log.debug("Error in access._has_access_to_course access_level=%s unknown", access_level) debug("Deny: unknown access level") return ACCESS_DENIED if staff_access and access_level == 'staff': debug("Allow: user has course staff access") return ACCESS_GRANTED if instructor_access and access_level in ('staff', 'instructor'): debug("Allow: user has course instructor access") return ACCESS_GRANTED debug("Deny: user did not have correct access") return ACCESS_DENIED
def _can_access_descriptor_with_start_date(user, descriptor, course_key): # pylint: disable=invalid-name """ Checks if a user has access to a descriptor based on its start date. If there is no start date specified, grant access. Else, check if we're past the start date. Note: We do NOT check whether the user is staff or if the descriptor is detached... it is assumed both of these are checked by the caller. Arguments: user (User): the user whose descriptor access we are checking. descriptor (AType): the descriptor for which we are checking access. where AType is any descriptor that has the attributes .location and .days_early_for_beta """ start_dates_disabled = settings.FEATURES["DISABLE_START_DATES"] if start_dates_disabled and not is_masquerading_as_student(user, course_key): return True else: now = datetime.now(UTC()) effective_start = _adjust_start_date_for_beta_testers(user, descriptor, course_key=course_key) return descriptor.start is None or now > effective_start or in_preview_mode()