summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2017-03-13 10:40:43 -0400
committerGitHub <noreply@github.com>2017-03-13 10:40:43 -0400
commit19c67d7fe35f92ae8a288dcdb9877d3bede41a61 (patch)
tree1119f74c30564ce53d5e7dc566009594e348f494
parent3ebfb369530e28ca3246c5cd2833e666edce9c90 (diff)
downloadchat-19c67d7fe35f92ae8a288dcdb9877d3bede41a61.tar.gz
chat-19c67d7fe35f92ae8a288dcdb9877d3bede41a61.tar.bz2
chat-19c67d7fe35f92ae8a288dcdb9877d3bede41a61.zip
Implement GET and POST /hooks/outgoing endpoints for APIv4 (#5645)
-rw-r--r--api4/webhook.go72
-rw-r--r--api4/webhook_test.go162
-rw-r--r--app/channel.go2
-rw-r--r--app/webhook.go32
-rw-r--r--model/client4.go47
-rw-r--r--store/sql_channel_store.go4
-rw-r--r--store/sql_webhook_store.go43
-rw-r--r--store/sql_webhook_store_test.go61
-rw-r--r--store/store.go5
9 files changed, 409 insertions, 19 deletions
diff --git a/api4/webhook.go b/api4/webhook.go
index 19a851390..923f66ad3 100644
--- a/api4/webhook.go
+++ b/api4/webhook.go
@@ -17,15 +17,17 @@ func InitWebhook() {
BaseRoutes.IncomingHooks.Handle("", ApiSessionRequired(createIncomingHook)).Methods("POST")
BaseRoutes.IncomingHooks.Handle("", ApiSessionRequired(getIncomingHooks)).Methods("GET")
-
BaseRoutes.IncomingHook.Handle("", ApiSessionRequired(getIncomingHook)).Methods("GET")
BaseRoutes.IncomingHook.Handle("", ApiSessionRequired(deleteIncomingHook)).Methods("DELETE")
+
+ BaseRoutes.OutgoingHooks.Handle("", ApiSessionRequired(createOutgoingHook)).Methods("POST")
+ BaseRoutes.OutgoingHooks.Handle("", ApiSessionRequired(getOutgoingHooks)).Methods("GET")
}
func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
hook := model.IncomingWebhookFromJson(r.Body)
if hook == nil {
- c.SetInvalidParam("webhook")
+ c.SetInvalidParam("incoming_webhook")
return
}
@@ -53,6 +55,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
c.LogAudit("success")
+ w.WriteHeader(http.StatusCreated)
w.Write([]byte(incomingHook.ToJson()))
}
}
@@ -158,3 +161,68 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
}
+
+func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
+ hook := model.OutgoingWebhookFromJson(r.Body)
+ if hook == nil {
+ c.SetInvalidParam("outgoing_webhook")
+ return
+ }
+
+ c.LogAudit("attempt")
+
+ hook.CreatorId = c.Session.UserId
+
+ if !app.SessionHasPermissionToTeam(c.Session, hook.TeamId, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.SetPermissionError(model.PERMISSION_MANAGE_WEBHOOKS)
+ return
+ }
+
+ if rhook, err := app.CreateOutgoingWebhook(hook); err != nil {
+ c.LogAudit("fail")
+ c.Err = err
+ return
+ } else {
+ c.LogAudit("success")
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(rhook.ToJson()))
+ }
+}
+
+func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
+ channelId := r.URL.Query().Get("channel_id")
+ teamId := r.URL.Query().Get("team_id")
+
+ var hooks []*model.OutgoingWebhook
+ var err *model.AppError
+
+ if len(channelId) > 0 {
+ if !app.SessionHasPermissionToChannel(c.Session, channelId, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.SetPermissionError(model.PERMISSION_MANAGE_WEBHOOKS)
+ return
+ }
+
+ hooks, err = app.GetOutgoingWebhooksForChannelPage(channelId, c.Params.Page, c.Params.PerPage)
+ } else if len(teamId) > 0 {
+ if !app.SessionHasPermissionToTeam(c.Session, teamId, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.SetPermissionError(model.PERMISSION_MANAGE_WEBHOOKS)
+ return
+ }
+
+ hooks, err = app.GetOutgoingWebhooksForTeamPage(teamId, c.Params.Page, c.Params.PerPage)
+ } else {
+ if !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_WEBHOOKS) {
+ c.SetPermissionError(model.PERMISSION_MANAGE_WEBHOOKS)
+ return
+ }
+
+ hooks, err = app.GetOutgoingWebhooksPage(c.Params.Page, c.Params.PerPage)
+ }
+
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ w.Write([]byte(model.OutgoingWebhookListToJson(hooks)))
+}
diff --git a/api4/webhook_test.go b/api4/webhook_test.go
index bfd75c7ec..2d8a1e8f9 100644
--- a/api4/webhook_test.go
+++ b/api4/webhook_test.go
@@ -256,3 +256,165 @@ func TestDeleteIncomingWebhook(t *testing.T) {
CheckForbiddenStatus(t, resp)
})
}
+
+func TestCreateOutgoingWebhook(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+
+ enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks
+ enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
+ defer func() {
+ utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
+ utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
+ }()
+ utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
+ *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
+
+ hook := &model.OutgoingWebhook{ChannelId: th.BasicChannel.Id, TeamId: th.BasicChannel.TeamId, CallbackURLs: []string{"http://nowhere.com"}}
+
+ rhook, resp := th.SystemAdminClient.CreateOutgoingWebhook(hook)
+ CheckNoError(t, resp)
+
+ if rhook.ChannelId != hook.ChannelId {
+ t.Fatal("channel ids didn't match")
+ } else if rhook.CreatorId != th.SystemAdminUser.Id {
+ t.Fatal("user ids didn't match")
+ } else if rhook.TeamId != th.BasicChannel.TeamId {
+ t.Fatal("team ids didn't match")
+ }
+
+ hook.ChannelId = "junk"
+ _, resp = th.SystemAdminClient.CreateOutgoingWebhook(hook)
+ CheckNotFoundStatus(t, resp)
+
+ hook.ChannelId = th.BasicChannel.Id
+ th.LoginTeamAdmin()
+ _, resp = Client.CreateOutgoingWebhook(hook)
+ CheckNoError(t, resp)
+
+ th.LoginBasic()
+ _, resp = Client.CreateOutgoingWebhook(hook)
+ CheckForbiddenStatus(t, resp)
+
+ *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
+
+ _, resp = Client.CreateOutgoingWebhook(hook)
+ CheckNoError(t, resp)
+
+ utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = false
+ _, resp = Client.CreateOutgoingWebhook(hook)
+ CheckNotImplementedStatus(t, resp)
+}
+
+func TestGetOutgoingWebhooks(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+
+ enableOutgoingHooks := utils.Cfg.ServiceSettings.EnableOutgoingWebhooks
+ enableAdminOnlyHooks := utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations
+ defer func() {
+ utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingHooks
+ utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = enableAdminOnlyHooks
+ utils.SetDefaultRolesBasedOnConfig()
+ }()
+ utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = true
+ *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = true
+ utils.SetDefaultRolesBasedOnConfig()
+
+ hook := &model.OutgoingWebhook{ChannelId: th.BasicChannel.Id, TeamId: th.BasicChannel.TeamId, CallbackURLs: []string{"http://nowhere.com"}}
+ rhook, resp := th.SystemAdminClient.CreateOutgoingWebhook(hook)
+ CheckNoError(t, resp)
+
+ hooks, resp := th.SystemAdminClient.GetOutgoingWebhooks(0, 1000, "")
+ CheckNoError(t, resp)
+
+ found := false
+ for _, h := range hooks {
+ if rhook.Id == h.Id {
+ found = true
+ }
+ }
+
+ if !found {
+ t.Fatal("missing hook")
+ }
+
+ hooks, resp = th.SystemAdminClient.GetOutgoingWebhooks(0, 1, "")
+ CheckNoError(t, resp)
+
+ if len(hooks) != 1 {
+ t.Fatal("should only be 1")
+ }
+
+ hooks, resp = th.SystemAdminClient.GetOutgoingWebhooksForTeam(th.BasicTeam.Id, 0, 1000, "")
+ CheckNoError(t, resp)
+
+ found = false
+ for _, h := range hooks {
+ if rhook.Id == h.Id {
+ found = true
+ }
+ }
+
+ if !found {
+ t.Fatal("missing hook")
+ }
+
+ hooks, resp = th.SystemAdminClient.GetOutgoingWebhooksForTeam(model.NewId(), 0, 1000, "")
+ CheckNoError(t, resp)
+
+ if len(hooks) != 0 {
+ t.Fatal("no hooks should be returned")
+ }
+
+ hooks, resp = th.SystemAdminClient.GetOutgoingWebhooksForChannel(th.BasicChannel.Id, 0, 1000, "")
+ CheckNoError(t, resp)
+
+ found = false
+ for _, h := range hooks {
+ if rhook.Id == h.Id {
+ found = true
+ }
+ }
+
+ if !found {
+ t.Fatal("missing hook")
+ }
+
+ hooks, resp = th.SystemAdminClient.GetOutgoingWebhooksForChannel(model.NewId(), 0, 1000, "")
+ CheckNoError(t, resp)
+
+ if len(hooks) != 0 {
+ t.Fatal("no hooks should be returned")
+ }
+
+ _, resp = Client.GetOutgoingWebhooks(0, 1000, "")
+ CheckForbiddenStatus(t, resp)
+
+ *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
+ utils.SetDefaultRolesBasedOnConfig()
+
+ _, resp = Client.GetOutgoingWebhooksForTeam(th.BasicTeam.Id, 0, 1000, "")
+ CheckNoError(t, resp)
+
+ _, resp = Client.GetOutgoingWebhooksForTeam(model.NewId(), 0, 1000, "")
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.GetOutgoingWebhooksForChannel(th.BasicChannel.Id, 0, 1000, "")
+ CheckNoError(t, resp)
+
+ _, resp = Client.GetOutgoingWebhooksForChannel(model.NewId(), 0, 1000, "")
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.GetOutgoingWebhooks(0, 1000, "")
+ CheckForbiddenStatus(t, resp)
+
+ Client.Logout()
+ _, resp = Client.GetOutgoingWebhooks(0, 1000, "")
+ CheckUnauthorizedStatus(t, resp)
+}
diff --git a/app/channel.go b/app/channel.go
index 67caed94d..59b71c0a5 100644
--- a/app/channel.go
+++ b/app/channel.go
@@ -313,7 +313,7 @@ func UpdateChannelMemberNotifyProps(data map[string]string, channelId string, us
func DeleteChannel(channel *model.Channel, userId string) *model.AppError {
uc := Srv.Store.User().Get(userId)
ihc := Srv.Store.Webhook().GetIncomingByChannel(channel.Id)
- ohc := Srv.Store.Webhook().GetOutgoingByChannel(channel.Id)
+ ohc := Srv.Store.Webhook().GetOutgoingByChannel(channel.Id, -1, -1)
if uresult := <-uc; uresult.Err != nil {
return uresult.Err
diff --git a/app/webhook.go b/app/webhook.go
index 6f1cec4a8..555b0f51d 100644
--- a/app/webhook.go
+++ b/app/webhook.go
@@ -33,7 +33,7 @@ func handleWebhookEvents(post *model.Post, team *model.Team, channel *model.Chan
return nil
}
- hchan := Srv.Store.Webhook().GetOutgoingByTeam(team.Id)
+ hchan := Srv.Store.Webhook().GetOutgoingByTeam(team.Id, -1, -1)
result := <-hchan
if result.Err != nil {
return result.Err
@@ -304,7 +304,7 @@ func CreateOutgoingWebhook(hook *model.OutgoingWebhook) (*model.OutgoingWebhook,
return nil, model.NewAppError("CreateOutgoingWebhook", "api.webhook.create_outgoing.triggers.app_error", nil, "", http.StatusBadRequest)
}
- if result := <-Srv.Store.Webhook().GetOutgoingByTeam(hook.TeamId); result.Err != nil {
+ if result := <-Srv.Store.Webhook().GetOutgoingByTeam(hook.TeamId, -1, -1); result.Err != nil {
return nil, result.Err
} else {
allHooks := result.Data.([]*model.OutgoingWebhook)
@@ -349,7 +349,7 @@ func UpdateOutgoingWebhook(oldHook, updatedHook *model.OutgoingWebhook) (*model.
}
var result store.StoreResult
- if result = <-Srv.Store.Webhook().GetOutgoingByTeam(oldHook.TeamId); result.Err != nil {
+ if result = <-Srv.Store.Webhook().GetOutgoingByTeam(oldHook.TeamId, -1, -1); result.Err != nil {
return nil, result.Err
}
@@ -389,12 +389,36 @@ func GetOutgoingWebhook(hookId string) (*model.OutgoingWebhook, *model.AppError)
}
}
+func GetOutgoingWebhooksPage(page, perPage int) ([]*model.OutgoingWebhook, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
+ return nil, model.NewAppError("GetOutgoingWebhooksPage", "api.outgoing_webhook.disabled.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if result := <-Srv.Store.Webhook().GetOutgoingList(page*perPage, perPage); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.OutgoingWebhook), nil
+ }
+}
+
+func GetOutgoingWebhooksForChannelPage(channelId string, page, perPage int) ([]*model.OutgoingWebhook, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
+ return nil, model.NewAppError("GetOutgoingWebhooksForChannelPage", "api.outgoing_webhook.disabled.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if result := <-Srv.Store.Webhook().GetOutgoingByChannel(channelId, page*perPage, perPage); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.OutgoingWebhook), nil
+ }
+}
+
func GetOutgoingWebhooksForTeamPage(teamId string, page, perPage int) ([]*model.OutgoingWebhook, *model.AppError) {
if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
return nil, model.NewAppError("GetOutgoingWebhooksForTeamPage", "api.outgoing_webhook.disabled.app_error", nil, "", http.StatusNotImplemented)
}
- if result := <-Srv.Store.Webhook().GetOutgoingByTeam(teamId); result.Err != nil {
+ if result := <-Srv.Store.Webhook().GetOutgoingByTeam(teamId, page*perPage, perPage); result.Err != nil {
return nil, result.Err
} else {
return result.Data.([]*model.OutgoingWebhook), nil
diff --git a/model/client4.go b/model/client4.go
index 94ac2c144..629bc69dd 100644
--- a/model/client4.go
+++ b/model/client4.go
@@ -162,6 +162,10 @@ func (c *Client4) GetComplianceReportRoute(reportId string) string {
return fmt.Sprintf("/compliance/reports/%v", reportId)
}
+func (c *Client4) GetOutgoingWebhooksRoute() string {
+ return fmt.Sprintf("/hooks/outgoing")
+}
+
func (c *Client4) GetPreferencesRoute(userId string) string {
return fmt.Sprintf(c.GetUserRoute(userId) + "/preferences")
}
@@ -1125,6 +1129,49 @@ func (c *Client4) DeleteIncomingWebhook(hookID string) (bool, *Response) {
}
}
+// CreateOutgoingWebhook creates an outgoing webhook for a team or channel.
+func (c *Client4) CreateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) {
+ if r, err := c.DoApiPost(c.GetOutgoingWebhooksRoute(), hook.ToJson()); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// GetOutgoingWebhooks returns a page of outgoing webhooks on the system. Page counting starts at 0.
+func (c *Client4) GetOutgoingWebhooks(page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
+ query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
+ if r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// GetOutgoingWebhooksForChannel returns a page of outgoing webhooks for a channel. Page counting starts at 0.
+func (c *Client4) GetOutgoingWebhooksForChannel(channelId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
+ query := fmt.Sprintf("?page=%v&per_page=%v&channel_id=%v", page, perPage, channelId)
+ if r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// GetOutgoingWebhooksForTeam returns a page of outgoing webhooks for a team. Page counting starts at 0.
+func (c *Client4) GetOutgoingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
+ query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId)
+ if r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
+ }
+}
+
// Preferences Section
// GetPreferences returns the user's preferences.
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go
index 0ee6ae308..a85bb0656 100644
--- a/store/sql_channel_store.go
+++ b/store/sql_channel_store.go
@@ -386,9 +386,9 @@ func (s SqlChannelStore) get(id string, master bool, allowFromCache bool) StoreC
}
if obj, err := db.Get(model.Channel{}, id); err != nil {
- result.Err = model.NewLocAppError("SqlChannelStore.Get", "store.sql_channel.get.find.app_error", nil, "id="+id+", "+err.Error())
+ result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.find.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError)
} else if obj == nil {
- result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.existing.app_error", nil, "id="+id, http.StatusBadRequest)
+ result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.existing.app_error", nil, "id="+id, http.StatusNotFound)
} else {
result.Data = obj.(*model.Channel)
channelCache.AddWithExpiresInSecs(id, obj.(*model.Channel), CHANNEL_CACHE_SEC)
diff --git a/store/sql_webhook_store.go b/store/sql_webhook_store.go
index e0e6562bf..67290c983 100644
--- a/store/sql_webhook_store.go
+++ b/store/sql_webhook_store.go
@@ -329,7 +329,7 @@ func (s SqlWebhookStore) GetOutgoing(id string) StoreChannel {
return storeChannel
}
-func (s SqlWebhookStore) GetOutgoingByChannel(channelId string) StoreChannel {
+func (s SqlWebhookStore) GetOutgoingList(offset, limit int) StoreChannel {
storeChannel := make(StoreChannel, 1)
go func() {
@@ -337,7 +337,35 @@ func (s SqlWebhookStore) GetOutgoingByChannel(channelId string) StoreChannel {
var webhooks []*model.OutgoingWebhook
- if _, err := s.GetReplica().Select(&webhooks, "SELECT * FROM OutgoingWebhooks WHERE ChannelId = :ChannelId AND DeleteAt = 0", map[string]interface{}{"ChannelId": channelId}); err != nil {
+ if _, err := s.GetReplica().Select(&webhooks, "SELECT * FROM OutgoingWebhooks WHERE DeleteAt = 0 LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil {
+ result.Err = model.NewLocAppError("SqlWebhookStore.GetOutgoingList", "store.sql_webhooks.get_outgoing_by_channel.app_error", nil, "err="+err.Error())
+ }
+
+ result.Data = webhooks
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlWebhookStore) GetOutgoingByChannel(channelId string, offset, limit int) StoreChannel {
+ storeChannel := make(StoreChannel, 1)
+
+ go func() {
+ result := StoreResult{}
+
+ var webhooks []*model.OutgoingWebhook
+
+ query := ""
+ if limit < 0 || offset < 0 {
+ query = "SELECT * FROM OutgoingWebhooks WHERE ChannelId = :ChannelId AND DeleteAt = 0"
+ } else {
+ query = "SELECT * FROM OutgoingWebhooks WHERE ChannelId = :ChannelId AND DeleteAt = 0 LIMIT :Limit OFFSET :Offset"
+ }
+
+ if _, err := s.GetReplica().Select(&webhooks, query, map[string]interface{}{"ChannelId": channelId, "Offset": offset, "Limit": limit}); err != nil {
result.Err = model.NewLocAppError("SqlWebhookStore.GetOutgoingByChannel", "store.sql_webhooks.get_outgoing_by_channel.app_error", nil, "channelId="+channelId+", err="+err.Error())
}
@@ -350,7 +378,7 @@ func (s SqlWebhookStore) GetOutgoingByChannel(channelId string) StoreChannel {
return storeChannel
}
-func (s SqlWebhookStore) GetOutgoingByTeam(teamId string) StoreChannel {
+func (s SqlWebhookStore) GetOutgoingByTeam(teamId string, offset, limit int) StoreChannel {
storeChannel := make(StoreChannel, 1)
go func() {
@@ -358,7 +386,14 @@ func (s SqlWebhookStore) GetOutgoingByTeam(teamId string) StoreChannel {
var webhooks []*model.OutgoingWebhook
- if _, err := s.GetReplica().Select(&webhooks, "SELECT * FROM OutgoingWebhooks WHERE TeamId = :TeamId AND DeleteAt = 0", map[string]interface{}{"TeamId": teamId}); err != nil {
+ query := ""
+ if limit < 0 || offset < 0 {
+ query = "SELECT * FROM OutgoingWebhooks WHERE TeamId = :TeamId AND DeleteAt = 0"
+ } else {
+ query = "SELECT * FROM OutgoingWebhooks WHERE TeamId = :TeamId AND DeleteAt = 0 LIMIT :Limit OFFSET :Offset"
+ }
+
+ if _, err := s.GetReplica().Select(&webhooks, query, map[string]interface{}{"TeamId": teamId, "Offset": offset, "Limit": limit}); err != nil {
result.Err = model.NewLocAppError("SqlWebhookStore.GetOutgoingByTeam", "store.sql_webhooks.get_outgoing_by_team.app_error", nil, "teamId="+teamId+", err="+err.Error())
}
diff --git a/store/sql_webhook_store_test.go b/store/sql_webhook_store_test.go
index 20bb8c151..6cfe36450 100644
--- a/store/sql_webhook_store_test.go
+++ b/store/sql_webhook_store_test.go
@@ -240,6 +240,59 @@ func TestWebhookStoreGetOutgoing(t *testing.T) {
}
}
+func TestWebhookStoreGetOutgoingList(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)
+
+ o2 := &model.OutgoingWebhook{}
+ o2.ChannelId = model.NewId()
+ o2.CreatorId = model.NewId()
+ o2.TeamId = model.NewId()
+ o2.CallbackURLs = []string{"http://nowhere.com/"}
+
+ o2 = (<-store.Webhook().SaveOutgoing(o2)).Data.(*model.OutgoingWebhook)
+
+ if r1 := <-store.Webhook().GetOutgoingList(0, 1000); r1.Err != nil {
+ t.Fatal(r1.Err)
+ } else {
+ hooks := r1.Data.([]*model.OutgoingWebhook)
+ found1 := false
+ found2 := false
+
+ for _, hook := range hooks {
+ if hook.CreateAt != o1.CreateAt {
+ found1 = true
+ }
+
+ if hook.CreateAt != o2.CreateAt {
+ found2 = true
+ }
+ }
+
+ if !found1 {
+ t.Fatal("missing hook1")
+ }
+ if !found2 {
+ t.Fatal("missing hook2")
+ }
+ }
+
+ if result := <-store.Webhook().GetOutgoingList(0, 2); result.Err != nil {
+ t.Fatal(result.Err)
+ } else {
+ if len(result.Data.([]*model.OutgoingWebhook)) != 2 {
+ t.Fatal("wrong number of hooks returned")
+ }
+ }
+}
+
func TestWebhookStoreGetOutgoingByChannel(t *testing.T) {
Setup()
@@ -251,7 +304,7 @@ func TestWebhookStoreGetOutgoingByChannel(t *testing.T) {
o1 = (<-store.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook)
- if r1 := <-store.Webhook().GetOutgoingByChannel(o1.ChannelId); r1.Err != nil {
+ if r1 := <-store.Webhook().GetOutgoingByChannel(o1.ChannelId, 0, 100); r1.Err != nil {
t.Fatal(r1.Err)
} else {
if r1.Data.([]*model.OutgoingWebhook)[0].CreateAt != o1.CreateAt {
@@ -259,7 +312,7 @@ func TestWebhookStoreGetOutgoingByChannel(t *testing.T) {
}
}
- if result := <-store.Webhook().GetOutgoingByChannel("123"); result.Err != nil {
+ if result := <-store.Webhook().GetOutgoingByChannel("123", -1, -1); result.Err != nil {
t.Fatal(result.Err)
} else {
if len(result.Data.([]*model.OutgoingWebhook)) != 0 {
@@ -279,7 +332,7 @@ func TestWebhookStoreGetOutgoingByTeam(t *testing.T) {
o1 = (<-store.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook)
- if r1 := <-store.Webhook().GetOutgoingByTeam(o1.TeamId); r1.Err != nil {
+ if r1 := <-store.Webhook().GetOutgoingByTeam(o1.TeamId, 0, 100); r1.Err != nil {
t.Fatal(r1.Err)
} else {
if r1.Data.([]*model.OutgoingWebhook)[0].CreateAt != o1.CreateAt {
@@ -287,7 +340,7 @@ func TestWebhookStoreGetOutgoingByTeam(t *testing.T) {
}
}
- if result := <-store.Webhook().GetOutgoingByTeam("123"); result.Err != nil {
+ if result := <-store.Webhook().GetOutgoingByTeam("123", -1, -1); result.Err != nil {
t.Fatal(result.Err)
} else {
if len(result.Data.([]*model.OutgoingWebhook)) != 0 {
diff --git a/store/store.go b/store/store.go
index 5596fa7f8..497f613da 100644
--- a/store/store.go
+++ b/store/store.go
@@ -273,8 +273,9 @@ type WebhookStore interface {
SaveOutgoing(webhook *model.OutgoingWebhook) StoreChannel
GetOutgoing(id string) StoreChannel
- GetOutgoingByChannel(channelId string) StoreChannel
- GetOutgoingByTeam(teamId string) StoreChannel
+ GetOutgoingList(offset, limit int) StoreChannel
+ GetOutgoingByChannel(channelId string, offset, limit int) StoreChannel
+ GetOutgoingByTeam(teamId string, offset, limit int) StoreChannel
DeleteOutgoing(webhookId string, time int64) StoreChannel
PermanentDeleteOutgoingByUser(userId string) StoreChannel
UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel