From 83bad16462f0c2649821fd6a4213f5975fdaf34f Mon Sep 17 00:00:00 2001 From: Victor Lacasse-Beaudoin Date: Wed, 30 Aug 2023 13:45:07 -0400 Subject: [PATCH] =?UTF-8?q?Ajouter=20de=20l'injection=20de=20d=C3=A9pendan?= =?UTF-8?q?ce=20=C3=A0=20handlers=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api_handlers/api_handlers.go | 153 +++++++---------------------------- cmd/server.go | 21 +++-- 2 files changed, 43 insertions(+), 131 deletions(-) diff --git a/api_handlers/api_handlers.go b/api_handlers/api_handlers.go index 9423f31..11b0fab 100644 --- a/api_handlers/api_handlers.go +++ b/api_handlers/api_handlers.go @@ -10,14 +10,18 @@ import ( "git.agecem.com/agecem/agecem-org/models" "github.com/labstack/echo/v4" "github.com/minio/minio-go/v7" - "github.com/spf13/viper" ) +type V1Handler struct { + Config config.Config + MediaClient *media.MediaClient +} + // API Handlers // HandleV1 affiche les routes accessibles. // Les routes sont triées selon .Path, pour les rendre plus facilement navigables. -func HandleV1(c echo.Context) error { +func (h *V1Handler) HandleV1(c echo.Context) error { routes := c.Echo().Routes() sort.Slice(routes, func(i, j int) bool { return routes[i].Path < routes[j].Path }) return c.JSON(http.StatusOK, routes) @@ -25,19 +29,10 @@ func HandleV1(c echo.Context) error { // HandleV1Seed créé des buckets dans minio selon la liste de buckets dans server.documents.buckets // Les buckets sont créés avec paramètres par défaut, et sont ensuite visible dans /v1/bucket. -func HandleV1Seed(c echo.Context) error { +func (h *V1Handler) HandleV1Seed(c echo.Context) error { var response models.V1SeedResponse - mediaClient, err := media.NewMediaClientFromViper() - if err != nil { - response.StatusCode = http.StatusInternalServerError - response.Message = "Error during media.NewMediaClientFromViper()" - response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - - new_buckets, err := mediaClient.Seed() + new_buckets, err := h.MediaClient.Seed() response.Data.Buckets = new_buckets if err != nil { response.StatusCode = http.StatusInternalServerError @@ -60,31 +55,13 @@ func HandleV1Seed(c echo.Context) error { } // HandleV1BucketList affiche les buckets permis par server.documents.buckets, qui existent. -func HandleV1BucketList(c echo.Context) error { +func (h *V1Handler) HandleV1BucketList(c echo.Context) error { var response models.V1BucketListResponse - var cfg config.Config - if err := viper.Unmarshal(&cfg); err != nil { - response.StatusCode = http.StatusInternalServerError - response.Message = "Error during viper.Unmarshal" - // response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - - mediaClient, err := media.NewMediaClientFromViper() - if err != nil { - response.StatusCode = http.StatusInternalServerError - response.Message = "Error during media.NewMediaClientFromViper()" - // response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - var buckets = make(map[string]string) - for bucket_name, bucket_display_name := range cfg.Server.Documents.Buckets { - exists, err := mediaClient.MinioClient.BucketExists(context.Background(), bucket_name) + for bucket_name, bucket_display_name := range h.Config.Server.Documents.Buckets { + exists, err := h.MediaClient.MinioClient.BucketExists(context.Background(), bucket_name) if err != nil { response.StatusCode = http.StatusInternalServerError response.Message = "Error during minio#BucketExists" @@ -103,24 +80,15 @@ func HandleV1BucketList(c echo.Context) error { response.Data.Buckets = buckets return c.JSON(response.StatusCode, response) - //return c.JSON(response.StatusCode, response.Data.Buckets) } -func HandleV1BucketRead(c echo.Context) error { +func (h *V1Handler) HandleV1BucketRead(c echo.Context) error { var response models.V1BucketReadResponse - var cfg config.Config - if err := viper.Unmarshal(&cfg); err != nil { - response.StatusCode = http.StatusInternalServerError - response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - bucket := c.Param("bucket") allowed := false - for bucket_allowed := range cfg.Server.Documents.Buckets { + for bucket_allowed := range h.Config.Server.Documents.Buckets { if bucket == bucket_allowed { allowed = true } @@ -134,16 +102,7 @@ func HandleV1BucketRead(c echo.Context) error { defer cancel() - mediaClient, err := media.NewMediaClientFromViper() - if err != nil { - response.StatusCode = http.StatusInternalServerError - response.Message = "Error during media.NewMediaClientFromViper()" - response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - - exists, err := mediaClient.MinioClient.BucketExists(ctx, bucket) + exists, err := h.MediaClient.MinioClient.BucketExists(ctx, bucket) if err != nil { response.StatusCode = http.StatusInternalServerError response.Message = "Error during minio#BucketExists" @@ -156,7 +115,7 @@ func HandleV1BucketRead(c echo.Context) error { return c.JSON(models.NotFoundResponse()) } - objectCh := mediaClient.MinioClient.ListObjects(ctx, bucket, minio.ListObjectsOptions{}) + objectCh := h.MediaClient.MinioClient.ListObjects(ctx, bucket, minio.ListObjectsOptions{}) for object := range objectCh { if object.Err != nil { response.StatusCode = http.StatusInternalServerError @@ -177,18 +136,9 @@ func HandleV1BucketRead(c echo.Context) error { } // HandleV1DocumentCreate permet d'ajouter un object dans un bucket, par multipart/form-data -func HandleV1DocumentCreate(c echo.Context) error { +func (h *V1Handler) HandleV1DocumentCreate(c echo.Context) error { var response models.V1DocumentCreateResponse - var cfg config.Config - if err := viper.Unmarshal(&cfg); err != nil { - response.StatusCode = http.StatusInternalServerError - response.Message = "Error during HandleV1DocumentCreate's echo#Context.FormFile" - response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - bucket := c.Param("bucket") form_file, err := c.FormFile("document") @@ -201,7 +151,7 @@ func HandleV1DocumentCreate(c echo.Context) error { } allowed := false - for bucket_allowed := range cfg.Server.Documents.Buckets { + for bucket_allowed := range h.Config.Server.Documents.Buckets { if bucket == bucket_allowed { allowed = true } @@ -215,15 +165,6 @@ func HandleV1DocumentCreate(c echo.Context) error { defer cancel() - mediaClient, err := media.NewMediaClientFromViper() - if err != nil { - response.StatusCode = http.StatusInternalServerError - response.Message = "Error during media.NewMediaClientFromViper()" - response.Error = err.Error() - - return c.JSON(response.StatusCode, response) - } - src, err := form_file.Open() if err != nil { response.StatusCode = http.StatusBadRequest @@ -234,16 +175,7 @@ func HandleV1DocumentCreate(c echo.Context) error { } defer src.Close() - /* - reg, err := regexp.Compile("[^.a-zA-Z0-9_-]+") - if err != nil { - return c.Render(http.StatusInternalServerError, "documentation-html", nil) - } - - filename_processed := reg.ReplaceAllString(form_file.Filename, "") - */ - - info, err := mediaClient.MinioClient.PutObject(ctx, bucket, form_file.Filename, src, form_file.Size, minio.PutObjectOptions{ + 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 { @@ -264,19 +196,12 @@ func HandleV1DocumentCreate(c echo.Context) error { } // HandleV1DocumentRead permet de lire le contenu d'un fichier et protentiellement de le télécharger -func HandleV1DocumentRead(c echo.Context) error { - var cfg config.Config - if err := viper.Unmarshal(&cfg); err != nil { - return c.JSON(http.StatusInternalServerError, map[string]string{ - "error": err.Error(), - }) - } - +func (h *V1Handler) HandleV1DocumentRead(c echo.Context) error { bucket := c.Param("bucket") document := c.Param("document") allowed := false - for bucket_allowed := range cfg.Server.Documents.Buckets { + for bucket_allowed := range h.Config.Server.Documents.Buckets { if bucket == bucket_allowed { allowed = true } @@ -290,15 +215,7 @@ func HandleV1DocumentRead(c echo.Context) error { defer cancel() - mediaClient, err := media.NewMediaClientFromViper() - if err != nil { - return c.JSON(http.StatusInternalServerError, map[string]string{ - "message": "Error during media.NewMediaClientFromViper()", - "error": err.Error(), - }) - } - - bucket_exists, err := mediaClient.MinioClient.BucketExists(ctx, bucket) + bucket_exists, err := h.MediaClient.MinioClient.BucketExists(ctx, bucket) if err != nil { return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists") } @@ -307,7 +224,7 @@ func HandleV1DocumentRead(c echo.Context) error { return c.JSON(models.NotFoundResponse()) } - document_info, err := mediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{}) + document_info, err := h.MediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{}) if err != nil { if err.Error() == "The specified key does not exist." { @@ -322,7 +239,7 @@ func HandleV1DocumentRead(c echo.Context) error { _ = document_info - document_object, err := mediaClient.MinioClient.GetObject(ctx, bucket, document, minio.GetObjectOptions{}) + 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", @@ -340,18 +257,12 @@ func HandleV1DocumentUpdate(c echo.Context) error { } // HandleV1DocumentDelete permet de supprimer un object -func HandleV1DocumentDelete(c echo.Context) error { - var cfg config.Config - if err := viper.Unmarshal(&cfg); err != nil { - return c.JSON(http.StatusInternalServerError, map[string]string{ - "error": err.Error(), - }) - } +func (h *V1Handler) HandleV1DocumentDelete(c echo.Context) error { bucket := c.Param("bucket") document := c.Param("document") allowed := false - for bucket_allowed := range cfg.Server.Documents.Buckets { + for bucket_allowed := range h.Config.Server.Documents.Buckets { if bucket == bucket_allowed { allowed = true } @@ -365,15 +276,7 @@ func HandleV1DocumentDelete(c echo.Context) error { defer cancel() - mediaClient, err := media.NewMediaClientFromViper() - if err != nil { - return c.JSON(http.StatusInternalServerError, map[string]string{ - "message": "Error during media.NewMediaClientFromViper()", - "error": err.Error(), - }) - } - - bucket_exists, err := mediaClient.MinioClient.BucketExists(ctx, bucket) + bucket_exists, err := h.MediaClient.MinioClient.BucketExists(ctx, bucket) if err != nil { return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists") } @@ -382,7 +285,7 @@ func HandleV1DocumentDelete(c echo.Context) error { return c.JSON(models.NotFoundResponse()) } - document_info, err := mediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{}) + document_info, err := h.MediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{}) if err != nil { if err.Error() == "The specified key does not exist." { @@ -397,7 +300,7 @@ func HandleV1DocumentDelete(c echo.Context) error { //TODO Add error validation _ = document_info - err = mediaClient.MinioClient.RemoveObject(ctx, bucket, document, minio.RemoveObjectOptions{}) + 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", diff --git a/cmd/server.go b/cmd/server.go index 831946e..f505ebf 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -197,22 +197,31 @@ func RunServer() { } // API Routes + mediaClient, err := media.NewMediaClientFromViper() + if err != nil { + log.Fatal("Error during NewMediaClientFromViper for API handlers") + } + + v1Handler := api_handlers.V1Handler{ + Config: cfg, + MediaClient: mediaClient, + } groupV1.GET("", api_handlers.HandleV1) - groupV1.POST("/seed", api_handlers.HandleV1Seed) + groupV1.POST("/seed", v1Handler.HandleV1Seed) - groupV1.GET("/bucket", api_handlers.HandleV1BucketList) + groupV1.GET("/bucket", v1Handler.HandleV1BucketList) - groupV1.GET("/bucket/:bucket", api_handlers.HandleV1BucketRead) + groupV1.GET("/bucket/:bucket", v1Handler.HandleV1BucketRead) - groupV1.POST("/bucket/:bucket", api_handlers.HandleV1DocumentCreate) + groupV1.POST("/bucket/:bucket", v1Handler.HandleV1DocumentCreate) - groupV1.GET("/bucket/:bucket/:document", api_handlers.HandleV1DocumentRead) + groupV1.GET("/bucket/:bucket/:document", v1Handler.HandleV1DocumentRead) groupV1.PUT("/bucket/:bucket/:document", api_handlers.HandleV1DocumentUpdate) - groupV1.DELETE("/bucket/:bucket/:document", api_handlers.HandleV1DocumentDelete) + groupV1.DELETE("/bucket/:bucket/:document", v1Handler.HandleV1DocumentDelete) // HTML Routes