Files
wehub-resource-sync 75f3dd141c
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CI and Release / lint-frontend (push) Has been cancelled
CI and Release / dockerfile-scan (push) Has been cancelled
CI and Release / test-frontend (push) Has been cancelled
CI and Release / lint-verification-agent (push) Has been cancelled
CI and Release / test-verification-agent (push) Has been cancelled
CI and Release / e2e-verification-agent (push) Has been cancelled
CI and Release / test-backend (push) Has been cancelled
CI and Release / build-dev-image (push) Has been cancelled
CI and Release / push-dev-image (push) Has been cancelled
CI and Release / build-image (push) Has been cancelled
CI and Release / build-verification-image (push) Has been cancelled
CI and Release / determine-version (push) Has been cancelled
CI and Release / push-image (push) Has been cancelled
CI and Release / push-verification-image (12) (push) Has been cancelled
CI and Release / lint-backend (push) Has been cancelled
CI and Release / push-verification-image (17) (push) Has been cancelled
CI and Release / push-verification-image (18) (push) Has been cancelled
CI and Release / release (push) Has been cancelled
CI and Release / publish-helm-chart (push) Has been cancelled
CI and Release / push-verification-image (13) (push) Has been cancelled
CI and Release / push-verification-image (14) (push) Has been cancelled
CI and Release / push-verification-image (15) (push) Has been cancelled
CI and Release / push-verification-image (16) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:11:07 +08:00

335 lines
9.5 KiB
Go

