diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index f30ba8b5dd..be02d3e198 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -416,6 +416,10 @@ func SearchUsers(ctx *context.APIContext) { // in: query // description: user's login name to search for // type: string + // - name: is_2fa_enabled + // in: query + // description: whether or not to filter users with the 2fa enabled + // type: boolean // - name: sort // in: query // description: sort order of results @@ -446,12 +450,13 @@ func SearchUsers(ctx *context.APIContext) { } users, maxResults, err := user_model.SearchUsers(ctx, &user_model.SearchUserOptions{ - Actor: ctx.Doer, - Type: user_model.UserTypeIndividual, - LoginName: ctx.FormTrim("login_name"), - SourceID: sourceID, - OrderBy: utils.GetDbSearchOrder(ctx), - ListOptions: listOptions, + Actor: ctx.Doer, + Type: user_model.UserTypeIndividual, + LoginName: ctx.FormTrim("login_name"), + IsTwoFactorEnabled: ctx.FormOptionalBool("is_2fa_enabled"), + SourceID: sourceID, + OrderBy: utils.GetDbSearchOrder(ctx), + ListOptions: listOptions, }) if err != nil { ctx.Error(http.StatusInternalServerError, "SearchUsers", err) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index e872051b18..3401d42641 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1509,6 +1509,12 @@ "name": "login_name", "in": "query" }, + { + "type": "boolean", + "description": "whether or not to filter users with the 2fa enabled", + "name": "is_2fa_enabled", + "in": "query" + }, { "enum": [ "oldest", diff --git a/tests/integration/api_admin_test.go b/tests/integration/api_admin_test.go index 70a921a0a4..513eac1155 100644 --- a/tests/integration/api_admin_test.go +++ b/tests/integration/api_admin_test.go @@ -169,6 +169,38 @@ func TestAPIListUsers(t *testing.T) { assert.Len(t, users, numberOfUsers) } +func TestAPIListUsersNo2FA(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + adminUsername := "user1" + token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeReadAdmin) + + req := NewRequest(t, "GET", "/api/v1/admin/users?is_2fa_enabled=0"). + AddTokenAuth(token) + resp := MakeRequest(t, req, http.StatusOK) + total := resp.Header().Get("X-Total-Count") + + numberOfUsers := "28" + + assert.Equal(t, numberOfUsers, total) +} + +func TestAPIListUsers2FA(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + adminUsername := "user1" + token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeReadAdmin) + + req := NewRequest(t, "GET", "/api/v1/admin/users?is_2fa_enabled=1"). + AddTokenAuth(token) + resp := MakeRequest(t, req, http.StatusOK) + total := resp.Header().Get("X-Total-Count") + + numberOfUsers := "2" + + assert.Equal(t, numberOfUsers, total) +} + func TestAPIListUsersNotLoggedIn(t *testing.T) { defer tests.PrepareTestEnv(t)() req := NewRequest(t, "GET", "/api/v1/admin/users")