Commit a69013c8 by Torkel Ödegaard Committed by GitHub

Merge pull request #13611 from grafana/remove-user-from-org-and-system

Remove user form org in single org setup improvement 
parents 69e0311c 19b69a82
...@@ -102,26 +102,32 @@ func updateOrgUserHelper(cmd m.UpdateOrgUserCommand) Response { ...@@ -102,26 +102,32 @@ func updateOrgUserHelper(cmd m.UpdateOrgUserCommand) Response {
// DELETE /api/org/users/:userId // DELETE /api/org/users/:userId
func RemoveOrgUserForCurrentOrg(c *m.ReqContext) Response { func RemoveOrgUserForCurrentOrg(c *m.ReqContext) Response {
userID := c.ParamsInt64(":userId") return removeOrgUserHelper(&m.RemoveOrgUserCommand{
return removeOrgUserHelper(c.OrgId, userID) UserId: c.ParamsInt64(":userId"),
OrgId: c.OrgId,
ShouldDeleteOrphanedUser: true,
})
} }
// DELETE /api/orgs/:orgId/users/:userId // DELETE /api/orgs/:orgId/users/:userId
func RemoveOrgUser(c *m.ReqContext) Response { func RemoveOrgUser(c *m.ReqContext) Response {
userID := c.ParamsInt64(":userId") return removeOrgUserHelper(&m.RemoveOrgUserCommand{
orgID := c.ParamsInt64(":orgId") UserId: c.ParamsInt64(":userId"),
return removeOrgUserHelper(orgID, userID) OrgId: c.ParamsInt64(":orgId"),
})
} }
func removeOrgUserHelper(orgID int64, userID int64) Response { func removeOrgUserHelper(cmd *m.RemoveOrgUserCommand) Response {
cmd := m.RemoveOrgUserCommand{OrgId: orgID, UserId: userID} if err := bus.Dispatch(cmd); err != nil {
if err := bus.Dispatch(&cmd); err != nil {
if err == m.ErrLastOrgAdmin { if err == m.ErrLastOrgAdmin {
return Error(400, "Cannot remove last organization admin", nil) return Error(400, "Cannot remove last organization admin", nil)
} }
return Error(500, "Failed to remove user from organization", err) return Error(500, "Failed to remove user from organization", err)
} }
if cmd.UserWasDeleted {
return Success("User deleted")
}
return Success("User removed from organization") return Success("User removed from organization")
} }
...@@ -74,6 +74,8 @@ type OrgUser struct { ...@@ -74,6 +74,8 @@ type OrgUser struct {
type RemoveOrgUserCommand struct { type RemoveOrgUserCommand struct {
UserId int64 UserId int64
OrgId int64 OrgId int64
ShouldDeleteOrphanedUser bool
UserWasDeleted bool
} }
type AddOrgUserCommand struct { type AddOrgUserCommand struct {
......
...@@ -182,6 +182,21 @@ func TestAccountDataAccess(t *testing.T) { ...@@ -182,6 +182,21 @@ func TestAccountDataAccess(t *testing.T) {
}) })
}) })
Convey("Removing user from org should delete user completely if in no other org", func() {
// make sure ac2 has no org
err := DeleteOrg(&m.DeleteOrgCommand{Id: ac2.OrgId})
So(err, ShouldBeNil)
// remove frome ac2 from ac1 org
remCmd := m.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac2.Id, ShouldDeleteOrphanedUser: true}
err = RemoveOrgUser(&remCmd)
So(err, ShouldBeNil)
So(remCmd.UserWasDeleted, ShouldBeTrue)
err = GetSignedInUser(&m.GetSignedInUserQuery{UserId: ac2.Id})
So(err, ShouldEqual, m.ErrUserNotFound)
})
Convey("Cannot delete last admin org user", func() { Convey("Cannot delete last admin org user", func() {
cmd := m.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac1.Id} cmd := m.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac1.Id}
err := RemoveOrgUser(&cmd) err := RemoveOrgUser(&cmd)
......
...@@ -157,6 +157,12 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error { ...@@ -157,6 +157,12 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error {
} }
} }
// validate that after delete there is at least one user with admin role in org
if err := validateOneAdminLeftInOrg(cmd.OrgId, sess); err != nil {
return err
}
// check user other orgs and update user current org
var userOrgs []*m.UserOrgDTO var userOrgs []*m.UserOrgDTO
sess.Table("org_user") sess.Table("org_user")
sess.Join("INNER", "org", "org_user.org_id=org.id") sess.Join("INNER", "org", "org_user.org_id=org.id")
...@@ -168,6 +174,7 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error { ...@@ -168,6 +174,7 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error {
return err return err
} }
if len(userOrgs) > 0 {
hasCurrentOrgSet := false hasCurrentOrgSet := false
for _, userOrg := range userOrgs { for _, userOrg := range userOrgs {
if user.OrgId == userOrg.OrgId { if user.OrgId == userOrg.OrgId {
...@@ -176,14 +183,22 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error { ...@@ -176,14 +183,22 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error {
} }
} }
if !hasCurrentOrgSet && len(userOrgs) > 0 { if !hasCurrentOrgSet {
err = setUsingOrgInTransaction(sess, user.Id, userOrgs[0].OrgId) err = setUsingOrgInTransaction(sess, user.Id, userOrgs[0].OrgId)
if err != nil { if err != nil {
return err return err
} }
} }
} else if cmd.ShouldDeleteOrphanedUser {
// no other orgs, delete the full user
if err := deleteUserInTransaction(sess, &m.DeleteUserCommand{UserId: user.Id}); err != nil {
return err
}
return validateOneAdminLeftInOrg(cmd.OrgId, sess) cmd.UserWasDeleted = true
}
return nil
}) })
} }
......
...@@ -445,6 +445,11 @@ func SearchUsers(query *m.SearchUsersQuery) error { ...@@ -445,6 +445,11 @@ func SearchUsers(query *m.SearchUsersQuery) error {
func DeleteUser(cmd *m.DeleteUserCommand) error { func DeleteUser(cmd *m.DeleteUserCommand) error {
return inTransaction(func(sess *DBSession) error { return inTransaction(func(sess *DBSession) error {
return deleteUserInTransaction(sess, cmd)
})
}
func deleteUserInTransaction(sess *DBSession, cmd *m.DeleteUserCommand) error {
deletes := []string{ deletes := []string{
"DELETE FROM star WHERE user_id = ?", "DELETE FROM star WHERE user_id = ?",
"DELETE FROM " + dialect.Quote("user") + " WHERE id = ?", "DELETE FROM " + dialect.Quote("user") + " WHERE id = ?",
...@@ -463,7 +468,6 @@ func DeleteUser(cmd *m.DeleteUserCommand) error { ...@@ -463,7 +468,6 @@ func DeleteUser(cmd *m.DeleteUserCommand) error {
} }
return nil return nil
})
} }
func UpdateUserPermissions(cmd *m.UpdateUserPermissionsCommand) error { func UpdateUserPermissions(cmd *m.UpdateUserPermissionsCommand) error {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment