Exemplo n.º 1
0
def results_callback(request):
    """
    Software Secure will call this callback to tell us whether a user is
    verified to be who they said they are.
    """
    body = request.body

    try:
        body_dict = json.loads(body)
    except ValueError:
        log.exception(
            "Invalid JSON received from Software Secure:\n\n{}\n".format(body))
        return HttpResponseBadRequest(
            "Invalid JSON. Received:\n\n{}".format(body))

    if not isinstance(body_dict, dict):
        log.error(
            "Reply from Software Secure is not a dict:\n\n{}\n".format(body))
        return HttpResponseBadRequest(
            "JSON should be dict. Received:\n\n{}".format(body))

    headers = {
        "Authorization": request.META.get("HTTP_AUTHORIZATION", ""),
        "Date": request.META.get("HTTP_DATE", "")
    }

    has_valid_signature(
        "POST", headers, body_dict,
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"],
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"])

    _response, access_key_and_sig = headers["Authorization"].split(" ")
    access_key = access_key_and_sig.split(":")[0]

    # This is what we should be doing...
    #if not sig_valid:
    #    return HttpResponseBadRequest("Signature is invalid")

    # This is what we're doing until we can figure out why we disagree on sigs
    if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"][
            "API_ACCESS_KEY"]:
        return HttpResponseBadRequest("Access key invalid")

    receipt_id = body_dict.get("EdX-ID")
    result = body_dict.get("Result")
    reason = body_dict.get("Reason", "")
    error_code = body_dict.get("MessageType", "")

    try:
        attempt = SoftwareSecurePhotoVerification.objects.get(
            receipt_id=receipt_id)
    except SoftwareSecurePhotoVerification.DoesNotExist:
        log.error(
            "Software Secure posted back for receipt_id %s, but not found",
            receipt_id)
        return HttpResponseBadRequest("edX ID {} not found".format(receipt_id))
    if result == "PASS":
        log.debug("Approving verification for %s", receipt_id)
        attempt.approve()
        status = "approved"

    elif result == "FAIL":
        log.debug("Denying verification for %s", receipt_id)
        attempt.deny(json.dumps(reason), error_code=error_code)
        status = "denied"
    elif result == "SYSTEM FAIL":
        log.debug("System failure for %s -- resetting to must_retry",
                  receipt_id)
        attempt.system_error(json.dumps(reason), error_code=error_code)
        status = "error"
        log.error("Software Secure callback attempt for %s failed: %s",
                  receipt_id, reason)
    else:
        log.error("Software Secure returned unknown result %s", result)
        return HttpResponseBadRequest(
            "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".
            format(result))

    return HttpResponse("OK!")
