B: Several Silly fixes for silly mistakes

This commit is contained in:
Preston Baxter 2023-11-23 08:05:44 -06:00
parent e0f0bb3b5f
commit f430e33a28
11 changed files with 82 additions and 27 deletions

View File

@ -5,7 +5,7 @@ WEBHOOK_VERSION=$(shell jq -rc ".webhook_version" versions.json)
deploy: deploy-ui deploy-service deploy-tf
deploy-tf:
cd infra; make deploy
cd infra; make deploy-yes
deploy-ui: build-ui
docker push $(BASE_URL)/frontend-service:latest

View File

@ -1,8 +1,15 @@
FRONTEND_VERSION=$(shell jq -rc ".frontend_version" ../versions.json)
WEBHOOK_VERSION=$(shell jq -rc ".webhook_version" ../versions.json)
deploy: SHELL := /bin/bash
deploy:
replace: SHELL := /bin/bash
replace:
sed -i -Ee "s/(webhook_service_tag = \").*(\")/\1$(WEBHOOK_VERSION)\2/g" terraform.tfvars
sed -i -Ee "s/(frontend_service_tag = \").*(\")/\1$(FRONTEND_VERSION)\2/g" terraform.tfvars
deploy: SHELL := /bin/bash
deploy: replace
tofu apply
deploy-yes: SHELL := /bin/bash
deploy-yes: replace
tofu apply -auto-approve

View File

