Skip to content

Commit

Permalink
Add event types (#2180)
Browse files Browse the repository at this point in the history
* feat: add event types

* chore: add API tests
  • Loading branch information
jirevwe authored Oct 28, 2024
1 parent 99c5fd3 commit 7ddb3c1
Show file tree
Hide file tree
Showing 13 changed files with 626 additions and 10 deletions.
14 changes: 14 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,13 @@ func (a *ApplicationHandler) BuildControlPlaneRoutes() *chi.Mux {
})
})

projectSubRouter.Route("/event-types", func(eventTypesRouter chi.Router) {
eventTypesRouter.Get("/", handler.GetEventTypes)
eventTypesRouter.With(handler.RequireEnabledProject()).Post("/", handler.CreateEventType)
eventTypesRouter.With(handler.RequireEnabledProject()).Put("/{eventTypeId}", handler.UpdateEventType)
eventTypesRouter.With(handler.RequireEnabledProject()).Post("/{eventTypeId}/deprecate", handler.DeprecateEventType)
})

projectSubRouter.Route("/eventdeliveries", func(eventDeliveryRouter chi.Router) {
eventDeliveryRouter.With(middleware.Pagination).Get("/", handler.GetEventDeliveriesPaged)
eventDeliveryRouter.With(handler.RequireEnabledProject()).Post("/forceresend", handler.ForceResendEventDeliveries)
Expand Down Expand Up @@ -353,6 +360,13 @@ func (a *ApplicationHandler) BuildControlPlaneRoutes() *chi.Mux {
})
})

projectSubRouter.Route("/event-types", func(eventTypesRouter chi.Router) {
eventTypesRouter.Get("/", handler.GetEventTypes)
eventTypesRouter.With(handler.RequireEnabledProject()).Post("/", handler.CreateEventType)
eventTypesRouter.With(handler.RequireEnabledProject()).Put("/{eventTypeId}", handler.UpdateEventType)
eventTypesRouter.With(handler.RequireEnabledProject()).Post("/{eventTypeId}/deprecate", handler.DeprecateEventType)
})