Exemplo n.º 2
0
def results_callback(request):
    """
    Software Secure will call this callback to tell us whether a user is
    verified to be who they said they are.
    """
    body = request.body

    try:
        body_dict = json.loads(body.decode('utf-8'))
    except ValueError:
        log.exception(u"Invalid JSON received from Software Secure:\n\n{}\n".format(body))
        return HttpResponseBadRequest(u"Invalid JSON. Received:\n\n{}".format(body))

    if not isinstance(body_dict, dict):
        log.error(u"Reply from Software Secure is not a dict:\n\n{}\n".format(body))
        return HttpResponseBadRequest(u"JSON should be dict. Received:\n\n{}".format(body))

    headers = {
        "Authorization": request.META.get("HTTP_AUTHORIZATION", ""),
        "Date": request.META.get("HTTP_DATE", "")
    }

    has_valid_signature(
        "POST",
        headers,
        body_dict,
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"],
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"]
    )

    _response, access_key_and_sig = headers["Authorization"].split(" ")
    access_key = access_key_and_sig.split(":")[0]

    # This is what we should be doing...
    # if not sig_valid:
    #    return HttpResponseBadRequest("Signature is invalid")

    # This is what we're doing until we can figure out why we disagree on sigs
    if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"]:
        return HttpResponseBadRequest("Access key invalid")

    receipt_id = body_dict.get("EdX-ID")
    result = body_dict.get("Result")
    reason = body_dict.get("Reason", "")
    error_code = body_dict.get("MessageType", "")

    try:
        attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id)
    except SoftwareSecurePhotoVerification.DoesNotExist:
        log.error(u"Software Secure posted back for receipt_id %s, but not found", receipt_id)
        return HttpResponseBadRequest(u"edX ID {} not found".format(receipt_id))

    user = attempt.user
    verification_status_email_vars = {
        'platform_name': settings.PLATFORM_NAME,
    }
    if result == "PASS":
        # If this verification is not an outdated version then make expiry date of previous approved verification NULL
        # Setting expiry date to NULL is important so that it does not get filtered in the management command
        # that sends email when verification expires : verify_student/send_verification_expiry_email
        if attempt.status != 'approved':
            verification = SoftwareSecurePhotoVerification.objects.filter(status='approved', user_id=attempt.user_id)
            if verification:
                log.info(u'Making expiry date of previous approved verification NULL for {}'.format(attempt.user_id))
                # The updated_at field in sspv model has auto_now set to True, which means any time save() is called on
                # the model instance, `updated_at` will change. Some of the existing functionality of verification
                # (showing your verification has expired on dashboard) relies on updated_at.
                # In case the attempt.approve() fails for some reason and to not cause any inconsistencies in existing
                # functionality update() is called instead of save()
                previous_verification = verification.latest('updated_at')
                SoftwareSecurePhotoVerification.objects.filter(pk=previous_verification.pk
                                                               ).update(expiry_date=None, expiry_email_date=None)
        log.debug(u'Approving verification for {}'.format(receipt_id))
        attempt.approve()
        status = u"approved"
        expiry_date = datetime.date.today() + datetime.timedelta(
            days=settings.VERIFY_STUDENT["DAYS_GOOD_FOR"]
        )
        verification_status_email_vars['expiry_date'] = expiry_date.strftime("%m/%d/%Y")
        verification_status_email_vars['full_name'] = user.profile.name
        subject = _(u"Your {platform_name} ID Verification Approved").format(
            platform_name=settings.PLATFORM_NAME
        )
        context = {
            'subject': subject,
            'template': 'emails/passed_verification_email.txt',
            'email': user.email,
            'email_vars': verification_status_email_vars
        }
        send_verification_status_email.delay(context)

    elif result == "FAIL":
        log.debug(u"Denying verification for %s", receipt_id)
        attempt.deny(json.dumps(reason), error_code=error_code)
        status = "denied"
        reverify_url = '{}{}'.format(settings.LMS_ROOT_URL, reverse("verify_student_reverify"))
        verification_status_email_vars['reasons'] = reason
        verification_status_email_vars['reverify_url'] = reverify_url
        verification_status_email_vars['faq_url'] = settings.ID_VERIFICATION_SUPPORT_LINK
        subject = _(u"Your {platform_name} Verification Has Been Denied").format(
            platform_name=settings.PLATFORM_NAME
        )
        context = {
            'subject': subject,
            'template': 'emails/failed_verification_email.txt',
            'email': user.email,
            'email_vars': verification_status_email_vars
        }
        send_verification_status_email.delay(context)

    elif result == "SYSTEM FAIL":
        log.debug(u"System failure for %s -- resetting to must_retry", receipt_id)
        attempt.system_error(json.dumps(reason), error_code=error_code)
        status = "error"
        log.error(u"Software Secure callback attempt for %s failed: %s", receipt_id, reason)
    else:
        log.error(u"Software Secure returned unknown result %s", result)
        return HttpResponseBadRequest(
            u"Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result)
        )

    return HttpResponse("OK!")
