Drop universal framing and reduce feature walkthrough. README now names
the actual class and school, points at the live deployment, and keeps
only the bits needed to clone/run locally.
README in German with universal framing (class, study group, cohort)
rather than INFO1-specific wording. MIT license. Update package.json
with description, keywords, repository URL, proper license field,
start script. Add .env.example documenting required environment
variables.
- Add password_resets table: single-use tokens with 1h expiry.
- Add POST /api/forgot-password: sends reset link if account exists and is verified (always returns ok to prevent enumeration).
- Add POST /api/reset-password: validates token, updates password, invalidates all open reset tokens for that user in one transaction.
- Add /reset-password page with password strength meter and confirm field.
- Add "Passwort vergessen?" flow on login page.
- Factor shared email template into mailer helper, add sendPasswordResetMail.
- Rate limits: 5 forgot-requests/hour per IP, 10 reset attempts/15min per IP.
- Replace "IFB-Berufsfachschule Rosenheim" brand text with neutral "Klassenportal" labels in titles, brand headers, and footers.
- Rewrite privacy-policy responsible-party section to clarify this is a private, non-official project (no school/organization affiliation).
- Include prior uncommitted work on index.html and app.html.
Retain factual audience descriptors ("Nur für IFB-Schüler") and external links to the school website; these reference but do not impersonate.
- Require JWT_SECRET env var (fatal exit if missing)
- Add helmet middleware with custom CSP
- Cookie Secure flag when NODE_ENV=production
- requireAuth re-verifies user.status from DB on every request
- class_events DELETE restricted to creator or admin
- Rate limit /register (5/hr) and PUT /me/password (5/15min)
- Password minimum 6 to 8 chars
- crudRoutes truncates strings to 1000 chars
- Remove application/octet-stream from allowed upload MIMEs
- Teacher registration requires subject selection; account starts pending
- Admin approves/rejects via existing admin panel
- Teacher panel (Materialien, Ankündigungen, Prüfungen, Noten) visible only to approved teachers
- Students see class materials and announcements via sidebar overlays
- Teachers can assign grades to students (scoped to own subject)
- New tables: teacher_materials, teacher_announcements, teacher_exams, teacher_assigned_grades
- subject column added to users; included in JWT and /api/me
- requireTeacher middleware fetches fresh status+subject from DB on every request
- Login hint: username is the part of the school email before the @