-
Notifications
You must be signed in to change notification settings - Fork 38
/
webhook_subscriptions.go
177 lines (146 loc) · 7.54 KB
/
webhook_subscriptions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package adminapi
import (
"fmt"
"github.com/go-openapi/runtime/middleware"
"github.com/gofrs/uuid"
"go.uber.org/zap"
"github.com/transcom/mymove/pkg/appcontext"
"github.com/transcom/mymove/pkg/apperror"
webhooksubscriptionop "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/webhook_subscriptions"
"github.com/transcom/mymove/pkg/gen/adminmessages"
"github.com/transcom/mymove/pkg/handlers"
"github.com/transcom/mymove/pkg/handlers/adminapi/payloads"
"github.com/transcom/mymove/pkg/models"
"github.com/transcom/mymove/pkg/services"
"github.com/transcom/mymove/pkg/services/query"
)
// IndexWebhookSubscriptionsHandler returns a list of webhook subscriptions via GET /webhook-subscriptions
type IndexWebhookSubscriptionsHandler struct {
handlers.HandlerConfig
services.ListFetcher
services.NewQueryFilter
services.NewPagination
}
// Handle retrieves a list of webhook subscriptions
func (h IndexWebhookSubscriptionsHandler) Handle(params webhooksubscriptionop.IndexWebhookSubscriptionsParams) middleware.Responder {
return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest,
func(appCtx appcontext.AppContext) (middleware.Responder, error) {
// Here is where NewQueryFilter will be used to create Filters from the 'filter' query param
queryFilters := []services.QueryFilter{}
ordering := query.NewQueryOrder(params.Sort, params.Order)
pagination := h.NewPagination(params.Page, params.PerPage)
var webhookSubscriptions models.WebhookSubscriptions
err := h.ListFetcher.FetchRecordList(appCtx, &webhookSubscriptions, queryFilters, nil, pagination, ordering)
if err != nil {
return handlers.ResponseForError(appCtx.Logger(), err), err
}
totalWebhookSubscriptionsCount, err := h.ListFetcher.FetchRecordCount(appCtx, &webhookSubscriptions, queryFilters)
if err != nil {
return handlers.ResponseForError(appCtx.Logger(), err), err
}
queriedWebhookSubscriptionsCount := len(webhookSubscriptions)
payload := make(adminmessages.WebhookSubscriptions, queriedWebhookSubscriptionsCount)
for i, s := range webhookSubscriptions {
payload[i] = payloads.WebhookSubscriptionPayload(s)
}
return webhooksubscriptionop.NewIndexWebhookSubscriptionsOK().WithContentRange(fmt.Sprintf("webhookSubscriptions %d-%d/%d", pagination.Offset(), pagination.Offset()+queriedWebhookSubscriptionsCount, totalWebhookSubscriptionsCount)).WithPayload(payload), nil
})
}
// GetWebhookSubscriptionHandler returns one webhookSubscription via GET /webhook-subscriptions/:ID
type GetWebhookSubscriptionHandler struct {
handlers.HandlerConfig
services.WebhookSubscriptionFetcher
services.NewQueryFilter
}
// Handle retrieves a webhook subscription
func (h GetWebhookSubscriptionHandler) Handle(params webhooksubscriptionop.GetWebhookSubscriptionParams) middleware.Responder {
return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest,
func(appCtx appcontext.AppContext) (middleware.Responder, error) {
webhookSubscriptionID := uuid.FromStringOrNil(params.WebhookSubscriptionID.String())
queryFilters := []services.QueryFilter{query.NewQueryFilter("id", "=", webhookSubscriptionID)}
webhookSubscription, err := h.WebhookSubscriptionFetcher.FetchWebhookSubscription(appCtx, queryFilters)
if err != nil {
return handlers.ResponseForError(appCtx.Logger(), err), err
}
payload := payloads.WebhookSubscriptionPayload(webhookSubscription)
return webhooksubscriptionop.NewGetWebhookSubscriptionOK().WithPayload(payload), nil
})
}
// CreateWebhookSubscriptionHandler is the handler for creating users.
type CreateWebhookSubscriptionHandler struct {
handlers.HandlerConfig
services.WebhookSubscriptionCreator
services.NewQueryFilter
}
// Handle creates an admin user
func (h CreateWebhookSubscriptionHandler) Handle(params webhooksubscriptionop.CreateWebhookSubscriptionParams) middleware.Responder {
return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest,
func(appCtx appcontext.AppContext) (middleware.Responder, error) {
subscription := payloads.WebhookSubscriptionModelFromCreate(params.WebhookSubscription)
createdWebhookSubscription, verrs, err := h.WebhookSubscriptionCreator.CreateWebhookSubscription(appCtx, subscription)
if verrs != nil {
appCtx.Logger().Error("Error saving webhook subscription", zap.Error(verrs))
return webhooksubscriptionop.NewCreateWebhookSubscriptionInternalServerError(), verrs
}
if err != nil {
appCtx.Logger().Error("Error saving webhook subscription", zap.Error(err))
switch e := err.(type) {
case apperror.NotFoundError:
return webhooksubscriptionop.NewCreateWebhookSubscriptionBadRequest(), err
case apperror.QueryError:
if e.Unwrap() != nil {
// If you can unwrap, log the internal error (usually a pq error) for better debugging
appCtx.Logger().Error("adminapi.CreateWebhookSubscriptionHandler query error", zap.Error(e.Unwrap()))
}
return webhooksubscriptionop.NewCreateWebhookSubscriptionInternalServerError(), err
default:
return webhooksubscriptionop.NewCreateWebhookSubscriptionInternalServerError(), err
}
}
returnPayload := payloads.WebhookSubscriptionPayload(*createdWebhookSubscription)
return webhooksubscriptionop.NewCreateWebhookSubscriptionCreated().WithPayload(returnPayload), nil
})
}
// UpdateWebhookSubscriptionHandler returns an updated webhook subscription via PATCH
type UpdateWebhookSubscriptionHandler struct {
handlers.HandlerConfig
services.WebhookSubscriptionUpdater
services.NewQueryFilter
}
// Handle updates a webhook subscription
func (h UpdateWebhookSubscriptionHandler) Handle(params webhooksubscriptionop.UpdateWebhookSubscriptionParams) middleware.Responder {
return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest,
func(appCtx appcontext.AppContext) (middleware.Responder, error) {
payload := params.WebhookSubscription
// Checks that ID in body matches ID in query
payloadID := uuid.FromStringOrNil(payload.ID.String())
if payloadID != uuid.Nil && params.WebhookSubscriptionID != payload.ID {
webhookErr := apperror.NewUnprocessableEntityError("Payload ID does not match query ID")
return webhooksubscriptionop.NewUpdateWebhookSubscriptionUnprocessableEntity(), webhookErr
}
// If no ID in body, use query ID
payload.ID = params.WebhookSubscriptionID
// Convert payload to model
webhookSubscription := payloads.WebhookSubscriptionModel(payload)
// Note we are not checking etag as adminapi does not seem to use this
updatedWebhookSubscription, err := h.WebhookSubscriptionUpdater.UpdateWebhookSubscription(appCtx, webhookSubscription, payload.Severity, ¶ms.IfMatch)
// Return error response if not successful
if err != nil {
if err.Error() == models.RecordNotFoundErrorString {
appCtx.Logger().Error("Error finding webhookSubscription to update")
return webhooksubscriptionop.NewUpdateWebhookSubscriptionNotFound(), err
}
switch err.(type) {
case apperror.PreconditionFailedError:
appCtx.Logger().Error("Error updating webhookSubscription due to stale eTag")
return webhooksubscriptionop.NewUpdateWebhookSubscriptionPreconditionFailed(), err
default:
appCtx.Logger().Error(fmt.Sprintf("Error updating webhookSubscription %s", params.WebhookSubscriptionID.String()), zap.Error(err))
return handlers.ResponseForError(appCtx.Logger(), err), err
}
}
// Convert model back to a payload and return to caller
payload = payloads.WebhookSubscriptionPayload(*updatedWebhookSubscription)
return webhooksubscriptionop.NewUpdateWebhookSubscriptionOK().WithPayload(payload), nil
})
}