PLT-6019: Add APIv4 Endpoint for restoring Channels (#6263)
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
34728f748b
Коммит
0a20e8d326
@@ -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
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user