Skip to content

feat(assignments): Full assignment management system#265

Draft
BOUKAR-Nadia wants to merge 45 commits into
Open-TutorAi:mainfrom
BOUKAR-Nadia:assignments
Draft

feat(assignments): Full assignment management system#265
BOUKAR-Nadia wants to merge 45 commits into
Open-TutorAi:mainfrom
BOUKAR-Nadia:assignments

Conversation

@BOUKAR-Nadia

@BOUKAR-Nadia BOUKAR-Nadia commented Jun 21, 2026

Copy link
Copy Markdown

What does this PR do?

This PR adds a complete assignment management system for OpenTutorAI:

  1. Classroom management – teachers can create classrooms, enroll students by email, view enrolled students by full name and email, and remove a student from a class.
  2. Assignment CRUD – teachers can create, edit, and delete assignments (title, instructions, due date, max score, optional file attachment or external URL). Deleting an assignment also removes all its submissions.
  3. URL link support – teachers can share a Google Drive, Google Docs, YouTube, or any external link as the assignment attachment; students can do the same in their submissions. External links open in a new tab; internal files download with authentication.
  4. Student submission – students can submit a text answer, attach a file, and/or paste an external link. Late submissions are automatically detected. Students can also cancel their submission before the teacher grades it.
  5. Grading – teachers see all submissions in a table with the student's full name, open a grading modal that shows the student's work and an "Open Link" or "Download" button for their attachment, enter a score and feedback, and return the grade.
  6. Student grade view – once graded, students see their score, teacher feedback, and can open or download their own submitted attachment.
  7. Status tracker – teachers have a per-student status overview: submitted, late, returned, missed, or not_submitted.

Why is this needed?

The platform had no structured way for teachers to assign work and for students to hand it in. This feature closes that gap with a complete end-to-end submission and grading loop integrated into both the teacher and student portals.

How to test?

Setup

  1. Start the backend: python -m uvicorn --factory gateway.http.app:create_app --host 0.0.0.0 --port 8080
  2. Start the frontend: cd ui && npm run dev

Teacher flow

  1. Sign up as a teacher → go to My Classrooms → click New Classroom → create a class.
  2. Open the classroom → click Enroll Student → enter the student's email → confirm → Enroll. Use the remove icon next to a student to unenroll them.
  3. Go to Assignments → click New Assignment → fill in title, classroom, due date, instructions → optionally upload a file or paste an external URL (Google Drive, Docs…) → Create Assignment.
  4. Open the assignment → click Edit to update any field including the attachment link, or Delete to remove it entirely.
  5. See the Submissions table (students shown by full name), Status Tracker tab, and Overview tab with an Open Link or Download Attachment button.
  6. Click Grade → view the student's answer and attachment → enter a score and feedback → Return Grade.

Student flow

  1. Sign up as a student (role: user) → go to Assignments → see the assignment in the To Do tab.
  2. Open the assignment → click Open Link (if the teacher shared a URL) or Download Attachment (if they uploaded a file).
  3. In the Your Work section: write an answer, attach a file, or paste an external link → Submit Assignment.
  4. Click Cancel Submission to withdraw before the teacher grades.
  5. After the teacher grades: reload → see the Graded badge, score, feedback, and attachment link.

Late submission

  1. Create an assignment with a due date in the past → submit as a student → automatically flagged as Late.

Screenshots

Teacher — Assignments list
Teacher assignments list

Teacher — New Assignment modal with file upload and URL link field
Teacher create assignment modal with URL field

Teacher — Assignment detail (Overview tab with Open Link button)
Teacher assignment detail with Open Link button

Teacher — Edit assignment modal with attachment link field
Teacher edit assignment modal

Teacher — Grade modal showing student's link ("Open student's link")
Teacher grade modal with student link

Teacher — Classroom with enrolled students and remove button
Classroom enrolled students

Student — My Assignments (tabs)
Student assignments list

Student — Submission form: teacher's Open Link + student's submitted link
Student submit with link

Student — Returned grade with score and feedback
Student grade result