Exemplo n.º 3
0
def results_callback(request):
    """
    Software Secure will call this callback to tell us whether a user is
    verified to be who they said they are.
    """
    body = request.body

    try:
        body_dict = json.loads(body)
    except ValueError:
        log.exception("Invalid JSON received from Software Secure:\n\n{}\n".format(body))
        return HttpResponseBadRequest("Invalid JSON. Received:\n\n{}".format(body))

    if not isinstance(body_dict, dict):
        log.error("Reply from Software Secure is not a dict:\n\n{}\n".format(body))
        return HttpResponseBadRequest("JSON should be dict. Received:\n\n{}".format(body))

    headers = {
        "Authorization": request.META.get("HTTP_AUTHORIZATION", ""),
        "Date": request.META.get("HTTP_DATE", "")
    }

    has_valid_signature(
        "POST",
        headers,
        body_dict,
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"],
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"]
    )

    _response, access_key_and_sig = headers["Authorization"].split(" ")
    access_key = access_key_and_sig.split(":")[0]

    # This is what we should be doing...
    #if not sig_valid:
    #    return HttpResponseBadRequest("Signature is invalid")

    # This is what we're doing until we can figure out why we disagree on sigs
    if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"]:
        return HttpResponseBadRequest("Access key invalid")

    receipt_id = body_dict.get("EdX-ID")
    result = body_dict.get("Result")
    reason = body_dict.get("Reason", "")
    error_code = body_dict.get("MessageType", "")

    try:
        attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id)
    except SoftwareSecurePhotoVerification.DoesNotExist:
        log.error("Software Secure posted back for receipt_id %s, but not found", receipt_id)
        return HttpResponseBadRequest("edX ID {} not found".format(receipt_id))

    user = attempt.user
    verification_status_email_vars = {
        'platform_name': settings.PLATFORM_NAME,
    }
    if result == "PASS":
        log.debug("Approving verification for %s", receipt_id)
        attempt.approve()
        status = "approved"
        expiry_date = datetime.date.today() + datetime.timedelta(
            days=settings.VERIFY_STUDENT["DAYS_GOOD_FOR"]
        )
        verification_status_email_vars['expiry_date'] = expiry_date.strftime("%m/%d/%Y")
        verification_status_email_vars['full_name'] = user.profile.name
        subject = _("Your {platform_name} ID Verification Approved").format(
            platform_name=settings.PLATFORM_NAME
        )
        context = {
            'subject': subject,
            'template': 'emails/passed_verification_email.txt',
            'email': user.email,
            'email_vars': verification_status_email_vars
        }
        send_verification_status_email.delay(context)

    elif result == "FAIL":
        log.debug("Denying verification for %s", receipt_id)
        attempt.deny(json.dumps(reason), error_code=error_code)
        status = "denied"
        reverify_url = '{}{}'.format(settings.LMS_ROOT_URL, reverse("verify_student_reverify"))
        verification_status_email_vars['reasons'] = reason
        verification_status_email_vars['reverify_url'] = reverify_url
        verification_status_email_vars['faq_url'] = settings.ID_VERIFICATION_SUPPORT_LINK
        subject = _("Your {platform_name} Verification Has Been Denied").format(
            platform_name=settings.PLATFORM_NAME
        )
        context = {
            'subject': subject,
            'template': 'emails/failed_verification_email.txt',
            'email': user.email,
            'email_vars': verification_status_email_vars
        }
        send_verification_status_email.delay(context)

    elif result == "SYSTEM FAIL":
        log.debug("System failure for %s -- resetting to must_retry", receipt_id)
        attempt.system_error(json.dumps(reason), error_code=error_code)
        status = "error"
        log.error("Software Secure callback attempt for %s failed: %s", receipt_id, reason)
    else:
        log.error("Software Secure returned unknown result %s", result)
        return HttpResponseBadRequest(
            "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result)
        )

    return HttpResponse("OK!")
Exemplo n.º 4
0
def results_callback(request):
    """
    Software Secure will call this callback to tell us whether a user is
    verified to be who they said they are.
    """
    body = request.body

    try:
        body_dict = json.loads(body)
    except ValueError:
        log.exception("Invalid JSON received from Software Secure:\n\n{}\n".format(body))
        return HttpResponseBadRequest("Invalid JSON. Received:\n\n{}".format(body))

    if not isinstance(body_dict, dict):
        log.error("Reply from Software Secure is not a dict:\n\n{}\n".format(body))
        return HttpResponseBadRequest("JSON should be dict. Received:\n\n{}".format(body))

    headers = {
        "Authorization": request.META.get("HTTP_AUTHORIZATION", ""),
        "Date": request.META.get("HTTP_DATE", "")
    }

    has_valid_signature(
        "POST",
        headers,
        body_dict,
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"],
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"]
    )

    _response, access_key_and_sig = headers["Authorization"].split(" ")
    access_key = access_key_and_sig.split(":")[0]

    # This is what we should be doing...
    #if not sig_valid:
    #    return HttpResponseBadRequest("Signature is invalid")

    # This is what we're doing until we can figure out why we disagree on sigs
    if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"]:
        return HttpResponseBadRequest("Access key invalid")

    receipt_id = body_dict.get("EdX-ID")
    result = body_dict.get("Result")
    reason = body_dict.get("Reason", "")
    error_code = body_dict.get("MessageType", "")

    try:
        attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id)
    except SoftwareSecurePhotoVerification.DoesNotExist:
        log.error("Software Secure posted back for receipt_id %s, but not found", receipt_id)
        return HttpResponseBadRequest("edX ID {} not found".format(receipt_id))
    if result == "PASS":
        log.debug("Approving verification for %s", receipt_id)
        attempt.approve()
        status = "approved"

    elif result == "FAIL":
        log.debug("Denying verification for %s", receipt_id)
        attempt.deny(json.dumps(reason), error_code=error_code)
        status = "denied"
    elif result == "SYSTEM FAIL":
        log.debug("System failure for %s -- resetting to must_retry", receipt_id)
        attempt.system_error(json.dumps(reason), error_code=error_code)
        status = "error"
        log.error("Software Secure callback attempt for %s failed: %s", receipt_id, reason)
    else:
        log.error("Software Secure returned unknown result %s", result)
        return HttpResponseBadRequest(
            "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result)
        )

    return HttpResponse("OK!")
