예제 #1
0
    def get(self, request, *args, **kwargs):

        # Get the study
        study = kwargs['study']

        try:
            # Get the patient email and ensure they exist
            patient_email = get_jwt_email(request=request, verify=False)

            # Check FHIR
            if not PPMFHIR.get_consent_document_reference(
                    patient=patient_email, study=study, flatten_return=True):

                # Save it
                APIConsentView.create_consent_document_reference(
                    request=request, study=study)

            # Get their ID
            ppm_id = PPMFHIR.query_patient_id(email=patient_email)

            return HttpResponseRedirect(
                redirect_to=P2MD.get_consent_url(study=study, ppm_id=ppm_id))

        except Exception as e:
            logger.error("Error while rendering consent: {}".format(e),
                         exc_info=True,
                         extra={
                             'request': request,
                             'project': study,
                         })

        raise SystemError('Could not render consent document')
예제 #2
0
def update_dbmi_user(request, **profile):
    logger.debug("Update DBMI user")

    # Get the JWT
    email = authn.get_jwt_email(request, verify=False)

    # Get their profile first
    reg_profile = get_dbmi_user(request=request, email=email)
    if not reg_profile:

        # Ensure email is in their profile
        if "email" not in profile:
            profile["email"] = email

        # Create the profile
        return create_dbmi_user(request, **profile)

    else:
        # Build the URL (needs trailing slash)
        url = furl(dbmi_settings.REG_URL)
        url.path.segments.extend(["api", "register", reg_profile["id"], ""])

        response = requests.put(url.url,
                                headers=authn.dbmi_http_headers(request),
                                data=json.dumps(profile))
        if not response.ok:
            logger.error("Update user response: {}".format(response.content))

        return response.json()
예제 #3
0
def check_email_confirmation(request):
    logger.debug("Checking email confirmation")

    # Build the URL (needs trailing slash)
    url = furl(dbmi_settings.REG_URL)
    url.path.segments.extend(["api", "register", ""])
    url.query.params.add("email", authn.get_jwt_email(request, verify=False))

    # Make the call
    response = requests.get(url.url, headers=authn.dbmi_http_headers(request))
    if not response.ok:
        logger.error("Confirmation email response: {}".format(
            response.content))
        return None

    try:
        # Parse the profile for the status
        email_status = response.json()["results"][0]["email_confirmed"]
        logger.debug("Email confirmation status: {}".format(email_status))

        return email_status

    except (KeyError, IndexError) as e:
        logger.error("Failed parsing profile: {}".format(e))

    return None
예제 #4
0
    def wrap(request, *args, **kwargs):

        # Check for current user
        if not request.user or not request.user.is_authenticated:
            return unauthorized_response(request)

        # Get the payload
        payload = authn.get_jwt_payload(request, verify=False)

        # Check claims in the JWT first, as it is least costly.
        if authz.jwt_has_authz(payload, authz.JWT_AUTHZ_GROUPS,
                               dbmi_settings.AUTHZ_ADMIN_GROUP):
            return view(request, *args, **kwargs)

        # Get their email address
        email = authn.get_jwt_email(request, verify=False)

        # Now consult the AuthZ server
        if authz.has_permission(request, email, dbmi_settings.CLIENT,
                                dbmi_settings.AUTHZ_ADMIN_PERMISSION):
            return view(request, *args, **kwargs)

        # Possibly store these elsewhere for records
        # TODO: Figure out a better way to flag failed access attempts
        logger.warning("{} Failed {} permission on {}".format(
            email, dbmi_settings.AUTHZ_ADMIN_PERMISSION, dbmi_settings.CLIENT))

        raise PermissionDenied