@ -24,6 +24,7 @@ func BuildRouter(r *gin.Engine) {
log.SetFormatter(&logrus.TextFormatter{
DisableColors: true,
})
log.SetLevel(logrus.DebugLevel)
var err error
mongo, err = db.NewClient(conf.Mongo.Uri)

View File

@ -2,10 +2,11 @@ package controllers
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
"git.preston-baxter.com/Preston_PLB/capstone/webhook-service/vendors/pco/webhooks"
@ -31,14 +32,16 @@ func ValidatePcoWebhook(c *gin.Context) {
return
}
//clone request to harmlessly inspect the body
bodyReader := c.Request.Clone(context.Background()).Body
body, err := io.ReadAll(bodyReader)
//clone request body to harmlessly inspect the body
bodyCopy := bytes.NewBuffer([]byte{})
_, err = io.Copy(bodyCopy, c.Request.Body)
if err != nil {
log.WithError(err).Error("Failed to read body while validating PCO webhook")
log.WithError(err).Error("Failed to copy body while validating PCO webhook")
_ = c.AbortWithError(501, err)
return
}
body := bodyCopy.Bytes()
c.Request.Body = io.NopCloser(bytes.NewReader(body))
//Get secret
key, err := getAuthSecret(c, body)
@ -60,16 +63,25 @@ func ValidatePcoWebhook(c *gin.Context) {
func getAuthSecret(c *gin.Context, body []byte) (string, error) {
userObjectId := userIdFromContext(c)
log.Debug(string(body))
event := &webhooks.EventDelivery{}
err := jsonapi.UnmarshalPayload(bytes.NewBuffer(body), event)
//Pco is weird and sends a data array instead of an object. Yet there is only one event. Fun times
event, err := jsonapi.UnmarshalManyPayload[webhooks.EventDelivery](bytes.NewBuffer(body))
if err != nil {
return "", err
return "", errors.Join(fmt.Errorf("Failed to unmarshall event delivery from PCO"), err)
}
webhook, err := mongo.FindPcoSubscriptionForUser(*userObjectId, event.Name)
if len(event) == 0 {
return "", fmt.Errorf("There are no events in the delivery. Something is wrong")
}
webhook, err := mongo.FindPcoSubscriptionForUser(*userObjectId, event[0].Name)
if err != nil {
return "", err
return "", errors.Join(fmt.Errorf("Failed to find pco subscription for user: %s and event: %s", userObjectId.Hex(), event[0].Name), err)
}
if webhook == nil {
return "", fmt.Errorf("Could not find subscription for user: %s and name %s", userObjectId.Hex(), event[0].Name)
}
return webhook.Details.AuthenticitySecret, nil

View File

@ -68,13 +68,16 @@ func ConsumePcoWebhook(c *gin.Context) {
errs := make([]error, 2)
go func(wg *sync.WaitGroup) {
defer wg.Done()
actionMappings, errs[0] = mongo.FindActionMappingsByUser(*userObjectId)
wg.Done()
}(wg)
go func(wg *sync.WaitGroup) {
errs[1] = jsonapi.UnmarshalPayload(c.Request.Body, webhookBody)
wg.Done()
defer wg.Done()
var payload []webhooks.EventDelivery
payload, errs[1] = jsonapi.UnmarshalManyPayload[webhooks.EventDelivery](c.Request.Body)
webhookBody = &payload[0]
}(wg)
wg.Wait()
@ -89,9 +92,9 @@ func ConsumePcoWebhook(c *gin.Context) {
//loop through all actions a user has
for _, mapping := range actionMappings {
//find the ones that are runable by this function
if mapping.SourceEvent.VendorName == models.PCO_VENDOR_NAME && eventMatch(webhookBody.Name) {
if mapping.SourceEvent.VendorName == models.PCO_VENDOR_NAME && eventMatch(mapping.SourceEvent.Key, webhookBody.Name) {
//generate lookup key for function
actionKey := fmt.Sprintf("%s:%s", mapping.Action.VendorName, mapping.Action.Type)
actionKey := fmt.Sprintf("%s.%s", mapping.Action.VendorName, mapping.Action.Type)
//if function exists run the function
if action, ok := actionFuncMap[actionKey]; ok {
err := action(c, webhookBody)
@ -99,15 +102,21 @@ func ConsumePcoWebhook(c *gin.Context) {
if err != nil {
log.WithError(err).Errorf("Failed to execute action: %s. From event source: %s:%s", actionKey, mapping.SourceEvent.VendorName, mapping.SourceEvent.Key)
_ = c.AbortWithError(501, err)
} else {
log.Infof("Succesfully proccessed: %s for %s", webhookBody.Name, userObjectId.Hex())
c.Status(200)
}
return
}
}
}
log.Warnf("No errors, but also no work...")
c.Status(200)
}
func eventMatch(event string) bool {
if regexString, ok := eventRegexKeys[event]; ok {
reg := regexp.MustCompile(regexString)
func eventMatch(key, event string) bool {
if regexString, ok := eventRegexKeys[key]; ok {
reg := regexp.MustCompile(regexString) //TODO: Make this regex cache-able
return reg.MatchString(event)
} else {
return false
@ -204,6 +213,7 @@ func ScheduleBroadcastFromWebhook(c *gin.Context, body *webhooks.EventDelivery)
VendorName: models.PCO_VENDOR_NAME,
Type: body.Name,
}
if err := mongo.SaveModel(eventRecievedAudit); err != nil {
log.WithError(err).WithField("EventRecieved", eventRecievedAudit).Error("Failed to save audit event. Logging here and resuming")
}
@ -215,6 +225,16 @@ func ScheduleBroadcastFromWebhook(c *gin.Context, body *webhooks.EventDelivery)
switch body.Name {
case "services.v2.events.plan.created":
broadcast, err = scheduleNewBroadcastFromWebhook(c, payload, ytClient, pcoClient)
if err != nil {
log.WithError(err).Error("Failed to schedule broadcast from created event")
return err
}
case "services.v2.events.plan.updated":
log.Warn("services.v2.events.plan.updated event not implemented")
return nil
case "services.v2.events.plan.destroyed":
log.Warn("services.v2.events.plan.destroyed event not implemented")
return nil
default:
return fmt.Errorf("Unkown event error: %s", body.Name)
}

View File

@ -0,0 +1,15 @@
package controllers
import (
"testing"
"github.com/go-playground/assert/v2"
)
func TestPlanEventMatch(t *testing.T) {
events := []string{"services.v2.events.plan.updated","services.v2.events.plan.destroyed","services.v2.events.plan.created"}
for _, event := range events {
assert.Equal(t, eventMatch("plan", event), true)
}
}

View File

@ -17,7 +17,7 @@ type EventDelivery struct {
//number of attemts taken to deliver the event
Attempt int `jsonapi:"attr,attempt"`
//JSON:API string of the event
Payload string `jsonapi:"attr,attempt"`
Payload string `jsonapi:"attr,payload"`
//Owner Organization of the event
Organization *services.Organization `jsonapi:"relation,organization"`
}

View File

@ -152,7 +152,7 @@ func setupPcoSubscriptions(user *models.User) error {
}
//Save Subscriptions
err = mongo.SaveSubscriptionsForUser(user.Id, subscriptions...)
err = mongo.SaveSubscriptionsForUser(user.Id, builtHooks...)
if err != nil {
return errors.Join(fmt.Errorf("Failed to save subscriptions for user: %s", user.Id), err)
}

View File

@ -67,7 +67,7 @@ func (db *DB) SaveModels(m ...Model) error {
for index, model := range m {
entry := mongo.NewUpdateOneModel()
entry.SetFilter(bson.M{"_id": model.MongoId})
entry.SetFilter(bson.M{"_id": model.MongoId()})
entry.SetUpsert(true)
entry.SetUpdate(bson.M{"$set": model})
model.UpdateObjectInfo()

View File

@ -17,7 +17,7 @@ func (db *DB) FindPcoSubscriptionForUser(userId primitive.ObjectID, eventName st
conf := config.Config()
opts := options.FindOne()
res := db.client.Database(conf.Mongo.EntDb).Collection(conf.Mongo.EntCol).FindOne(context.Background(), bson.M{"_id": userId, "obj_info.ent": models.PCO_SUBSCRIPTION_TYPE, "details.name": eventName}, opts)
res := db.client.Database(conf.Mongo.EntDb).Collection(conf.Mongo.EntCol).FindOne(context.Background(), bson.M{"user_id": userId, "obj_info.ent": models.PCO_SUBSCRIPTION_TYPE, "details.name": eventName}, opts)
if res.Err() != nil {
if res.Err() == mongo.ErrNoDocuments {

View File

@ -1,4 +1,4 @@
{
"webhook_version": "0.0.31",
"frontend_version": "0.0.34"
"webhook_version": "0.0.45",
"frontend_version": "0.0.35"
}