Ejemplo n.º 1
0
async def setup_course_hook(
    authenticator: Authenticator, handler: RequestHandler, authentication: Dict[str, str]
) -> Dict[str, str]:
    """
    Calls the microservice to setup up a new course in case it does not exist.
    The data needed is received from auth_state within authentication object. This
    function assumes that the required k/v's in the auth_state dictionary are available,
    since the Authenticator(s) validates the data beforehand.

    This function requires `Authenticator.enable_auth_state = True` and is intended
    to be used as a post_auth_hook.

    Args:
        authenticator: the JupyterHub Authenticator object
        handler: the JupyterHub handler object
        authentication: the authentication object returned by the
          authenticator class

    Returns:
        authentication (Required): updated authentication object
    """
    lti_utils = LTIUtils()
    jupyterhub_api = JupyterHubAPI()

    # normalize the name and course_id strings in authentication dictionary
    course_id = lti_utils.normalize_string(authentication['auth_state']['course_id'])
    nb_service = NbGraderServiceHelper(course_id)
    username = lti_utils.normalize_string(authentication['name'])
    lms_user_id = authentication['auth_state']['lms_user_id']
    user_role = authentication['auth_state']['user_role']
    # register the user (it doesn't matter if it is a student or instructor) with her/his lms_user_id in nbgrader
    nb_service.add_user_to_nbgrader_gradebook(username, lms_user_id)
    # TODO: verify the logic to simplify groups creation and membership
    if user_is_a_student(user_role):
        # assign the user to 'nbgrader-<course_id>' group in jupyterhub and gradebook
        await jupyterhub_api.add_student_to_jupyterhub_group(course_id, username)
    elif user_is_an_instructor(user_role):
        # assign the user in 'formgrade-<course_id>' group
        await jupyterhub_api.add_instructor_to_jupyterhub_group(course_id, username)
    # launch the new (?) grader-notebook as a service
    setup_response = await register_new_service(org_name=ORG_NAME, course_id=course_id)

    return authentication
Ejemplo n.º 2
0
def test_user_is_a_student_method_returns_false_when_instructor_role():
    result = user_is_a_student('Instructor')
    assert result is False
Ejemplo n.º 3
0
def test_user_is_a_student_method_ignores_case():
    result = user_is_a_student('learner')
    assert result is True
    result = user_is_a_student('LeArNeR')
    assert result is True
Ejemplo n.º 4
0
def test_user_is_a_student_method_returns_false_when_role_not_supported():
    result = user_is_a_student('Unknown')
    assert result is False
Ejemplo n.º 5
0
def test_user_is_a_student_method_returns_true_when_learner_role():
    result = user_is_a_student('Learner')
    assert result is True
Ejemplo n.º 6
0
def test_user_is_a_student_method_raises_an_error_with_missing_value():
    with pytest.raises(ValueError):
        user_is_a_student('')
Ejemplo n.º 7
0
def test_user_is_a_student_method_ignores_case():
    result = user_is_a_student("learner")
    assert result is True
    result = user_is_a_student("LeArNeR")
    assert result is True
Ejemplo n.º 8
0
async def setup_course_hook_lti11(
    handler: RequestHandler,
    authentication: Dict[str, str],
) -> Dict[str, str]:
    """
    Calls the microservice to setup up a new course in case it does not exist when receiving
    LTI 1.1 launch requests. The data needed is received from auth_state within authentication object.
    This function assumes that the required k/v's in the auth_state dictionary are available,
    since the Authenticator(s) validates the data beforehand.

    This function requires `Authenticator.enable_auth_state = True` and is intended
    to be used as a post_auth_hook.

    Args:
        handler: the JupyterHub handler object
        authentication: the authentication object returned by the
            authenticator class

    Returns:
        authentication (Required): updated authentication object
    """
    lti_utils = LTIUtils()
    jupyterhub_api = JupyterHubAPI()

    # normalize the name and course_id strings in authentication dictionary
    username = authentication["name"]
    lms_user_id = authentication["auth_state"]["user_id"]
    user_role = authentication["auth_state"]["roles"].split(",")[0]
    course_id = lti_utils.normalize_string(
        authentication["auth_state"]["context_label"])
    nb_service = NbGraderServiceHelper(course_id, True)

    # register the user (it doesn't matter if it is a student or instructor) with her/his lms_user_id in nbgrader
    nb_service.add_user_to_nbgrader_gradebook(username, lms_user_id)
    # TODO: verify the logic to simplify groups creation and membership
    if user_is_a_student(user_role):
        try:
            # assign the user to 'nbgrader-<course_id>' group in jupyterhub and gradebook
            await jupyterhub_api.add_student_to_jupyterhub_group(
                course_id, username)
        except AddJupyterHubUserException as e:
            logger.error(
                "An error when adding student username: %s to course_id: %s with exception %s",
                (username, course_id, e),
            )
    elif user_is_an_instructor(user_role):
        try:
            # assign the user in 'formgrade-<course_id>' group
            await jupyterhub_api.add_instructor_to_jupyterhub_group(
                course_id, username)
        except AddJupyterHubUserException as e:
            logger.error(
                "An error when adding instructor username: %s to course_id: %s with exception %s",
                (username, course_id, e),
            )

    # launch the new grader-notebook as a service
    try:
        _ = await register_new_service(org_name=ORG_NAME, course_id=course_id)
    except Exception as e:
        logger.error(
            "Unable to launch the shared grader notebook with exception %s", e)

    return authentication