Systemmenue im Logo, in beiden Leisten

Das ■ HONEYOS ist jetzt ein Menue statt eines Links: Schreibtisch,
Einstellungen, HoneyBar einklappen, Abmelden. In fremden Apps sind es
Links auf den Schreibtisch (?einstellungen=1 / ?abmelden=1), weil die
HoneyBar dort nicht schreiben darf — Sitzung und CSRF-Pruefwort ueber-
leben die Site-Grenze nicht, und ein Abmelden per Aufruf koennte jede
Seite ausloesen.

Der Abmeldeknopf in der Menueleiste faellt weg (stand doppelt), und
Abmelden erscheint nur, wenn HoneyOS ueberhaupt anmeldet — dafuer gibt
/api/apps jetzt oidc mit heraus. Nebenbei: restliche 'Leiste' im Text
zu 'HoneyBar' vereinheitlicht.
This commit is contained in:
marc committed 2026-08-29 21:23:11 +02:00
1 parent 52deffa30e
commit 0a5cd94ba0
12 files changed
+244 -51

No files matched your search

+12 -9
View File
@@ -31,7 +31,7 @@ var webFS embed.FS
// Version ist die einzige Stelle, an der sie steht. build.sh liest sie hier aus
// und vergibt denselben Docker-Tag; die Oberfläche holt sie über /api/public.
// Vorher stand sie zusätzlich in os.js und lief mit den Image-Tags auseinander.
const Version = "1.0"
const Version = "1.1"
type Server struct {
cfg config.Config
@@ -128,7 +128,7 @@ func (s *Server) routes() http.Handler {
mux.HandleFunc("PUT /api/settings", s.requireAuth(s.handleSetSettings))
mux.HandleFunc("GET /api/apps", s.appsReadable(s.handleApps))
mux.HandleFunc("PUT /api/apps", s.requireAuth(s.handleSetApps))
// Dieselbe Tür wie die App-Liste: Die Leiste steht in einer fremden App und
// Dieselbe Tür wie die App-Liste: Die HoneyBar steht in einer fremden App und
// kommt dort nur mit dem Schlüssel an Daten.
mux.HandleFunc("GET /api/weather", s.appsReadable(s.handleWeather))
// Die Ortssuche dagegen nur für Angemeldete. Sie reicht einen Suchbegriff an
@@ -180,7 +180,7 @@ func htmlAttr(v string) string {
/* ── Zwischenschichten ───────────────────────────────────────────────────── */
// cors öffnet die Leiste für die eingetragenen Apps — und nur für die. Die
// cors öffnet die HoneyBar für die eingetragenen Apps — und nur für die. Die
// App-Liste ist damit zugleich die Freigabeliste; wer nicht darin steht, kommt
// auch nicht an die Sitzung.
func (s *Server) cors(next http.Handler) http.Handler {
@@ -205,11 +205,11 @@ func (s *Server) cors(next http.Handler) http.Handler {
func noCache(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-cache")
// Die Leiste wird von fremden Ursprüngen geladen — das ist ihr Zweck.
// Die HoneyBar wird von fremden Ursprüngen geladen — das ist ihr Zweck.
// Apps, die selbst COEP „require-corp" setzen (alles mit WASM oder
// SharedArrayBuffer, etwa BentoPDF), lehnen sonst jede fremde Datei ab,
// die sich nicht ausdrücklich dazu bekennt. Ohne diese Zeile erscheint
// dort keine Leiste, und im Fehlerprotokoll steht nur ein Kürzel.
// dort keine HoneyBar, und im Fehlerprotokoll steht nur ein Kürzel.
w.Header().Set("Cross-Origin-Resource-Policy", "cross-origin")
next.ServeHTTP(w, r)
})
@@ -220,7 +220,7 @@ func noCache(next http.Handler) http.Handler {
// Der Grund ist eine Browserregel, keine Bequemlichkeit: Liegt HoneyOS auf
// einer anderen Site als die Apps, schickt der Browser die Sitzung bei der
// Anfrage aus einer App heraus nicht mit. Ohne einen zweiten Ausweis bekäme die
// Leiste dort nie eine Liste. Der Schlüssel steht im Skript-Tag der App und ist
// HoneyBar dort nie eine Liste. Der Schlüssel steht im Skript-Tag der App und ist
// damit nur für den lesbar, der ohnehin an die App herankommt.
func (s *Server) appsReadable(next func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -305,24 +305,27 @@ func (s *Server) handleSetSettings(w http.ResponseWriter, r *http.Request, sub s
}
// handleApps liefert die Liste **und** das Aussehen. Beides zusammen, weil die
// Leiste in einer fremden App genau eine Anfrage stellen kann: Sie liegt oft auf
// HoneyBar in einer fremden App genau eine Anfrage stellen kann: Sie liegt oft auf
// einer anderen Site, kommt also nur mit dem Schlüssel an Daten und hat keine
// Sitzung, aus der sich der Rest ergäbe.
//
// Welche Einstellungen? Die des Angemeldeten, wenn es einen gibt — sonst die des
// Standardnutzers. Bei mehreren Nutzern trägt die Leiste damit die Farbe des
// Standardnutzers. Bei mehreren Nutzern trägt die HoneyBar damit die Farbe des
// Standardnutzers; für eine Person stimmt es immer.
func (s *Server) handleApps(w http.ResponseWriter, r *http.Request, sub string) {
writeJSON(w, http.StatusOK, map[string]any{
"apps": s.store.Apps(),
"settings": s.store.SettingsFor(sub),
// Fuer das Systemmenue der HoneyBar: ohne Anbieter gibt es nichts
// abzumelden, dann steht der Punkt dort auch nicht.
"oidc": s.auth.Enabled(),
})
}
// handleWeather liefert das Wetter für den eingestellten Ort — oder nichts.
//
// „Nichts" ist hier ein 204 und kein Fehler: Kein Ort eingestellt ist der
// Normalfall, solange niemand einen gewählt hat, und die Leiste soll dafür
// Normalfall, solange niemand einen gewählt hat, und die HoneyBar soll dafür
// nicht rot blinken, sondern das Symbol einfach weglassen. Dasselbe gilt, wenn
// der Dienst nicht erreichbar ist: lieber kein Wetter als eine Zahl von gestern.
func (s *Server) handleWeather(w http.ResponseWriter, r *http.Request, sub string) {