Exemplo n.º 5
0
def results_callback(request):
    """
    Software Secure will call this callback to tell us whether a user is
    verified to be who they said they are.
    """
    body = request.body

    try:
        body_dict = json.loads(body)
    except ValueError:
        log.exception("Invalid JSON received from Software Secure:\n\n{}\n".format(body))
        return HttpResponseBadRequest("Invalid JSON. Received:\n\n{}".format(body))

    if not isinstance(body_dict, dict):
        log.error("Reply from Software Secure is not a dict:\n\n{}\n".format(body))
        return HttpResponseBadRequest("JSON should be dict. Received:\n\n{}".format(body))

    headers = {
        "Authorization": request.META.get("HTTP_AUTHORIZATION", ""),
        "Date": request.META.get("HTTP_DATE", "")
    }

    has_valid_signature(
        "POST",
        headers,
        body_dict,
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"],
        settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"]
    )

    _response, access_key_and_sig = headers["Authorization"].split(" ")
    access_key = access_key_and_sig.split(":")[0]

    # This is what we should be doing...
    #if not sig_valid:
    #    return HttpResponseBadRequest("Signature is invalid")

    # This is what we're doing until we can figure out why we disagree on sigs
    if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"]:
        return HttpResponseBadRequest("Access key invalid")

    receipt_id = body_dict.get("EdX-ID")
    result = body_dict.get("Result")
    reason = body_dict.get("Reason", "")
    error_code = body_dict.get("MessageType", "")

    try:
        attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id)
    except SoftwareSecurePhotoVerification.DoesNotExist:
        log.error("Software Secure posted back for receipt_id %s, but not found", receipt_id)
        return HttpResponseBadRequest("edX ID {} not found".format(receipt_id))

    user = attempt.user
    verification_status_email_vars = {
        'platform_name': settings.PLATFORM_NAME,
    }
    if result == "PASS":
        log.debug("Approving verification for %s", receipt_id)
        attempt.approve()
        status = "approved"
        expiry_date = datetime.date.today() + datetime.timedelta(
            days=settings.VERIFY_STUDENT["DAYS_GOOD_FOR"]
        )
        verification_status_email_vars['expiry_date'] = expiry_date.strftime("%m/%d/%Y")
        verification_status_email_vars['full_name'] = user.profile.name
        subject = _("Your {platform_name} ID Verification Approved").format(
            platform_name=settings.PLATFORM_NAME
        )
        context = {
            'subject': subject,
            'template': 'emails/passed_verification_email.txt',
            'email': user.email,
            'email_vars': verification_status_email_vars
        }
        send_verification_status_email.delay(context)

    elif result == "FAIL":
        log.debug("Denying verification for %s", receipt_id)
        attempt.deny(json.dumps(reason), error_code=error_code)
        status = "denied"
        reverify_url = '{}{}'.format(settings.LMS_ROOT_URL, reverse("verify_student_reverify"))
        verification_status_email_vars['reasons'] = reason
        verification_status_email_vars['reverify_url'] = reverify_url
        verification_status_email_vars['faq_url'] = settings.ID_VERIFICATION_SUPPORT_LINK
        subject = _("Your {platform_name} Verification Has Been Denied").format(
            platform_name=settings.PLATFORM_NAME
        )
        context = {
            'subject': subject,
            'template': 'emails/failed_verification_email.txt',
            'email': user.email,
            'email_vars': verification_status_email_vars
        }
        send_verification_status_email.delay(context)

    elif result == "SYSTEM FAIL":
        log.debug("System failure for %s -- resetting to must_retry", receipt_id)
        attempt.system_error(json.dumps(reason), error_code=error_code)
        status = "error"
        log.error("Software Secure callback attempt for %s failed: %s", receipt_id, reason)
    else:
        log.error("Software Secure returned unknown result %s", result)
        return HttpResponseBadRequest(
            "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result)
        )

    return HttpResponse("OK!")