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!")
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!")
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!")
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!")