From fa230a19647e2564e16a8e446d24e8a906bb6156 Mon Sep 17 00:00:00 2001 From: BtbN Date: Mon, 22 Dec 2025 12:59:37 +0100 Subject: [PATCH] fix: always search for issue posters by user and full name (#10394) Previously searching for posters would use full name or username depending on the `[ui].DEFAULT_SHOW_FULL_NAME` setting, now it searches for both of them regardless of the setting. This also a fixes a bug when `[ui].DEFAULT_SHOW_FULL_NAME=true` that users without a full name where not able to searched for. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10394 Reviewed-by: Beowulf Co-authored-by: BtbN Co-committed-by: BtbN --- models/repo/user_repo.go | 12 +++++------ routers/web/repo/issue.go | 2 +- tests/integration/issue_test.go | 37 +++++++++++++++++++-------------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go index 309bfee18f..ca02c1e3f0 100644 --- a/models/repo/user_repo.go +++ b/models/repo/user_repo.go @@ -162,14 +162,12 @@ func GetReviewers(ctx context.Context, repo *Repository, doerID, posterID int64) return users, db.GetEngine(ctx).Where(cond).OrderBy(user_model.GetOrderByName()).Find(&users) } -// GetIssuePostersWithSearch returns users with limit of 30 whose username started with prefix that have authored an issue/pull request for the given repository -// If isShowFullName is set to true, also include full name prefix search -func GetIssuePostersWithSearch(ctx context.Context, repo *Repository, isPull bool, search string, isShowFullName bool) ([]*user_model.User, error) { +// GetIssuePostersWithSearch returns up to 30 users whose username starts with or full_name contains the given search string for the given repository. +func GetIssuePostersWithSearch(ctx context.Context, repo *Repository, isPull bool, search string) ([]*user_model.User, error) { users := make([]*user_model.User, 0, 30) - prefixCond := db.BuildCaseInsensitiveLike("name", search+"%") - if isShowFullName { - prefixCond = db.BuildCaseInsensitiveLike("full_name", "%"+search+"%") - } + prefixCond := builder.Or( + db.BuildCaseInsensitiveLike("name", search+"%"), + db.BuildCaseInsensitiveLike("full_name", "%"+search+"%")) cond := builder.In("`user`.id", builder.Select("poster_id").From("issue").Where( diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index df61ef0daf..d46ea7f133 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -3767,7 +3767,7 @@ func PullPosters(ctx *context.Context) { func issuePosters(ctx *context.Context, isPullList bool) { repo := ctx.Repo.Repository search := strings.TrimSpace(ctx.FormString("q")) - posters, err := repo_model.GetIssuePostersWithSearch(ctx, repo, isPullList, search, setting.UI.DefaultShowFullName) + posters, err := repo_model.GetIssuePostersWithSearch(ctx, repo, isPullList, search) if err != nil { ctx.JSON(http.StatusInternalServerError, err) return diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go index b47f3fd534..19fe59a10a 100644 --- a/tests/integration/issue_test.go +++ b/tests/integration/issue_test.go @@ -1547,34 +1547,39 @@ func TestIssuePostersSearch(t *testing.T) { Results []*userSearchInfo `json:"results"` } - t.Run("Name search", func(t *testing.T) { - defer tests.PrintCurrentTest(t)() - defer test.MockVariableValue(&setting.UI.DefaultShowFullName, false)() + testCase := func(t *testing.T, showFullName bool, url, wantUserName string, wantUserID int64) { + t.Helper() + defer test.MockVariableValue(&setting.UI.DefaultShowFullName, showFullName)() - req := NewRequest(t, "GET", "/user2/repo1/issues/posters?q=USer2") + req := NewRequest(t, "GET", url) resp := MakeRequest(t, req, http.StatusOK) var data userSearchResponse DecodeJSON(t, resp, &data) assert.Len(t, data.Results, 1) - assert.Equal(t, "user2", data.Results[0].UserName) - assert.EqualValues(t, 2, data.Results[0].UserID) + assert.Equal(t, wantUserName, data.Results[0].UserName) + assert.Equal(t, wantUserID, data.Results[0].UserID) + } + + t.Run("Name search", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + testCase(t, false, "/user2/repo1/issues/posters?q=USer2", "user2", 2) + }) + + t.Run("Name search (default full_name)", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + testCase(t, true, "/user2/repo1/issues/posters?q=USer2", "user2", 2) }) t.Run("Full name search", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - defer test.MockVariableValue(&setting.UI.DefaultShowFullName, true)() + testCase(t, true, "/user2/repo1/issues/posters?q=OnE", "user1", 1) + }) - req := NewRequest(t, "GET", "/user2/repo1/issues/posters?q=OnE") - resp := MakeRequest(t, req, http.StatusOK) - - var data userSearchResponse - DecodeJSON(t, resp, &data) - - assert.Len(t, data.Results, 1) - assert.Equal(t, "user1", data.Results[0].UserName) - assert.EqualValues(t, 1, data.Results[0].UserID) + t.Run("Full name search (no default full_name)", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + testCase(t, false, "/user2/repo1/issues/posters?q=OnE", "user1", 1) }) }