From 9a8a0abe2ea0b802ed306efe004a6a3084b34370 Mon Sep 17 00:00:00 2001 From: Victor Lacasse-Beaudoin Date: Mon, 20 Nov 2023 15:36:27 -0500 Subject: [PATCH] =?UTF-8?q?change!:=20renommer=20HandleV1DocumentCreate=20?= =?UTF-8?q?=C3=A0=20V1DocumentPOST?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING: renommer `HandleV1DocumentCreate` à `V1DocumentPOST` --- api/api.go | 4 +- apihandler/apihandler.go | 179 ------------------------------------- apihandler/document.go | 187 +++++++++++++++++++++++++++++++++++++++ apiresponse/document.go | 2 +- cmd/server.go | 2 +- 5 files changed, 191 insertions(+), 183 deletions(-) create mode 100644 apihandler/document.go diff --git a/api/api.go b/api/api.go index c648440..c1e49e3 100644 --- a/api/api.go +++ b/api/api.go @@ -36,8 +36,8 @@ func New(client *http.Client, host, key string, port int, protocol string) (*API return &API{Voki: voki.New(client, host, key, port, protocol)}, nil } -func (a *API) UploadDocument(bucket string, file_header *multipart.FileHeader) (apiresponse.V1DocumentCreate, error) { - var response apiresponse.V1DocumentCreate +func (a *API) UploadDocument(bucket string, file_header *multipart.FileHeader) (apiresponse.V1DocumentPOST, error) { + var response apiresponse.V1DocumentPOST endpoint := fmt.Sprintf("%s://%s:%d", a.Voki.Protocol, a.Voki.Host, diff --git a/apihandler/apihandler.go b/apihandler/apihandler.go index b810cc9..7118b3d 100644 --- a/apihandler/apihandler.go +++ b/apihandler/apihandler.go @@ -1,7 +1,6 @@ package apihandler import ( - "context" "net/http" "sort" @@ -10,7 +9,6 @@ import ( "git.agecem.com/agecem/agecem-org/config" "git.agecem.com/agecem/agecem-org/media" "github.com/labstack/echo/v4" - "github.com/minio/minio-go/v7" ) type V1Handler struct { @@ -55,180 +53,3 @@ func (h *V1Handler) HandleV1Seed(c echo.Context) error { return c.JSON(response.StatusCode, response) } - -// HandleV1DocumentCreate permet d'ajouter un object dans un bucket, par multipart/form-data -func (h *V1Handler) HandleV1DocumentCreate(c echo.Context) error { - var response apiresponse.V1DocumentCreate - - bucket := c.Param("bucket") - - form_file, err := c.FormFile("document") - if err != nil { - response.StatusCode = http.StatusBadRequest - response.Message = "Error during HandleV1DocumentCreate's echo#Context.FormFile" - response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - - allowed := false - for bucket_allowed := range h.Config.Server.Documents.Buckets { - if bucket == bucket_allowed { - allowed = true - } - } - - if !allowed { - return c.JSON(apiresponse.NotFoundResponse()) - } - - ctx, cancel := context.WithCancel(context.Background()) - - defer cancel() - - src, err := form_file.Open() - if err != nil { - response.StatusCode = http.StatusBadRequest - response.Message = "Error during form_file.Open()" - response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - defer src.Close() - - info, err := h.MediaClient.MinioClient.PutObject(ctx, bucket, form_file.Filename, src, form_file.Size, minio.PutObjectOptions{ - ContentType: form_file.Header.Get("Content-Type"), - }) - if err != nil { - response.StatusCode = http.StatusInternalServerError - response.Message = "Error during minio#PutObject" - //response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - - response.StatusCode = http.StatusOK - response.Message = "ok" - response.Data.Bucket = info.Bucket - response.Data.Key = info.Key - response.Data.Size = info.Size - - return c.JSON(response.StatusCode, response) -} - -// HandleV1DocumentRead permet de lire le contenu d'un fichier et protentiellement de le télécharger -func (h *V1Handler) HandleV1DocumentRead(c echo.Context) error { - bucket := c.Param("bucket") - document := c.Param("document") - - allowed := false - for bucket_allowed := range h.Config.Server.Documents.Buckets { - if bucket == bucket_allowed { - allowed = true - } - } - - if !allowed { - return c.JSON(apiresponse.NotFoundResponse()) - } - - ctx, cancel := context.WithCancel(context.Background()) - - defer cancel() - - bucket_exists, err := h.MediaClient.MinioClient.BucketExists(ctx, bucket) - if err != nil { - return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists") - } - - if !bucket_exists { - return c.JSON(apiresponse.NotFoundResponse()) - } - - document_info, err := h.MediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{}) - - if err != nil { - if err.Error() == "The specified key does not exist." { - - return c.JSON(apiresponse.NotFoundResponse()) - } - - return c.JSON(http.StatusInternalServerError, map[string]interface{}{ - "message": "Error during minio#StatObject", - }) - } - - _ = document_info - - document_object, err := h.MediaClient.MinioClient.GetObject(ctx, bucket, document, minio.GetObjectOptions{}) - if err != nil { - return c.JSON(http.StatusInternalServerError, map[string]string{ - "message": "Error during minio#GetObject", - }) - } - - defer document_object.Close() - - return c.Stream(http.StatusOK, document_info.ContentType, document_object) -} - -// HandleV1DocumentUpdate permet de mettre à jour certains champs d'un object, comme le Content-Type ou le Filename -func (h *V1Handler) HandleV1DocumentUpdate(c echo.Context) error { - return c.JSON(apiresponse.NotImplementedResponse()) -} - -// HandleV1DocumentDelete permet de supprimer un object -func (h *V1Handler) HandleV1DocumentDelete(c echo.Context) error { - bucket := c.Param("bucket") - document := c.Param("document") - - allowed := false - for bucket_allowed := range h.Config.Server.Documents.Buckets { - if bucket == bucket_allowed { - allowed = true - } - } - - if !allowed { - return c.JSON(apiresponse.NotFoundResponse()) - } - - ctx, cancel := context.WithCancel(context.Background()) - - defer cancel() - - bucket_exists, err := h.MediaClient.MinioClient.BucketExists(ctx, bucket) - if err != nil { - return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists") - } - - if !bucket_exists { - return c.JSON(apiresponse.NotFoundResponse()) - } - - document_info, err := h.MediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{}) - if err != nil { - if err.Error() == "The specified key does not exist." { - - return c.JSON(apiresponse.NotFoundResponse()) - } - - return c.JSON(http.StatusInternalServerError, map[string]interface{}{ - "message": "Error during minio#StatObject", - }) - } - - //TODO Add error validation - _ = document_info - - err = h.MediaClient.MinioClient.RemoveObject(ctx, bucket, document, minio.RemoveObjectOptions{}) - if err != nil { - return c.JSON(http.StatusInternalServerError, map[string]string{ - "message": "Error during minio#RemoveObject", - }) - } - - return c.JSON(http.StatusOK, map[string]string{ - "message": "Document deleted", - }) -} diff --git a/apihandler/document.go b/apihandler/document.go new file mode 100644 index 0000000..60f9b6c --- /dev/null +++ b/apihandler/document.go @@ -0,0 +1,187 @@ +package apihandler + +import ( + "context" + "net/http" + + "git.agecem.com/agecem/agecem-org/apiresponse" + "github.com/labstack/echo/v4" + "github.com/minio/minio-go/v7" +) + +// V1DocumentPOST permet d'ajouter un object dans un bucket, par multipart/form-data +func (h *V1Handler) V1DocumentPOST(c echo.Context) error { + var response apiresponse.V1DocumentPOST + + bucket := c.Param("bucket") + + form_file, err := c.FormFile("document") + if err != nil { + response.StatusCode = http.StatusBadRequest + response.Message = "Error during HandleV1DocumentCreate's echo#Context.FormFile" + response.Error = err.Error() + + return c.JSON(response.StatusCode, response) + } + + allowed := false + for bucket_allowed := range h.Config.Server.Documents.Buckets { + if bucket == bucket_allowed { + allowed = true + } + } + + if !allowed { + return c.JSON(apiresponse.NotFoundResponse()) + } + + ctx, cancel := context.WithCancel(context.Background()) + + defer cancel() + + src, err := form_file.Open() + if err != nil { + response.StatusCode = http.StatusBadRequest + response.Message = "Error during form_file.Open()" + response.Error = err.Error() + + return c.JSON(response.StatusCode, response) + } + defer src.Close() + + info, err := h.MediaClient.MinioClient.PutObject(ctx, bucket, form_file.Filename, src, form_file.Size, minio.PutObjectOptions{ + ContentType: form_file.Header.Get("Content-Type"), + }) + if err != nil { + response.StatusCode = http.StatusInternalServerError + response.Message = "Error during minio#PutObject" + //response.Error = err.Error() + + return c.JSON(response.StatusCode, response) + } + + response.StatusCode = http.StatusOK + response.Message = "ok" + response.Data.Bucket = info.Bucket + response.Data.Key = info.Key + response.Data.Size = info.Size + + return c.JSON(response.StatusCode, response) +} + +// HandleV1DocumentRead permet de lire le contenu d'un fichier et protentiellement de le télécharger +func (h *V1Handler) HandleV1DocumentRead(c echo.Context) error { + bucket := c.Param("bucket") + document := c.Param("document") + + allowed := false + for bucket_allowed := range h.Config.Server.Documents.Buckets { + if bucket == bucket_allowed { + allowed = true + } + } + + if !allowed { + return c.JSON(apiresponse.NotFoundResponse()) + } + + ctx, cancel := context.WithCancel(context.Background()) + + defer cancel() + + bucket_exists, err := h.MediaClient.MinioClient.BucketExists(ctx, bucket) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists") + } + + if !bucket_exists { + return c.JSON(apiresponse.NotFoundResponse()) + } + + document_info, err := h.MediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{}) + + if err != nil { + if err.Error() == "The specified key does not exist." { + + return c.JSON(apiresponse.NotFoundResponse()) + } + + return c.JSON(http.StatusInternalServerError, map[string]interface{}{ + "message": "Error during minio#StatObject", + }) + } + + _ = document_info + + document_object, err := h.MediaClient.MinioClient.GetObject(ctx, bucket, document, minio.GetObjectOptions{}) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{ + "message": "Error during minio#GetObject", + }) + } + + defer document_object.Close() + + return c.Stream(http.StatusOK, document_info.ContentType, document_object) +} + +// HandleV1DocumentUpdate permet de mettre à jour certains champs d'un object, comme le Content-Type ou le Filename +func (h *V1Handler) HandleV1DocumentUpdate(c echo.Context) error { + return c.JSON(apiresponse.NotImplementedResponse()) +} + +// HandleV1DocumentDelete permet de supprimer un object +func (h *V1Handler) HandleV1DocumentDelete(c echo.Context) error { + bucket := c.Param("bucket") + document := c.Param("document") + + allowed := false + for bucket_allowed := range h.Config.Server.Documents.Buckets { + if bucket == bucket_allowed { + allowed = true + } + } + + if !allowed { + return c.JSON(apiresponse.NotFoundResponse()) + } + + ctx, cancel := context.WithCancel(context.Background()) + + defer cancel() + + bucket_exists, err := h.MediaClient.MinioClient.BucketExists(ctx, bucket) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists") + } + + if !bucket_exists { + return c.JSON(apiresponse.NotFoundResponse()) + } + + document_info, err := h.MediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{}) + if err != nil { + if err.Error() == "The specified key does not exist." { + + return c.JSON(apiresponse.NotFoundResponse()) + } + + return c.JSON(http.StatusInternalServerError, map[string]interface{}{ + "message": "Error during minio#StatObject", + }) + } + + //TODO Add error validation + _ = document_info + + err = h.MediaClient.MinioClient.RemoveObject(ctx, bucket, document, minio.RemoveObjectOptions{}) + if err != nil { + return c.JSON(http.StatusInternalServerError, map[string]string{ + "message": "Error during minio#RemoveObject", + }) + } + + return c.JSON(http.StatusOK, map[string]string{ + "message": "Document deleted", + }) +} diff --git a/apiresponse/document.go b/apiresponse/document.go index 3e99d70..75c15e3 100644 --- a/apiresponse/document.go +++ b/apiresponse/document.go @@ -1,6 +1,6 @@ package apiresponse -type V1DocumentCreate struct { +type V1DocumentPOST struct { Response Data struct { Bucket string diff --git a/cmd/server.go b/cmd/server.go index 1b93e1f..ae431fb 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -234,7 +234,7 @@ func RunServer() { groupV1.GET("/bucket/:bucket", v1Handler.V1BucketGET) - groupV1.POST("/bucket/:bucket", v1Handler.HandleV1DocumentCreate) + groupV1.POST("/bucket/:bucket", v1Handler.V1DocumentPOST) groupV1.GET("/bucket/:bucket/:document", v1Handler.HandleV1DocumentRead)