Skip to content

Commit 0d11ba9

Browse files
Fix the permission check for user search API and limit the number of returned users for /user/search (#32310)
Partially backport #32288 --------- Co-authored-by: wxiaoguang <[email protected]>
1 parent b7d1234 commit 0d11ba9

File tree

4 files changed

+32
-40
lines changed

4 files changed

+32
-40
lines changed

routers/api/v1/api.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,20 @@ func reqToken() func(ctx *context.APIContext) {
356356

357357
func reqExploreSignIn() func(ctx *context.APIContext) {
358358
return func(ctx *context.APIContext) {
359-
if setting.Service.Explore.RequireSigninView && !ctx.IsSigned {
359+
if (setting.Service.RequireSignInView || setting.Service.Explore.RequireSigninView) && !ctx.IsSigned {
360360
ctx.Error(http.StatusUnauthorized, "reqExploreSignIn", "you must be signed in to search for users")
361361
}
362362
}
363363
}
364364

365+
func reqUsersExploreEnabled() func(ctx *context.APIContext) {
366+
return func(ctx *context.APIContext) {
367+
if setting.Service.Explore.DisableUsersPage {
368+
ctx.NotFound()
369+
}
370+
}
371+
}
372+
365373
func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) {
366374
return func(ctx *context.APIContext) {
367375
if ctx.IsSigned && setting.Service.EnableReverseProxyAuthAPI && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName {
@@ -955,7 +963,7 @@ func Routes() *web.Route {
955963

956964
// Users (requires user scope)
957965
m.Group("/users", func() {
958-
m.Get("/search", reqExploreSignIn(), user.Search)
966+
m.Get("/search", reqExploreSignIn(), reqUsersExploreEnabled(), user.Search)
959967

960968
m.Group("/{username}", func() {
961969
m.Get("", reqExploreSignIn(), user.GetInfo)

routers/web/user/search.go

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,24 @@ import (
88

99
"code.gitea.io/gitea/models/db"
1010
user_model "code.gitea.io/gitea/models/user"
11+
"code.gitea.io/gitea/modules/optional"
12+
"code.gitea.io/gitea/modules/setting"
1113
"code.gitea.io/gitea/services/context"
1214
"code.gitea.io/gitea/services/convert"
1315
)
1416

15-
// Search search users
16-
func Search(ctx *context.Context) {
17-
listOptions := db.ListOptions{
18-
Page: ctx.FormInt("page"),
19-
PageSize: convert.ToCorrectPageSize(ctx.FormInt("limit")),
20-
}
21-
22-
users, maxResults, err := user_model.SearchUsers(ctx, &user_model.SearchUserOptions{
17+
// SearchCandidates searches candidate users for dropdown list
18+
func SearchCandidates(ctx *context.Context) {
19+
users, _, err := user_model.SearchUsers(ctx, &user_model.SearchUserOptions{
2320
Actor: ctx.Doer,
2421
Keyword: ctx.FormTrim("q"),
25-
UID: ctx.FormInt64("uid"),
2622
Type: user_model.UserTypeIndividual,
27-
IsActive: ctx.FormOptionalBool("active"),
28-
ListOptions: listOptions,
23+
IsActive: optional.Some(true),
24+
ListOptions: db.ListOptions{PageSize: setting.UI.MembersPagingNum},
2925
})
3026
if err != nil {
31-
ctx.JSON(http.StatusInternalServerError, map[string]any{
32-
"ok": false,
33-
"error": err.Error(),
34-
})
27+
ctx.ServerError("Unable to search users", err)
3528
return
3629
}
37-
38-
ctx.SetTotalCountHeader(maxResults)
39-
40-
ctx.JSON(http.StatusOK, map[string]any{
41-
"ok": true,
42-
"data": convert.ToUsers(ctx, ctx.Doer, users),
43-
})
30+
ctx.JSON(http.StatusOK, map[string]any{"data": convert.ToUsers(ctx, ctx.Doer, users)})
4431
}

routers/web/web.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ func registerRoutes(m *web.Route) {
668668
m.Post("/forgot_password", auth.ForgotPasswdPost)
669669
m.Post("/logout", auth.SignOut)
670670
m.Get("/stopwatches", reqSignIn, user.GetStopwatches)
671-
m.Get("/search", ignExploreSignIn, user.Search)
671+
m.Get("/search_candidates", ignExploreSignIn, user.SearchCandidates)
672672
m.Group("/oauth2", func() {
673673
m.Get("/{provider}", auth.SignInOAuth)
674674
m.Get("/{provider}/callback", auth.SignInOAuthCallback)

web_src/js/features/comp/SearchUserBox.js

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,38 @@ export function initCompSearchUserBox() {
88
const searchUserBox = document.getElementById('search-user-box');
99
if (!searchUserBox) return;
1010

11-
const $searchUserBox = $(searchUserBox);
1211
const allowEmailInput = searchUserBox.getAttribute('data-allow-email') === 'true';
1312
const allowEmailDescription = searchUserBox.getAttribute('data-allow-email-description') ?? undefined;
14-
$searchUserBox.search({
13+
$(searchUserBox).search({
1514
minCharacters: 2,
1615
apiSettings: {
17-
url: `${appSubUrl}/user/search?active=1&q={query}`,
16+
url: `${appSubUrl}/user/search_candidates?q={query}`,
1817
onResponse(response) {
19-
const items = [];
20-
const searchQuery = $searchUserBox.find('input').val();
18+
const resultItems = [];
19+
const searchQuery = searchUserBox.querySelector('input').value;
2120
const searchQueryUppercase = searchQuery.toUpperCase();
22-
$.each(response.data, (_i, item) => {
21+
for (const item of response.data) {
2322
const resultItem = {
2423
title: item.login,
2524
image: item.avatar_url,
25+
description: htmlEscape(item.full_name),
2626
};
27-
if (item.full_name) {
28-
resultItem.description = htmlEscape(item.full_name);
29-
}
3027
if (searchQueryUppercase === item.login.toUpperCase()) {
31-
items.unshift(resultItem);
28+
resultItems.unshift(resultItem); // add the exact match to the top
3229
} else {
33-
items.push(resultItem);
30+
resultItems.push(resultItem);
3431
}
35-
});
32+
}
3633

37-
if (allowEmailInput && !items.length && looksLikeEmailAddressCheck.test(searchQuery)) {
34+
if (allowEmailInput && !resultItems.length && looksLikeEmailAddressCheck.test(searchQuery)) {
3835
const resultItem = {
3936
title: searchQuery,
4037
description: allowEmailDescription,
4138
};
42-
items.push(resultItem);
39+
resultItems.push(resultItem);
4340
}
4441

45-
return {results: items};
42+
return {results: resultItems};
4643
},
4744
},
4845
searchFields: ['login', 'full_name'],

0 commit comments

Comments
 (0)