Skip to content

Commit

Permalink
[sprint-1][EA-3] image: upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Duchieuctk41 committed Feb 3, 2024
1 parent 188fa52 commit 4e62934
Show file tree
Hide file tree
Showing 22 changed files with 602 additions and 20 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@

.idea
/config/config.yml
app.env
32 changes: 32 additions & 0 deletions cmd/infrastructure/cloudinary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package infrastructure

import (
"context"
"github.com/cloudinary/cloudinary-go/v2"
)

type Cloudinary struct {
*cloudinary.Cloudinary
}

func NewCloudinary() *Cloudinary {
cld, _ := credentials()
return &Cloudinary{
cld,
}
}

func credentials() (*cloudinary.Cloudinary, context.Context) {
// Add your Cloudinary credentials, set configuration parameter
// Secure=true to return "https" URLs, and create a context
//===================
cld, err := cloudinary.New()
if err != nil {
panic(err)
}
// CLOUDINARY_URL=cloudinary://API-Key:API-Secret@Cloud-name
// CLOUDINARY_URL=cloudinary://oZ47iHrgrFQq4fe7ksKKlo7tg4A:991793784142871@dsr2xnaj7
cld.Config.URL.Secure = true
ctx := context.Background()
return cld, ctx
}
2 changes: 1 addition & 1 deletion cmd/infrastructure/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ package infrastructure

import "go.uber.org/fx"

var Module = fx.Options(fx.Provide(NewDatabase))
var Module = fx.Options(fx.Provide(NewDatabase, NewCloudinary))
101 changes: 101 additions & 0 deletions cmd/lib/cloudinary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package lib

import (
"context"
"erp/cmd/infrastructure"
"erp/config"
"fmt"
"github.com/cloudinary/cloudinary-go/v2/api"
"github.com/cloudinary/cloudinary-go/v2/api/admin"
"github.com/cloudinary/cloudinary-go/v2/api/uploader"
"go.uber.org/zap"
"mime/multipart"
)

type CloudinaryRepository interface {
UploadFileCloud(ctx context.Context, file *multipart.FileHeader) (resp *uploader.UploadResult, err error)
GetAssetInfo(ctx context.Context)
TransformImage(ctx context.Context)
}

type cloudinaryRepository struct {
cld *infrastructure.Cloudinary
config *config.Config
logger *zap.Logger
}

func NewCloudinaryRepository(cld *infrastructure.Cloudinary, logger *zap.Logger, config *config.Config) CloudinaryRepository {
return &cloudinaryRepository{
cld: cld,
config: config,
logger: logger,
}
}

func (r *cloudinaryRepository) UploadFileCloud(ctx context.Context, file *multipart.FileHeader) (resp *uploader.UploadResult, err error) {

// SaveFile the cloudinary.
// Set the asset's public ID and allow overwriting the asset with new versions
resp, err = r.cld.Upload.Upload(ctx, file, uploader.UploadParams{
PublicID: r.config.Cloudinary.PublicId,
UniqueFilename: api.Bool(false),
Overwrite: api.Bool(true)})
if err != nil {
fmt.Println("error")
}

return resp, err
}

func (r *cloudinaryRepository) GetAssetInfo(ctx context.Context) {
// Get and use details of the cloudinary
// ==============================
resp, err := r.cld.Admin.Asset(ctx, admin.AssetParams{PublicID: r.config.Cloudinary.PublicId})
if err != nil {
fmt.Println("error")
}
fmt.Println("****3. Get and use details of the cloudinary****\nDetailed response:\n", resp, "\n")

// Assign tags to the uploaded cloudinary based on its width. Save the response to the update in the variable 'update_resp'.
if resp.Width > 900 {
updateResp, err := r.cld.Admin.UpdateAsset(ctx, admin.UpdateAssetParams{
PublicID: r.config.Cloudinary.PublicId,
Tags: []string{"large"}})
if err != nil {
fmt.Println("error")
} else {
// Log the new tag to the console.
fmt.Println("New tag: ", updateResp.Tags, "\n")
}
} else {
updateResp, err := r.cld.Admin.UpdateAsset(ctx, admin.UpdateAssetParams{
PublicID: r.config.Cloudinary.PublicId,
Tags: []string{"small"}})
if err != nil {
fmt.Println("error")
} else {
// Log the new tag to the console.
fmt.Println("New tag: ", updateResp.Tags, "\n")
}
}

}

