Shorted names of models in verify_student
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user