Compare commits

...

1 Commits

Author SHA1 Message Date
coderabbitai[bot]
bb49b0448d 📝 Add docstrings to feat/accurate-user-search
Docstrings generation was requested by @HenryXiaoYang.

* https://github.com/QuantumNous/new-api/pull/2535#issuecomment-3693274850

The following files were modified:

* `controller/user.go`
* `model/user.go`
2025-12-26 19:31:52 +00:00
2 changed files with 69 additions and 21 deletions

View File

@@ -287,11 +287,37 @@ func GetAllUsers(c *gin.Context) {
return
}
// SearchUsers handles a request to find users by keyword, group, or external identifier filters and returns paginated results.
// It requires at least one search parameter (keyword, group, or any of the external ID/email filters) and responds with an error if none are provided.
// On success it populates the page query with matching users and total count and returns that page info.
func SearchUsers(c *gin.Context) {
keyword := c.Query("keyword")
group := c.Query("group")
filters := map[string]string{
"github_id": c.Query("github_id"),
"discord_id": c.Query("discord_id"),
"oidc_id": c.Query("oidc_id"),
"wechat_id": c.Query("wechat_id"),
"email": c.Query("email"),
"telegram_id": c.Query("telegram_id"),
"linux_do_id": c.Query("linux_do_id"),
}
// 检查是否至少有一个搜索条件
hasFilter := keyword != "" || group != ""
for _, v := range filters {
if v != "" {
hasFilter = true
break
}
}
if !hasFilter {
common.ApiErrorMsg(c, "at least one search parameter is required")
return
}
pageInfo := common.GetPageQuery(c)
users, total, err := model.SearchUsers(keyword, group, pageInfo.GetStartIdx(), pageInfo.GetPageSize())
users, total, err := model.SearchUsers(keyword, group, filters, pageInfo.GetStartIdx(), pageInfo.GetPageSize())
if err != nil {
common.ApiError(c, err)
return
@@ -1293,4 +1319,4 @@ func UpdateUserSetting(c *gin.Context) {
"success": true,
"message": "设置已更新",
})
}
}

View File

@@ -185,6 +185,11 @@ func GetMaxUserId() int {
return user.Id
}
// GetAllUsers retrieves a paginated list of users and the total number of users.
// It returns results that include soft-deleted records, ordered by id descending,
// and omits the password field from the returned user objects.
// The pageInfo parameter provides the page size and start index for pagination.
// Returns the slice of users, the total user count, and any error encountered.
func GetAllUsers(pageInfo *common.PageInfo) (users []*User, total int64, err error) {
// Start transaction
tx := DB.Begin()
@@ -219,7 +224,10 @@ func GetAllUsers(pageInfo *common.PageInfo) (users []*User, total int64, err err
return users, total, nil
}
func SearchUsers(keyword string, group string, startIdx int, num int) ([]*User, int64, error) {
// SearchUsers searches for users matching the provided keyword, group, and exact-match filters.
// The function accepts a keyword (performs LIKE match on username, email, and display_name; if the keyword is numeric it also matches id), a group to scope results, a map of exact-match filters (allowed keys: "github_id", "discord_id", "oidc_id", "wechat_id", "email", "telegram_id", "linux_do_id"), and pagination parameters startIdx and num.
// It returns the matched users, the total number of records matching the query (ignoring pagination), and an error if the operation fails.
func SearchUsers(keyword string, group string, filters map[string]string, startIdx int, num int) ([]*User, int64, error) {
var users []*User
var total int64
var err error
@@ -238,32 +246,46 @@ func SearchUsers(keyword string, group string, startIdx int, num int) ([]*User,
// 构建基础查询
query := tx.Unscoped().Model(&User{})
// 构建搜索条件
likeCondition := "username LIKE ? OR email LIKE ? OR display_name LIKE ?"
// 允许的过滤字段白名单
allowedFields := map[string]bool{
"github_id": true,
"discord_id": true,
"oidc_id": true,
"wechat_id": true,
"email": true,
"telegram_id": true,
"linux_do_id": true,
}
// 尝试将关键字转换为整数ID
keywordInt, err := strconv.Atoi(keyword)
if err == nil {
// 如果是数字同时搜索ID和其他字段
likeCondition = "id = ? OR " + likeCondition
if group != "" {
query = query.Where("("+likeCondition+") AND "+commonGroupCol+" = ?",
keywordInt, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", group)
} else {
// 应用精确匹配过滤器
for field, value := range filters {
if value != "" && allowedFields[field] {
query = query.Where(field+" = ?", value)
}
}
// 构建搜索条件
if keyword != "" {
likeCondition := "username LIKE ? OR email LIKE ? OR display_name LIKE ?"
// 尝试将关键字转换为整数ID
keywordInt, err := strconv.Atoi(keyword)
if err == nil {
// 如果是数字同时搜索ID和其他字段
likeCondition = "id = ? OR " + likeCondition
query = query.Where(likeCondition,
keywordInt, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
}
} else {
// 非数字关键字,只搜索字符串字段
if group != "" {
query = query.Where("("+likeCondition+") AND "+commonGroupCol+" = ?",
"%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", group)
} else {
// 非数字关键字,只搜索字符串字段
query = query.Where(likeCondition,
"%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
}
}
if group != "" {
query = query.Where(commonGroupCol+" = ?", group)
}
// 获取总数
err = query.Count(&total).Error
if err != nil {
@@ -928,4 +950,4 @@ func RootUserExists() bool {
return false
}
return true
}
}