diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go index e349bb1e92..3d4dbcd104 100644 --- a/routers/web/explore/user.go +++ b/routers/web/explore/user.go @@ -20,7 +20,7 @@ import ( ) const ( - // tplExploreUsers explore users page template + // `tplExploreUsers` explore users page template. tplExploreUsers base.TplName = "explore/users" ) @@ -30,9 +30,9 @@ func isKeywordValid(keyword string) bool { return !bytes.Contains([]byte(keyword), nullByte) } -// RenderUserSearch render user search page +// `RenderUserSearch` render user search page. func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions, tplName base.TplName) { - // Sitemap index for sitemap paths + // Sitemap index for sitemap paths. opts.Page = int(ctx.ParamsInt64("idx")) isSitemap := ctx.Params("idx") != "" if opts.Page <= 1 { @@ -47,42 +47,24 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions, } var ( - users []*user_model.User - count int64 - err error - orderBy db.SearchOrderBy + users []*user_model.User + count int64 + err error ) - // we can not set orderBy to `models.SearchOrderByXxx`, because there may be a JOIN in the statement, different tables may have the same name columns - sortOrder := ctx.FormString("sort") if sortOrder == "" { sortOrder = setting.UI.ExploreDefaultSort } ctx.Data["SortType"] = sortOrder - switch sortOrder { - case "newest": - orderBy = "`user`.id DESC" - case "oldest": - orderBy = "`user`.id ASC" - case "leastupdate": - orderBy = "`user`.updated_unix ASC" - case "reversealphabetically": - orderBy = "`user`.name DESC" - case "lastlogin": - orderBy = "`user`.last_login_unix ASC" - case "reverselastlogin": - orderBy = "`user`.last_login_unix DESC" - case "alphabetically": - orderBy = "`user`.name ASC" - case "recentupdate": - fallthrough - default: - // in case the sortType is not valid, we set it to recentupdate + orderBy := MapSortOrder(sortOrder) + + if orderBy == "" { + // In case the `sortType` is not valid, we set it to `recentupdate`. sortOrder = "recentupdate" ctx.Data["SortType"] = "recentupdate" - orderBy = "`user`.updated_unix DESC" + orderBy = MapSortOrder(sortOrder) } if opts.SupportedSortOrders != nil && !opts.SupportedSortOrders.Contains(sortOrder) { @@ -130,7 +112,7 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions, ctx.HTML(http.StatusOK, tplName) } -// Users render explore users page +// Users render explore users page. func Users(ctx *context.Context) { if setting.Service.Explore.DisableUsersPage { ctx.Redirect(setting.AppSubURL + "/explore") @@ -169,3 +151,37 @@ func Users(ctx *context.Context) { SupportedSortOrders: supportedSortOrders, }, tplExploreUsers) } + +// Maps a sort query to a database search order. +// +// We cannot use `models.SearchOrderByXxx`, because there may be a JOIN in the statement, different tables may have the same name columns. +func MapSortOrder(sortOrder string) db.SearchOrderBy { + switch sortOrder { + case "newest": + return "`user`.created_unix DESC" + + case "oldest": + return "`user`.created_unix ASC" + + case "leastupdate": + return "`user`.updated_unix ASC" + + case "reversealphabetically": + return "`user`.name DESC" + + case "lastlogin": + return "`user`.last_login_unix ASC" + + case "reverselastlogin": + return "`user`.last_login_unix DESC" + + case "alphabetically": + return "`user`.name ASC" + + case "recentupdate": + return "`user`.updated_unix DESC" + + default: + return "" + } +} diff --git a/routers/web/explore/user_test.go b/routers/web/explore/user_test.go new file mode 100644 index 0000000000..04573a149f --- /dev/null +++ b/routers/web/explore/user_test.go @@ -0,0 +1,23 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package explore + +import ( + "testing" + + "forgejo.org/models/db" + + "github.com/stretchr/testify/assert" +) + +func TestMapSortOrder(t *testing.T) { + assert.Equal(t, MapSortOrder("newest"), db.SearchOrderBy("`user`.created_unix DESC")) + assert.Equal(t, MapSortOrder("oldest"), db.SearchOrderBy("`user`.created_unix ASC")) + assert.Equal(t, MapSortOrder("leastupdate"), db.SearchOrderBy("`user`.updated_unix ASC")) + assert.Equal(t, MapSortOrder("reversealphabetically"), db.SearchOrderBy("`user`.name DESC")) + assert.Equal(t, MapSortOrder("lastlogin"), db.SearchOrderBy("`user`.last_login_unix ASC")) + assert.Equal(t, MapSortOrder("reverselastlogin"), db.SearchOrderBy("`user`.last_login_unix DESC")) + assert.Equal(t, MapSortOrder("alphabetically"), db.SearchOrderBy("`user`.name ASC")) + assert.Equal(t, MapSortOrder("recentupdate"), db.SearchOrderBy("`user`.updated_unix DESC")) +}