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:
@@ -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).
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
## 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).
|
||||
|
||||
Reference in New Issue
Block a user