projectSubRouter.Route("/eventdeliveries", func(eventDeliveryRouter chi.Router) {
eventDeliveryRouter.With(middleware.Pagination).Get("/", handler.GetEventDeliveriesPaged)
eventDeliveryRouter.With(handler.RequireEnabledProject()).Post("/forceresend", handler.ForceResendEventDeliveries)
Expand Down
184 changes: 184 additions & 0 deletions api/handlers/event_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package handlers

import (
"github.com/frain-dev/convoy/api/models"
"github.com/frain-dev/convoy/database/postgres"
"github.com/frain-dev/convoy/datastore"
"github.com/frain-dev/convoy/util"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/oklog/ulid/v2"
"net/http"
)

// GetEventTypes
//
// @Summary Retrieves a project's event types
// @Description This endpoint fetches the project's event types
// @Id GetEventTypes
// @Tags EventTypes
// @Accept json
// @Produce json
// @Param projectID path string true "Project ID"
// @Success 200 {object} util.ServerResponse{data=models.EventTypeListResponse}
// @Failure 400,401,404 {object} util.ServerResponse{data=Stub}
// @Security ApiKeyAuth
// @Router /v1/projects/{projectID}/event-types [get]
func (h *Handler) GetEventTypes(w http.ResponseWriter, r *http.Request) {
project, err := h.retrieveProject(r)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

eventTypeRepo := postgres.NewEventTypesRepo(h.A.DB)
eventTypes, err := eventTypeRepo.FetchAllEventTypes(r.Context(), project.UID)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

resp := &models.EventTypeListResponse{EventTypes: eventTypes}
_ = render.Render(w, r, util.NewServerResponse("Event types fetched successfully", resp, http.StatusOK))
}

// CreateEventType
//
// @Summary Create an event type
// @Description This endpoint creates an event type
// @Id CreateEventType
// @Tags EventTypes
// @Accept json
// @Produce json
// @Param projectID path string true "Project ID"
// @Param eventType body models.CreateEventType true "Event Type Details"
// @Success 201 {object} util.ServerResponse{data=models.EventTypeResponse}
// @Failure 400,401,404 {object} util.ServerResponse{data=Stub}
// @Security ApiKeyAuth
// @Router /v1/projects/{projectID}/event-types [post]
func (h *Handler) CreateEventType(w http.ResponseWriter, r *http.Request) {
project, err := h.retrieveProject(r)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

var newEventType models.CreateEventType
err = util.ReadJSON(r, &newEventType)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

err = newEventType.Validate()
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

pe := &datastore.ProjectEventType{
ProjectId: project.UID,
Name: newEventType.Name,
ID: ulid.Make().String(),
Category: newEventType.Category,
Description: newEventType.Description,
}

eventTypeRepo := postgres.NewEventTypesRepo(h.A.DB)
err = eventTypeRepo.CreateEventType(r.Context(), pe)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

resp := &models.EventTypeResponse{EventType: pe}
_ = render.Render(w, r, util.NewServerResponse("Event type created successfully", resp, http.StatusCreated))
}

// UpdateEventType
//
// @Summary Updates an event type
// @Description This endpoint updates an event type
// @Id CreateEventType
// @Tags EventTypes
// @Accept json
// @Produce json
// @Param projectID path string true "Project ID"
// @Param eventType body models.UpdateEventType true "Event Type Details"
// @Success 201 {object} util.ServerResponse{data=models.EventTypeResponse}
// @Failure 400,401,404 {object} util.ServerResponse{data=Stub}
// @Security ApiKeyAuth
// @Router /v1/projects/{projectID}/event-types/{eventTypeId} [put]
func (h *Handler) UpdateEventType(w http.ResponseWriter, r *http.Request) {
project, err := h.retrieveProject(r)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

eventTypeId := chi.URLParam(r, "eventTypeId")

var ue models.UpdateEventType
err = util.ReadJSON(r, &ue)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

eventTypeRepo := postgres.NewEventTypesRepo(h.A.DB)
pe, err := eventTypeRepo.FetchEventTypeById(r.Context(), eventTypeId, project.UID)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

if !util.IsStringEmpty(ue.Description) {
pe.Description = ue.Description
}

if !util.IsStringEmpty(ue.Category) {
pe.Category = ue.Category
}

err = eventTypeRepo.UpdateEventType(r.Context(), pe)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

resp := &models.EventTypeResponse{EventType: pe}
_ = render.Render(w, r, util.NewServerResponse("Event type created successfully", resp, http.StatusAccepted))
}

// DeprecateEventType
//
// @Summary Create an event type
// @Description This endpoint creates an event type
// @Id DeprecateEventType
// @Tags EventTypes
// @Accept json
// @Produce json
// @Param projectID path string true "Project ID"
// @Param eventTypeId path string true "Event Type ID"
// @Success 201 {object} util.ServerResponse{data=models.EventTypeResponse}
// @Failure 400,401,404 {object} util.ServerResponse{data=Stub}
// @Security ApiKeyAuth
// @Router /v1/projects/{projectID}/event-types/{eventTypeId}/deprecate [post]
func (h *Handler) DeprecateEventType(w http.ResponseWriter, r *http.Request) {
project, err := h.retrieveProject(r)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

eventTypeId := chi.URLParam(r, "eventTypeId")
eventTypeRepo := postgres.NewEventTypesRepo(h.A.DB)
pe, err := eventTypeRepo.DeprecateEventType(r.Context(), eventTypeId, project.UID)
if err != nil {
_ = render.Render(w, r, util.NewErrorResponse(err.Error(), http.StatusBadRequest))
return
}

resp := &models.EventTypeResponse{EventType: pe}
_ = render.Render(w, r, util.NewServerResponse("Event type deprecated successfully", resp, http.StatusOK))
}
1 change: 0 additions & 1 deletion api/ingest_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ func (i *IngestIntegrationTestSuite) Test_IngestEvent_GoodAPIKey() {
// Act.
i.Router.ServeHTTP(w, req)

fmt.Println("eee", w.Body.String())
// Assert.
require.Equal(i.T(), expectedStatusCode, w.Code)
}
Expand Down
2 changes: 1 addition & 1 deletion api/models/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type CreateEndpoint struct {
AdvancedSignatures *bool `json:"advanced_signatures"`

// Endpoint name.
Name string `json:"name" valid:"required~please provide your endpointName"`
Name string `json:"name" valid:"required~please provide your endpoint name"`

// Endpoint developers support email. This is used for communicating endpoint state
// changes. You should always turn this on when disabling endpoints are enabled.
Expand Down
37 changes: 37 additions & 0 deletions api/models/event_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package models

import (
"github.com/frain-dev/convoy/datastore"
"github.com/frain-dev/convoy/util"
)

type CreateEventType struct {
// Name is the event type name. E.g., invoice.created
Name string `json:"name" valid:"required~please provide a name for this event type"`

// Category is a product-specific grouping for the event type
Category string `json:"category"`

// Description is used to describe what the event type does
Description string `json:"description"`
}

func (ce *CreateEventType) Validate() error {
return util.Validate(ce)
}

type EventTypeResponse struct {
EventType *datastore.ProjectEventType `json:"event_type"`
}

type EventTypeListResponse struct {
EventTypes []datastore.ProjectEventType `json:"event_types"`
}

type UpdateEventType struct {
// Category is a product-specific grouping for the event type
Category string `json:"category"`

// Description is used to describe what the event type does
Description string `json:"description"`
}
Loading

0 comments on commit 7ddb3c1

Please sign in to comment.