def get(self, request, course_id, checkpoint_name, usage_id): """ Display the view for face photo submission""" # Check the in-course re-verification is enabled or not incourse_reverify_enabled = InCourseReverificationConfiguration.current().enabled if not incourse_reverify_enabled: raise Http404 user = request.user course_key = CourseKey.from_string(course_id) course = modulestore().get_course(course_key) if course is None: raise Http404 checkpoint = VerificationCheckpoint.get_verification_checkpoint(course_key, checkpoint_name) if checkpoint is None: raise Http404 init_verification = SoftwareSecurePhotoVerification.get_initial_verification(user) if not init_verification: return redirect(reverse('verify_student_verify_later', kwargs={'course_id': unicode(course_key)})) # emit the reverification event self._track_reverification_events( EVENT_NAME_USER_ENTERED_INCOURSE_REVERIFY_VIEW, user.id, course_id, checkpoint_name ) context = { 'course_key': unicode(course_key), 'course_name': course.display_name_with_default, 'checkpoint_name': checkpoint_name, 'platform_name': settings.PLATFORM_NAME, 'usage_id': usage_id } return render_to_response("verify_student/incourse_reverify.html", context)
def get(self, request, course_id, checkpoint_name): """ Display the view for face photo submission""" # Check the in-course re-verification is enabled or not incourse_reverify_enabled = InCourseReverificationConfiguration.current().enabled if not incourse_reverify_enabled: raise Http404 user = request.user course_key = CourseKey.from_string(course_id) course = modulestore().get_course(course_key) if course is None: raise Http404 checkpoint = VerificationCheckpoint.get_verification_checkpoint(course_key, checkpoint_name) if checkpoint is None: raise Http404 init_verification = SoftwareSecurePhotoVerification.get_initial_verification(user) if not init_verification: return redirect(reverse('verify_student_verify_later', kwargs={'course_id': unicode(course_key)})) # emit the reverification event self._track_reverification_events( EVENT_NAME_USER_ENTERED_INCOURSE_REVERIFY_VIEW, user.id, course_id, checkpoint_name ) context = { 'course_key': unicode(course_key), 'course_name': course.display_name_with_default, 'checkpoint_name': checkpoint_name, 'platform_name': settings.PLATFORM_NAME, } return render_to_response("verify_student/incourse_reverify.html", context)
def post(self, request, course_id, checkpoint_name): """Submits the re-verification attempt to SoftwareSecure Args: request(HttpRequest): HttpRequest object course_id(str): Course Id checkpoint_name(str): Checkpoint name Returns: HttpResponse with status_code 400 if photo is missing or any error or redirect to verify_student_verify_later url if initial verification doesn't exist otherwise HttpsResponse with status code 200 """ # Check the in-course re-verification is enabled or not incourse_reverify_enabled = InCourseReverificationConfiguration.current().enabled if not incourse_reverify_enabled: raise Http404 user = request.user course_key = CourseKey.from_string(course_id) course = modulestore().get_course(course_key) checkpoint = VerificationCheckpoint.get_verification_checkpoint(course_key, checkpoint_name) if checkpoint is None: log.error("Checkpoint is not defined. Could not submit verification attempt for user %s", request.user.id) context = { 'course_key': unicode(course_key), 'course_name': course.display_name_with_default, 'checkpoint_name': checkpoint_name, 'error': True, 'errorMsg': _("No checkpoint found"), 'platform_name': settings.PLATFORM_NAME, } return render_to_response("verify_student/incourse_reverify.html", context) init_verification = SoftwareSecurePhotoVerification.get_initial_verification(user) if not init_verification: log.error("Could not submit verification attempt for user %s", request.user.id) return redirect(reverse('verify_student_verify_later', kwargs={'course_id': unicode(course_key)})) try: attempt = SoftwareSecurePhotoVerification.submit_faceimage( request.user, request.POST['face_image'], init_verification.photo_id_key ) checkpoint.add_verification_attempt(attempt) VerificationStatus.add_verification_status(checkpoint, user, "submitted") # emit the reverification event self._track_reverification_events( EVENT_NAME_USER_SUBMITTED_INCOURSE_REVERIFY, user.id, course_id, checkpoint_name ) return HttpResponse() except IndexError: log.exception("Invalid image data during photo verification.") return HttpResponseBadRequest(_("Invalid image data during photo verification.")) except Exception: # pylint: disable=broad-except log.exception("Could not submit verification attempt for user {}.").format(request.user.id) msg = _("Could not submit photos") return HttpResponseBadRequest(msg)
def get(self, request, course_id, usage_id): """Display the view for face photo submission. Args: request(HttpRequest): HttpRequest object course_id(str): A string of course id usage_id(str): Location of Reverification XBlock in courseware Returns: HttpResponse """ # Check that in-course re-verification is enabled or not incourse_reverify_enabled = InCourseReverificationConfiguration.current().enabled if not incourse_reverify_enabled: log.error( u"In-course reverification is not enabled. " u"You can enable it in Django admin by setting " u"InCourseReverificationConfiguration to enabled." ) raise Http404 user = request.user course_key = CourseKey.from_string(course_id) course = modulestore().get_course(course_key) if course is None: log.error(u"Could not find course '%s' for in-course reverification.", course_key) raise Http404 checkpoint = VerificationCheckpoint.get_verification_checkpoint(course_key, usage_id) if checkpoint is None: log.error( u"No verification checkpoint exists for the " u"course '%s' and checkpoint location '%s'.", course_key, usage_id ) raise Http404 initial_verification = SoftwareSecurePhotoVerification.get_initial_verification(user) if not initial_verification: return self._redirect_no_initial_verification(user, course_key) # emit the reverification event self._track_reverification_events( EVENT_NAME_USER_ENTERED_INCOURSE_REVERIFY_VIEW, user.id, course_id, checkpoint.checkpoint_name ) context = { 'course_key': unicode(course_key), 'course_name': course.display_name_with_default, 'checkpoint_name': checkpoint.checkpoint_name, 'platform_name': settings.PLATFORM_NAME, 'usage_id': usage_id, 'capture_sound': staticfiles_storage.url("audio/camera_capture.wav"), } return render_to_response("verify_student/incourse_reverify.html", context)
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" _set_user_requirement_status(attempt, 'reverification', 'satisfied') elif result == "FAIL": log.debug("Denying verification for %s", receipt_id) attempt.deny(json.dumps(reason), error_code=error_code) status = "denied" _set_user_requirement_status( attempt, 'reverification', 'failed', json.dumps(reason) ) 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) ) incourse_reverify_enabled = InCourseReverificationConfiguration.current().enabled if incourse_reverify_enabled: checkpoints = VerificationCheckpoint.objects.filter(photo_verification=attempt).all() VerificationStatus.add_status_from_checkpoints(checkpoints=checkpoints, user=attempt.user, status=status) # If this is re-verification then send the update email if checkpoints: user_id = attempt.user.id course_key = checkpoints[0].course_id related_assessment_location = checkpoints[0].checkpoint_location subject, message = _compose_message_reverification_email( course_key, user_id, related_assessment_location, status, request ) _send_email(user_id, subject, message) return HttpResponse("OK!")
def post(self, request, course_id, usage_id): """Submits the re-verification attempt to SoftwareSecure. Args: request(HttpRequest): HttpRequest object course_id(str): Course Id usage_id(str): Location of Reverification XBlock in courseware Returns: HttpResponse with status_code 400 if photo is missing or any error or redirect to the verification flow if initial verification doesn't exist otherwise HttpResponse with status code 200 """ # Check the in-course re-verification is enabled or not incourse_reverify_enabled = InCourseReverificationConfiguration.current().enabled if not incourse_reverify_enabled: raise Http404 user = request.user try: course_key = CourseKey.from_string(course_id) usage_key = UsageKey.from_string(usage_id).replace(course_key=course_key) except InvalidKeyError: raise Http404(u"Invalid course_key or usage_key") course = modulestore().get_course(course_key) if course is None: log.error(u"Invalid course id '%s'", course_id) return HttpResponseBadRequest(_("Invalid course location.")) checkpoint = VerificationCheckpoint.get_verification_checkpoint(course_key, usage_id) if checkpoint is None: log.error( u"Checkpoint is not defined. Could not submit verification attempt" u" for user '%s', course '%s' and checkpoint location '%s'.", request.user.id, course_key, usage_id ) return HttpResponseBadRequest(_("Invalid checkpoint location.")) init_verification = SoftwareSecurePhotoVerification.get_initial_verification(user) if not init_verification: return self._redirect_no_initial_verification(user, course_key) try: attempt = SoftwareSecurePhotoVerification.submit_faceimage( request.user, request.POST['face_image'], init_verification.photo_id_key ) checkpoint.add_verification_attempt(attempt) VerificationStatus.add_verification_status(checkpoint, user, "submitted") # emit the reverification event self._track_reverification_events( 'edx.bi.reverify.submitted', user.id, course_id, checkpoint.checkpoint_name ) redirect_url = get_redirect_url(course_key, usage_key) response = JsonResponse({'url': redirect_url}) except (ItemNotFoundError, NoPathToItem): log.warning(u"Could not find redirect URL for location %s in course %s", course_key, usage_key) redirect_url = reverse("courseware", args=(unicode(course_key),)) response = JsonResponse({'url': redirect_url}) except Http404 as expt: log.exception("Invalid location during photo verification.") response = HttpResponseBadRequest(expt.message) except IndexError: log.exception("Invalid image data during photo verification.") response = HttpResponseBadRequest(_("Invalid image data during photo verification.")) except Exception: # pylint: disable=broad-except log.exception("Could not submit verification attempt for user %s.", request.user.id) msg = _("Could not submit photos") response = HttpResponseBadRequest(msg) return response