From 54544c489cef6544f200775264d044951f4dbee2 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 30 Mar 2022 16:14:23 -0700 Subject: [PATCH] Helper method to receive WebhookEvent (#109) --- auth/provider.go | 23 +++++++++++ webhook/verifier.go | 20 ++++++++++ webhook/webhook_test.go | 86 +++++++++++++++++++++++++++++------------ 3 files changed, 105 insertions(+), 24 deletions(-) diff --git a/auth/provider.go b/auth/provider.go index 9feb5ca..2a00d98 100644 --- a/auth/provider.go +++ b/auth/provider.go @@ -36,3 +36,26 @@ func (p *FileBasedKeyProvider) GetSecret(key string) string { func (p *FileBasedKeyProvider) NumKeys() int { return len(p.keys) } + +type SimpleKeyProvider struct { + apiKey string + apiSecret string +} + +func NewSimpleKeyProvider(apiKey, apiSecret string) *SimpleKeyProvider { + return &SimpleKeyProvider{ + apiKey: apiKey, + apiSecret: apiSecret, + } +} + +func (p *SimpleKeyProvider) GetSecret(key string) string { + if key == p.apiKey { + return p.apiSecret + } + return "" +} + +func (p *SimpleKeyProvider) NumKeys() int { + return 1 +} diff --git a/webhook/verifier.go b/webhook/verifier.go index f215301..13ac6bd 100644 --- a/webhook/verifier.go +++ b/webhook/verifier.go @@ -6,7 +6,10 @@ import ( "io/ioutil" "net/http" + "google.golang.org/protobuf/encoding/protojson" + "github.com/livekit/protocol/auth" + "github.com/livekit/protocol/livekit" ) // Receive reads and verifies incoming webhook is signed with key/secret pair @@ -48,3 +51,20 @@ func Receive(r *http.Request, provider auth.KeyProvider) ([]byte, error) { return data, nil } + +// ReceiveWebhookEvent reads and verifies incoming webhook, and returns a parsed WebhookEvent +func ReceiveWebhookEvent(r *http.Request, provider auth.KeyProvider) (*livekit.WebhookEvent, error) { + data, err := Receive(r, provider) + if err != nil { + return nil, err + } + unmarshalOpts := protojson.UnmarshalOptions{ + DiscardUnknown: true, + AllowPartial: true, + } + event := livekit.WebhookEvent{} + if err = unmarshalOpts.Unmarshal(data, &event); err != nil { + return nil, err + } + return &event, nil +} diff --git a/webhook/webhook_test.go b/webhook/webhook_test.go index 067932f..0291e39 100644 --- a/webhook/webhook_test.go +++ b/webhook/webhook_test.go @@ -5,45 +5,83 @@ import ( "encoding/json" "net" "net/http" + "sync" "testing" "github.com/stretchr/testify/require" "github.com/livekit/protocol/auth" + "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/webhook" ) +const ( + apiKey = "mykey" + apiSecret = "mysecret" +) + func TestWebHook(t *testing.T) { s := newServer(":8765") require.NoError(t, s.Start()) defer s.Stop() - authProvider := auth.NewFileBasedKeyProviderFromMap(map[string]string{ - "mykey": "mysecret", - }) - - payload := map[string]interface{}{ - "test": "payload", - "nested": map[string]interface{}{ - "structure": true, - }, - } - - s.handler = func(r *http.Request) { - // receive logic - data, err := webhook.Receive(r, authProvider) - require.NoError(t, err) - - var decoded map[string]interface{} - require.NoError(t, json.Unmarshal(data, &decoded)) - - require.EqualValues(t, decoded, payload) - } - - notifier := webhook.NewNotifier("mykey", "mysecret", []string{ + authProvider := auth.NewSimpleKeyProvider( + apiKey, apiSecret, + ) + notifier := webhook.NewNotifier(apiKey, apiSecret, []string{ "http://localhost:8765", }) - require.NoError(t, notifier.Notify(context.Background(), payload)) + + t.Run("test json payload", func(t *testing.T) { + payload := map[string]interface{}{ + "test": "payload", + "nested": map[string]interface{}{ + "structure": true, + }, + } + + wg := sync.WaitGroup{} + wg.Add(1) + s.handler = func(r *http.Request) { + defer wg.Done() + // receive logic + data, err := webhook.Receive(r, authProvider) + require.NoError(t, err) + + var decoded map[string]interface{} + require.NoError(t, json.Unmarshal(data, &decoded)) + + require.EqualValues(t, decoded, payload) + } + + require.NoError(t, notifier.Notify(context.Background(), payload)) + wg.Wait() + }) + + t.Run("test event payload", func(t *testing.T) { + event := &livekit.WebhookEvent{ + Event: webhook.EventTrackPublished, + Participant: &livekit.ParticipantInfo{ + Identity: "test", + }, + Track: &livekit.TrackInfo{ + Sid: "TR_abcde", + }, + } + + wg := sync.WaitGroup{} + wg.Add(1) + s.handler = func(r *http.Request) { + defer wg.Done() + decodedEvent, err := webhook.ReceiveWebhookEvent(r, authProvider) + require.NoError(t, err) + + require.EqualValues(t, event, decodedEvent) + } + require.NoError(t, notifier.Notify(context.Background(), event)) + wg.Wait() + }) + } type testServer struct {