From 3fb83b06105766b9cd8e1a205fd2c7f7eb6988c2 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Tue, 11 Feb 2025 22:02:15 -0500 Subject: [PATCH] Update Circle model to include webhook URL field --- internal/circle/model/model.go | 2 +- internal/circle/repo/repository.go | 4 +++ internal/events/producer.go | 16 +++++------ internal/user/handler.go | 46 ++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/internal/circle/model/model.go b/internal/circle/model/model.go index e8b9e38..53e26cb 100644 --- a/internal/circle/model/model.go +++ b/internal/circle/model/model.go @@ -14,7 +14,7 @@ type Circle struct { UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` // Updated at InviteCode string `json:"invite_code" gorm:"column:invite_code"` // Invite code Disabled bool `json:"disabled" gorm:"column:disabled"` // Disabled - WebhookURL *string `json:"-" gorm:"column:webhook_url"` // Webhook URL + WebhookURL *string `json:"webhook_url" gorm:"column:webhook_url"` // Webhook URL } type CircleDetail struct { diff --git a/internal/circle/repo/repository.go b/internal/circle/repo/repository.go index 36aba93..2e4f9c8 100644 --- a/internal/circle/repo/repository.go +++ b/internal/circle/repo/repository.go @@ -167,3 +167,7 @@ func (r *CircleRepository) RedeemPoints(c context.Context, circleID int, userID } return nil } + +func (r *CircleRepository) SetWebhookURL(c context.Context, circleID int, webhookURL *string) error { + return r.db.WithContext(c).Model(&cModel.Circle{}).Where("id = ?", circleID).Update("webhook_url", webhookURL).Error +} diff --git a/internal/events/producer.go b/internal/events/producer.go index 527b8d4..bd38f59 100644 --- a/internal/events/producer.go +++ b/internal/events/producer.go @@ -24,14 +24,14 @@ const ( type EventType string const ( - EventTypeUnknown EventType = "" - EventTypeTaskCreated EventType = "task.created" - EventTypeTaskReminder EventType = "task.reminder" - EventTypeTaskUpdated EventType = "task.updated" - EventTypeTaskCompleted EventType = "task.completed" - EventTypeTaskReassigned EventType = "task.reassigned" - EventTypeTaskSkipped EventType = "task.skipped" - EventTypeThingChanged EventType = "thing.changed" + EventTypeUnknown EventType = "" + // EventTypeTaskCreated EventType = "task.created" + EventTypeTaskReminder EventType = "task.reminder" + // EventTypeTaskUpdated EventType = "task.updated" + EventTypeTaskCompleted EventType = "task.completed" + // EventTypeTaskReassigned EventType = "task.reassigned" + EventTypeTaskSkipped EventType = "task.skipped" + EventTypeThingChanged EventType = "thing.changed" ) type Event struct { diff --git a/internal/user/handler.go b/internal/user/handler.go index ca83933..8759cda 100644 --- a/internal/user/handler.go +++ b/internal/user/handler.go @@ -686,6 +686,51 @@ func (h *Handler) updateUserPasswordLoggedInOnly(c *gin.Context) { c.JSON(http.StatusOK, gin.H{}) } +func (h *Handler) setWebhook(c *gin.Context) { + currentUser, ok := auth.CurrentUser(c) + if !ok { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get current user"}) + return + } + + type Request struct { + URL *string `json:"url"` + } + + var req Request + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + // get circle admins + admins, err := h.circleRepo.GetCircleAdmins(c, currentUser.CircleID) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get circle details"}) + return + } + + // confirm that the user is an admin: + isAdmin := false + for _, admin := range admins { + if admin.ID == currentUser.ID { + isAdmin = true + break + } + } + if !isAdmin { + c.JSON(http.StatusForbidden, gin.H{"error": "You are not an admin"}) + return + } + + err = h.circleRepo.SetWebhookURL(c, currentUser.CircleID, req.URL) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to set webhook URL"}) + return + } + c.JSON(http.StatusOK, gin.H{}) +} + func Routes(router *gin.Engine, h *Handler, auth *jwt.GinJWTMiddleware, limiter *limiter.Limiter) { userRoutes := router.Group("api/v1/users") @@ -697,6 +742,7 @@ func Routes(router *gin.Engine, h *Handler, auth *jwt.GinJWTMiddleware, limiter userRoutes.POST("/tokens", h.CreateLongLivedToken) userRoutes.GET("/tokens", h.GetAllUserToken) userRoutes.DELETE("/tokens/:id", h.DeleteUserToken) + userRoutes.PUT("/webhook", h.setWebhook) userRoutes.PUT("/targets", h.UpdateNotificationTarget) userRoutes.PUT("change_password", h.updateUserPasswordLoggedInOnly)