package api import ( "fmt" "log" "net/http" "strconv" "time" "srs.epita.fr/fic-server/libfic" "github.com/gin-gonic/gin" ) func declareQARoutes(router *gin.RouterGroup) { exercicesRoutes := router.Group("/qa") exercicesRoutes.GET("", getExerciceQA) exercicesRoutes.POST("", createExerciceQA) qaRoutes := exercicesRoutes.Group("/:qid") qaRoutes.Use(qaHandler) qaRoutes.PUT("", updateExerciceQA) qaRoutes.DELETE("", deleteExerciceQA) qaRoutes.GET("comments", getQAComments) qaRoutes.POST("comments", createQAComment) commentsRoutes := qaRoutes.Group("comments/:cid") commentsRoutes.Use(qaCommentHandler) commentsRoutes.DELETE("", deleteQAComment) } func qaHandler(c *gin.Context) { var qa *fic.QAQuery qid, err := strconv.ParseInt(string(c.Param("qid")), 10, 64) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad QA identifier."}) return } if exercice, ok := c.Get("exercice"); ok { qa, err = exercice.(*fic.Exercice).GetQAQuery(qid) } else { qa, err = fic.GetQAQuery(qid) } if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "QA entry not found."}) return } c.Set("qa", qa) c.Next() } func qaCommentHandler(c *gin.Context) { qa := c.MustGet("qa").(*fic.QAQuery) var comment *fic.QAComment if cid, err := strconv.ParseInt(string(c.Param("cid")), 10, 64); err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad comment identifier."}) return } else if comment, err = qa.GetComment(cid); err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Comment entry not found."}) return } c.Set("comment", comment) c.Next() } func getExerciceQA(c *gin.Context) { exercice := c.MustGet("exercice").(*fic.Exercice) qa, err := exercice.GetQAQueries() if err != nil { log.Println("Unable to GetQAQueries: ", err.Error()) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to list QA entries: %s", err.Error())}) return } c.JSON(http.StatusOK, qa) } type QAQueryAndComment struct { *fic.QAQuery Content string `json:"content"` } func createExerciceQA(c *gin.Context) { teamid := c.MustGet("LoggedTeam").(int64) ficteam := c.MustGet("LoggedUser").(string) // Create a new query var uq QAQueryAndComment if err := c.ShouldBindJSON(&uq); err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) return } if len(uq.State) == 0 { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "State not filled"}) return } if len(uq.Subject) == 0 { if uq.State == "ok" { tmp := time.Now() uq.Subject = "RAS" uq.Solved = &tmp } else { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Subject not filled"}) return } } exercice := c.MustGet("exercice").(*fic.Exercice) qa, err := exercice.NewQAQuery(uq.Subject, &teamid, ficteam, uq.State, uq.Solved) if err != nil { log.Println("Unable to NewQAQuery: ", err.Error()) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Unable to create the new QA query. Please retry."}) return } if len(uq.Content) > 0 { _, err = qa.AddComment(uq.Content, &teamid, ficteam) if err != nil { log.Println("Unable to AddComment: ", err.Error()) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "QA entry added successfully, but unable to create the associated comment. Please retry."}) return } } c.JSON(http.StatusOK, qa) } func updateExerciceQA(c *gin.Context) { query := c.MustGet("qa").(*fic.QAQuery) var uq *fic.QAQuery if err := c.ShouldBindJSON(&uq); err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) return } uq.Id = query.Id if uq.User != query.User && (uq.IdExercice != query.IdExercice || uq.IdTeam != query.IdTeam || uq.User != query.User || uq.Creation != query.Creation || uq.State != query.State || uq.Subject != query.Subject || uq.Closed != query.Closed) { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "You can only update your own entry."}) return } _, err := uq.Update() if err != nil { log.Println("Unable to Update QAQuery:", err.Error()) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Unable to update the query. Please try again."}) return } c.JSON(http.StatusOK, uq) } func deleteExerciceQA(c *gin.Context) { query := c.MustGet("qa").(*fic.QAQuery) user := c.MustGet("LoggedUser").(string) if user != query.User { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "You can only delete your own entry."}) return } _, err := query.Delete() if err != nil { log.Println("Unable to Delete QAQuery:", err.Error()) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to delete the query. Please try again."}) return } c.JSON(http.StatusNoContent, nil) } func getQAComments(c *gin.Context) { query := c.MustGet("qa").(*fic.QAQuery) comments, err := query.GetComments() if err != nil { log.Println("Unable to GetComments: ", err.Error()) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to list comments: %s", err.Error())}) return } c.JSON(http.StatusOK, comments) } func createQAComment(c *gin.Context) { // Create a new query var uc *fic.QAComment if err := c.ShouldBindJSON(&uc); err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) return } if len(uc.Content) == 0 { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Empty comment."}) return } teamid := c.MustGet("LoggedTeam").(int64) ficteam := c.MustGet("LoggedUser").(string) query := c.MustGet("qa").(*fic.QAQuery) comment, err := query.AddComment(uc.Content, &teamid, ficteam) if err != nil { log.Println("Unable to AddComment: ", err.Error()) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to add your comment. Please try again later."}) return } c.JSON(http.StatusOK, comment) } func deleteQAComment(c *gin.Context) { ficteam := c.MustGet("LoggedUser").(string) comment := c.MustGet("comment").(*fic.QAComment) if ficteam != comment.User { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "You can only delete your own comment."}) return } _, err := comment.Delete() if err != nil { log.Println("Unable to Delete QAComment:", err.Error()) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to delete the comment. Please try again."}) return } c.JSON(http.StatusNoContent, nil) }