Skip to content

Commit

Permalink
Merge pull request #123 from xmidt-org/improve-listeners
Browse files Browse the repository at this point in the history
Move events into their own sub package, add listener options.
  • Loading branch information
schmidtw authored Sep 2, 2023
2 parents 268dd73 + c022498 commit da8416e
Show file tree
Hide file tree
Showing 8 changed files with 726 additions and 276 deletions.
150 changes: 150 additions & 0 deletions event/event.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// SPDX-FileCopyrightText: 2023 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package event

import (
"fmt"
"strings"
"time"
)

// Registration is an event that occurs during webhook registration.
//
// The time the registration is attempted may be quite different from the time
// the event is created. Therefore it is recorded in the event as At when it
// occurs.
//
// The duration of the registration may be of interest so it is captured in the
// event as Duration when it occurs.
//
// The body of the request or response may be of interest so it is captured in
// the event as Body when an error occurs and it is available.
//
// The status code of the response may be of interest so it is captured in the
// event as StatusCode when it occurs.
//
// Any error that occurs during the registration is captured in the event as Err
// when it occurs. Multiple error may be included for each event.
type Registration struct {
// At holds the starting time of the event if applicable.
At time.Time

// Duration holds the duration of the event if applicable.
Duration time.Duration

// The body of the request or response if applicable.
Body []byte

// StatusCode holds the HTTP status code returned by the webhook registration.
StatusCode int

// Err holds any error that occurred while performing the registration.
Err error
}

func (r Registration) String() string {
buf := strings.Builder{}

buf.WriteString("event.Registration{\n")
buf.WriteString(fmt.Sprintf(" At: %s\n", r.At.Format(time.RFC3339)))
buf.WriteString(fmt.Sprintf(" Duration: %s\n", r.Duration.String()))
buf.WriteString(fmt.Sprintf(" Body: '%s'\n", string(r.Body)))
buf.WriteString(fmt.Sprintf(" StatusCode: %d\n", r.StatusCode))
buf.WriteString(fmt.Sprintf(" Err: %v\n", r.Err))
buf.WriteString("}\n")

return buf.String()
}

// RegistrationListener is a sink for registration events.
type RegistrationListener interface {
OnRegistrationEvent(Registration)
}

// RegistrationFunc is a function that implements the RegistrationListener
// interface. It is useful for creating a listener from a function.
type RegistrationFunc func(Registration)

func (f RegistrationFunc) OnRegistrationEvent(r Registration) {
f(r)
}

// Tokenize is an event that occurs during Tokenize() call.
//
// When available the header, algorithms, and algorithm used are included.
// Any error that occurs during tokenization is included.
type Tokenize struct {
// Header holds the header that was used to tokenize the request.
Header string

// Algorithms holds the algorithms that were offered to tokenize the request.
Algorithms []string

// Algorithm holds the algorithm that was used to tokenize the request.
Algorithm string

// Err holds any error that occurred while tokenizing the request.
Err error
}

func (t Tokenize) String() string {
buf := strings.Builder{}

buf.WriteString("event.Tokenize{\n")
buf.WriteString(fmt.Sprintf(" Header: '%s'\n", t.Header))
buf.WriteString(fmt.Sprintf(" Algorithms: [%s]\n", strings.Join(t.Algorithms, ", ")))
buf.WriteString(fmt.Sprintf(" Algorithm: '%s'\n", t.Algorithm))
buf.WriteString(fmt.Sprintf(" Err: %v\n", t.Err))
buf.WriteString("}\n")

return buf.String()
}

// RegistrationListener is a sink for registration events.
type TokenizeListener interface {
OnTokenizeEvent(Tokenize)
}

// TokenizeEventFunc is a function that implements the TokenizeListener
// interface. It is useful for creating a listener from a function.
type TokenizeFunc func(Tokenize)

func (f TokenizeFunc) OnTokenizeEvent(t Tokenize) {
f(t)
}

// AuthorizeEvent is an event that occurs during the Authorize() call.
// When available the algorithm used is included.
// Any error that occurs during authorization is included.
type Authorize struct {
// Algorithm holds the algorithm that was used for authorization.
Algorithm string

// Err holds any error that occurred while tokenizing the request.
Err error
}

func (a Authorize) String() string {
buf := strings.Builder{}

buf.WriteString("event.Authorize{\n")
buf.WriteString(fmt.Sprintf(" Algorithm: '%s'\n", a.Algorithm))
buf.WriteString(fmt.Sprintf(" Err: %v\n", a.Err))
buf.WriteString("}\n")

return buf.String()
}

// RegistrationListener is a sink for registration events.
type AuthorizeListener interface {
OnAuthorizeEvent(Authorize)
}

// AuthorizeFunc is a function that implements the AuthorizeListener
// interface. It is useful for creating a listener from a function.
type AuthorizeFunc func(Authorize)

func (f AuthorizeFunc) OnAuthorizeEvent(a Authorize) {
f(a)
}
98 changes: 98 additions & 0 deletions event/event_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// SPDX-FileCopyrightText: 2023 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package event

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestString(t *testing.T) {
tests := []struct {
description string
reg *Registration
token *Tokenize
auth *Authorize
want string
}{
{
description: "Empty Registration",
reg: &Registration{},
want: "event.Registration{\n" +
" At: 0001-01-01T00:00:00Z\n" +
" Duration: 0s\n" +
" Body: ''\n" +
" StatusCode: 0\n" +
" Err: <nil>\n" +
"}\n",
}, {
description: "Empty Tokenize",
token: &Tokenize{},
want: "event.Tokenize{\n" +
" Header: ''\n" +
" Algorithms: []\n" +
" Algorithm: ''\n" +
" Err: <nil>\n" +
"}\n",
}, {
description: "Empty Authorize",
auth: &Authorize{},
want: "event.Authorize{\n" +
" Algorithm: ''\n" +
" Err: <nil>\n" +
"}\n",
},
}
for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) {
assert := assert.New(t)

switch {
case tc.reg != nil:
assert.Equal(tc.want, tc.reg.String())
case tc.token != nil:
assert.Equal(tc.want, tc.token.String())
case tc.auth != nil:
assert.Equal(tc.want, tc.auth.String())
}
})
}
}

func TestRegistrationListenerFunc(t *testing.T) {
assert := assert.New(t)

var called bool
f := RegistrationFunc(func(Registration) {
called = true
})

f.OnRegistrationEvent(Registration{})
assert.True(called)
}

func TestTokenizeListenerFunc(t *testing.T) {
assert := assert.New(t)

var called bool
f := TokenizeFunc(func(Tokenize) {
called = true
})

f.OnTokenizeEvent(Tokenize{})
assert.True(called)
}

func TestAuthorizeListenerFunc(t *testing.T) {
assert := assert.New(t)

var called bool
f := AuthorizeFunc(func(Authorize) {
called = true
})

f.OnAuthorizeEvent(Authorize{})
assert.True(called)
}
84 changes: 0 additions & 84 deletions events.go

This file was deleted.

Loading

0 comments on commit da8416e

Please sign in to comment.