From 5c26c92fe6e7584265daef3b10f7d744fdc7e38d Mon Sep 17 00:00:00 2001 From: charliemirabile <46761267+charliemirabile@users.noreply.github.com> Date: Thu, 19 Sep 2024 12:08:03 -0400 Subject: [PATCH 1/2] mailman: avoid hard coded list of assignments giving mailman access to the denis db allows querying the real list of assignments to determine whether or not a patch is addressed to one of the special mailboxes. --- container-compose.yml | 6 ++++++ mailman/Containerfile | 1 + mailman/submit.py | 9 +++------ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/container-compose.yml b/container-compose.yml index cb3aeda8..deaa10e2 100644 --- a/container-compose.yml +++ b/container-compose.yml @@ -124,6 +124,7 @@ services: dockerfile: Containerfile additional_contexts: - watcher_source=./watcher + - denis_source=./denis volumes: - type: volume source: email-mail @@ -133,12 +134,17 @@ services: source: email-logs target: /var/lib/email/logs read_only: true + - type: volume + source: denis-db + target: /var/lib/denis + read_only: true - type: volume source: submissions-db target: /var/lib/mailman read_only: false depends_on: - smtp + - denis networks: - mailman denis: diff --git a/mailman/Containerfile b/mailman/Containerfile index 55a1b422..9ea8f87d 100644 --- a/mailman/Containerfile +++ b/mailman/Containerfile @@ -27,6 +27,7 @@ RUN mkdir -p /var/lib/mailman/ && \ RUN chown -R 100:100 /var/lib/mailman COPY --from=build /watcher/watcher /usr/local/bin/watcher +COPY --from=denis_source . ./denis VOLUME /var/lib/email/ diff --git a/mailman/submit.py b/mailman/submit.py index 9f3fffb6..023a9831 100755 --- a/mailman/submit.py +++ b/mailman/submit.py @@ -6,11 +6,7 @@ import patchset import db - -ASSIGNMENT_LIST = ["introductions", - "exercise0", "exercise1", "exercise2", - "programming0", "programming1", "programming2", - "final0", "final1"] +import denis.db Email = collections.namedtuple('Email', ['rcpt', 'msg_id']) @@ -40,7 +36,8 @@ def main(argv): # if the 'cover letter' is not addressed to # an assignment inbox, this email session # isn't a patchset at all - if cover_letter.rcpt not in ASSIGNMENT_LIST: + asn_db = denis.db.Assignment + if not asn_db.get_or_none(asn_db.name == cover_letter.rcpt): # TODO process peer review return 0 From ad1a2377917bd0dbe988f4f39e1d1db3565b594d Mon Sep 17 00:00:00 2001 From: charliemirabile <46761267+charliemirabile@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:14:20 -0400 Subject: [PATCH 2/2] mailman: unify all submissions under common table for dashboard Remove special processing for assignments and just store peer reviews alongside submissions so that students can see all activity as it occurs and know that their submission as being counted. --- mailman/db.py | 5 +++-- mailman/submit.py | 54 ++++++++++++++++++----------------------------- orbit/radius.py | 5 +++-- 3 files changed, 26 insertions(+), 38 deletions(-) diff --git a/mailman/db.py b/mailman/db.py index 8c6a4f16..8e80a745 100755 --- a/mailman/db.py +++ b/mailman/db.py @@ -13,10 +13,11 @@ class Meta: class Submission(BaseModel): submission_id = peewee.TextField(unique=True) - assignment = peewee.TextField() timestamp = peewee.IntegerField() user = peewee.TextField() - status = peewee.TextField() + recipient = peewee.TextField() + email_count = peewee.IntegerField() + in_reply_to = peewee.TextField(null=True) if __name__ == '__main__': diff --git a/mailman/submit.py b/mailman/submit.py index 023a9831..e031633f 100755 --- a/mailman/submit.py +++ b/mailman/submit.py @@ -4,9 +4,7 @@ from pathlib import Path import sys -import patchset import db -import denis.db Email = collections.namedtuple('Email', ['rcpt', 'msg_id']) @@ -31,38 +29,26 @@ def main(argv): if not emails: return 0 - cover_letter, *patches = emails - - # if the 'cover letter' is not addressed to - # an assignment inbox, this email session - # isn't a patchset at all - asn_db = denis.db.Assignment - if not asn_db.get_or_none(asn_db.name == cover_letter.rcpt): - # TODO process peer review - return 0 - - sub = db.Submission(submission_id=logfile, assignment=cover_letter.rcpt, - timestamp=timestamp, user=user, status='new') - - # only one email - if not patches: - # only one patch, but addressed to an - # assignment inbox. This cannot be valid. - sub.status = 'no patches or no cover letter' - sub.save() - return 0 - - mis_addressed_patches = [str(i+1) for i, patch in enumerate(patches) - if patch.rcpt != cover_letter.rcpt] - - if mis_addressed_patches: - sub.status = (f'patch(es) {",".join(mis_addressed_patches)} ' - f'not addressed to {cover_letter.rcpt}') - sub.save() - return 0 - - sub.status = patchset.check(cover_letter, patches, submission_id=logfile) - sub.save() + irt_header = 'In-Reply-To: <' + reply_id = None + with open(f'/var/lib/email/mail/{emails[0].msg_id}') as f: + for line in f: + if not line: + break + if not line.startswith(irt_header): + continue + at_sign = line.find('@', len(irt_header)) + if -1 == at_sign: + continue + reply_email_id = line[len(irt_header):at_sign] + + # "clear the lower 16 bits" to get the reviewee patchset id + reply_id = reply_email_id[:-4] + '0000' + break + + db.Submission.create(submission_id=logfile, timestamp=timestamp, + user=user, recipient=emails[0].rcpt, + email_count=len(emails), in_reply_to=reply_id) if __name__ == "__main__": diff --git a/orbit/radius.py b/orbit/radius.py index 5985cd7f..84204431 100644 --- a/orbit/radius.py +++ b/orbit/radius.py @@ -389,7 +389,8 @@ def handle_dashboard(rocket): def submission_fields(sub): return (datetime.fromtimestamp(sub.timestamp).isoformat(), - sub.assignment, sub.submission_id, sub.status) + sub.recipient, sub.email_count, sub.in_reply_to or '-', + sub.submission_id, ) # Split data from Submission table into values for HTML table table_data = [[f'{val}' for val in submission_fields(sub)] @@ -397,7 +398,7 @@ def submission_fields(sub): table_content = '\n'.join(''.join(row) for row in table_data) return rocket.respond(f""" - +{table_content}
TimestampAssignmentSubmission IDStatus
TimestampRecipientEmail CountIn Reply ToSubmission ID
""")