feat(api): Benutzernamen (Profil-Tabelle, /api/profil, Pflicht beim Hochladen und Veröffentlichen)
- Schema: Tabelle `profiles` (Zeilen-ID = Konto-ID, `username` und `usernameKey`
je 20 Zeichen, Unique-Index `username_key` auf `usernameKey`, rowSecurity an,
keine Tabellenrechte) im Setup-Skript.
- Neues Modul `deploy/api/profiles.js`: `POST /api/profil` legt das Profil an
oder ändert es (Zeilenrecht genau read("any"), Sperre je Konto). Muster,
Sperrliste und Schlüssel (`usernameKey`) stehen in `common.js`; vergeben ->
409 `usernameTaken`, auch wenn erst der Unique-Index bei einem Rennen
entscheidet. Dazu die MSG-Texte `usernameInvalid`, `usernameReserved`,
`usernameTaken`, `usernameRequired`.
- `POST /api/logos/hochladen` und `POST /api/veroeffentlichen` antworten 403
`usernameRequired`, wenn das Konto kein Profil hat (`hasProfile`, nach der
Anmeldung und vor allen anderen Prüfungen).
- Fake-Appwrite: Tabelle `profiles` mit Unique-Index (409), `addProfile`,
`holdNext`. API-Dienst besteht jetzt aus sechs Dateien (READMEs).
- Client: die vier API-Texte in `API_MESSAGES` und `en.ts` (Gleichlauf mit MSG).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a65c075004
commit
19c8151c7e
15 files changed
+980
-53
No files matched your search
@@ -3,9 +3,9 @@
|
||||
* AirCard – Appwrite-Schema-Setup (idempotent)
|
||||
*
|
||||
* Legt im selbst gehosteten Appwrite (Projekt `aircard`) die Datenbank `aircard`,
|
||||
* die Tabellen `cards`, `gallery`, `reports`, `logos`, `logo_likes` und
|
||||
* `logo_reports` (TablesDB, mit Spalten und Indizes) und die Buckets
|
||||
* `card-images`, `gallery-images` und `logo-images` an.
|
||||
* die Tabellen `cards`, `gallery`, `reports`, `logos`, `logo_likes`,
|
||||
* `logo_reports` und `profiles` (TablesDB, mit Spalten und Indizes) und die
|
||||
* Buckets `card-images`, `gallery-images` und `logo-images` an.
|
||||
* Reines `fetch`, keine Abhängigkeiten, Node 22+.
|
||||
*
|
||||
* Aufruf (vom Repo-Wurzelverzeichnis):
|
||||
@@ -41,7 +41,7 @@ const str = (key, size, required) => ({ key, type: 'string', size, required });
|
||||
|
||||
export const DESIRED = {
|
||||
database: { id: 'aircard', name: 'AirCard' },
|
||||
// Reihenfolge ist Ablauf: cards, gallery, reports, logos, logo_likes, logo_reports (je Tabelle: Spalten, dann Indizes).
|
||||
// Reihenfolge ist Ablauf: cards, gallery, reports, logos, logo_likes, logo_reports, profiles (je Tabelle: Spalten, dann Indizes).
|
||||
tables: [
|
||||
{
|
||||
id: 'cards',
|
||||
@@ -137,6 +137,16 @@ export const DESIRED = {
|
||||
],
|
||||
indexes: [{ key: 'logo', type: 'key', columns: ['logoId'] }],
|
||||
},
|
||||
{
|
||||
// Benutzernamen: eine Zeile je Konto, Zeilen-ID = Konto-ID, öffentlich lesbar (Zeilenrecht read("any") setzt die API); geschrieben wird nur
|
||||
// über die API. `usernameKey` ist der Name klein geschrieben: der Unique-Index macht ihn auch bei gleichzeitigen Anfragen nur einmal vergebbar.
|
||||
id: 'profiles',
|
||||
name: 'Profiles',
|
||||
permissions: [],
|
||||
rowSecurity: true,
|
||||
columns: [str('username', 20, true), str('usernameKey', 20, true)],
|
||||
indexes: [{ key: 'username_key', type: 'unique', columns: ['usernameKey'] }],
|
||||
},
|
||||
],
|
||||
buckets: [
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user