package handlers import ( "net/http" "strconv" "github.com/gin-gonic/gin" "building-mgmt/internal/repository" ) // Пагинация списков: одинаковые параметры limit/offset/sort/order // у всех GET-списков, поэтому разбор вынесен отдельно. // Словари сортировок приходят из repository — того же источника, // что и ORDER BY в SQL: валидация и запрос не могут разъехаться. // parsePage разбирает параметры страницы. Возвращает ok=false после // ответа 400 — вызывающий хендлер обязан сразу вернуться. func parsePage(c *gin.Context, sorts map[string]repository.SortSpec) (repository.Page, bool) { page := repository.Page{ Limit: repository.DefaultLimit, Sort: c.Query("sort"), Order: c.Query("order"), } if v := c.Query("limit"); v != "" { n, err := strconv.Atoi(v) if err != nil || n < 1 || n > repository.MaxLimit { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid limit"}) return page, false } page.Limit = n } if v := c.Query("offset"); v != "" { n, err := strconv.Atoi(v) if err != nil || n < 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid offset"}) return page, false } page.Offset = n } if page.Order != "" && page.Order != "asc" && page.Order != "desc" { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid order"}) return page, false } if page.Sort != "" { if _, ok := sorts[page.Sort]; !ok { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid sort"}) return page, false } } return page, true }