mirror of
https://github.com/stashapp/stash.git
synced 2025-12-16 20:07:05 +03:00
Enforce whitelist for sort values (#4865)
This commit is contained in:
@@ -8,6 +8,7 @@ input FindFilterType {
|
|||||||
page: Int
|
page: Int
|
||||||
"use per_page = -1 to indicate all results. Defaults to 25."
|
"use per_page = -1 to indicate all results. Defaults to 25."
|
||||||
per_page: Int
|
per_page: Int
|
||||||
|
# TODO - this should be refactored to not use a string
|
||||||
sort: String
|
sort: String
|
||||||
direction: SortDirectionEnum
|
direction: SortDirectionEnum
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -862,7 +862,9 @@ func (qb *FileStore) Query(ctx context.Context, options models.FileQueryOptions)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
qb.setQuerySort(&query, findFilter)
|
if err := qb.setQuerySort(&query, findFilter); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
query.sortAndPagination += getPagination(findFilter)
|
query.sortAndPagination += getPagination(findFilter)
|
||||||
|
|
||||||
result, err := qb.queryGroupedFields(ctx, options, query)
|
result, err := qb.queryGroupedFields(ctx, options, query)
|
||||||
@@ -911,12 +913,25 @@ func (qb *FileStore) queryGroupedFields(ctx context.Context, options models.File
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *FileStore) setQuerySort(query *queryBuilder, findFilter *models.FindFilterType) {
|
var fileSortOptions = sortOptions{
|
||||||
|
"created_at",
|
||||||
|
"id",
|
||||||
|
"path",
|
||||||
|
"random",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qb *FileStore) setQuerySort(query *queryBuilder, findFilter *models.FindFilterType) error {
|
||||||
if findFilter == nil || findFilter.Sort == nil || *findFilter.Sort == "" {
|
if findFilter == nil || findFilter.Sort == nil || *findFilter.Sort == "" {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
sort := findFilter.GetSort("path")
|
sort := findFilter.GetSort("path")
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := fileSortOptions.validateSort(sort); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
direction := findFilter.GetDirection()
|
direction := findFilter.GetDirection()
|
||||||
switch sort {
|
switch sort {
|
||||||
case "path":
|
case "path":
|
||||||
@@ -925,6 +940,8 @@ func (qb *FileStore) setQuerySort(query *queryBuilder, findFilter *models.FindFi
|
|||||||
default:
|
default:
|
||||||
query.sortAndPagination += getSort(sort, direction, "files")
|
query.sortAndPagination += getSort(sort, direction, "files")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *FileStore) captionRepository() *captionRepository {
|
func (qb *FileStore) captionRepository() *captionRepository {
|
||||||
|
|||||||
@@ -782,7 +782,9 @@ func (qb *GalleryStore) makeQuery(ctx context.Context, galleryFilter *models.Gal
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
qb.setGallerySort(&query, findFilter)
|
if err := qb.setGallerySort(&query, findFilter); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
query.sortAndPagination += getPagination(findFilter)
|
query.sortAndPagination += getPagination(findFilter)
|
||||||
|
|
||||||
return &query, nil
|
return &query, nil
|
||||||
@@ -1100,14 +1102,35 @@ func galleryAverageResolutionCriterionHandler(qb *GalleryStore, resolution *mode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *GalleryStore) setGallerySort(query *queryBuilder, findFilter *models.FindFilterType) {
|
var gallerySortOptions = sortOptions{
|
||||||
|
"created_at",
|
||||||
|
"date",
|
||||||
|
"file_count",
|
||||||
|
"file_mod_time",
|
||||||
|
"id",
|
||||||
|
"images_count",
|
||||||
|
"path",
|
||||||
|
"performer_count",
|
||||||
|
"random",
|
||||||
|
"rating",
|
||||||
|
"tag_count",
|
||||||
|
"title",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qb *GalleryStore) setGallerySort(query *queryBuilder, findFilter *models.FindFilterType) error {
|
||||||
if findFilter == nil || findFilter.Sort == nil || *findFilter.Sort == "" {
|
if findFilter == nil || findFilter.Sort == nil || *findFilter.Sort == "" {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sort := findFilter.GetSort("path")
|
sort := findFilter.GetSort("path")
|
||||||
direction := findFilter.GetDirection()
|
direction := findFilter.GetDirection()
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := gallerySortOptions.validateSort(sort); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
addFileTable := func() {
|
addFileTable := func() {
|
||||||
query.addJoins(
|
query.addJoins(
|
||||||
join{
|
join{
|
||||||
@@ -1163,6 +1186,8 @@ func (qb *GalleryStore) setGallerySort(query *queryBuilder, findFilter *models.F
|
|||||||
|
|
||||||
// Whatever the sorting, always use title/id as a final sort
|
// Whatever the sorting, always use title/id as a final sort
|
||||||
query.sortAndPagination += ", COALESCE(galleries.title, galleries.id) COLLATE NATURAL_CI ASC"
|
query.sortAndPagination += ", COALESCE(galleries.title, galleries.id) COLLATE NATURAL_CI ASC"
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *GalleryStore) GetURLs(ctx context.Context, galleryID int) ([]string, error) {
|
func (qb *GalleryStore) GetURLs(ctx context.Context, galleryID int) ([]string, error) {
|
||||||
|
|||||||
@@ -791,7 +791,9 @@ func (qb *ImageStore) makeQuery(ctx context.Context, imageFilter *models.ImageFi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
qb.setImageSortAndPagination(&query, findFilter)
|
if err := qb.setImageSortAndPagination(&query, findFilter); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &query, nil
|
return &query, nil
|
||||||
}
|
}
|
||||||
@@ -1051,13 +1053,35 @@ func imagePerformerTagsCriterionHandler(qb *ImageStore, tags *models.Hierarchica
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *ImageStore) setImageSortAndPagination(q *queryBuilder, findFilter *models.FindFilterType) {
|
var imageSortOptions = sortOptions{
|
||||||
|
"created_at",
|
||||||
|
"date",
|
||||||
|
"file_count",
|
||||||
|
"file_mod_time",
|
||||||
|
"filesize",
|
||||||
|
"id",
|
||||||
|
"o_counter",
|
||||||
|
"path",
|
||||||
|
"performer_count",
|
||||||
|
"random",
|
||||||
|
"rating",
|
||||||
|
"tag_count",
|
||||||
|
"title",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qb *ImageStore) setImageSortAndPagination(q *queryBuilder, findFilter *models.FindFilterType) error {
|
||||||
sortClause := ""
|
sortClause := ""
|
||||||
|
|
||||||
if findFilter != nil && findFilter.Sort != nil && *findFilter.Sort != "" {
|
if findFilter != nil && findFilter.Sort != nil && *findFilter.Sort != "" {
|
||||||
sort := findFilter.GetSort("title")
|
sort := findFilter.GetSort("title")
|
||||||
direction := findFilter.GetDirection()
|
direction := findFilter.GetDirection()
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := imageSortOptions.validateSort(sort); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// translate sort field
|
// translate sort field
|
||||||
if sort == "file_mod_time" {
|
if sort == "file_mod_time" {
|
||||||
sort = "mod_time"
|
sort = "mod_time"
|
||||||
@@ -1110,6 +1134,8 @@ func (qb *ImageStore) setImageSortAndPagination(q *queryBuilder, findFilter *mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
q.sortAndPagination = sortClause + getPagination(findFilter)
|
q.sortAndPagination = sortClause + getPagination(findFilter)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *ImageStore) galleriesRepository() *joinRepository {
|
func (qb *ImageStore) galleriesRepository() *joinRepository {
|
||||||
|
|||||||
@@ -368,7 +368,13 @@ func (qb *MovieStore) makeQuery(ctx context.Context, movieFilter *models.MovieFi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query.sortAndPagination = qb.getMovieSort(findFilter) + getPagination(findFilter)
|
var err error
|
||||||
|
query.sortAndPagination, err = qb.getMovieSort(findFilter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query.sortAndPagination += getPagination(findFilter)
|
||||||
|
|
||||||
return &query, nil
|
return &query, nil
|
||||||
}
|
}
|
||||||
@@ -466,7 +472,19 @@ func moviePerformersCriterionHandler(qb *MovieStore, performers *models.MultiCri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *MovieStore) getMovieSort(findFilter *models.FindFilterType) string {
|
var movieSortOptions = sortOptions{
|
||||||
|
"created_at",
|
||||||
|
"date",
|
||||||
|
"duration",
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"random",
|
||||||
|
"rating",
|
||||||
|
"scenes_count",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qb *MovieStore) getMovieSort(findFilter *models.FindFilterType) (string, error) {
|
||||||
var sort string
|
var sort string
|
||||||
var direction string
|
var direction string
|
||||||
if findFilter == nil {
|
if findFilter == nil {
|
||||||
@@ -477,6 +495,11 @@ func (qb *MovieStore) getMovieSort(findFilter *models.FindFilterType) string {
|
|||||||
direction = findFilter.GetDirection()
|
direction = findFilter.GetDirection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := movieSortOptions.validateSort(sort); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
sortQuery := ""
|
sortQuery := ""
|
||||||
switch sort {
|
switch sort {
|
||||||
case "scenes_count": // generic getSort won't work for this
|
case "scenes_count": // generic getSort won't work for this
|
||||||
@@ -487,7 +510,7 @@ func (qb *MovieStore) getMovieSort(findFilter *models.FindFilterType) string {
|
|||||||
|
|
||||||
// Whatever the sorting, always use name/id as a final sort
|
// Whatever the sorting, always use name/id as a final sort
|
||||||
sortQuery += ", COALESCE(movies.name, movies.id) COLLATE NATURAL_CI ASC"
|
sortQuery += ", COALESCE(movies.name, movies.id) COLLATE NATURAL_CI ASC"
|
||||||
return sortQuery
|
return sortQuery, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *MovieStore) queryMovies(ctx context.Context, query string, args []interface{}) ([]*models.Movie, error) {
|
func (qb *MovieStore) queryMovies(ctx context.Context, query string, args []interface{}) ([]*models.Movie, error) {
|
||||||
|
|||||||
@@ -706,7 +706,12 @@ func (qb *PerformerStore) makeQuery(ctx context.Context, performerFilter *models
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query.sortAndPagination = qb.getPerformerSort(findFilter) + getPagination(findFilter)
|
var err error
|
||||||
|
query.sortAndPagination, err = qb.getPerformerSort(findFilter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
query.sortAndPagination += getPagination(findFilter)
|
||||||
|
|
||||||
return &query, nil
|
return &query, nil
|
||||||
}
|
}
|
||||||
@@ -1113,7 +1118,27 @@ func (qb *PerformerStore) sortByLastPlayedAt(direction string) string {
|
|||||||
return " ORDER BY (" + selectPerformerLastPlayedAtSQL + ") " + direction
|
return " ORDER BY (" + selectPerformerLastPlayedAtSQL + ") " + direction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *PerformerStore) getPerformerSort(findFilter *models.FindFilterType) string {
|
var performerSortOptions = sortOptions{
|
||||||
|
"birthdate",
|
||||||
|
"created_at",
|
||||||
|
"galleries_count",
|
||||||
|
"height",
|
||||||
|
"id",
|
||||||
|
"images_count",
|
||||||
|
"last_o_at",
|
||||||
|
"last_played_at",
|
||||||
|
"name",
|
||||||
|
"o_counter",
|
||||||
|
"penis_length",
|
||||||
|
"play_count",
|
||||||
|
"random",
|
||||||
|
"rating",
|
||||||
|
"scenes_count",
|
||||||
|
"tag_count",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qb *PerformerStore) getPerformerSort(findFilter *models.FindFilterType) (string, error) {
|
||||||
var sort string
|
var sort string
|
||||||
var direction string
|
var direction string
|
||||||
if findFilter == nil {
|
if findFilter == nil {
|
||||||
@@ -1124,6 +1149,11 @@ func (qb *PerformerStore) getPerformerSort(findFilter *models.FindFilterType) st
|
|||||||
direction = findFilter.GetDirection()
|
direction = findFilter.GetDirection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := performerSortOptions.validateSort(sort); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
sortQuery := ""
|
sortQuery := ""
|
||||||
switch sort {
|
switch sort {
|
||||||
case "tag_count":
|
case "tag_count":
|
||||||
@@ -1148,7 +1178,7 @@ func (qb *PerformerStore) getPerformerSort(findFilter *models.FindFilterType) st
|
|||||||
|
|
||||||
// Whatever the sorting, always use name/id as a final sort
|
// Whatever the sorting, always use name/id as a final sort
|
||||||
sortQuery += ", COALESCE(performers.name, performers.id) COLLATE NATURAL_CI ASC"
|
sortQuery += ", COALESCE(performers.name, performers.id) COLLATE NATURAL_CI ASC"
|
||||||
return sortQuery
|
return sortQuery, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *PerformerStore) tagsRepository() *joinRepository {
|
func (qb *PerformerStore) tagsRepository() *joinRepository {
|
||||||
|
|||||||
@@ -1083,7 +1083,9 @@ func (qb *SceneStore) makeQuery(ctx context.Context, sceneFilter *models.SceneFi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
qb.setSceneSort(&query, findFilter)
|
if err := qb.setSceneSort(&query, findFilter); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
query.sortAndPagination += getPagination(findFilter)
|
query.sortAndPagination += getPagination(findFilter)
|
||||||
|
|
||||||
return &query, nil
|
return &query, nil
|
||||||
@@ -1522,12 +1524,47 @@ func scenePhashDistanceCriterionHandler(qb *SceneStore, phashDistance *models.Ph
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindFilterType) {
|
var sceneSortOptions = sortOptions{
|
||||||
|
"bitrate",
|
||||||
|
"created_at",
|
||||||
|
"date",
|
||||||
|
"file_count",
|
||||||
|
"filesize",
|
||||||
|
"duration",
|
||||||
|
"file_mod_time",
|
||||||
|
"framerate",
|
||||||
|
"id",
|
||||||
|
"interactive",
|
||||||
|
"interactive_speed",
|
||||||
|
"last_o_at",
|
||||||
|
"last_played_at",
|
||||||
|
"movie_scene_number",
|
||||||
|
"o_counter",
|
||||||
|
"organized",
|
||||||
|
"performer_count",
|
||||||
|
"play_count",
|
||||||
|
"play_duration",
|
||||||
|
"resume_time",
|
||||||
|
"path",
|
||||||
|
"perceptual_similarity",
|
||||||
|
"random",
|
||||||
|
"rating",
|
||||||
|
"tag_count",
|
||||||
|
"title",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindFilterType) error {
|
||||||
if findFilter == nil || findFilter.Sort == nil || *findFilter.Sort == "" {
|
if findFilter == nil || findFilter.Sort == nil || *findFilter.Sort == "" {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
sort := findFilter.GetSort("title")
|
sort := findFilter.GetSort("title")
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := sceneSortOptions.validateSort(sort); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
addFileTable := func() {
|
addFileTable := func() {
|
||||||
query.addJoins(
|
query.addJoins(
|
||||||
join{
|
join{
|
||||||
@@ -1627,6 +1664,8 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
|||||||
|
|
||||||
// Whatever the sorting, always use title/id as a final sort
|
// Whatever the sorting, always use title/id as a final sort
|
||||||
query.sortAndPagination += ", COALESCE(scenes.title, scenes.id) COLLATE NATURAL_CI ASC"
|
query.sortAndPagination += ", COALESCE(scenes.title, scenes.id) COLLATE NATURAL_CI ASC"
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *SceneStore) SaveActivity(ctx context.Context, id int, resumeTime *float64, playDuration *float64) (bool, error) {
|
func (qb *SceneStore) SaveActivity(ctx context.Context, id int, resumeTime *float64, playDuration *float64) (bool, error) {
|
||||||
|
|||||||
@@ -310,7 +310,9 @@ func (qb *SceneMarkerStore) makeQuery(ctx context.Context, sceneMarkerFilter *mo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
qb.setSceneMarkerSort(&query, findFilter)
|
if err := qb.setSceneMarkerSort(&query, findFilter); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
query.sortAndPagination += getPagination(findFilter)
|
query.sortAndPagination += getPagination(findFilter)
|
||||||
|
|
||||||
return &query, nil
|
return &query, nil
|
||||||
@@ -473,10 +475,26 @@ func sceneMarkerPerformersCriterionHandler(qb *SceneMarkerStore, performers *mod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *SceneMarkerStore) setSceneMarkerSort(query *queryBuilder, findFilter *models.FindFilterType) {
|
var sceneMarkerSortOptions = sortOptions{
|
||||||
|
"created_at",
|
||||||
|
"id",
|
||||||
|
"title",
|
||||||
|
"random",
|
||||||
|
"scene_id",
|
||||||
|
"scenes_updated_at",
|
||||||
|
"seconds",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qb *SceneMarkerStore) setSceneMarkerSort(query *queryBuilder, findFilter *models.FindFilterType) error {
|
||||||
sort := findFilter.GetSort("title")
|
sort := findFilter.GetSort("title")
|
||||||
direction := findFilter.GetDirection()
|
direction := findFilter.GetDirection()
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := sceneMarkerSortOptions.validateSort(sort); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
switch sort {
|
switch sort {
|
||||||
case "scenes_updated_at":
|
case "scenes_updated_at":
|
||||||
sort = "updated_at"
|
sort = "updated_at"
|
||||||
@@ -490,6 +508,7 @@ func (qb *SceneMarkerStore) setSceneMarkerSort(query *queryBuilder, findFilter *
|
|||||||
}
|
}
|
||||||
|
|
||||||
query.sortAndPagination += ", scene_markers.scene_id ASC, scene_markers.seconds ASC"
|
query.sortAndPagination += ", scene_markers.scene_id ASC, scene_markers.seconds ASC"
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *SceneMarkerStore) querySceneMarkers(ctx context.Context, query string, args []interface{}) ([]*models.SceneMarker, error) {
|
func (qb *SceneMarkerStore) querySceneMarkers(ctx context.Context, query string, args []interface{}) ([]*models.SceneMarker, error) {
|
||||||
|
|||||||
@@ -42,6 +42,30 @@ func getPaginationSQL(page int, perPage int) string {
|
|||||||
return " LIMIT " + strconv.Itoa(perPage) + " OFFSET " + strconv.Itoa(page) + " "
|
return " LIMIT " + strconv.Itoa(perPage) + " OFFSET " + strconv.Itoa(page) + " "
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const randomSeedPrefix = "random_" // prefix for random sort
|
||||||
|
|
||||||
|
type sortOptions []string
|
||||||
|
|
||||||
|
func (o sortOptions) validateSort(sort string) error {
|
||||||
|
if strings.HasPrefix(sort, randomSeedPrefix) {
|
||||||
|
// seed as a parameter from the UI
|
||||||
|
seedStr := sort[len(randomSeedPrefix):]
|
||||||
|
_, err := strconv.ParseUint(seedStr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid random seed: %s", seedStr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range o {
|
||||||
|
if v == sort {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("invalid sort: %s", sort)
|
||||||
|
}
|
||||||
|
|
||||||
func getSortDirection(direction string) string {
|
func getSortDirection(direction string) string {
|
||||||
if direction != "ASC" && direction != "DESC" {
|
if direction != "ASC" && direction != "DESC" {
|
||||||
return "ASC"
|
return "ASC"
|
||||||
@@ -52,8 +76,6 @@ func getSortDirection(direction string) string {
|
|||||||
func getSort(sort string, direction string, tableName string) string {
|
func getSort(sort string, direction string, tableName string) string {
|
||||||
direction = getSortDirection(direction)
|
direction = getSortDirection(direction)
|
||||||
|
|
||||||
const randomSeedPrefix = "random_"
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case strings.HasSuffix(sort, "_count"):
|
case strings.HasSuffix(sort, "_count"):
|
||||||
var relationTableName = strings.TrimSuffix(sort, "_count") // TODO: pluralize?
|
var relationTableName = strings.TrimSuffix(sort, "_count") // TODO: pluralize?
|
||||||
|
|||||||
@@ -555,7 +555,12 @@ func (qb *StudioStore) makeQuery(ctx context.Context, studioFilter *models.Studi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query.sortAndPagination = qb.getStudioSort(findFilter) + getPagination(findFilter)
|
var err error
|
||||||
|
query.sortAndPagination, err = qb.getStudioSort(findFilter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
query.sortAndPagination += getPagination(findFilter)
|
||||||
|
|
||||||
return &query, nil
|
return &query, nil
|
||||||
}
|
}
|
||||||
@@ -666,7 +671,20 @@ func studioChildCountCriterionHandler(qb *StudioStore, childCount *models.IntCri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *StudioStore) getStudioSort(findFilter *models.FindFilterType) string {
|
var studioSortOptions = sortOptions{
|
||||||
|
"child_count",
|
||||||
|
"created_at",
|
||||||
|
"galleries_count",
|
||||||
|
"id",
|
||||||
|
"images_count",
|
||||||
|
"name",
|
||||||
|
"scenes_count",
|
||||||
|
"random",
|
||||||
|
"rating",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qb *StudioStore) getStudioSort(findFilter *models.FindFilterType) (string, error) {
|
||||||
var sort string
|
var sort string
|
||||||
var direction string
|
var direction string
|
||||||
if findFilter == nil {
|
if findFilter == nil {
|
||||||
@@ -677,6 +695,11 @@ func (qb *StudioStore) getStudioSort(findFilter *models.FindFilterType) string {
|
|||||||
direction = findFilter.GetDirection()
|
direction = findFilter.GetDirection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := studioSortOptions.validateSort(sort); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
sortQuery := ""
|
sortQuery := ""
|
||||||
switch sort {
|
switch sort {
|
||||||
case "scenes_count":
|
case "scenes_count":
|
||||||
@@ -693,7 +716,7 @@ func (qb *StudioStore) getStudioSort(findFilter *models.FindFilterType) string {
|
|||||||
|
|
||||||
// Whatever the sorting, always use name/id as a final sort
|
// Whatever the sorting, always use name/id as a final sort
|
||||||
sortQuery += ", COALESCE(studios.name, studios.id) COLLATE NATURAL_CI ASC"
|
sortQuery += ", COALESCE(studios.name, studios.id) COLLATE NATURAL_CI ASC"
|
||||||
return sortQuery
|
return sortQuery, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *StudioStore) GetImage(ctx context.Context, studioID int) ([]byte, error) {
|
func (qb *StudioStore) GetImage(ctx context.Context, studioID int) ([]byte, error) {
|
||||||
|
|||||||
@@ -548,7 +548,12 @@ func (qb *TagStore) Query(ctx context.Context, tagFilter *models.TagFilterType,
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query.sortAndPagination = qb.getTagSort(&query, findFilter) + getPagination(findFilter)
|
var err error
|
||||||
|
query.sortAndPagination, err = qb.getTagSort(&query, findFilter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
query.sortAndPagination += getPagination(findFilter)
|
||||||
idsResult, countResult, err := query.executeFind(ctx)
|
idsResult, countResult, err := query.executeFind(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -853,11 +858,24 @@ func tagChildCountCriterionHandler(qb *TagStore, childCount *models.IntCriterion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tagSortOptions = sortOptions{
|
||||||
|
"created_at",
|
||||||
|
"galleries_count",
|
||||||
|
"id",
|
||||||
|
"images_count",
|
||||||
|
"name",
|
||||||
|
"performers_count",
|
||||||
|
"random",
|
||||||
|
"scene_markers_count",
|
||||||
|
"scenes_count",
|
||||||
|
"updated_at",
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *TagStore) getDefaultTagSort() string {
|
func (qb *TagStore) getDefaultTagSort() string {
|
||||||
return getSort("name", "ASC", "tags")
|
return getSort("name", "ASC", "tags")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *TagStore) getTagSort(query *queryBuilder, findFilter *models.FindFilterType) string {
|
func (qb *TagStore) getTagSort(query *queryBuilder, findFilter *models.FindFilterType) (string, error) {
|
||||||
var sort string
|
var sort string
|
||||||
var direction string
|
var direction string
|
||||||
if findFilter == nil {
|
if findFilter == nil {
|
||||||
@@ -868,6 +886,11 @@ func (qb *TagStore) getTagSort(query *queryBuilder, findFilter *models.FindFilte
|
|||||||
direction = findFilter.GetDirection()
|
direction = findFilter.GetDirection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
|
||||||
|
if err := tagSortOptions.validateSort(sort); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
sortQuery := ""
|
sortQuery := ""
|
||||||
switch sort {
|
switch sort {
|
||||||
case "scenes_count":
|
case "scenes_count":
|
||||||
@@ -886,7 +909,7 @@ func (qb *TagStore) getTagSort(query *queryBuilder, findFilter *models.FindFilte
|
|||||||
|
|
||||||
// Whatever the sorting, always use name/id as a final sort
|
// Whatever the sorting, always use name/id as a final sort
|
||||||
sortQuery += ", COALESCE(tags.name, tags.id) COLLATE NATURAL_CI ASC"
|
sortQuery += ", COALESCE(tags.name, tags.id) COLLATE NATURAL_CI ASC"
|
||||||
return sortQuery
|
return sortQuery, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *TagStore) queryTags(ctx context.Context, query string, args []interface{}) ([]*models.Tag, error) {
|
func (qb *TagStore) queryTags(ctx context.Context, query string, args []interface{}) ([]*models.Tag, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user