Exemple #1
0
    def as_task(self, fun: t.Callable[[], None]) -> None:
        """Run the given ``fun`` as the task.

        .. warning::

            One of the first things this function do is committing the current
            session, however after running ``fun`` nothing is committed.

        :param fun: The function to run as the task, catching the exceptions it
            produces and storing them in this task result.
        :returns: Nothing.
        """
        assert self.state == TaskResultState.not_started, (
            'Cannot start task that has already started, state was in {}'
        ).format(self.state)

        self.state = TaskResultState.started
        db.session.commit()

        try:
            self.result = fun()
        except APIException as exc:
            self.state = TaskResultState.failed
            self.result = JSONResponse.dump_to_object(exc)
        except:  # pylint: disable=bare-except
            logger.warning('The task crashed', exc_info=True)
            self.state = TaskResultState.crashed
            self.result = JSONResponse.dump_to_object(
                APIException(
                    'The task failed for an unknown reason',
                    f'The task {self.id} failed with a uncaught exception',
                    APICodes.UNKOWN_ERROR, 400))
        else:
            self.state = TaskResultState.finished
def test_jsonify():
    class Enum(CGEnum):
        name_a = 2
        name_b = 3

    with flask.Flask(__name__).app_context():
        assert JSONResponse.dump_to_object(Enum.name_a) == 'name_a'
        assert JSONResponse.dump_to_object(Enum.name_b) == 'name_b'
Exemple #3
0
    def as_task(
        self,
        fun: t.Callable[[], t.Optional[TaskResultState]],
        *,
        eta: t.Optional[DatetimeWithTimezone] = None,
    ) -> bool:
        """Run the given ``fun`` as the task.

        .. warning::

            One of the first things this function do is committing the current
            session, however after running ``fun`` nothing is committed.

        :param fun: The function to run as the task, catching the exceptions it
            produces and storing them in this task result.
        :param eta: The time the task should run, if the current time is before
            this ETA the current celery task will be scheduled again and
            ``fun`` will not be called.

        :returns: ``True`` if the task ran, otherwise ``False``.
        """
        if not self.state.is_not_started:  # pragma: no cover
            logger.error('Cannot start task that has already started',
                         task_result=self)
            return False
        elif eta and current_task.maybe_delay_task(eta):
            return False

        self.state = TaskResultState.started
        db.session.commit()

        try:
            result_code = fun()
        except APIException as exc:
            self.state = TaskResultState.failed
            self.result = JSONResponse.dump_to_object(exc)
        except:  # pylint: disable=bare-except
            logger.warning('The task crashed', exc_info=True)
            self.state = TaskResultState.crashed
            self.result = JSONResponse.dump_to_object(
                APIException(
                    'The task failed for an unknown reason',
                    f'The task {self.id} failed with a uncaught exception',
                    APICodes.UNKOWN_ERROR, 400))
        else:
            self.result = None
            self.state = handle_none(result_code, TaskResultState.finished)

        return True
Exemple #4
0
def do_oidc_login(
        lti_provider_id: t.Optional[str] = None) -> werkzeug.wrappers.Response:
    """Do an LTI 1.3 OIDC login.

    :param lti_provider_id: The id of the provider doing the launch, not
        required for LMSes that pass all required information.
    """
    req = helpers.maybe_unwrap_proxy(flask.request, flask.Request)
    if req.method == 'GET':
        target = req.args.get('target_link_uri')
    else:
        target = req.form.get('target_link_uri')
    assert target is not None

    try:
        provider = _maybe_get_provider(lti_provider_id)
        oidc = lti_v1_3.FlaskOIDCLogin.from_request(lti_provider=provider)
        red = oidc.get_redirect_object(target)
    except exceptions.APIException as exc:
        logger.info('Login request went wrong', exc_info=True)
        message = exc.message

        if exc.api_code == exceptions.APICodes.OBJECT_NOT_FOUND:
            message = (
                'This LMS was not found as a LTIProvider for CodeGrade, this'
                ' is probably caused by a wrong setup.')

        return _make_blob_and_redirect(
            {
                'type': 'exception',
                'exception_message': message,
                'original_exception': JSONResponse.dump_to_object(exc),
            },
            version=LTIVersion.v1_3,
            goto_latest_submission=False,
        )
    except pylti1p3.exception.OIDCException as exc:
        logger.info('Login request went wrong', exc_info=True)
        return _make_blob_and_redirect(
            {
                'type': 'exception',
                'exception_message': exc.args[0],
            },
            version=LTIVersion.v1_3,
            goto_latest_submission=False,
        )
    logger.info(
        'Redirecting after oidc',
        target=target,
        get_args=req.args,
        post_args=req.form,
        redirect=red,
    )
    return red.do_redirect()
Exemple #5
0
def _handle_lti_advantage_launch(
        lti_provider_id: t.Optional[str],
        goto_latest_sub: bool) -> t.Union[str, werkzeug.wrappers.Response]:
    app.config['SESSION_COOKIE_SAMESITE'] = 'None'

    try:
        provider = _maybe_get_provider(lti_provider_id)
        message_launch = lti_v1_3.FlaskMessageLaunch.from_request(
            lti_provider=provider, ).validate()
    except exceptions.APIException as exc:
        logger.info('An error occurred during the LTI launch', exc_info=True)
        return _make_blob_and_redirect(
            {
                'type': 'exception',
                'exception_message': exc.message,
                'original_exception': JSONResponse.dump_to_object(exc),
            },
            version=LTIVersion.v1_3,
            goto_latest_submission=False,
        )
    except pylti1p3.exception.LtiException as exc:
        logger.info('Incorrect LTI launch encountered', exc_info=True)
        return _make_blob_and_redirect(
            {
                'type': 'exception',
                'exception_message': exc.args[0],
            },
            version=LTIVersion.v1_3,
            goto_latest_submission=False,
        )

    plat_red_url = flask.request.args.get('platform_redirect_url')
    full_win_launch = flask.request.args.get('full_win_launch_requested')
    if full_win_launch == '1' and plat_red_url:
        return flask.redirect(plat_red_url)

    provider = message_launch.get_lti_provider()
    if (message_launch.is_deep_link_launch()
            and not provider.lms_capabilities.actual_deep_linking_required):
        deep_link = message_launch.get_deep_link()
        dp_resource = lti_v1_3.CGDeepLinkResource.make(message_launch)
        form = deep_link.output_response_form([dp_resource])
        return f'<!DOCTYPE html>\n<html><body>{form}</body></html>'

    return _make_blob_and_redirect(
        {
            'launch_data': message_launch.get_launch_data(),
            'lti_provider_id': message_launch.get_lti_provider().id,
            'request_args': dict(flask.request.args),
        },
        version=LTIVersion.v1_3,
        goto_latest_submission=goto_latest_sub,
    )
Exemple #6
0
def launch_lti() -> t.Any:
    """Do a LTI launch.
    """
    try:
        params = lti_v1_1.LTI.create_from_request(flask.request).launch_params
    except exceptions.APIException as exc:
        return _make_blob_and_redirect(
            {
                'type': 'exception',
                'exception_message': exc.message,
                'original_exception': JSONResponse.dump_to_object(exc),
            },
            version=LTIVersion.v1_1,
            goto_latest_submission=False,
        )

    return _make_blob_and_redirect(params,
                                   LTIVersion.v1_1,
                                   goto_latest_submission=False)