Commit Graph

6 Commits (02a5120b9cc2b3e56b758b6a722f04ee9bdc4f84)

Author SHA1 Message Date
nexxo 02a5120b9c Der Weg zurueck geht durch die Vordertuer, und ein Fehlschlag bleibt sichtbar
Der letzte Fix hat zwei eigene Loecher gerissen, beide dieselbe Klasse wie das,
was er schliessen sollte: die Oberflaeche versicherte etwas, das im Gast nicht
eingetreten war.

Entzogen stand VOR dem Fehlschlag, also verschwanden Grund und
Wiederholen-Knopf genau dort, wo sie am noetigsten sind: scheitert das disable,
ist das Konto weiter offen, waehrend die Zeile "entzogen" sagt. Es gibt keinen
Wiederholungslauf und keinen Abgleich, und diese Seite ist die einzige, die
nc_state anzeigt. Beides steht jetzt nebeneinander.

Und die Meldung empfahl einen neuen Sitz, den die Eindeutigkeit von
(customer_id, email) unmoeglich machte. addSeat() nimmt einen entzogenen Sitz
derselben Adresse wieder auf — durch dieselbe Platzpruefung wie jeder neue,
denn das ist der Grund, warum es die Vordertuer sein muss und kein Knopf an der
Zeile. Der Auftrag entsperrt dabei, was revoke() gesperrt hat; user:welcome tut
das nicht.

retry() bekommt die owner-Wache nach, die bisher nur am Knopf davor hing. Und
der Kommentar in mount() behauptet keine Heilung mehr, die nicht stattfindet.
2026-08-03 22:32:45 +02:00
nexxo a569d2215b Entzogen bleibt entzogen, und der Inhaber laedt sich nicht selbst ein
Dass revoke() nicht mehr loescht, hat eine Kehrseite, die nirgends stand: der
Umschalter in suspend() kannte nur zwei Zustaende und machte aus einem
entzogenen Sitz beim zweiten Klick wieder einen aktiven — samt user:enable und
vorbei an der Platzgrenze, die nur beim Anlegen geprueft wird. sendInvite() bot
denselben Weg. Beide weisen 'revoked' jetzt ab, die Zeile traegt keinen
Handlungsknopf mehr, und wieder aufmachen kann man sie gar nicht: der Weg
zurueck ist ein neuer Sitz.

Der Einladen-Knopf stand auch an der Inhaber-Zeile. Ein Klick vor der fertigen
Bereitstellung haette spaeter ein zweites Konto in der Gruppe admin angelegt,
neben dem echten — und mount() haette den Sitz danach nie wieder verknuepft,
weil die Bedingung am Zustand hing statt am Anmeldenamen.

queueSync() entscheidet ueber nc_synced_at statt ueber nc_state: ein Sitz,
dessen Einladung an einem unerreichbaren Gast scheiterte, hat dort nichts, was
man sperren koennte. Damit das keine Luecke reisst, vermerkt der Auftrag ein
angelegtes Konto sofort, auch wenn die Rolle danach scheitert.
2026-08-03 22:14:19 +02:00
nexxo 0e3a76a7cb Aus der Attrappe wird Verwaltung
Anlegen und Einladen sind zwei Vorgaenge. Einladen schickt einen Auftrag auf
die Bereitstellungs-Warteschlange — die einzige, die einen Gast erreicht — und
der Sitz zeigt danach, was WIRKLICH passiert ist, samt Grund und
Wiederholen-Knopf. Ohne das drueckt der Inhaber wieder und wieder.

Entziehen loescht nichts mehr. Ratelimit 10 je Kunde und 3 je Sitz pro Stunde,
mit echter Restzeit in der Meldung statt stummer Verweigerung.

Eine Pruefung verbietet user:delete im ganzen app/-Verzeichnis.
2026-08-03 21:52:59 +02:00
nexxo 320e485215 Dauerhafte Pruefung: Wanderung und linkToInstanceAdmin() bleiben gleich
Die Gleichheit zwischen der eingefrorenen Wanderungsfassung und der
Modellmethode war bisher nur mit einer geloeschten Testdatei belegt - gut
fuer heute, nicht fuer morgen. Nach dem Muster von HostTokenKeyMigrationTest
laedt der neue Test die echte Wanderungsdatei per require() und haelt sie
gegen linkToInstanceAdmin(): einmal die entschluesselte Falle direkt
geprueft (nc_username darf nie Chiffretext werden), einmal beide Wege bei
derselben Ausgangslage gegeneinander.
2026-08-03 21:07:19 +02:00
nexxo 80974108b1 Wanderung friert das Nachziehen selbst ein, statt die Modellmethode zu rufen
up() rief bisher Seat::linkToInstanceAdmin() auf. Ein migrate:fresh auf
frischer Datenbank haette damit die dann aktuelle Fassung dieser Methode
mitgefahren, nicht die von heute. Die Nachbefuellung ist jetzt eine eigene,
dokumentiert duplizierte Fassung ueber den Query Builder.

nc_admin_ref ist am Modell verschluesselt gecastet - roher Spaltenzugriff
haette Chiffretext statt Klartext geliefert. Crypt::decryptString() macht
denselben Aufruf wie der Modell-Cast, ohne eine Modellklasse zu laden.

Kleinere Nachbesserung: fill() statt forceFill() in linkToInstanceAdmin()
(alle drei Felder stehen in $fillable), und die Gruppen-Zuordnungspruefung
verifiziert jetzt die konkreten Namen 'mitarbeiter'/'nur-lesen', nicht nur
"irgendein Wert".
2026-08-03 20:59:45 +02:00
nexxo 94210a7176 Ein Sitz fuehrt Absicht und Wirklichkeit getrennt
status = was der Inhaber will, nc_state = was in der Nextcloud ist. Ein
einzelnes Feld muesste luegen — und "fehlgeschlagen" liesse sich gar nicht
sagen.

Rollen werden Nextcloud-Gruppen. Der Inhaber-Sitz wird mit dem Admin-Konto
verknuepft, das die Bereitstellung laengst angelegt hat.

SeatFactory setzt nc_state jetzt explizit (wie status/locale bei Customer
und Instance): Eloquents create() liest DB-Spalten-Vorgaben nicht ins
In-Memory-Modell zurueck, sonst haette Seat::factory()->create()->nc_state
null statt 'none' geliefert.
2026-08-03 20:48:36 +02:00