From 5b5cb6622d88db4b21d9828a1b6dd05c9bd7e609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Oct 2018 07:48:35 +0200 Subject: [PATCH] Remove user form org now completely removes the user from the system if the user is orphaned --- pkg/api/org_users.go | 20 +++++++++-------- pkg/models/org_user.go | 5 +++-- pkg/services/sqlstore/org_test.go | 14 ++++++++++++ pkg/services/sqlstore/org_users.go | 33 ++++++++++++++++++--------- pkg/services/sqlstore/user.go | 36 +++++++++++++++++------------- 5 files changed, 71 insertions(+), 37 deletions(-) diff --git a/pkg/api/org_users.go b/pkg/api/org_users.go index 4e2ed36431e..83b6d56b2c6 100644 --- a/pkg/api/org_users.go +++ b/pkg/api/org_users.go @@ -102,21 +102,23 @@ func updateOrgUserHelper(cmd m.UpdateOrgUserCommand) Response { // DELETE /api/org/users/:userId func RemoveOrgUserForCurrentOrg(c *m.ReqContext) Response { - userID := c.ParamsInt64(":userId") - return removeOrgUserHelper(c.OrgId, userID) + return removeOrgUserHelper(&m.RemoveOrgUserCommand{ + UserId: c.ParamsInt64(":userId"), + OrgId: c.OrgId, + ShouldDeleteOrphanedUser: true, + }) } // DELETE /api/orgs/:orgId/users/:userId func RemoveOrgUser(c *m.ReqContext) Response { - userID := c.ParamsInt64(":userId") - orgID := c.ParamsInt64(":orgId") - return removeOrgUserHelper(orgID, userID) + return removeOrgUserHelper(&m.RemoveOrgUserCommand{ + UserId: c.ParamsInt64(":userId"), + OrgId: c.ParamsInt64(":orgId"), + }) } -func removeOrgUserHelper(orgID int64, userID int64) Response { - cmd := m.RemoveOrgUserCommand{OrgId: orgID, UserId: userID} - - if err := bus.Dispatch(&cmd); err != nil { +func removeOrgUserHelper(cmd *m.RemoveOrgUserCommand) Response { + if err := bus.Dispatch(cmd); err != nil { if err == m.ErrLastOrgAdmin { return Error(400, "Cannot remove last organization admin", nil) } diff --git a/pkg/models/org_user.go b/pkg/models/org_user.go index 9231d18cfd6..51ab2f62e68 100644 --- a/pkg/models/org_user.go +++ b/pkg/models/org_user.go @@ -72,8 +72,9 @@ type OrgUser struct { // COMMANDS type RemoveOrgUserCommand struct { - UserId int64 - OrgId int64 + UserId int64 + OrgId int64 + ShouldDeleteOrphanedUser bool } type AddOrgUserCommand struct { diff --git a/pkg/services/sqlstore/org_test.go b/pkg/services/sqlstore/org_test.go index af8500707d5..eda20fe1b91 100644 --- a/pkg/services/sqlstore/org_test.go +++ b/pkg/services/sqlstore/org_test.go @@ -182,6 +182,20 @@ 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) + + err = GetSignedInUser(&m.GetSignedInUserQuery{UserId: ac2.Id}) + So(err, ShouldEqual, m.ErrUserNotFound) + }) + Convey("Cannot delete last admin org user", func() { cmd := m.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac1.Id} err := RemoveOrgUser(&cmd) diff --git a/pkg/services/sqlstore/org_users.go b/pkg/services/sqlstore/org_users.go index 14981cfde64..a4d7cb52136 100644 --- a/pkg/services/sqlstore/org_users.go +++ b/pkg/services/sqlstore/org_users.go @@ -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 sess.Table("org_user") sess.Join("INNER", "org", "org_user.org_id=org.id") @@ -168,22 +174,29 @@ func RemoveOrgUser(cmd *m.RemoveOrgUserCommand) error { return err } - hasCurrentOrgSet := false - for _, userOrg := range userOrgs { - if user.OrgId == userOrg.OrgId { - hasCurrentOrgSet = true - break + if len(userOrgs) > 0 { + hasCurrentOrgSet := false + for _, userOrg := range userOrgs { + if user.OrgId == userOrg.OrgId { + hasCurrentOrgSet = true + break + } } - } - if !hasCurrentOrgSet && len(userOrgs) > 0 { - err = setUsingOrgInTransaction(sess, user.Id, userOrgs[0].OrgId) - if err != nil { + if !hasCurrentOrgSet { + err = setUsingOrgInTransaction(sess, user.Id, userOrgs[0].OrgId) + if err != nil { + 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) + return nil }) } diff --git a/pkg/services/sqlstore/user.go b/pkg/services/sqlstore/user.go index 848a11d81ab..72d5654a777 100644 --- a/pkg/services/sqlstore/user.go +++ b/pkg/services/sqlstore/user.go @@ -445,25 +445,29 @@ func SearchUsers(query *m.SearchUsersQuery) error { func DeleteUser(cmd *m.DeleteUserCommand) error { return inTransaction(func(sess *DBSession) error { - deletes := []string{ - "DELETE FROM star WHERE user_id = ?", - "DELETE FROM " + dialect.Quote("user") + " WHERE id = ?", - "DELETE FROM org_user WHERE user_id = ?", - "DELETE FROM dashboard_acl WHERE user_id = ?", - "DELETE FROM preferences WHERE user_id = ?", - "DELETE FROM team_member WHERE user_id = ?", - "DELETE FROM user_auth WHERE user_id = ?", - } + return deleteUserInTransaction(sess, cmd) + }) +} - for _, sql := range deletes { - _, err := sess.Exec(sql, cmd.UserId) - if err != nil { - return err - } +func deleteUserInTransaction(sess *DBSession, cmd *m.DeleteUserCommand) error { + deletes := []string{ + "DELETE FROM star WHERE user_id = ?", + "DELETE FROM " + dialect.Quote("user") + " WHERE id = ?", + "DELETE FROM org_user WHERE user_id = ?", + "DELETE FROM dashboard_acl WHERE user_id = ?", + "DELETE FROM preferences WHERE user_id = ?", + "DELETE FROM team_member WHERE user_id = ?", + "DELETE FROM user_auth WHERE user_id = ?", + } + + for _, sql := range deletes { + _, err := sess.Exec(sql, cmd.UserId) + if err != nil { + return err } + } - return nil - }) + return nil } func UpdateUserPermissions(cmd *m.UpdateUserPermissionsCommand) error {