3
0

Remove webhooks (endpoints, service, type, db tables, ...)

This commit is contained in:
Denis Arh
2020-06-02 15:18:21 +02:00
parent ef95660d4b
commit 2a9e9411b6
28 changed files with 27 additions and 2916 deletions

View File

@@ -879,275 +879,6 @@
}
]
},
{
"entrypoint": "webhooks",
"authentication": [],
"path": "/webhooks",
"method": "GET",
"title": "Webhooks",
"struct": [
{
"imports": [
"github.com/cortezaproject/corteza-server/messaging/types"
]
}
],
"parameters": {},
"apis": [
{
"name": "list",
"path": "/",
"method": "GET",
"title": "List created webhooks",
"parameters": {
"get": [
{
"name": "channelID",
"type": "uint64",
"required": false,
"title": "Channel ID"
},
{
"name": "userID",
"type": "uint64",
"required": false,
"title": "Owner user ID"
}
]
}
},
{
"name": "create",
"path": "/",
"method": "POST",
"title": "Create webhook",
"parameters": {
"post": [
{
"name": "channelID",
"type": "uint64",
"required": true,
"title": "Channel ID"
},
{
"name": "kind",
"type": "types.WebhookKind",
"required": true,
"title": "Kind (incoming, outgoing)"
},
{
"name": "userID",
"type": "uint64",
"required": true,
"title": "Bot User ID"
},
{
"name": "trigger",
"type": "string",
"required": false,
"title": "Trigger word"
},
{
"name": "url",
"type": "string",
"required": false,
"title": "POST URL"
},
{
"name": "username",
"type": "string",
"required": false,
"title": "Default user name"
},
{
"name": "avatar",
"type": "*multipart.FileHeader",
"required": false,
"title": "Default avatar"
},
{
"name": "avatarURL",
"type": "string",
"required": false,
"title": "Default avatar (from URL)"
}
]
}
},
{
"name": "update",
"path": "/{webhookID}",
"method": "POST",
"title": "Attach file to channel",
"parameters": {
"path": [
{
"name": "webhookID",
"type": "uint64",
"required": true,
"title": "Webhook ID"
}
],
"post": [
{
"name": "channelID",
"type": "uint64",
"required": true,
"title": "Channel ID"
},
{
"name": "kind",
"type": "types.WebhookKind",
"required": true,
"title": "Kind (incoming, outgoing)"
},
{
"name": "userID",
"type": "uint64",
"required": true,
"title": "Bot User ID"
},
{
"name": "trigger",
"type": "string",
"required": false,
"title": "Trigger word"
},
{
"name": "url",
"type": "string",
"required": false,
"title": "POST URL"
},
{
"name": "username",
"type": "string",
"required": false,
"title": "Default user name"
},
{
"name": "avatar",
"type": "*multipart.FileHeader",
"required": false,
"title": "Default avatar"
},
{
"name": "avatarURL",
"type": "string",
"required": false,
"title": "Default avatar (from URL)"
}
]
}
},
{
"method": "GET",
"name": "get",
"path": "/{webhookID}",
"title": "Get webhook details",
"parameters": {
"path": [
{
"name": "webhookID",
"type": "uint64",
"required": true,
"title": "Webhook ID"
}
]
}
},
{
"method": "DELETE",
"name": "delete",
"path": "/{webhookID}",
"title": "Delete webhook",
"parameters": {
"path": [
{
"name": "webhookID",
"type": "uint64",
"required": true,
"title": "Webhook ID"
}
]
}
}
]
},
{
"entrypoint": "webhooks_public",
"authentication": [],
"path": "/webhooks",
"method": "GET",
"title": "Webhooks (Public)",
"parameters": {},
"apis": [
{
"method": "DELETE",
"name": "delete",
"path": "/{webhookID}/{webhookToken}",
"title": "Delete webhook",
"parameters": {
"path": [
{
"name": "webhookID",
"type": "uint64",
"required": true,
"title": "Webhook ID"
},
{
"name": "webhookToken",
"type": "string",
"required": true,
"title": "Authentication token"
}
]
}
},
{
"method": "POST",
"name": "create",
"path": "/{webhookID}/{webhookToken}",
"title": "Create a message from a webhook payload",
"parameters": {
"path": [
{
"name": "webhookID",
"type": "uint64",
"required": true,
"title": "Webhook ID"
},
{
"name": "webhookToken",
"type": "string",
"required": true,
"title": "Authentication token"
}
],
"get": [
{
"name": "username",
"type": "string",
"required": false,
"title": "Custom username for webhook message"
},
{
"name": "avatarURL",
"type": "string",
"required": false,
"title": "Custom avatar picture for webhook message"
},
{
"name": "content",
"type": "string",
"required": true,
"title": "Message contents"
}
]
}
}
]
},
{
"title": "Permissions",
"parameters": {},

View File

@@ -1,195 +0,0 @@
{
"Title": "Webhooks",
"Interface": "Webhooks",
"Struct": [
{
"imports": [
"github.com/cortezaproject/corteza-server/messaging/types"
]
}
],
"Parameters": {},
"Protocol": "",
"Authentication": [],
"Path": "/webhooks",
"APIs": [
{
"Name": "list",
"Method": "GET",
"Title": "List created webhooks",
"Path": "/",
"Parameters": {
"get": [
{
"name": "channelID",
"required": false,
"title": "Channel ID",
"type": "uint64"
},
{
"name": "userID",
"required": false,
"title": "Owner user ID",
"type": "uint64"
}
]
}
},
{
"Name": "create",
"Method": "POST",
"Title": "Create webhook",
"Path": "/",
"Parameters": {
"post": [
{
"name": "channelID",
"required": true,
"title": "Channel ID",
"type": "uint64"
},
{
"name": "kind",
"required": true,
"title": "Kind (incoming, outgoing)",
"type": "types.WebhookKind"
},
{
"name": "userID",
"required": true,
"title": "Bot User ID",
"type": "uint64"
},
{
"name": "trigger",
"required": false,
"title": "Trigger word",
"type": "string"
},
{
"name": "url",
"required": false,
"title": "POST URL",
"type": "string"
},
{
"name": "username",
"required": false,
"title": "Default user name",
"type": "string"
},
{
"name": "avatar",
"required": false,
"title": "Default avatar",
"type": "*multipart.FileHeader"
},
{
"name": "avatarURL",
"required": false,
"title": "Default avatar (from URL)",
"type": "string"
}
]
}
},
{
"Name": "update",
"Method": "POST",
"Title": "Attach file to channel",
"Path": "/{webhookID}",
"Parameters": {
"path": [
{
"name": "webhookID",
"required": true,
"title": "Webhook ID",
"type": "uint64"
}
],
"post": [
{
"name": "channelID",
"required": true,
"title": "Channel ID",
"type": "uint64"
},
{
"name": "kind",
"required": true,
"title": "Kind (incoming, outgoing)",
"type": "types.WebhookKind"
},
{
"name": "userID",
"required": true,
"title": "Bot User ID",
"type": "uint64"
},
{
"name": "trigger",
"required": false,
"title": "Trigger word",
"type": "string"
},
{
"name": "url",
"required": false,
"title": "POST URL",
"type": "string"
},
{
"name": "username",
"required": false,
"title": "Default user name",
"type": "string"
},
{
"name": "avatar",
"required": false,
"title": "Default avatar",
"type": "*multipart.FileHeader"
},
{
"name": "avatarURL",
"required": false,
"title": "Default avatar (from URL)",
"type": "string"
}
]
}
},
{
"Name": "get",
"Method": "GET",
"Title": "Get webhook details",
"Path": "/{webhookID}",
"Parameters": {
"path": [
{
"name": "webhookID",
"required": true,
"title": "Webhook ID",
"type": "uint64"
}
]
}
},
{
"Name": "delete",
"Method": "DELETE",
"Title": "Delete webhook",
"Path": "/{webhookID}",
"Parameters": {
"path": [
{
"name": "webhookID",
"required": true,
"title": "Webhook ID",
"type": "uint64"
}
]
}
}
]
}

View File

@@ -1,75 +0,0 @@
{
"Title": "Webhooks (Public)",
"Interface": "Webhooks_public",
"Struct": null,
"Parameters": {},
"Protocol": "",
"Authentication": [],
"Path": "/webhooks",
"APIs": [
{
"Name": "delete",
"Method": "DELETE",
"Title": "Delete webhook",
"Path": "/{webhookID}/{webhookToken}",
"Parameters": {
"path": [
{
"name": "webhookID",
"required": true,
"title": "Webhook ID",
"type": "uint64"
},
{
"name": "webhookToken",
"required": true,
"title": "Authentication token",
"type": "string"
}
]
}
},
{
"Name": "create",
"Method": "POST",
"Title": "Create a message from a webhook payload",
"Path": "/{webhookID}/{webhookToken}",
"Parameters": {
"get": [
{
"name": "username",
"required": false,
"title": "Custom username for webhook message",
"type": "string"
},
{
"name": "avatarURL",
"required": false,
"title": "Custom avatar picture for webhook message",
"type": "string"
},
{
"name": "content",
"required": true,
"title": "Message contents",
"type": "string"
}
],
"path": [
{
"name": "webhookID",
"required": true,
"title": "Webhook ID",
"type": "uint64"
},
{
"name": "webhookToken",
"required": true,
"title": "Authentication token",
"type": "string"
}
]
}
}
]
}

View File

@@ -57,14 +57,12 @@ function types {
./build/gen-type-set --types MessageFlag --output messaging/types/message_flag.gen.go
./build/gen-type-set --types Message --output messaging/types/message.gen.go
./build/gen-type-set --types Channel --output messaging/types/channel.gen.go
./build/gen-type-set --types Webhook --output messaging/types/webhook.gen.go
./build/gen-type-set-test --types MessageAttachment --output messaging/types/attachment.gen_test.go
./build/gen-type-set-test --types Mention --output messaging/types/mention.gen_test.go
./build/gen-type-set-test --types MessageFlag --output messaging/types/message_flag.gen_test.go
./build/gen-type-set-test --types Message --output messaging/types/message.gen_test.go
./build/gen-type-set-test --types Channel --output messaging/types/channel.gen_test.go
./build/gen-type-set-test --types Webhook --output messaging/types/webhook.gen_test.go
./build/gen-type-set --with-primary-key=false --types ChannelMember --output messaging/types/channel_member.gen.go
./build/gen-type-set --with-primary-key=false --types Command --output messaging/types/command.gen.go

View File

@@ -223,6 +223,7 @@ func (r PageCreate) Auditable() map[string]interface{} {
out["title"] = r.Title
out["handle"] = r.Handle
out["description"] = r.Description
out["weight"] = r.Weight
out["visible"] = r.Visible
out["blocks"] = r.Blocks
out["namespaceID"] = r.NamespaceID

View File

@@ -127,7 +127,9 @@
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/automation/` | HTTP/S | GET | |
| `/automation/` | HTTP/S | GET |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters
@@ -146,7 +148,9 @@
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/automation/{bundle}-{type}.{ext}` | HTTP/S | GET | |
| `/automation/{bundle}-{type}.{ext}` | HTTP/S | GET |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters
@@ -162,7 +166,9 @@
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/automation/trigger` | HTTP/S | POST | |
| `/automation/trigger` | HTTP/S | POST |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters
@@ -603,6 +609,7 @@ Compose pages
| title | string | POST | Title | N/A | YES |
| handle | string | POST | Handle | N/A | NO |
| description | string | POST | Description | N/A | NO |
| weight | int | POST | Page tree weight | N/A | NO |
| visible | bool | POST | Visible in navigation | N/A | NO |
| blocks | sqlxTypes.JSONText | POST | Blocks JSON | N/A | NO |
| namespaceID | uint64 | PATH | Namespace ID | N/A | YES |

View File

@@ -771,150 +771,4 @@ A channel is a representation of a sequence of messages. It has meta data like c
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
---
# Webhooks
| Method | Endpoint | Purpose |
| ------ | -------- | ------- |
| `GET` | `/webhooks/` | List created webhooks |
| `POST` | `/webhooks/` | Create webhook |
| `POST` | `/webhooks/{webhookID}` | Attach file to channel |
| `GET` | `/webhooks/{webhookID}` | Get webhook details |
| `DELETE` | `/webhooks/{webhookID}` | Delete webhook |
## List created webhooks
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/webhooks/` | HTTP/S | GET | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| channelID | uint64 | GET | Channel ID | N/A | NO |
| userID | uint64 | GET | Owner user ID | N/A | NO |
## Create webhook
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/webhooks/` | HTTP/S | POST | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| channelID | uint64 | POST | Channel ID | N/A | YES |
| kind | types.WebhookKind | POST | Kind (incoming, outgoing) | N/A | YES |
| userID | uint64 | POST | Bot User ID | N/A | YES |
| trigger | string | POST | Trigger word | N/A | NO |
| url | string | POST | POST URL | N/A | NO |
| username | string | POST | Default user name | N/A | NO |
| avatar | *multipart.FileHeader | POST | Default avatar | N/A | NO |
| avatarURL | string | POST | Default avatar (from URL) | N/A | NO |
## Attach file to channel
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/webhooks/{webhookID}` | HTTP/S | POST | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| webhookID | uint64 | PATH | Webhook ID | N/A | YES |
| channelID | uint64 | POST | Channel ID | N/A | YES |
| kind | types.WebhookKind | POST | Kind (incoming, outgoing) | N/A | YES |
| userID | uint64 | POST | Bot User ID | N/A | YES |
| trigger | string | POST | Trigger word | N/A | NO |
| url | string | POST | POST URL | N/A | NO |
| username | string | POST | Default user name | N/A | NO |
| avatar | *multipart.FileHeader | POST | Default avatar | N/A | NO |
| avatarURL | string | POST | Default avatar (from URL) | N/A | NO |
## Get webhook details
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/webhooks/{webhookID}` | HTTP/S | GET | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| webhookID | uint64 | PATH | Webhook ID | N/A | YES |
## Delete webhook
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/webhooks/{webhookID}` | HTTP/S | DELETE | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| webhookID | uint64 | PATH | Webhook ID | N/A | YES |
---
# Webhooks (Public)
| Method | Endpoint | Purpose |
| ------ | -------- | ------- |
| `DELETE` | `/webhooks/{webhookID}/{webhookToken}` | Delete webhook |
| `POST` | `/webhooks/{webhookID}/{webhookToken}` | Create a message from a webhook payload |
## Delete webhook
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/webhooks/{webhookID}/{webhookToken}` | HTTP/S | DELETE | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| webhookID | uint64 | PATH | Webhook ID | N/A | YES |
| webhookToken | string | PATH | Authentication token | N/A | YES |
## Create a message from a webhook payload
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/webhooks/{webhookID}/{webhookToken}` | HTTP/S | POST | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
| username | string | GET | Custom username for webhook message | N/A | NO |
| avatarURL | string | GET | Custom avatar picture for webhook message | N/A | NO |
| content | string | GET | Message contents | N/A | YES |
| webhookID | uint64 | PATH | Webhook ID | N/A | YES |
| webhookToken | string | PATH | Authentication token | N/A | YES |
---

View File

@@ -451,7 +451,9 @@ Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.cru
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/automation/` | HTTP/S | GET | |
| `/automation/` | HTTP/S | GET |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters
@@ -470,7 +472,9 @@ Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.cru
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/automation/{bundle}-{type}.{ext}` | HTTP/S | GET | |
| `/automation/{bundle}-{type}.{ext}` | HTTP/S | GET |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters
@@ -486,7 +490,9 @@ Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.cru
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/automation/trigger` | HTTP/S | POST | |
| `/automation/trigger` | HTTP/S | POST |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters
@@ -1183,7 +1189,9 @@ An organisation may have many roles. Roles may have many channels available. Acc
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/subscription/` | HTTP/S | GET | |
| `/subscription/` | HTTP/S | GET |
Warning: implode(): Invalid arguments passed in /private/tmp/Users/darh/Work.crust/corteza-server/codegen/templates/README.tpl on line 32
|
#### Request parameters

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
DROP TABLE `messaging_webhook`;

View File

@@ -1,125 +0,0 @@
package repository
import (
"context"
"time"
"github.com/pkg/errors"
"github.com/titpetric/factory"
"github.com/cortezaproject/corteza-server/messaging/types"
"github.com/cortezaproject/corteza-server/pkg/rh"
)
type (
WebhookRepository interface {
With(ctx context.Context, db *factory.DB) WebhookRepository
Create(*types.Webhook) (*types.Webhook, error)
Update(*types.Webhook) (*types.Webhook, error)
Get(webhookID uint64) (*types.Webhook, error)
GetByToken(webhookID uint64, webhookToken string) (*types.Webhook, error)
Find(filter *types.WebhookFilter) (types.WebhookSet, error)
Delete(webhookID uint64) error
DeleteByToken(webhookID uint64, webhookToken string) error
}
webhook struct {
webhook string
*repository
}
)
func Webhook(ctx context.Context, db *factory.DB) WebhookRepository {
return (&webhook{}).With(ctx, db)
}
func (r *webhook) With(ctx context.Context, db *factory.DB) WebhookRepository {
return &webhook{
webhook: "messaging_webhook",
repository: r.repository.With(ctx, db),
}
}
func (r *webhook) Create(webhook *types.Webhook) (*types.Webhook, error) {
webhook.ID = factory.Sonyflake.NextID()
webhook.CreatedAt = time.Now()
return webhook, errors.WithStack(r.db().Insert(r.webhook, webhook))
}
func (r *webhook) Update(webhook *types.Webhook) (*types.Webhook, error) {
rh.SetCurrentTimeRounded(&webhook.UpdatedAt)
return webhook, errors.WithStack(r.db().Replace(r.webhook, webhook))
}
func (r *webhook) Get(webhookID uint64) (*types.Webhook, error) {
hook := &types.Webhook{}
if err := r.db().Get(hook, "select * from "+r.webhook+" where id=?", webhookID); err != nil {
return nil, errors.WithStack(err)
}
return hook, nil
}
func (r *webhook) GetByToken(webhookID uint64, webhookToken string) (*types.Webhook, error) {
webhook, err := r.Get(webhookID)
switch {
case err != nil:
return nil, errors.WithStack(err)
case webhook.AuthToken == webhookToken:
return webhook, nil
default:
return nil, errors.New("Invalid Webhook Token")
}
}
// Find webhooks based on filter
//
// If ChannelID > 0 it returns webhooks created on a specific channel
// If OwnerUserID > 0 it returns webhooks owned by a specific user
func (r *webhook) Find(filter *types.WebhookFilter) (types.WebhookSet, error) {
params := make([]interface{}, 0)
vv := types.WebhookSet{}
sql := "select * from messaging_webhook where 1=1"
if filter != nil {
if filter.OwnerUserID > 0 {
// scope: only channel we have access to
sql += " AND rel_owner=?"
params = append(params, filter.OwnerUserID)
}
if filter.OutgoingTrigger != "" {
// scope: only channel we have access to
sql += " AND outgoing_trigger=?"
params = append(params, filter.OutgoingTrigger)
}
if filter.ChannelID > 0 {
// scope: only channel we have access to
sql += " AND rel_channel=?"
params = append(params, filter.ChannelID)
}
}
return vv, errors.WithStack(r.db().Select(&vv, sql, params...))
}
func (r *webhook) Delete(webhookID uint64) error {
if _, err := r.Get(webhookID); err != nil {
return err
}
_, err := r.db().Exec("delete from "+r.webhook+" where id=?", webhookID)
return errors.WithStack(err)
}
func (r *webhook) DeleteByToken(webhookID uint64, webhookToken string) error {
if _, err := r.GetByToken(webhookID, webhookToken); err != nil {
return err
}
_, err := r.db().Exec("delete from "+r.webhook+" where id=?", webhookID)
return errors.WithStack(err)
}

View File

@@ -1,162 +0,0 @@
package handlers
/*
Hello! This file is auto-generated from `docs/src/spec.json`.
For development:
In order to update the generated files, edit this file under the location,
add your struct fields, imports, API definitions and whatever you want, and:
1. run [spec](https://github.com/titpetric/spec) in the same folder,
2. run `./_gen.php` in this folder.
You may edit `webhooks.go`, `webhooks.util.go` or `webhooks_test.go` to
implement your API calls, helper functions and tests. The file `webhooks.go`
is only generated the first time, and will not be overwritten if it exists.
*/
import (
"context"
"net/http"
"github.com/go-chi/chi"
"github.com/titpetric/factory/resputil"
"github.com/cortezaproject/corteza-server/messaging/rest/request"
"github.com/cortezaproject/corteza-server/pkg/logger"
)
// Internal API interface
type WebhooksAPI interface {
List(context.Context, *request.WebhooksList) (interface{}, error)
Create(context.Context, *request.WebhooksCreate) (interface{}, error)
Update(context.Context, *request.WebhooksUpdate) (interface{}, error)
Get(context.Context, *request.WebhooksGet) (interface{}, error)
Delete(context.Context, *request.WebhooksDelete) (interface{}, error)
}
// HTTP API interface
type Webhooks struct {
List func(http.ResponseWriter, *http.Request)
Create func(http.ResponseWriter, *http.Request)
Update func(http.ResponseWriter, *http.Request)
Get func(http.ResponseWriter, *http.Request)
Delete func(http.ResponseWriter, *http.Request)
}
func NewWebhooks(h WebhooksAPI) *Webhooks {
return &Webhooks{
List: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewWebhooksList()
if err := params.Fill(r); err != nil {
logger.LogParamError("Webhooks.List", r, err)
resputil.JSON(w, err)
return
}
value, err := h.List(r.Context(), params)
if err != nil {
logger.LogControllerError("Webhooks.List", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("Webhooks.List", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
Create: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewWebhooksCreate()
if err := params.Fill(r); err != nil {
logger.LogParamError("Webhooks.Create", r, err)
resputil.JSON(w, err)
return
}
value, err := h.Create(r.Context(), params)
if err != nil {
logger.LogControllerError("Webhooks.Create", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("Webhooks.Create", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
Update: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewWebhooksUpdate()
if err := params.Fill(r); err != nil {
logger.LogParamError("Webhooks.Update", r, err)
resputil.JSON(w, err)
return
}
value, err := h.Update(r.Context(), params)
if err != nil {
logger.LogControllerError("Webhooks.Update", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("Webhooks.Update", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
Get: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewWebhooksGet()
if err := params.Fill(r); err != nil {
logger.LogParamError("Webhooks.Get", r, err)
resputil.JSON(w, err)
return
}
value, err := h.Get(r.Context(), params)
if err != nil {
logger.LogControllerError("Webhooks.Get", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("Webhooks.Get", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
Delete: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewWebhooksDelete()
if err := params.Fill(r); err != nil {
logger.LogParamError("Webhooks.Delete", r, err)
resputil.JSON(w, err)
return
}
value, err := h.Delete(r.Context(), params)
if err != nil {
logger.LogControllerError("Webhooks.Delete", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("Webhooks.Delete", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
}
}
func (h Webhooks) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
r.Group(func(r chi.Router) {
r.Use(middlewares...)
r.Get("/webhooks/", h.List)
r.Post("/webhooks/", h.Create)
r.Post("/webhooks/{webhookID}", h.Update)
r.Get("/webhooks/{webhookID}", h.Get)
r.Delete("/webhooks/{webhookID}", h.Delete)
})
}

View File

@@ -1,93 +0,0 @@
package handlers
/*
Hello! This file is auto-generated from `docs/src/spec.json`.
For development:
In order to update the generated files, edit this file under the location,
add your struct fields, imports, API definitions and whatever you want, and:
1. run [spec](https://github.com/titpetric/spec) in the same folder,
2. run `./_gen.php` in this folder.
You may edit `webhooks_public.go`, `webhooks_public.util.go` or `webhooks_public_test.go` to
implement your API calls, helper functions and tests. The file `webhooks_public.go`
is only generated the first time, and will not be overwritten if it exists.
*/
import (
"context"
"net/http"
"github.com/go-chi/chi"
"github.com/titpetric/factory/resputil"
"github.com/cortezaproject/corteza-server/messaging/rest/request"
"github.com/cortezaproject/corteza-server/pkg/logger"
)
// Internal API interface
type WebhooksPublicAPI interface {
Delete(context.Context, *request.WebhooksPublicDelete) (interface{}, error)
Create(context.Context, *request.WebhooksPublicCreate) (interface{}, error)
}
// HTTP API interface
type WebhooksPublic struct {
Delete func(http.ResponseWriter, *http.Request)
Create func(http.ResponseWriter, *http.Request)
}
func NewWebhooksPublic(h WebhooksPublicAPI) *WebhooksPublic {
return &WebhooksPublic{
Delete: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewWebhooksPublicDelete()
if err := params.Fill(r); err != nil {
logger.LogParamError("WebhooksPublic.Delete", r, err)
resputil.JSON(w, err)
return
}
value, err := h.Delete(r.Context(), params)
if err != nil {
logger.LogControllerError("WebhooksPublic.Delete", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("WebhooksPublic.Delete", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
Create: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewWebhooksPublicCreate()
if err := params.Fill(r); err != nil {
logger.LogParamError("WebhooksPublic.Create", r, err)
resputil.JSON(w, err)
return
}
value, err := h.Create(r.Context(), params)
if err != nil {
logger.LogControllerError("WebhooksPublic.Create", r, err, params.Auditable())
resputil.JSON(w, err)
return
}
logger.LogControllerCall("WebhooksPublic.Create", r, params.Auditable())
if !serveHTTP(value, w, r) {
resputil.JSON(w, value)
}
},
}
}
func (h WebhooksPublic) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
r.Group(func(r chi.Router) {
r.Use(middlewares...)
r.Delete("/webhooks/{webhookID}/{webhookToken}", h.Delete)
r.Post("/webhooks/{webhookID}/{webhookToken}", h.Create)
})
}

View File

@@ -1,804 +0,0 @@
package request
/*
Hello! This file is auto-generated from `docs/src/spec.json`.
For development:
In order to update the generated files, edit this file under the location,
add your struct fields, imports, API definitions and whatever you want, and:
1. run [spec](https://github.com/titpetric/spec) in the same folder,
2. run `./_gen.php` in this folder.
You may edit `webhooks.go`, `webhooks.util.go` or `webhooks_test.go` to
implement your API calls, helper functions and tests. The file `webhooks.go`
is only generated the first time, and will not be overwritten if it exists.
*/
import (
"io"
"strings"
"encoding/json"
"mime/multipart"
"net/http"
"github.com/go-chi/chi"
"github.com/pkg/errors"
"github.com/cortezaproject/corteza-server/messaging/types"
)
var _ = chi.URLParam
var _ = multipart.FileHeader{}
// WebhooksList request parameters
type WebhooksList struct {
hasChannelID bool
rawChannelID string
ChannelID uint64 `json:",string"`
hasUserID bool
rawUserID string
UserID uint64 `json:",string"`
}
// NewWebhooksList request
func NewWebhooksList() *WebhooksList {
return &WebhooksList{}
}
// Auditable returns all auditable/loggable parameters
func (r WebhooksList) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["channelID"] = r.ChannelID
out["userID"] = r.UserID
return out
}
// Fill processes request and fills internal variables
func (r *WebhooksList) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseForm(); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
if val, ok := get["channelID"]; ok {
r.hasChannelID = true
r.rawChannelID = val
r.ChannelID = parseUInt64(val)
}
if val, ok := get["userID"]; ok {
r.hasUserID = true
r.rawUserID = val
r.UserID = parseUInt64(val)
}
return err
}
var _ RequestFiller = NewWebhooksList()
// WebhooksCreate request parameters
type WebhooksCreate struct {
hasChannelID bool
rawChannelID string
ChannelID uint64 `json:",string"`
hasKind bool
rawKind string
Kind types.WebhookKind
hasUserID bool
rawUserID string
UserID uint64 `json:",string"`
hasTrigger bool
rawTrigger string
Trigger string
hasUrl bool
rawUrl string
Url string
hasUsername bool
rawUsername string
Username string
hasAvatar bool
rawAvatar string
Avatar *multipart.FileHeader
hasAvatarURL bool
rawAvatarURL string
AvatarURL string
}
// NewWebhooksCreate request
func NewWebhooksCreate() *WebhooksCreate {
return &WebhooksCreate{}
}
// Auditable returns all auditable/loggable parameters
func (r WebhooksCreate) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["channelID"] = r.ChannelID
out["kind"] = r.Kind
out["userID"] = r.UserID
out["trigger"] = r.Trigger
out["url"] = r.Url
out["username"] = r.Username
out["avatar.size"] = r.Avatar.Size
out["avatar.filename"] = r.Avatar.Filename
out["avatarURL"] = r.AvatarURL
return out
}
// Fill processes request and fills internal variables
func (r *WebhooksCreate) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseMultipartForm(32 << 20); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
if val, ok := post["channelID"]; ok {
r.hasChannelID = true
r.rawChannelID = val
r.ChannelID = parseUInt64(val)
}
if val, ok := post["kind"]; ok {
r.hasKind = true
r.rawKind = val
r.Kind = types.WebhookKind(val)
}
if val, ok := post["userID"]; ok {
r.hasUserID = true
r.rawUserID = val
r.UserID = parseUInt64(val)
}
if val, ok := post["trigger"]; ok {
r.hasTrigger = true
r.rawTrigger = val
r.Trigger = val
}
if val, ok := post["url"]; ok {
r.hasUrl = true
r.rawUrl = val
r.Url = val
}
if val, ok := post["username"]; ok {
r.hasUsername = true
r.rawUsername = val
r.Username = val
}
if _, r.Avatar, err = req.FormFile("avatar"); err != nil {
return errors.Wrap(err, "error processing uploaded file")
}
if val, ok := post["avatarURL"]; ok {
r.hasAvatarURL = true
r.rawAvatarURL = val
r.AvatarURL = val
}
return err
}
var _ RequestFiller = NewWebhooksCreate()
// WebhooksUpdate request parameters
type WebhooksUpdate struct {
hasWebhookID bool
rawWebhookID string
WebhookID uint64 `json:",string"`
hasChannelID bool
rawChannelID string
ChannelID uint64 `json:",string"`
hasKind bool
rawKind string
Kind types.WebhookKind
hasUserID bool
rawUserID string
UserID uint64 `json:",string"`
hasTrigger bool
rawTrigger string
Trigger string
hasUrl bool
rawUrl string
Url string
hasUsername bool
rawUsername string
Username string
hasAvatar bool
rawAvatar string
Avatar *multipart.FileHeader
hasAvatarURL bool
rawAvatarURL string
AvatarURL string
}
// NewWebhooksUpdate request
func NewWebhooksUpdate() *WebhooksUpdate {
return &WebhooksUpdate{}
}
// Auditable returns all auditable/loggable parameters
func (r WebhooksUpdate) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["webhookID"] = r.WebhookID
out["channelID"] = r.ChannelID
out["kind"] = r.Kind
out["userID"] = r.UserID
out["trigger"] = r.Trigger
out["url"] = r.Url
out["username"] = r.Username
out["avatar.size"] = r.Avatar.Size
out["avatar.filename"] = r.Avatar.Filename
out["avatarURL"] = r.AvatarURL
return out
}
// Fill processes request and fills internal variables
func (r *WebhooksUpdate) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseMultipartForm(32 << 20); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
r.hasWebhookID = true
r.rawWebhookID = chi.URLParam(req, "webhookID")
r.WebhookID = parseUInt64(chi.URLParam(req, "webhookID"))
if val, ok := post["channelID"]; ok {
r.hasChannelID = true
r.rawChannelID = val
r.ChannelID = parseUInt64(val)
}
if val, ok := post["kind"]; ok {
r.hasKind = true
r.rawKind = val
r.Kind = types.WebhookKind(val)
}
if val, ok := post["userID"]; ok {
r.hasUserID = true
r.rawUserID = val
r.UserID = parseUInt64(val)
}
if val, ok := post["trigger"]; ok {
r.hasTrigger = true
r.rawTrigger = val
r.Trigger = val
}
if val, ok := post["url"]; ok {
r.hasUrl = true
r.rawUrl = val
r.Url = val
}
if val, ok := post["username"]; ok {
r.hasUsername = true
r.rawUsername = val
r.Username = val
}
if _, r.Avatar, err = req.FormFile("avatar"); err != nil {
return errors.Wrap(err, "error processing uploaded file")
}
if val, ok := post["avatarURL"]; ok {
r.hasAvatarURL = true
r.rawAvatarURL = val
r.AvatarURL = val
}
return err
}
var _ RequestFiller = NewWebhooksUpdate()
// WebhooksGet request parameters
type WebhooksGet struct {
hasWebhookID bool
rawWebhookID string
WebhookID uint64 `json:",string"`
}
// NewWebhooksGet request
func NewWebhooksGet() *WebhooksGet {
return &WebhooksGet{}
}
// Auditable returns all auditable/loggable parameters
func (r WebhooksGet) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["webhookID"] = r.WebhookID
return out
}
// Fill processes request and fills internal variables
func (r *WebhooksGet) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseForm(); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
r.hasWebhookID = true
r.rawWebhookID = chi.URLParam(req, "webhookID")
r.WebhookID = parseUInt64(chi.URLParam(req, "webhookID"))
return err
}
var _ RequestFiller = NewWebhooksGet()
// WebhooksDelete request parameters
type WebhooksDelete struct {
hasWebhookID bool
rawWebhookID string
WebhookID uint64 `json:",string"`
}
// NewWebhooksDelete request
func NewWebhooksDelete() *WebhooksDelete {
return &WebhooksDelete{}
}
// Auditable returns all auditable/loggable parameters
func (r WebhooksDelete) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["webhookID"] = r.WebhookID
return out
}
// Fill processes request and fills internal variables
func (r *WebhooksDelete) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseForm(); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
r.hasWebhookID = true
r.rawWebhookID = chi.URLParam(req, "webhookID")
r.WebhookID = parseUInt64(chi.URLParam(req, "webhookID"))
return err
}
var _ RequestFiller = NewWebhooksDelete()
// HasChannelID returns true if channelID was set
func (r *WebhooksList) HasChannelID() bool {
return r.hasChannelID
}
// RawChannelID returns raw value of channelID parameter
func (r *WebhooksList) RawChannelID() string {
return r.rawChannelID
}
// GetChannelID returns casted value of channelID parameter
func (r *WebhooksList) GetChannelID() uint64 {
return r.ChannelID
}
// HasUserID returns true if userID was set
func (r *WebhooksList) HasUserID() bool {
return r.hasUserID
}
// RawUserID returns raw value of userID parameter
func (r *WebhooksList) RawUserID() string {
return r.rawUserID
}
// GetUserID returns casted value of userID parameter
func (r *WebhooksList) GetUserID() uint64 {
return r.UserID
}
// HasChannelID returns true if channelID was set
func (r *WebhooksCreate) HasChannelID() bool {
return r.hasChannelID
}
// RawChannelID returns raw value of channelID parameter
func (r *WebhooksCreate) RawChannelID() string {
return r.rawChannelID
}
// GetChannelID returns casted value of channelID parameter
func (r *WebhooksCreate) GetChannelID() uint64 {
return r.ChannelID
}
// HasKind returns true if kind was set
func (r *WebhooksCreate) HasKind() bool {
return r.hasKind
}
// RawKind returns raw value of kind parameter
func (r *WebhooksCreate) RawKind() string {
return r.rawKind
}
// GetKind returns casted value of kind parameter
func (r *WebhooksCreate) GetKind() types.WebhookKind {
return r.Kind
}
// HasUserID returns true if userID was set
func (r *WebhooksCreate) HasUserID() bool {
return r.hasUserID
}
// RawUserID returns raw value of userID parameter
func (r *WebhooksCreate) RawUserID() string {
return r.rawUserID
}
// GetUserID returns casted value of userID parameter
func (r *WebhooksCreate) GetUserID() uint64 {
return r.UserID
}
// HasTrigger returns true if trigger was set
func (r *WebhooksCreate) HasTrigger() bool {
return r.hasTrigger
}
// RawTrigger returns raw value of trigger parameter
func (r *WebhooksCreate) RawTrigger() string {
return r.rawTrigger
}
// GetTrigger returns casted value of trigger parameter
func (r *WebhooksCreate) GetTrigger() string {
return r.Trigger
}
// HasUrl returns true if url was set
func (r *WebhooksCreate) HasUrl() bool {
return r.hasUrl
}
// RawUrl returns raw value of url parameter
func (r *WebhooksCreate) RawUrl() string {
return r.rawUrl
}
// GetUrl returns casted value of url parameter
func (r *WebhooksCreate) GetUrl() string {
return r.Url
}
// HasUsername returns true if username was set
func (r *WebhooksCreate) HasUsername() bool {
return r.hasUsername
}
// RawUsername returns raw value of username parameter
func (r *WebhooksCreate) RawUsername() string {
return r.rawUsername
}
// GetUsername returns casted value of username parameter
func (r *WebhooksCreate) GetUsername() string {
return r.Username
}
// HasAvatar returns true if avatar was set
func (r *WebhooksCreate) HasAvatar() bool {
return r.hasAvatar
}
// RawAvatar returns raw value of avatar parameter
func (r *WebhooksCreate) RawAvatar() string {
return r.rawAvatar
}
// GetAvatar returns casted value of avatar parameter
func (r *WebhooksCreate) GetAvatar() *multipart.FileHeader {
return r.Avatar
}
// HasAvatarURL returns true if avatarURL was set
func (r *WebhooksCreate) HasAvatarURL() bool {
return r.hasAvatarURL
}
// RawAvatarURL returns raw value of avatarURL parameter
func (r *WebhooksCreate) RawAvatarURL() string {
return r.rawAvatarURL
}
// GetAvatarURL returns casted value of avatarURL parameter
func (r *WebhooksCreate) GetAvatarURL() string {
return r.AvatarURL
}
// HasWebhookID returns true if webhookID was set
func (r *WebhooksUpdate) HasWebhookID() bool {
return r.hasWebhookID
}
// RawWebhookID returns raw value of webhookID parameter
func (r *WebhooksUpdate) RawWebhookID() string {
return r.rawWebhookID
}
// GetWebhookID returns casted value of webhookID parameter
func (r *WebhooksUpdate) GetWebhookID() uint64 {
return r.WebhookID
}
// HasChannelID returns true if channelID was set
func (r *WebhooksUpdate) HasChannelID() bool {
return r.hasChannelID
}
// RawChannelID returns raw value of channelID parameter
func (r *WebhooksUpdate) RawChannelID() string {
return r.rawChannelID
}
// GetChannelID returns casted value of channelID parameter
func (r *WebhooksUpdate) GetChannelID() uint64 {
return r.ChannelID
}
// HasKind returns true if kind was set
func (r *WebhooksUpdate) HasKind() bool {
return r.hasKind
}
// RawKind returns raw value of kind parameter
func (r *WebhooksUpdate) RawKind() string {
return r.rawKind
}
// GetKind returns casted value of kind parameter
func (r *WebhooksUpdate) GetKind() types.WebhookKind {
return r.Kind
}
// HasUserID returns true if userID was set
func (r *WebhooksUpdate) HasUserID() bool {
return r.hasUserID
}
// RawUserID returns raw value of userID parameter
func (r *WebhooksUpdate) RawUserID() string {
return r.rawUserID
}
// GetUserID returns casted value of userID parameter
func (r *WebhooksUpdate) GetUserID() uint64 {
return r.UserID
}
// HasTrigger returns true if trigger was set
func (r *WebhooksUpdate) HasTrigger() bool {
return r.hasTrigger
}
// RawTrigger returns raw value of trigger parameter
func (r *WebhooksUpdate) RawTrigger() string {
return r.rawTrigger
}
// GetTrigger returns casted value of trigger parameter
func (r *WebhooksUpdate) GetTrigger() string {
return r.Trigger
}
// HasUrl returns true if url was set
func (r *WebhooksUpdate) HasUrl() bool {
return r.hasUrl
}
// RawUrl returns raw value of url parameter
func (r *WebhooksUpdate) RawUrl() string {
return r.rawUrl
}
// GetUrl returns casted value of url parameter
func (r *WebhooksUpdate) GetUrl() string {
return r.Url
}
// HasUsername returns true if username was set
func (r *WebhooksUpdate) HasUsername() bool {
return r.hasUsername
}
// RawUsername returns raw value of username parameter
func (r *WebhooksUpdate) RawUsername() string {
return r.rawUsername
}
// GetUsername returns casted value of username parameter
func (r *WebhooksUpdate) GetUsername() string {
return r.Username
}
// HasAvatar returns true if avatar was set
func (r *WebhooksUpdate) HasAvatar() bool {
return r.hasAvatar
}
// RawAvatar returns raw value of avatar parameter
func (r *WebhooksUpdate) RawAvatar() string {
return r.rawAvatar
}
// GetAvatar returns casted value of avatar parameter
func (r *WebhooksUpdate) GetAvatar() *multipart.FileHeader {
return r.Avatar
}
// HasAvatarURL returns true if avatarURL was set
func (r *WebhooksUpdate) HasAvatarURL() bool {
return r.hasAvatarURL
}
// RawAvatarURL returns raw value of avatarURL parameter
func (r *WebhooksUpdate) RawAvatarURL() string {
return r.rawAvatarURL
}
// GetAvatarURL returns casted value of avatarURL parameter
func (r *WebhooksUpdate) GetAvatarURL() string {
return r.AvatarURL
}
// HasWebhookID returns true if webhookID was set
func (r *WebhooksGet) HasWebhookID() bool {
return r.hasWebhookID
}
// RawWebhookID returns raw value of webhookID parameter
func (r *WebhooksGet) RawWebhookID() string {
return r.rawWebhookID
}
// GetWebhookID returns casted value of webhookID parameter
func (r *WebhooksGet) GetWebhookID() uint64 {
return r.WebhookID
}
// HasWebhookID returns true if webhookID was set
func (r *WebhooksDelete) HasWebhookID() bool {
return r.hasWebhookID
}
// RawWebhookID returns raw value of webhookID parameter
func (r *WebhooksDelete) RawWebhookID() string {
return r.rawWebhookID
}
// GetWebhookID returns casted value of webhookID parameter
func (r *WebhooksDelete) GetWebhookID() uint64 {
return r.WebhookID
}

View File

@@ -1,298 +0,0 @@
package request
/*
Hello! This file is auto-generated from `docs/src/spec.json`.
For development:
In order to update the generated files, edit this file under the location,
add your struct fields, imports, API definitions and whatever you want, and:
1. run [spec](https://github.com/titpetric/spec) in the same folder,
2. run `./_gen.php` in this folder.
You may edit `webhooks_public.go`, `webhooks_public.util.go` or `webhooks_public_test.go` to
implement your API calls, helper functions and tests. The file `webhooks_public.go`
is only generated the first time, and will not be overwritten if it exists.
*/
import (
"io"
"strings"
"encoding/json"
"mime/multipart"
"net/http"
"github.com/go-chi/chi"
"github.com/pkg/errors"
)
var _ = chi.URLParam
var _ = multipart.FileHeader{}
// WebhooksPublicDelete request parameters
type WebhooksPublicDelete struct {
hasWebhookID bool
rawWebhookID string
WebhookID uint64 `json:",string"`
hasWebhookToken bool
rawWebhookToken string
WebhookToken string
}
// NewWebhooksPublicDelete request
func NewWebhooksPublicDelete() *WebhooksPublicDelete {
return &WebhooksPublicDelete{}
}
// Auditable returns all auditable/loggable parameters
func (r WebhooksPublicDelete) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["webhookID"] = r.WebhookID
out["webhookToken"] = r.WebhookToken
return out
}
// Fill processes request and fills internal variables
func (r *WebhooksPublicDelete) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseForm(); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
r.hasWebhookID = true
r.rawWebhookID = chi.URLParam(req, "webhookID")
r.WebhookID = parseUInt64(chi.URLParam(req, "webhookID"))
r.hasWebhookToken = true
r.rawWebhookToken = chi.URLParam(req, "webhookToken")
r.WebhookToken = chi.URLParam(req, "webhookToken")
return err
}
var _ RequestFiller = NewWebhooksPublicDelete()
// WebhooksPublicCreate request parameters
type WebhooksPublicCreate struct {
hasUsername bool
rawUsername string
Username string
hasAvatarURL bool
rawAvatarURL string
AvatarURL string
hasContent bool
rawContent string
Content string
hasWebhookID bool
rawWebhookID string
WebhookID uint64 `json:",string"`
hasWebhookToken bool
rawWebhookToken string
WebhookToken string
}
// NewWebhooksPublicCreate request
func NewWebhooksPublicCreate() *WebhooksPublicCreate {
return &WebhooksPublicCreate{}
}
// Auditable returns all auditable/loggable parameters
func (r WebhooksPublicCreate) Auditable() map[string]interface{} {
var out = map[string]interface{}{}
out["username"] = r.Username
out["avatarURL"] = r.AvatarURL
out["content"] = r.Content
out["webhookID"] = r.WebhookID
out["webhookToken"] = r.WebhookToken
return out
}
// Fill processes request and fills internal variables
func (r *WebhooksPublicCreate) Fill(req *http.Request) (err error) {
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = req.ParseForm(); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := req.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := req.Form
for name, param := range postVars {
post[name] = string(param[0])
}
if val, ok := get["username"]; ok {
r.hasUsername = true
r.rawUsername = val
r.Username = val
}
if val, ok := get["avatarURL"]; ok {
r.hasAvatarURL = true
r.rawAvatarURL = val
r.AvatarURL = val
}
if val, ok := get["content"]; ok {
r.hasContent = true
r.rawContent = val
r.Content = val
}
r.hasWebhookID = true
r.rawWebhookID = chi.URLParam(req, "webhookID")
r.WebhookID = parseUInt64(chi.URLParam(req, "webhookID"))
r.hasWebhookToken = true
r.rawWebhookToken = chi.URLParam(req, "webhookToken")
r.WebhookToken = chi.URLParam(req, "webhookToken")
return err
}
var _ RequestFiller = NewWebhooksPublicCreate()
// HasWebhookID returns true if webhookID was set
func (r *WebhooksPublicDelete) HasWebhookID() bool {
return r.hasWebhookID
}
// RawWebhookID returns raw value of webhookID parameter
func (r *WebhooksPublicDelete) RawWebhookID() string {
return r.rawWebhookID
}
// GetWebhookID returns casted value of webhookID parameter
func (r *WebhooksPublicDelete) GetWebhookID() uint64 {
return r.WebhookID
}
// HasWebhookToken returns true if webhookToken was set
func (r *WebhooksPublicDelete) HasWebhookToken() bool {
return r.hasWebhookToken
}
// RawWebhookToken returns raw value of webhookToken parameter
func (r *WebhooksPublicDelete) RawWebhookToken() string {
return r.rawWebhookToken
}
// GetWebhookToken returns casted value of webhookToken parameter
func (r *WebhooksPublicDelete) GetWebhookToken() string {
return r.WebhookToken
}
// HasUsername returns true if username was set
func (r *WebhooksPublicCreate) HasUsername() bool {
return r.hasUsername
}
// RawUsername returns raw value of username parameter
func (r *WebhooksPublicCreate) RawUsername() string {
return r.rawUsername
}
// GetUsername returns casted value of username parameter
func (r *WebhooksPublicCreate) GetUsername() string {
return r.Username
}
// HasAvatarURL returns true if avatarURL was set
func (r *WebhooksPublicCreate) HasAvatarURL() bool {
return r.hasAvatarURL
}
// RawAvatarURL returns raw value of avatarURL parameter
func (r *WebhooksPublicCreate) RawAvatarURL() string {
return r.rawAvatarURL
}
// GetAvatarURL returns casted value of avatarURL parameter
func (r *WebhooksPublicCreate) GetAvatarURL() string {
return r.AvatarURL
}
// HasContent returns true if content was set
func (r *WebhooksPublicCreate) HasContent() bool {
return r.hasContent
}
// RawContent returns raw value of content parameter
func (r *WebhooksPublicCreate) RawContent() string {
return r.rawContent
}
// GetContent returns casted value of content parameter
func (r *WebhooksPublicCreate) GetContent() string {
return r.Content
}
// HasWebhookID returns true if webhookID was set
func (r *WebhooksPublicCreate) HasWebhookID() bool {
return r.hasWebhookID
}
// RawWebhookID returns raw value of webhookID parameter
func (r *WebhooksPublicCreate) RawWebhookID() string {
return r.rawWebhookID
}
// GetWebhookID returns casted value of webhookID parameter
func (r *WebhooksPublicCreate) GetWebhookID() uint64 {
return r.WebhookID
}
// HasWebhookToken returns true if webhookToken was set
func (r *WebhooksPublicCreate) HasWebhookToken() bool {
return r.hasWebhookToken
}
// RawWebhookToken returns raw value of webhookToken parameter
func (r *WebhooksPublicCreate) RawWebhookToken() string {
return r.rawWebhookToken
}
// GetWebhookToken returns casted value of webhookToken parameter
func (r *WebhooksPublicCreate) GetWebhookToken() string {
return r.WebhookToken
}

View File

@@ -11,7 +11,6 @@ func MountRoutes(r chi.Router) {
// Initialize handlers & controllers.
r.Group(func(r chi.Router) {
handlers.NewAttachment(Attachment{}.New()).MountRoutes(r)
handlers.NewWebhooksPublic(WebhooksPublic{}.New()).MountRoutes(r)
})
// Protect all _private_ routes
@@ -25,7 +24,6 @@ func MountRoutes(r chi.Router) {
handlers.NewSearch(Search{}.New()).MountRoutes(r)
handlers.NewStatus(Status{}.New()).MountRoutes(r)
handlers.NewCommands(Commands{}.New()).MountRoutes(r)
handlers.NewWebhooks(Webhooks{}.New()).MountRoutes(r)
handlers.NewPermissions(Permissions{}.New()).MountRoutes(r)
handlers.NewSettings(Settings{}.New()).MountRoutes(r)
})

View File

@@ -1,71 +0,0 @@
package rest
import (
"context"
"github.com/pkg/errors"
"github.com/cortezaproject/corteza-server/messaging/rest/request"
"github.com/cortezaproject/corteza-server/messaging/service"
"github.com/cortezaproject/corteza-server/messaging/types"
"github.com/cortezaproject/corteza-server/pkg/store"
)
var _ = errors.Wrap
type Webhooks struct {
webhook service.WebhookService
}
func (Webhooks) New() *Webhooks {
return &Webhooks{}
}
func (ctrl *Webhooks) Get(ctx context.Context, r *request.WebhooksGet) (interface{}, error) {
return ctrl.webhook.With(ctx).Get(r.WebhookID)
}
func (ctrl *Webhooks) Delete(ctx context.Context, r *request.WebhooksDelete) (interface{}, error) {
return nil, ctrl.webhook.With(ctx).Delete(r.WebhookID)
}
func (ctrl *Webhooks) List(ctx context.Context, r *request.WebhooksList) (interface{}, error) {
return ctrl.webhook.With(ctx).Find(&types.WebhookFilter{
ChannelID: r.ChannelID,
OwnerUserID: r.UserID,
})
}
func (ctrl *Webhooks) Create(ctx context.Context, r *request.WebhooksCreate) (interface{}, error) {
avatar, err := store.FromAny(r.Avatar, r.AvatarURL)
if err != nil {
return nil, err
}
defer avatar.Close()
// Webhook request parameters
parameters := types.WebhookRequest{
r.Username,
r.UserID,
avatar,
r.Trigger,
r.Url,
}
return ctrl.webhook.With(ctx).Create(r.Kind, r.ChannelID, parameters)
}
func (ctrl *Webhooks) Update(ctx context.Context, r *request.WebhooksUpdate) (interface{}, error) {
avatar, err := store.FromAny(r.Avatar, r.AvatarURL)
if err != nil {
return nil, err
}
defer avatar.Close()
// Webhook request parameters
parameters := types.WebhookRequest{
r.Username,
r.UserID,
avatar,
r.Trigger,
r.Url,
}
return ctrl.webhook.With(ctx).Update(r.WebhookID, r.Kind, r.ChannelID, parameters)
}

View File

@@ -1,34 +0,0 @@
package rest
import (
"context"
"github.com/pkg/errors"
"github.com/cortezaproject/corteza-server/messaging/rest/request"
"github.com/cortezaproject/corteza-server/messaging/service"
"github.com/cortezaproject/corteza-server/pkg/store"
)
var _ = errors.Wrap
type WebhooksPublic struct {
webhook service.WebhookService
}
func (WebhooksPublic) New() *WebhooksPublic {
return &WebhooksPublic{}
}
func (ctrl *WebhooksPublic) Delete(ctx context.Context, r *request.WebhooksPublicDelete) (interface{}, error) {
return nil, ctrl.webhook.With(ctx).DeleteByToken(r.WebhookID, r.WebhookToken)
}
func (ctrl *WebhooksPublic) Create(ctx context.Context, r *request.WebhooksPublicCreate) (interface{}, error) {
avatar, err := store.FromAny(nil, r.AvatarURL)
if err != nil {
return nil, err
}
defer avatar.Close()
return ctrl.webhook.With(ctx).Message(r.WebhookID, r.WebhookToken, r.Username, avatar, r.Content)
}

View File

@@ -77,22 +77,6 @@ func (svc accessControl) CanCreateGroupChannel(ctx context.Context) bool {
return svc.can(ctx, types.MessagingPermissionResource, "channel.group.create", permissions.Allowed)
}
func (svc accessControl) CanCreateWebhook(ctx context.Context) bool {
return svc.can(ctx, types.MessagingPermissionResource, "webhook.create")
}
func (svc accessControl) CanManageWebhooks(ctx context.Context) bool {
return svc.can(ctx, types.MessagingPermissionResource, "webhook.manage.all")
}
func (svc accessControl) CanManageOwnWebhooks(ctx context.Context, wh *types.Webhook) bool {
if wh.UserID != auth.GetIdentityFromContext(ctx).Identity() {
return false
}
return svc.can(ctx, types.MessagingPermissionResource, "webhook.manage.own")
}
func (svc accessControl) CanUpdateChannel(ctx context.Context, ch *types.Channel) bool {
return svc.can(ctx, ch, "update", svc.isChannelOwnerFallback(ctx, ch))
}
@@ -276,9 +260,6 @@ func (svc accessControl) Whitelist() permissions.Whitelist {
"channel.public.create",
"channel.private.create",
"channel.group.create",
"webhook.create",
"webhook.manage.all",
"webhook.manage.own",
)
wl.Set(
@@ -292,7 +273,6 @@ func (svc accessControl) Whitelist() permissions.Whitelist {
"archive",
"unarchive",
"members.manage",
"webhooks.manage",
"attachments.manage",
"message.send",
"message.reply",

View File

@@ -57,15 +57,7 @@ func (svc command) Do(channelID uint64, command, input string) (*types.Message,
msg.Message = input + " " + msg.Message
}
return DefaultMessage.With(svc.ctx).Create(msg)
default:
webhookSvc := DefaultWebhook.With(svc.ctx)
webhooks, err := webhookSvc.Find(&types.WebhookFilter{
ChannelID: channelID,
OutgoingTrigger: command,
})
if err != nil || len(webhooks) == 0 {
return nil, err
}
return webhookSvc.Do(webhooks[0], input)
}
return nil, nil
}

View File

@@ -12,7 +12,6 @@ import (
actionlogRepository "github.com/cortezaproject/corteza-server/pkg/actionlog/repository"
"github.com/cortezaproject/corteza-server/pkg/app/options"
intAuth "github.com/cortezaproject/corteza-server/pkg/auth"
"github.com/cortezaproject/corteza-server/pkg/http"
"github.com/cortezaproject/corteza-server/pkg/permissions"
"github.com/cortezaproject/corteza-server/pkg/settings"
"github.com/cortezaproject/corteza-server/pkg/store"
@@ -55,7 +54,6 @@ var (
DefaultMessage MessageService
DefaultEvent EventService
DefaultCommand CommandService
DefaultWebhook WebhookService
)
func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) {
@@ -129,19 +127,11 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) {
}
}
client, err := http.New(&http.Config{
Timeout: 10,
})
if err != nil {
return err
}
DefaultEvent = Event(ctx)
DefaultChannel = Channel(ctx)
DefaultAttachment = Attachment(ctx, DefaultStore)
DefaultMessage = Message(ctx)
DefaultCommand = Command(ctx)
DefaultWebhook = Webhook(ctx, client)
return nil
}

View File

@@ -1,249 +0,0 @@
package service
import (
"context"
"encoding/json"
"io"
"io/ioutil"
"net/url"
"strings"
"github.com/pkg/errors"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/cortezaproject/corteza-server/messaging/repository"
"github.com/cortezaproject/corteza-server/messaging/types"
"github.com/cortezaproject/corteza-server/pkg/auth"
"github.com/cortezaproject/corteza-server/pkg/http"
"github.com/cortezaproject/corteza-server/pkg/logger"
"github.com/cortezaproject/corteza-server/pkg/store"
)
type (
webhook struct {
db db
ctx context.Context
logger *zap.Logger
client *http.Client
webhook repository.WebhookRepository
ac webhookAccessController
}
webhookAccessController interface {
CanCreateWebhook(context.Context) bool
CanManageWebhooks(context.Context) bool
CanManageOwnWebhooks(context.Context, *types.Webhook) bool
}
WebhookService interface {
With(ctx context.Context) WebhookService
Get(webhookID uint64) (*types.Webhook, error)
Find(*types.WebhookFilter) (types.WebhookSet, error)
Delete(webhookID uint64) error
DeleteByToken(webhookID uint64, webhookToken string) error
Message(webhookID uint64, webhookToken string, username string, avatar io.Reader, message string) (interface{}, error)
Create(kind types.WebhookKind, channelID uint64, params types.WebhookRequest) (*types.Webhook, error)
Update(webhookID uint64, kind types.WebhookKind, channelID uint64, params types.WebhookRequest) (*types.Webhook, error)
Do(webhook *types.Webhook, message string) (*types.Message, error)
}
)
func Webhook(ctx context.Context, client *http.Client) WebhookService {
return (&webhook{
logger: DefaultLogger.Named("webhook"),
client: client,
}).With(ctx)
}
func (svc webhook) With(ctx context.Context) WebhookService {
db := repository.DB(ctx)
return &webhook{
db: db,
ctx: ctx,
logger: svc.logger,
client: svc.client,
webhook: repository.Webhook(ctx, db),
ac: DefaultAccessControl,
}
}
// log() returns zap's logger with requestID from current context and fields.
func (svc webhook) log(ctx context.Context, fields ...zapcore.Field) *zap.Logger {
return logger.AddRequestID(ctx, svc.logger).With(fields...)
}
func (svc webhook) Create(kind types.WebhookKind, channelID uint64, params types.WebhookRequest) (*types.Webhook, error) {
var userID = auth.GetIdentityFromContext(svc.ctx).Identity()
// @todo: params.Avatar (io.Reader)
webhook := &types.Webhook{
Kind: kind,
UserID: params.UserID,
OwnerUserID: userID,
ChannelID: channelID,
OutgoingTrigger: params.OutgoingTrigger,
OutgoingURL: params.OutgoingURL,
}
if !svc.ac.CanCreateWebhook(svc.ctx) {
return nil, ErrNoPermissions.withStack()
}
return svc.webhook.Create(webhook)
}
func (svc webhook) Update(webhookID uint64, kind types.WebhookKind, channelID uint64, params types.WebhookRequest) (*types.Webhook, error) {
if webhookID == 0 {
return nil, ErrInvalidID.withStack()
}
webhook, err := svc.Get(webhookID)
if err != nil {
return nil, err
}
if !svc.ac.CanManageOwnWebhooks(svc.ctx, webhook) || !svc.ac.CanManageWebhooks(svc.ctx) {
return nil, ErrNoPermissions.withStack()
}
// @todo: params.Avatar (io.Reader)
webhook.Kind = kind
webhook.ChannelID = channelID
webhook.OutgoingTrigger = params.OutgoingTrigger
webhook.OutgoingURL = params.OutgoingURL
return svc.webhook.Update(webhook)
}
func (svc webhook) Get(webhookID uint64) (*types.Webhook, error) {
return svc.webhook.Get(webhookID)
}
func (svc webhook) Find(filter *types.WebhookFilter) (types.WebhookSet, error) {
return svc.webhook.Find(filter)
}
func (svc webhook) Delete(webhookID uint64) error {
webhook, err := svc.Get(webhookID)
if err != nil {
return err
}
if !svc.ac.CanManageOwnWebhooks(svc.ctx, webhook) || !svc.ac.CanManageWebhooks(svc.ctx) {
return svc.webhook.Delete(webhookID)
}
var userID = auth.GetIdentityFromContext(svc.ctx).Identity()
if webhook.OwnerUserID == userID && svc.ac.CanManageOwnWebhooks(svc.ctx, webhook) {
return svc.webhook.Delete(webhookID)
}
return ErrNoPermissions.withStack()
}
func (svc webhook) DeleteByToken(webhookID uint64, webhookToken string) error {
return svc.webhook.DeleteByToken(webhookID, webhookToken)
}
func (svc webhook) Message(webhookID uint64, webhookToken string, username string, avatar io.Reader, message string) (interface{}, error) {
if webhook, err := svc.webhook.GetByToken(webhookID, webhookToken); err != nil {
return nil, err
} else {
msg := &types.Message{
Message: message,
Meta: &types.MessageMeta{
Username: username,
},
}
return svc.sendMessage(webhook, msg, avatar)
}
}
// Do executes an outgoing HTTP webhook request
func (svc webhook) Do(webhook *types.Webhook, message string) (*types.Message, error) {
if webhook.Kind != types.OutgoingWebhook {
return nil, errors.Errorf("Unsupported webhook type: %s", webhook.Kind)
}
// replace url query %s with message
url := strings.Replace(webhook.OutgoingURL, "%s", url.QueryEscape(message), -1)
// post body contains only `text`
requestBody := types.WebhookBody{
Text: message,
}
req, err := svc.client.Post(url, requestBody)
if err != nil {
return nil, err
}
// execute outgoing webhook
resp, err := svc.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// parse response body
responseBody := types.WebhookBody{}
contentType := resp.Header.Get("Content-Type")
switch {
case strings.Contains(contentType, "text/plain"):
// keep plain/text as-is
if b, err := ioutil.ReadAll(resp.Body); err != nil {
return nil, errors.WithStack(err)
} else {
responseBody.Text = string(b)
}
default:
switch resp.StatusCode {
case 200:
// assume the response is an expected json structure
if err := json.NewDecoder(resp.Body).Decode(&responseBody); err != nil {
return nil, errors.WithStack(err)
}
if responseBody.Text == "" {
return nil, errors.New("Empty webhook response")
}
default:
return nil, http.ToError(resp)
}
}
msg := &types.Message{
Message: responseBody.Text,
Meta: &types.MessageMeta{
Username: responseBody.Username,
},
}
avatar, err := store.FromURL(responseBody.Avatar)
if err != nil {
return svc.sendMessage(webhook, msg, nil)
}
defer avatar.Close()
return svc.sendMessage(webhook, msg, avatar)
}
func (svc webhook) sendMessage(webhook *types.Webhook, msg *types.Message, avatar io.Reader) (*types.Message, error) {
// We need a webhook user context for message service
ctx := auth.SetIdentityToContext(svc.ctx, auth.NewIdentity(webhook.UserID))
messageSvc := Message(ctx)
msg.ChannelID = webhook.ChannelID
msg.UserID = webhook.UserID
return messageSvc.CreateWithAvatar(msg, avatar)
}

View File

@@ -1,31 +0,0 @@
// +build integration
package service
import (
"fmt"
"encoding/json"
"net/http"
)
type Fortune struct{}
func (*Fortune) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fortune := "Fortune favors the prepared mind. - Louis Pasteur"
username := r.URL.Query()["username"]
if len(username) > 0 {
response := struct {
Username string `json:"username"`
Text string `json:"text"`
}{
username[0],
fortune,
}
b, _ := json.Marshal(response)
w.Header().Set("Content-Type", "application/json")
w.Write(b)
return
}
fmt.Fprintf(w, fortune)
}

View File

@@ -1,84 +0,0 @@
// +build integration
package service
import (
"context"
"net/http/httptest"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/cortezaproject/corteza-server/messaging/repository"
"github.com/cortezaproject/corteza-server/messaging/types"
"github.com/cortezaproject/corteza-server/pkg/auth"
"github.com/cortezaproject/corteza-server/pkg/http"
)
func TestOutgoingWebhook(t *testing.T) {
handler := &Fortune{}
server := httptest.NewServer(handler)
defer server.Close()
var channel = &types.Channel{ID: 1}
ctx := context.WithValue(context.Background(), "testing", true)
ctx = auth.SetIdentityToContext(ctx, auth.NewIdentity(1337))
// set up channel
{
rpo := repository.Channel(ctx, repository.DB(ctx))
_, err := rpo.Create(channel)
require.True(t, err == nil, "Error when creating channel: %+v", err)
}
client, err := http.New(&http.Config{
Timeout: 10,
})
require.True(t, err == nil, "Error creating HTTP client: %+v", err)
svc := Webhook(ctx, client)
{
/* create outgoing webhook */
webhook, err := svc.Create(types.OutgoingWebhook, channel.ID, types.WebhookRequest{
Username: "test-webhook",
UserID: 1337,
OutgoingTrigger: "fortune",
OutgoingURL: server.URL,
})
require.True(t, err == nil, "Error when creating webhook: %+v", err)
/* find outgoing webhook */
webhooks, err := svc.Find(&types.WebhookFilter{
OutgoingTrigger: webhook.OutgoingTrigger,
})
require.True(t, err == nil, "Error when finding webhook: %+v", err)
require.True(t, len(webhooks) == 1, "Expected to find 1 webhook, got %d", len(webhooks))
/* trigger outgoing webhook */
{
message, err := svc.Do(webhooks[0], "")
require.True(t, err == nil, "Error when triggering webhook: %+v", err)
require.True(t, strings.Contains(message.Message, "Louis Pasteur"), "Unexpected webhook output: %s", message.Message)
}
// update webhook
wh, err := svc.Update(webhook.ID, types.OutgoingWebhook, channel.ID, types.WebhookRequest{
Username: "test-webhook-json",
UserID: 1337,
OutgoingTrigger: "fortune-json",
OutgoingURL: server.URL + "?username=test",
})
require.True(t, err == nil, "Error when updating webhook: %+v", err)
/* trigger outgoing webhook */
{
message, err := svc.Do(wh, "")
require.True(t, err == nil, "Error when triggering webhook: %+v", err)
require.True(t, message.Meta.Username == "test", "Expected message.meta.username = 'test', got: '%s'", message.Meta.Username)
require.True(t, strings.Contains(message.Message, "Louis Pasteur"), "Unexpected webhook output: %s", message.Message)
}
}
}

View File

@@ -6,4 +6,3 @@ import (
const MessagingPermissionResource = permissions.Resource("messaging")
const ChannelPermissionResource = permissions.Resource("messaging:channel:")
const WebhookPermissionResource = permissions.Resource("messaging:webhook:")

View File

@@ -1,67 +0,0 @@
package types
// Hello! This file is auto-generated.
type (
// WebhookSet slice of Webhook
//
// This type is auto-generated.
WebhookSet []*Webhook
)
// Walk iterates through every slice item and calls w(Webhook) err
//
// This function is auto-generated.
func (set WebhookSet) Walk(w func(*Webhook) error) (err error) {
for i := range set {
if err = w(set[i]); err != nil {
return
}
}
return
}
// Filter iterates through every slice item, calls f(Webhook) (bool, err) and return filtered slice
//
// This function is auto-generated.
func (set WebhookSet) Filter(f func(*Webhook) (bool, error)) (out WebhookSet, err error) {
var ok bool
out = WebhookSet{}
for i := range set {
if ok, err = f(set[i]); err != nil {
return
} else if ok {
out = append(out, set[i])
}
}
return
}
// FindByID finds items from slice by its ID property
//
// This function is auto-generated.
func (set WebhookSet) FindByID(ID uint64) *Webhook {
for i := range set {
if set[i].ID == ID {
return set[i]
}
}
return nil
}
// IDs returns a slice of uint64s from all items in the set
//
// This function is auto-generated.
func (set WebhookSet) IDs() (IDs []uint64) {
IDs = make([]uint64, len(set))
for i := range set {
IDs[i] = set[i].ID
}
return
}

View File

@@ -1,102 +0,0 @@
package types
import (
"testing"
"errors"
"github.com/stretchr/testify/require"
)
// Hello! This file is auto-generated.
func TestWebhookSetWalk(t *testing.T) {
var (
value = make(WebhookSet, 3)
req = require.New(t)
)
// check walk with no errors
{
err := value.Walk(func(*Webhook) error {
return nil
})
req.NoError(err)
}
// check walk with error
req.Error(value.Walk(func(*Webhook) error { return errors.New("walk error") }))
}
func TestWebhookSetFilter(t *testing.T) {
var (
value = make(WebhookSet, 3)
req = require.New(t)
)
// filter nothing
{
set, err := value.Filter(func(*Webhook) (bool, error) {
return true, nil
})
req.NoError(err)
req.Equal(len(set), len(value))
}
// filter one item
{
found := false
set, err := value.Filter(func(*Webhook) (bool, error) {
if !found {
found = true
return found, nil
}
return false, nil
})
req.NoError(err)
req.Len(set, 1)
}
// filter error
{
_, err := value.Filter(func(*Webhook) (bool, error) {
return false, errors.New("filter error")
})
req.Error(err)
}
}
func TestWebhookSetIDs(t *testing.T) {
var (
value = make(WebhookSet, 3)
req = require.New(t)
)
// construct objects
value[0] = new(Webhook)
value[1] = new(Webhook)
value[2] = new(Webhook)
// set ids
value[0].ID = 1
value[1].ID = 2
value[2].ID = 3
// Find existing
{
val := value.FindByID(2)
req.Equal(uint64(2), val.ID)
}
// Find non-existing
{
val := value.FindByID(4)
req.Nil(val)
}
// List IDs from set
{
val := value.IDs()
req.Equal(len(val), len(value))
}
}

View File

@@ -1,58 +0,0 @@
package types
import (
"io"
"time"
)
type (
Webhook struct {
ID uint64 `json:"id" db:"id"`
Kind WebhookKind `json:"kind" db:"kind"`
AuthToken string `json:"-" db:"token"`
OwnerUserID uint64 `json:"userId" db:"rel_owner"`
// Created bot User ID
UserID uint64 `json:"userId" db:"rel_user"`
ChannelID uint64 `json:"channelId" db:"rel_channel"`
// Outgoing webhook details
OutgoingTrigger string `json:"trigger" db:"outgoing_trigger"`
OutgoingURL string `json:"url" db:"outgoing_url"`
CreatedAt time.Time `json:"createdAt,omitempty" db:"created_at"`
UpdatedAt *time.Time `json:"updatedAt,omitempty" db:"updated_at"`
DeletedAt *time.Time `json:"deletedAt,omitempty" db:"deleted_at"`
}
WebhookRequest struct {
Username string
UserID uint64
Avatar io.Reader
OutgoingTrigger string
OutgoingURL string
}
WebhookFilter struct {
ChannelID uint64
OwnerUserID uint64
OutgoingTrigger string
}
WebhookBody struct {
Text string `json:"text"`
Avatar string `json:"avatar,omitempty"`
Username string `json:"username,omitempty"`
}
WebhookKind string
)
const (
IncomingWebhook WebhookKind = "incoming"
OutgoingWebhook WebhookKind = "outgoing"
)