Worked on user administration page, a grafana server admin can now add and edit organization roles for any user, #2014
This commit is contained in:
@@ -9,16 +9,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func AdminSearchUsers(c *middleware.Context) {
|
||||
query := m.SearchUsersQuery{Query: "", Page: 0, Limit: 1000}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to fetch users", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func AdminCreateUser(c *middleware.Context, form dtos.AdminCreateUserForm) {
|
||||
cmd := m.CreateUserCommand{
|
||||
Login: form.Login,
|
||||
|
||||
+7
-3
@@ -53,7 +53,8 @@ func Register(r *macaron.Macaron) {
|
||||
|
||||
// authed api
|
||||
r.Group("/api", func() {
|
||||
// user
|
||||
|
||||
// user (signed in)
|
||||
r.Group("/user", func() {
|
||||
r.Get("/", wrap(GetSignedInUser))
|
||||
r.Put("/", bind(m.UpdateUserCommand{}), wrap(UpdateSignedInUser))
|
||||
@@ -64,8 +65,9 @@ func Register(r *macaron.Macaron) {
|
||||
r.Put("/password", bind(m.ChangeUserPasswordCommand{}), ChangeUserPassword)
|
||||
})
|
||||
|
||||
// users
|
||||
// users (admin permission required)
|
||||
r.Group("/users", func() {
|
||||
r.Get("/", wrap(SearchUsers))
|
||||
r.Get("/:id", wrap(GetUserById))
|
||||
r.Get("/:id/orgs", wrap(GetUserOrgList))
|
||||
r.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser))
|
||||
@@ -84,6 +86,9 @@ func Register(r *macaron.Macaron) {
|
||||
// create new org
|
||||
r.Post("/orgs", bind(m.CreateOrgCommand{}), wrap(CreateOrg))
|
||||
|
||||
// search all orgs
|
||||
r.Get("/orgs", reqGrafanaAdmin, wrap(SearchOrgs))
|
||||
|
||||
// orgs (admin routes)
|
||||
r.Group("/orgs/:orgId", func() {
|
||||
r.Put("/", bind(m.UpdateOrgCommand{}), wrap(UpdateOrg))
|
||||
@@ -133,7 +138,6 @@ func Register(r *macaron.Macaron) {
|
||||
// admin api
|
||||
r.Group("/api/admin", func() {
|
||||
r.Get("/settings", AdminGetSettings)
|
||||
r.Get("/users", AdminSearchUsers)
|
||||
r.Post("/users", bind(dtos.AdminCreateUserForm{}), AdminCreateUser)
|
||||
r.Put("/users/:id/password", bind(dtos.AdminUpdateUserPasswordForm{}), AdminUpdateUserPassword)
|
||||
r.Put("/users/:id/permissions", bind(dtos.AdminUpdateUserPermissionsForm{}), AdminUpdateUserPermissions)
|
||||
|
||||
@@ -72,3 +72,18 @@ func updateOrgHelper(cmd m.UpdateOrgCommand) Response {
|
||||
|
||||
return ApiSuccess("Organization updated")
|
||||
}
|
||||
|
||||
func SearchOrgs(c *middleware.Context) Response {
|
||||
query := m.SearchOrgsQuery{
|
||||
Query: c.Query("query"),
|
||||
Name: c.Query("name"),
|
||||
Page: 0,
|
||||
Limit: 1000,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to search orgs", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
@@ -84,6 +84,9 @@ func updateOrgUserHelper(cmd m.UpdateOrgUserCommand) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrLastOrgAdmin {
|
||||
return ApiError(400, "Cannot change role so that there is no organization admin left", nil)
|
||||
}
|
||||
return ApiError(500, "Failed update org user", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -142,3 +142,13 @@ func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand)
|
||||
|
||||
c.JsonOK("User password changed")
|
||||
}
|
||||
|
||||
// GET /api/users
|
||||
func SearchUsers(c *middleware.Context) Response {
|
||||
query := m.SearchUsersQuery{Query: "", Page: 0, Limit: 1000}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to fetch users", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
+7
-2
@@ -48,8 +48,13 @@ type GetOrgByNameQuery struct {
|
||||
Result *Org
|
||||
}
|
||||
|
||||
type GetOrgListQuery struct {
|
||||
Result []*Org
|
||||
type SearchOrgsQuery struct {
|
||||
Query string
|
||||
Name string
|
||||
Limit int
|
||||
Page int
|
||||
|
||||
Result []*OrgDTO
|
||||
}
|
||||
|
||||
type OrgDTO struct {
|
||||
|
||||
@@ -14,12 +14,23 @@ func init() {
|
||||
bus.AddHandler("sql", CreateOrg)
|
||||
bus.AddHandler("sql", UpdateOrg)
|
||||
bus.AddHandler("sql", GetOrgByName)
|
||||
bus.AddHandler("sql", GetOrgList)
|
||||
bus.AddHandler("sql", SearchOrgs)
|
||||
bus.AddHandler("sql", DeleteOrg)
|
||||
}
|
||||
|
||||
func GetOrgList(query *m.GetOrgListQuery) error {
|
||||
return x.Find(&query.Result)
|
||||
func SearchOrgs(query *m.SearchOrgsQuery) error {
|
||||
query.Result = make([]*m.OrgDTO, 0)
|
||||
sess := x.Table("org")
|
||||
if query.Query != "" {
|
||||
sess.Where("name LIKE ?", query.Query+"%")
|
||||
}
|
||||
if query.Name != "" {
|
||||
sess.Where("name=?", query.Name)
|
||||
}
|
||||
sess.Limit(query.Limit, query.Limit*query.Page)
|
||||
sess.Cols("id", "name")
|
||||
err := sess.Find(&query.Result)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetOrgById(query *m.GetOrgByIdQuery) error {
|
||||
|
||||
@@ -142,11 +142,18 @@ func TestAccountDataAccess(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Cannot delete last admin account user", func() {
|
||||
Convey("Cannot delete last admin org user", func() {
|
||||
cmd := m.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac1.Id}
|
||||
err := RemoveOrgUser(&cmd)
|
||||
So(err, ShouldEqual, m.ErrLastOrgAdmin)
|
||||
})
|
||||
|
||||
Convey("Cannot update role so no one is admin user", func() {
|
||||
cmd := m.UpdateOrgUserCommand{OrgId: ac1.OrgId, UserId: ac1.Id, Role: m.ROLE_VIEWER}
|
||||
err := UpdateOrgUser(&cmd)
|
||||
So(err, ShouldEqual, m.ErrLastOrgAdmin)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -48,7 +48,11 @@ func UpdateOrgUser(cmd *m.UpdateOrgUserCommand) error {
|
||||
orgUser.Role = cmd.Role
|
||||
orgUser.Updated = time.Now()
|
||||
_, err = sess.Id(orgUser.Id).Update(&orgUser)
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return validateOneAdminLeftInOrg(cmd.OrgId, sess)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -72,16 +76,20 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// validate that there is an admin user left
|
||||
res, err := sess.Query("SELECT 1 from org_user WHERE org_id=? and role='Admin'", cmd.OrgId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
return m.ErrLastOrgAdmin
|
||||
}
|
||||
|
||||
return err
|
||||
return validateOneAdminLeftInOrg(cmd.OrgId, sess)
|
||||
})
|
||||
}
|
||||
|
||||
func validateOneAdminLeftInOrg(orgId int64, sess *xorm.Session) error {
|
||||
// validate that there is an admin user left
|
||||
res, err := sess.Query("SELECT 1 from org_user WHERE org_id=? and role='Admin'", orgId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
return m.ErrLastOrgAdmin
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user