From 775ae010a23a1a94bc96ab0e4e62b787f3d2502e Mon Sep 17 00:00:00 2001
From: David Ormsbee <dave@edx.org>
Date: Tue, 20 Aug 2013 09:19:35 -0400
Subject: [PATCH] Shorted names of models in verify_student

---
 lms/djangoapps/verify_student/models.py       | 38 +++++++++++--------
 .../verify_student/tests/test_models.py       | 19 +++++-----
 lms/djangoapps/verify_student/urls.py         | 15 ++++++++
 lms/djangoapps/verify_student/views.py        | 22 ++++++++++-
 4 files changed, 68 insertions(+), 26 deletions(-)

diff --git a/lms/djangoapps/verify_student/models.py b/lms/djangoapps/verify_student/models.py
index 913d69f06b5..816f5da8d44 100644
--- a/lms/djangoapps/verify_student/models.py
+++ b/lms/djangoapps/verify_student/models.py
@@ -4,8 +4,8 @@ Models for Student Identity Verification
 
 This is where we put any models relating to establishing the real-life identity
 of a student over a period of time. Right now, the only models are the abstract
-`PhotoVerificationAttempt`, and its one concrete implementation
-`SoftwareSecurePhotoVerificationAttempt`. The hope is to keep as much of the
+`PhotoVerification`, and its one concrete implementation
+`SoftwareSecurePhotoVerification`. The hope is to keep as much of the
 photo verification process as generic as possible.
 """
 from datetime import datetime
@@ -63,14 +63,14 @@ def status_before_must_be(*valid_start_statuses):
     return decorator_func
 
 
-class PhotoVerificationAttempt(StatusModel):
+class PhotoVerification(StatusModel):
     """
-    Each PhotoVerificationAttempt represents a Student's attempt to establish
+    Each PhotoVerification represents a Student's attempt to establish
     their identity by uploading a photo of themselves and a picture ID. An
     attempt actually has a number of fields that need to be filled out at
     different steps of the approval process. While it's useful as a Django Model
     for the querying facilities, **you should only create and edit a
-    `PhotoVerificationAttempt` object through the methods provided**. Do not
+    `PhotoVerification` object through the methods provided**. Do not
     just construct one and start setting fields unless you really know what
     you're doing.
 
@@ -96,9 +96,9 @@ class PhotoVerificationAttempt(StatusModel):
 
     Because this Model inherits from StatusModel, we can also do things like::
 
-        attempt.status == PhotoVerificationAttempt.STATUS.created
+        attempt.status == PhotoVerification.STATUS.created
         attempt.status == "created"
-        pending_requests = PhotoVerificationAttempt.submitted.all()
+        pending_requests = PhotoVerification.submitted.all()
     """
     ######################## Fields Set During Creation ########################
     # See class docstring for description of status states
@@ -154,24 +154,33 @@ class PhotoVerificationAttempt(StatusModel):
 
     class Meta:
         abstract = True
+        ordering = ['-created_at']
 
     ##### Methods listed in the order you'd typically call them
     @classmethod
-    def user_is_verified(cls, user_id):
-        """Returns whether or not a user has satisfactorily proved their
+    def user_is_verified(cls, user):
+        """
+        Returns whether or not a user has satisfactorily proved their
         identity. Depending on the policy, this can expire after some period of
         time, so a user might have to renew periodically."""
         raise NotImplementedError
 
     @classmethod
-    def active_for_user(cls, user_id):
-        """Return all PhotoVerificationAttempts that are still active (i.e. not
+    def active_for_user(cls, user):
+        """
+        Return all PhotoVerifications that are still active (i.e. not
         approved or denied).
 
         Should there only be one active at any given time for a user? Enforced
         at the DB level?
         """
-        raise NotImplementedError
+        # This should only be one at the most, but just in case we create more
+        # by mistake, we'll grab the most recently created one.
+        active_attempts = cls.objects.filter(user=user, status='created')
+        if active_attempts:
+            return active_attempts[0]
+        else:
+            return None
 
     @status_before_must_be("created")
     def upload_face_image(self, img):
@@ -315,10 +324,10 @@ class PhotoVerificationAttempt(StatusModel):
         self.save()
 
 
-class SoftwareSecurePhotoVerificationAttempt(PhotoVerificationAttempt):
+class SoftwareSecurePhotoVerification(PhotoVerification):
     """
     Model to verify identity using a service provided by Software Secure. Much
-    of the logic is inherited from `PhotoVerificationAttempt`, but this class
+    of the logic is inherited from `PhotoVerification`, but this class
     encrypts the photos.
 
     Software Secure (http://www.softwaresecure.com/) is a remote proctoring
@@ -368,4 +377,3 @@ class SoftwareSecurePhotoVerificationAttempt(PhotoVerificationAttempt):
         )
         rsa_cipher = PKCS1_OAEP.new(key)
         rsa_encrypted_aes_key = rsa_cipher.encrypt(aes_key)
