Initial commit: breakpilot-core - Shared Infrastructure
Docker Compose with 24+ services: - PostgreSQL (PostGIS), Valkey, MinIO, Qdrant - Vault (PKI/TLS), Nginx (Reverse Proxy) - Backend Core API, Consent Service, Billing Service - RAG Service, Embedding Service - Gitea, Woodpecker CI/CD - Night Scheduler, Health Aggregator - Jitsi (Web/XMPP/JVB/Jicofo), Mailpit Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
203
consent-service/internal/handlers/notification_handlers.go
Normal file
203
consent-service/internal/handlers/notification_handlers.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/breakpilot/consent-service/internal/middleware"
|
||||
"github.com/breakpilot/consent-service/internal/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// NotificationHandler handles notification-related requests
|
||||
type NotificationHandler struct {
|
||||
notificationService *services.NotificationService
|
||||
}
|
||||
|
||||
// NewNotificationHandler creates a new notification handler
|
||||
func NewNotificationHandler(notificationService *services.NotificationService) *NotificationHandler {
|
||||
return &NotificationHandler{
|
||||
notificationService: notificationService,
|
||||
}
|
||||
}
|
||||
|
||||
// GetNotifications returns notifications for the current user
|
||||
func (h *NotificationHandler) GetNotifications(c *gin.Context) {
|
||||
userID, err := middleware.GetUserID(c)
|
||||
if err != nil || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
||||
return
|
||||
}
|
||||
|
||||
// Parse query parameters
|
||||
limit := 20
|
||||
offset := 0
|
||||
unreadOnly := false
|
||||
|
||||
if l := c.Query("limit"); l != "" {
|
||||
if parsed, err := strconv.Atoi(l); err == nil && parsed > 0 {
|
||||
limit = parsed
|
||||
}
|
||||
}
|
||||
if o := c.Query("offset"); o != "" {
|
||||
if parsed, err := strconv.Atoi(o); err == nil && parsed >= 0 {
|
||||
offset = parsed
|
||||
}
|
||||
}
|
||||
if u := c.Query("unread_only"); u == "true" {
|
||||
unreadOnly = true
|
||||
}
|
||||
|
||||
notifications, total, err := h.notificationService.GetUserNotifications(c.Request.Context(), userID, limit, offset, unreadOnly)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch notifications"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"notifications": notifications,
|
||||
"total": total,
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
})
|
||||
}
|
||||
|
||||
// GetUnreadCount returns the count of unread notifications
|
||||
func (h *NotificationHandler) GetUnreadCount(c *gin.Context) {
|
||||
userID, err := middleware.GetUserID(c)
|
||||
if err != nil || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
||||
return
|
||||
}
|
||||
|
||||
count, err := h.notificationService.GetUnreadCount(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get unread count"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"unread_count": count})
|
||||
}
|
||||
|
||||
// MarkAsRead marks a notification as read
|
||||
func (h *NotificationHandler) MarkAsRead(c *gin.Context) {
|
||||
userID, err := middleware.GetUserID(c)
|
||||
if err != nil || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
||||
return
|
||||
}
|
||||
|
||||
notificationID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid notification ID"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.notificationService.MarkAsRead(c.Request.Context(), userID, notificationID); err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Notification not found or already read"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Notification marked as read"})
|
||||
}
|
||||
|
||||
// MarkAllAsRead marks all notifications as read
|
||||
func (h *NotificationHandler) MarkAllAsRead(c *gin.Context) {
|
||||
userID, err := middleware.GetUserID(c)
|
||||
if err != nil || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.notificationService.MarkAllAsRead(c.Request.Context(), userID); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to mark notifications as read"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "All notifications marked as read"})
|
||||
}
|
||||
|
||||
// DeleteNotification deletes a notification
|
||||
func (h *NotificationHandler) DeleteNotification(c *gin.Context) {
|
||||
userID, err := middleware.GetUserID(c)
|
||||
if err != nil || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
||||
return
|
||||
}
|
||||
|
||||
notificationID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid notification ID"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.notificationService.DeleteNotification(c.Request.Context(), userID, notificationID); err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Notification not found"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Notification deleted"})
|
||||
}
|
||||
|
||||
// GetPreferences returns notification preferences for the user
|
||||
func (h *NotificationHandler) GetPreferences(c *gin.Context) {
|
||||
userID, err := middleware.GetUserID(c)
|
||||
if err != nil || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
||||
return
|
||||
}
|
||||
|
||||
prefs, err := h.notificationService.GetPreferences(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get preferences"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, prefs)
|
||||
}
|
||||
|
||||
// UpdatePreferences updates notification preferences for the user
|
||||
func (h *NotificationHandler) UpdatePreferences(c *gin.Context) {
|
||||
userID, err := middleware.GetUserID(c)
|
||||
if err != nil || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid user"})
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
EmailEnabled *bool `json:"email_enabled"`
|
||||
PushEnabled *bool `json:"push_enabled"`
|
||||
InAppEnabled *bool `json:"in_app_enabled"`
|
||||
ReminderFrequency *string `json:"reminder_frequency"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
|
||||
return
|
||||
}
|
||||
|
||||
// Get current preferences
|
||||
prefs, _ := h.notificationService.GetPreferences(c.Request.Context(), userID)
|
||||
|
||||
// Update only provided fields
|
||||
if req.EmailEnabled != nil {
|
||||
prefs.EmailEnabled = *req.EmailEnabled
|
||||
}
|
||||
if req.PushEnabled != nil {
|
||||
prefs.PushEnabled = *req.PushEnabled
|
||||
}
|
||||
if req.InAppEnabled != nil {
|
||||
prefs.InAppEnabled = *req.InAppEnabled
|
||||
}
|
||||
if req.ReminderFrequency != nil {
|
||||
prefs.ReminderFrequency = *req.ReminderFrequency
|
||||
}
|
||||
|
||||
if err := h.notificationService.UpdatePreferences(c.Request.Context(), userID, prefs); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update preferences"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Preferences updated", "preferences": prefs})
|
||||
}
|
||||
Reference in New Issue
Block a user