Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
775ae010
Commit
775ae010
authored
Aug 20, 2013
by
David Ormsbee
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Shorted names of models in verify_student
parent
8f572e53
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
68 additions
and
26 deletions
+68
-26
lms/djangoapps/verify_student/models.py
+23
-15
lms/djangoapps/verify_student/tests/test_models.py
+10
-9
lms/djangoapps/verify_student/urls.py
+15
-0
lms/djangoapps/verify_student/views.py
+20
-2
No files found.
lms/djangoapps/verify_student/models.py
View file @
775ae010
...
...
@@ -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
`PhotoVerification
Attempt
`, and its one concrete implementation
`SoftwareSecurePhotoVerification
Attempt
`. 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
PhotoVerification
Attempt
(
StatusModel
):
class
PhotoVerification
(
StatusModel
):
"""
Each PhotoVerification
Attempt
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
`PhotoVerification
Attempt
` 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 == PhotoVerification
Attempt
.STATUS.created
attempt.status == PhotoVerification.STATUS.created
attempt.status == "created"
pending_requests = PhotoVerification
Attempt
.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
SoftwareSecurePhotoVerification
Attempt
(
PhotoVerificationAttempt
):
class
SoftwareSecurePhotoVerification
(
PhotoVerification
):
"""
Model to verify identity using a service provided by Software Secure. Much
of the logic is inherited from `PhotoVerification
Attempt
`, 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
)
lms/djangoapps/verify_student/tests/test_models.py
View file @
775ae010
# -*- 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
TestPhotoVerification
Attempt
(
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.
...
...
lms/djangoapps/verify_student/urls.py
View file @
775ae010
...
...
@@ -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"
)
)
lms/djangoapps/verify_student/views.py
View file @
775ae010
...
...
@@ -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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment