62 lines
2.4 KiB
Go
62 lines
2.4 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/krow/krow-backend/go-api/internal/authctx"
|
|
"github.com/krow/krow-backend/go-api/internal/domain"
|
|
"github.com/krow/krow-backend/go-api/internal/owliver"
|
|
)
|
|
|
|
// routeOwliver registers the Owliver panel's suggestion endpoint.
|
|
//
|
|
// GET, and a query string rather than a body, because the request is a read
|
|
// with no side effect and the panel issues one per keystroke: a GET is what
|
|
// makes it retryable, cancellable and cacheable by anything in front of it.
|
|
//
|
|
// It is deliberately NOT on the publicPaths allowlist in auth.go. Which
|
|
// readings exist depends on the caller's role, so an anonymous suggestion has
|
|
// no meaning — and the allowlist's failure mode is a route that refuses
|
|
// everyone, which is the direction this should fall in.
|
|
func (s *Server) routeOwliver(mux *http.ServeMux) int {
|
|
mux.HandleFunc("GET /api/v1/owliver/suggestions", s.handleOwliverSuggestions)
|
|
return 1
|
|
}
|
|
|
|
// suggestionsBody is the payload inside the standard data envelope.
|
|
//
|
|
// An object rather than a bare array, so the response has somewhere to grow — a
|
|
// future `truncated` or `context` field would otherwise be a breaking change to
|
|
// a client already reading `data` as a list.
|
|
type suggestionsBody struct {
|
|
Suggestions []owliver.Suggestion `json:"suggestions"`
|
|
}
|
|
|
|
// handleOwliverSuggestions answers what the caller could usefully ask here.
|
|
//
|
|
// There is no s.authorize call and no policy lookup in this handler, and that
|
|
// is the design rather than an omission: this endpoint exposes no resource, so
|
|
// there is no operation to gate. Authorization happens per suggestion, inside
|
|
// the catalogue, against the same domain.Policy table every other endpoint
|
|
// consults — a reading the caller could not perform is never ranked, so it
|
|
// cannot be returned. Authentication is upstream, in the middleware.
|
|
func (s *Server) handleOwliverSuggestions(w http.ResponseWriter, r *http.Request) {
|
|
ident, err := authctx.MustFrom(r.Context())
|
|
if err != nil {
|
|
// Unreachable: the middleware refuses an unauthenticated request before
|
|
// the router sees it. A missing identity here is a wiring bug.
|
|
writeError(w, s.log, domain.Internal(err))
|
|
return
|
|
}
|
|
|
|
params, err := s.suggestions.ParseParams(r.URL.Query())
|
|
if err != nil {
|
|
writeError(w, s.log, err)
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, envelope{
|
|
Data: suggestionsBody{Suggestions: s.suggestions.Suggest(r.Context(), ident, params)},
|
|
})
|
|
}
|