-
diff --git a/lms/djangoapps/verify_student/tests/test_models.py b/lms/djangoapps/verify_student/tests/test_models.py
index 2c80447d6cc..838da26fbad 100644
--- a/lms/djangoapps/verify_student/tests/test_models.py
+++ b/lms/djangoapps/verify_student/tests/test_models.py
@@ -1,12 +1,13 @@
-# -*- coding: utf-8 -*- 
-from nose.tools import assert_in, assert_is_none, assert_equals, \
-                       assert_raises, assert_not_equals
+# -*- coding: utf-8 -*-
+from nose.tools import (
+    assert_in, assert_is_none, assert_equals, assert_raises, assert_not_equals
+)
 from django.test import TestCase
 from student.tests.factories import UserFactory
-from verify_student.models import PhotoVerificationAttempt, VerificationException
+from verify_student.models import SoftwareSecurePhotoVerification, VerificationException
 
 
-class TestPhotoVerificationAttempt(object):
+class TestPhotoVerification(object):
 
     def test_state_transitions(self):
         """Make sure we can't make unexpected status transitions.
@@ -14,12 +15,12 @@ class TestPhotoVerificationAttempt(object):
         The status transitions we expect are::
 
             created → ready → submitted → approved
-                                            ↑ ↓ 
+                                            ↑ ↓
                                         →  denied
         """
         user = UserFactory.create()
-        attempt = PhotoVerificationAttempt(user=user)
-        assert_equals(attempt.status, PhotoVerificationAttempt.STATUS.created)
+        attempt = SoftwareSecurePhotoVerification(user=user)
+        assert_equals(attempt.status, SoftwareSecurePhotoVerification.STATUS.created)
         assert_equals(attempt.status, "created")
 
         # This should fail because we don't have the necessary fields filled out
@@ -38,7 +39,7 @@ class TestPhotoVerificationAttempt(object):
         assert_equals(attempt.status, "ready")
 
         # Once again, state transitions should fail here. We can't approve or
-        # deny anything until it's been placed into the submitted state -- i.e. 
+        # deny anything until it's been placed into the submitted state -- i.e.
         # the user has clicked on whatever agreements, or given payment, or done
         # whatever the application requires before it agrees to process their
         # attempt.
diff --git a/lms/djangoapps/verify_student/urls.py b/lms/djangoapps/verify_student/urls.py
index a3644615e8a..de085639701 100644
--- a/lms/djangoapps/verify_student/urls.py
+++ b/lms/djangoapps/verify_student/urls.py
@@ -25,4 +25,19 @@ urlpatterns = patterns(
         views.final_verification,
         name="verify_student/final_verification"
     ),
+
+    # The above are what we did for the design mockups, but what we're really
+    # looking at now is:
+    url(
+        r'^show_verification_page',
+        views.show_verification_page,
+        name="verify_student/show_verification_page"
+    ),
+
+    url(
+        r'^start_or_resume_attempt',
+        views.start_or_resume_attempt,
+        name="verify_student/start_or_resume_attempt"
+    )
+
 )
diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py
index acaafb092de..3da2dd3bbe4 100644
--- a/lms/djangoapps/verify_student/views.py
+++ b/lms/djangoapps/verify_student/views.py
@@ -4,14 +4,26 @@
 """
 from mitxmako.shortcuts import render_to_response
 
+from verify_student.models import SoftwareSecurePhotoVerification
+
 # @login_required
-def start_or_resume_attempt(request):
+def start_or_resume_attempt(request, course_id):
     """
     If they've already started a PhotoVerificationAttempt, we move to wherever
     they are in that process. If they've completed one, then we skip straight
     to payment.
     """
-    pass
+    # If the user has already been verified within the given time period,
+    # redirect straight to the payment -- no need to verify again.
+    #if SoftwareSecurePhotoVerification.user_is_verified(user):
+    #    pass
+
+    attempt = SoftwareSecurePhotoVerification.active_for_user(request.user)
+    if not attempt:
+        # Redirect to show requirements
+        pass
+
+    # if attempt.
 
 def show_requirements(request):
     """This might just be a plain template without a view."""
@@ -29,3 +41,9 @@ def photo_id_upload(request):
 def final_verification(request):
     context = { "course_id" : "edX/Certs101/2013_Test" }
     return render_to_response("verify_student/final_verification.html", context)
+
+#
+
+def show_verification_page(request):
+    pass
+
-- 
GitLab