Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Add PII annotations #273

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions submissions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
need to then generate a matching migration for it using:

./manage.py makemigrations submissions

"""

import logging
Expand All @@ -34,7 +33,9 @@


class AnonymizedUserIDField(models.CharField):
""" Field for storing anonymized user ids. """
"""
Field for storing anonymized user ids.
"""
description = "The anonymized User ID that the XBlock sees"

def __init__(self, *args, **kwargs):
Expand All @@ -50,11 +51,13 @@ def deconstruct(self):


class StudentItem(models.Model):
"""Represents a single item for a single course for a single user.
"""
Represents a single item for a single course for a single user.

This is typically an XBlock problem, but could be something more generic
like class participation.

.. no_pii:
"""
# The anonymized Student ID that the XBlock sees, not their real ID.
student_id = AnonymizedUserIDField()
Expand Down Expand Up @@ -111,6 +114,8 @@ class TeamSubmission(TimeStampedModel):
An abstraction layer over Submission used to for teams. Since we create a submission record for every team member,
there is a need to have a single point to connect the team to the workflows.
TeamSubmission is a 1 to many with Submission

.. no_pii:
"""

uuid = models.UUIDField(db_index=True, default=uuid4, null=False)
Expand Down Expand Up @@ -287,14 +292,16 @@ def validate_only_one_submission_per_team(sender, **kwargs): # pylint:disable=u


class Submission(models.Model):
"""A single response by a student for a given problem in a given course.
"""
A single response by a student for a given problem in a given course.

A student may have multiple submissions for the same problem. Submissions
should never be mutated. If the student makes another Submission, or if we
have to make corrective Submissions to fix bugs, those should be new
objects. We want to keep Submissions immutable both for audit purposes, and
because it makes caching trivial.

.. no_pii:
"""
MAXSIZE = 1024*100 # 100KB

Expand Down Expand Up @@ -363,12 +370,15 @@ class Meta:


class Score(models.Model):
"""What the user scored for a given StudentItem at a given time.
"""
What the user scored for a given StudentItem at a given time.

Note that while a Score *can* be tied to a Submission, it doesn't *have* to.
Specifically, if we want to have scores for things that are not a part of
the courseware (like "class participation"), there would be no corresponding
Submission.

.. no_pii:
"""
student_item = models.ForeignKey(StudentItem, on_delete=models.CASCADE)
submission = models.ForeignKey(Submission, null=True, on_delete=models.CASCADE)
Expand Down Expand Up @@ -449,7 +459,6 @@ def create_reset_score(cls, student_item):

Raises:
DatabaseError: An error occurred while creating the score

"""
# By setting the "reset" flag, we ensure that the "highest"
# score in the score summary will point to this score.
Expand All @@ -468,7 +477,11 @@ def __str__(self):


class ScoreSummary(models.Model):
"""Running store of the highest and most recent Scores for a StudentItem."""
"""
Running store of the highest and most recent Scores for a StudentItem.

.. no_pii:
"""
student_item = models.OneToOneField(StudentItem, on_delete=models.CASCADE)

highest = models.ForeignKey(Score, related_name="+", on_delete=models.CASCADE)
Expand All @@ -488,7 +501,6 @@ def update_score_summary(sender, **kwargs): # pylint: disable=no-self-argument

Kwargs:
instance (Score): The score model whose save triggered this receiver.

"""
score = kwargs['instance']
try:
Expand Down Expand Up @@ -529,7 +541,11 @@ def update_score_summary(sender, **kwargs): # pylint: disable=no-self-argument


class ScoreAnnotation(models.Model):
""" Annotate individual scores with extra information if necessary. """
"""
Annotate individual scores with extra information if necessary.

.. no_pii:
"""

class Meta:
app_label = "submissions"
Expand Down