func (r *cloudinaryRepository) TransformImage(ctx context.Context) {
// Instantiate an object for the asset with public ID "my_image"
qs_img, err := r.cld.Image("quickstart_butterfly")
if err != nil {
fmt.Println("error")
}

// Add the transformation
qs_img.Transformation = "r_max/e_sepia"

// Generate and log the delivery URL
new_url, err := qs_img.String()
if err != nil {
fmt.Println("error")
} else {
print("****4. Transform the image****\nTransfrmation URL: ", new_url, "\n")
}
}
2 changes: 1 addition & 1 deletion cmd/lib/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ package lib

import "go.uber.org/fx"

var Module = fx.Options(fx.Provide(NewZapLogger, NewServer, NewServerGroup))
var Module = fx.Options(fx.Provide(NewZapLogger, NewServer, NewServerGroup, NewCloudinaryRepository))
2 changes: 1 addition & 1 deletion cmd/lib/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Handler struct {

func NewServerGroup(instance *gin.Engine) *Handler {
return &Handler{
instance.Group("/handler/"),
instance.Group("/api/"),
}
}

Expand Down
2 changes: 2 additions & 0 deletions config/app.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ENV=local
CLOUDINARY_URL=cloudinary://991793784142871:oZ47iHrgrFQq4fe7ksKKlo7tg4A@dsr2xnaj7
2 changes: 2 additions & 0 deletions config/app.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ENV=***
CLOUDINARY_URL=cloudinary://***
85 changes: 71 additions & 14 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"erp/utils/constants"
"fmt"
"os"
"reflect"

"github.com/gin-gonic/gin"
"github.com/spf13/viper"
Expand All @@ -16,22 +17,31 @@ var (
configType = "yml"
)

var (
configEnv = "./config/app.env"
configTypeEnv = "env"
configEnvName = "app"
)

type (
Config struct {
Debug bool `mapstructure:"debug"`
ContextTimeout int `mapstructure:"contextTimeout"`
Server Server `mapstructure:"server"`
Services Services `mapstructure:"services"`
Database Database `mapstructure:"database"`
Logger Logger `mapstructure:"logger"`
Jwt Jwt `mapstructure:"jwt"`
Env Env `mapstructure:"env"`
Debug bool `mapstructure:"debug"`
ContextTimeout int `mapstructure:"contextTimeout"`
Server Server `mapstructure:"server"`
Services Services `mapstructure:"services"`
Database Database `mapstructure:"database"`
Logger Logger `mapstructure:"logger"`
Jwt Jwt `mapstructure:"jwt"`
Cloudinary Cloudinary `mapstructure:"cloudinary"`
}

Server struct {
Host string `mapstructure:"host"`
Env string `mapstructure:"env"`
UseRedis bool `mapstructure:"useRedis"`
Port int `mapstructure:"port"`
Host string `mapstructure:"host"`
Env string `mapstructure:"env"`
UseRedis bool `mapstructure:"useRedis"`
Port int `mapstructure:"port"`
UploadPath string `mapstructure:"uploadPath"`
}

Database struct {
Expand All @@ -45,6 +55,11 @@ type (
TimeZone string `mapstructure:"timeZone"`
}

Env struct {
Env string `mapstructure:"ENV"`
CloudinaryURL string `mapstructure:"CLOUDINARY_URL"`
}

Jwt struct {
Secret string `mapstructure:"secret"`
AccessTokenExpiresIn int64 `mapstructure:"accessTokenExpiresIn"`
Expand All @@ -59,18 +74,60 @@ type (

Services struct {
}

Cloudinary struct {
CloudName string `mapstructure:"cloudName"`
ApiKey string `mapstructure:"apiKey"`
ApiSecret string `mapstructure:"apiSecret"`
PublicId string `mapstructure:"publicId"`
URL string `mapstructure:"url"`
}
)

func initEnv(conf *Config) {
if err := LoadConfigEnv(configEnv, configTypeEnv); err != nil {
fmt.Printf("unable decode into config struct, %v", err)
}
if err := UnmarsharConfig(&conf.Env); err != nil {
fmt.Printf("unable decode into config struct, %v", err)
}
SetEnv(conf)
}

func NewConfig() *Config {
initConfig()
conf := &Config{}
err := viper.Unmarshal(conf)
if err != nil {
initEnv(conf)
initConfig()
if err := UnmarsharConfig(conf); err != nil {
fmt.Printf("unable decode into config struct, %v", err)
}
return conf
}

func LoadConfigEnv(configFile, configType string) (err error) {
viper.SetConfigType(configType)
viper.SetConfigFile(configFile)

if err = viper.ReadInConfig(); err != nil {
fmt.Println(err.Error())
}
return
}

func UnmarsharConfig[E any](config *E) error {
return viper.Unmarshal(config)

}

func SetEnv(config *Config) {
v := reflect.ValueOf(config.Env)
for i := 0; i < v.NumField(); i++ {
if v.Field(i).Interface() != "" {
os.Setenv(v.Type().Field(i).Tag.Get("mapstructure"), v.Field(i).Interface().(string))
}
}
}

func initConfig() {
var configFile string
switch os.Getenv("ENV") {
Expand Down
21 changes: 21 additions & 0 deletions domain/upload.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package domain

import (
"encoding/json"
uuid "github.com/satori/go.uuid"
)

type File struct {
BaseModel
FileName string `json:"file_name" gorm:"column:file_name;type:varchar(50);not null"`
Path string `json:"path" gorm:"column:path;type:varchar(255);not null"`
Size int64 `json:"size" gorm:"column:size;type:bigint;not null"`
ExtensionName string `json:"type" gorm:"column:extension_name;type:varchar(10);not null"`
Data json.RawMessage `json:"domain" gorm:"column:data;type:jsonb;" swaggertype:"string"` // save domain flexibly
UserId uuid.UUID `json:"user_id" gorm:"column:user_id;type:uuid"`
User User `json:"user" gorm:"foreignKey:UserId; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}

func (File) TableName() string {
return "files"
}
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ require (
require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/cloudinary/cloudinary-go/v2 v2.7.0 // indirect
github.com/creasty/defaults v1.5.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/gorilla/schema v1.2.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,14 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudinary/cloudinary-go/v2 v2.7.0 h1:8Fuh/SOen6IQgqH8CLso2E+kuKi2xjbdiyXOspwXFTM=
github.com/cloudinary/cloudinary-go/v2 v2.7.0/go.mod h1:jtSxa6xbzvu4IwChRJVDcXwVXrTRczhbvq3Z1VSoFdk=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creasty/defaults v1.5.1 h1:j8WexcS3d/t4ZmllX4GEkl4wIB/trOr035ajcLHCISM=
github.com/creasty/defaults v1.5.1/go.mod h1:FPZ+Y0WNrbqOVw+c6av63eyHUAl6pMHZwqLPvXUZGfY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -91,6 +95,7 @@ github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
Expand Down Expand Up @@ -151,13 +156,18 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/heimdalr/dag v1.0.1/go.mod h1:t+ZkR+sjKL4xhlE1B9rwpvwfo+x+2R0363efS+Oghns=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
Expand Down
Loading

0 comments on commit 4e62934

Please sign in to comment.