package notifiers
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
users_middleware "databasus-backend/internal/features/users/middleware"
workspaces_services "databasus-backend/internal/features/workspaces/services"
)
type NotifierController struct {
notifierService *NotifierService
workspaceService *workspaces_services.WorkspaceService
}
func (c *NotifierController) RegisterRoutes(router *gin.RouterGroup) {
router.POST("/notifiers", c.SaveNotifier)
router.GET("/notifiers", c.GetNotifiers)
router.GET("/notifiers/:id", c.GetNotifier)
router.DELETE("/notifiers/:id", c.DeleteNotifier)
router.POST("/notifiers/:id/test", c.SendTestNotification)
router.POST("/notifiers/:id/transfer", c.TransferNotifierToWorkspace)
router.POST("/notifiers/direct-test", c.SendTestNotificationDirect)
}
// SaveNotifier
// @Summary Save a notifier
// @Description Create or update a notifier
// @Tags notifiers
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT token"
// @Param request body Notifier true "Notifier data with workspaceId"
// @Success 200 {object} Notifier
// @Failure 400
// @Failure 401
// @Failure 403
// @Router /notifiers [post]
func (c *NotifierController) SaveNotifier(ctx *gin.Context) {
user, ok := users_middleware.GetUserFromContext(ctx)
if !ok {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
return
}
var request Notifier
if err := ctx.ShouldBindJSON(&request); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if request.WorkspaceID == uuid.Nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "workspaceId is required"})
return
}
if err := c.notifierService.SaveNotifier(user, request.WorkspaceID, &request); err != nil {
if errors.Is(err, ErrInsufficientPermissionsToManageNotifier) {
ctx.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, request)
}
// GetNotifier
// @Summary Get a notifier by ID
// @Description Get a specific notifier by ID
// @Tags notifiers
// @Produce json
// @Param Authorization header string true "JWT token"
// @Param id path string true "Notifier ID"
// @Success 200 {object} Notifier
// @Failure 400
// @Failure 401
// @Failure 403
// @Router /notifiers/{id} [get]
func (c *NotifierController) GetNotifier(ctx *gin.Context) {
user, ok := users_middleware.GetUserFromContext(ctx)
if !ok {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
return
}
id, err := uuid.Parse(ctx.Param("id"))
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "invalid notifier ID"})
return
}
notifier, err := c.notifierService.GetNotifier(user, id)
if err != nil {
if errors.Is(err, ErrInsufficientPermissionsToViewNotifier) {
ctx.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, notifier)
}
// GetNotifiers
// @Summary Get all notifiers
// @Description Get all notifiers for a workspace
// @Tags notifiers
// @Produce json
// @Param Authorization header string true "JWT token"
// @Param workspace_id query string true "Workspace ID"
// @Success 200 {array} Notifier
// @Failure 400
// @Failure 401
// @Failure 403
// @Router /notifiers [get]
func (c *NotifierController) GetNotifiers(ctx *gin.Context) {
user, ok := users_middleware.GetUserFromContext(ctx)
if !ok {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
return
}
workspaceIDStr := ctx.Query("workspace_id")
if workspaceIDStr == "" {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "workspace_id query parameter is required"})
return
}
workspaceID, err := uuid.Parse(workspaceIDStr)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace_id"})
return
}
notifiers, err := c.notifierService.GetNotifiers(user, workspaceID)
if err != nil {
if errors.Is(err, ErrInsufficientPermissionsToViewNotifiers) {
ctx.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, notifiers)
}
// DeleteNotifier
// @Summary Delete a notifier
// @Description Delete a notifier by ID
// @Tags notifiers
// @Produce json
// @Param Authorization header string true "JWT token"
// @Param id path string true "Notifier ID"
// @Success 200
// @Failure 400
// @Failure 401
// @Failure 403
// @Router /notifiers/{id} [delete]
func (c *NotifierController) DeleteNotifier(ctx *gin.Context) {
user, ok := users_middleware.GetUserFromContext(ctx)
if !ok {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
return
}
id, err := uuid.Parse(ctx.Param("id"))
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "invalid notifier ID"})
return
}
if err := c.notifierService.DeleteNotifier(user, id); err != nil {
if errors.Is(err, ErrInsufficientPermissionsToManageNotifier) {
ctx.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"message": "notifier deleted successfully"})
}
// SendTestNotification
// @Summary Send test notification
// @Description Send a test notification using the specified notifier
// @Tags notifiers
// @Produce json
// @Param Authorization header string true "JWT token"
// @Param id path string true "Notifier ID"
// @Success 200
// @Failure 400
// @Failure 401
// @Failure 403
// @Router /notifiers/{id}/test [post]
func (c *NotifierController) SendTestNotification(ctx *gin.Context) {
user, ok := users_middleware.GetUserFromContext(ctx)
if !ok {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
return
}
id, err := uuid.Parse(ctx.Param("id"))
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "invalid notifier ID"})
return
}
if err := c.notifierService.SendTestNotification(user, id); err != nil {
if errors.Is(err, ErrInsufficientPermissionsToTestNotifier) {
ctx.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"message": "test notification sent successfully"})
}
// TransferNotifierToWorkspace
// @Summary Transfer notifier to another workspace
// @Description Transfer a notifier from one workspace to another
// @Tags notifiers
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT token"
// @Param id path string true "Notifier ID"
// @Param request body TransferNotifierRequest true "Target workspace ID"
// @Success 200
// @Failure 400
// @Failure 401
// @Failure 403
// @Router /notifiers/{id}/transfer [post]
func (c *NotifierController) TransferNotifierToWorkspace(ctx *gin.Context) {
user, ok := users_middleware.GetUserFromContext(ctx)
if !ok {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
return
}
id, err := uuid.Parse(ctx.Param("id"))
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "invalid notifier ID"})
return
}
var request TransferNotifierRequest
if err := ctx.ShouldBindJSON(&request); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if request.TargetWorkspaceID == uuid.Nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "targetWorkspaceId is required"})
return
}
if err := c.notifierService.TransferNotifierToWorkspace(
user,
id,
request.TargetWorkspaceID,
nil,
); err != nil {
if errors.Is(err, ErrInsufficientPermissionsInSourceWorkspace) ||
errors.Is(err, ErrInsufficientPermissionsInTargetWorkspace) {
ctx.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"message": "notifier transferred successfully"})
}
// SendTestNotificationDirect
// @Summary Send test notification directly
// @Description Send a test notification using a notifier object provided in the request
// @Tags notifiers
// @Accept json
// @Produce json
// @Param Authorization header string true "JWT token"
// @Param request body Notifier true "Notifier data with workspaceId"
// @Success 200
// @Failure 400
// @Failure 401
// @Failure 403
// @Router /notifiers/direct-test [post]
func (c *NotifierController) SendTestNotificationDirect(ctx *gin.Context) {
user, ok := users_middleware.GetUserFromContext(ctx)
if !ok {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
return
}
var request Notifier
if err := ctx.ShouldBindJSON(&request); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if request.WorkspaceID == uuid.Nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "workspaceId is required"})
return
}
canView, _, err := c.workspaceService.CanUserAccessWorkspace(request.WorkspaceID, user)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if !canView {
ctx.JSON(
http.StatusForbidden,
gin.H{"error": "insufficient permissions to test notifier in this workspace"},
)
return
}
if err := c.notifierService.SendTestNotificationToNotifier(&request); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"message": "test notification sent successfully"})
}