Skip to content

Commit

Permalink
fix: webhooks processor unamrshal empty interface (#582)
Browse files Browse the repository at this point in the history
**Describe the pull request**

An issue when webhooks are unmarshalled into an interface and not a
struct.

**Checklist**

- [x] I have made the modifications or added tests related to my PR
- [x] I have run the tests and linters locally and they pass
- [x] I have added/updated the documentation for my RP
  • Loading branch information
42atomys authored Feb 20, 2024
1 parent 6e6bdba commit 9dd49b1
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 12 deletions.
8 changes: 8 additions & 0 deletions internal/webhooks/campus_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ type campusUserProcessor struct {
duoapi.CampusUserWebhookProcessor
}

func unmarshalAndProcessCampusUser(data []byte, metadata duoapi.WebhookMetadata, p *processor) error {
webhookCampusUser, err := unmarshalWebhook[duoapi.WebhookMetadata, duoapi.CampusUser](data)
if err != nil {
return err
}
return webhookCampusUser.Payload.ProcessWebhook(p.ctx, &metadata, &campusUserProcessor{processor: p})
}

func (p *campusUserProcessor) Create(cu *duoapi.CampusUser, metadata *duoapi.WebhookMetadata) error {
// Do nothing if the primary campus is not true. Due to the fact of when an
// User switch of campus : the current campus is set to false and the new
Expand Down
8 changes: 8 additions & 0 deletions internal/webhooks/location.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ type locationProcessor struct {
duoapi.LocationWebhookProcessor[duoapi.LocationUser]
}

func unmarshalAndProcessLocation(data []byte, metadata duoapi.WebhookMetadata, p *processor) error {
webhookLocation, err := unmarshalWebhook[duoapi.WebhookMetadata, duoapi.Location[duoapi.LocationUser]](data)
if err != nil {
return err
}
return webhookLocation.Payload.ProcessWebhook(p.ctx, &metadata, &locationProcessor{processor: p})
}

func (p *locationProcessor) Create(loc *duoapi.Location[duoapi.LocationUser], metadata *duoapi.WebhookMetadata) error {
campus, err := p.db.Campus.Query().Where(campus.DuoID(loc.CampusID)).Only(p.ctx)
if err != nil {
Expand Down
29 changes: 17 additions & 12 deletions internal/webhooks/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,14 @@ func (p *processor) handler(data []byte) error {

handler := strings.Split(webhook.Metadata.SpecName, "-")[0]

log.Debug().Msgf("Received a message(%s): %+v", webhook.Metadata.SpecName, webhook.Payload)
log.Debug().Msgf("Received a message[%s](%s): %+v", handler, webhook.Metadata.SpecName, webhook.Payload)
switch handler {
case "github":
return p.githubHandler(data)
case "duo":
return p.duoHandler(data)
default:
log.Error().Str("handler", handler).Msg("Unknown handler")
}

return nil
Expand Down Expand Up @@ -193,24 +195,27 @@ func (p *processor) githubHandler(data []byte) error {

// duoHandler is the processor for the duo webhooks.
func (p *processor) duoHandler(data []byte) error {
webhook, err := unmarshalWebhook[*duoapi.WebhookMetadata, any](data)
webhook, err := unmarshalWebhook[duoapi.WebhookMetadata, any](data)
if err != nil {
return err
}

payload, ok := webhook.Payload.(duoapi.IWebhookPayload)
if !ok {
return errors.New("invalid duo webhook payload. Cannot cast to IWebhookPayload interface")
var modelToFunction = map[string]func([]byte, duoapi.WebhookMetadata, *processor) error{
"campus_user": unmarshalAndProcessCampusUser,
"location": unmarshalAndProcessLocation,
"user": unmarshalAndProcessUser,
}

switch webhook.Metadata.Model {
case "campus_user":
err = payload.ProcessWebhook(p.ctx, webhook.Metadata, &campusUserProcessor{processor: p})
case "location":
err = payload.ProcessWebhook(p.ctx, webhook.Metadata, &locationProcessor{processor: p})
case "user":
err = payload.ProcessWebhook(p.ctx, webhook.Metadata, &userProcessor{processor: p})
if function, exists := modelToFunction[webhook.Metadata.Model]; exists {
err = function(data, webhook.Metadata, p)
if err != nil {
log.Error().Err(err).Str("model", webhook.Metadata.Model).Str("event", webhook.Metadata.Event).Msg("Failed to process webhook")
return err
}
} else {
log.Error().Str("model", webhook.Metadata.Model).Msg("Unknown model")
}

if err != nil {
log.Error().Err(err).Str("model", webhook.Metadata.Model).Str("event", webhook.Metadata.Event).Msg("Failed to process webhook")
return err
Expand Down
8 changes: 8 additions & 0 deletions internal/webhooks/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ type userProcessor struct {
duoapi.UserWebhookProcessor
}

func unmarshalAndProcessUser(data []byte, metadata duoapi.WebhookMetadata, p *processor) error {
webhookUser, err := unmarshalWebhook[duoapi.WebhookMetadata, duoapi.User](data)
if err != nil {
return err
}
return webhookUser.Payload.ProcessWebhook(p.ctx, &metadata, &userProcessor{processor: p})
}

func (p *userProcessor) Create(u *duoapi.User, metadata *duoapi.WebhookMetadata) error {
ok, err := p.db.User.Query().Where(user.DuoID(u.ID)).Exist(p.ctx)
if err != nil && !modelgen.IsNotFound(err) {
Expand Down

0 comments on commit 9dd49b1

Please sign in to comment.