Checklist

  • Target branch: main
  • Description: Provided above
  • Changelog: Added below
  • Documentation: docs/assignments.md (API reference) and docs/assignments-user-guide.md (user guide)
  • Dependencies: No new dependencies added
  • Testing: Tested locally with FastAPI + SvelteKit dev server (Playwright end-to-end)
  • Code review: Self-review done
  • Prefix: feat

Changelog Entry

Added

  • Classroom management: create, enroll by email, list students with name + email, unenroll (DELETE /api/v1/classrooms/{id}/students/{student_id})
  • Assignment CRUD: create, edit (PUT /api/v1/assignments/{id}), delete (DELETE /api/v1/assignments/{id})
  • URL link attachments: teachers and students can paste external URLs (Google Drive, Docs, YouTube…) as attachments; displayed as "Open Link" buttons opening in a new tab
  • Student submission with text answer, file, and/or external link; automatic late detection (POST /api/v1/assignments/{id}/submit)
  • Student cancel submission (DELETE /api/v1/assignments/{id}/my-submission)
  • Teacher grading with score and feedback (POST /api/v1/assignments/{id}/submissions/{sub_id}/grade)
  • Per-student status tracker (GET /api/v1/assignments/{id}/status)
  • Student lookup by email (GET /api/v1/users/lookup?email=)
  • Teacher assignment detail: Edit modal (with attachment link field), Delete button with confirmation
  • Teacher classroom: Remove student button per row
  • Student assignment page: Cancel Submission button (visible until graded)
  • API documentation: docs/assignments.md
  • User guide: docs/assignments-user-guide.md

Changed

  • Submissions table and status tracker: display student full name instead of UUID
  • Enrolled students list returns name and email alongside student_id
  • File download uses fetch() + Authorization: Bearer header
  • All primary action buttons use indigo to match the app color palette
  • attachment_url now accepts both internal file URLs and any external URL

Fixed

  • Protected file download no longer returns 401 (was using plain <a href>)
  • Student names displayed everywhere instead of UUIDs
  • Cancel submission no longer throws JSON.parse error (204 No Content response handled correctly)
  • Overview tab activates automatically after editing an assignment so the updated link is immediately visible

Breaking Changes

  • None

Additional Information

  • Branch: assignments from fork BOUKAR-Nadia/open-tutor-ai-CE
  • No new npm or Python dependencies required.

TarekAi and others added 30 commits June 9, 2026 23:15
fix(auth): persist and return user role on signup
…orts

Each feature under lib/features/ now exposes a public surface via index.ts
so routes import from `$lib/features/<feature>` instead of deep component
paths. Covered: admin, auth, channel, legal, playground, student, workspace.
Routes using chat/avatar barrels (already existing) also migrated off direct
component paths (Messages, PairedResponses, SettingsModal).
Scans requirements*.txt and ui/package-lock.json against the OSV
database on manifest changes and weekly. Detection-only: findings
land in the Security tab without blocking merges.
Replace Black with Ruff (format + lint) across pre-commit, CI, and
requirements. Ruff config lives in pyproject.toml with E/F/I rules.

Cleanup of the 103 pre-existing lint findings: unsorted/unused
imports auto-fixed, SQLAlchemy boolean filters converted to .is_()
(the E712 autofix would have broken the queries), test asserts
switched to 'is True/False', one dead mock binding removed.

Full pytest suite passes (210 tests).
'vitest --passWithNoTests' enters watch mode outside CI (GitHub
Actions sets CI=true, which is why CI never hung) and leaks worker
processes locally — 'make test' never returned. Use 'vitest run'
explicitly; watch mode stays available via test:watch.
- CONTRIBUTING: English-only, required local setup (pre-commit +
  commit-msg hook), Make targets table, and the mandatory feature
  workflow (issue -> architecture -> TDD -> docs -> PR)
- Issue/PR templates: required Architecture section (OpenWebUI-first,
  DDD boundary, API contract, test plan) and matching PR checklist
- AGENTS.md: Known Pitfalls, graduated proof standards,
  change-detector test anti-patterns, git discipline, feature workflow
- SECURITY.md: private vulnerability reporting via GitHub advisories
- Normalize end-of-file newlines flagged by pre-commit across
  remaining files; repo links point to the canonical Open-TutorAi org
