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.
This commit is contained in:
Simon
2026-04-18 11:41:00 +02:00
parent c217705eb5
commit 38d69c65a5
+17 -132
View File
@@ -1,154 +1,39 @@
# INFO1
Ein selbst gehostetes Dashboard für eine Klasse, Lerngruppe oder kleine Kohorte. Ein Ort für Stundenplan, Hausaufgaben, Noten, Fehlzeiten, gemeinsamen Kalender, Klassenchat und Ende zu Ende verschlüsselte Direktnachrichten.
Dashboard für die Klasse INFO1 an der IFB-Berufsfachschule Rosenheim. Stundenplan, Hausaufgaben, Noten, Fehlzeiten, Klassenkalender, Chat und Ende zu Ende verschlüsselte Direktnachrichten an einem Ort.
Bewusst unspektakulär aufgebaut: Node.js, Express, SQLite, vanilla JavaScript. Kein Buildschritt, kein Framework Lock in, läuft auf einem 1 GB VPS.
Läuft unter [info1.simon0x.xyz](https://info1.simon0x.xyz).
![License](https://img.shields.io/badge/license-MIT-blue.svg)
![Node](https://img.shields.io/badge/node-%E2%89%A520-brightgreen)
![No Build Step](https://img.shields.io/badge/build-none-lightgrey)
![Self Hosted](https://img.shields.io/badge/self--hosted-yes-informational)
## Stack
## Worum geht es
Node.js 20, Express 5, SQLite über `better-sqlite3`, Vanilla JS im Frontend. Kein Buildschritt. Auth per JWT im HttpOnly-Cookie, bcrypt, TOTP-2FA. Mail über Resend. E2EE mit ECDH P-256 und AES-GCM im Browser.
Die meisten Schul- und Lernplattformen sind schwergewichtig, kommerziell oder an eine bestimmte Institution gebunden. INFO1 ist das Gegenteil: eine einzige App, die jede Gruppe für sich selbst hosten kann, mit voller Kontrolle über die eigenen Daten und ohne Anbieter dazwischen.
Das Projekt nimmt Datenschutz ernst (Direktnachrichten werden im Browser verschlüsselt, der Server sieht nie Klartext), bleibt im Umfang ehrlich (für ein paar hundert aktive Nutzer, nicht für tausende) und ist so geschrieben, dass eine Person den Code an einem Nachmittag vollständig lesen kann.
## Funktionen
**Persönliches Dashboard**
- Stundenplan, Hausaufgabenverwaltung, Notenbuch mit automatischen Durchschnitten
- Fehlzeitenprotokoll, persönliche Todos, Countdowns, anpassbare Schnelllinks
- Dateiablage pro Nutzer mit Speicherkontingent
**Geteilte Klassenebene**
- Klassenkalender für Prüfungen, Ferien, Ereignisse (ohne Login einsehbar)
- Klassenchat mit Rate Limiting und sanfter Moderation
- Ende zu Ende verschlüsselte Gruppennachrichten (ECDH P-256 und AES-GCM, Schlüssel verlassen nie den Browser)
**Lehrerwerkzeuge**
- Fachbezogene Ankündigungen, Materialupload, Klausurplanung
- Direktes Setzen von Noten für einzelne Schüler
- Freigabeprozess: neue Lehrerkonten landen in einer Warteschlange für einen Admin
**Adminkonsole**
- Nutzerverwaltung (sperren, entsperren, befördern, zurückstufen, löschen)
- Manuelles Freischalten der E-Mail-Verifizierung, Rollenänderung, Auditlog
- Triage von Supporttickets mit Thread-Antworten
- Speicher- und Nutzungsstatistiken pro Nutzer
**Auth und Kontosicherheit**
- E-Mail-Verifizierung bei der Registrierung über [Resend](https://resend.com)
- Passwort-Reset per Mail mit einmalig verwendbaren Tokens (1 Stunde gültig)
- TOTP-Zweifaktor-Authentifizierung mit QR-Code
- Passwort-Hashing mit bcrypt (Kosten 12), JWT in HttpOnly-Cookie
- Rate Limiting auf allen sensiblen Endpoints
## Technologie
| Schicht | Wahl |
|---------|------|
| Laufzeit | Node.js 20, Express 5 |
| Datenbank | SQLite über `better-sqlite3` (synchron, in-process) |
| Auth | JWT im HttpOnly-Cookie, bcrypt, otplib für TOTP |
| Mail | Resend (austauschbar gegen jeden SMTP-Anbieter) |
| Frontend | Vanilla JavaScript, kein Bundler, kein Framework |
| Security | Helmet, CSP, express-rate-limit |
Gesamtgröße: rund 3 KLOC Servercode und eine Handvoll eigenständige HTML-Dateien.
## Schnellstart
## Lokal starten
```bash
git clone https://github.com/lulinretrograde/ifb-schulapp.git info1
cd info1
npm install
cp .env.example .env # dann bearbeiten
cp .env.example .env # JWT_SECRET und RESEND_API_KEY setzen
node index.js
```
Die App bindet an `127.0.0.1:3010`. Für öffentliche Deployments einen Reverse Proxy davorschalten (Caddy, nginx, Cloudflare Tunnel).
Bindet an `127.0.0.1:3010`.
## Konfiguration
## Registrierung
Alle Einstellungen laufen über Umgebungsvariablen. Vollständige Liste in `.env.example`.
Beschränkt auf `@ifb-schulen.com`-Adressen (Regex `IFB_EMAIL_RE` in `src/routes.js`). Jeder neue Account muss per Mail bestätigt werden. Neue Lehrerkonten landen in einer Admin-Warteschlange.
```dotenv
JWT_SECRET= # Pflicht, 32+ zufällige Bytes
RESEND_API_KEY= # Pflicht für Verifizierungs- und Reset-Mails
MAIL_FROM=noreply@deinedomain.example
MAIL_FROM_NAME=Klassenportal
APP_URL=https://deinedomain.example
NODE_ENV=production
```
### E-Mail-Domain-Beschränkung
Die Registrierung ist standardmäßig auf eine einzige E-Mail-Domain beschränkt, via Regex in `src/routes.js`. `IFB_EMAIL_RE` anpassen oder entfernen, um die Beschränkung zu lockern, oder durch eine eigene Allowlist ersetzen.
### Datenbank
SQLite-Datei liegt unter `./data.db` und wird beim ersten Start erzeugt. Migrationen sind idempotent und stehen am Ende von `src/db.js`. Für ein Backup die Datei zur Laufzeit kopieren (SQLite erlaubt parallele Lesezugriffe während des Kopierens).
## Deployment
Minimale systemd-Unit:
```ini
[Unit]
Description=INFO1
After=network.target
[Service]
Type=simple
User=www
WorkingDirectory=/opt/info1
ExecStart=/usr/bin/node index.js
Restart=always
Environment=NODE_ENV=production
EnvironmentFile=/opt/info1/.env
[Install]
WantedBy=multi-user.target
```
TLS am Reverse Proxy terminieren und `NODE_ENV=production` setzen, damit das Auth-Cookie das `Secure`-Flag bekommt.
## Sicherheit
- Die App startet nicht, wenn `JWT_SECRET` nicht gesetzt ist.
- Direktnachrichten werden im Browser verschlüsselt, bevor sie hochgeladen werden. Der Server speichert ausschließlich opaken Chiffretext und kann auch mit Datenbankzugriff den Inhalt nicht lesen.
- Alle schreibenden Endpoints sind Rate limitiert. Die Limits sind für kleine Gruppen abgestimmt und sollten für größere Deployments nachgezogen werden.
- Adminaktionen landen in `admin_logs` mit Akteur, Ziel und einem JSON-Detail-Blob.
Verantwortungsvolle Offenlegung von Schwachstellen: Issue mit Kurzbeschreibung öffnen, Details per Mail nachreichen.
## Projektstruktur
## Layout
```
index.js Express-Bootstrap, Static Serving, Routenmontage
src/
db.js SQLite-Singleton, Schema, Migrationen
auth.js JWT-Hilfsfunktionen, requireAuth-Middleware
routes.js Auth-Endpoints, Admin, Tickets, Chat, Klassenkalender
teacher.js Lehrer-Endpoints und Material-Upload
files.js Dateiablage pro Nutzer mit Quota
mailer.js Resend-Wrapper und Mail-Templates
public/
index.html Öffentliche Startseite
login.html Login, Registrierung, Passwort-Reset
app.html Hauptdashboard nach Login
admin.html Adminkonsole
reset-password.html Zielseite für Passwort-Reset-Links
datenschutz.html Datenschutzerklärung
e2ee.js Kryptoprimitiven für Ende zu Ende Verschlüsselung
index.js Express-Bootstrap
src/db.js SQLite, Schema, Migrationen
src/routes.js Auth, Admin, Chat, Kalender, Tickets
src/teacher.js Lehrerendpoints
src/files.js Dateiablage mit Quota
src/mailer.js Resend-Wrapper
public/ HTML-Seiten und E2EE-Primitiven
```
## Status
Aktiv entwickelt für eine einzelne Kohorte. Im produktiven Einsatz bei einer kleinen Gruppe von Lernenden und Lehrenden. Die APIs sind nicht versioniert und können sich zwischen Commits ändern.
## Lizenz
MIT. Siehe [LICENSE](./LICENSE).