def get_own_targets_from_course(user_requesting, course_id):
     """
     This function should return a list of objects with the attributes set up above. 
     """
     course_for_user = LTICourse.get_course_by_id(course_id)
     response = TargetObject.objects.filter(target_courses=course_for_user)
     return response
 def get_own_targets_from_course(course_id):
     """
     This function should return a list of objects with the attributes set up above. 
     """
     course_for_user = LTICourse.get_course_by_id(course_id)
     response = TargetObject.objects.filter(target_courses=course_for_user).order_by('assignmenttargets')
     return response
Ejemplo n.º 3
0
def test_LTICourse_get_course_by_id(user_profile_factory):
    """
    Checks that you can get a course given an id.
    """
    # TODO: chack that is ok to add 'Learner' as admin to course
    instructor = user_profile_factory()
    course_object = LTICourse.create_course("test_course_id", instructor)
    course_to_test = LTICourse.get_course_by_id("test_course_id")

    assert isinstance(course_to_test, LTICourse)
    assert course_object == course_to_test
    assert course_to_test.course_id == "test_course_id"
Ejemplo n.º 4
0
def test_launchLti_user_scope_canvas_no_platform_created_ok(
    lti_path,
    lti_launch_url,
    lti_launch_params_factory,
):
    # have to set ORGANIZATION to something else than HARVARDX
    settings.ORGANIZATION = "ATG"

    # user and course don't exist yet
    instructor_name = "audre_lorde"
    instructor_edxid = "{}{}".format(randint(1000, 65534),
                                     randint(1000, 65534))
    user_roles = ["Administrator"]
    course_id = "hx+FancyCourse+TermCode+Year"
    resource_link_id = "some_string_to_be_the_FAKE_resource_link_id"

    params = lti_launch_params_factory(
        course_id=course_id,
        user_name=instructor_name,
        user_id=instructor_edxid,
        user_roles=user_roles,
        resource_link_id=resource_link_id,
        launch_url=lti_launch_url,
        course_name="{}+title".format(course_id),
    )

    client = Client(enforce_csrf_checks=False)
    response = client.post(
        lti_path,
        data=params,
    )
    assert response.status_code == 302
    assert response.cookies.get("sessionid")
    expected_url = (reverse("hx_lti_initializer:course_admin_hub") +
                    f"?resource_link_id={resource_link_id}" +
                    f"&utm_source={client.session.session_key}")
    assert response.url == expected_url

    # check user was created
    user = User.objects.get(username=instructor_name)
    assert user is not None
    lti_profile = LTIProfile.objects.get(anon_id=instructor_edxid)
    assert lti_profile is not None
    assert lti_profile.user.username == user.username
    # scope is course
    assert lti_profile.scope == "course:{}".format(course_id)

    # check course was created
    course = LTICourse.get_course_by_id(course_id)
    assert course is not None
    assert len(LTICourse.get_all_courses()) == 1
    assert course.course_admins.all()[0].anon_id == instructor_edxid
    assert course.course_name == "{}+title".format(course_id)
Ejemplo n.º 5
0
def test_launchLti_user_course_ok_no_context_title(
    lti_path,
    lti_launch_url,
    lti_launch_params_factory,
):
    # user and course don't exist yet
    instructor_name = "sylvia_plath"
    instructor_edxid = "{}{}".format(randint(1000, 65534),
                                     randint(1000, 65534))
    user_roles = ["Administrator"]
    course_id = "hx+FANcyCourse+TermCode+Year"
    resource_link_id = "some_string_to_BE_THE_fake_resource_link_id"

    params = lti_launch_params_factory(
        course_id=course_id,
        user_name=instructor_name,
        user_id=instructor_edxid,
        user_roles=user_roles,
        resource_link_id=resource_link_id,
        launch_url=lti_launch_url,
        # 04feb20 naomi: context_title has to do with edx studio not
        # sending user_id in launch params to create course user.
        # course_name='{}+title'.format(course_id),
    )

    client = Client(enforce_csrf_checks=False)
    response = client.post(
        lti_path,
        data=params,
    )
    assert response.status_code == 302
    assert response.cookies.get("sessionid")
    expected_url = (reverse("hx_lti_initializer:course_admin_hub") +
                    f"?resource_link_id={resource_link_id}" +
                    f"&utm_source={client.session.session_key}")
    assert response.url == expected_url

    # check user was created
    user = User.objects.get(username=instructor_name)
    assert user is not None
    lti_profile = LTIProfile.objects.get(anon_id=instructor_edxid)
    assert lti_profile is not None
    assert lti_profile.user.username == user.username

    # check course was created
    course = LTICourse.get_course_by_id(course_id)
    assert course is not None
    assert len(LTICourse.get_all_courses()) == 1
    assert course.course_admins.all()[0].anon_id == instructor_edxid
    assert course.course_name.startswith("noname-")
