7.4 KiB
AirCard-IOS – Benutzernamen – Design
Stand: 2026-10-05 · Status: Entwurf im Chat von Kenso freigegeben („ja passt, mach weiter“), Spec + Plan + Umsetzung ohne weitere Rückfrage · baut auf 2026-10-04-aircard-logos-sprache-design.md auf (live, main 13b46da)
1. Ziel und Rahmen
Jedes Konto bekommt einen eindeutigen Benutzernamen. Logos und Community-Karten zeigen „von @name“ statt „Anonym“, damit man Leute wiedererkennt.
| Punkt | Entscheidung (Kenso) |
|---|---|
| Eindeutig | Ja, jeder Name nur einmal; Groß-/Kleinschreibung zählt beim Vergleich nicht. |
| Pflicht | Ja, auch für bestehende Konten. Registrieren nur mit Name; alte Konten werden nach dem Anmelden einmal gefragt; Hochladen und Veröffentlichen gehen erst mit Name. |
| Anzeige | Immer der Benutzername; das Feld „Anzeigename“ fällt weg; gilt auch für vorhandene Einträge des Kontos. |
| Ändern | Ja, im Konto-Menü; danach überall der neue Name, der alte wird frei. |
2. Regeln für den Namen
- Muster:
^[A-Za-z0-9][A-Za-z0-9._-]{2,19}$. Das sind 3–20 Zeichen, das erste ein Buchstabe oder eine Zahl, danach Buchstaben, Zahlen,.,_,-. - Schlüssel für die Eindeutigkeit: der Name in Kleinbuchstaben (
usernameKey). Gespeichert und angezeigt wird der Name, wie er eingegeben wurde. - Gesperrte Schlüssel:
admin,administrator,root,system,support,moderator,mod,aircard,aircardios,aircard-ios,aircard.ios,aircard_ios,webklar,anonym,anonymous,null,undefined,team,staff,official,offiziell,hilfe,help,kontakt,contact,info. - Anzeige mit
@davor: „von @name“ bzw. „by @name“.
3. Daten (Appwrite, Datenbank aircard, Setup-Skript erweitert)
Tabelle profiles (rowSecurity an, keine Tabellenrechte für Clients):
| Spalte | Typ | Inhalt |
|---|---|---|
username |
string 20, Pflicht | Name wie eingegeben |
usernameKey |
string 20, Pflicht | Name klein geschrieben |
- Zeilen-ID = Nutzer-ID (eine Zeile pro Konto).
- Index
username_key: unique aufusernameKey. Damit kann auch bei Gleichzeitigkeit kein Name doppelt vergeben werden. - Zeilenrecht genau
['read("any")'], öffentlich lesbar. Schreiben nur über die API.
4. API-Dienst aircard-api
Eigenes Modul deploy/api/profiles.js, eingebunden wie logos.js. Der Betrieb kopiert künftig sechs Dateien: appwrite.js, common.js, app.js, logos.js, profiles.js, server.js.
POST /api/profil {username}, Nutzer-JWT:
- 401 ohne Anmeldung.
- 400
usernameInvalidbei falschem Muster. - 400
usernameReservedbei gesperrtem Schlüssel. - 409
usernameTaken, wenn ein anderes Konto den Schlüssel hat. Das wird vorab per Abfrage geprüft; bei einem Rennen meldet Appwrite 409 auf dem Unique-Index, das wird ebenfalls zuusernameTaken. - Sonst: Hat das Konto schon eine Zeile, wird sie aktualisiert (der alte Name ist damit frei); sonst wird sie mit ID = Nutzer-ID und
read("any")angelegt. Antwort200 {username}. - Groß-/Kleinschreibung des eigenen Namens ändern („kenso“ → „Kenso“) ist erlaubt.
- Sperre je Konto (
profile:<userId>).
Pflicht serverseitig: POST /api/logos/hochladen und POST /api/veroeffentlichen antworten 403 usernameRequired, wenn das Konto keine Zeile in profiles hat. Die Prüfung läuft nach der Anmeldung und vor allen anderen Prüfungen. Bestehende Logos und Karten bleiben unberührt.
Neue MSG-Texte:
usernameInvalid: „Der Benutzername muss 3–20 Zeichen lang sein, mit einem Buchstaben oder einer Zahl beginnen und darf nur Buchstaben, Zahlen, Punkt, Unterstrich und Bindestrich enthalten.“usernameReserved: „Dieser Benutzername ist nicht erlaubt.“usernameTaken: „Dieser Benutzername ist schon vergeben.“usernameRequired: „Bitte wähle zuerst einen Benutzernamen.“
5. Oberfläche
- Registrieren (Login-Dialog, Reiter „Registrieren“): neues Pflichtfeld „Benutzername“ vor der E-Mail,
autocomplete="username", Hinweis „3–20 Zeichen: Buchstaben, Zahlen, . _ -“.- Vor dem Anlegen des Kontos werden Muster, Sperrliste und Verfügbarkeit geprüft (Abfrage auf
profiles). Ein Fehler steht am Feld. - Danach: Konto anlegen → anmelden →
POST /api/profil. - Scheitert dieser letzte Schritt (Rennen, Netz), ist man trotzdem angemeldet, und der Dialog „Benutzername wählen“ erscheint.
- Vor dem Anlegen des Kontos werden Muster, Sperrliste und Verfügbarkeit geprüft (Abfrage auf
- Dialog „Benutzername wählen“ mit Feld, „Speichern“ und „Später“ bzw. „Abbrechen“:
- Nach dem Anmelden oder beim Seitenstart mit Sitzung, wenn das Konto keinen Namen hat. Einmal pro Sitzung (Merker in
sessionStorageaircard.usernamePrompted, Zugriffe in try/catch), mit „Später“. - Vor dem Hochladen eines Logos und vor dem Veröffentlichen, wenn kein Name da ist. Hier gibt es „Abbrechen“ statt „Später“; ohne Namen geht es nicht weiter.
- Antwortet der Server mit
usernameRequired, erscheint der Dialog ebenfalls.
- Nach dem Anmelden oder beim Seitenstart mit Sitzung, wenn das Konto keinen Namen hat. Einmal pro Sitzung (Merker in
- Konto-Menü: Statt der E-Mail steht „@name“ oben (die E-Mail darunter klein). Neuer Eintrag „Benutzername ändern“, der den Dialog vorbelegt öffnet. Ohne Namen heißt der Eintrag „Benutzername wählen“.
- Anzeige „von @name“: Logo-Kacheln, Logo-Infozeile, Detailseite einer Community-Karte.
- Der Name wird über
ownerIdinprofilesnachgeschlagen, gesammelt je Seite (equal('$id', ids)) und zwischengespeichert. - Ohne Profil: der früher gespeicherte
displayName(ohne@), sonst „Anonym“. - Nach einer eigenen Namensänderung aktualisieren Kacheln, Infozeile und Detailseite die eigenen Einträge sofort.
- Der Name wird über
- Weg fällt das Feld „Anzeigename“ in den Dialogen „Logo hochladen“ und „Veröffentlichen“ samt
account/display-name.tsund demlocalStorage-Schlüsselaircard.displayName. Der Client schicktdisplayName: ''; die API nimmt das Feld weiter an (Altbestand).
Alle Texte gibt es auf Deutsch und Englisch.
6. Fehlerbehandlung
| Fall | Meldung |
|---|---|
| Muster falsch / gesperrt / vergeben | die drei MSG-Texte aus § 4, am Feld |
Server meldet usernameRequired |
Dialog „Benutzername wählen“ |
| Netz/API weg beim Speichern | „Der Dienst ist gerade nicht erreichbar.“, Dialog bleibt offen |
| Profil lässt sich nicht lesen (Anzeige) | Fallback displayName bzw. „Anonym“, kein Fehlertext |
7. Tests
- node:test:
/api/profil: anlegen, ändern, Groß/klein am eigenen Namen, vergeben 409, gesperrt 400, Muster 400, ohne JWT 401.- Rennen mit zwei Konten: genau eines bekommt den Namen.
- Zeilenrechte genau
read("any"). - Hochladen und Veröffentlichen ohne Profil → 403
usernameRequired. - Setup-Skript deckt
profilesmit Unique-Index ab.
- Vitest:
- Prüfung des Namens (Muster, Sperrliste, Schlüssel).
- Registrieren mit Vorabprüfung und Fehlern am Feld.
- Dialog: Später, Abbrechen, Speichern, Fehler.
- Einmal-pro-Sitzung-Abfrage.
- Konto-Menü mit „@name“ und Ändern.
- Anzeige „von @name“ mit Fallbacks; sofortige Aktualisierung nach Umbenennen.
- Dialoge ohne „Anzeigename“.
- Hochladen und Veröffentlichen fragen vorher nach dem Namen.
- Gleichlauf der API-Codes, i18n-Abdeckung.
- Live: Gast sieht „von …“-Zeilen. Kenso registriert bzw. wird gefragt, ändert den Namen und sieht ihn an seinem Logo.
8. Nicht im Umfang
Profilseiten, Suche nach Benutzernamen, Moderation von Namen, Konto löschen, Avatar-Bilder, Benutzername als Anmeldename (angemeldet wird weiter per E-Mail).