예제 #5
0
    def create_consent_document_reference(request, study, ppm_id=None):
        """
        Accepts the context of a participant's request and renders their signed and accepted consent
        as a PDF and then sends the PDF details to P2MD to create a file location, and finally uploads
        the contents of the file to the datalake for storage.
        :param request: The current request
        :type request: HttpRequest
        :param study: The study for which the consent was signed
        :type study: str
        :param ppm_id: The participant ID for which the consent render is being generated
        :type ppm_id: str
        """
        # Get the participant ID if needed
        if not ppm_id:
            ppm_id = FHIR.query_patient_id(get_jwt_email(request=request, verify=False))

        # Pull their record
        bundle = FHIR.query_participant(patient=ppm_id, flatten_return=True)

        # Get study title
        study_title = PPM.Study.title(study)

        # Check for study-specific PDF
        try:
            template_name = f"consent/pdf/{PPM.Study.get(study).value}.html"
            loader.get_template(template_name)
        except TemplateDoesNotExist:
            template_name = 'consent/pdf/consent.html'

        # Submit consent PDF
        logger.debug(f"PPM/{study}: Rendering consent with template: {template_name}")
        response = render_pdf(f'People-Powered Medicine {study_title} Consent', request, template_name,
                              context=bundle.get('composition'), options={})

        # Hash the content
        hash = hashlib.md5(response.content).hexdigest()
        size = len(response.content)

        # Create the file through P2MD
        uuid, upload_data = P2MD.create_consent_file(request, study, ppm_id, hash, size)

        # Pull the needed bits to upload the PDF
        location = upload_data['locationid']
        post = upload_data['post']

        # Set the files dictionary
        files = {'file': response.content}

        # Now that we have the file locally, send it to S3
        response = requests.post(post['url'], data=post['fields'], files=files)
        response.raise_for_status()

        # Set request data
        P2MD.uploaded_consent(request, study, ppm_id, uuid, location)

        return True
예제 #6
0
    def get_user_info(self, request):

        # Get info from token header
        return {
            "ip_address": get_client_ip(request.META),
            "username": get_jwt_username(request, verify=False),
            "email": get_jwt_email(request, verify=False),
            "client": get_jwt_value(request, "aud", verify=False),
            "tenant": get_jwt_value(request, "iss", verify=False),
        }
예제 #7
0
    def get_jwt_user(request):

        # Check for a valid token
        token = authn.get_jwt(request)
        if not token or not authn.validate_rs256_jwt(token):
            return AnonymousUser()

        # Get their username
        username = authn.get_jwt_username(request, verify=False)

        # Use the usual routine to get the currently cached user
        user = django_auth.get_user(request)
        if user.is_authenticated:
            logger.debug("Found existing User session: {}".format(username))

            # A cached user is present. We need to double-check JWT user to ensure
            # they are the same as the cached user.
            username = authn.get_jwt_username(request, verify=False)
            email = authn.get_jwt_email(request, verify=False)
            if username and email:
                if not user.username.lower() == username.lower(
                ) or not user.email.lower() == email.lower():
                    logger.debug(
                        "User session does not match JWT, logging out")

                    # TODO: Figure out if its necessary to person any session invalidation here
                    return AnonymousUser()

        else:
            logger.debug(
                "No existing User, attempting to login: {}".format(username))

            # No user is logged in but we have a JWT token. Attempt to authenticate
            # the current JWT and if it succeeds, login and cache the user.
            user = django_auth.authenticate(request, token=token)
            if user and user.is_authenticated:
                logger.debug("User has authenticated: {}".format(username))

                # Store this user in session
                django_auth.login(request, user)

            else:
                logger.debug(
                    "User could not be authenticated: {}".format(username))
                # Whatever token this user has, it's not valid OR their account would/could not
                # be created, deny permission. This will likely be the case for instances where
                # automatic user creation is disabled and a user with a valid JWT is not being
                # granted an account.
                raise PermissionDenied

        return user
예제 #8
0
    def get(self, request, *args, **kwargs):
        logger.debug("Generating contact form")

        # Set initial values.
        initial = {
            'email': get_jwt_email(request=request, verify=False)
        }

        # Generate and render the form.
        form = ContactForm(initial=initial)
        if request.is_ajax():
            return render(request, 'contact/modal.html', {'contact_form': form})
        else:
            return render(request, 'contact/contact.html', {'contact_form': form})
