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'
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
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()
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, )
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)