feat(notifications): tighten chatwoot scoping
This commit is contained in:
@@ -2,7 +2,9 @@ package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -81,7 +83,9 @@ func (h *NotificationHandler) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
notification, svcErr := h.notificationService.GetNotification(c.Request.Context(), notificationID)
|
||||
accountID := getAccountID(c)
|
||||
userID := getUserID(c)
|
||||
notification, svcErr := h.notificationService.GetNotificationByAccount(c.Request.Context(), notificationID, userID, accountID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
@@ -99,15 +103,10 @@ func (h *NotificationHandler) Update(c *gin.Context) {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid notification id")
|
||||
return
|
||||
}
|
||||
accountID := getAccountID(c)
|
||||
userID := getUserID(c)
|
||||
|
||||
// MarkRead only returns error; need to fetch updated notification for response
|
||||
if svcErr := h.notificationService.MarkRead(c.Request.Context(), notificationID); svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
|
||||
// Return the updated notification (Chatwoot renders json: @notification)
|
||||
notification, svcErr := h.notificationService.GetNotification(c.Request.Context(), notificationID)
|
||||
notification, svcErr := h.notificationService.MarkReadByAccount(c.Request.Context(), notificationID, userID, accountID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
@@ -147,9 +146,10 @@ func (h *NotificationHandler) MarkAllRead(c *gin.Context) {
|
||||
// GET /api/v1/accounts/:account_id/notifications/unread_count
|
||||
// Reference: Chatwoot unread_count — render json: @unread_count
|
||||
func (h *NotificationHandler) UnreadCount(c *gin.Context) {
|
||||
accountID := getAccountID(c)
|
||||
userID := getUserID(c)
|
||||
|
||||
count, err := h.notificationService.GetUnreadCount(c.Request.Context(), userID)
|
||||
count, err := h.notificationService.GetUnreadCountByAccount(c.Request.Context(), userID, accountID)
|
||||
if err != nil {
|
||||
applogger.L().Errorf("UnreadCount notifications: %v", err)
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, "Failed to count unread notifications")
|
||||
@@ -173,14 +173,23 @@ func (h *NotificationHandler) Snooze(c *gin.Context) {
|
||||
userID := getUserID(c)
|
||||
|
||||
var req struct {
|
||||
SnoozedUntil string `json:"snoozed_until"`
|
||||
SnoozedUntil interface{} `json:"snoozed_until"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
if err := bindOptionalNotificationJSON(c, &req); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid request body")
|
||||
return
|
||||
}
|
||||
if req.SnoozedUntil == nil || fmt.Sprint(req.SnoozedUntil) == "" {
|
||||
notification, svcErr := h.notificationService.GetNotificationByAccount(c.Request.Context(), notificationID, userID, accountID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, serializeNotification(notification))
|
||||
return
|
||||
}
|
||||
|
||||
snoozedUntil, parseErr := time.Parse(time.RFC3339, req.SnoozedUntil)
|
||||
snoozedUntil, parseErr := parseNotificationUnixTime(req.SnoozedUntil)
|
||||
if parseErr != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid snoozed_until format")
|
||||
return
|
||||
@@ -227,7 +236,9 @@ func (h *NotificationHandler) Destroy(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if svcErr := h.notificationService.DeleteNotification(c.Request.Context(), notificationID); svcErr != nil {
|
||||
accountID := getAccountID(c)
|
||||
userID := getUserID(c)
|
||||
if svcErr := h.notificationService.DeleteNotificationByAccount(c.Request.Context(), notificationID, userID, accountID); svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
@@ -341,3 +352,26 @@ func bindOptionalNotificationJSON(c *gin.Context, target interface{}) error {
|
||||
}
|
||||
return c.ShouldBindJSON(target)
|
||||
}
|
||||
|
||||
func parseNotificationUnixTime(value interface{}) (time.Time, error) {
|
||||
switch v := value.(type) {
|
||||
case float64:
|
||||
return time.Unix(int64(v), 0).UTC(), nil
|
||||
case int64:
|
||||
return time.Unix(v, 0).UTC(), nil
|
||||
case int:
|
||||
return time.Unix(int64(v), 0).UTC(), nil
|
||||
case string:
|
||||
seconds, err := strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return time.Unix(seconds, 0).UTC(), nil
|
||||
default:
|
||||
seconds, err := strconv.ParseInt(fmt.Sprint(v), 10, 64)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return time.Unix(seconds, 0).UTC(), nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user