예제 #9
0
def create_dbmi_user(request, **profile):
    logger.debug("Creating DBMI user")

    # Get the JWT
    email = authn.get_jwt_email(request, verify=False)

    # Update kwargs
    profile["email"] = email

    # Build the URL (needs trailing slash)
    url = furl(dbmi_settings.REG_URL)
    url.path.segments.extend(["api", "register", ""])

    response = requests.post(url.url,
                             headers=authn.dbmi_http_headers(request),
                             data=json.dumps(profile))
    if not response.ok:
        logger.error("Create user response: {}".format(response.content))

    return response.json()
예제 #10
0
        def wrap(request, *args, **kwargs):

            # Check for current user
            if not request.user or not request.user.is_authenticated:
                return unauthorized_response(request)

            # Get their email address
            email = authn.get_jwt_email(request, verify=False)

            # Check permission
            if authz.has_permission(request, email, item, permission):
                return view(request, *args, **kwargs)

            # Possibly store these elsewhere for records
            # TODO: Figure out a better way to flag failed access attempts
            logger.warning("{} Failed {} permission on {}".format(
                email, permission, dbmi_settings.CLIENT))

            # Forbid if nothing else
            raise PermissionDenied
예제 #11
0
def get_dbmi_user(request, email=None):
    logger.debug("Get DBMI user")

    # Get the JWT
    if not email:
        email = authn.get_jwt_email(request, verify=False)

    # Build the URL (needs trailing slash)
    url = furl(dbmi_settings.REG_URL)
    url.path.segments.extend(["api", "register", ""])

    # Add email
    url.query.params.add("email", email)

    # Requests for profiles are limited to the profile for the requesting user
    response = requests.get(url.url, headers=authn.dbmi_http_headers(request))
    if not response.ok:
        logger.error("Get user response: {}".format(response.content))

    # Return the profile
    profiles = response.json()["results"]
    return next(iter(profiles), None)
예제 #12
0
    def get_jwt_user(request):

        # Use super's implementation
        user = DBMIAuthenticationMiddleware.get_jwt_user(request)
        if user:

            # Check if they've been granted admin level privileges
            if user.is_staff or user.is_superuser:

                # Get details
                token = authn.get_jwt(request)
                username = authn.get_jwt_username(request, verify=False)
                email = authn.get_jwt_email(request, verify=False)

                logger.debug(
                    f'User "{username}":"{email}" is currently admin; rerunning sync...'
                )

                # Run their sync again to make absolutely sure they're still an admin
                user = django_auth.authenticate(request, token=token)
                if user and user.is_authenticated:
                    logger.debug(
                        "User has re-authenticated: {}".format(username))

                    # Check updated status
                    if user.is_superuser or user.is_staff:
                        logger.debug(
                            f'User "{username}":"{email}" is still admin')

                else:
                    logger.debug(
                        "User could not be authenticated: {}".format(username))
                    # Whatever token this user has, it's not valid OR their account would/could not
                    # be created, deny permission. This will likely be the case for instances where
                    # automatic user creation is disabled and a user with a valid JWT is not being
                    # granted an account.
                    raise PermissionDenied

        return user
예제 #13
0
    def get(self, request, *args, **kwargs):
        logger.debug(f'PPM/{self.study}: GET questionnaire')

        # Get the patient email and ensure they exist
        patient_email = get_jwt_email(request=request, verify=False)

        try:
            # If demo mode, disable checks for participant and past submissions
            if not self.demo(request):

                # Check the current patient
                FHIR.check_patient(patient_email)

                # Check response
                FHIR.check_response(self.questionnaire_id, patient_email)

            # Create the form
            form = self.Form(self.questionnaire_id)

            # Prepare the context
            context = {
                'study': self.study,
                'questionnaire_id': self.questionnaire_id,
                'form': form,
                'return_url': self.return_url,
            }

            # Get the passed parameters
            return render(request,
                          template_name='questionnaire/{}.html'.format(
                              self.study),
                          context=context)

        except FHIR.PatientDoesNotExist:
            logger.warning(
                'Patient does not exist: {}'.format(patient_email[:3] +
                                                    '****' +
                                                    patient_email[-4:]))
            return render_error(
                request,
                title='Patient Does Not Exist',
                message=
                'A FHIR resource does not yet exist for the current user. '
                'Please sign into the People-Powered dashboard to '
                'create your user.',
                support=False)

        except FHIR.QuestionnaireDoesNotExist:
            logger.warning('Questionnaire does not exist: {}'.format(
                self.questionnaire_id))
            return render_error(
                request,
                title='Questionnaire Does Not Exist',
                message='The requested questionnaire does not exist!',
                support=False)

        except FHIR.QuestionnaireResponseAlreadyExists:
            logger.warning('Questionnaire already finished')
            return render_error(
                request,
                title='Questionnaire Already Completed',
                message='You have already filled out and submitted this '
                'questionnaire.',
                support=False)

        except Exception as e:
            logger.error("Error while rendering questionnaire: {}".format(e),
                         exc_info=True,
                         extra={
                             'request': request,
                             'project': self.study,
                         })
            return render_error(
                request,
                title='Application Error',
                message='The application has experienced an unknown error {}'.
                format(': {}'.format(e) if settings.DEBUG else '.'),
                support=False)
