middleware.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package fever // import "miniflux.app/v2/internal/fever"
  4. import (
  5. "context"
  6. "log/slog"
  7. "net/http"
  8. "miniflux.app/v2/internal/http/request"
  9. "miniflux.app/v2/internal/http/response/json"
  10. "miniflux.app/v2/internal/storage"
  11. )
  12. type middleware struct {
  13. store *storage.Storage
  14. }
  15. func newMiddleware(s *storage.Storage) *middleware {
  16. return &middleware{s}
  17. }
  18. func (m *middleware) serve(next http.Handler) http.Handler {
  19. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  20. clientIP := request.ClientIP(r)
  21. apiKey := r.FormValue("api_key")
  22. if apiKey == "" {
  23. slog.Warn("[Fever] No API key provided",
  24. slog.Bool("authentication_failed", true),
  25. slog.String("client_ip", clientIP),
  26. slog.String("user_agent", r.UserAgent()),
  27. )
  28. json.OK(w, r, newAuthFailureResponse())
  29. return
  30. }
  31. user, err := m.store.UserByFeverToken(apiKey)
  32. if err != nil {
  33. slog.Error("[Fever] Unable to fetch user by API key",
  34. slog.Bool("authentication_failed", true),
  35. slog.String("client_ip", clientIP),
  36. slog.String("user_agent", r.UserAgent()),
  37. slog.Any("error", err),
  38. )
  39. json.OK(w, r, newAuthFailureResponse())
  40. return
  41. }
  42. if user == nil {
  43. slog.Warn("[Fever] No user found with the API key provided",
  44. slog.Bool("authentication_failed", true),
  45. slog.String("client_ip", clientIP),
  46. slog.String("user_agent", r.UserAgent()),
  47. )
  48. json.OK(w, r, newAuthFailureResponse())
  49. return
  50. }
  51. slog.Info("[Fever] User authenticated successfully",
  52. slog.Bool("authentication_successful", true),
  53. slog.String("client_ip", clientIP),
  54. slog.String("user_agent", r.UserAgent()),
  55. slog.Int64("user_id", user.ID),
  56. slog.String("username", user.Username),
  57. )
  58. m.store.SetLastLogin(user.ID)
  59. ctx := r.Context()
  60. ctx = context.WithValue(ctx, request.UserIDContextKey, user.ID)
  61. ctx = context.WithValue(ctx, request.UserTimezoneContextKey, user.Timezone)
  62. ctx = context.WithValue(ctx, request.IsAdminUserContextKey, user.IsAdmin)
  63. ctx = context.WithValue(ctx, request.IsAuthenticatedContextKey, true)
  64. next.ServeHTTP(w, r.WithContext(ctx))
  65. })
  66. }