fix: das Aussehen erreicht die Leiste auch über die Site-Grenze
Marcs Frage: gilt die Einstellung vom Rechner auch für die Leiste am Handy? Sie hätte es nicht getan, sobald HONEYOS_USER_HEADER gesetzt ist: die Einstellungen liegen dann unter "proxy:marc", die Leiste fragt aber ohne Sitzung und landet beim Standardnutzer — dessen Satz ist leer, die Leiste wäre bernsteinfarben geblieben, während der Schreibtisch grün leuchtet. SettingsFor() hilft nach: gibt es genau einen Nutzer mit Einstellungen, gelten dessen. Bei mehreren bleibt es beim Standard, dann ist nicht zu erraten, wer da schaut. Nachgestellt mit einem Pixel-7-Profil ohne jedes Cookie: die Leiste kommt grün an. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5cf210ae97
commit
b4dcb74404
3 files changed
+88
-2
No files matched your search
@@ -595,3 +595,54 @@ func TestVersionKommtVomServer(t *testing.T) {
|
||||
t.Error("os.js trägt wieder eine eigene Version — die läuft mit den Image-Tags auseinander")
|
||||
}
|
||||
}
|
||||
|
||||
// Der Fall, nach dem Marc gefragt hat: Einstellungen am Rechner setzen, und die
|
||||
// Leiste am Handy trägt dieselbe Farbe. Sie fragt über die Site-Grenze, landet
|
||||
// also beim Standardnutzer — die Einstellungen können aber unter einem Namen
|
||||
// aus der Proxy-Kopfzeile liegen.
|
||||
func TestLeisteFindetDasAussehenAuchÜberDieSiteGrenze(t *testing.T) {
|
||||
s := proxyServer(t, Config{ProxyAuth: true, UserHeader: "Remote-User", AppsKey: "geheim123"})
|
||||
h := s.routes()
|
||||
|
||||
// Am Rechner, durch den Proxy: grün.
|
||||
req := httptest.NewRequest("PUT", "/api/settings", strings.NewReader(`{"phosphor":"green"}`))
|
||||
req.Header.Set("Remote-User", "marc")
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusNoContent {
|
||||
t.Fatalf("speichern: %d", rec.Code)
|
||||
}
|
||||
|
||||
// Am Handy fragt die Leiste nur mit dem Schlüssel — ohne Namen.
|
||||
req = httptest.NewRequest("GET", "/api/apps", nil)
|
||||
req.Header.Set("X-HoneyOS-Key", "geheim123")
|
||||
rec = httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
|
||||
var got struct{ Settings map[string]string }
|
||||
_ = json.Unmarshal(rec.Body.Bytes(), &got)
|
||||
if got.Settings["phosphor"] != "green" {
|
||||
t.Fatalf("die Leiste bekäme %q statt grün — auf dem Handy bliebe sie bernstein", got.Settings["phosphor"])
|
||||
}
|
||||
}
|
||||
|
||||
// Bei mehreren Nutzern darf nicht geraten werden, wessen Farbe gilt.
|
||||
func TestBeiMehrerenNutzernWirdNichtGeraten(t *testing.T) {
|
||||
s := proxyServer(t, Config{ProxyAuth: true, UserHeader: "Remote-User", AppsKey: "geheim123"})
|
||||
for name, farbe := range map[string]string{"marc": "green", "gast": "ice"} {
|
||||
if err := s.store.SetSettings("proxy:"+name, map[string]string{"phosphor": farbe}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
req := httptest.NewRequest("GET", "/api/apps", nil)
|
||||
req.Header.Set("X-HoneyOS-Key", "geheim123")
|
||||
rec := httptest.NewRecorder()
|
||||
s.routes().ServeHTTP(rec, req)
|
||||
|
||||
var got struct{ Settings map[string]string }
|
||||
_ = json.Unmarshal(rec.Body.Bytes(), &got)
|
||||
if got.Settings["phosphor"] != "" {
|
||||
t.Errorf("es wurde geraten: %q", got.Settings["phosphor"])
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ const localSub = "local"
|
||||
// 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 = "0.5"
|
||||
const Version = "0.6"
|
||||
|
||||
type Config struct {
|
||||
Addr string
|
||||
@@ -335,7 +335,7 @@ func (s *Server) handleSetSettings(w http.ResponseWriter, r *http.Request, sub s
|
||||
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.User(sub).Settings,
|
||||
"settings": s.store.SettingsFor(sub),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -208,6 +208,41 @@ func (s *Store) SetSettings(sub string, in map[string]string) error {
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// SettingsFor liefert das Aussehen für sub — und hilft nach, wenn die Frage
|
||||
// über eine Site-Grenze kam.
|
||||
//
|
||||
// Die Leiste in einer fremden App weist sich nur mit dem Schlüssel aus, nicht
|
||||
// mit einer Sitzung: der Browser schickt das Cookie dorthin nicht mit. Sie
|
||||
// landet deshalb beim Standardnutzer. Sind die Einstellungen aber unter einem
|
||||
// Namen aus der Proxy-Kopfzeile gespeichert, wäre der leer — und die Leiste
|
||||
// bliebe bernsteinfarben, während der Schreibtisch grün leuchtet.
|
||||
//
|
||||
// Gibt es genau einen Nutzer mit Einstellungen, gilt dessen Aussehen. Bei
|
||||
// mehreren bleibt es beim Standard: dann ist nicht zu erraten, wer da schaut.
|
||||
func (s *Store) SettingsFor(sub string) map[string]string {
|
||||
if own := s.User(sub).Settings; len(own) > 0 {
|
||||
return own
|
||||
}
|
||||
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
var einziger map[string]string
|
||||
for _, u := range s.d.Users {
|
||||
if len(u.Settings) == 0 {
|
||||
continue
|
||||
}
|
||||
if einziger != nil {
|
||||
return map[string]string{} // mehrere — kein Rateweg
|
||||
}
|
||||
einziger = u.Settings
|
||||
}
|
||||
out := map[string]string{}
|
||||
for k, v := range einziger {
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// AppOrigins nennt die Ursprünge der eingetragenen Apps. Nur sie dürfen die
|
||||
// Leiste mit Anmeldedaten abfragen — die Liste ist damit ihre eigene Freigabe.
|
||||
func (s *Store) AppOrigins() map[string]bool {
|
||||
|
||||
Reference in new issue
Block a user