Merge pull request #1448 from mattermost/PLT-975
PLT-975 adding delete to command line tool
Этот коммит содержится в:
33
api/team.go
33
api/team.go
@@ -582,6 +582,39 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write([]byte(oldTeam.ToJson()))
|
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)
|
||||||
|
c.Path = "/teams/permanent_delete"
|
||||||
|
c.LogAuditWithUserId("", fmt.Sprintf("attempt teamId=%v", 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.Channel().PermanentDeleteByTeam(team.Id); result.Err != nil {
|
||||||
|
return result.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
c.LogAuditWithUserId("", fmt.Sprintf("success teamId=%v", team.Id))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
if len(c.Session.TeamId) == 0 {
|
if len(c.Session.TeamId) == 0 {
|
||||||
|
|||||||
@@ -168,6 +168,45 @@ 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.ClearOAuthToken()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
XXXXXX investigate and fix failing test
|
XXXXXX investigate and fix failing test
|
||||||
@@ -221,6 +260,7 @@ func TestFindTeamByEmailSend(t *testing.T) {
|
|||||||
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"}
|
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"}
|
||||||
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
|
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
|
||||||
store.Must(Srv.Store.User().VerifyEmail(user.Id))
|
store.Must(Srv.Store.User().VerifyEmail(user.Id))
|
||||||
|
Client.LoginByEmail(team.Name, user.Email, "pwd")
|
||||||
|
|
||||||
if _, err := Client.FindTeamsSendEmail(user.Email); err != nil {
|
if _, err := Client.FindTeamsSendEmail(user.Email); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
65
api/user.go
65
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 {
|
if active {
|
||||||
user.DeleteAt = 0
|
user.DeleteAt = 0
|
||||||
} else {
|
} 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 {
|
if result := <-Srv.Store.User().Update(user, true); result.Err != nil {
|
||||||
c.Err = result.Err
|
c.Err = result.Err
|
||||||
return
|
return nil
|
||||||
} else {
|
} else {
|
||||||
c.LogAuditWithUserId(user.Id, fmt.Sprintf("active=%v", active))
|
c.LogAuditWithUserId(user.Id, fmt.Sprintf("active=%v", active))
|
||||||
|
|
||||||
@@ -1216,10 +1224,63 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
options := utils.SanitizeOptions
|
options := utils.SanitizeOptions
|
||||||
options["passwordupdate"] = false
|
options["passwordupdate"] = false
|
||||||
ruser.Sanitize(options)
|
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 = "/users/permanent_delete"
|
||||||
|
c.LogAuditWithUserId(user.Id, fmt.Sprintf("attempt userId=%v", user.Id))
|
||||||
|
c.LogAuditWithUserId("", fmt.Sprintf("attempt userId=%v", user.Id))
|
||||||
|
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)
|
||||||
|
c.LogAuditWithUserId("", fmt.Sprintf("success userId=%v", user.Id))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
|
func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
props := model.MapFromJson(r.Body)
|
props := model.MapFromJson(r.Body)
|
||||||
|
|
||||||
|
|||||||
@@ -767,6 +767,45 @@ 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.ClearOAuthToken()
|
||||||
|
}
|
||||||
|
|
||||||
func TestSendPasswordReset(t *testing.T) {
|
func TestSendPasswordReset(t *testing.T) {
|
||||||
Setup()
|
Setup()
|
||||||
|
|
||||||
|
|||||||
128
mattermost.go
128
mattermost.go
@@ -30,6 +30,8 @@ var flagCmdCreateUser bool
|
|||||||
var flagCmdAssignRole bool
|
var flagCmdAssignRole bool
|
||||||
var flagCmdVersion bool
|
var flagCmdVersion bool
|
||||||
var flagCmdResetPassword bool
|
var flagCmdResetPassword bool
|
||||||
|
var flagCmdPermanentDeleteUser bool
|
||||||
|
var flagCmdPermanentDeleteTeam bool
|
||||||
var flagConfigFile string
|
var flagConfigFile string
|
||||||
var flagEmail string
|
var flagEmail string
|
||||||
var flagPassword string
|
var flagPassword string
|
||||||
@@ -191,10 +193,18 @@ func parseCmds() {
|
|||||||
flag.BoolVar(&flagCmdAssignRole, "assign_role", false, "")
|
flag.BoolVar(&flagCmdAssignRole, "assign_role", false, "")
|
||||||
flag.BoolVar(&flagCmdVersion, "version", false, "")
|
flag.BoolVar(&flagCmdVersion, "version", false, "")
|
||||||
flag.BoolVar(&flagCmdResetPassword, "reset_password", false, "")
|
flag.BoolVar(&flagCmdResetPassword, "reset_password", false, "")
|
||||||
|
flag.BoolVar(&flagCmdPermanentDeleteUser, "permanent_delete_user", false, "")
|
||||||
|
flag.BoolVar(&flagCmdPermanentDeleteTeam, "permanent_delete_team", false, "")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
flagRunCmds = flagCmdCreateTeam || flagCmdCreateUser || flagCmdAssignRole || flagCmdResetPassword || flagCmdVersion
|
flagRunCmds = (flagCmdCreateTeam ||
|
||||||
|
flagCmdCreateUser ||
|
||||||
|
flagCmdAssignRole ||
|
||||||
|
flagCmdResetPassword ||
|
||||||
|
flagCmdVersion ||
|
||||||
|
flagCmdPermanentDeleteUser ||
|
||||||
|
flagCmdPermanentDeleteTeam)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmds() {
|
func runCmds() {
|
||||||
@@ -203,6 +213,8 @@ func runCmds() {
|
|||||||
cmdCreateUser()
|
cmdCreateUser()
|
||||||
cmdAssignRole()
|
cmdAssignRole()
|
||||||
cmdResetPassword()
|
cmdResetPassword()
|
||||||
|
cmdPermDeleteUser()
|
||||||
|
cmdPermDeleteTeam()
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdCreateTeam() {
|
func cmdCreateTeam() {
|
||||||
@@ -406,6 +418,106 @@ func cmdResetPassword() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cmdPermDeleteUser() {
|
||||||
|
if flagCmdPermanentDeleteUser {
|
||||||
|
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 flagCmdPermanentDeleteTeam {
|
||||||
|
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) {
|
func flushLogAndExit(code int) {
|
||||||
l4g.Close()
|
l4g.Close()
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
@@ -461,5 +573,19 @@ Usage:
|
|||||||
Example:
|
Example:
|
||||||
platform -reset_password -team_name="name" -email="user@example.com" -password="newpassword"
|
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. You may need to restart the
|
||||||
|
server to invlidate the cache
|
||||||
|
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. You may need to restart
|
||||||
|
the server to invalidate the cache.
|
||||||
|
Example:
|
||||||
|
platform -permanent_delete_team -team_name="name"
|
||||||
|
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -86,3 +86,22 @@ func (s SqlAuditStore) Get(user_id string, limit int) StoreChannel {
|
|||||||
|
|
||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlAuditStore) PermanentDeleteByUser(userId string) StoreChannel {
|
||||||
|
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
if _, err := s.GetMaster().Exec("DELETE FROM Audits WHERE UserId = :userId",
|
||||||
|
map[string]interface{}{"userId": userId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlAuditStore.Delete", "We encountered an error deleting the audits", "user_id="+userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,4 +44,8 @@ func TestSqlAuditStore(t *testing.T) {
|
|||||||
if len(audits) != 0 {
|
if len(audits) != 0 {
|
||||||
t.Fatal("Should have returned empty because user_id is missing")
|
t.Fatal("Should have returned empty because user_id is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r2 := <-store.Audit().PermanentDeleteByUser(audit.UserId); r2.Err != nil {
|
||||||
|
t.Fatal(r2.Err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,6 +279,23 @@ func (s SqlChannelStore) Delete(channelId string, time int64) StoreChannel {
|
|||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
if _, err := s.GetMaster().Exec("DELETE FROM Channels WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "We couldn't delete the channels", "teamId="+teamId+", "+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|
||||||
type channelWithMember struct {
|
type channelWithMember struct {
|
||||||
model.Channel
|
model.Channel
|
||||||
model.ChannelMember
|
model.ChannelMember
|
||||||
@@ -616,6 +633,23 @@ func (s SqlChannelStore) RemoveMember(channelId string, userId string) StoreChan
|
|||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
if _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "We couldn't remove the channel member", "user_id="+userId+", "+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|
||||||
func (s SqlChannelStore) CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel {
|
func (s SqlChannelStore) CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel {
|
||||||
storeChannel := make(StoreChannel)
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
|||||||
@@ -379,6 +379,63 @@ func TestChannelMemberStore(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestChannelDeleteMemberStore(t *testing.T) {
|
||||||
|
Setup()
|
||||||
|
|
||||||
|
c1 := model.Channel{}
|
||||||
|
c1.TeamId = model.NewId()
|
||||||
|
c1.DisplayName = "NameName"
|
||||||
|
c1.Name = "a" + model.NewId() + "b"
|
||||||
|
c1.Type = model.CHANNEL_OPEN
|
||||||
|
c1 = *Must(store.Channel().Save(&c1)).(*model.Channel)
|
||||||
|
|
||||||
|
c1t1 := (<-store.Channel().Get(c1.Id)).Data.(*model.Channel)
|
||||||
|
t1 := c1t1.ExtraUpdateAt
|
||||||
|
|
||||||
|
u1 := model.User{}
|
||||||
|
u1.TeamId = model.NewId()
|
||||||
|
u1.Email = model.NewId()
|
||||||
|
u1.Nickname = model.NewId()
|
||||||
|
Must(store.User().Save(&u1))
|
||||||
|
|
||||||
|
u2 := model.User{}
|
||||||
|
u2.TeamId = model.NewId()
|
||||||
|
u2.Email = model.NewId()
|
||||||
|
u2.Nickname = model.NewId()
|
||||||
|
Must(store.User().Save(&u2))
|
||||||
|
|
||||||
|
o1 := model.ChannelMember{}
|
||||||
|
o1.ChannelId = c1.Id
|
||||||
|
o1.UserId = u1.Id
|
||||||
|
o1.NotifyProps = model.GetDefaultChannelNotifyProps()
|
||||||
|
Must(store.Channel().SaveMember(&o1))
|
||||||
|
|
||||||
|
o2 := model.ChannelMember{}
|
||||||
|
o2.ChannelId = c1.Id
|
||||||
|
o2.UserId = u2.Id
|
||||||
|
o2.NotifyProps = model.GetDefaultChannelNotifyProps()
|
||||||
|
Must(store.Channel().SaveMember(&o2))
|
||||||
|
|
||||||
|
c1t2 := (<-store.Channel().Get(c1.Id)).Data.(*model.Channel)
|
||||||
|
t2 := c1t2.ExtraUpdateAt
|
||||||
|
|
||||||
|
if t2 <= t1 {
|
||||||
|
t.Fatal("Member update time incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
count := (<-store.Channel().GetMemberCount(o1.ChannelId)).Data.(int64)
|
||||||
|
if count != 2 {
|
||||||
|
t.Fatal("should have saved 2 members")
|
||||||
|
}
|
||||||
|
|
||||||
|
Must(store.Channel().PermanentDeleteMembersByUser(o2.UserId))
|
||||||
|
|
||||||
|
count = (<-store.Channel().GetMemberCount(o1.ChannelId)).Data.(int64)
|
||||||
|
if count != 1 {
|
||||||
|
t.Fatal("should have removed 1 member")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestChannelStorePermissionsTo(t *testing.T) {
|
func TestChannelStorePermissionsTo(t *testing.T) {
|
||||||
Setup()
|
Setup()
|
||||||
|
|
||||||
|
|||||||
@@ -332,3 +332,21 @@ func (as SqlOAuthStore) RemoveAuthData(code string) StoreChannel {
|
|||||||
|
|
||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (as SqlOAuthStore) PermanentDeleteAuthDataByUser(userId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
_, err := as.GetMaster().Exec("DELETE FROM OAuthAuthData WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
|
||||||
|
if err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlOAuthStore.RemoveAuthDataByUserId", "We couldn't remove the authorization code", "err="+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|||||||
@@ -180,3 +180,17 @@ func TestOAuthStoreRemoveAuthData(t *testing.T) {
|
|||||||
t.Fatal("should have errored - auth code removed")
|
t.Fatal("should have errored - auth code removed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOAuthStoreRemoveAuthDataByUser(t *testing.T) {
|
||||||
|
Setup()
|
||||||
|
|
||||||
|
a1 := model.AuthData{}
|
||||||
|
a1.ClientId = model.NewId()
|
||||||
|
a1.UserId = model.NewId()
|
||||||
|
a1.Code = model.NewId()
|
||||||
|
Must(store.OAuth().SaveAuthData(&a1))
|
||||||
|
|
||||||
|
if err := (<-store.OAuth().PermanentDeleteAuthDataByUser(a1.UserId)).Err; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -228,6 +228,99 @@ func (s SqlPostStore) Delete(postId string, time int64) StoreChannel {
|
|||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlPostStore) permanentDelete(postId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
_, 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())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(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 {
|
func (s SqlPostStore) GetPosts(channelId string, offset int, limit int) StoreChannel {
|
||||||
storeChannel := make(StoreChannel)
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
func TestPostStoreGetWithChildren(t *testing.T) {
|
||||||
Setup()
|
Setup()
|
||||||
|
|
||||||
|
|||||||
@@ -239,3 +239,21 @@ func (s SqlPreferenceStore) GetAll(userId string) StoreChannel {
|
|||||||
|
|
||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlPreferenceStore) PermanentDeleteByUser(userId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
if _, err := s.GetMaster().Exec(
|
||||||
|
`DELETE FROM Preferences WHERE UserId = :UserId`, map[string]interface{}{"UserId": userId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlPreferenceStore.Delete", "We encountered an error while deleteing preferences", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|||||||
@@ -192,3 +192,43 @@ func TestPreferenceGetAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPreferenceDelete(t *testing.T) {
|
||||||
|
Setup()
|
||||||
|
|
||||||
|
userId := model.NewId()
|
||||||
|
category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW
|
||||||
|
name := model.NewId()
|
||||||
|
|
||||||
|
preferences := model.Preferences{
|
||||||
|
{
|
||||||
|
UserId: userId,
|
||||||
|
Category: category,
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
// same user/category, different name
|
||||||
|
{
|
||||||
|
UserId: userId,
|
||||||
|
Category: category,
|
||||||
|
Name: model.NewId(),
|
||||||
|
},
|
||||||
|
// same user/name, different category
|
||||||
|
{
|
||||||
|
UserId: userId,
|
||||||
|
Category: model.NewId(),
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
// same name/category, different user
|
||||||
|
{
|
||||||
|
UserId: model.NewId(),
|
||||||
|
Category: category,
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Must(store.Preference().Save(&preferences))
|
||||||
|
|
||||||
|
if result := <-store.Preference().PermanentDeleteByUser(userId); result.Err != nil {
|
||||||
|
t.Fatal(result.Err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -158,6 +158,24 @@ func (me SqlSessionStore) RemoveAllSessionsForTeam(teamId string) StoreChannel {
|
|||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (me SqlSessionStore) PermanentDeleteSessionsByUser(userId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
_, err := me.GetMaster().Exec("DELETE FROM Sessions WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
|
||||||
|
if err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlSessionStore.RemoveAllSessionsForUser", "We couldn't remove all the sessions for the user", "id="+userId+", err="+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|
||||||
func (me SqlSessionStore) CleanUpExpiredSessions(userId string) StoreChannel {
|
func (me SqlSessionStore) CleanUpExpiredSessions(userId string) StoreChannel {
|
||||||
storeChannel := make(StoreChannel)
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,29 @@ func TestSessionRemoveAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSessionRemoveByUser(t *testing.T) {
|
||||||
|
Setup()
|
||||||
|
|
||||||
|
s1 := model.Session{}
|
||||||
|
s1.UserId = model.NewId()
|
||||||
|
s1.TeamId = model.NewId()
|
||||||
|
Must(store.Session().Save(&s1))
|
||||||
|
|
||||||
|
if rs1 := (<-store.Session().Get(s1.Id)); rs1.Err != nil {
|
||||||
|
t.Fatal(rs1.Err)
|
||||||
|
} else {
|
||||||
|
if rs1.Data.(*model.Session).Id != s1.Id {
|
||||||
|
t.Fatal("should match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Must(store.Session().PermanentDeleteSessionsByUser(s1.UserId))
|
||||||
|
|
||||||
|
if rs2 := (<-store.Session().Get(s1.Id)); rs2.Err == nil {
|
||||||
|
t.Fatal("should have been removed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSessionRemoveToken(t *testing.T) {
|
func TestSessionRemoveToken(t *testing.T) {
|
||||||
Setup()
|
Setup()
|
||||||
|
|
||||||
|
|||||||
@@ -300,3 +300,20 @@ func (s SqlTeamStore) GetAllTeamListing() StoreChannel {
|
|||||||
|
|
||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlTeamStore) PermanentDelete(teamId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
if _, err := s.GetMaster().Exec("DELETE FROM Teams WHERE Id = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlTeamStore.Delete", "We couldn't delete the existing team", "teamId="+teamId+", "+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|||||||
@@ -238,3 +238,26 @@ func TestAllTeamListing(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
Setup()
|
||||||
|
|
||||||
|
o1 := model.Team{}
|
||||||
|
o1.DisplayName = "DisplayName"
|
||||||
|
o1.Name = "a" + model.NewId() + "b"
|
||||||
|
o1.Email = model.NewId() + "@nowhere.com"
|
||||||
|
o1.Type = model.TEAM_OPEN
|
||||||
|
o1.AllowTeamListing = true
|
||||||
|
Must(store.Team().Save(&o1))
|
||||||
|
|
||||||
|
o2 := model.Team{}
|
||||||
|
o2.DisplayName = "DisplayName"
|
||||||
|
o2.Name = "a" + model.NewId() + "b"
|
||||||
|
o2.Email = model.NewId() + "@nowhere.com"
|
||||||
|
o2.Type = model.TEAM_OPEN
|
||||||
|
Must(store.Team().Save(&o2))
|
||||||
|
|
||||||
|
if r1 := <-store.Team().PermanentDelete(o1.Id); r1.Err != nil {
|
||||||
|
t.Fatal(r1.Err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -554,3 +554,21 @@ func (us SqlUserStore) GetTotalActiveUsersCount() StoreChannel {
|
|||||||
|
|
||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (us SqlUserStore) PermanentDelete(userId string) StoreChannel {
|
||||||
|
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
if _, err := us.GetMaster().Exec("DELETE FROM Users WHERE Id = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlUserStore.GetByEmail", "We couldn't delete the existing account", "userId="+userId+", "+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|||||||
@@ -377,3 +377,16 @@ func TestUserStoreUpdatePassword(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserStoreDelete(t *testing.T) {
|
||||||
|
Setup()
|
||||||
|
|
||||||
|
u1 := model.User{}
|
||||||
|
u1.TeamId = model.NewId()
|
||||||
|
u1.Email = model.NewId()
|
||||||
|
Must(store.User().Save(&u1))
|
||||||
|
|
||||||
|
if err := (<-store.User().PermanentDelete(u1.Id)).Err; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -116,6 +116,24 @@ func (s SqlWebhookStore) DeleteIncoming(webhookId string, time int64) StoreChann
|
|||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlWebhookStore) PermanentDeleteIncomingByUser(userId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
_, err := s.GetMaster().Exec("DELETE FROM IncomingWebhooks WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
|
||||||
|
if err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlWebhookStore.DeleteIncomingByUser", "We couldn't delete the webhook", "id="+userId+", err="+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|
||||||
func (s SqlWebhookStore) GetIncomingByUser(userId string) StoreChannel {
|
func (s SqlWebhookStore) GetIncomingByUser(userId string) StoreChannel {
|
||||||
storeChannel := make(StoreChannel)
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
@@ -294,6 +312,24 @@ func (s SqlWebhookStore) DeleteOutgoing(webhookId string, time int64) StoreChann
|
|||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlWebhookStore) PermanentDeleteOutgoingByUser(userId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
_, err := s.GetMaster().Exec("DELETE FROM OutgoingWebhooks WHERE CreatorId = :UserId", map[string]interface{}{"UserId": userId})
|
||||||
|
if err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlWebhookStore.DeleteOutgoingByUser", "We couldn't delete the webhook", "id="+userId+", err="+err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|
||||||
func (s SqlWebhookStore) UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel {
|
func (s SqlWebhookStore) UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel {
|
||||||
storeChannel := make(StoreChannel)
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,34 @@ func TestWebhookStoreDeleteIncoming(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWebhookStoreDeleteIncomingByUser(t *testing.T) {
|
||||||
|
Setup()
|
||||||
|
|
||||||
|
o1 := &model.IncomingWebhook{}
|
||||||
|
o1.ChannelId = model.NewId()
|
||||||
|
o1.UserId = model.NewId()
|
||||||
|
o1.TeamId = model.NewId()
|
||||||
|
|
||||||
|
o1 = (<-store.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook)
|
||||||
|
|
||||||
|
if r1 := <-store.Webhook().GetIncoming(o1.Id); r1.Err != nil {
|
||||||
|
t.Fatal(r1.Err)
|
||||||
|
} else {
|
||||||
|
if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt {
|
||||||
|
t.Fatal("invalid returned webhook")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r2 := <-store.Webhook().PermanentDeleteIncomingByUser(o1.UserId); r2.Err != nil {
|
||||||
|
t.Fatal(r2.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r3 := (<-store.Webhook().GetIncoming(o1.Id)); r3.Err == nil {
|
||||||
|
t.Log(r3.Data)
|
||||||
|
t.Fatal("Missing id should have failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestWebhookStoreSaveOutgoing(t *testing.T) {
|
func TestWebhookStoreSaveOutgoing(t *testing.T) {
|
||||||
Setup()
|
Setup()
|
||||||
|
|
||||||
@@ -258,6 +286,35 @@ func TestWebhookStoreDeleteOutgoing(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWebhookStoreDeleteOutgoingByUser(t *testing.T) {
|
||||||
|
Setup()
|
||||||
|
|
||||||
|
o1 := &model.OutgoingWebhook{}
|
||||||
|
o1.ChannelId = model.NewId()
|
||||||
|
o1.CreatorId = model.NewId()
|
||||||
|
o1.TeamId = model.NewId()
|
||||||
|
o1.CallbackURLs = []string{"http://nowhere.com/"}
|
||||||
|
|
||||||
|
o1 = (<-store.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook)
|
||||||
|
|
||||||
|
if r1 := <-store.Webhook().GetOutgoing(o1.Id); r1.Err != nil {
|
||||||
|
t.Fatal(r1.Err)
|
||||||
|
} else {
|
||||||
|
if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt {
|
||||||
|
t.Fatal("invalid returned webhook")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r2 := <-store.Webhook().PermanentDeleteOutgoingByUser(o1.CreatorId); r2.Err != nil {
|
||||||
|
t.Fatal(r2.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r3 := (<-store.Webhook().GetOutgoing(o1.Id)); r3.Err == nil {
|
||||||
|
t.Log(r3.Data)
|
||||||
|
t.Fatal("Missing id should have failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestWebhookStoreUpdateOutgoing(t *testing.T) {
|
func TestWebhookStoreUpdateOutgoing(t *testing.T) {
|
||||||
Setup()
|
Setup()
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ type TeamStore interface {
|
|||||||
GetAll() StoreChannel
|
GetAll() StoreChannel
|
||||||
GetAllTeamListing() StoreChannel
|
GetAllTeamListing() StoreChannel
|
||||||
GetByInviteId(inviteId string) StoreChannel
|
GetByInviteId(inviteId string) StoreChannel
|
||||||
|
PermanentDelete(teamId string) StoreChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelStore interface {
|
type ChannelStore interface {
|
||||||
@@ -60,6 +61,7 @@ type ChannelStore interface {
|
|||||||
Update(channel *model.Channel) StoreChannel
|
Update(channel *model.Channel) StoreChannel
|
||||||
Get(id string) StoreChannel
|
Get(id string) StoreChannel
|
||||||
Delete(channelId string, time int64) StoreChannel
|
Delete(channelId string, time int64) StoreChannel
|
||||||
|
PermanentDeleteByTeam(teamId string) StoreChannel
|
||||||
GetByName(team_id string, domain string) StoreChannel
|
GetByName(team_id string, domain string) StoreChannel
|
||||||
GetChannels(teamId string, userId string) StoreChannel
|
GetChannels(teamId string, userId string) StoreChannel
|
||||||
GetMoreChannels(teamId string, userId string) StoreChannel
|
GetMoreChannels(teamId string, userId string) StoreChannel
|
||||||
@@ -72,6 +74,7 @@ type ChannelStore interface {
|
|||||||
GetMember(channelId string, userId string) StoreChannel
|
GetMember(channelId string, userId string) StoreChannel
|
||||||
GetMemberCount(channelId string) StoreChannel
|
GetMemberCount(channelId string) StoreChannel
|
||||||
RemoveMember(channelId string, userId string) StoreChannel
|
RemoveMember(channelId string, userId string) StoreChannel
|
||||||
|
PermanentDeleteMembersByUser(userId string) StoreChannel
|
||||||
GetExtraMembers(channelId string, limit int) StoreChannel
|
GetExtraMembers(channelId string, limit int) StoreChannel
|
||||||
CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel
|
CheckPermissionsTo(teamId string, channelId string, userId string) StoreChannel
|
||||||
CheckOpenChannelPermissions(teamId string, channelId string) StoreChannel
|
CheckOpenChannelPermissions(teamId string, channelId string) StoreChannel
|
||||||
@@ -86,6 +89,7 @@ type PostStore interface {
|
|||||||
Update(post *model.Post, newMessage string, newHashtags string) StoreChannel
|
Update(post *model.Post, newMessage string, newHashtags string) StoreChannel
|
||||||
Get(id string) StoreChannel
|
Get(id string) StoreChannel
|
||||||
Delete(postId string, time int64) StoreChannel
|
Delete(postId string, time int64) StoreChannel
|
||||||
|
PermanentDeleteByUser(userId string) StoreChannel
|
||||||
GetPosts(channelId string, offset int, limit int) StoreChannel
|
GetPosts(channelId string, offset int, limit int) StoreChannel
|
||||||
GetPostsBefore(channelId string, postId string, numPosts int, offset int) StoreChannel
|
GetPostsBefore(channelId string, postId string, numPosts int, offset int) StoreChannel
|
||||||
GetPostsAfter(channelId string, postId string, numPosts int, offset int) StoreChannel
|
GetPostsAfter(channelId string, postId string, numPosts int, offset int) StoreChannel
|
||||||
@@ -118,6 +122,7 @@ type UserStore interface {
|
|||||||
GetTotalUsersCount() StoreChannel
|
GetTotalUsersCount() StoreChannel
|
||||||
GetTotalActiveUsersCount() StoreChannel
|
GetTotalActiveUsersCount() StoreChannel
|
||||||
GetSystemAdminProfiles() StoreChannel
|
GetSystemAdminProfiles() StoreChannel
|
||||||
|
PermanentDelete(userId string) StoreChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
type SessionStore interface {
|
type SessionStore interface {
|
||||||
@@ -126,6 +131,7 @@ type SessionStore interface {
|
|||||||
GetSessions(userId string) StoreChannel
|
GetSessions(userId string) StoreChannel
|
||||||
Remove(sessionIdOrToken string) StoreChannel
|
Remove(sessionIdOrToken string) StoreChannel
|
||||||
RemoveAllSessionsForTeam(teamId string) StoreChannel
|
RemoveAllSessionsForTeam(teamId string) StoreChannel
|
||||||
|
PermanentDeleteSessionsByUser(teamId string) StoreChannel
|
||||||
UpdateLastActivityAt(sessionId string, time int64) StoreChannel
|
UpdateLastActivityAt(sessionId string, time int64) StoreChannel
|
||||||
UpdateRoles(userId string, roles string) StoreChannel
|
UpdateRoles(userId string, roles string) StoreChannel
|
||||||
}
|
}
|
||||||
@@ -133,6 +139,7 @@ type SessionStore interface {
|
|||||||
type AuditStore interface {
|
type AuditStore interface {
|
||||||
Save(audit *model.Audit) StoreChannel
|
Save(audit *model.Audit) StoreChannel
|
||||||
Get(user_id string, limit int) StoreChannel
|
Get(user_id string, limit int) StoreChannel
|
||||||
|
PermanentDeleteByUser(userId string) StoreChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
type OAuthStore interface {
|
type OAuthStore interface {
|
||||||
@@ -143,6 +150,7 @@ type OAuthStore interface {
|
|||||||
SaveAuthData(authData *model.AuthData) StoreChannel
|
SaveAuthData(authData *model.AuthData) StoreChannel
|
||||||
GetAuthData(code string) StoreChannel
|
GetAuthData(code string) StoreChannel
|
||||||
RemoveAuthData(code string) StoreChannel
|
RemoveAuthData(code string) StoreChannel
|
||||||
|
PermanentDeleteAuthDataByUser(userId string) StoreChannel
|
||||||
SaveAccessData(accessData *model.AccessData) StoreChannel
|
SaveAccessData(accessData *model.AccessData) StoreChannel
|
||||||
GetAccessData(token string) StoreChannel
|
GetAccessData(token string) StoreChannel
|
||||||
GetAccessDataByAuthCode(authCode string) StoreChannel
|
GetAccessDataByAuthCode(authCode string) StoreChannel
|
||||||
@@ -161,12 +169,14 @@ type WebhookStore interface {
|
|||||||
GetIncomingByUser(userId string) StoreChannel
|
GetIncomingByUser(userId string) StoreChannel
|
||||||
GetIncomingByChannel(channelId string) StoreChannel
|
GetIncomingByChannel(channelId string) StoreChannel
|
||||||
DeleteIncoming(webhookId string, time int64) StoreChannel
|
DeleteIncoming(webhookId string, time int64) StoreChannel
|
||||||
|
PermanentDeleteIncomingByUser(userId string) StoreChannel
|
||||||
SaveOutgoing(webhook *model.OutgoingWebhook) StoreChannel
|
SaveOutgoing(webhook *model.OutgoingWebhook) StoreChannel
|
||||||
GetOutgoing(id string) StoreChannel
|
GetOutgoing(id string) StoreChannel
|
||||||
GetOutgoingByCreator(userId string) StoreChannel
|
GetOutgoingByCreator(userId string) StoreChannel
|
||||||
GetOutgoingByChannel(channelId string) StoreChannel
|
GetOutgoingByChannel(channelId string) StoreChannel
|
||||||
GetOutgoingByTeam(teamId string) StoreChannel
|
GetOutgoingByTeam(teamId string) StoreChannel
|
||||||
DeleteOutgoing(webhookId string, time int64) StoreChannel
|
DeleteOutgoing(webhookId string, time int64) StoreChannel
|
||||||
|
PermanentDeleteOutgoingByUser(userId string) StoreChannel
|
||||||
UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel
|
UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,4 +185,5 @@ type PreferenceStore interface {
|
|||||||
Get(userId string, category string, name string) StoreChannel
|
Get(userId string, category string, name string) StoreChannel
|
||||||
GetCategory(userId string, category string) StoreChannel
|
GetCategory(userId string, category string) StoreChannel
|
||||||
GetAll(userId string) StoreChannel
|
GetAll(userId string) StoreChannel
|
||||||
|
PermanentDeleteByUser(userId string) StoreChannel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,8 +59,7 @@ func FindDir(dir string) string {
|
|||||||
func ConfigureCmdLineLog() {
|
func ConfigureCmdLineLog() {
|
||||||
ls := model.LogSettings{}
|
ls := model.LogSettings{}
|
||||||
ls.EnableConsole = true
|
ls.EnableConsole = true
|
||||||
ls.ConsoleLevel = "ERROR"
|
ls.ConsoleLevel = "WARN"
|
||||||
ls.EnableFile = false
|
|
||||||
configureLog(&ls)
|
configureLog(&ls)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +71,8 @@ func configureLog(s *model.LogSettings) {
|
|||||||
level := l4g.DEBUG
|
level := l4g.DEBUG
|
||||||
if s.ConsoleLevel == "INFO" {
|
if s.ConsoleLevel == "INFO" {
|
||||||
level = l4g.INFO
|
level = l4g.INFO
|
||||||
|
} else if s.ConsoleLevel == "WARN" {
|
||||||
|
level = l4g.WARNING
|
||||||
} else if s.ConsoleLevel == "ERROR" {
|
} else if s.ConsoleLevel == "ERROR" {
|
||||||
level = l4g.ERROR
|
level = l4g.ERROR
|
||||||
}
|
}
|
||||||
@@ -90,6 +91,8 @@ func configureLog(s *model.LogSettings) {
|
|||||||
level := l4g.DEBUG
|
level := l4g.DEBUG
|
||||||
if s.FileLevel == "INFO" {
|
if s.FileLevel == "INFO" {
|
||||||
level = l4g.INFO
|
level = l4g.INFO
|
||||||
|
} else if s.FileLevel == "WARN" {
|
||||||
|
level = l4g.WARNING
|
||||||
} else if s.FileLevel == "ERROR" {
|
} else if s.FileLevel == "ERROR" {
|
||||||
level = l4g.ERROR
|
level = l4g.ERROR
|
||||||
}
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user