Ejemplo n.º 6
0
def test_launchLti_expired_timestamp(
    lti_path,
    lti_launch_url,
    lti_launch_params_factory,
):
    # user and course don't exist yet
    instructor_name = "sylvia_plath"
    instructor_edxid = "{}{}".format(randint(1000, 65534),
                                     randint(1000, 65534))
    user_roles = ["Administrator"]
    course_id = "hx+fancyCOURSE+TermCode+Year"
    resource_link_id = "some_STRING_to_be_the_fake_resource_link_id"

    params = lti_launch_params_factory(
        course_id=course_id,
        user_name=instructor_name,
        user_id=instructor_edxid,
        user_roles=user_roles,
        resource_link_id=resource_link_id,
        launch_url=lti_launch_url,
    )
    # replace for old timestamp
    params["oauth_timestamp"] = old_timestamp

    client = Client(enforce_csrf_checks=False)
    response = client.post(
        lti_path,
        data=params,
    )
    assert response.status_code == 403

    # check user was NOT created
    with pytest.raises(User.DoesNotExist) as e:
        user = User.objects.get(username=instructor_name)
    assert "does not exist" in str(e.value)

    # check course was created
    with pytest.raises(LTICourse.DoesNotExist) as e:
        course = LTICourse.get_course_by_id(course_id)
    assert "does not exist" in str(e.value)
Ejemplo n.º 7
0
def launch_lti(request):
    """
    Gets a request from an LTI consumer.
    Passes along information to render a welcome screen to the user.

    Assumptions: LTI launch request has already been validated by middleware
    """

    # collect anonymous_id and consumer key in order to fetch LTIProfile
    # if it exists, we initialize the tool otherwise, we create a new user
    user_id = request.LTI['launch_params']['user_id']
    logger.debug('DEBUG - Found anonymous ID in request: %s' % user_id)

    course = request.LTI['launch_params'][settings.LTI_COURSE_ID]
    logger.debug('DEBUG - Found course being accessed: %s' % course)

    resource_link_id = request.LTI['launch_params']['resource_link_id']

    # This is where we identify the "scope" of the LTI user_id (anon_id), meaning
    # the scope in which the identifier is unique. In canvas this is the domain instance,
    # where as in edX this is the course instance.
    #
    # The idea is that the combination of the LTI user_id (anon_id) and scope should be
    # globally unique.
    user_scope = None
    if settings.ORGANIZATION == "HARVARDX":
        user_scope = "course:%s" % course
    else:
        tool_consumer_instance_guid = request.LTI['launch_params'][
            'tool_consumer_instance_guid']
        if tool_consumer_instance_guid:
            user_scope = "consumer:%s" % tool_consumer_instance_guid
    logger.debug("DEBUG - user scope is: %s" % user_scope)

    # default to student
    save_session(request, is_staff=False)

    # this is where canvas will tell us what level individual is coming into
    # the tool the 'roles' field usually consists of just 'Instructor'
    # or 'Learner'
    roles = request.LTI['launch_params'][settings.LTI_ROLES]
    logger.debug("DEBUG - user logging in with roles: " + str(roles))

    # This is the name that we will show on the UI if provided...
    # EDX-NOTE: edx does not return the person's name!
    display_name = request.LTI['launch_params'].get('lis_person_name_full',
                                                    None)
    if not display_name:
        display_name = request.LTI['launch_params'].get(
            'lis_person_sourcedid', '')

    # This is the unique identifier for the person in the source system
    # In canvas this would be the SIS user id, in edX the registered username
    external_user_id = request.LTI['launch_params'].get(
        'lis_person_sourcedid', '')

    # This handles the rare case in which we have neither display name nor external user id
    if not (display_name or external_user_id):
        try:
            lti_profile = LTIProfile.objects.get(anon_id=str(course))
            roles = ['student']
            display_name = lti_profile.user.username
            messages.warning(
                request,
                "edX still has not fixed issue with no user_id in studio.")
            messages.error(
                request,
                "Warning: you are logged in as a Preview user. Please view this in live to access admin hub."
            )
        except:
            logger.debug('DEBUG - username not found in post.')
            raise PermissionDenied('username not found in LTI launch')
    logger.debug("DEBUG - user name: " + display_name)

    # Check whether user is a admin, instructor or teaching assistant
    if set(roles) & set(settings.ADMIN_ROLES):
        try:
            # See if the user already has a profile, and use it if so.
            lti_profile = LTIProfile.objects.get(anon_id=user_id)
            logger.debug('DEBUG - LTI Profile was found via anonymous id.')
        except LTIProfile.DoesNotExist:
            # if it's a new user (profile doesn't exist), set up and save a new LTI Profile
            logger.debug(
                'DEBUG - LTI Profile NOT found. New User to be created.')
            user, lti_profile = create_new_user(anon_id=user_id,
                                                username=external_user_id,
                                                display_name=display_name,
                                                roles=roles,
                                                scope=user_scope)
            # log the user into the Django backend
        lti_profile.user.backend = 'django.contrib.auth.backends.ModelBackend'
        login(request, lti_profile.user)
        save_session(request,
                     user_id=user_id,
                     user_name=display_name,
                     user_scope=user_scope,
                     context_id=course,
                     roles=roles,
                     is_staff=True,
                     resource_link_id=resource_link_id)
    else:
        # For HX, students only access one object or collection, and don't
        # have an index
        # For ATG, students have the index  to choose where to go, so
        # collection_id and object_id are probably blank for their session
        # right now.
        collection_id = request.LTI['launch_params'].get(
            settings.LTI_COLLECTION_ID)
        object_id = request.LTI['launch_params'].get(settings.LTI_OBJECT_ID)
        save_session(request,
                     user_id=user_id,
                     user_name=display_name,
                     user_scope=user_scope,
                     context_id=course,
                     roles=roles,
                     is_staff=False,
                     resource_link_id=resource_link_id)

    # now it's time to deal with the course_id it does not associate
    # with users as they can flow in and out in a MOOC
    try:
        course_object = LTICourse.get_course_by_id(course)
        logger.debug('DEBUG - Course was found %s' % course)

        # save the course name to the session so it auto-populate later.
        save_session(
            request,
            course_name=course_object.course_name,
            course_id=course_object.id,
        )

    except LTICourse.DoesNotExist:
        logger.debug('DEBUG - Course %s was NOT found. Will be created.' %
                     course)

        # Put a message on the screen to indicate to the user that the course doesn't exist
        message_error = "Sorry, the course you are trying to reach does not exist."
        messages.error(request, message_error)

        if set(roles) & set(settings.ADMIN_ROLES):
            # This must be the instructor's first time accessing the annotation tool
            # Make him/her a new course within the tool

            message_error = "Because you are an instructor, a course has been created for you, please refresh the page to begin editing your course."
            messages.warning(request, message_error)

            # create and save a new course for the instructor, with a default name of their canvas course's name
            context_title = None
            if request.LTI['launch_params']['context_title'] is not None:
                context_title = request.LTI['launch_params']['context_title']
            course_object = LTICourse.create_course(course,
                                                    lti_profile,
                                                    name=context_title)
            create_new_user(anon_id=str(course),
                            username='******' % course_object.id,
                            display_name="Preview %s" % str(course_object),
                            roles=['student'],
                            scope=user_scope)

            # save the course name to the session so it auto-populate later.
            save_session(
                request,
                course_name=course_object.course_name,
                course_id=course_object.id,
            )
        else:
            logger.info(
                'Course not created because user does not have an admin role')
    try:
        config = LTIResourceLinkConfig.objects.get(
            resource_link_id=resource_link_id)
        assignment_id = config.collection_id
        object_id = config.object_id
        logger.debug(
            "DEBUG - LTIResourceLinkConfig: resource_link_id=%s collection_id=%s object_id=%s"
            % (resource_link_id, config.collection_id, config.object_id))
        course_id = str(course)
        if set(roles) & set(settings.ADMIN_ROLES):
            try:
                userfound = LTICourseAdmin.objects.get(
                    admin_unique_identifier=lti_profile.user.username,
                    new_admin_course_id=course)
                course_object.add_admin(lti_profile)
                logger.info("CourseAdmin Pending found: %s" % userfound)
                userfound.delete()
            except:
                logger.info("Not waiting to be added as admin")
        logger.debug(
            "DEBUG - User wants to go directly to annotations for a specific target object using UI"
        )
        return access_annotation_target(request, course_id, assignment_id,
                                        object_id)
    except AnnotationTargetDoesNotExist as e:
        logger.warning(
            'Could not access annotation target using resource config.')
        logger.info('Deleting resource config because it is invalid.')
        LTIResourceLinkConfig.objects.filter(
            resource_link_id=resource_link_id).delete()
        logger.info('Proceed to the admin hub.')
    except PermissionDenied as e:
        raise e  # make sure to re-raise this exception since we shouldn't proceed
    except:
        # For the use case where the course head wants to display an assignment object instead
        # of the admin_hub upon launch (i.e. for embedded use), this allows the user
        # to be routed directly to an assignment given the correct POST parameters,
        # as by Luis' original method of putting collection_id and object_id in the
        # LTI tool launch params.
        try:
            # Keeping the HX functionality whereby students are routed to specific assignment objects
            # This is motivated by the Poetry in America Course

            # If there are variables passed into the launch indicating a desired target object, render that object
            assignment_id = request.LTI['launch_params'][
                settings.LTI_COLLECTION_ID]
            object_id = request.LTI['launch_params'][settings.LTI_OBJECT_ID]
            course_id = str(course)
            if set(roles) & set(settings.ADMIN_ROLES):
                try:
                    userfound = LTICourseAdmin.objects.get(
                        admin_unique_identifier=lti_profile.user.username,
                        new_admin_course_id=course)
                    course_object.add_admin(lti_profile)
                    logger.info("CourseAdmin Pending found: %s" % userfound)
                    userfound.delete()
                except:
                    logger.info("Not waiting to be added as admin")
                return course_admin_hub(request)
            else:
                logger.debug(
                    "DEBUG - User wants to go directly to annotations for a specific target object"
                )
                return access_annotation_target(request, course_id,
                                                assignment_id, object_id)
        except:
            logger.debug("DEBUG - User wants the index")

    try:
        userfound = LTICourseAdmin.objects.get(
            admin_unique_identifier=lti_profile.user.username,
            new_admin_course_id=course)
        course_object.add_admin(lti_profile)
        logger.info("CourseAdmin Pending found: %s" % userfound)
        userfound.delete()
    except:
        logger.debug("DEBUG - Not waiting to be added as admin")

    return course_admin_hub(request)
