Skip to content

Commit 6ec918e

Browse files
committed
use OptionalBool instead of status map
1 parent 79a2be0 commit 6ec918e

File tree

4 files changed

+62
-40
lines changed

4 files changed

+62
-40
lines changed

models/user.go

+31-38
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@ import (
1616
"os"
1717
"path/filepath"
1818
"regexp"
19-
"strconv"
2019
"strings"
2120
"time"
2221
"unicode/utf8"
23-
"xorm.io/xorm"
2422

2523
"code.gitea.io/gitea/modules/base"
2624
"code.gitea.io/gitea/modules/git"
@@ -35,7 +33,9 @@ import (
3533
"golang.org/x/crypto/bcrypt"
3634
"golang.org/x/crypto/pbkdf2"
3735
"golang.org/x/crypto/scrypt"
36+
3837
"xorm.io/builder"
38+
"xorm.io/xorm"
3939
)
4040

4141
// UserType defines the user type
@@ -1590,15 +1590,19 @@ func GetUser(user *User) (bool, error) {
15901590
// SearchUserOptions contains the options for searching
15911591
type SearchUserOptions struct {
15921592
ListOptions
1593-
Keyword string
1594-
StatusFilterMap map[string]string // Admin can apply advanced search filters
1595-
Type UserType
1596-
UID int64
1597-
OrderBy SearchOrderBy
1598-
Visible []structs.VisibleType
1599-
Actor *User // The user doing the search
1600-
IsActive util.OptionalBool
1601-
SearchByEmail bool // Search by email as well as username/full name
1593+
Keyword string
1594+
Type UserType
1595+
UID int64
1596+
OrderBy SearchOrderBy
1597+
Visible []structs.VisibleType
1598+
Actor *User // The user doing the search
1599+
SearchByEmail bool // Search by email as well as username/full name
1600+
1601+
IsActive util.OptionalBool
1602+
IsAdmin util.OptionalBool
1603+
IsRestricted util.OptionalBool
1604+
IsTwoFactorEnabled util.OptionalBool
1605+
IsProhibitLogin util.OptionalBool
16021606
}
16031607

16041608
func (opts *SearchUserOptions) toConds() builder.Cond {
@@ -1640,6 +1644,7 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
16401644
accessCond = accessCond.Or(builder.Eq{"id": opts.Actor.ID})
16411645
cond = cond.And(accessCond)
16421646
}
1647+
16431648
} else {
16441649
// Force visibility for privacy
16451650
// Not logged in - only public users
@@ -1654,6 +1659,18 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
16541659
cond = cond.And(builder.Eq{"is_active": opts.IsActive.IsTrue()})
16551660
}
16561661

1662+
if !opts.IsAdmin.IsNone() {
1663+
cond = cond.And(builder.Eq{"is_admin": opts.IsAdmin.IsTrue()})
1664+
}
1665+
1666+
if !opts.IsRestricted.IsNone() {
1667+
cond = cond.And(builder.Eq{"is_restricted": opts.IsRestricted.IsTrue()})
1668+
}
1669+
1670+
if !opts.IsProhibitLogin.IsNone() {
1671+
cond = cond.And(builder.Eq{"prohibit_login": opts.IsProhibitLogin.IsTrue()})
1672+
}
1673+
16571674
return cond
16581675
}
16591676

