User searching improvements
Remove standalone findbyIDs, add filtering by user and role ID
This commit is contained in:
@@ -697,6 +697,18 @@
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"get": [
|
||||
{
|
||||
"name": "userID",
|
||||
"type": "[]string",
|
||||
"required": false,
|
||||
"title": "Filter by user ID"
|
||||
},
|
||||
{
|
||||
"name": "roleID",
|
||||
"type": "[]string",
|
||||
"required": false,
|
||||
"title": "Filter by role membership"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "query",
|
||||
|
||||
@@ -23,6 +23,18 @@
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"get": [
|
||||
{
|
||||
"name": "userID",
|
||||
"required": false,
|
||||
"title": "Filter by user ID",
|
||||
"type": "[]string"
|
||||
},
|
||||
{
|
||||
"name": "roleID",
|
||||
"required": false,
|
||||
"title": "Filter by role membership",
|
||||
"type": "[]string"
|
||||
},
|
||||
{
|
||||
"name": "query",
|
||||
"required": false,
|
||||
|
||||
@@ -1106,6 +1106,8 @@ An organisation may have many roles. Roles may have many channels available. Acc
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| userID | []string | GET | Filter by user ID | N/A | NO |
|
||||
| roleID | []string | GET | Filter by role membership | N/A | NO |
|
||||
| query | string | GET | Search query to match against users | N/A | NO |
|
||||
| username | string | GET | Search username to match against users | N/A | NO |
|
||||
| email | string | GET | Search email to match against users | N/A | NO |
|
||||
|
||||
@@ -20,7 +20,6 @@ type (
|
||||
FindByUsername(username string) (*types.User, error)
|
||||
FindByHandle(handle string) (*types.User, error)
|
||||
FindByID(id uint64) (*types.User, error)
|
||||
FindByIDs(id ...uint64) (types.UserSet, error)
|
||||
Find(filter types.UserFilter) (set types.UserSet, f types.UserFilter, err error)
|
||||
Total() uint
|
||||
|
||||
@@ -111,19 +110,6 @@ func (r user) FindByID(id uint64) (*types.User, error) {
|
||||
return r.findBy("id", id)
|
||||
}
|
||||
|
||||
func (r user) FindByIDs(IDs ...uint64) (types.UserSet, error) {
|
||||
if len(IDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
query = r.query().Where("u.id IN (?)", IDs)
|
||||
uu = types.UserSet{}
|
||||
)
|
||||
|
||||
return uu, r.fetchSet(&uu, query)
|
||||
}
|
||||
|
||||
func (r user) Find(filter types.UserFilter) (set types.UserSet, f types.UserFilter, err error) {
|
||||
f = filter
|
||||
q := r.queryNoFilter()
|
||||
@@ -139,6 +125,21 @@ func (r user) Find(filter types.UserFilter) (set types.UserSet, f types.UserFilt
|
||||
q = q.Where(squirrel.Eq{"u.suspended_at": nil})
|
||||
}
|
||||
|
||||
if len(f.UserID) > 0 {
|
||||
q = q.Where(squirrel.Eq{"u.ID": f.UserID})
|
||||
}
|
||||
|
||||
if len(f.RoleID) > 0 {
|
||||
or := squirrel.Or{}
|
||||
// Due to lack of support for more exotic expressions (slice of values inside subquery)
|
||||
// we'll use set of OR expressions as a workaround
|
||||
for _, roleID := range f.RoleID {
|
||||
or = append(or, squirrel.Expr("u.ID IN (SELECT rel_user FROM sys_role_member WHERE rel_role IN (?))", roleID))
|
||||
}
|
||||
|
||||
q = q.Where(or)
|
||||
}
|
||||
|
||||
if f.Query != "" {
|
||||
qs := f.Query + "%"
|
||||
q = q.Where(squirrel.Or{
|
||||
|
||||
@@ -34,6 +34,8 @@ var _ = multipart.FileHeader{}
|
||||
|
||||
// User list request parameters
|
||||
type UserList struct {
|
||||
UserID []string
|
||||
RoleID []string
|
||||
Query string
|
||||
Username string
|
||||
Email string
|
||||
@@ -53,6 +55,8 @@ func NewUserList() *UserList {
|
||||
func (r UserList) Auditable() map[string]interface{} {
|
||||
var out = map[string]interface{}{}
|
||||
|
||||
out["userID"] = r.UserID
|
||||
out["roleID"] = r.RoleID
|
||||
out["query"] = r.Query
|
||||
out["username"] = r.Username
|
||||
out["email"] = r.Email
|
||||
@@ -94,6 +98,18 @@ func (r *UserList) Fill(req *http.Request) (err error) {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := urlQuery["userID[]"]; ok {
|
||||
r.UserID = parseStrings(val)
|
||||
} else if val, ok = urlQuery["userID"]; ok {
|
||||
r.UserID = parseStrings(val)
|
||||
}
|
||||
|
||||
if val, ok := urlQuery["roleID[]"]; ok {
|
||||
r.RoleID = parseStrings(val)
|
||||
} else if val, ok = urlQuery["roleID"]; ok {
|
||||
r.RoleID = parseStrings(val)
|
||||
}
|
||||
|
||||
if val, ok := get["query"]; ok {
|
||||
r.Query = val
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ func (User) New() *User {
|
||||
|
||||
func (ctrl User) List(ctx context.Context, r *request.UserList) (interface{}, error) {
|
||||
f := types.UserFilter{
|
||||
UserID: payload.ParseUInt64s(r.UserID),
|
||||
RoleID: payload.ParseUInt64s(r.RoleID),
|
||||
Query: r.Query,
|
||||
Email: r.Email,
|
||||
Username: r.Username,
|
||||
|
||||
@@ -73,7 +73,6 @@ type (
|
||||
FindByEmail(email string) (*types.User, error)
|
||||
FindByHandle(handle string) (*types.User, error)
|
||||
FindByID(id uint64) (*types.User, error)
|
||||
FindByIDs(id ...uint64) (types.UserSet, error)
|
||||
Find(types.UserFilter) (types.UserSet, types.UserFilter, error)
|
||||
|
||||
Create(input *types.User) (*types.User, error)
|
||||
@@ -156,12 +155,6 @@ func (svc user) proc(u *types.User, err error) (*types.User, error) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (svc user) FindByIDs(userIDs ...uint64) (types.UserSet, error) {
|
||||
uu, err := svc.user.FindByIDs(userIDs...)
|
||||
uu, _, err = svc.procSet(uu, types.UserFilter{}, err)
|
||||
return uu, err
|
||||
}
|
||||
|
||||
func (svc user) Find(f types.UserFilter) (types.UserSet, types.UserFilter, error) {
|
||||
if f.IncDeleted || f.IncSuspended {
|
||||
// If list with deleted or suspended users is requested
|
||||
|
||||
@@ -44,6 +44,8 @@ type (
|
||||
}
|
||||
|
||||
UserFilter struct {
|
||||
UserID []uint64 `json:"userID"`
|
||||
RoleID []uint64 `json:"roleID"`
|
||||
Query string `json:"query"`
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
|
||||
Reference in New Issue
Block a user