Skip to content

Commit

Permalink
feat(server): add update notifications and get unread notification count
Browse files Browse the repository at this point in the history
  • Loading branch information
lareii committed Sep 19, 2024
1 parent 1e2b7ad commit ef91bd6
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 0 deletions.
27 changes: 27 additions & 0 deletions server/handlers/me/get_unreads.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package me

import (
"github.com/gofiber/fiber/v2"
"github.com/lareii/copl.uk/server/models"
)

func GetUnreadNotifications(c *fiber.Ctx) error {
user, ok := c.Locals("user").(models.User)
if !ok {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "User not authenticated.",
})
}

unreads, err := models.GetUnreadNotifications(user.ID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error fetching unread notifications.",
})
}

return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "Unread notifications fetched.",
"unreads": unreads,
})
}
66 changes: 66 additions & 0 deletions server/handlers/me/update_notifications.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package me

import (
"github.com/gofiber/fiber/v2"
"github.com/lareii/copl.uk/server/models"
"github.com/lareii/copl.uk/server/utils"
"go.mongodb.org/mongo-driver/bson/primitive"
)

type UpdateNotificationBody struct {
Read *bool `json:"read" validate:"required"`
}

func UpdateNotification(c *fiber.Ctx) error {
user, ok := c.Locals("user").(models.User)
if !ok {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "User not authenticated.",
})
}

var body UpdateNotificationBody
if err := c.BodyParser(&body); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid request body.",
})
}

if err := utils.Validate.Struct(&body); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Missing or invalid fields.",
})
}

id := c.Params("id")
notificationID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid notification ID.",
})
}

notification, err := models.GetNotificationByID(notificationID)
if err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"message": "Error fetching notification.",
})
}

if notification.TargetUserID != user.ID {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "User not authorized.",
})
}

err = models.UpdateNotification(notificationID, *body.Read)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error updating notification.",
})
}

return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "Notification updated.",
})
}
34 changes: 34 additions & 0 deletions server/models/notifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/lareii/copl.uk/server/database"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)

Expand All @@ -21,6 +22,15 @@ type Notification struct {
Read bool `bson:"read" json:"read"`
}

func GetNotificationByID(notificationID primitive.ObjectID) (notification Notification, err error) {
err = database.Notifications.FindOne(context.Background(), bson.M{"_id": notificationID}).Decode(&notification)
if err != nil && err == mongo.ErrNoDocuments {
return notification, nil
}

return notification, err
}

func GetNotifications(limit, offset int64, userID primitive.ObjectID) ([]Notification, error) {
var notifications []Notification
cursor, err := database.Notifications.Find(context.Background(),
Expand All @@ -42,6 +52,18 @@ func GetNotifications(limit, offset int64, userID primitive.ObjectID) ([]Notific
return notifications, nil
}

func GetUnreadNotifications(userID primitive.ObjectID) (int64, error) {
count, err := database.Notifications.CountDocuments(context.Background(), bson.M{
"target_user_id": userID,
"read": false,
})
if err != nil {
return 0, fmt.Errorf("error counting unread notifications: %v", err)
}

return count, nil
}

func CreateNotification(notification Notification) error {
notification.ID = primitive.NewObjectID()
notification.CreatedAt = primitive.Timestamp{T: uint32(time.Now().Unix())}
Expand All @@ -54,3 +76,15 @@ func CreateNotification(notification Notification) error {

return nil
}

func UpdateNotification(notificationID primitive.ObjectID, read bool) error {
_, err := database.Notifications.UpdateOne(context.Background(),
bson.M{"_id": notificationID},
bson.M{"$set": bson.M{"read": read}},
)
if err != nil {
return fmt.Errorf("error updating notification: %v", err)
}

return nil
}
2 changes: 2 additions & 0 deletions server/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func SetupRouter(app *fiber.App) {
meGroup.Patch("/", middlewares.AuthMiddleware(), middlewares.RateLimiterMiddleware(10, 60), me.UpdateUser)
meGroup.Get("/feed", middlewares.AuthMiddleware(), middlewares.RateLimiterMiddleware(20, 60), me.GetFeed)
meGroup.Get("/notifications", middlewares.AuthMiddleware(), middlewares.RateLimiterMiddleware(20, 60), me.GetNotifications)
meGroup.Patch("/notifications/:id", middlewares.AuthMiddleware(), me.UpdateNotification)
meGroup.Get("/notifications/unread", middlewares.AuthMiddleware(), me.GetUnreadNotifications)

userGroup := app.Group("/users")
userGroup.Get("/", middlewares.AuthMiddleware(), middlewares.RateLimiterMiddleware(20, 60), users.GetUsers)
Expand Down

0 comments on commit ef91bd6

Please sign in to comment.