mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Backend api for filtering users using filter query string (#2553)
* User search query string
This commit is contained in:
@@ -285,19 +285,25 @@ func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
|
||||
users = tmp
|
||||
}
|
||||
|
||||
if len(params.Status) == 0 {
|
||||
params.Status = []database.UserStatus{database.UserStatusActive}
|
||||
}
|
||||
|
||||
usersFilteredByStatus := make([]database.User, 0, len(users))
|
||||
for i, user := range users {
|
||||
for _, status := range params.Status {
|
||||
if user.Status == status {
|
||||
if len(params.Status) > 0 {
|
||||
usersFilteredByStatus := make([]database.User, 0, len(users))
|
||||
for i, user := range users {
|
||||
if slice.Contains(params.Status, user.Status) {
|
||||
usersFilteredByStatus = append(usersFilteredByStatus, users[i])
|
||||
}
|
||||
}
|
||||
users = usersFilteredByStatus
|
||||
}
|
||||
|
||||
if len(params.RbacRole) > 0 {
|
||||
usersFilteredByRole := make([]database.User, 0, len(users))
|
||||
for i, user := range users {
|
||||
if slice.Overlap(params.RbacRole, user.RBACRoles) {
|
||||
usersFilteredByRole = append(usersFilteredByRole, users[i])
|
||||
}
|
||||
}
|
||||
users = usersFilteredByRole
|
||||
}
|
||||
users = usersFilteredByStatus
|
||||
|
||||
if params.OffsetOpt > 0 {
|
||||
if int(params.OffsetOpt) > len(users)-1 {
|
||||
|
||||
@@ -30,3 +30,10 @@ func (d ProvisionerDaemon) RBACObject() rbac.Object {
|
||||
func (f File) RBACObject() rbac.Object {
|
||||
return rbac.ResourceFile.WithID(f.Hash).WithOwner(f.CreatedBy.String())
|
||||
}
|
||||
|
||||
// RBACObject returns the RBAC object for the site wide user resource.
|
||||
// If you are trying to get the RBAC object for the UserData, use
|
||||
// rbac.ResourceUserData
|
||||
func (u User) RBACObject() rbac.Object {
|
||||
return rbac.ResourceUser.WithID(u.ID.String())
|
||||
}
|
||||
|
||||
@@ -2571,27 +2571,33 @@ WHERE
|
||||
AND CASE
|
||||
-- @status needs to be a text because it can be empty, If it was
|
||||
-- user_status enum, it would not.
|
||||
WHEN cardinality($3 :: user_status[]) > 0 THEN (
|
||||
WHEN cardinality($3 :: user_status[]) > 0 THEN
|
||||
status = ANY($3 :: user_status[])
|
||||
)
|
||||
ELSE
|
||||
-- Only show active by default
|
||||
status = 'active'
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by rbac_roles
|
||||
AND CASE
|
||||
-- @rbac_role allows filtering by rbac roles. If 'member' is included, show everyone, as
|
||||
-- everyone is a member.
|
||||
WHEN cardinality($4 :: text[]) > 0 AND 'member' != ANY($4 :: text[]) THEN
|
||||
rbac_roles && $4 :: text[]
|
||||
ELSE true
|
||||
END
|
||||
-- End of filters
|
||||
ORDER BY
|
||||
-- Deterministic and consistent ordering of all users, even if they share
|
||||
-- a timestamp. This is to ensure consistent pagination.
|
||||
(created_at, id) ASC OFFSET $4
|
||||
(created_at, id) ASC OFFSET $5
|
||||
LIMIT
|
||||
-- A null limit means "no limit", so -1 means return all
|
||||
NULLIF($5 :: int, -1)
|
||||
NULLIF($6 :: int, -1)
|
||||
`
|
||||
|
||||
type GetUsersParams struct {
|
||||
AfterID uuid.UUID `db:"after_id" json:"after_id"`
|
||||
Search string `db:"search" json:"search"`
|
||||
Status []UserStatus `db:"status" json:"status"`
|
||||
RbacRole []string `db:"rbac_role" json:"rbac_role"`
|
||||
OffsetOpt int32 `db:"offset_opt" json:"offset_opt"`
|
||||
LimitOpt int32 `db:"limit_opt" json:"limit_opt"`
|
||||
}
|
||||
@@ -2601,6 +2607,7 @@ func (q *sqlQuerier) GetUsers(ctx context.Context, arg GetUsersParams) ([]User,
|
||||
arg.AfterID,
|
||||
arg.Search,
|
||||
pq.Array(arg.Status),
|
||||
pq.Array(arg.RbacRole),
|
||||
arg.OffsetOpt,
|
||||
arg.LimitOpt,
|
||||
)
|
||||
|
||||
@@ -108,12 +108,17 @@ WHERE
|
||||
AND CASE
|
||||
-- @status needs to be a text because it can be empty, If it was
|
||||
-- user_status enum, it would not.
|
||||
WHEN cardinality(@status :: user_status[]) > 0 THEN (
|
||||
WHEN cardinality(@status :: user_status[]) > 0 THEN
|
||||
status = ANY(@status :: user_status[])
|
||||
)
|
||||
ELSE
|
||||
-- Only show active by default
|
||||
status = 'active'
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by rbac_roles
|
||||
AND CASE
|
||||
-- @rbac_role allows filtering by rbac roles. If 'member' is included, show everyone, as
|
||||
-- everyone is a member.
|
||||
WHEN cardinality(@rbac_role :: text[]) > 0 AND 'member' != ANY(@rbac_role :: text[]) THEN
|
||||
rbac_roles && @rbac_role :: text[]
|
||||
ELSE true
|
||||
END
|
||||
-- End of filters
|
||||
ORDER BY
|
||||
|
||||
Reference in New Issue
Block a user