Files
Felis/internal/api/handlers_auth_owner.go
T
Lemon-miaow efbbe27629 feat: initialize panel access before linking Minecraft accounts
Configure connection and storage before creating or resuming the one-time Owner login. Remove Minecraft prerequisites from setup and preserve established login credentials.

Let staff preview and confirm roles from configured authentication sources using the existing account-link storage and game UUID mapping. Retain in-game code proof for players, add client-version and lobby guidance, and support NodePort passkey origins.
2026-10-04 03:05:05 +08:00

44 lines
1.7 KiB
Go

package api
import (
"log"
"net/http"
)
// Pre-session install-state probe. Until `felis setup` creates an Owner, local sign-in is
// off and every login door answers 403 local_auth_disabled, so the sign-in page would
// offer four doors that all fail. This Public route lets the page say instead that no
// Owner exists yet and how to bind one.
//
// It discloses one bit: whether the install is still unclaimed. Claiming it needs root
// on the host (`felis setup` or the break-glass console); no web door works before then, so knowing the
// bit gives a remote caller nothing to act on. It must answer while local auth is off,
// so unlike its sibling doors it is not gated on local_auth_enabled.
//
// The first true is cached in API.ownerBound. An Owner is never unbound through the
// product, so from then on the probe costs no query; before it, each call is one
// indexed LIMIT 1 read. It is not an AuthDoor: the page polls it on every load, and
// sharing the doors' per-address bucket would throttle the sign-in that follows.
type ownerStatusView struct {
OwnerBound bool `json:"owner_bound"`
}
// handleOwnerStatus reports whether any staff account exists. A store failure is a 503,
// so the page falls back to its normal doors rather than claiming the install is unbound.
func (a *API) handleOwnerStatus(w http.ResponseWriter, r *http.Request) {
if a.ownerBound.Load() {
writeJSON(w, http.StatusOK, ownerStatusView{OwnerBound: true})
return
}
bound, err := a.Repo.AdminExists(r.Context())
if err != nil {
log.Printf("owner status: %v", err)
writeError(w, r, errAuthUnavailable)
return
}
if bound {
a.ownerBound.Store(true)
}
writeJSON(w, http.StatusOK, ownerStatusView{OwnerBound: bound})
}