package web import ( "bytes" "encoding/binary" "fmt" "html/template" "log/slog" "net/http" "strings" "time" "tug/internal/transport/web/text" ) const ( flashCookie = "__Host-authsvc_flash" flashTTL = 60 * time.Second ) func (k *Kit) SetFlash(w http.ResponseWriter, key text.Key, v Ident) error { if !key.IsFlash() { return fmt.Errorf("web: %q is not a flash key", key) } if _, err := lookup(key); err != nil { return err } setCookie(w, flashCookie, k.sealFlash(key, v, k.now()), int(flashTTL/time.Second)) return nil } func (k *Kit) sealFlash(key text.Key, v Ident, now time.Time) string { payload := binary.BigEndian.AppendUint64(nil, uint64(now.Add(flashTTL).Unix())) payload = append(payload, key...) payload = append(payload, 0) payload = append(payload, v...) return seal(k.keys.flash, payload) } func (k *Kit) takeFlash(w http.ResponseWriter, r *http.Request) template.HTML { c, err := r.Cookie(flashCookie) if err != nil { return "" } setCookie(w, flashCookie, "", -1) payload, err := unseal(k.keys.flash, c.Value) if err != nil || len(payload) < 9 || k.now().Unix() > int64(binary.BigEndian.Uint64(payload[:8])) { return "" } key, v, _ := bytes.Cut(payload[8:], []byte{0}) fk := text.Key(key) if !fk.IsFlash() { return "" } s, err := lookup(fk) if err != nil { return "" } if !strings.Contains(s, identMarker) { return template.HTML(template.HTMLEscapeString(s)) } out, err := translate(fk, Ident(v)) if err != nil || len(v) == 0 { slog.Warn("flash not shown", "key", string(fk)) return "" } return out }