From a86f2fa34b9ccd2e3f573238199200a53e9cf3b3 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 9 Feb 2018 10:42:37 +0100 Subject: [PATCH] user picker should only include users from current org (#10845) --- pkg/api/org_users.go | 18 +++++++------ pkg/models/org_user.go | 5 +++- pkg/services/sqlstore/org_test.go | 25 +++++++++++++++++++ pkg/services/sqlstore/org_users.go | 24 +++++++++++++++++- .../app/core/components/Picker/UserPicker.tsx | 8 +++--- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/pkg/api/org_users.go b/pkg/api/org_users.go index 57a15bd8db5..433b9f2bd66 100644 --- a/pkg/api/org_users.go +++ b/pkg/api/org_users.go @@ -46,26 +46,30 @@ func addOrgUserHelper(cmd m.AddOrgUserCommand) Response { // GET /api/org/users func GetOrgUsersForCurrentOrg(c *middleware.Context) Response { - return getOrgUsersHelper(c.OrgId) + return getOrgUsersHelper(c.OrgId, c.Params("query"), c.ParamsInt("limit")) } // GET /api/orgs/:orgId/users func GetOrgUsers(c *middleware.Context) Response { - return getOrgUsersHelper(c.ParamsInt64(":orgId")) + return getOrgUsersHelper(c.ParamsInt64(":orgId"), "", 0) } -func getOrgUsersHelper(orgId int64) Response { - query := m.GetOrgUsersQuery{OrgId: orgId} +func getOrgUsersHelper(orgId int64, query string, limit int) Response { + q := m.GetOrgUsersQuery{ + OrgId: orgId, + Query: query, + Limit: limit, + } - if err := bus.Dispatch(&query); err != nil { + if err := bus.Dispatch(&q); err != nil { return ApiError(500, "Failed to get account user", err) } - for _, user := range query.Result { + for _, user := range q.Result { user.AvatarUrl = dtos.GetGravatarUrl(user.Email) } - return Json(200, query.Result) + return Json(200, q.Result) } // PATCH /api/org/users/:userId diff --git a/pkg/models/org_user.go b/pkg/models/org_user.go index 9379625d458..ca32cc50060 100644 --- a/pkg/models/org_user.go +++ b/pkg/models/org_user.go @@ -95,7 +95,10 @@ type UpdateOrgUserCommand struct { // QUERIES type GetOrgUsersQuery struct { - OrgId int64 + OrgId int64 + Query string + Limit int + Result []*OrgUserDTO } diff --git a/pkg/services/sqlstore/org_test.go b/pkg/services/sqlstore/org_test.go index 59d96c4f8ca..5322dfd4748 100644 --- a/pkg/services/sqlstore/org_test.go +++ b/pkg/services/sqlstore/org_test.go @@ -123,6 +123,31 @@ func TestAccountDataAccess(t *testing.T) { So(query.Result[0].Role, ShouldEqual, "Admin") }) + Convey("Can get organization users with query", func() { + query := m.GetOrgUsersQuery{ + OrgId: ac1.OrgId, + Query: "ac1", + } + err := GetOrgUsers(&query) + + So(err, ShouldBeNil) + So(len(query.Result), ShouldEqual, 1) + So(query.Result[0].Email, ShouldEqual, ac1.Email) + }) + + Convey("Can get organization users with query and limit", func() { + query := m.GetOrgUsersQuery{ + OrgId: ac1.OrgId, + Query: "ac", + Limit: 1, + } + err := GetOrgUsers(&query) + + So(err, ShouldBeNil) + So(len(query.Result), ShouldEqual, 1) + So(query.Result[0].Email, ShouldEqual, ac1.Email) + }) + Convey("Can set using org", func() { cmd := m.SetUsingOrgCommand{UserId: ac2.Id, OrgId: ac1.Id} err := SetUsingOrg(&cmd) diff --git a/pkg/services/sqlstore/org_users.go b/pkg/services/sqlstore/org_users.go index 2c2a51fd362..79745c30386 100644 --- a/pkg/services/sqlstore/org_users.go +++ b/pkg/services/sqlstore/org_users.go @@ -2,6 +2,7 @@ package sqlstore import ( "fmt" + "strings" "time" "github.com/grafana/grafana/pkg/bus" @@ -69,9 +70,30 @@ func UpdateOrgUser(cmd *m.UpdateOrgUserCommand) error { func GetOrgUsers(query *m.GetOrgUsersQuery) error { query.Result = make([]*m.OrgUserDTO, 0) + sess := x.Table("org_user") sess.Join("INNER", "user", fmt.Sprintf("org_user.user_id=%s.id", x.Dialect().Quote("user"))) - sess.Where("org_user.org_id=?", query.OrgId) + + whereConditions := make([]string, 0) + whereParams := make([]interface{}, 0) + + whereConditions = append(whereConditions, "org_user.org_id = ?") + whereParams = append(whereParams, query.OrgId) + + if query.Query != "" { + queryWithWildcards := "%" + query.Query + "%" + whereConditions = append(whereConditions, "(user.email "+dialect.LikeStr()+" ? OR user.name "+dialect.LikeStr()+" ? OR user.login "+dialect.LikeStr()+" ?)") + whereParams = append(whereParams, queryWithWildcards, queryWithWildcards, queryWithWildcards) + } + + if len(whereConditions) > 0 { + sess.Where(strings.Join(whereConditions, " AND "), whereParams...) + } + + if query.Limit > 0 { + sess.Limit(query.Limit, 0) + } + sess.Cols("org_user.org_id", "org_user.user_id", "user.email", "user.login", "org_user.role", "user.last_seen_at") sess.Asc("user.email", "user.login") diff --git a/public/app/core/components/Picker/UserPicker.tsx b/public/app/core/components/Picker/UserPicker.tsx index 5c36505aeaa..77bf6c1fe15 100644 --- a/public/app/core/components/Picker/UserPicker.tsx +++ b/public/app/core/components/Picker/UserPicker.tsx @@ -31,7 +31,7 @@ class UserPicker extends Component { this.debouncedSearch = debounce(this.search, 300, { leading: true, - trailing: false, + trailing: true, }); } @@ -39,10 +39,10 @@ class UserPicker extends Component { const { toggleLoading, backendSrv } = this.props; toggleLoading(true); - return backendSrv.get(`/api/users/search?perpage=10&page=1&query=${query}`).then(result => { - const users = result.users.map(user => { + return backendSrv.get(`/api/org/users?query=${query}&limit=10`).then(result => { + const users = result.map(user => { return { - id: user.id, + id: user.userId, label: `${user.login} - ${user.email}`, avatarUrl: user.avatarUrl, login: user.login,