From 4f156dc08f7b3a18bbb5d3d045ad7436c0246df9 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Fri, 8 May 2015 09:08:34 -0400 Subject: [PATCH] Updates to the verify student Django admin. * Ensure that VerificationStatus is append-only and immutable. * Allow searching by student for verification status. * Properly pluralize verification status. * Use ConfigModelAdmin for ICRV config model admin. --- lms/djangoapps/verify_student/admin.py | 41 +++++++++++++++++++++---- lms/djangoapps/verify_student/models.py | 9 ++++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/lms/djangoapps/verify_student/admin.py b/lms/djangoapps/verify_student/admin.py index 56e5bd3a90..a9a26d3bdf 100644 --- a/lms/djangoapps/verify_student/admin.py +++ b/lms/djangoapps/verify_student/admin.py @@ -1,8 +1,10 @@ from ratelimitbackend import admin +from config_models.admin import ConfigurationModelAdmin from verify_student.models import ( SoftwareSecurePhotoVerification, InCourseReverificationConfiguration, - VerificationStatus + VerificationStatus, + SkippedReverification, ) @@ -20,12 +22,39 @@ class VerificationStatusAdmin(admin.ModelAdmin): """ Admin for the VerificationStatus table. """ - list_display = ('id', 'user', 'status', 'checkpoint', 'location_id') - search_fields = ( - 'checkpoint', - ) + list_display = ('timestamp', 'user', 'status', 'checkpoint', 'location_id') + readonly_fields = () + search_fields = ('checkpoint', 'user') + + def get_readonly_fields(self, request, obj=None): + """When editing an existing record, all fields should be read-only. + + VerificationStatus records should be immutable; to change the user's + status, create a new record with the updated status and a more + recent timestamp. + + """ + if obj: + return self.readonly_fields + ('status', 'checkpoint', 'user', 'location_id', 'response', 'error') + return self.readonly_fields + + def has_delete_permission(self, request, obj=None): + """The verification status table is append-only. """ + return False + + +class SkippedReverificationAdmin(admin.ModelAdmin): + """Admin for the SkippedReverification table. """ + list_display = ('created_at', 'user', 'course_id', 'checkpoint') + readonly_fields = ('user', 'course_id') + search_fields = ('user', 'course_id', 'checkpoint') + + def has_add_permission(self, request): + """Skipped verifications can't be created in Django admin. """ + return False admin.site.register(SoftwareSecurePhotoVerification, SoftwareSecurePhotoVerificationAdmin) -admin.site.register(InCourseReverificationConfiguration) +admin.site.register(InCourseReverificationConfiguration, ConfigurationModelAdmin) +admin.site.register(SkippedReverification, SkippedReverificationAdmin) admin.site.register(VerificationStatus, VerificationStatusAdmin) diff --git a/lms/djangoapps/verify_student/models.py b/lms/djangoapps/verify_student/models.py index da8476cf57..e9a7f5a1c1 100644 --- a/lms/djangoapps/verify_student/models.py +++ b/lms/djangoapps/verify_student/models.py @@ -974,6 +974,13 @@ class VerificationCheckpoint(models.Model): class Meta: # pylint: disable=missing-docstring, old-style-class unique_together = (('course_id', 'checkpoint_name'),) + def __unicode__(self): + """Unicode representation of the checkpoint. """ + return u"{checkpoint} in {course}".format( + checkpoint=self.checkpoint_name, + course=self.course_id + ) + def add_verification_attempt(self, verification_attempt): """ Add the verification attempt in M2M relation of photo_verification @@ -1047,6 +1054,8 @@ class VerificationStatus(models.Model): class Meta(object): # pylint: disable=missing-docstring get_latest_by = "timestamp" + verbose_name = "Verification Status" + verbose_name_plural = "Verification Statuses" @classmethod def add_verification_status(cls, checkpoint, user, status, location_id=None):