@@ -1662,38 +1679,14 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
16621679
func SearchUsers(opts *SearchUserOptions) (users []*User, _ int64, _ error) {
16631680
cond := opts.toConds()
16641681

1665-
searchFilterTwoFactorValue := ""
1666-
if opts.Actor != nil && opts.Actor.IsAdmin {
1667-
// Admin can apply advanced filters
1668-
for filterKey, filterValue := range opts.StatusFilterMap {
1669-
if filterValue == "" {
1670-
continue
1671-
}
1672-
parsedBool, _ := strconv.ParseBool(filterValue)
1673-
if filterKey == "is_active" {
1674-
cond = cond.And(builder.Eq{"is_active": parsedBool})
1675-
} else if filterKey == "is_admin" {
1676-
cond = cond.And(builder.Eq{"is_admin": parsedBool})
1677-
} else if filterKey == "is_restricted" {
1678-
cond = cond.And(builder.Eq{"is_restricted": parsedBool})
1679-
} else if filterKey == "is_prohibit_login" {
1680-
cond = cond.And(builder.Eq{"prohibit_login": parsedBool})
1681-
} else if filterKey == "is_2fa_enabled" {
1682-
searchFilterTwoFactorValue = filterValue
1683-
} else {
1684-
log.Error("Unknown admin user search filter: %v=%v", filterKey, filterValue)
1685-
}
1686-
}
1687-
}
1688-
1689-
searchUserBaseQuery := func () (sess *xorm.Session) {
1682+
searchUserBaseQuery := func() (sess *xorm.Session) {
16901683
sess = x.Where(cond)
16911684

1692-
if searchFilterTwoFactorValue != "" {
1685+
if !opts.IsTwoFactorEnabled.IsNone() {
16931686
// 2fa filter uses LEFT JOIN to check whether a user has a 2fa record
16941687
// TODO: bad performance here, maybe there will be a column "is_2fa_enabled" in the future
16951688
sess = sess.Join("LEFT OUTER", "two_factor", "two_factor.uid = `user`.id")
1696-
if searchFilterTwoFactorValue == "1" {
1689+
if opts.IsTwoFactorEnabled.IsTrue() {
16971690
cond = cond.And(builder.Expr("two_factor.uid IS NOT NULL"))
16981691
} else {
16991692
cond = cond.And(builder.Expr("two_factor.uid IS NULL"))

modules/util/util.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"crypto/rand"
1010
"errors"
1111
"math/big"
12+
"strconv"
1213
"strings"
1314
)
1415

@@ -17,7 +18,7 @@ type OptionalBool byte
1718

1819
const (
1920
// OptionalBoolNone a "null" boolean value
20-
OptionalBoolNone = iota
21+
OptionalBoolNone OptionalBool = iota
2122
// OptionalBoolTrue a "true" boolean value
2223
OptionalBoolTrue
2324
// OptionalBoolFalse a "false" boolean value
@@ -47,6 +48,15 @@ func OptionalBoolOf(b bool) OptionalBool {
4748
return OptionalBoolFalse
4849
}
4950

51+
// OptionalBoolParse get the corresponding OptionalBool of a string using strconv.ParseBool
52+
func OptionalBoolParse(s string) OptionalBool {
53+
b, e := strconv.ParseBool(s)
54+
if e != nil {
55+
return OptionalBoolNone
56+
}
57+
return OptionalBoolOf(b)
58+
}
59+
5060
// Max max of two ints
5161
func Max(a, b int) int {
5262
if a < b {

modules/util/util_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,16 @@ func Test_RandomString(t *testing.T) {
156156

157157
assert.NotEqual(t, str3, str4)
158158
}
159+
160+
func Test_OptionalBool(t *testing.T) {
161+
assert.Equal(t, OptionalBoolNone, OptionalBoolParse(""))
162+
assert.Equal(t, OptionalBoolNone, OptionalBoolParse("x"))
163+
164+
assert.Equal(t, OptionalBoolFalse, OptionalBoolParse("0"))
165+
assert.Equal(t, OptionalBoolFalse, OptionalBoolParse("f"))
166+
assert.Equal(t, OptionalBoolFalse, OptionalBoolParse("False"))
167+
168+
assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("1"))
169+
assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("t"))
170+
assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("True"))
171+
}

routers/web/explore/user.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,15 @@ func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplN
6868
statusFilterMap[filterKey] = ctx.FormString("status_filter[" + filterKey + "]")
6969
}
7070

71+
opts.IsActive = util.OptionalBoolParse(statusFilterMap["is_active"])
72+
opts.IsAdmin = util.OptionalBoolParse(statusFilterMap["is_admin"])
73+
opts.IsRestricted = util.OptionalBoolParse(statusFilterMap["is_restricted"])
74+
opts.IsTwoFactorEnabled = util.OptionalBoolParse(statusFilterMap["is_2fa_enabled"])
75+
opts.IsProhibitLogin = util.OptionalBoolParse(statusFilterMap["is_prohibit_login"])
76+
7177
opts.Keyword = ctx.FormTrim("q")
7278
opts.OrderBy = orderBy
73-
opts.StatusFilterMap = statusFilterMap
79+
7480
if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
7581
users, count, err = models.SearchUsers(opts)
7682
if err != nil {

0 commit comments

Comments
 (0)