Commit Graph

18 Commits

Author SHA1 Message Date
Simon 78f3cb6fb4 feat: ifb.lol landing page with PDF downloads 2026-04-23 10:00:19 +02:00
Simon 345d995b96 feat: password generator, weak-password block, confirm step for generated passwords 2026-04-22 23:04:46 +02:00
Simon 480c3d09e5 fix: ql icons on load, text overflow in quicklink boxes 2026-04-22 22:53:04 +02:00
Simon 62ebc53875 feat: default quicklinks, static PDF downloads, improved app icon 2026-04-22 22:49:35 +02:00
Simon 6b54e3c813 feat: add PWA support (manifest, service worker, icons) 2026-04-22 22:28:17 +02:00
Simon d9189d558d fix: update contact email to kontakt@info1.ifb.lol 2026-04-22 21:49:28 +02:00
Simon 578dd4eab9 rebrand: Klassenportal, domain info1.ifb.lol, server status
- Replace INFO1 brand with Klassenportal everywhere (titles, nav,
  emails, TOTP issuer, recovery codes)
- Update domain from info1.simon0x.xyz to info1.ifb.lol
- Remove E2EE claims (e2ee.js was deleted, claims were false)
- Add GET /api/health endpoint (DB check + uptime)
- Add live server status section to landing page
- Fix README: domain, title, layout table
2026-04-22 21:31:03 +02:00
simon 55cfbcebdc Update README.md 2026-04-21 15:57:44 +02:00
Simon 0dd915eeb2 fix: harden auth, admin, teacher, and e2ee endpoints
- Invalidate JWTs on password change/reset via token_version
- Constant-time login compare against dummy hash to prevent user enum
- Register validates subject against subjects table + user_subjects link
- Last-admin guard on account delete and admin role/status PATCH
- purgeUser unlinks teacher_materials storage files
- 2FA setup/regenerate require password, setup blocks while enabled
- Group sender keys: existing-distributor check + INSERT OR IGNORE
- class_events: type whitelist, ISO date regex, end >= start check
- Teacher absences DELETE: ownership check (teacher_id)
- class_timetable POST: HHMM validation, overlap detection
- class_timetable PUT: subject restricted to teacher list, HHMM + overlap
- Register VALID_SUBJECTS removed; dynamic subjects from DB
- /api/subjects made public (needed by register form)
2026-04-21 13:18:17 +02:00
Simon 38d69c65a5 docs: shorten README and scope to INFO1/IFB
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.
2026-04-18 11:41:00 +02:00
Simon c217705eb5 docs: add README, LICENSE, .env.example
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.
2026-04-18 11:36:22 +02:00
Simon fe33058ae6 feat: password reset via email
- 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.
2026-04-18 01:36:26 +02:00
Simon 5ff616e0d9 chore: remove school-brand impersonation from public pages
- 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.
2026-04-18 01:33:53 +02:00
Simon 396148aea2 feat: email verification via Resend + admin user management
- Add email verification flow: register sends verify link, login blocks unverified accounts, 24h token expiry, resend endpoint (3/h rate limit).
- Add mailer module using Resend with branded HTML + plaintext template.
- Extend admin dashboard: verified-status column, toggle verify/unverify buttons, promote/demote admin role, delete any non-self user.
- Migrate users table: email_verified, verify_token, verify_expires columns.
- Load env via dotenv; add .env to gitignore.
2026-04-18 01:33:45 +02:00
Simon b2de630983 harden security: enforce JWT_SECRET, helmet, CSP, stricter rate limits
- 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
2026-04-17 23:40:27 +02:00
Simon 8f75bc6a10 feat: add TOTP 2FA with QR code and manual secret entry 2026-04-17 22:56:39 +02:00
Simon ae789318ba feat: add teacher system with approval flow
- 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 @
2026-04-17 10:00:09 +02:00
Simon db5efd8ed9 clean initial commit 2026-04-17 00:12:47 +02:00