PLT-6019: Add APIv4 Endpoint for restoring Channels (#6263)

Этот коммит содержится в:
Robin Naundorf
2017-05-15 22:12:30 +02:00
коммит произвёл Joram Wilander
родитель 34728f748b
Коммит 0a20e8d326
7 изменённых файлов: 108 добавлений и 0 удалений

Просмотреть файл

@@ -29,6 +29,7 @@ func InitChannel() {
BaseRoutes.Channel.Handle("", ApiSessionRequired(getChannel)).Methods("GET") BaseRoutes.Channel.Handle("", ApiSessionRequired(getChannel)).Methods("GET")
BaseRoutes.Channel.Handle("", ApiSessionRequired(updateChannel)).Methods("PUT") BaseRoutes.Channel.Handle("", ApiSessionRequired(updateChannel)).Methods("PUT")
BaseRoutes.Channel.Handle("/patch", ApiSessionRequired(patchChannel)).Methods("PUT") BaseRoutes.Channel.Handle("/patch", ApiSessionRequired(patchChannel)).Methods("PUT")
BaseRoutes.Channel.Handle("/restore", ApiSessionRequired(restoreChannel)).Methods("POST")
BaseRoutes.Channel.Handle("", ApiSessionRequired(deleteChannel)).Methods("DELETE") BaseRoutes.Channel.Handle("", ApiSessionRequired(deleteChannel)).Methods("DELETE")
BaseRoutes.Channel.Handle("/stats", ApiSessionRequired(getChannelStats)).Methods("GET") BaseRoutes.Channel.Handle("/stats", ApiSessionRequired(getChannelStats)).Methods("GET")
BaseRoutes.Channel.Handle("/pinned", ApiSessionRequired(getPinnedPosts)).Methods("GET") BaseRoutes.Channel.Handle("/pinned", ApiSessionRequired(getPinnedPosts)).Methods("GET")
@@ -180,6 +181,36 @@ func patchChannel(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
func restoreChannel(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireChannelId()
if c.Err != nil {
return
}
var channel *model.Channel
var err *model.AppError
if channel, err = app.GetChannel(c.Params.ChannelId); err != nil {
c.Err = err
return
}
teamId := channel.TeamId
if !app.SessionHasPermissionToTeam(c.Session, teamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
return
}
channel, err = app.RestoreChannel(channel)
if err != nil {
c.Err = err
return
}
c.LogAudit("name=" + channel.Name)
w.Write([]byte(channel.ToJson()))
}
func CanManageChannel(c *Context, channel *model.Channel) bool { func CanManageChannel(c *Context, channel *model.Channel) bool {
if channel.Type == model.CHANNEL_OPEN && !app.SessionHasPermissionToChannel(c.Session, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES) { if channel.Type == model.CHANNEL_OPEN && !app.SessionHasPermissionToChannel(c.Session, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES) {
c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES) c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES)

Просмотреть файл

@@ -1067,6 +1067,32 @@ func TestDeleteChannel(t *testing.T) {
CheckNoError(t, resp) CheckNoError(t, resp)
} }
func TestRestoreChannel(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Client := th.Client
publicChannel1 := th.CreatePublicChannel()
Client.DeleteChannel(publicChannel1.Id)
privateChannel1 := th.CreatePrivateChannel()
Client.DeleteChannel(privateChannel1.Id)
_, resp := Client.RestoreChannel(publicChannel1.Id)
CheckForbiddenStatus(t, resp)
_, resp = Client.RestoreChannel(privateChannel1.Id)
CheckForbiddenStatus(t, resp)
th.LoginTeamAdmin()
_, resp = Client.RestoreChannel(publicChannel1.Id)
CheckOKStatus(t, resp)
_, resp = Client.RestoreChannel(privateChannel1.Id)
CheckOKStatus(t, resp)
}
func TestGetChannelByName(t *testing.T) { func TestGetChannelByName(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin() th := Setup().InitBasic().InitSystemAdmin()
defer TearDown() defer TearDown()

Просмотреть файл

@@ -285,6 +285,14 @@ func UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError) {
} }
} }
func RestoreChannel(channel *model.Channel) (*model.Channel, *model.AppError) {
if result := <-Srv.Store.Channel().Restore(channel.Id, model.GetMillis()); result.Err != nil {
return nil, result.Err
} else {
return channel, nil
}
}
func PatchChannel(channel *model.Channel, patch *model.ChannelPatch, userId string) (*model.Channel, *model.AppError) { func PatchChannel(channel *model.Channel, patch *model.ChannelPatch, userId string) (*model.Channel, *model.AppError) {
oldChannelDisplayName := channel.DisplayName oldChannelDisplayName := channel.DisplayName
oldChannelHeader := channel.Header oldChannelHeader := channel.Header

Просмотреть файл

@@ -1217,6 +1217,16 @@ func (c *Client4) PatchChannel(channelId string, patch *ChannelPatch) (*Channel,
} }
} }
// RestoreChannel restores a previously deleted channel. Any missing fields are not updated.
func (c *Client4) RestoreChannel(channelId string) (*Channel, *Response) {
if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/restore", ""); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return ChannelFromJson(r.Body), BuildResponse(r)
}
}
// CreateDirectChannel creates a direct message channel based on the two user // CreateDirectChannel creates a direct message channel based on the two user
// ids provided. // ids provided.
func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Response) { func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Response) {

Просмотреть файл

@@ -440,6 +440,10 @@ func (s SqlChannelStore) Delete(channelId string, time int64) StoreChannel {
return s.SetDeleteAt(channelId, time, time) return s.SetDeleteAt(channelId, time, time)
} }
func (s SqlChannelStore) Restore(channelId string, time int64) StoreChannel {
return s.SetDeleteAt(channelId, 0, time)
}
func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt int64, updateAt int64) StoreChannel { func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt int64, updateAt int64) StoreChannel {
storeChannel := make(StoreChannel, 1) storeChannel := make(StoreChannel, 1)

Просмотреть файл

@@ -364,6 +364,34 @@ func TestChannelStoreGetForPost(t *testing.T) {
} }
} }
func TestSqlChannelStoreRestore(t *testing.T) {
Setup()
o1 := model.Channel{}
o1.TeamId = model.NewId()
o1.DisplayName = "Channel1"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
Must(store.Channel().Save(&o1))
if r := <-store.Channel().Delete(o1.Id, model.GetMillis()); r.Err != nil {
t.Fatal(r.Err)
}
if r := <-store.Channel().Get(o1.Id, false); r.Data.(*model.Channel).DeleteAt == 0 {
t.Fatal("should have been deleted")
}
if r := <-store.Channel().Restore(o1.Id, model.GetMillis()); r.Err != nil {
t.Fatal(r.Err)
}
if r := <-store.Channel().Get(o1.Id, false); r.Data.(*model.Channel).DeleteAt != 0 {
t.Fatal("should have been restored")
}
}
func TestChannelStoreDelete(t *testing.T) { func TestChannelStoreDelete(t *testing.T) {
Setup() Setup()

Просмотреть файл

@@ -97,6 +97,7 @@ type ChannelStore interface {
InvalidateChannelByName(teamId, name string) InvalidateChannelByName(teamId, name string)
GetFromMaster(id string) StoreChannel GetFromMaster(id string) StoreChannel
Delete(channelId string, time int64) StoreChannel Delete(channelId string, time int64) StoreChannel
Restore(channelId string, time int64) StoreChannel
SetDeleteAt(channelId string, deleteAt int64, updateAt int64) StoreChannel SetDeleteAt(channelId string, deleteAt int64, updateAt int64) StoreChannel
PermanentDeleteByTeam(teamId string) StoreChannel PermanentDeleteByTeam(teamId string) StoreChannel
PermanentDelete(channelId string) StoreChannel PermanentDelete(channelId string) StoreChannel