aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/user/search.go14
-rw-r--r--routers/api/v1/user/user.go11
-rw-r--r--tests/integration/api_user_search_test.go36
3 files changed, 55 insertions, 6 deletions
diff --git a/models/user/search.go b/models/user/search.go
index 45b051187e..382b6fac2b 100644
--- a/models/user/search.go
+++ b/models/user/search.go
@@ -65,7 +65,19 @@ func (opts *SearchUserOptions) toSearchQueryBase(ctx context.Context) *xorm.Sess
builder.Like{"LOWER(full_name)", lowerKeyword},
)
if opts.SearchByEmail {
- keywordCond = keywordCond.Or(builder.Like{"LOWER(email)", lowerKeyword})
+ var emailCond builder.Cond
+ emailCond = builder.Like{"LOWER(email)", lowerKeyword}
+ if opts.Actor == nil {
+ emailCond = emailCond.And(builder.Eq{"keep_email_private": false})
+ } else if !opts.Actor.IsAdmin {
+ emailCond = emailCond.And(
+ builder.Or(
+ builder.Eq{"keep_email_private": false},
+ builder.Eq{"id": opts.Actor.ID},
+ ),
+ )
+ }
+ keywordCond = keywordCond.Or(emailCond)
}
cond = cond.And(keywordCond)
diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go
index fedad87fc4..2c277a18c7 100644
--- a/routers/api/v1/user/user.go
+++ b/routers/api/v1/user/user.go
@@ -68,11 +68,12 @@ func Search(ctx *context.APIContext) {
users = []*user_model.User{user_model.NewActionsUser()}
default:
users, maxResults, err = user_model.SearchUsers(ctx, &user_model.SearchUserOptions{
- Actor: ctx.Doer,
- Keyword: ctx.FormTrim("q"),
- UID: uid,
- Type: user_model.UserTypeIndividual,
- ListOptions: listOptions,
+ Actor: ctx.Doer,
+ Keyword: ctx.FormTrim("q"),
+ UID: uid,
+ Type: user_model.UserTypeIndividual,
+ SearchByEmail: true,
+ ListOptions: listOptions,
})
if err != nil {
ctx.JSON(http.StatusInternalServerError, map[string]any{
diff --git a/tests/integration/api_user_search_test.go b/tests/integration/api_user_search_test.go
index f776b35325..ff4671c54e 100644
--- a/tests/integration/api_user_search_test.go
+++ b/tests/integration/api_user_search_test.go
@@ -109,3 +109,39 @@ func TestAPIUserSearchNotLoggedInUserHidden(t *testing.T) {
DecodeJSON(t, resp, &results)
assert.Empty(t, results.Data)
}
+
+func TestAPIUserSearchByEmail(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ // admin can search user with private email
+ adminUsername := "user1"
+ session := loginUser(t, adminUsername)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
+ query := "user2@example.com"
+ req := NewRequestf(t, "GET", "/api/v1/users/search?q=%s", query).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+
+ var results SearchResults
+ DecodeJSON(t, resp, &results)
+ assert.Equal(t, 1, len(results.Data))
+ assert.Equal(t, query, results.Data[0].Email)
+
+ // no login user can not search user with private email
+ req = NewRequestf(t, "GET", "/api/v1/users/search?q=%s", query)
+ resp = MakeRequest(t, req, http.StatusOK)
+ DecodeJSON(t, resp, &results)
+ assert.Empty(t, results.Data)
+
+ // user can search self with private email
+ user2 := "user2"
+ session = loginUser(t, user2)
+ token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser)
+ req = NewRequestf(t, "GET", "/api/v1/users/search?q=%s", query).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+
+ DecodeJSON(t, resp, &results)
+ assert.Equal(t, 1, len(results.Data))
+ assert.Equal(t, query, results.Data[0].Email)
+}