def _compose_message_reverification_email( course_key, user_id, related_assessment_location, status, request ): # pylint: disable=invalid-name """ Compose subject and message for photo reverification email. Args: course_key(CourseKey): CourseKey object user_id(str): User Id related_assessment_location(str): Location of reverification XBlock photo_verification(QuerySet): Queryset of SoftwareSecure objects status(str): Approval status is_secure(Bool): Is running on secure protocol or not Returns: None if any error occurred else Tuple of subject and message strings """ try: usage_key = UsageKey.from_string(related_assessment_location) reverification_block = modulestore().get_item(usage_key) course = modulestore().get_course(course_key) redirect_url = get_redirect_url(course_key, usage_key.replace(course_key=course_key)) subject = "Re-verification Status" context = { "status": status, "course_name": course.display_name_with_default, "assessment": reverification_block.related_assessment } # Allowed attempts is 1 if not set on verification block allowed_attempts = reverification_block.attempts + 1 used_attempts = VerificationStatus.get_user_attempts(user_id, course_key, related_assessment_location) left_attempts = allowed_attempts - used_attempts is_attempt_allowed = left_attempts > 0 verification_open = True if reverification_block.due: verification_open = timezone.now() <= reverification_block.due context["left_attempts"] = left_attempts context["is_attempt_allowed"] = is_attempt_allowed context["verification_open"] = verification_open context["due_date"] = get_default_time_display(reverification_block.due) context['platform_name'] = settings.PLATFORM_NAME context["used_attempts"] = used_attempts context["allowed_attempts"] = allowed_attempts context["support_link"] = microsite.get_value('email_from_address', settings.CONTACT_EMAIL) re_verification_link = reverse( 'verify_student_incourse_reverify', args=( unicode(course_key), related_assessment_location ) ) context["course_link"] = request.build_absolute_uri(redirect_url) context["reverify_link"] = request.build_absolute_uri(re_verification_link) message = render_to_string('emails/reverification_processed.txt', context) log.info( "Sending email to User_Id=%s. Attempts left for this user are %s. " "Allowed attempts %s. " "Due Date %s", str(user_id), left_attempts, allowed_attempts, str(reverification_block.due) ) return subject, message # Catch all exception to avoid raising back to view except: # pylint: disable=bare-except log.exception("The email for re-verification sending failed for user_id %s", user_id)
def post(self, request, course_id, checkpoint_name, usage_id): """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 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) 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, 'usage_id': usage_id } 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 ) try: redirect_url = get_redirect_url(course_key, usage_key) except (ItemNotFoundError, NoPathToItem): redirect_url = reverse("courseware", args=(unicode(course_key),)) return JsonResponse({'url': redirect_url}) except Http404 as expt: log.exception("Invalid location during photo verification.") return HttpResponseBadRequest(expt.message) 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 %s.", request.user.id) msg = _("Could not submit photos") return HttpResponseBadRequest(msg)
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