3
0

User searching improvements

Remove standalone findbyIDs, add filtering by user and role ID
This commit is contained in:
Denis Arh
2019-10-10 12:23:31 +02:00
parent e1c20cef4e
commit 4134375569
8 changed files with 61 additions and 21 deletions

View File

@@ -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",

View File

@@ -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,

View File

@@ -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 |

View File

@@ -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{

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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"`