diff --git a/app/src/pages/admin/AdminPostView.tsx b/app/src/pages/admin/AdminPostView.tsx index bf24890..f01cb6a 100644 --- a/app/src/pages/admin/AdminPostView.tsx +++ b/app/src/pages/admin/AdminPostView.tsx @@ -138,7 +138,7 @@ const ROLE_TO_STATUS_API: Record = { // Maps URL role param → API segment for the comment endpoint const ROLE_TO_COMMENT_API: Record = { faculty: 'faculty_posts', - warden: 'wardens_posts', + warden: 'warden_posts', centrehead: 'centrehead_posts', }; diff --git a/handlers/admin_comment.go b/handlers/admin_comment.go index 7c2026a..170079f 100644 --- a/handlers/admin_comment.go +++ b/handlers/admin_comment.go @@ -24,6 +24,27 @@ type CommentType struct { // AdminGetComments ///////////////////////////////////////////////////////////////////// +// AdminGetComments fetches all comments made by the logged-in admin. +func (h *AdminHandler) AdminGetComments(c *gin.Context) { + emailID, exists := c.Get(middleware.EmailKey) + if !exists { + c.JSON(401, gin.H{"error": "permission denied"}) + return + } + + var comments []models.Comment + result := h.DB.Where("email = ?", emailID).Find(&comments) + if result.Error != nil { + c.JSON(500, gin.H{"error": "failed to fetch comments"}) + return + } + + c.JSON(200, gin.H{ + "success": "comments fetched", + "comments": comments, + }) +} + // AdminPost comment allow any admin comment on any type of post. // Common for all type of admins and posts. @@ -103,3 +124,123 @@ func (h *AdminHandler) AdminPostComment(c *gin.Context) { c.JSON(201, gin.H{"success": "comment posted!"}) } + +// AdminEditComment allows an admin to edit their own comment. +func (h *AdminHandler) AdminEditComment(c *gin.Context) { + // verify the admin + emailID, exists := c.Get(middleware.EmailKey) + if !exists { + c.JSON(401, gin.H{"error": "permission denied"}) + return + } + + var inputs CommentType + if err := c.ShouldBindJSON(&inputs); err != nil { + c.JSON(400, gin.H{"error": "invalid request body"}) + return + } + + postType := c.Param("type") + postIDString := c.Param("id") + postID, err := strconv.ParseUint(postIDString, 10, 64) + if err != nil { + c.JSON(400, gin.H{"error": "invalid post id"}) + return + } + + commentIDString := c.Param("comment_id") + commentID, err := strconv.ParseUint(commentIDString, 10, 64) + if err != nil { + c.JSON(400, gin.H{"error": "invalid comment id"}) + return + } + + var comment models.Comment + result := h.DB.Where("id = ?", commentID).Take(&comment) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + c.JSON(404, gin.H{"error": "comment not found"}) + return + } + c.JSON(500, gin.H{"error": "internal server error"}) + return + } + + if comment.CommentableType != postType || comment.CommentableID != uint(postID) { + c.JSON(400, gin.H{"error": "comment does not belong to this post"}) + return + } + + // Verify that the comment belongs to this admin + if comment.Email != emailID { + c.JSON(403, gin.H{"error": "you are not authorized to edit this comment"}) + return + } + + // Update the comment + comment.Content = inputs.Content + comment.UpdatedAt = time.Now() + + result = h.DB.Save(&comment) + if result.Error != nil { + c.JSON(500, gin.H{"error": "failed to update comment"}) + return + } + + c.JSON(200, gin.H{"success": "comment updated!"}) +} + +// AdminDeleteComment allows an admin to delete their own comment. +func (h *AdminHandler) AdminDeleteComment(c *gin.Context) { + // verify the admin + emailID, exists := c.Get(middleware.EmailKey) + if !exists { + c.JSON(401, gin.H{"error": "permission denied"}) + return + } + + postType := c.Param("type") + postIDString := c.Param("id") + postID, err := strconv.ParseUint(postIDString, 10, 64) + if err != nil { + c.JSON(400, gin.H{"error": "invalid post id"}) + return + } + + commentIDString := c.Param("comment_id") + commentID, err := strconv.ParseUint(commentIDString, 10, 64) + if err != nil { + c.JSON(400, gin.H{"error": "invalid comment id"}) + return + } + + var comment models.Comment + result := h.DB.Where("id = ?", commentID).Take(&comment) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + c.JSON(404, gin.H{"error": "comment not found"}) + return + } + c.JSON(500, gin.H{"error": "internal server error"}) + return + } + + if comment.CommentableType != postType || comment.CommentableID != uint(postID) { + c.JSON(400, gin.H{"error": "comment does not belong to this post"}) + return + } + + // Verify that the comment belongs to this admin + if comment.Email != emailID { + c.JSON(403, gin.H{"error": "you are not authorized to delete this comment"}) + return + } + + result = h.DB.Delete(&comment) + if result.Error != nil { + c.JSON(500, gin.H{"error": "failed to delete comment"}) + return + } + + c.JSON(200, gin.H{"success": "comment deleted!"}) +} diff --git a/routes/admin.go b/routes/admin.go index 13678f1..b158a57 100644 --- a/routes/admin.go +++ b/routes/admin.go @@ -10,7 +10,10 @@ func AdminRoutes (e *gin.Engine, h *handlers.AdminHandler) { // e.POST("/api/auth/admin/signup", h.AdminSignup) // not to be used as an public API e.POST("/api/auth/admin/login", h.AdminLogin) + e.GET("/api/admin/comments", middleware.IsAuthenticated(), h.AdminGetComments) e.POST("/api/admin/comment/:type/:id", middleware.IsAuthenticated(), h.AdminPostComment) + e.PATCH("/api/admin/comment/:type/:id/:comment_id", middleware.IsAuthenticated(), h.AdminEditComment) + e.DELETE("/api/admin/comment/:type/:id/:comment_id", middleware.IsAuthenticated(), h.AdminDeleteComment) // keep separate apis for updating status stage := e.Group("/api/admin") @@ -23,9 +26,9 @@ func AdminRoutes (e *gin.Engine, h *handlers.AdminHandler) { // get the posts according to the status posts := e.Group("/api/admin") { - posts.GET("xen/posts", middleware.IsAuthenticated(), h.GetXENPosts) - posts.GET("ae/posts", middleware.IsAuthenticated(), h.GetAEPosts) - posts.GET("je/posts", middleware.IsAuthenticated(), h.GetJEPosts) + posts.GET("/xen/posts", middleware.IsAuthenticated(), h.GetXENPosts) + posts.GET("/ae/posts", middleware.IsAuthenticated(), h.GetAEPosts) + posts.GET("/je/posts", middleware.IsAuthenticated(), h.GetJEPosts) } // for any post