예제 #14
0
    def post(self, request, *args, **kwargs):
        logger.debug("Processing contact form POST")

        # Process the form.
        form = ContactForm(request.POST)
        if form.is_valid():
            logger.debug("Form is valid")

            # Get the user's browser
            user_agent = request.META.get('HTTP_USER_AGENT', 'unknown')

            # Form the context.
            context = {
                'from_email': form.cleaned_data['email'],
                'from_name': form.cleaned_data['name'],
                'message': form.cleaned_data['message'],
                'user_agent': user_agent,
            }

            # List out the recipients.
            recipients = settings.CONTACT_FORM_RECIPIENTS.split(',')

            # Check for test accounts.
            test_admin = ContactView.check_test_account(email=get_jwt_email(request=request, verify=False))
            if test_admin is not None:
                recipients = [test_admin]

            logger.debug("Found recipients {}".format(recipients))

            # Send it out.
            msg_html = render_to_string('contact/email/contact.html', context)
            msg_plain = render_to_string('contact/email/contact.txt', context)

            try:
                msg = EmailMultiAlternatives('PPM Contact Form Inquiry', msg_plain, settings.DEFAULT_FROM_EMAIL, recipients)
                msg.attach_alternative(msg_html, "text/html")
                msg.send()

                logger.debug("Contact email sent!")

                # Check how the request was made.
                if request.is_ajax():
                    return HttpResponse('SUCCESS', status=200)
                else:
                    return render(request, 'contact/success.html',
                                  context={'return_url': settings.RETURN_URL})

            except Exception as e:
                logger.error('Contact form error: {}'.format(e), exc_info=True,
                             extra={'request': request, 'context': context})

                if request.is_ajax():
                    return HttpResponse('ERROR', status=500)
                else:
                    messages.error(request, 'An unexpected error occurred, please try again')
                    return ContactView.render_error(request)

        else:
            logger.error("Form is invalid: {}".format(request.POST))

            # Check how the request was made.
            if request.is_ajax():
                return HttpResponse('INVALID', status=500)
            else:
                messages.error(request, 'An unexpected error occurred, please try again')
                return HttpResponseRedirect(reverse('contact:contact'))