Ejemplo n.º 8
0
def launch_lti(request):
    """
    Gets a request from an LTI consumer.
    Passes along information to render a welcome screen to the user.
    """

    validate_request(request)
    tool_provider = initialize_lti_tool_provider(request)

    # collect anonymous_id and consumer key in order to fetch LTIProfile
    # if it exists, we initialize the tool otherwise, we create a new user
    consumer_key_requested = request.POST["oauth_consumer_key"]
    user_id = get_lti_value("user_id", tool_provider)
    debug_printer("DEBUG - Found anonymous ID in request: %s" % user_id)

    course = get_lti_value(settings.LTI_COURSE_ID, tool_provider)
    debug_printer("DEBUG - Found course being accessed: %s" % course)

    roles = get_lti_value(settings.LTI_ROLES, tool_provider)

    if "Student" in roles or "Learner" in roles:
        collection_id = get_lti_value(settings.LTI_COLLECTION_ID, tool_provider)
        object_id = get_lti_value(settings.LTI_OBJECT_ID, tool_provider)
        debug_printer("DEBUG - Found assignment being accessed: %s" % collection_id)
        debug_printer("DEBUG - Found object being accessed: %s" % object_id)

        user_name = get_lti_value("lis_person_name_full", tool_provider)
        if user_name == None:
            # gather the necessary data from the LTI initialization request
            user_name = get_lti_value("lis_person_sourcedid", tool_provider)

        try:
            assignment = Assignment.objects.get(assignment_id=collection_id)
            targ_obj = TargetObject.objects.get(pk=object_id)
        except Assignment.DoesNotExist or TargetObject.DoesNotExist:
            raise PermissionDenied()

        original = {
            "user_id": user_id,
            "username": user_name,
            "roles": roles,
            "collection": collection_id,
            "course": course,
            "object": object_id,
            "target_object": targ_obj,
            "token": retrieve_token(
                user_id, assignment.annotation_database_apikey, assignment.annotation_database_secret_token
            ),
            "assignment": assignment,
        }

        if targ_obj.target_type == "vd":
            srcurl = targ_obj.target_content
            if "youtu" in srcurl:
                typeSource = "video/youtube"
            else:
                disassembled = urlparse(srcurl)
                file_ext = splitext(basename(disassembled.path))[1]
                typeSource = "video/" + file_ext.replace(".", "")
            original.update({"typeSource": typeSource})
        elif targ_obj.target_type == "ig":
            original.update({"osd_json": targ_obj.target_content})

        return render(request, "%s/detail.html" % targ_obj.target_type, original)

    try:
        # try to get the profile via the anon id
        lti_profile = LTIProfile.objects.get(anon_id=user_id)
        debug_printer("DEBUG - LTI Profile was found via anonymous id.")

    except LTIProfile.DoesNotExist:
        debug_printer("DEBUG - LTI Profile not found. New User to be created.")

        lti_username = get_lti_value("lis_person_name_full", tool_provider)
        if lti_username == None:
            # gather the necessary data from the LTI initialization request
            lti_username = get_lti_value("lis_person_sourcedid", tool_provider)

        # checks to see if email and username were not passed in
        # cannot create a user without them
        if not lti_username:
            debug_printer("DEBUG - user_id not found in post.")
            raise PermissionDenied()

        # checks to see if roles were passed in. Defaults to student role.
        all_user_roles = []

        if not roles:
            debug_printer(
                "DEBUG - ALL_ROLES is set but user was not passed in any roles via the request. Defaults to student."
            )
            all_user_roles += "Student"

        else:
            # makes sure that roles is a list and not just a string
            if not isinstance(roles, list):
                roles = [roles]
            all_user_roles += roles

        debug_printer("DEBUG - User had an acceptable role: %s" % all_user_roles)

        user, lti_profile = create_new_user(lti_username, user_id, roles)

    # now it's time to deal with the course_id it does not associate
    # with users as they can flow in and out in a MOOC
    try:
        debug_printer("DEBUG - Course was found %s" % course)
        course_object = LTICourse.get_course_by_id(course)

    except LTICourse.DoesNotExist:
        # this should only happen if an instructor is trying to access the
        # tool from a different course
        debug_printer("DEBUG - Course %s was NOT found. Will be created." % course)
        message_error = "Sorry, the course you are trying to reach does not exist."
        messages.error(request, message_error)
        if "Administrator" in roles or "Instructor" in roles:
            # if the user is an administrator, the missing course is created
            # otherwise, it will just display an error message
            message_error = (
                "Because you are an instructor, a course has been created for you, edit it below to add a proper name."
            )
            messages.warning(request, message_error)
            course_object = LTICourse.create_course(course, lti_profile)

    # get all the courses the user is a part of
    # courses_for_user = LTICourse.objects.filter(course_admins=lti_profile.id)

    # then gets all the files associated with the courses
    # files_in_courses = TOD_Implementation.get_dict_of_files_from_courses(lti_profile, courses_for_user)

    # logs the user in
    lti_profile.user.backend = "django.contrib.auth.backends.ModelBackend"
    login(request, lti_profile.user)

    return redirect("hx_lti_initializer:course_admin_hub")
