145 lines
5.9 KiB
Python
145 lines
5.9 KiB
Python
from django.conf import settings as settings
|
|
|
|
from django.contrib.auth.models import User
|
|
from django.db import models
|
|
|
|
|
|
'''
|
|
Certificates are created for a student and an offering of a course.
|
|
|
|
When a certificate is generated, a unique ID is generated so that
|
|
the certificate can be verified later. The ID is a UUID4, so that
|
|
it can't be easily guessed and so that it is unique. Even though
|
|
we save these generated certificates (for later verification), we
|
|
also record the UUID so that if we regenerate the certificate it
|
|
will have the same UUID.
|
|
|
|
If certificates are being generated on the fly, a GeneratedCertificate
|
|
should be created with the user, certificate_id, and enabled set
|
|
when a student requests a certificate. When the certificate has been
|
|
generated, the download_url should be set.
|
|
|
|
Certificates can also be pre-generated. In this case, the user,
|
|
certificate_id, and download_url are all set before the user does
|
|
anything. When the user requests the certificate, only enabled
|
|
needs to be set to true.
|
|
|
|
'''
|
|
|
|
|
|
class GeneratedCertificate(models.Model):
|
|
user = models.ForeignKey(User, db_index=True)
|
|
# This is the name at the time of request
|
|
name = models.CharField(blank=True, max_length=255)
|
|
|
|
certificate_id = models.CharField(max_length=32, null=True, default=None)
|
|
graded_certificate_id = models.CharField(max_length=32, null=True, default=None)
|
|
|
|
download_url = models.CharField(max_length=128, null=True)
|
|
graded_download_url = models.CharField(max_length=128, null=True)
|
|
|
|
grade = models.CharField(max_length=5, null=True)
|
|
|
|
# enabled should only be true if the student has earned a grade in the course
|
|
# The student must have a grade and request a certificate for enabled to be True
|
|
enabled = models.BooleanField(default=False)
|
|
|
|
|
|
class RevokedCertificate(models.Model):
|
|
"""
|
|
This model is for when a GeneratedCertificate must be regenerated. This model
|
|
contains all the same fields, to store a record of what the GeneratedCertificate
|
|
was before it was revoked (at which time all of it's information can change when
|
|
it is regenerated).
|
|
|
|
GeneratedCertificate may be deleted once they are revoked, and then created again.
|
|
For this reason, the only link between a GeneratedCertificate and RevokedCertificate
|
|
is that they share the same user.
|
|
"""
|
|
####-------------------New Fields--------------------####
|
|
explanation = models.TextField(blank=True)
|
|
|
|
####---------Fields from GeneratedCertificate---------####
|
|
user = models.ForeignKey(User, db_index=True)
|
|
# This is the name at the time of request
|
|
name = models.CharField(blank=True, max_length=255)
|
|
|
|
certificate_id = models.CharField(max_length=32, null=True, default=None)
|
|
graded_certificate_id = models.CharField(max_length=32, null=True, default=None)
|
|
|
|
download_url = models.CharField(max_length=128, null=True)
|
|
graded_download_url = models.CharField(max_length=128, null=True)
|
|
|
|
grade = models.CharField(max_length=5, null=True)
|
|
|
|
enabled = models.BooleanField(default=False)
|
|
|
|
|
|
def revoke_certificate(certificate, explanation):
|
|
"""
|
|
This method takes a GeneratedCertificate. It records its information from the certificate
|
|
into a RevokedCertificate, and then marks the certificate as needing regenerating.
|
|
When the new certificiate is regenerated it will have new IDs and download URLS.
|
|
|
|
Once this method has been called, it is safe to delete the certificate, or modify the
|
|
certificate's name or grade until it has been generated again.
|
|
"""
|
|
revoked = RevokedCertificate(user=certificate.user,
|
|
name=certificate.name,
|
|
certificate_id=certificate.certificate_id,
|
|
graded_certificate_id=certificate.graded_certificate_id,
|
|
download_url=certificate.download_url,
|
|
graded_download_url=certificate.graded_download_url,
|
|
grade=certificate.grade,
|
|
enabled=certificate.enabled)
|
|
|
|
revoked.explanation = explanation
|
|
|
|
certificate.certificate_id = None
|
|
certificate.graded_certificate_id = None
|
|
certificate.download_url = None
|
|
certificate.graded_download_url = None
|
|
|
|
certificate.save()
|
|
revoked.save()
|
|
|
|
|
|
def certificate_state_for_student(student, grade):
|
|
'''
|
|
This returns a dictionary with a key for state, and other information. The state is one of the
|
|
following:
|
|
|
|
unavailable - A student is not eligible for a certificate.
|
|
requestable - A student is eligible to request a certificate
|
|
generating - A student has requested a certificate, but it is not generated yet.
|
|
downloadable - The certificate has been requested and is available for download.
|
|
|
|
If the state is "downloadable", the dictionary also contains "download_url" and "graded_download_url".
|
|
|
|
'''
|
|
|
|
if grade:
|
|
#TODO: Remove the following after debugging
|
|
if settings.DEBUG_SURVEY:
|
|
return {'state': 'requestable'}
|
|
|
|
try:
|
|
generated_certificate = GeneratedCertificate.objects.get(user=student)
|
|
if generated_certificate.enabled:
|
|
if generated_certificate.download_url:
|
|
return {'state': 'downloadable',
|
|
'download_url': generated_certificate.download_url,
|
|
'graded_download_url': generated_certificate.graded_download_url}
|
|
else:
|
|
return {'state': 'generating'}
|
|
else:
|
|
# If enabled=False, it may have been pre-generated but not yet requested
|
|
# Our output will be the same as if the GeneratedCertificate did not exist
|
|
pass
|
|
except GeneratedCertificate.DoesNotExist:
|
|
pass
|
|
return {'state': 'requestable'}
|
|
else:
|
|
# No grade, no certificate. No exceptions
|
|
return {'state': 'unavailable'}
|