예제 #15
0
    def post(self, request, *args, **kwargs):
        logger.debug('Signature view')

        # Get the patient's email
        patient_email = get_jwt_email(request=request, verify=False)

        # Process the form
        try:
            # Check form type
            if request.session['individual']:
                logger.debug('Individual signature')

                # Get the form
                form = ASDIndividualSignatureForm(request.POST)
                if not form.is_valid():
                    logger.debug('Individual signature invalid: {}'.format(
                        form.errors.as_json()))

                    # Return the form
                    context = {'form': form, 'return_url': self.return_url}

                    return render(
                        request,
                        template_name=
                        'consent/asd/individual-signature-part-1.html',
                        context=context)

                # Build the data
                user_forms = dict({
                    'individual': form.cleaned_data,
                    'quiz': request.session['quiz']
                })

                # Submit the data
                FHIR.submit_asd_individual(patient_email,
                                           user_forms,
                                           dry=self.demo(request))

                # If in demo mode, do not create PDF
                if not self.demo(request):

                    # Submit consent PDF in the background
                    threading.Thread(target=APIConsentView.
                                     create_consent_document_reference,
                                     args=(request,
                                           PPM.Study.ASD.value)).start()

                # Get the return URL
                context = {
                    'return_url': self.return_url,
                    'demo': self.demo(request)
                }

                # Get the passed parameters
                return render(request,
                              template_name='consent/success.html',
                              context=context)

            else:
                logger.debug('Guardian/ward signature')

                # Check which signature
                if request.session.get('guardian'):
                    logger.debug('Ward signature')

                    # Get the form
                    form = ASDWardSignatureForm(request.POST)
                    if not form.is_valid():
                        logger.debug('Ward signature invalid: {}'.format(
                            form.errors.as_json()))

                        # Return the form
                        context = {'form': form, 'return_url': self.return_url}

                        return render(
                            request,
                            template_name=
                            'consent/asd/guardian-signature-part-3.html',
                            context=context)

                    # Build the data
                    user_forms = dict({
                        'ward': form.cleaned_data,
                        'guardian': request.session['guardian'],
                        'quiz': request.session['quiz']
                    })

                    # Submit the data
                    FHIR.submit_asd_guardian(patient_email,
                                             user_forms,
                                             dry=self.demo(request))

                    # If in demo mode, do not create PDF
                    if not self.demo(request):

                        # Submit consent PDF in the background
                        threading.Thread(target=APIConsentView.
                                         create_consent_document_reference,
                                         args=(request,
                                               PPM.Study.ASD.value)).start()

                    # Get the return URL
                    context = {
                        'return_url': self.return_url,
                        'demo': self.demo(request)
                    }

                    # Get the passed parameters
                    return render(request,
                                  template_name='consent/success.html',
                                  context=context)

                else:
                    logger.debug('Guardian signature')

                    # Get the form
                    form = ASDGuardianSignatureForm(request.POST)
                    if not form.is_valid():
                        logger.debug('Guardian signature invalid: {}'.format(
                            form.errors.as_json()))

                        # Return the form
                        context = {'form': form, 'return_url': self.return_url}

                        return render(
                            request,
                            template_name=
                            'consent/asd/guardian-signature-part-1-2.html',
                            context=context)

                    # Fix the date
                    date = form.cleaned_data['date'].isoformat()
                    form.cleaned_data['date'] = date

                    # Retain their responses
                    request.session['guardian'] = form.cleaned_data

                    # Make the ward signature form
                    form = ASDWardSignatureForm()

                    # Get the return URL
                    context = {
                        'form': form,
                        'return_url': self.return_url,
                    }

                    # Get the passed parameters
                    return render(request,
                                  template_name=
                                  'consent/asd/guardian-signature-part-3.html',
                                  context=context)

        except FHIR.PatientDoesNotExist:
            logger.warning('Patient does not exist')
            return render_error(
                request,
                title='Patient Does Not Exist',
                message=
                'A FHIR resource does not yet exist for the current user. '
                'Please sign into the People-Powered dashboard to '
                'create your user.',
                support=False)

        except FHIR.QuestionnaireDoesNotExist:
            logger.warning('Consent does not exist: ASD')
            return render_error(
                request,
                title='Consent Does Not Exist',
                message='The requested consent does not exist!',
                support=False)

        except FHIR.QuestionnaireResponseAlreadyExists:
            logger.warning('Consent already finished')
            return render_error(
                request,
                title='Consent Already Completed',
                message='You have already filled out and submitted this '
                'consent.',
                support=False)

        except Exception as e:
            logger.error(
                "Error while submitting consent signature: {}".format(e),
                exc_info=True,
                extra={
                    'project': 'asd',
                    'request': request,
                })
            return render_error(
                request,
                title='Application Error',
                message='The application has experienced an unknown error{}'.
                format(': {}'.format(e) if settings.DEBUG else '.'),
                support=False)
예제 #16
0
    def get(self, request, *args, **kwargs):

        # Clearing any leftover sessions
        [
            request.session.pop(key, None)
            for key in ['quiz', 'individual', 'guardian']
        ]

        # Get the patient email and ensure they exist
        patient_email = get_jwt_email(request=request, verify=False)

        try:

            # If in demo mode, do not check participant and prior submissions
            if not self.demo(request):

                FHIR.check_patient(patient_email)

                # Check response
                FHIR.check_consent(PPM.Study.ASD.value, patient_email)

            # Create the form
            form = ASDTypeForm()

            context = {'form': form, 'return_url': self.return_url}

            return render(request,
                          template_name='consent/asd.html',
                          context=context)

        except FHIR.PatientDoesNotExist:
            logger.warning('Patient does not exist')
            return render_error(
                request,
                title='Patient Does Not Exist',
                message=
                'A FHIR resource does not yet exist for the current user. '
                'Please sign into the People-Powered dashboard to '
                'create your user.',
                support=False)

        except FHIR.QuestionnaireDoesNotExist:
            logger.warning('Consent does not exist: NEER')
            return render_error(
                request,
                title='Consent Does Not Exist',
                message='The requested consent does not exist!',
                support=False)

        except FHIR.ConsentAlreadyExists:
            logger.warning('Consent already finished')
            return render_error(
                request,
                title='Consent Already Completed',
                message='You have already filled out and submitted this '
                'consent.',
                support=False)

        except Exception as e:
            logger.error("Error while rendering consent: {}".format(e),
                         exc_info=True,
                         extra={
                             'request': request,
                             'project': 'asd',
                         })
            return render_error(
                request,
                title='Application Error',
                message='The application has experienced an unknown error{}'.
                format(': {}'.format(e) if settings.DEBUG else '.'),
                support=False)
예제 #17
0
    def post(self, request, *args, **kwargs):

        # Get the patient email
        patient_email = get_jwt_email(request=request, verify=False)

        # Get the form
        form = self.Form(request.POST)
        if not form.is_valid():

            # Return the form
            context = {
                'study': self.study,
                'form': form,
                'return_url': self.return_url
            }

            return render(request,
                          template_name='consent/{}.html'.format(self.study),
                          context=context)

        # Process the form
        try:
            # Submit the consent
            FHIR.submit_consent(self.study,
                                patient_email,
                                form.cleaned_data,
                                dry=self.demo(request))

            if not self.demo(request):

                # Submit consent PDF in the background
                threading.Thread(
                    target=APIConsentView.create_consent_document_reference,
                    args=(request, self.study)).start()

            # Get the return URL
            context = {
                'study': self.study,
                'return_url': self.return_url,
                'demo': self.demo(request)
            }

            # Get the passed parameters
            return render(request,
                          template_name='consent/success.html',
                          context=context)

        except FHIR.QuestionnaireDoesNotExist:
            logger.warning('Consent does not exist: {}'.format(
                PPM.Study.title(self.study)))
            return render_error(
                request,
                title='Consent Does Not Exist: {}'.format(
                    self.questionnaire_id),
                message='The requested consent does not exist!',
                support=False)

        except FHIR.PatientDoesNotExist:
            logger.warning(
                'Patient does not exist: {}'.format(patient_email[:3] +
                                                    '****' +
                                                    patient_email[-4:]))
            return render_error(
                request,
                title='Patient Does Not Exist',
                message=
                'A FHIR resource does not yet exist for the current user. '
                'Please sign into the People-Powered dashboard to '
                'create your user.',
                support=False)
        except Exception as e:
            logger.error("Error while submitting consent: {}".format(e),
                         exc_info=True,
                         extra={
                             'request': request,
                             'project': self.study,
                             'questionnaire': self.questionnaire_id,
                             'form': self.Form
                         })
            return render_error(
                request,
                title='Application Error',
                message='The application has experienced an unknown error {}'.
                format(': {}'.format(e) if settings.DEBUG else '.'),
                support=False)