Ejemplo n.º 9
0
def launch_lti(request):
    """
    Gets a request from an LTI consumer.
    Passes along information to render a welcome screen to the user.
    """
    
    validate_request(request)
    tool_provider = initialize_lti_tool_provider(request)
    
    # collect anonymous_id and consumer key in order to fetch LTIProfile
    # if it exists, we initialize the tool otherwise, we create a new user
    consumer_key_requested = request.POST['oauth_consumer_key']
    anon_id = '%s:%s' % (consumer_key_requested, get_lti_value('user_id', tool_provider))
    debug_printer('DEBUG - Found anonymous ID in request: %s' % anon_id)
    
    course = get_lti_value(settings.LTI_COURSE_ID, tool_provider)
    collection = get_lti_value(settings.LTI_COLLECTION_ID, tool_provider)
    object = get_lti_value(settings.LTI_OBJECT_ID, tool_provider)
    
    debug_printer('DEBUG - Found course being accessed: %s' % course)
    
    roles = get_lti_value(settings.LTI_ROLES, tool_provider)
    if "Student" in roles:
        targ_obj = TargetObject.objects.get(pk=object)
        return render(request, '%s/detail.html' % targ_obj.target_type, {
            'email': get_lti_value('lis_person_contact_email_primary', tool_provider),
            'user_id': get_lti_value('lis_person_sourcedid', tool_provider),
            'roles': roles,
            'collection': collection,
            'course': course,
            'object': object,
            'target_object': targ_obj,
            'token': retrieve_token(get_lti_value('lis_person_contact_email_primary', tool_provider), ''),
        })
    
    try:
        # try to get the profile via the anon id
        lti_profile = LTIProfile.objects.get(anon_id=anon_id)
        debug_printer('DEBUG - LTI Profile was found via anonymous id.')
    
    except LTIProfile.DoesNotExist:
        debug_printer('DEBUG - LTI Profile not found. New User to be created.')
        
        # gather the necessary data from the LTI initialization request
        email = get_lti_value('lis_person_contact_email_primary', tool_provider)
        lti_username = get_lti_value('lis_person_sourcedid', tool_provider)
        
        # checks to see if email and username were not passed in
        # cannot create a user without them
        if not email or not lti_username:
            debug_printer('DEBUG - Email and/or user_id not found in post.')
            raise PermissionDenied()
        
        # checks to see if roles were passed in. Defaults to student role.
        if settings.ALL_ROLES:
            all_user_roles = []
            
            if not roles:
                debug_printer('DEBUG - ALL_ROLES is set but user was not passed in any roles via the request. Defaults to student.')
                all_user_roles += "Student"
            
            else:
                # makes sure that roles is a list and not just a string
                if not isinstance(roles, list):
                    roles = [roles]
                all_user_roles += roles
            
            # checks to make sure that role is actually allowed/expected
            role_allowed = False
            for role_type in settings.ALL_ROLES:
                for user_role in roles:
                    if role_type.lower() == user_role.lower():
                        role_allowed = True
            
            # if role is not allowed then denied (problem with platform)
            # if role is missing, default to Student (problem with request)
            if not role_allowed:
                debug_printer('DEBUG - User does not have an acceptable role. Check with platform.')
                raise PermissionedDenied()
            else:
                debug_printer('DEBUG - User had an acceptable role: %s' % all_user_roles)
        
        user, lti_profile = create_new_user(lti_username, email, roles)
    
    # now it's time to deal with the course_id it does not associate
    # with users as they can flow in and out in a MOOC
    try:
        debug_printer('DEBUG - Course was found %s' % course)
        course_object = LTICourse.get_course_by_id(course)
    
    except LTICourse.DoesNotExist:
        # this should only happen if an instructor is trying to access the 
        # tool from a different course
        debug_printer('DEBUG - Course %s was NOT found. Will be created.' %course)
        message_error = "Sorry, the course you are trying to reach does not exist."
        messages.error(request, message_error)
        if 'Administrator' in roles:
            # if the user is an administrator, the missing course is created
            # otherwise, it will just display an error message
            message_error = "Because you are an instructor, a course has been created for you, edit it below to add a proper name."
            messages.warning(request, message_error)
            course_object = LTICourse.create_course(course, lti_profile)
    
    # get all the courses the user is a part of
    courses_for_user = LTICourse.get_courses_of_user(lti_profile, course_object)
    
    # then gets all the files associated with the courses 
    files_in_courses = TOD_Implementation.get_dict_of_files_from_courses(lti_profile, courses_for_user)
    
    # logs the user in
    lti_profile.user.backend = 'django.contrib.auth.backends.ModelBackend'
    login(request, lti_profile.user)
    
    # then renders the page using the template
    return render(request, 'hx_lti_initializer/testpage2.html', {'user': lti_profile.user, 'email': lti_profile.user.email, 'user_id': lti_profile.user.get_username(), 'roles': lti_profile.roles, 'courses': courses_for_user, 'files': files_in_courses})
