package api import ( "context" "fmt" "net/http" "time" "dns.froth.zone/pomme/internal" "dns.froth.zone/pomme/internal/db" "github.com/go-chi/httplog" "github.com/go-chi/render" "gorm.io/gorm" ) var mode string // setDBMiddleware is the http Handler func for the GORM middleware with context. func setDBMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var ( pommeDB *gorm.DB ok bool ) c, err := internal.ReadConfig() if err != nil { logger := newResponder(Response[any]{ Message: "No config file defined", Err: err.Error(), }) logger.writeLogEntry() } pommeDB, err, ok = db.InitDb(c.DB, mode) if err != nil && !ok { logger := newResponder(Response[any]{ Message: "Error initializing DB", Err: err.Error(), }) logger.writeLogEntry() err = internal.SysKill() if err != nil { panic("this should not happen.") } } timeoutContext, cancelContext := context.WithTimeout(context.Background(), time.Second) ctx := context.WithValue(r.Context(), keyPrincipalContextID, pommeDB.WithContext(timeoutContext)) defer cancelContext() next.ServeHTTP(w, r.WithContext(ctx)) }) } // apiError sends unsuccessful API requests back to the user with the appropriate information. func (e *Response[T]) apiError(w http.ResponseWriter, r *http.Request) { v := map[string]any{ "message": e.Message, "status": e.Status, "realm": e.Realm, "error": e.Err, } w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("Content-Type", "application/json; charset=utf-8") switch v["realm"] { default: w.Header().Add("WWW-Authenticate", fmt.Sprintf(`realm="%v"`, e.Realm)) delete(v, "realm") fallthrough case nil: w.Header().Add("API Error", v["message"].(string)) } w.WriteHeader(v["status"].(int)) delete(v, "error") delete(v, "status") delete(v, "realm") render.JSON(w, r, v) } // writeLogEntry takes a response struct and writes info and error level logs // todo: make it write to file maybe func (e *Response[T]) writeLogEntry() { v := map[string]any{ "message": e.Message, "error": e.Err, } logger := httplog.NewLogger("Pomme", httplog.Options{ JSON: true, }) switch v["error"] { default: logger.Error().Msg(v["error"].(string)) fallthrough case nil: logger.Info().Msg(v["message"].(string)) } }