refactor(api): load assignees list correctly (#39917)

Correctly handle empty names, upper&lower cases, duplicate names.

Fixes https://github.com/go-gitea/gitea/issues/39916

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Shivansh Gargandwxiaoguang authored and GitHub committed 2026-10-21 16:15:43 +00:00
1 parent 33610142c3
commit 0948aed411
7 files changed
+98 -104

No files matched your search

-19
View File
@@ -9,7 +9,6 @@ import (
"gitea.dev/models/db"
user_model "gitea.dev/models/user"
"gitea.dev/modules/util"
"xorm.io/builder"
)
@@ -172,21 +171,3 @@ func toggleUserAssignee(ctx context.Context, issue *Issue, assigneeID int64) (re
return found, nil
}
// MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs
func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multipleAssignees []string) ([]int64, error) {
var requestAssignees []string
// Keeping the old assigning method for compatibility reasons
if oneAssignee != "" && !util.SliceContainsString(multipleAssignees, oneAssignee) {
requestAssignees = append(requestAssignees, oneAssignee)
}
// Prevent empty assignees
if len(multipleAssignees) > 0 && multipleAssignees[0] != "" {
requestAssignees = append(requestAssignees, multipleAssignees...)
}
// Get the IDs of all assignees
return user_model.GetDoerUserIDsByNames(ctx, requestAssignees)
}
-26
View File
@@ -65,29 +65,3 @@ func TestUpdateAssignee(t *testing.T) {
assert.NoError(t, err)
assert.False(t, isAssigned)
}
func TestMakeIDsFromAPIAssigneesToAdd(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "", []string{""})
assert.NoError(t, err)
assert.Equal(t, []int64{}, IDs)
_, err = issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "", []string{"none_existing_user"})
assert.Error(t, err)
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "user1", []string{"user1"})
assert.NoError(t, err)
assert.Equal(t, []int64{1}, IDs)
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "user2", []string{""})
assert.NoError(t, err)
assert.Equal(t, []int64{2}, IDs)
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "", []string{"user1", "user2"})
assert.NoError(t, err)
assert.Equal(t, []int64{1, 2}, IDs)
}
+19 -6
View File
@@ -1180,6 +1180,15 @@ func GetMailableUsersByIDs(ctx context.Context, ids []int64, isMention bool) ([]
}
func getDoerUserIDsByNames(ctx context.Context, names []string, allowSystemDoer bool) ([]int64, error) {
users, err := getDoerUsersByNames(ctx, names, allowSystemDoer)
ids := make([]int64, 0, len(users))
for _, u := range users {
ids = append(ids, u.ID)
}
return ids, err
}
func getDoerUsersByNames(ctx context.Context, names []string, allowSystemDoer bool) ([]*User, error) {
namesLower := make([]string, 0, len(names))
namesMap := make(map[string]*User, len(names))
for _, name := range names {
@@ -1193,16 +1202,16 @@ func getDoerUserIDsByNames(ctx context.Context, names []string, allowSystemDoer
}
}
var users []*User
err := db.GetEngine(ctx).In("lower_name", namesLower).Where("`type` IN (?,?)", UserTypeIndividual, UserTypeBot).Find(&users)
var dbUsers []*User
err := db.GetEngine(ctx).In("lower_name", namesLower).Where("`type` IN (?,?)", UserTypeIndividual, UserTypeBot).Find(&dbUsers)
if err != nil {
return nil, err
}
for _, user := range users {
for _, user := range dbUsers {
namesMap[user.LowerName] = user
}
ids := make([]int64, 0, len(names))
users := make([]*User, 0, len(names))
var errFinal error
for _, nameLower := range namesLower {
u := namesMap[nameLower]
@@ -1210,9 +1219,13 @@ func getDoerUserIDsByNames(ctx context.Context, names []string, allowSystemDoer
errFinal = ErrUserNotExist{Name: nameLower}
continue
}
ids = append(ids, u.ID)
users = append(users, u)
}
return ids, errFinal
return users, errFinal
}
func GetDoerUsersByNames(ctx context.Context, names []string) ([]*User, error) {
return getDoerUsersByNames(ctx, names, false)
}
func GetDoerUserIDsByNamesWithSystem(ctx context.Context, names []string) ([]int64, error) {