Fix/file attachment report auth#1106
Conversation
- Replace broken per-answer/assignment require loop with a proper
bouncer rule (if_can_read_attachment) that grants access if the user
can read any linked assignment or answer, or uploaded the file
- Add authorization gate for report file type (was a TODO)
- Activate previously-skipped unauthorized access test
Greptile SummaryThis PR fixes two authorization gaps: report file downloads were previously unprotected (noted as a TODO), and attachment authorization was refactored from a broken "require-on-every-linked-object" loop to a proper Bouncer rule. It also fixes a bug in
Confidence Score: 5/5The PR closes two real authorization gaps and contains a targeted bug fix; all changed code paths are straightforward and well-tested. The attachment auth refactor moves to a correct Bouncer predicate, the report auth embeds an unforgeable course UUID in the filename and validates role membership server-side, and the comparison-criterion fix corrects an inadvertent no-op add. Tests cover the key allow/deny scenarios for both file types. No incorrect data handling or broken auth paths were found. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant FileRetrieve as file_retrieve()
participant Bouncer as Bouncer (authorization.py)
participant DB as Database
Client->>FileRetrieve: "GET /app/attachment/<file_name>"
FileRetrieve->>DB: File.get_by_file_name_or_404(file_name)
DB-->>FileRetrieve: attachment (File)
FileRetrieve->>Bouncer: require(READ, attachment)
Bouncer->>DB: file.assignments.all() / file.answers.all()
DB-->>Bouncer: "linked assignments & answers"
Bouncer-->>FileRetrieve: allowed / Forbidden
FileRetrieve-->>Client: file stream or 403
Client->>FileRetrieve: "GET /app/report/<file_name>"
FileRetrieve->>FileRetrieve: "extract UUID via regex(--{22chars}.ext$)"
FileRetrieve->>DB: "Course.query.filter_by(uuid=course_uuid)"
DB-->>FileRetrieve: course (or None)
FileRetrieve->>FileRetrieve: check user.user_courses for instructor/TA role
FileRetrieve-->>Client: file stream or 403
Reviews (4): Last reviewed commit: "fix report access to verify enrollment i..." | Re-trigger Greptile |
The cascade_backrefs behavior was removed in SQLAlchemy 2.0, so setting comparison=comparison in the ComparisonCriterion constructor no longer implicitly adds the child to the session. Explicitly add comparison_criterion instead of the already-tracked comparison.
No description provided.