diff --git a/cmd/autobrr/main.go b/cmd/autobrr/main.go index bf7219f..f56b078 100644 --- a/cmd/autobrr/main.go +++ b/cmd/autobrr/main.go @@ -114,6 +114,7 @@ func main() { go func() { httpServer := http.NewServer( + log, cfg.Config, serverEvents, db, diff --git a/internal/auth/service.go b/internal/auth/service.go index bfb8407..051e703 100644 --- a/internal/auth/service.go +++ b/internal/auth/service.go @@ -2,14 +2,14 @@ package auth import ( "context" - "errors" - - "github.com/autobrr/autobrr/internal/logger" - "github.com/rs/zerolog" "github.com/autobrr/autobrr/internal/domain" + "github.com/autobrr/autobrr/internal/logger" "github.com/autobrr/autobrr/internal/user" "github.com/autobrr/autobrr/pkg/argon2id" + + "github.com/pkg/errors" + "github.com/rs/zerolog" ) type Service interface { @@ -47,7 +47,7 @@ func (s *service) Login(ctx context.Context, username, password string) (*domain } if u == nil { - return nil, errors.New("bad credentials") + return nil, errors.Errorf("invalid login: %s", username) } // compare password from request and the saved password diff --git a/internal/database/user.go b/internal/database/user.go index 2927918..d66ab97 100644 --- a/internal/database/user.go +++ b/internal/database/user.go @@ -2,6 +2,7 @@ package database import ( "context" + "database/sql" "github.com/autobrr/autobrr/internal/domain" "github.com/autobrr/autobrr/internal/logger" @@ -63,6 +64,10 @@ func (r *UserRepo) FindByUsername(ctx context.Context, username string) (*domain var user domain.User if err := row.Scan(&user.ID, &user.Username, &user.Password); err != nil { + if err == sql.ErrNoRows { + return nil, nil + } + return nil, errors.Wrap(err, "error scanning row") } diff --git a/internal/http/auth.go b/internal/http/auth.go index a4ae9c9..f9cdad4 100644 --- a/internal/http/auth.go +++ b/internal/http/auth.go @@ -5,10 +5,11 @@ import ( "encoding/json" "net/http" + "github.com/autobrr/autobrr/internal/domain" + "github.com/go-chi/chi/v5" "github.com/gorilla/sessions" - - "github.com/autobrr/autobrr/internal/domain" + "github.com/rs/zerolog" ) type authService interface { @@ -18,6 +19,7 @@ type authService interface { } type authHandler struct { + log zerolog.Logger encoder encoder config *domain.Config service authService @@ -25,8 +27,9 @@ type authHandler struct { cookieStore *sessions.CookieStore } -func newAuthHandler(encoder encoder, config *domain.Config, cookieStore *sessions.CookieStore, service authService) *authHandler { +func newAuthHandler(encoder encoder, log zerolog.Logger, config *domain.Config, cookieStore *sessions.CookieStore, service authService) *authHandler { return &authHandler{ + log: log, encoder: encoder, config: config, service: service, @@ -72,6 +75,7 @@ func (h authHandler) login(w http.ResponseWriter, r *http.Request) { _, err := h.service.Login(ctx, data.Username, data.Password) if err != nil { + h.log.Error().Err(err).Msgf("invalid login [%s] from: %s", ReadUserIP(r)) h.encoder.StatusResponse(ctx, w, nil, http.StatusUnauthorized) return } @@ -155,3 +159,14 @@ func (h authHandler) validate(w http.ResponseWriter, r *http.Request) { // send empty response as ok h.encoder.StatusResponse(ctx, w, nil, http.StatusNoContent) } + +func ReadUserIP(r *http.Request) string { + IPAddress := r.Header.Get("X-Real-Ip") + if IPAddress == "" { + IPAddress = r.Header.Get("X-Forwarded-For") + } + if IPAddress == "" { + IPAddress = r.RemoteAddr + } + return IPAddress +} diff --git a/internal/http/server.go b/internal/http/server.go index 944d047..5fa417d 100644 --- a/internal/http/server.go +++ b/internal/http/server.go @@ -8,6 +8,7 @@ import ( "github.com/autobrr/autobrr/internal/database" "github.com/autobrr/autobrr/internal/domain" + "github.com/autobrr/autobrr/internal/logger" "github.com/autobrr/autobrr/web" "github.com/go-chi/chi/v5" @@ -15,9 +16,11 @@ import ( "github.com/gorilla/sessions" "github.com/r3labs/sse/v2" "github.com/rs/cors" + "github.com/rs/zerolog" ) type Server struct { + log zerolog.Logger sse *sse.Server db *database.DB @@ -40,8 +43,9 @@ type Server struct { releaseService releaseService } -func NewServer(config *domain.Config, sse *sse.Server, db *database.DB, version string, commit string, date string, actionService actionService, apiService apikeyService, authService authService, downloadClientSvc downloadClientService, filterSvc filterService, feedSvc feedService, indexerSvc indexerService, ircSvc ircService, notificationSvc notificationService, releaseSvc releaseService) Server { +func NewServer(log logger.Logger, config *domain.Config, sse *sse.Server, db *database.DB, version string, commit string, date string, actionService actionService, apiService apikeyService, authService authService, downloadClientSvc downloadClientService, filterSvc filterService, feedSvc feedService, indexerSvc indexerService, ircSvc ircService, notificationSvc notificationService, releaseSvc releaseService) Server { return Server{ + log: log.With().Str("module", "http").Logger(), config: config, sse: sse, db: db, @@ -109,7 +113,7 @@ func (s Server) Handler() http.Handler { fileSystem.ServeHTTP(w, r) }) - r.Route("/api/auth", newAuthHandler(encoder, s.config, s.cookieStore, s.authService).Routes) + r.Route("/api/auth", newAuthHandler(encoder, s.log, s.config, s.cookieStore, s.authService).Routes) r.Route("/api/healthz", newHealthHandler(encoder, s.db).Routes) r.Group(func(r chi.Router) {