diff --git a/internal/fever/handler.go b/internal/fever/handler.go index 4b5f21b4..e13502ef 100644 --- a/internal/fever/handler.go +++ b/internal/fever/handler.go @@ -25,7 +25,9 @@ func Serve(router *mux.Router, store *storage.Storage) { handler := &handler{store, router} sr := router.PathPrefix("/fever").Subrouter() - sr.Use(newMiddleware(store).serve) + middleware := newMiddleware(store) + sr.Use(middleware.maybeUnauthorizedFever) + sr.Use(middleware.serve) sr.HandleFunc("/", handler.serve).Name("feverEndpoint") } diff --git a/internal/fever/middleware.go b/internal/fever/middleware.go index dfa6c0a1..3478856d 100644 --- a/internal/fever/middleware.go +++ b/internal/fever/middleware.go @@ -9,6 +9,7 @@ import ( "net/http" "miniflux.app/v2/internal/http/request" + "miniflux.app/v2/internal/http/response" "miniflux.app/v2/internal/http/response/json" "miniflux.app/v2/internal/storage" ) @@ -21,6 +22,29 @@ func newMiddleware(s *storage.Storage) *middleware { return &middleware{s} } +func (m *middleware) maybeUnauthorizedFever(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + feverUsed, err := m.store.IsFeverUsed() + if err != nil { + builder := response.New(w, r) + builder.WithStatus(http.StatusInternalServerError) + builder.WithHeader("Content-Type", "text/plain") + builder.Write() + return + } + + if !feverUsed { + builder := response.New(w, r) + builder.WithStatus(http.StatusUnauthorized) + builder.WithHeader("Content-Type", "text/plain") + builder.Write() + return + } + + next.ServeHTTP(w, r) + }) +} + func (m *middleware) serve(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { clientIP := request.ClientIP(r) diff --git a/internal/googlereader/handler.go b/internal/googlereader/handler.go index 28090b5b..154ef83d 100644 --- a/internal/googlereader/handler.go +++ b/internal/googlereader/handler.go @@ -49,6 +49,7 @@ func Serve(router *mux.Router, store *storage.Storage) { sr := router.PathPrefix("/reader/api/0").Subrouter() sr.Use(middleware.handleCORS) sr.Use(middleware.apiKeyAuth) + sr.Use(middleware.maybeUnauthorizedGoogleReader) sr.Methods(http.MethodOptions) sr.HandleFunc("/token", handler.tokenHandler).Methods(http.MethodGet).Name("Token") sr.HandleFunc("/edit-tag", handler.editTagHandler).Methods(http.MethodPost).Name("EditTag") diff --git a/internal/googlereader/middleware.go b/internal/googlereader/middleware.go index 86d08226..49ddeff5 100644 --- a/internal/googlereader/middleware.go +++ b/internal/googlereader/middleware.go @@ -25,6 +25,22 @@ func newMiddleware(s *storage.Storage) *middleware { return &middleware{s} } +func (m *middleware) maybeUnauthorizedGoogleReader(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + googleReaderUsed, err := m.store.IsGoogleReaderUsed() + if err != nil { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusInternalServerError) + return + } + if googleReaderUsed { + next.ServeHTTP(w, r) + } else { + sendUnauthorizedResponse(w) + } + }) +} + func (m *middleware) handleCORS(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") diff --git a/internal/storage/integration.go b/internal/storage/integration.go index 761a8dd8..b56bffbb 100644 --- a/internal/storage/integration.go +++ b/internal/storage/integration.go @@ -52,6 +52,21 @@ func (s *Storage) UserByFeverToken(token string) (*model.User, error) { } } +func (s *Storage) IsFeverUsed() (bool, error) { + query := `SELECT true FROM integrations WHERE fever_enabled=true LIMIT 1` + result := false + err := s.db.QueryRow(query).Scan(&result) + + if err != nil { + if err == sql.ErrNoRows { + return false, nil + } + return false, fmt.Errorf(`store: unable to check if fever is used: %v`, err) + } + + return result, nil +} + // GoogleReaderUserCheckPassword validates the Google Reader hashed password. func (s *Storage) GoogleReaderUserCheckPassword(username, password string) error { var hash string @@ -105,6 +120,21 @@ func (s *Storage) GoogleReaderUserGetIntegration(username string) (*model.Integr return &integration, nil } +func (s *Storage) IsGoogleReaderUsed() (bool, error) { + query := `SELECT true FROM integrations WHERE googlereader_enabled=true LIMIT 1` + var result bool + err := s.db.QueryRow(query).Scan(&result) + + if err != nil { + if err == sql.ErrNoRows { + return false, nil + } + return false, fmt.Errorf(`store: unable to check if Google Reader is used: %v`, err) + } + + return result, nil +} + // Integration returns user integration settings. func (s *Storage) Integration(userID int64) (*model.Integration, error) { query := `