Ejemplo n.º 10
0
def launch_lti(request):
    """
    Gets a request from an LTI consumer.
    Passes along information to render a welcome screen to the user.
    """

    validate_request(request)
    tool_provider = initialize_lti_tool_provider(request)

    # collect anonymous_id and consumer key in order to fetch LTIProfile
    # if it exists, we initialize the tool otherwise, we create a new user
    consumer_key_requested = request.POST['oauth_consumer_key']
    anon_id = '%s:%s' % (consumer_key_requested,
                         get_lti_value('user_id', tool_provider))
    debug_printer('DEBUG - Found anonymous ID in request: %s' % anon_id)

    course = get_lti_value(settings.LTI_COURSE_ID, tool_provider)
    collection = get_lti_value(settings.LTI_COLLECTION_ID, tool_provider)
    object = get_lti_value(settings.LTI_OBJECT_ID, tool_provider)

    debug_printer('DEBUG - Found course being accessed: %s' % course)

    roles = get_lti_value(settings.LTI_ROLES, tool_provider)
    if "Student" in roles:
        targ_obj = TargetObject.objects.get(pk=object)
        return render(
            request, '%s/detail.html' % targ_obj.target_type, {
                'email':
                get_lti_value('lis_person_contact_email_primary',
                              tool_provider),
                'user_id':
                get_lti_value('lis_person_sourcedid', tool_provider),
                'roles':
                roles,
                'collection':
                collection,
                'course':
                course,
                'object':
                object,
                'target_object':
                targ_obj,
                'token':
                retrieve_token(
                    get_lti_value('lis_person_contact_email_primary',
                                  tool_provider), ''),
            })

    try:
        # try to get the profile via the anon id
        lti_profile = LTIProfile.objects.get(anon_id=anon_id)
        debug_printer('DEBUG - LTI Profile was found via anonymous id.')

    except LTIProfile.DoesNotExist:
        debug_printer('DEBUG - LTI Profile not found. New User to be created.')

        # gather the necessary data from the LTI initialization request
        email = get_lti_value('lis_person_contact_email_primary',
                              tool_provider)
        lti_username = get_lti_value('lis_person_sourcedid', tool_provider)

        # checks to see if email and username were not passed in
        # cannot create a user without them
        if not email or not lti_username:
            debug_printer('DEBUG - Email and/or user_id not found in post.')
            raise PermissionDenied()

        # checks to see if roles were passed in. Defaults to student role.
        if settings.ALL_ROLES:
            all_user_roles = []

            if not roles:
                debug_printer(
                    'DEBUG - ALL_ROLES is set but user was not passed in any roles via the request. Defaults to student.'
                )
                all_user_roles += "Student"

            else:
                # makes sure that roles is a list and not just a string
                if not isinstance(roles, list):
                    roles = [roles]
                all_user_roles += roles

            # checks to make sure that role is actually allowed/expected
            role_allowed = False
            for role_type in settings.ALL_ROLES:
                for user_role in roles:
                    if role_type.lower() == user_role.lower():
                        role_allowed = True

            # if role is not allowed then denied (problem with platform)
            # if role is missing, default to Student (problem with request)
            if not role_allowed:
                debug_printer(
                    'DEBUG - User does not have an acceptable role. Check with platform.'
                )
                raise PermissionedDenied()
            else:
                debug_printer('DEBUG - User had an acceptable role: %s' %
                              all_user_roles)

        user, lti_profile = create_new_user(lti_username, email, roles)

    # now it's time to deal with the course_id it does not associate
    # with users as they can flow in and out in a MOOC
    try:
        debug_printer('DEBUG - Course was found %s' % course)
        course_object = LTICourse.get_course_by_id(course)

    except LTICourse.DoesNotExist:
        # this should only happen if an instructor is trying to access the
        # tool from a different course
        debug_printer('DEBUG - Course %s was NOT found. Will be created.' %
                      course)
        message_error = "Sorry, the course you are trying to reach does not exist."
        messages.error(request, message_error)
        if 'Administrator' in roles:
            # if the user is an administrator, the missing course is created
            # otherwise, it will just display an error message
            message_error = "Because you are an instructor, a course has been created for you, edit it below to add a proper name."
            messages.warning(request, message_error)
            course_object = LTICourse.create_course(course, lti_profile)

    # get all the courses the user is a part of
    courses_for_user = LTICourse.get_courses_of_user(lti_profile,
                                                     course_object)

    # then gets all the files associated with the courses
    files_in_courses = TOD_Implementation.get_dict_of_files_from_courses(
        lti_profile, courses_for_user)

    # logs the user in
    lti_profile.user.backend = 'django.contrib.auth.backends.ModelBackend'
    login(request, lti_profile.user)

    # then renders the page using the template
    return render(
        request, 'hx_lti_initializer/testpage2.html', {
            'user': lti_profile.user,
            'email': lti_profile.user.email,
            'user_id': lti_profile.user.get_username(),
            'roles': lti_profile.roles,
            'courses': courses_for_user,
            'files': files_in_courses
        })