- Teacher space: sidebar, navbar, dashboard with quick actions
- Student detail page: header, stats, parents/guardians tab
- Invite modal: form triggered by button click
- Guardian backend: ORM model, repository, service, 4 REST endpoints
- Fix: teacher signup now correctly redirects to /teacher
- Tests: 9 passing tests for guardian endpoints
- Classroom & enrollment management (create, enroll students by email)
- Assignment CRUD with file attachments (PDF, images, etc.)
- Student submission with text answer and/or file attachment
- Teacher grading modal with score, feedback, and student attachment download
- Per-student status tracker: submitted / late / returned / missed / not_submitted
- Student assignments list with tabs (To Do / Submitted / Late / Missed)
- Enrolled students now display full name + email instead of UUID
- Protected file download via fetch + Authorization Bearer header
- API docs in docs/assignments.md
@BOUKAR-Nadia BOUKAR-Nadia changed the title feat(assignments): E7 — Full assignment management system feat(assignments): Full assignment management system Jun 21, 2026
- Display full student name (from enrolled list) in submissions table,
  status tracker, and grade modal instead of truncated UUID
- Change "Return Grade" button from emerald to indigo to match app palette
- Update getClassroomStudents type to include name and email fields
Replace old screenshots with new captures that reflect:
- Student full name (Lucas Dupont) in submissions table, status tracker, and grade modal
- "Return Grade" button in indigo instead of green
…ubmission

Teacher:
- PUT /api/v1/assignments/{id} — edit title, instructions, due date, max score
- DELETE /api/v1/assignments/{id} — delete assignment + all its submissions
- DELETE /api/v1/classrooms/{id}/students/{student_id} — unenroll a student
- Edit modal on assignment detail page (pencil button in header)
- Delete button in header with confirmation dialog
- Remove button (user-minus icon) next to each enrolled student

Student:
- DELETE /api/v1/assignments/{id}/my-submission — cancel own submission
- "Cancel Submission" button shown when submission exists and not yet graded
…mission

New captures showing all new features:
- teacher-assignment-detail: Edit + Delete buttons in header
- teacher-edit-modal: edit assignment form
- classroom-students: remove student button per row
- student-submit: Cancel Submission + Update Submission buttons
@Oumaima-elkhoummassi

Copy link
Copy Markdown

Documentation Review — Assignments Feature

Hi @BOUKAR-Nadia! 👋

I've reviewed both documentation files. Overall good work, but there are some issues to fix:


assignments.md

Missing endpoints (present in your changelog, absent from the table):

  • DELETE /api/v1/assignments/{id} — delete assignment
  • PUT /api/v1/assignments/{id} — edit assignment
  • DELETE /api/v1/classrooms/{id}/students/{student_id} — unenroll student
  • DELETE /api/v1/assignments/{id}/my-submission — cancel submission

Path mismatch with your own changelog (please confirm which one is correct):

  • Grading: table says POST /api/v1/assignments/{id}/grade/{sub_id}, changelog says POST /api/v1/assignments/{id}/submissions/{sub_id}/grade
  • Status tracker: table says GET /api/v1/assignments/{id}/status-tracker, changelog says GET /api/v1/assignments/{id}/status

assignments-user-guide.md

Missing sections:

  • Remove a student from classroom (teacher)
  • Edit / Delete an assignment (teacher)
  • Cancel Submission (student)

Screenshots issue:

Screenshots are in docs/screenshots/ but not referenced in the guide — add ![...](./screenshots/...) or remove unused images.


Summary

Please fix these issues before I can approve the PR. Let me know if you need any clarification! 🚀

onMount(async () => {
try {
[assignment, submission] = await Promise.all([
getAssignment(localStorage.token, assignmentId),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi 👋,BOUKAR-Nadia

[HIGH – CWE-523 / OWASP A02] Authentication tokens are currently stored in localStorage throughout the Svelte application.

Storing sensitive tokens in localStorage exposes them to any JavaScript running in the browser. In the event of an XSS vulnerability, compromised third-party script, or malicious browser extension, the token could be extracted and used to gain unauthorized API access.

Recommendation: Store authentication tokens in HttpOnly, Secure, and SameSite=Strict cookies managed by the server. This prevents client-side JavaScript from accessing the token and significantly reduces the impact of XSS attacks. Remove all frontend references to localStorage for authentication data.

@OumaLam

OumaLam commented Jun 23, 2026

Copy link
Copy Markdown

Security Review
Hi @BOUKAR-Nadia

Thank you for this contribution. The assignment management system is a significant addition to the platform and covers the complete workflow from classroom management and assignment creation to submission tracking and grading.

While reviewing the implementation from a security perspective, I identified a few concerns that should be considered before merging or releasing this feature:

Critical Findings

1. Missing Authorization Checks (CWE-862 / OWASP A01)

GET /guardians/student/{student_id} exposes guardian PII (name, email, relationship) without verifying whether the authenticated user is authorized to access data for the requested student.

Risk: Any authenticated user can enumerate guardian information for unrelated students.

Recommendation : Enforce object-level authorization and verify that the caller owns the resource or has a legitimate administrative/teaching relationship with the student.

2. IDOR Vulnerabilities (CWE-639 / OWASP A01)

Endpoints using guardian_id (/contact, /resend) retrieve or modify resources directly from user-controlled identifiers without validating ownership or authorization.

Risk: Unauthorized disclosure of guardian data and abuse of email invitation functionality.

Recommendation: Implement resource ownership validation before returning data or performing actions.

High Severity Findings

3. Missing Authorization Re-Validation (CWE-285)

Assignment operations rely on enrollment checks performed during listing but do not consistently re-validate authorization during subsequent actions.

Risk: Users may continue interacting with assignments after losing access rights.

Recommendation: Perform authorization checks on every state-changing operation (submit, cancel_submission, etc.).

4. Authentication Token Stored in localStorage (CWE-922)

Frontend authentication relies on localStorage.token.

Risk: Any XSS vulnerability or malicious third-party script can exfiltrate authentication tokens and fully compromise user accounts.

Recommendation: Store session tokens in HttpOnly, Secure, SameSite=Strict cookies and implement short-lived access tokens with rotating refresh tokens.

Thanks again for the contribution. These improvements would significantly strengthen the security of the project and help prevent common access control and authorization issues.

Feel free to reach out if you have any questions about the findings or need assistance implementing the recommended fixes. I'd be happy to help review the changes so that the pull request can move forward toward a successful merge.

@pr-elhajji

Copy link
Copy Markdown
Contributor

Hi,
This branch cannot be merged yet due to existing conflicts. Please resolve the conflicts and update the branch so we can continue the review process.

@TarekAi TarekAi self-requested a review June 24, 2026 23:02
pr-elhajji and others added 6 commits June 26, 2026 00:14
…fied-ai-context-spec

chore: add unified AI agent context and shared skills workflow & CI pipelines fix
docs: add current and target backend architecture sequence diagrams
Merge upstream/main into assignments branch. Kept all assignment
management features (classrooms, guardians, assignments routers) while
integrating upstream's refactored imports, api_routes, and UI fixes.
…and screenshots

- Teachers can paste external URLs (Google Drive, Docs, YouTube, etc.)
  when creating or editing an assignment, in addition to uploading files
- Students can paste external URLs when submitting work
- External links open in a new tab ("Open Link" button); internal file
  URLs continue to download with auth ("Download Attachment" button)
- Fix: 204 No Content response on cancel submission no longer throws
  JSON.parse error
- Fix: Overview tab now activates automatically after editing, so the
  updated attachment link is immediately visible
- Docs: update assignments.md with all endpoints (PUT, DELETE, cancel)
  and attachment_url semantics; update user guide with URL link steps
  and cancel/unenroll instructions
- Screenshots: replace all captures with fresh ones showing the new
  URL fields, Open Link buttons, and student link display
Merge upstream import style refactor (split router imports into one block
per router) while keeping Guardian, Classroom, and Assignment models and
routers added by the assignments feature branch.
- PUT /api/v1/classrooms/{id} to update name, subject, description
- DELETE /api/v1/classrooms/{id} to permanently delete a classroom
- Frontend: edit modal pre-filled and delete confirmation modal
- Fix apiFetch to handle 204 No Content responses

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants