1. Constraint in class CertificateInvalidation
generated_certificate should be unique in the model CertificateInvalidation, as one certificate should not be invalidated twice. This would cause exceptions in the program which hurts the data integrity. We can add unique=True to prevent that.
In file lms/djangoapps/certificates/models.py
class CertificateInvalidation(TimeStampedModel):
"""
Model for storing Certificate Invalidation.
.. no_pii:
"""
generated_certificate = models.ForeignKey(GeneratedCertificate, on_delete=models.CASCADE)
invalidated_by = models.ForeignKey(User, on_delete=models.CASCADE)
2. Constraint in class BadgeAssertion
Each user should only have one completion badge. We can add this data constraint with
unique_together=('user', 'badge_class') to avoid invalid data to get in the database.
# Usage in lms/djangoapps/badges/events/course_complete.py
if BadgeAssertion.objects.filter(user=user, badge_class=badge_class):
LOGGER.info("Completion badge already exists for this user on this course.")
# definition in lms/djangoapps/badges/models.py
class BadgeAssertion(TimeStampedModel):
"""
Tracks badges on our side of the badge baking transaction
.. no_pii:
"""
user = models.ForeignKey(User, on_delete=models.CASCADE)
badge_class = models.ForeignKey(BadgeClass, on_delete=models.CASCADE)
3. Constraint in class LoginFailures
Similar issue, user field should be unique for the LoginFailures, this would prevent duplicate entries for the same user, due to potential race conditions of get_or_create() in the first place.
class LoginFailures(models.Model):
"""
This model will keep track of failed login attempts.
.. no_pii:
"""
user = models.ForeignKey(User, on_delete=models.CASCADE)
failure_count = models.IntegerField(default=0)
lockout_until = models.DateTimeField(null=True)
I can work on the PR for this issue if needed, please let me know your thoughts. Thanks!