From 6b2eabf6108e078bed8143e91c605dec5ccfafa6 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Mon, 16 Nov 2015 17:12:49 -0800 Subject: Adding perm delete to cmd line --- api/team.go | 26 ++++++++ api/team_test.go | 37 ++++++++++++ api/user.go | 63 ++++++++++++++++++- api/user_test.go | 37 ++++++++++++ mattermost.go | 120 ++++++++++++++++++++++++++++++++++++- store/sql_audit_store.go | 2 +- store/sql_audit_store_test.go | 2 +- store/sql_channel_store.go | 2 +- store/sql_channel_store_test.go | 2 +- store/sql_oauth_store.go | 2 +- store/sql_oauth_store_test.go | 4 +- store/sql_post_store.go | 79 +++++++++++++++++++++++- store/sql_post_store_test.go | 70 ++++++++++++++++++++++ store/sql_preference_store.go | 2 +- store/sql_preference_store_test.go | 2 +- store/sql_session_store.go | 2 +- store/sql_session_store_test.go | 2 +- store/sql_team_store.go | 2 +- store/sql_team_store_test.go | 2 +- store/sql_user_store.go | 2 +- store/sql_user_store_test.go | 2 +- store/sql_webhook_store.go | 4 +- store/sql_webhook_store_test.go | 4 +- store/store.go | 19 +++--- utils/config.go | 7 ++- 25 files changed, 461 insertions(+), 35 deletions(-) diff --git a/api/team.go b/api/team.go index 862970887..eb8b0772d 100644 --- a/api/team.go +++ b/api/team.go @@ -582,6 +582,32 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) { w.Write([]byte(oldTeam.ToJson())) } +func PermanentDeleteTeam(c *Context, team *model.Team) *model.AppError { + l4g.Warn("Attempting to permanently delete team %v id=%v", team.Name, team.Id) + + team.DeleteAt = model.GetMillis() + if result := <-Srv.Store.Team().Update(team); result.Err != nil { + return result.Err + } + + if result := <-Srv.Store.User().GetForExport(team.Id); result.Err != nil { + return result.Err + } else { + users := result.Data.([]*model.User) + for _, user := range users { + PermanentDeleteUser(c, user) + } + } + + if result := <-Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil { + return result.Err + } + + l4g.Warn("Permanently deleted team %v id=%v", team.Name, team.Id) + + return nil +} + func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) { if len(c.Session.TeamId) == 0 { diff --git a/api/team_test.go b/api/team_test.go index 7a3b092ce..8e9b8852e 100644 --- a/api/team_test.go +++ b/api/team_test.go @@ -168,6 +168,43 @@ func TestGetAllTeams(t *testing.T) { } } +func TestTeamPermDelete(t *testing.T) { + Setup() + + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) + + user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} + user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) + store.Must(Srv.Store.User().VerifyEmail(user1.Id)) + + Client.LoginByEmail(team.Name, user1.Email, "pwd") + + channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) + + post1 := &model.Post{ChannelId: channel1.Id, Message: "search for post1"} + post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) + + post2 := &model.Post{ChannelId: channel1.Id, Message: "search for post2"} + post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) + + post3 := &model.Post{ChannelId: channel1.Id, Message: "#hashtag search for post3"} + post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) + + post4 := &model.Post{ChannelId: channel1.Id, Message: "hashtag for post4"} + post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post) + + c := &Context{} + c.RequestId = model.NewId() + c.IpAddress = "test" + + err := PermanentDeleteTeam(c, team) + if err != nil { + t.Fatal(err) + } +} + /* XXXXXX investigate and fix failing test diff --git a/api/user.go b/api/user.go index 0f868a678..c9aa897ed 100644 --- a/api/user.go +++ b/api/user.go @@ -1196,6 +1196,14 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) { } } + ruser := UpdateActive(c, user, active) + + if c.Err == nil { + w.Write([]byte(ruser.ToJson())) + } +} + +func UpdateActive(c *Context, user *model.User, active bool) *model.User { if active { user.DeleteAt = 0 } else { @@ -1204,7 +1212,7 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) { if result := <-Srv.Store.User().Update(user, true); result.Err != nil { c.Err = result.Err - return + return nil } else { c.LogAuditWithUserId(user.Id, fmt.Sprintf("active=%v", active)) @@ -1216,8 +1224,59 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) { options := utils.SanitizeOptions options["passwordupdate"] = false ruser.Sanitize(options) - w.Write([]byte(ruser.ToJson())) + return ruser + } +} + +func PermanentDeleteUser(c *Context, user *model.User) *model.AppError { + l4g.Warn("Attempting to permanently delete account %v id=%v", user.Email, user.Id) + c.Path = "/user/permanent_delete" + c.LogAuditWithUserId(user.Id, fmt.Sprintf("attempt")) + if user.IsInRole(model.ROLE_SYSTEM_ADMIN) { + l4g.Warn("You are deleting %v that is a system administrator. You may need to set another account as the system administrator using the command line tools.", user.Email) + } + + UpdateActive(c, user, false) + + if result := <-Srv.Store.Session().PermanentDeleteSessionsByUser(user.Id); result.Err != nil { + return result.Err + } + + if result := <-Srv.Store.OAuth().PermanentDeleteAuthDataByUser(user.Id); result.Err != nil { + return result.Err } + + if result := <-Srv.Store.Webhook().PermanentDeleteIncomingByUser(user.Id); result.Err != nil { + return result.Err + } + + if result := <-Srv.Store.Webhook().PermanentDeleteOutgoingByUser(user.Id); result.Err != nil { + return result.Err + } + + if result := <-Srv.Store.Preference().PermanentDeleteByUser(user.Id); result.Err != nil { + return result.Err + } + + if result := <-Srv.Store.Channel().PermanentDeleteMembersByUser(user.Id); result.Err != nil { + return result.Err + } + + if result := <-Srv.Store.Post().PermanentDeleteByUser(user.Id); result.Err != nil { + return result.Err + } + + if result := <-Srv.Store.User().PermanentDelete(user.Id); result.Err != nil { + return result.Err + } + + if result := <-Srv.Store.Audit().PermanentDeleteByUser(user.Id); result.Err != nil { + return result.Err + } + + l4g.Warn("Permanently deleted account %v id=%v", user.Email, user.Id) + + return nil } func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) { diff --git a/api/user_test.go b/api/user_test.go index f067182cb..b6d549a9c 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -767,6 +767,43 @@ func TestUserUpdateActive(t *testing.T) { } } +func TestUserPermDelete(t *testing.T) { + Setup() + + team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} + team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) + + user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"} + user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) + store.Must(Srv.Store.User().VerifyEmail(user1.Id)) + + Client.LoginByEmail(team.Name, user1.Email, "pwd") + + channel1 := &model.Channel{DisplayName: "TestGetPosts", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} + channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) + + post1 := &model.Post{ChannelId: channel1.Id, Message: "search for post1"} + post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) + + post2 := &model.Post{ChannelId: channel1.Id, Message: "search for post2"} + post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) + + post3 := &model.Post{ChannelId: channel1.Id, Message: "#hashtag search for post3"} + post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) + + post4 := &model.Post{ChannelId: channel1.Id, Message: "hashtag for post4"} + post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post) + + c := &Context{} + c.RequestId = model.NewId() + c.IpAddress = "test" + + err := PermanentDeleteUser(c, user1) + if err != nil { + t.Fatal(err) + } +} + func TestSendPasswordReset(t *testing.T) { Setup() diff --git a/mattermost.go b/mattermost.go index e1ae58904..37b4c4c06 100644 --- a/mattermost.go +++ b/mattermost.go @@ -30,6 +30,8 @@ var flagCmdCreateUser bool var flagCmdAssignRole bool var flagCmdVersion bool var flagCmdResetPassword bool +var flagCmdResetPermanentDeleteUser bool +var flagCmdResetPermanentDeleteTeam bool var flagConfigFile string var flagEmail string var flagPassword string @@ -191,10 +193,12 @@ func parseCmds() { flag.BoolVar(&flagCmdAssignRole, "assign_role", false, "") flag.BoolVar(&flagCmdVersion, "version", false, "") flag.BoolVar(&flagCmdResetPassword, "reset_password", false, "") + flag.BoolVar(&flagCmdResetPermanentDeleteUser, "permanent_delete_user", false, "") + flag.BoolVar(&flagCmdResetPermanentDeleteTeam, "permanent_delete_team", false, "") flag.Parse() - flagRunCmds = flagCmdCreateTeam || flagCmdCreateUser || flagCmdAssignRole || flagCmdResetPassword || flagCmdVersion + flagRunCmds = flagCmdCreateTeam || flagCmdCreateUser || flagCmdAssignRole || flagCmdResetPassword || flagCmdVersion || flagCmdResetPermanentDeleteUser || flagCmdResetPermanentDeleteTeam } func runCmds() { @@ -203,6 +207,8 @@ func runCmds() { cmdCreateUser() cmdAssignRole() cmdResetPassword() + cmdPermDeleteUser() + cmdPermDeleteTeam() } func cmdCreateTeam() { @@ -406,6 +412,106 @@ func cmdResetPassword() { } } +func cmdPermDeleteUser() { + if flagCmdResetPermanentDeleteUser { + if len(flagTeamName) == 0 { + fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name") + flag.Usage() + os.Exit(1) + } + + if len(flagEmail) == 0 { + fmt.Fprintln(os.Stderr, "flag needs an argument: -email") + flag.Usage() + os.Exit(1) + } + + c := &api.Context{} + c.RequestId = model.NewId() + c.IpAddress = "cmd_line" + + var team *model.Team + if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil { + l4g.Error("%v", result.Err) + flushLogAndExit(1) + } else { + team = result.Data.(*model.Team) + } + + var user *model.User + if result := <-api.Srv.Store.User().GetByEmail(team.Id, flagEmail); result.Err != nil { + l4g.Error("%v", result.Err) + flushLogAndExit(1) + } else { + user = result.Data.(*model.User) + } + + var confirmBackup string + fmt.Print("Have you performed a database backup? (YES/NO): ") + fmt.Scanln(&confirmBackup) + if confirmBackup != "YES" { + flushLogAndExit(1) + } + + var confirm string + fmt.Printf("Are you sure you want to delete the user %v? All data will be permanently deleted? (YES/NO): ", user.Email) + fmt.Scanln(&confirm) + if confirm != "YES" { + flushLogAndExit(1) + } + + if err := api.PermanentDeleteUser(c, user); err != nil { + l4g.Error("%v", err) + flushLogAndExit(1) + } else { + flushLogAndExit(0) + } + } +} + +func cmdPermDeleteTeam() { + if flagCmdResetPermanentDeleteTeam { + if len(flagTeamName) == 0 { + fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name") + flag.Usage() + os.Exit(1) + } + + c := &api.Context{} + c.RequestId = model.NewId() + c.IpAddress = "cmd_line" + + var team *model.Team + if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil { + l4g.Error("%v", result.Err) + flushLogAndExit(1) + } else { + team = result.Data.(*model.Team) + } + + var confirmBackup string + fmt.Print("Have you performed a database backup? (YES/NO): ") + fmt.Scanln(&confirmBackup) + if confirmBackup != "YES" { + flushLogAndExit(1) + } + + var confirm string + fmt.Printf("Are you sure you want to delete the team %v? All data will be permanently deleted? (YES/NO): ", team.Name) + fmt.Scanln(&confirm) + if confirm != "YES" { + flushLogAndExit(1) + } + + if err := api.PermanentDeleteTeam(c, team); err != nil { + l4g.Error("%v", err) + flushLogAndExit(1) + } else { + flushLogAndExit(0) + } + } +} + func flushLogAndExit(code int) { l4g.Close() time.Sleep(time.Second) @@ -461,5 +567,17 @@ Usage: Example: platform -reset_password -team_name="name" -email="user@example.com" -password="newpassword" + -permanent_delete_user Permanently deletes a user and all related information + include posts from the database. It requires the + -team_name, and -email flag. + Example: + platform -permanent_delete_user -team_name="name" -email="user@example.com" + + -permanent_delete_team Permanently deletes a team and all users along with + all related information including posts from the database. + It requires the -team_name flag. + Example: + platform -permanent_delete_team -team_name="name" + ` diff --git a/store/sql_audit_store.go b/store/sql_audit_store.go index fd39eda8f..f4fd29aab 100644 --- a/store/sql_audit_store.go +++ b/store/sql_audit_store.go @@ -87,7 +87,7 @@ func (s SqlAuditStore) Get(user_id string, limit int) StoreChannel { return storeChannel } -func (s SqlAuditStore) Delete(userId string) StoreChannel { +func (s SqlAuditStore) PermanentDeleteByUser(userId string) StoreChannel { storeChannel := make(StoreChannel) diff --git a/store/sql_audit_store_test.go b/store/sql_audit_store_test.go index 4dce6701f..b395631f1 100644 --- a/store/sql_audit_store_test.go +++ b/store/sql_audit_store_test.go @@ -45,7 +45,7 @@ func TestSqlAuditStore(t *testing.T) { t.Fatal("Should have returned empty because user_id is missing") } - if r2 := <-store.Audit().Delete(audit.UserId); r2.Err != nil { + if r2 := <-store.Audit().PermanentDeleteByUser(audit.UserId); r2.Err != nil { t.Fatal(r2.Err) } } diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go index 65e2cc45d..cc5c86107 100644 --- a/store/sql_channel_store.go +++ b/store/sql_channel_store.go @@ -616,7 +616,7 @@ func (s SqlChannelStore) RemoveMember(channelId string, userId string) StoreChan return storeChannel } -func (s SqlChannelStore) DeleteMember(userId string) StoreChannel { +func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) StoreChannel { storeChannel := make(StoreChannel) go func() { diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go index 238f79be8..695991bf7 100644 --- a/store/sql_channel_store_test.go +++ b/store/sql_channel_store_test.go @@ -428,7 +428,7 @@ func TestChannelDeleteMemberStore(t *testing.T) { t.Fatal("should have saved 2 members") } - Must(store.Channel().DeleteMember(o2.UserId)) + Must(store.Channel().PermanentDeleteMembersByUser(o2.UserId)) count = (<-store.Channel().GetMemberCount(o1.ChannelId)).Data.(int64) if count != 1 { diff --git a/store/sql_oauth_store.go b/store/sql_oauth_store.go index 688e39b09..43a5bee31 100644 --- a/store/sql_oauth_store.go +++ b/store/sql_oauth_store.go @@ -333,7 +333,7 @@ func (as SqlOAuthStore) RemoveAuthData(code string) StoreChannel { return storeChannel } -func (as SqlOAuthStore) RemoveAuthDataByUserId(userId string) StoreChannel { +func (as SqlOAuthStore) PermanentDeleteAuthDataByUser(userId string) StoreChannel { storeChannel := make(StoreChannel) go func() { diff --git a/store/sql_oauth_store_test.go b/store/sql_oauth_store_test.go index 2a9aad1b3..c3f6ea7ac 100644 --- a/store/sql_oauth_store_test.go +++ b/store/sql_oauth_store_test.go @@ -181,7 +181,7 @@ func TestOAuthStoreRemoveAuthData(t *testing.T) { } } -func TestOAuthStoreRemoveAuthDataByUserId(t *testing.T) { +func TestOAuthStoreRemoveAuthDataByUser(t *testing.T) { Setup() a1 := model.AuthData{} @@ -190,7 +190,7 @@ func TestOAuthStoreRemoveAuthDataByUserId(t *testing.T) { a1.Code = model.NewId() Must(store.OAuth().SaveAuthData(&a1)) - if err := (<-store.OAuth().RemoveAuthDataByUserId(a1.UserId)).Err; err != nil { + if err := (<-store.OAuth().PermanentDeleteAuthDataByUser(a1.UserId)).Err; err != nil { t.Fatal(err) } } diff --git a/store/sql_post_store.go b/store/sql_post_store.go index 0bcb420bd..cc596074f 100644 --- a/store/sql_post_store.go +++ b/store/sql_post_store.go @@ -228,13 +228,13 @@ func (s SqlPostStore) Delete(postId string, time int64) StoreChannel { return storeChannel } -func (s SqlPostStore) PermanentDelete(userId string) StoreChannel { +func (s SqlPostStore) permanentDelete(postId string) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} - _, err := s.GetMaster().Exec("Update Posts SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :Id OR ParentId = :ParentId OR RootId = :RootId", map[string]interface{}{"DeleteAt": time, "UpdateAt": time, "Id": postId, "ParentId": postId, "RootId": postId}) + _, err := s.GetMaster().Exec("DELETE FROM Posts WHERE Id = :Id OR ParentId = :ParentId OR RootId = :RootId", map[string]interface{}{"Id": postId, "ParentId": postId, "RootId": postId}) if err != nil { result.Err = model.NewAppError("SqlPostStore.Delete", "We couldn't delete the post", "id="+postId+", err="+err.Error()) } @@ -246,6 +246,81 @@ func (s SqlPostStore) PermanentDelete(userId string) StoreChannel { return storeChannel } +func (s SqlPostStore) permanentDeleteAllCommentByUser(userId string) StoreChannel { + storeChannel := make(StoreChannel) + + go func() { + result := StoreResult{} + + _, err := s.GetMaster().Exec("DELETE FROM Posts WHERE UserId = :UserId AND RootId != ''", map[string]interface{}{"UserId": userId}) + if err != nil { + result.Err = model.NewAppError("SqlPostStore.permanentDeleteAllCommentByUser", "We couldn't delete the comments for user", "userId="+userId+", err="+err.Error()) + } + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + +func (s SqlPostStore) PermanentDeleteByUser(userId string) StoreChannel { + storeChannel := make(StoreChannel) + + go func() { + result := StoreResult{} + + // First attempt to delete all the comments for a user + if r := <-s.permanentDeleteAllCommentByUser(userId); r.Err != nil { + result.Err = r.Err + storeChannel <- result + close(storeChannel) + return + } + + // Now attempt to delete all the root posts for a user. This will also + // delete all the comments for each post. + found := true + count := 0 + + for found { + var ids []string + _, err := s.GetMaster().Select(&ids, "SELECT Id FROM Posts WHERE UserId = :UserId LIMIT 1000", map[string]interface{}{"UserId": userId}) + if err != nil { + result.Err = model.NewAppError("SqlPostStore.PermanentDeleteByUser.select", "We couldn't select the posts to delete for the user", "userId="+userId+", err="+err.Error()) + storeChannel <- result + close(storeChannel) + return + } else { + found = false + for _, id := range ids { + found = true + if r := <-s.permanentDelete(id); r.Err != nil { + result.Err = r.Err + storeChannel <- result + close(storeChannel) + return + } + } + } + + // This is a fail safe, give up if more than 10K messages + count = count + 1 + if count >= 10 { + result.Err = model.NewAppError("SqlPostStore.PermanentDeleteByUser.toolarge", "We couldn't select the posts to delete for the user (too many), please re-run", "userId="+userId) + storeChannel <- result + close(storeChannel) + return + } + } + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + func (s SqlPostStore) GetPosts(channelId string, offset int, limit int) StoreChannel { storeChannel := make(StoreChannel) diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go index fe7195a54..d9b087ea7 100644 --- a/store/sql_post_store_test.go +++ b/store/sql_post_store_test.go @@ -247,6 +247,76 @@ func TestPostStoreDelete2Level(t *testing.T) { } } +func TestPostStorePermDelete1Level(t *testing.T) { + Setup() + + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "a" + model.NewId() + "b" + o1 = (<-store.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "a" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-store.Post().Save(o2)).Data.(*model.Post) + + if r2 := <-store.Post().PermanentDeleteByUser(o2.UserId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-store.Post().Get(o1.Id)); r3.Err != nil { + t.Fatal("Deleted id shouldn't have failed") + } + + if r4 := (<-store.Post().Get(o2.Id)); r4.Err == nil { + t.Fatal("Deleted id should have failed") + } +} + +func TestPostStorePermDelete1Level2(t *testing.T) { + Setup() + + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "a" + model.NewId() + "b" + o1 = (<-store.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "a" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-store.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = model.NewId() + o3.UserId = model.NewId() + o3.Message = "a" + model.NewId() + "b" + o3 = (<-store.Post().Save(o3)).Data.(*model.Post) + + if r2 := <-store.Post().PermanentDeleteByUser(o1.UserId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-store.Post().Get(o1.Id)); r3.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r4 := (<-store.Post().Get(o2.Id)); r4.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r5 := (<-store.Post().Get(o3.Id)); r5.Err != nil { + t.Fatal("Deleted id shouldn't have failed") + } +} + func TestPostStoreGetWithChildren(t *testing.T) { Setup() diff --git a/store/sql_preference_store.go b/store/sql_preference_store.go index 6fa30ba7a..8454abcbd 100644 --- a/store/sql_preference_store.go +++ b/store/sql_preference_store.go @@ -240,7 +240,7 @@ func (s SqlPreferenceStore) GetAll(userId string) StoreChannel { return storeChannel } -func (s SqlPreferenceStore) Delete(userId string) StoreChannel { +func (s SqlPreferenceStore) PermanentDeleteByUser(userId string) StoreChannel { storeChannel := make(StoreChannel) go func() { diff --git a/store/sql_preference_store_test.go b/store/sql_preference_store_test.go index 8d850e22c..77da71fd6 100644 --- a/store/sql_preference_store_test.go +++ b/store/sql_preference_store_test.go @@ -228,7 +228,7 @@ func TestPreferenceDelete(t *testing.T) { Must(store.Preference().Save(&preferences)) - if result := <-store.Preference().Delete(userId); result.Err != nil { + if result := <-store.Preference().PermanentDeleteByUser(userId); result.Err != nil { t.Fatal(result.Err) } } diff --git a/store/sql_session_store.go b/store/sql_session_store.go index 8237d8200..86604b4fe 100644 --- a/store/sql_session_store.go +++ b/store/sql_session_store.go @@ -158,7 +158,7 @@ func (me SqlSessionStore) RemoveAllSessionsForTeam(teamId string) StoreChannel { return storeChannel } -func (me SqlSessionStore) RemoveAllSessionsForUser(userId string) StoreChannel { +func (me SqlSessionStore) PermanentDeleteSessionsByUser(userId string) StoreChannel { storeChannel := make(StoreChannel) go func() { diff --git a/store/sql_session_store_test.go b/store/sql_session_store_test.go index a06a2bdff..cec8e93b0 100644 --- a/store/sql_session_store_test.go +++ b/store/sql_session_store_test.go @@ -119,7 +119,7 @@ func TestSessionRemoveByUser(t *testing.T) { } } - Must(store.Session().RemoveAllSessionsForUser(s1.UserId)) + Must(store.Session().PermanentDeleteSessionsByUser(s1.UserId)) if rs2 := (<-store.Session().Get(s1.Id)); rs2.Err == nil { t.Fatal("should have been removed") diff --git a/store/sql_team_store.go b/store/sql_team_store.go index 7bcdc7349..9578549ca 100644 --- a/store/sql_team_store.go +++ b/store/sql_team_store.go @@ -301,7 +301,7 @@ func (s SqlTeamStore) GetAllTeamListing() StoreChannel { return storeChannel } -func (s SqlTeamStore) Delete(teamId string) StoreChannel { +func (s SqlTeamStore) PermanentDelete(teamId string) StoreChannel { storeChannel := make(StoreChannel) go func() { diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go index 6547b0c8f..7dc31cbe2 100644 --- a/store/sql_team_store_test.go +++ b/store/sql_team_store_test.go @@ -257,7 +257,7 @@ func TestDelete(t *testing.T) { o2.Type = model.TEAM_OPEN Must(store.Team().Save(&o2)) - if r1 := <-store.Team().Delete(o1.Id); r1.Err != nil { + if r1 := <-store.Team().PermanentDelete(o1.Id); r1.Err != nil { t.Fatal(r1.Err) } } diff --git a/store/sql_user_store.go b/store/sql_user_store.go index 90efc00f1..d19135b64 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -555,7 +555,7 @@ func (us SqlUserStore) GetTotalActiveUsersCount() StoreChannel { return storeChannel } -func (us SqlUserStore) Delete(userId string) StoreChannel { +func (us SqlUserStore) PermanentDelete(userId string) StoreChannel { storeChannel := make(StoreChannel) diff --git a/store/sql_user_store_test.go b/store/sql_user_store_test.go index 25f4a3475..dd08438f1 100644 --- a/store/sql_user_store_test.go +++ b/store/sql_user_store_test.go @@ -386,7 +386,7 @@ func TestUserStoreDelete(t *testing.T) { u1.Email = model.NewId() Must(store.User().Save(&u1)) - if err := (<-store.User().Delete(u1.Id)).Err; err != nil { + if err := (<-store.User().PermanentDelete(u1.Id)).Err; err != nil { t.Fatal(err) } } diff --git a/store/sql_webhook_store.go b/store/sql_webhook_store.go index 11b9f6e52..b7bf0615f 100644 --- a/store/sql_webhook_store.go +++ b/store/sql_webhook_store.go @@ -116,7 +116,7 @@ func (s SqlWebhookStore) DeleteIncoming(webhookId string, time int64) StoreChann return storeChannel } -func (s SqlWebhookStore) DeleteIncomingByUser(userId string) StoreChannel { +func (s SqlWebhookStore) PermanentDeleteIncomingByUser(userId string) StoreChannel { storeChannel := make(StoreChannel) go func() { @@ -312,7 +312,7 @@ func (s SqlWebhookStore) DeleteOutgoing(webhookId string, time int64) StoreChann return storeChannel } -func (s SqlWebhookStore) DeleteOutgoingByUser(userId string) StoreChannel { +func (s SqlWebhookStore) PermanentDeleteOutgoingByUser(userId string) StoreChannel { storeChannel := make(StoreChannel) go func() { diff --git a/store/sql_webhook_store_test.go b/store/sql_webhook_store_test.go index 1b770c6d4..1a9d5be3b 100644 --- a/store/sql_webhook_store_test.go +++ b/store/sql_webhook_store_test.go @@ -121,7 +121,7 @@ func TestWebhookStoreDeleteIncomingByUser(t *testing.T) { } } - if r2 := <-store.Webhook().DeleteIncomingByUser(o1.UserId); r2.Err != nil { + if r2 := <-store.Webhook().PermanentDeleteIncomingByUser(o1.UserId); r2.Err != nil { t.Fatal(r2.Err) } @@ -305,7 +305,7 @@ func TestWebhookStoreDeleteOutgoingByUser(t *testing.T) { } } - if r2 := <-store.Webhook().DeleteOutgoingByUser(o1.CreatorId); r2.Err != nil { + if r2 := <-store.Webhook().PermanentDeleteOutgoingByUser(o1.CreatorId); r2.Err != nil { t.Fatal(r2.Err) } diff --git a/store/store.go b/store/store.go index 13434e7b0..a8b57dcdd 100644 --- a/store/store.go +++ b/store/store.go @@ -52,7 +52,7 @@ type TeamStore interface { GetAll() StoreChannel GetAllTeamListing() StoreChannel GetByInviteId(inviteId string) StoreChannel - Delete(teamId string) StoreChannel + PermanentDelete(teamId string) StoreChannel } type ChannelStore interface { @@ -73,7 +73,7 @@ type ChannelStore interface { GetMember(channelId string, userId string) StoreChannel GetMemberCount(channelId string) StoreChannel RemoveMember(channelId string, userId string) StoreChannel - DeleteMember(userId string) StoreChannel + PermanentDeleteMembersByUser(userId string) StoreChannel GetExtraMembers(channelId string, limit int) StoreChannel CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel CheckOpenChannelPermissions(teamId string, channelId string) StoreChannel @@ -88,6 +88,7 @@ type PostStore interface { Update(post *model.Post, newMessage string, newHashtags string) StoreChannel Get(id string) StoreChannel Delete(postId string, time int64) StoreChannel + PermanentDeleteByUser(userId string) StoreChannel GetPosts(channelId string, offset int, limit int) StoreChannel GetPostsBefore(channelId string, postId string, numPosts int, offset int) StoreChannel GetPostsAfter(channelId string, postId string, numPosts int, offset int) StoreChannel @@ -120,7 +121,7 @@ type UserStore interface { GetTotalUsersCount() StoreChannel GetTotalActiveUsersCount() StoreChannel GetSystemAdminProfiles() StoreChannel - Delete(userId string) StoreChannel + PermanentDelete(userId string) StoreChannel } type SessionStore interface { @@ -129,7 +130,7 @@ type SessionStore interface { GetSessions(userId string) StoreChannel Remove(sessionIdOrToken string) StoreChannel RemoveAllSessionsForTeam(teamId string) StoreChannel - RemoveAllSessionsForUser(teamId string) StoreChannel + PermanentDeleteSessionsByUser(teamId string) StoreChannel UpdateLastActivityAt(sessionId string, time int64) StoreChannel UpdateRoles(userId string, roles string) StoreChannel } @@ -137,7 +138,7 @@ type SessionStore interface { type AuditStore interface { Save(audit *model.Audit) StoreChannel Get(user_id string, limit int) StoreChannel - Delete(userId string) StoreChannel + PermanentDeleteByUser(userId string) StoreChannel } type OAuthStore interface { @@ -148,7 +149,7 @@ type OAuthStore interface { SaveAuthData(authData *model.AuthData) StoreChannel GetAuthData(code string) StoreChannel RemoveAuthData(code string) StoreChannel - RemoveAuthDataByUserId(userId string) StoreChannel + PermanentDeleteAuthDataByUser(userId string) StoreChannel SaveAccessData(accessData *model.AccessData) StoreChannel GetAccessData(token string) StoreChannel GetAccessDataByAuthCode(authCode string) StoreChannel @@ -167,14 +168,14 @@ type WebhookStore interface { GetIncomingByUser(userId string) StoreChannel GetIncomingByChannel(channelId string) StoreChannel DeleteIncoming(webhookId string, time int64) StoreChannel - DeleteIncomingByUser(userId string) StoreChannel + PermanentDeleteIncomingByUser(userId string) StoreChannel SaveOutgoing(webhook *model.OutgoingWebhook) StoreChannel GetOutgoing(id string) StoreChannel GetOutgoingByCreator(userId string) StoreChannel GetOutgoingByChannel(channelId string) StoreChannel GetOutgoingByTeam(teamId string) StoreChannel DeleteOutgoing(webhookId string, time int64) StoreChannel - DeleteOutgoingByUser(userId string) StoreChannel + PermanentDeleteOutgoingByUser(userId string) StoreChannel UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel } @@ -183,5 +184,5 @@ type PreferenceStore interface { Get(userId string, category string, name string) StoreChannel GetCategory(userId string, category string) StoreChannel GetAll(userId string) StoreChannel - Delete(userId string) StoreChannel + PermanentDeleteByUser(userId string) StoreChannel } diff --git a/utils/config.go b/utils/config.go index 13b7b6b64..2fd799cd1 100644 --- a/utils/config.go +++ b/utils/config.go @@ -59,8 +59,7 @@ func FindDir(dir string) string { func ConfigureCmdLineLog() { ls := model.LogSettings{} ls.EnableConsole = true - ls.ConsoleLevel = "ERROR" - ls.EnableFile = false + ls.ConsoleLevel = "WARN" configureLog(&ls) } @@ -72,6 +71,8 @@ func configureLog(s *model.LogSettings) { level := l4g.DEBUG if s.ConsoleLevel == "INFO" { level = l4g.INFO + } else if s.ConsoleLevel == "WARN" { + level = l4g.WARNING } else if s.ConsoleLevel == "ERROR" { level = l4g.ERROR } @@ -90,6 +91,8 @@ func configureLog(s *model.LogSettings) { level := l4g.DEBUG if s.FileLevel == "INFO" { level = l4g.INFO + } else if s.FileLevel == "WARN" { + level = l4g.WARNING } else if s.FileLevel == "ERROR" { level = l4g.ERROR } -- cgit v1.2.3-1-g7c22