diff --git a/cmd/api/movies.go b/cmd/api/movies.go index b816ea4..c8bc40c 100644 --- a/cmd/api/movies.go +++ b/cmd/api/movies.go @@ -227,6 +227,14 @@ func (app *application) listMoviesHandler(w http.ResponseWriter, r *http.Request // Extract the sort query string value, falling back to "id" if it is not provided by the client (which will imply an ascending sort on movie ID) input.Filters.Sort = app.readString(qs, "sort", "id") + // Add the supported sort values for this endpoint to the sort safelist + input.Filters.SortSafelist = []string{"id", "title", "year", "runtime", "-id", "-title", "-year", "-runtime"} + + // Execute the validation checks on Filters struct and send a response + if data.ValidateFilters(v, input.Filters); !v.Valid() { + app.failedValidationResponse(w, r, v.Errors) + return + } // Check the Validator instance for any errors and use the failedValidationResponse() helper to send the client a response if necessary if !v.Valid() { diff --git a/internal/data/filters.go b/internal/data/filters.go index 2f7fe06..3e4d560 100644 --- a/internal/data/filters.go +++ b/internal/data/filters.go @@ -1,7 +1,21 @@ package data +import "greenlight.craftr.fr/internal/validator" + type Filters struct { - Page int - PageSize int - Sort string + Page int + PageSize int + Sort string + SortSafelist []string +} + +func ValidateFilters(v *validator.Validator, f Filters) { + // Check that the page and page_size parameters contain sensible values + v.Check(f.Page > 0, "page", "must be greater than 0") + v.Check(f.Page <= 10_000_000, "page", "must be a maximum of 10 million") + v.Check(f.PageSize > 0, "page_size", "must be greater than 0") + v.Check(f.PageSize <= 100, "page_size", "must be a maximum of 100") + + // Check that the sort parameter matches a value in the safelist + v.Check(validator.PermittedValue(f.Sort, f.SortSafelist...), "sort", "invalid sort value") }