mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-18 15:23:11 +00:00
Merge pull request 'Add sorting functionality to /api/v1/admin/users
endpoint' (#6228) from awiteb/forgejo:sort-user-search-endpoint into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6228 Reviewed-by: Otto <otto@codeberg.org>
This commit is contained in:
commit
6a4a24e2d7
5 changed files with 148 additions and 4 deletions
|
@ -36,6 +36,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578000
|
||||
|
||||
-
|
||||
id: 2
|
||||
|
@ -74,6 +75,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578010
|
||||
|
||||
-
|
||||
id: 3
|
||||
|
@ -111,6 +113,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578020
|
||||
|
||||
-
|
||||
id: 4
|
||||
|
@ -148,6 +151,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578030
|
||||
|
||||
-
|
||||
id: 5
|
||||
|
@ -185,6 +189,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578040
|
||||
|
||||
-
|
||||
id: 6
|
||||
|
@ -222,6 +227,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578050
|
||||
|
||||
-
|
||||
id: 7
|
||||
|
@ -259,6 +265,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578060
|
||||
|
||||
-
|
||||
id: 8
|
||||
|
@ -296,6 +303,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578070
|
||||
|
||||
-
|
||||
id: 9
|
||||
|
@ -333,7 +341,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1730468968
|
||||
created_unix: 1672578080
|
||||
|
||||
-
|
||||
id: 10
|
||||
|
@ -371,6 +379,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578090
|
||||
|
||||
-
|
||||
id: 11
|
||||
|
@ -408,6 +417,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578100
|
||||
|
||||
-
|
||||
id: 12
|
||||
|
@ -445,6 +455,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578110
|
||||
|
||||
-
|
||||
id: 13
|
||||
|
@ -482,6 +493,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578120
|
||||
|
||||
-
|
||||
id: 14
|
||||
|
@ -519,6 +531,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578130
|
||||
|
||||
-
|
||||
id: 15
|
||||
|
@ -556,6 +569,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578140
|
||||
|
||||
-
|
||||
id: 16
|
||||
|
@ -593,6 +607,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578150
|
||||
|
||||
-
|
||||
id: 17
|
||||
|
@ -630,6 +645,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578160
|
||||
|
||||
-
|
||||
id: 18
|
||||
|
@ -667,6 +683,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578170
|
||||
|
||||
-
|
||||
id: 19
|
||||
|
@ -704,6 +721,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578180
|
||||
|
||||
-
|
||||
id: 20
|
||||
|
@ -741,6 +759,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578190
|
||||
|
||||
-
|
||||
id: 21
|
||||
|
@ -778,6 +797,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578200
|
||||
|
||||
-
|
||||
id: 22
|
||||
|
@ -815,6 +835,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578210
|
||||
|
||||
-
|
||||
id: 23
|
||||
|
@ -852,6 +873,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578220
|
||||
|
||||
-
|
||||
id: 24
|
||||
|
@ -889,6 +911,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578230
|
||||
|
||||
-
|
||||
id: 25
|
||||
|
@ -926,6 +949,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578240
|
||||
|
||||
-
|
||||
id: 26
|
||||
|
@ -963,6 +987,7 @@
|
|||
repo_admin_change_team_access: true
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578250
|
||||
|
||||
-
|
||||
id: 27
|
||||
|
@ -1000,6 +1025,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578260
|
||||
|
||||
-
|
||||
id: 28
|
||||
|
@ -1037,6 +1063,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578270
|
||||
|
||||
-
|
||||
id: 29
|
||||
|
@ -1074,6 +1101,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578280
|
||||
|
||||
-
|
||||
id: 30
|
||||
|
@ -1111,6 +1139,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578290
|
||||
|
||||
-
|
||||
id: 31
|
||||
|
@ -1148,6 +1177,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578300
|
||||
|
||||
-
|
||||
id: 32
|
||||
|
@ -1185,6 +1215,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578310
|
||||
|
||||
-
|
||||
id: 33
|
||||
|
@ -1222,6 +1253,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578320
|
||||
|
||||
-
|
||||
id: 34
|
||||
|
@ -1260,6 +1292,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578330
|
||||
|
||||
-
|
||||
id: 35
|
||||
|
@ -1297,6 +1330,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578340
|
||||
|
||||
-
|
||||
id: 36
|
||||
|
@ -1334,6 +1368,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578350
|
||||
|
||||
-
|
||||
id: 37
|
||||
|
@ -1371,6 +1406,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578360
|
||||
|
||||
-
|
||||
id: 38
|
||||
|
@ -1408,6 +1444,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578370
|
||||
|
||||
-
|
||||
id: 39
|
||||
|
@ -1445,6 +1482,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578380
|
||||
|
||||
-
|
||||
id: 40
|
||||
|
@ -1482,6 +1520,7 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578390
|
||||
|
||||
-
|
||||
id: 41
|
||||
|
@ -1519,3 +1558,4 @@
|
|||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
created_unix: 1672578400
|
||||
|
|
|
@ -771,11 +771,11 @@ func TestGetInactiveUsers(t *testing.T) {
|
|||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// all inactive users
|
||||
// user1's createdunix is 1730468968
|
||||
// user1's createdunix is 1672578000
|
||||
users, err := user_model.GetInactiveUsers(db.DefaultContext, 0)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, users, 1)
|
||||
interval := time.Now().Unix() - 1730468968 + 3600*24
|
||||
interval := time.Now().Unix() - 1672578000 + 3600*24
|
||||
users, err = user_model.GetInactiveUsers(db.DefaultContext, time.Duration(interval*int64(time.Second)))
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, users)
|
||||
|
|
|
@ -416,6 +416,11 @@ func SearchUsers(ctx *context.APIContext) {
|
|||
// in: query
|
||||
// description: user's login name to search for
|
||||
// type: string
|
||||
// - name: sort
|
||||
// in: query
|
||||
// description: sort order of results
|
||||
// type: string
|
||||
// enum: [oldest, newest, alphabetically, reversealphabetically, recentupdate, leastupdate]
|
||||
// - name: page
|
||||
// in: query
|
||||
// description: page number of results to return (1-based)
|
||||
|
@ -431,6 +436,27 @@ func SearchUsers(ctx *context.APIContext) {
|
|||
// "$ref": "#/responses/forbidden"
|
||||
|
||||
listOptions := utils.GetListOptions(ctx)
|
||||
|
||||
sort := ctx.FormString("sort")
|
||||
var orderBy db.SearchOrderBy
|
||||
|
||||
switch sort {
|
||||
case "oldest":
|
||||
orderBy = db.SearchOrderByOldest
|
||||
case "newest":
|
||||
orderBy = db.SearchOrderByNewest
|
||||
case "alphabetically":
|
||||
orderBy = db.SearchOrderByAlphabetically
|
||||
case "reversealphabetically":
|
||||
orderBy = db.SearchOrderByAlphabeticallyReverse
|
||||
case "recentupdate":
|
||||
orderBy = db.SearchOrderByRecentUpdated
|
||||
case "leastupdate":
|
||||
orderBy = db.SearchOrderByLeastUpdated
|
||||
default:
|
||||
orderBy = db.SearchOrderByAlphabetically
|
||||
}
|
||||
|
||||
intSource, err := strconv.ParseInt(ctx.FormString("source_id"), 10, 64)
|
||||
var sourceID optional.Option[int64]
|
||||
if ctx.FormString("source_id") == "" || err != nil {
|
||||
|
@ -444,7 +470,7 @@ func SearchUsers(ctx *context.APIContext) {
|
|||
Type: user_model.UserTypeIndividual,
|
||||
LoginName: ctx.FormTrim("login_name"),
|
||||
SourceID: sourceID,
|
||||
OrderBy: db.SearchOrderByAlphabetically,
|
||||
OrderBy: orderBy,
|
||||
ListOptions: listOptions,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
14
templates/swagger/v1_json.tmpl
generated
14
templates/swagger/v1_json.tmpl
generated
|
@ -1146,6 +1146,20 @@
|
|||
"name": "login_name",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"oldest",
|
||||
"newest",
|
||||
"alphabetically",
|
||||
"reversealphabetically",
|
||||
"recentupdate",
|
||||
"leastupdate"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "sort order of results",
|
||||
"name": "sort",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page number of results to return (1-based)",
|
||||
|
|
|
@ -9,12 +9,15 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -132,3 +135,64 @@ func TestSourceId(t *testing.T) {
|
|||
assert.Len(t, users, 1)
|
||||
assert.Equal(t, "ausersourceid23", users[0].UserName)
|
||||
}
|
||||
|
||||
func TestAdminViewUsersSorted(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
createTimestamp := time.Now().Unix() - 1000
|
||||
updateTimestamp := time.Now().Unix() - 500
|
||||
sess := db.GetEngine(context.Background())
|
||||
|
||||
// Create 10 users with login source 44
|
||||
for i := int64(1); i <= 10; i++ {
|
||||
name := "sorttest" + strconv.Itoa(int(i))
|
||||
user := &user_model.User{
|
||||
Name: name,
|
||||
LowerName: name,
|
||||
LoginName: name,
|
||||
Email: name + "@example.com",
|
||||
Passwd: name + ".password",
|
||||
Type: user_model.UserTypeIndividual,
|
||||
LoginType: auth_model.OAuth2,
|
||||
LoginSource: 44,
|
||||
CreatedUnix: timeutil.TimeStamp(createTimestamp - i),
|
||||
UpdatedUnix: timeutil.TimeStamp(updateTimestamp - i),
|
||||
}
|
||||
if _, err := sess.NoAutoTime().Insert(user); err != nil {
|
||||
t.Fatalf("Failed to create user: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadAdmin)
|
||||
|
||||
testCases := []struct {
|
||||
loginSource int64
|
||||
sortType string
|
||||
expectedUsers []string
|
||||
}{
|
||||
{0, "alphabetically", []string{"the_34-user.with.all.allowedChars", "user1", "user10", "user11"}},
|
||||
{0, "reversealphabetically", []string{"user9", "user8", "user5", "user40"}},
|
||||
{0, "newest", []string{"user40", "user39", "user38", "user37"}},
|
||||
{0, "oldest", []string{"user1", "user2", "user4", "user5"}},
|
||||
{44, "recentupdate", []string{"sorttest1", "sorttest2", "sorttest3", "sorttest4"}},
|
||||
{44, "leastupdate", []string{"sorttest10", "sorttest9", "sorttest8", "sorttest7"}},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
req := NewRequest(
|
||||
t,
|
||||
"GET",
|
||||
fmt.Sprintf("/api/v1/admin/users?sort=%s&limit=4&source_id=%d",
|
||||
testCase.sortType,
|
||||
testCase.loginSource),
|
||||
).AddTokenAuth(token)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var users []api.User
|
||||
DecodeJSON(t, resp, &users)
|
||||
assert.Len(t, users, 4)
|
||||
for i, user := range users {
|
||||
assert.Equalf(t, testCase.expectedUsers[i], user.UserName, "Sort type: %s, index %d", testCase.sortType, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue