Implement document PATCH operation

This commit is contained in:
Pijus Kamandulis
2024-06-01 19:52:07 +03:00
parent 0cec7816c1
commit 2cd61aa620
9 changed files with 233 additions and 51 deletions

View File

@@ -1,11 +1,14 @@
package handlers
import (
"encoding/json"
"fmt"
"net/http"
jsonpatch "github.com/evanphx/json-patch/v5"
"github.com/gin-gonic/gin"
"github.com/pikami/cosmium/internal/constants"
"github.com/pikami/cosmium/internal/logger"
"github.com/pikami/cosmium/internal/repositories"
repositorymodels "github.com/pikami/cosmium/internal/repository_models"
)
@@ -100,6 +103,82 @@ func ReplaceDocument(c *gin.Context) {
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
}
func PatchDocument(c *gin.Context) {
databaseId := c.Param("databaseId")
collectionId := c.Param("collId")
documentId := c.Param("docId")
document, status := repositories.GetDocument(databaseId, collectionId, documentId)
if status == repositorymodels.StatusNotFound {
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
return
}
var requestBody map[string]interface{}
if err := c.BindJSON(&requestBody); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
return
}
operations := requestBody["operations"]
operationsBytes, err := json.Marshal(operations)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": "Could not decode operations"})
return
}
patch, err := jsonpatch.DecodePatch(operationsBytes)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
return
}
currentDocumentBytes, err := json.Marshal(document)
if err != nil {
logger.Error("Failed to marshal existing document:", err)
c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to marshal existing document"})
return
}
modifiedDocumentBytes, err := patch.Apply(currentDocumentBytes)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
return
}
var modifiedDocument map[string]interface{}
err = json.Unmarshal(modifiedDocumentBytes, &modifiedDocument)
if err != nil {
logger.Error("Failed to unmarshal modified document:", err)
c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to unmarshal modified document"})
return
}
if modifiedDocument["id"] != document["id"] {
c.JSON(http.StatusUnprocessableEntity, gin.H{"message": "The ID field cannot be modified"})
return
}
status = repositories.DeleteDocument(databaseId, collectionId, documentId)
if status == repositorymodels.StatusNotFound {
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
return
}
createdDocument, status := repositories.CreateDocument(databaseId, collectionId, modifiedDocument)
if status == repositorymodels.Conflict {
c.IndentedJSON(http.StatusConflict, gin.H{"message": "Conflict"})
return
}
if status == repositorymodels.StatusOk {
c.IndentedJSON(http.StatusCreated, createdDocument)
return
}
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
}
func DocumentsPost(c *gin.Context) {
databaseId := c.Param("databaseId")
collectionId := c.Param("collId")