package gateway // push_routes.go provides the always-registered push HTTP entrypoints. // When the gateway has no push provider configured (no NtfyBaseURL, // no ExpoAccessToken, etc. — and therefore no g.pushHandlers), these // methods return a canonical 503 envelope instead of letting the route // fall through to the default 404 handler. // // Bug #220: tenants saw `404 Page Not Found` on /v1/push/devices and // couldn't tell whether the path was wrong or push wasn't enabled. // 503 + a clear message points operators directly at the config knob. import ( "net/http" "github.com/DeBrosOfficial/network/pkg/httputil" ) // pushNotConfiguredMessage is the human-readable 503 body. Same text // reused by every push entrypoint so operators see consistent guidance. const pushNotConfiguredMessage = "push notifications are not configured on this namespace gateway. " + "Set `ntfy_base_url` or `expo_access_token` in the gateway config and restart, " + "then call this endpoint again. See core/docs/SERVERLESS.md for details." // pushDevicesHandler dispatches GET (list) / POST (register) on // /v1/push/devices. Returns 503 when push isn't configured. func (g *Gateway) pushDevicesHandler(w http.ResponseWriter, r *http.Request) { if g.pushHandlers == nil { httputil.WriteRPCError(w, http.StatusServiceUnavailable, httputil.ErrCodeServiceUnavailable, pushNotConfiguredMessage) return } switch r.Method { case http.MethodGet: g.pushHandlers.ListDevicesHandler(w, r) case http.MethodPost: g.pushHandlers.RegisterDeviceHandler(w, r) default: httputil.WriteRPCError(w, http.StatusMethodNotAllowed, httputil.ErrCodeValidationFailed, "method not allowed: use GET to list or POST to register") } } // pushDevicesByIDHandler handles DELETE /v1/push/devices/{id}. Returns // 503 when push isn't configured. func (g *Gateway) pushDevicesByIDHandler(w http.ResponseWriter, r *http.Request) { if g.pushHandlers == nil { httputil.WriteRPCError(w, http.StatusServiceUnavailable, httputil.ErrCodeServiceUnavailable, pushNotConfiguredMessage) return } g.pushHandlers.DeleteDeviceHandler(w, r) } // pushSendHandler handles POST /v1/push/send. Returns 503 when push // isn't configured. func (g *Gateway) pushSendHandler(w http.ResponseWriter, r *http.Request) { if g.pushHandlers == nil { httputil.WriteRPCError(w, http.StatusServiceUnavailable, httputil.ErrCodeServiceUnavailable, pushNotConfiguredMessage) return } g.pushHandlers.SendHandler(w, r) } // pushConfigHandler dispatches GET / PUT / DELETE on /v1/push/config — the // tenant-self-service entrypoint for per-namespace push provider config // (bug #220 follow-up). When push is fully disabled returns 503 with the // same actionable message as the device endpoints. func (g *Gateway) pushConfigHandler(w http.ResponseWriter, r *http.Request) { if g.pushHandlers == nil { httputil.WriteRPCError(w, http.StatusServiceUnavailable, httputil.ErrCodeServiceUnavailable, pushNotConfiguredMessage) return } switch r.Method { case http.MethodGet: g.pushHandlers.GetConfigHandler(w, r) case http.MethodPut, http.MethodPost: g.pushHandlers.PutConfigHandler(w, r) case http.MethodDelete: g.pushHandlers.DeleteConfigHandler(w, r) default: httputil.WriteRPCError(w, http.StatusMethodNotAllowed, httputil.ErrCodeValidationFailed, "method not allowed: use GET to read, PUT to update, or DELETE to clear") } } // pushCredentialsSummaryHandler — GET /v1/namespace/push-credentials. // Returns the list of providers with credentials stored AND the list of // providers this gateway supports (feature #72). 503 when push isn't // configured at all. func (g *Gateway) pushCredentialsSummaryHandler(w http.ResponseWriter, r *http.Request) { if g.pushHandlers == nil { httputil.WriteRPCError(w, http.StatusServiceUnavailable, httputil.ErrCodeServiceUnavailable, pushNotConfiguredMessage) return } g.pushHandlers.CredentialsSummaryHandler(w, r) } // pushCredentialsByProviderHandler dispatches GET / PUT / DELETE on // /v1/namespace/push-credentials/{provider} (feature #72 — generic // per-provider credential storage). The {provider} segment is parsed // inside the handler so unknown providers return a 400 with the list // of supported ones rather than a bare 404. func (g *Gateway) pushCredentialsByProviderHandler(w http.ResponseWriter, r *http.Request) { if g.pushHandlers == nil { httputil.WriteRPCError(w, http.StatusServiceUnavailable, httputil.ErrCodeServiceUnavailable, pushNotConfiguredMessage) return } g.pushHandlers.CredentialsByProviderHandler(w, r) }