diff options
Diffstat (limited to 'handlers')
| -rw-r--r-- | handlers/admin.go | 19 | ||||
| -rw-r--r-- | handlers/auth_login.go | 11 | ||||
| -rw-r--r-- | handlers/auth_token.go | 8 | ||||
| -rw-r--r-- | handlers/php_proxy.go | 2 | ||||
| -rw-r--r-- | handlers/user.go | 22 |
5 files changed, 22 insertions, 40 deletions
diff --git a/handlers/admin.go b/handlers/admin.go index 8413ac9..a568ac5 100644 --- a/handlers/admin.go +++ b/handlers/admin.go @@ -11,7 +11,6 @@ import ( "encoding/json" "fmt" "net/http" - "strconv" "sync" "time" ) @@ -43,8 +42,6 @@ func AdminPageHandler(w http.ResponseWriter, r *http.Request) { } } - - // GetUsersHandler returns a list of all users with enriched information. // It uses a worker pool to calculate extra information for each user in parallel. func GetUsersHandler(w http.ResponseWriter, r *http.Request) { @@ -71,8 +68,8 @@ func GetUsersHandler(w http.ResponseWriter, r *http.Request) { time.Sleep(5 * time.Millisecond) timeSinceLogin := "N/A" - if userCopy.LastLoginAt.Valid { - timeSinceLogin = fmt.Sprintf("%.0fm ago", time.Since(userCopy.LastLoginAt.Time).Minutes()) + if userCopy.LastLoginAt != nil { + timeSinceLogin = fmt.Sprintf("%.0fm ago", time.Since(*userCopy.LastLoginAt).Minutes()) } enrichedUsers[index] = types.EnrichedUser{ @@ -103,8 +100,8 @@ func UpdateUserRoleHandler(w http.ResponseWriter, r *http.Request) { } adminUsername := adminUser.Username - id, err := strconv.ParseInt(r.URL.Path[len(config.Paths.AdminUsersAPI+"/"):len(r.URL.Path)-len("/role")], 10, 64) - if err != nil { + id := r.URL.Path[len(config.Paths.AdminUsersAPI+"/") : len(r.URL.Path)-len("/role")] + if id == "" { logging.AppLog.Warn("Invalid user ID in request", "path", r.URL.Path, "ip", ip) http.Error(w, "Invalid user ID", http.StatusBadRequest) return @@ -148,8 +145,8 @@ func DeleteUserHandler(w http.ResponseWriter, r *http.Request) { } adminUsername := adminUser.Username - id, err := strconv.ParseInt(r.URL.Path[len(config.Paths.AdminUsersAPI+"/"):], 10, 64) - if err != nil { + id := r.URL.Path[len(config.Paths.AdminUsersAPI+"/"):] + if id == "" { logging.AppLog.Warn("Invalid user ID in request", "path", r.URL.Path, "ip", ip) http.Error(w, "Invalid user ID", http.StatusBadRequest) return @@ -177,8 +174,8 @@ func SetUserActiveStatusHandler(w http.ResponseWriter, r *http.Request) { } adminUsername := adminUser.Username - id, err := strconv.ParseInt(r.URL.Path[len(config.Paths.AdminUsersAPI+"/"):len(r.URL.Path)-len("/status")], 10, 64) - if err != nil { + id := r.URL.Path[len(config.Paths.AdminUsersAPI+"/") : len(r.URL.Path)-len("/status")] + if id == "" { logging.AppLog.Warn("Invalid user ID in request", "path", r.URL.Path, "ip", ip) http.Error(w, "Invalid user ID", http.StatusBadRequest) return diff --git a/handlers/auth_login.go b/handlers/auth_login.go index 33a3482..b0a288a 100644 --- a/handlers/auth_login.go +++ b/handlers/auth_login.go @@ -50,8 +50,8 @@ func authenticateUser(username, password, ip string) (*types.User, error) { } } - // Step 2: If the account is active, validate credentials. - if !models.CheckPasswordHash(password, user.PasswordHash) { + // Step 2: If the account is active, validate credentials against PocketBase. + if _, err := models.AuthenticateWithPassword(username, password); err != nil { // Record the failure if err := models.RecordLoginFailure(user.ID); err != nil { logging.AppLog.Error("Failed to record login failure", "error", err, "user_id", user.ID, "ip", ip) @@ -62,7 +62,7 @@ func authenticateUser(username, password, ip string) (*types.User, error) { maxAttempts := config.Paths.MaxLoginAttempts // Lock the account if max attempts are exceeded - if maxAttempts > 0 && updatedUser.FailedLogins >= maxAttempts { + if updatedUser != nil && maxAttempts > 0 && updatedUser.FailedLogins >= maxAttempts { if err := models.SetUserActiveStatus(user.ID, false); err != nil { logging.AppLog.Error("Failed to lock account", "error", err, "user_id", user.ID, "ip", ip) } @@ -77,6 +77,9 @@ func authenticateUser(username, password, ip string) (*types.User, error) { if err := models.RecordLoginSuccess(user.ID); err != nil { logging.AppLog.Error("Failed to record login success", "error", err, "user_id", user.ID, "ip", ip) } + if refreshedUser, refreshErr := models.GetUserByID(user.ID); refreshErr == nil && refreshedUser != nil { + user = refreshedUser + } logging.SecurityLog.Info("AUTH SUCCESS", "username", user.Username, "ip", ip) return user, nil @@ -148,7 +151,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { // --- Create Session Cookie --- duration := time.Duration(config.Paths.TokenDurationHours) * time.Hour - token, err := models.CreateAuthToken(user.ID, duration) + token, err := models.CreateAuthToken(user, duration) if err != nil { logging.AppLog.Error("Failed to create auth token", "error", err, "username", user.Username, "ip", ip) renderLoginWithError(w, r, "Could not create session.") diff --git a/handlers/auth_token.go b/handlers/auth_token.go index 7ea7ef6..a35a23b 100644 --- a/handlers/auth_token.go +++ b/handlers/auth_token.go @@ -49,7 +49,7 @@ func RefreshTokenHandler(w http.ResponseWriter, r *http.Request) { } // 4. Issue a new access token - newAccessToken, err := utils.GenerateJWT(user, time.Duration(config.Paths.AccessTokenDurationMinutes)*time.Minute) + newAccessToken, err := utils.GenerateJWT(user, time.Duration(config.Paths.AccessTokenDurationMinutes)*time.Minute, "access") if err != nil { logging.AppLog.Error("Failed to generate new access token", "error", err, "username", user.Username, "ip", ip) http.Error(w, "Internal Server Error", http.StatusInternalServerError) @@ -64,7 +64,7 @@ func RefreshTokenHandler(w http.ResponseWriter, r *http.Request) { } // 6. Issue a new refresh token - newRefreshToken, err := models.CreateRefreshToken(user.ID, time.Duration(config.Paths.RefreshTokenDurationDays)*24*time.Hour) + newRefreshToken, err := models.CreateRefreshToken(user, time.Duration(config.Paths.RefreshTokenDurationDays)*24*time.Hour) if err != nil { logging.AppLog.Error("Failed to create new refresh token", "error", err, "username", user.Username, "ip", ip) http.Error(w, "Internal Server Error", http.StatusInternalServerError) @@ -111,7 +111,7 @@ func TokenHandler(w http.ResponseWriter, r *http.Request) { // --- Issue Tokens --- // Access Token - accessToken, err := utils.GenerateJWT(user, time.Duration(config.Paths.AccessTokenDurationMinutes)*time.Minute) + accessToken, err := utils.GenerateJWT(user, time.Duration(config.Paths.AccessTokenDurationMinutes)*time.Minute, "access") if err != nil { logging.AppLog.Error("Failed to generate access token", "error", err, "username", user.Username, "ip", ip) http.Error(w, "Failed to generate access token", http.StatusInternalServerError) @@ -119,7 +119,7 @@ func TokenHandler(w http.ResponseWriter, r *http.Request) { } // Refresh Token - refreshToken, err := models.CreateRefreshToken(user.ID, time.Duration(config.Paths.RefreshTokenDurationDays)*24*time.Hour) + refreshToken, err := models.CreateRefreshToken(user, time.Duration(config.Paths.RefreshTokenDurationDays)*24*time.Hour) if err != nil { logging.AppLog.Error("Failed to create refresh token", "error", err, "username", user.Username, "ip", ip) http.Error(w, "Failed to create refresh token", http.StatusInternalServerError) diff --git a/handlers/php_proxy.go b/handlers/php_proxy.go index 3c6c597..1a394f7 100644 --- a/handlers/php_proxy.go +++ b/handlers/php_proxy.go @@ -143,4 +143,4 @@ func NewPhpProxyHandler(scriptName string) http.Handler { logging.AppLog.Error("Failed to copy response body from PHP-FPM", "error", err) } }) -}
\ No newline at end of file +} diff --git a/handlers/user.go b/handlers/user.go index 65ebe83..ad68f6f 100644 --- a/handlers/user.go +++ b/handlers/user.go @@ -83,16 +83,7 @@ func ChangePasswordHandler(w http.ResponseWriter, r *http.Request) { return } - dbUser, err := models.GetUserByID(user.ID) - if err != nil || dbUser == nil { - w.WriteHeader(http.StatusInternalServerError) - if err := json.NewEncoder(w).Encode(map[string]string{"error": "Could not retrieve user data."}); err != nil { - logging.AppLog.Error("Failed to encode json error response", "error", err) - } - return - } - - if !models.CheckPasswordHash(currentPassword, dbUser.PasswordHash) { + if _, err := models.AuthenticateWithPassword(user.Username, currentPassword); err != nil { w.WriteHeader(http.StatusUnauthorized) if err := json.NewEncoder(w).Encode(map[string]string{"error": "Current password is incorrect."}); err != nil { logging.AppLog.Error("Failed to encode json error response", "error", err) @@ -100,16 +91,7 @@ func ChangePasswordHandler(w http.ResponseWriter, r *http.Request) { return } - newPasswordHash, err := models.HashPassword(newPassword) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - if err := json.NewEncoder(w).Encode(map[string]string{"error": "Failed to process new password."}); err != nil { - logging.AppLog.Error("Failed to encode json error response", "error", err) - } - return - } - - if err := models.UpdateUserPassword(dbUser.ID, newPasswordHash); err != nil { + if err := models.ChangeUserPassword(user.ID, currentPassword, newPassword); err != nil { w.WriteHeader(http.StatusInternalServerError) if err := json.NewEncoder(w).Encode(map[string]string{"error": "Failed to update password."}); err != nil { logging.AppLog.Error("Failed to encode json error response", "error", err) |
