Merge pull request 'Ajouter objet Config pour viper.Unmarshal()' (#63) from feature/viper-config-object into main
Reviewed-on: #63
This commit is contained in:
commit
5cef3f47ca
6 changed files with 220 additions and 115 deletions
|
@ -12,6 +12,10 @@ ADD cmd/ cmd/
|
||||||
|
|
||||||
ADD api/ api/
|
ADD api/ api/
|
||||||
|
|
||||||
|
ADD config/ config/
|
||||||
|
|
||||||
|
ADD media/ media/
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o agecem-org .
|
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o agecem-org .
|
||||||
|
|
||||||
# Alpine
|
# Alpine
|
||||||
|
|
12
README.md
12
README.md
|
@ -17,6 +17,18 @@ Le lifecycle du serveur est maintenu par containers, en utilisant `docker-compos
|
||||||
|
|
||||||
### Exemples d'utilisation de docker-compose
|
### Exemples d'utilisation de docker-compose
|
||||||
|
|
||||||
|
*L'exemple suivant assume que minio est déployé par docker-compose en même temps que le serveur web.*
|
||||||
|
|
||||||
|
Remplir .env avec les credentials que minio utilisera pour sa configuration initiale.
|
||||||
|
|
||||||
|
Remplacer `agecem-org` par quelque chose de sécurisé.
|
||||||
|
|
||||||
|
```
|
||||||
|
# .env
|
||||||
|
MINIO_ROOT_USER=agecem-org
|
||||||
|
MINIO_ROOT_PASSWORD=agecem-org
|
||||||
|
```
|
||||||
|
|
||||||
Déployer le ou les containers en mode détaché, en s'assurant de rebâtir l'image.
|
Déployer le ou les containers en mode détaché, en s'assurant de rebâtir l'image.
|
||||||
|
|
||||||
`$ docker-compose up -d --build`
|
`$ docker-compose up -d --build`
|
||||||
|
|
44
cmd/config.go
Normal file
44
cmd/config.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2023 AGECEM
|
||||||
|
*/
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"git.agecem.com/agecem/agecem-org/config"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// configCmd represents the config command
|
||||||
|
var configCmd = &cobra.Command{
|
||||||
|
Use: "config",
|
||||||
|
Short: "Print the config to stdout in indented JSON format",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
var cfg config.Config
|
||||||
|
|
||||||
|
if err := viper.Unmarshal(&cfg); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
printConfig(cfg)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(configCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printConfig(config config.Config) error {
|
||||||
|
buf, err := json.MarshalIndent(config, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(buf))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
183
cmd/server.go
183
cmd/server.go
|
@ -18,11 +18,12 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/minio/minio-go/v7"
|
"github.com/minio/minio-go/v7"
|
||||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"git.agecem.com/agecem/agecem-org/api"
|
"git.agecem.com/agecem/agecem-org/api"
|
||||||
|
"git.agecem.com/agecem/agecem-org/config"
|
||||||
|
"git.agecem.com/agecem/agecem-org/media"
|
||||||
"git.agecem.com/agecem/agecem-org/public"
|
"git.agecem.com/agecem/agecem-org/public"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
|
@ -32,6 +33,8 @@ type Template struct {
|
||||||
templates *template.Template
|
templates *template.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cfg config.Config
|
||||||
|
|
||||||
var embedFS embed.FS
|
var embedFS embed.FS
|
||||||
|
|
||||||
// serverCmd represents the server command
|
// serverCmd represents the server command
|
||||||
|
@ -39,6 +42,10 @@ var serverCmd = &cobra.Command{
|
||||||
Use: "server",
|
Use: "server",
|
||||||
Short: "Démarrer le serveur web",
|
Short: "Démarrer le serveur web",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := viper.Unmarshal(&cfg); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
RunServer()
|
RunServer()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -64,7 +71,7 @@ func init() {
|
||||||
|
|
||||||
// server.documents.access_key_id - --server-documents-access-key-id
|
// server.documents.access_key_id - --server-documents-access-key-id
|
||||||
serverCmd.Flags().String("server-documents-access-key-id", "", "Storage server access key id (config: server.documents.access_key_id)")
|
serverCmd.Flags().String("server-documents-access-key-id", "", "Storage server access key id (config: server.documents.access_key_id)")
|
||||||
viper.BindPFlag("documents.accessKeyID", serverCmd.Flags().Lookup("documents-access-key-id"))
|
viper.BindPFlag("server.documents.access_key_id", serverCmd.Flags().Lookup("server-documents-access-key-id"))
|
||||||
|
|
||||||
// server.documents.secret_access_key - --server-documents-secret-access-key
|
// server.documents.secret_access_key - --server-documents-secret-access-key
|
||||||
serverCmd.Flags().String("server-documents-secret-access-key", "", "Storage server secret access key (config: server.documents.secret_access_key)")
|
serverCmd.Flags().String("server-documents-secret-access-key", "", "Storage server secret access key (config: server.documents.secret_access_key)")
|
||||||
|
@ -114,13 +121,13 @@ func RunServer() {
|
||||||
|
|
||||||
groupV1.Use(middleware.AddTrailingSlash())
|
groupV1.Use(middleware.AddTrailingSlash())
|
||||||
|
|
||||||
if viper.GetBool("server.api.auth") {
|
if cfg.Server.Api.Auth {
|
||||||
if len(viper.GetString("server.api.key")) < 10 {
|
if len(cfg.Server.Api.Key) < 10 {
|
||||||
log.Fatal("server.api.auth is enabled, but server.api.key is too small (needs at least 10 characters)")
|
log.Fatal("server.api.auth is enabled, but server.api.key is too small (needs at least 10 characters)")
|
||||||
}
|
}
|
||||||
|
|
||||||
groupV1.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
|
groupV1.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
|
||||||
return subtle.ConstantTimeCompare([]byte(key), []byte(viper.GetString("server.api.key"))) == 1, nil
|
return subtle.ConstantTimeCompare([]byte(key), []byte(cfg.Server.Api.Key)) == 1, nil
|
||||||
}))
|
}))
|
||||||
|
|
||||||
log.Println("Key auth for /v1 activated")
|
log.Println("Key auth for /v1 activated")
|
||||||
|
@ -130,21 +137,19 @@ func RunServer() {
|
||||||
|
|
||||||
groupAdmin.Use(middleware.AddTrailingSlash())
|
groupAdmin.Use(middleware.AddTrailingSlash())
|
||||||
|
|
||||||
if viper.GetBool("server.admin.auth") {
|
if cfg.Server.Admin.Auth {
|
||||||
username := viper.GetString("server.admin.username")
|
if len(cfg.Server.Admin.Username) < 5 {
|
||||||
password := viper.GetString("server.admin.password")
|
|
||||||
if len(username) < 5 {
|
|
||||||
log.Fatal("server.admin.auth is enabled, but server.admin.username is too small (needs at least 5 characters)")
|
log.Fatal("server.admin.auth is enabled, but server.admin.username is too small (needs at least 5 characters)")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(password) < 10 {
|
if len(cfg.Server.Admin.Password) < 10 {
|
||||||
log.Fatal("server.admin.auth is enabled, but server.admin.password is too small (needs at least 10 characters)")
|
log.Fatal("server.admin.auth is enabled, but server.admin.password is too small (needs at least 10 characters)")
|
||||||
}
|
}
|
||||||
|
|
||||||
groupAdmin.Use(middleware.BasicAuth(func(username_entered, password_entered string, c echo.Context) (bool, error) {
|
groupAdmin.Use(middleware.BasicAuth(func(username_entered, password_entered string, c echo.Context) (bool, error) {
|
||||||
// Be careful to use constant time comparison to prevent timing attacks
|
// Be careful to use constant time comparison to prevent timing attacks
|
||||||
if subtle.ConstantTimeCompare([]byte(username_entered), []byte(username)) == 1 &&
|
if subtle.ConstantTimeCompare([]byte(username_entered), []byte(cfg.Server.Admin.Username)) == 1 &&
|
||||||
subtle.ConstantTimeCompare([]byte(password_entered), []byte(password)) == 1 {
|
subtle.ConstantTimeCompare([]byte(password_entered), []byte(cfg.Server.Admin.Password)) == 1 {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -208,7 +213,7 @@ func RunServer() {
|
||||||
groupAdmin.POST("/documents/upload", handleAdminDocumentsUploadPOST)
|
groupAdmin.POST("/documents/upload", handleAdminDocumentsUploadPOST)
|
||||||
|
|
||||||
e.Logger.Fatal(e.Start(
|
e.Logger.Fatal(e.Start(
|
||||||
fmt.Sprintf(":%d", viper.GetInt("server.port"))))
|
fmt.Sprintf(":%d", cfg.Server.Port)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
||||||
|
@ -228,30 +233,22 @@ func handleV1(c echo.Context) error {
|
||||||
// handleV1Seed créé des buckets dans minio selon la liste de buckets dans server.documents.buckets
|
// 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.
|
// 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 handleV1Seed(c echo.Context) error {
|
||||||
documents_buckets := viper.GetStringSlice("server.documents.buckets")
|
mediaClient, err := media.NewMediaClientFromViper()
|
||||||
documents_endpoint := viper.GetString("server.documents.endpoint")
|
|
||||||
documents_access_key_id := viper.GetString("server.documents.access_key_id")
|
|
||||||
documents_secret_access_key := viper.GetString("server.documents.secret_access_key")
|
|
||||||
documents_use_ssl := viper.GetBool("server.documents.use_ssl")
|
|
||||||
|
|
||||||
// Initialize minio client object
|
|
||||||
client, err := minio.New(documents_endpoint, &minio.Options{
|
|
||||||
Creds: credentials.NewStaticV4(documents_access_key_id, documents_secret_access_key, ""),
|
|
||||||
Secure: documents_use_ssl,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#New",
|
"message": "Error during media.NewMediaClientFromViper()",
|
||||||
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var new_buckets []string
|
var new_buckets []string
|
||||||
|
|
||||||
for _, bucket := range documents_buckets {
|
for _, bucket := range cfg.Server.Documents.Buckets {
|
||||||
exists, err := client.BucketExists(context.Background(), bucket)
|
exists, err := mediaClient.MinioClient.BucketExists(context.Background(), bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#BucketExists",
|
"message": "Error during minio#BucketExists",
|
||||||
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,9 +256,10 @@ func handleV1Seed(c echo.Context) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = client.MakeBucket(context.Background(), bucket, minio.MakeBucketOptions{}); err != nil {
|
if err = mediaClient.MinioClient.MakeBucket(context.Background(), bucket, minio.MakeBucketOptions{}); err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#MakeBucket",
|
"message": "Error during minio#MakeBucket",
|
||||||
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
new_buckets = append(new_buckets, bucket)
|
new_buckets = append(new_buckets, bucket)
|
||||||
|
@ -282,27 +280,18 @@ func handleV1Seed(c echo.Context) error {
|
||||||
|
|
||||||
// handleV1BucketList affiche les buckets permis par server.documents.buckets, qui existent.
|
// handleV1BucketList affiche les buckets permis par server.documents.buckets, qui existent.
|
||||||
func handleV1BucketList(c echo.Context) error {
|
func handleV1BucketList(c echo.Context) error {
|
||||||
documents_buckets := viper.GetStringSlice("server.documents.buckets")
|
mediaClient, err := media.NewMediaClientFromViper()
|
||||||
documents_endpoint := viper.GetString("server.documents.endpoint")
|
|
||||||
documents_access_key_id := viper.GetString("server.documents.access_key_id")
|
|
||||||
documents_secret_access_key := viper.GetString("server.documents.secret_access_key")
|
|
||||||
documents_use_ssl := viper.GetBool("server.documents.use_ssl")
|
|
||||||
|
|
||||||
// Initialize minio client object
|
|
||||||
client, err := minio.New(documents_endpoint, &minio.Options{
|
|
||||||
Creds: credentials.NewStaticV4(documents_access_key_id, documents_secret_access_key, ""),
|
|
||||||
Secure: documents_use_ssl,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#New",
|
"message": "Error during media.NewMediaClientFromViper()",
|
||||||
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var buckets []string
|
var buckets []string
|
||||||
|
|
||||||
for _, bucket_name := range documents_buckets {
|
for _, bucket_name := range cfg.Server.Documents.Buckets {
|
||||||
exists, err := client.BucketExists(context.Background(), bucket_name)
|
exists, err := mediaClient.MinioClient.BucketExists(context.Background(), bucket_name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
||||||
}
|
}
|
||||||
|
@ -316,16 +305,10 @@ func handleV1BucketList(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleV1BucketRead(c echo.Context) error {
|
func handleV1BucketRead(c echo.Context) error {
|
||||||
documents_buckets := viper.GetStringSlice("server.documents.buckets")
|
|
||||||
documents_endpoint := viper.GetString("server.documents.endpoint")
|
|
||||||
documents_access_key_id := viper.GetString("server.documents.access_key_id")
|
|
||||||
documents_secret_access_key := viper.GetString("server.documents.secret_access_key")
|
|
||||||
documents_use_ssl := viper.GetBool("server.documents.use_ssl")
|
|
||||||
|
|
||||||
bucket := c.Param("bucket")
|
bucket := c.Param("bucket")
|
||||||
|
|
||||||
allowed := false
|
allowed := false
|
||||||
for _, bucket_allowed := range documents_buckets {
|
for _, bucket_allowed := range cfg.Server.Documents.Buckets {
|
||||||
if bucket == bucket_allowed {
|
if bucket == bucket_allowed {
|
||||||
allowed = true
|
allowed = true
|
||||||
}
|
}
|
||||||
|
@ -344,18 +327,15 @@ func handleV1BucketRead(c echo.Context) error {
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Initialize minio client object
|
mediaClient, err := media.NewMediaClientFromViper()
|
||||||
client, err := minio.New(documents_endpoint, &minio.Options{
|
|
||||||
Creds: credentials.NewStaticV4(documents_access_key_id, documents_secret_access_key, ""),
|
|
||||||
Secure: documents_use_ssl,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#New",
|
"message": "Error during media.NewMediaClientFromViper()",
|
||||||
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := client.BucketExists(ctx, bucket)
|
exists, err := mediaClient.MinioClient.BucketExists(ctx, bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
||||||
}
|
}
|
||||||
|
@ -366,7 +346,7 @@ func handleV1BucketRead(c echo.Context) error {
|
||||||
|
|
||||||
var keys []string
|
var keys []string
|
||||||
|
|
||||||
objectCh := client.ListObjects(ctx, bucket, minio.ListObjectsOptions{})
|
objectCh := mediaClient.MinioClient.ListObjects(ctx, bucket, minio.ListObjectsOptions{})
|
||||||
for object := range objectCh {
|
for object := range objectCh {
|
||||||
if object.Err != nil {
|
if object.Err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
|
@ -382,12 +362,6 @@ func handleV1BucketRead(c echo.Context) error {
|
||||||
|
|
||||||
// handleV1DocumentCreate permet d'ajouter un object dans un bucket, par multipart/form-data
|
// handleV1DocumentCreate permet d'ajouter un object dans un bucket, par multipart/form-data
|
||||||
func handleV1DocumentCreate(c echo.Context) error {
|
func handleV1DocumentCreate(c echo.Context) error {
|
||||||
documents_buckets := viper.GetStringSlice("server.documents.buckets")
|
|
||||||
documents_endpoint := viper.GetString("server.documents.endpoint")
|
|
||||||
documents_access_key_id := viper.GetString("server.documents.access_key_id")
|
|
||||||
documents_secret_access_key := viper.GetString("server.documents.secret_access_key")
|
|
||||||
documents_use_ssl := viper.GetBool("server.documents.use_ssl")
|
|
||||||
|
|
||||||
bucket := c.Param("bucket")
|
bucket := c.Param("bucket")
|
||||||
|
|
||||||
form_file, err := c.FormFile("document")
|
form_file, err := c.FormFile("document")
|
||||||
|
@ -399,7 +373,7 @@ func handleV1DocumentCreate(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
allowed := false
|
allowed := false
|
||||||
for _, bucket_allowed := range documents_buckets {
|
for _, bucket_allowed := range cfg.Server.Documents.Buckets {
|
||||||
if bucket == bucket_allowed {
|
if bucket == bucket_allowed {
|
||||||
allowed = true
|
allowed = true
|
||||||
}
|
}
|
||||||
|
@ -413,14 +387,11 @@ func handleV1DocumentCreate(c echo.Context) error {
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Initialize minio client object
|
mediaClient, err := media.NewMediaClientFromViper()
|
||||||
client, err := minio.New(documents_endpoint, &minio.Options{
|
|
||||||
Creds: credentials.NewStaticV4(documents_access_key_id, documents_secret_access_key, ""),
|
|
||||||
Secure: documents_use_ssl,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#New",
|
"message": "Error during media.NewMediaClientFromViper()",
|
||||||
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,7 +408,7 @@ func handleV1DocumentCreate(c echo.Context) error {
|
||||||
|
|
||||||
filename_processed := reg.ReplaceAllString(form_file.Filename, "")
|
filename_processed := reg.ReplaceAllString(form_file.Filename, "")
|
||||||
|
|
||||||
info, err := client.PutObject(ctx, bucket, filename_processed, src, form_file.Size, minio.PutObjectOptions{
|
info, err := mediaClient.MinioClient.PutObject(ctx, bucket, filename_processed, src, form_file.Size, minio.PutObjectOptions{
|
||||||
ContentType: form_file.Header.Get("Content-Type"),
|
ContentType: form_file.Header.Get("Content-Type"),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -458,17 +429,11 @@ func handleV1DocumentCreate(c echo.Context) error {
|
||||||
|
|
||||||
// handleV1DocumentRead permet de lire le contenu d'un fichier et protentiellement de le télécharger
|
// handleV1DocumentRead permet de lire le contenu d'un fichier et protentiellement de le télécharger
|
||||||
func handleV1DocumentRead(c echo.Context) error {
|
func handleV1DocumentRead(c echo.Context) error {
|
||||||
documents_buckets := viper.GetStringSlice("server.documents.buckets")
|
|
||||||
documents_endpoint := viper.GetString("server.documents.endpoint")
|
|
||||||
documents_access_key_id := viper.GetString("server.documents.access_key_id")
|
|
||||||
documents_secret_access_key := viper.GetString("server.documents.secret_access_key")
|
|
||||||
documents_use_ssl := viper.GetBool("server.documents.use_ssl")
|
|
||||||
|
|
||||||
bucket := c.Param("bucket")
|
bucket := c.Param("bucket")
|
||||||
document := c.Param("document")
|
document := c.Param("document")
|
||||||
|
|
||||||
allowed := false
|
allowed := false
|
||||||
for _, bucket_allowed := range documents_buckets {
|
for _, bucket_allowed := range cfg.Server.Documents.Buckets {
|
||||||
if bucket == bucket_allowed {
|
if bucket == bucket_allowed {
|
||||||
allowed = true
|
allowed = true
|
||||||
}
|
}
|
||||||
|
@ -487,18 +452,15 @@ func handleV1DocumentRead(c echo.Context) error {
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Initialize minio client object
|
mediaClient, err := media.NewMediaClientFromViper()
|
||||||
client, err := minio.New(documents_endpoint, &minio.Options{
|
|
||||||
Creds: credentials.NewStaticV4(documents_access_key_id, documents_secret_access_key, ""),
|
|
||||||
Secure: documents_use_ssl,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#New",
|
"message": "Error during media.NewMediaClientFromViper()",
|
||||||
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
bucket_exists, err := client.BucketExists(ctx, bucket)
|
bucket_exists, err := mediaClient.MinioClient.BucketExists(ctx, bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
||||||
}
|
}
|
||||||
|
@ -507,7 +469,7 @@ func handleV1DocumentRead(c echo.Context) error {
|
||||||
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
|
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
|
||||||
}
|
}
|
||||||
|
|
||||||
document_info, err := client.StatObject(ctx, bucket, document, minio.StatObjectOptions{})
|
document_info, err := mediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "The specified key does not exist." {
|
if err.Error() == "The specified key does not exist." {
|
||||||
|
@ -522,7 +484,7 @@ func handleV1DocumentRead(c echo.Context) error {
|
||||||
|
|
||||||
_ = document_info
|
_ = document_info
|
||||||
|
|
||||||
document_object, err := client.GetObject(ctx, bucket, document, minio.GetObjectOptions{})
|
document_object, err := mediaClient.MinioClient.GetObject(ctx, bucket, document, minio.GetObjectOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#GetObject",
|
"message": "Error during minio#GetObject",
|
||||||
|
@ -543,17 +505,11 @@ func handleV1DocumentUpdate(c echo.Context) error {
|
||||||
|
|
||||||
// handleV1DocumentDelete permet de supprimer un object
|
// handleV1DocumentDelete permet de supprimer un object
|
||||||
func handleV1DocumentDelete(c echo.Context) error {
|
func handleV1DocumentDelete(c echo.Context) error {
|
||||||
documents_buckets := viper.GetStringSlice("server.documents.buckets")
|
|
||||||
documents_endpoint := viper.GetString("server.documents.endpoint")
|
|
||||||
documents_access_key_id := viper.GetString("server.documents.access_key_id")
|
|
||||||
documents_secret_access_key := viper.GetString("server.documents.secret_access_key")
|
|
||||||
documents_use_ssl := viper.GetBool("server.documents.use_ssl")
|
|
||||||
|
|
||||||
bucket := c.Param("bucket")
|
bucket := c.Param("bucket")
|
||||||
document := c.Param("document")
|
document := c.Param("document")
|
||||||
|
|
||||||
allowed := false
|
allowed := false
|
||||||
for _, bucket_allowed := range documents_buckets {
|
for _, bucket_allowed := range cfg.Server.Documents.Buckets {
|
||||||
if bucket == bucket_allowed {
|
if bucket == bucket_allowed {
|
||||||
allowed = true
|
allowed = true
|
||||||
}
|
}
|
||||||
|
@ -572,18 +528,15 @@ func handleV1DocumentDelete(c echo.Context) error {
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Initialize minio client object
|
mediaClient, err := media.NewMediaClientFromViper()
|
||||||
client, err := minio.New(documents_endpoint, &minio.Options{
|
|
||||||
Creds: credentials.NewStaticV4(documents_access_key_id, documents_secret_access_key, ""),
|
|
||||||
Secure: documents_use_ssl,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#New",
|
"message": "Error during media.NewMediaClientFromViper()",
|
||||||
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
bucket_exists, err := client.BucketExists(ctx, bucket)
|
bucket_exists, err := mediaClient.MinioClient.BucketExists(ctx, bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
return c.JSON(http.StatusInternalServerError, "Error during minio#BucketExists")
|
||||||
}
|
}
|
||||||
|
@ -592,7 +545,7 @@ func handleV1DocumentDelete(c echo.Context) error {
|
||||||
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
|
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
|
||||||
}
|
}
|
||||||
|
|
||||||
document_info, err := client.StatObject(ctx, bucket, document, minio.StatObjectOptions{})
|
document_info, err := mediaClient.MinioClient.StatObject(ctx, bucket, document, minio.StatObjectOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "The specified key does not exist." {
|
if err.Error() == "The specified key does not exist." {
|
||||||
|
|
||||||
|
@ -607,7 +560,7 @@ func handleV1DocumentDelete(c echo.Context) error {
|
||||||
//TODO Add error validation
|
//TODO Add error validation
|
||||||
_ = document_info
|
_ = document_info
|
||||||
|
|
||||||
err = client.RemoveObject(ctx, bucket, document, minio.RemoveObjectOptions{})
|
err = mediaClient.MinioClient.RemoveObject(ctx, bucket, document, minio.RemoveObjectOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
"message": "Error during minio#RemoveObject",
|
"message": "Error during minio#RemoveObject",
|
||||||
|
@ -648,9 +601,9 @@ func handleVieEtudianteOrganisme(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleDocumentation(c echo.Context) error {
|
func handleDocumentation(c echo.Context) error {
|
||||||
client, err := api.New("http", "localhost", viper.GetInt("server.port"), api.APIOptions{
|
client, err := api.New("http", "localhost", cfg.Server.Port, api.APIOptions{
|
||||||
KeyAuth: viper.GetBool("server.api.auth"),
|
KeyAuth: cfg.Server.Api.Auth,
|
||||||
Key: viper.GetString("server.api.key"),
|
Key: cfg.Server.Api.Key,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
return c.Render(http.StatusInternalServerError, "documentation-html", nil)
|
||||||
|
@ -720,9 +673,9 @@ func handleFormulaires(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlePublicDocumentation(c echo.Context) error {
|
func handlePublicDocumentation(c echo.Context) error {
|
||||||
client, err := api.New("http", "localhost", viper.GetInt("server.port"), api.APIOptions{
|
client, err := api.New("http", "localhost", cfg.Server.Port, api.APIOptions{
|
||||||
KeyAuth: viper.GetBool("server.api.auth"),
|
KeyAuth: cfg.Server.Api.Auth,
|
||||||
Key: viper.GetString("server.api.key"),
|
Key: cfg.Server.Api.Key,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
|
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
|
||||||
|
@ -756,12 +709,12 @@ func handleAdminDocumentsUpload(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAdminDocumentsUploadPOST(c echo.Context) error {
|
func handleAdminDocumentsUploadPOST(c echo.Context) error {
|
||||||
client, err := api.New("http", "localhost", viper.GetInt("server.port"), api.APIOptions{
|
client, err := api.New("http", "localhost", cfg.Server.Port, api.APIOptions{
|
||||||
KeyAuth: viper.GetBool("server.api.auth"),
|
KeyAuth: cfg.Server.Api.Auth,
|
||||||
Key: viper.GetString("server.api.key"),
|
Key: cfg.Server.Api.Key,
|
||||||
BasicAuth: viper.GetBool("server.admin.auth"),
|
BasicAuth: cfg.Server.Admin.Auth,
|
||||||
Username: viper.GetString("server.admin.username"),
|
Username: cfg.Server.Admin.Username,
|
||||||
Password: viper.GetString("server.admin.password"),
|
Password: cfg.Server.Admin.Password,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Render(http.StatusInternalServerError, "admin-upload-html", struct{ Message string }{Message: fmt.Sprintf("handleAdminDocumentsUploadPOST#api.New: %s", err)})
|
return c.Render(http.StatusInternalServerError, "admin-upload-html", struct{ Message string }{Message: fmt.Sprintf("handleAdminDocumentsUploadPOST#api.New: %s", err)})
|
||||||
|
|
38
config/config.go
Normal file
38
config/config.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
/*
|
||||||
|
Permet de contenir la configuration obtenue par cobra/viper
|
||||||
|
|
||||||
|
Example d'utilisation sans error handling:
|
||||||
|
|
||||||
|
```
|
||||||
|
var cfg config.Config
|
||||||
|
viper.Unmarshal(&cfg)
|
||||||
|
```
|
||||||
|
|
||||||
|
`cfg` devrait alors contenir la configuration, et les données peuvent être
|
||||||
|
obtenues simplement en utilisant la dot (.) notation
|
||||||
|
*/
|
||||||
|
type Config struct {
|
||||||
|
Server struct {
|
||||||
|
Admin struct {
|
||||||
|
Auth bool `mapstructure:"auth"`
|
||||||
|
Password string `mapstructure:"password"`
|
||||||
|
Username string `mapstructure:"username"`
|
||||||
|
} `mapstructure:"admin"`
|
||||||
|
Api struct {
|
||||||
|
Auth bool `mapstructure:"auth"`
|
||||||
|
Key string `mapstructure:"key"`
|
||||||
|
} `mapstructure:"api"`
|
||||||
|
Documents struct {
|
||||||
|
AccessKeyId string `mapstructure:"access_key_id"`
|
||||||
|
Buckets []string `mapstructure:"buckets"`
|
||||||
|
Endpoint string `mapstructure:"endpoint"`
|
||||||
|
SecretAccessKey string `mapstructure:"secret_access_key"`
|
||||||
|
UseSSL bool `mapstructure:"use_ssl"`
|
||||||
|
KeyId string `mapstructure:"keyid"`
|
||||||
|
KeyValue string `mapstructure:"keyvalue"`
|
||||||
|
} `mapstructure:"documents"`
|
||||||
|
Port int `mapstructure:"port"`
|
||||||
|
} `mapstructure:"server"`
|
||||||
|
}
|
54
media/media.go
Normal file
54
media/media.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package media
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.agecem.com/agecem/agecem-org/config"
|
||||||
|
"github.com/minio/minio-go/v7"
|
||||||
|
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewMediaClient(endpoint, accessKeyId, secretAccessKey string, useSSL bool) (*MediaClient, error) {
|
||||||
|
if accessKeyId == "" {
|
||||||
|
return nil, errors.New("accessKeyId was found empty, but cannot be")
|
||||||
|
}
|
||||||
|
|
||||||
|
if secretAccessKey == "" {
|
||||||
|
return nil, errors.New("secretAccessKey was found empty, but cannot be")
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaClient MediaClient
|
||||||
|
minioClient, err := minio.New(endpoint, &minio.Options{
|
||||||
|
Creds: credentials.NewStaticV4(accessKeyId, secretAccessKey, ""),
|
||||||
|
Secure: useSSL,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return &mediaClient, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaClient.MinioClient = *minioClient
|
||||||
|
return &mediaClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMediaClientFromViper() (*MediaClient, error) {
|
||||||
|
var cfg config.Config
|
||||||
|
if err := viper.Unmarshal(&cfg); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaClient, err := NewMediaClient(cfg.Server.Documents.Endpoint, cfg.Server.Documents.AccessKeyId, cfg.Server.Documents.SecretAccessKey, cfg.Server.Documents.UseSSL)
|
||||||
|
if err != nil {
|
||||||
|
return mediaClient, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return mediaClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MediaClient struct {
|
||||||
|
MinioClient minio.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MediaClient) foo() string {
|
||||||
|
return "bar"
|
||||||
|
}
|
Loading…
Reference in a new issue