예제 #18
0
    def get(self, request, *args, **kwargs):

        # Get the patient email and ensure they exist
        patient_email = get_jwt_email(request=request, verify=False)

        try:
            # If in demo mode, do not check participant and prior submissions
            if not self.demo(request):

                # Ensure the current user has a record
                FHIR.check_patient(patient_email)

                # Check response
                FHIR.check_consent(self.study, patient_email)

            # Create the form
            form = self.Form()

            context = {
                'study': self.study,
                'form': form,
                'return_url': self.return_url
            }

            # Build the template response
            response = render(request,
                              template_name='consent/{}.html'.format(
                                  self.study),
                              context=context)

            return response

        except FHIR.PatientDoesNotExist:
            logger.warning('Patient does not exist')
            return render_error(
                request,
                title='Patient Does Not Exist',
                message=
                'A FHIR resource does not yet exist for the current user. '
                'Please sign into the People-Powered dashboard to '
                'create your user.',
                support=False)

        except FHIR.QuestionnaireDoesNotExist:
            logger.warning('Consent does not exist: {}'.format(
                PPM.Study.title(self.study)))
            return render_error(
                request,
                title='Consent Does Not Exist: {}'.format(
                    self.questionnaire_id),
                message='The requested consent does not exist!',
                support=False)

        except FHIR.ConsentAlreadyExists:
            logger.warning('Consent already finished')
            return render_error(
                request,
                title='Consent Already Completed',
                message='You have already filled out and submitted this '
                'consent.',
                support=False)

        except Exception as e:
            logger.error("Error while rendering consent: {}".format(e),
                         exc_info=True,
                         extra={
                             'request': request,
                             'project': self.study,
                             'questionnaire': self.questionnaire_id,
                             'form': self.Form
                         })
            return render_error(
                request,
                title='Application Error',
                message='The application has experienced an unknown error{}'.
                format(': {}'.format(e) if settings.DEBUG else '.'),
                support=False)
예제 #19
0
    def post(self, request, *args, **kwargs):
        logger.debug(f'PPM/{self.study}: POST questionnaire')

        # Get the patient email
        patient_email = get_jwt_email(request=request, verify=False)

        # create a form instance and populate it with data from the request:
        form = self.Form(self.questionnaire_id, request.POST)

        # check whether it's valid:
        if not form.is_valid():
            logger.debug(
                f'PPM/{self.study}: Form was invalid: {form.errors.as_json()}')

            # Return with errors
            context = {
                'study': self.study,
                'form': form,
                'questionnaire_id': self.questionnaire_id,
                'return_url': self.return_url,
            }

            # Get the passed parameters
            return render(request,
                          template_name='questionnaire/{}.html'.format(
                              self.study),
                          context=context)

        else:
            logger.debug(f'PPM/{self.study}: Form was valid')

        # Process the form
        try:

            # Submit the form
            FHIR.submit_questionnaire(self.study,
                                      patient_email,
                                      form.cleaned_data,
                                      dry=self.demo(request))

            # Get the return URL
            logger.debug(
                f'PPM/{self.study}: Success, returning user to: {self.return_url}'
            )
            context = {
                'questionnaire_id': self.questionnaire_id,
                'return_url': self.return_url,
                'demo': self.demo(request)
            }

            # Get the passed parameters
            return render(request,
                          template_name='questionnaire/success.html',
                          context=context)

        except FHIR.QuestionnaireDoesNotExist:
            logger.warning('Questionnaire does not exist: {}'.format(
                self.questionnaire_id))
            return render_error(
                request,
                title='Questionnaire Does Not Exist',
                message='The requested questionnaire does not exist!',
                support=False)

        except FHIR.PatientDoesNotExist:
            logger.warning(
                'Patient does not exist: {}'.format(patient_email[:3] +
                                                    '****' +
                                                    patient_email[-4:]))
            return render_error(
                request,
                title='Patient Does Not Exist',
                message=
                'A FHIR resource does not yet exist for the current user. '
                'Please sign into the People-Powered dashboard to '
                'create your user.',
                support=False)
        except Exception as e:
            logger.error("Error while submitting questionnaire: {}".format(e),
                         exc_info=True,
                         extra={
                             'project': self.study,
                         })
            return render_error(
                request,
                title='Application Error',
                message='The application has experienced an unknown error{}'.
                format(': {}'.format(e) if settings.DEBUG else '.'),
                support=False)