Skip to content

Commit

Permalink
updated file uploader
Browse files Browse the repository at this point in the history
  • Loading branch information
kayprogrammer committed Dec 5, 2024
1 parent 55ee61a commit 6b41428
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 109 deletions.
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,7 @@ BOOK_COVER_IMAGES_BUCKET=
USER_IMAGES_BUCKET=
ID_FRONT_IMAGES_BUCKET=
ID_BACK_IMAGES_BUCKET=
PGADMIN_PASSWORD=
PGADMIN_PASSWORD=
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
17 changes: 6 additions & 11 deletions config/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,12 @@ type Config struct {
StripeCheckoutSuccessUrlPath string `mapstructure:"STRIPE_CHECKOUT_SUCCESS_URL_PATH"`
StripeWebhookSecret string `mapstructure:"STRIPE_WEBHOOK_SECRET"`
SocketSecret string `mapstructure:"SOCKET_SECRET"`
S3AccessKey string `mapstructure:"S3_ACCESS_KEY"`
S3SecretKey string `mapstructure:"S3_SECRET_KEY"`
S3EndpointUrl string `mapstructure:"S3_ENDPOINT_URL"`
BookCoverImagesBucket string `mapstructure:"BOOK_COVER_IMAGES_BUCKET"`
UserImagesBucket string `mapstructure:"USER_IMAGES_BUCKET"`
IDFrontImagesBucket string `mapstructure:"ID_FRONT_IMAGES_BUCKET"`
IDBackImagesBucket string `mapstructure:"ID_BACK_IMAGES_BUCKET"`
ICPPrivateKey string `mapstructure:"ICP_PRIVATE_KEY"`
ICPPublicKey string `mapstructure:"ICP_PUBLIC_KEY"`

PGAdminPassword string `mapstructure:"PGADMIN_PASSWORD"`
ICPPrivateKey string `mapstructure:"ICP_PRIVATE_KEY"`
ICPPublicKey string `mapstructure:"ICP_PUBLIC_KEY"`
PGAdminPassword string `mapstructure:"PGADMIN_PASSWORD"`
CloudinaryCloudName string `mapstructure:"CLOUDINARY_CLOUD_NAME"`
CloudinaryApiKey string `mapstructure:"CLOUDINARY_API_KEY"`
CloudinaryApiSecret string `mapstructure:"CLOUDINARY_API_SECRET"`
}

func GetConfig() (config Config) {
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ require (
github.com/aviate-labs/leb128 v0.3.0 // indirect
github.com/aviate-labs/secp256k1 v0.0.0-5e6736a // indirect
github.com/bits-and-blooms/bitset v1.7.0 // indirect
github.com/cloudinary/cloudinary-go/v2 v2.9.0 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e // indirect
github.com/creasty/defaults v1.7.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
Expand All @@ -60,6 +62,7 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/gorilla/schema v1.4.1 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHl
github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudinary/cloudinary-go/v2 v2.9.0 h1:8C76QklmuV4qmKAC7cUnu9D68X9kCkFMuLspPikECCo=
github.com/cloudinary/cloudinary-go/v2 v2.9.0/go.mod h1:ireC4gqVetsjVhYlwjUJwKTbZuWjEIynbR9zQTlqsvo=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e h1:MKdOuCiy2DAX1tMp2YsmtNDaqdigpY6B5cZQDJ9BvEo=
github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdBA=
github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
Expand Down Expand Up @@ -174,6 +178,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA=
github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4=
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
github.com/gosimple/slug v1.14.0 h1:RtTL/71mJNDfpUbCOmnf/XFkzKRtD6wL6Uy+3akm4Es=
github.com/gosimple/slug v1.14.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ=
github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o=
Expand Down
19 changes: 13 additions & 6 deletions managers/books.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,21 @@ func (b BookManager) Create(db *gorm.DB, author models.User, data schemas.BookCr
return book
}

func (b BookManager) Update(db *gorm.DB, book models.Book, data schemas.BookCreateSchema, genre models.Genre, Tags []models.Tag) models.Book {
func (b BookManager) Update(db *gorm.DB, book models.Book, data schemas.BookCreateSchema, genre models.Genre, coverImage string, Tags []models.Tag) models.Book {
book.Title = data.Title
book.Blurb = data.Blurb
book.AgeDiscretion = data.AgeDiscretion
book.GenreID = genre.ID
book.Genre = genre
book.Tags = Tags
if coverImage != "" {
book.CoverImage = coverImage
}
db.Omit("Tags.*").Save(&book)
return book
}

func (b BookManager) SetContract(db *gorm.DB, book models.Book, data schemas.ContractCreateSchema) models.Book {
func (b BookManager) SetContract(db *gorm.DB, book models.Book, idFrontImage string, idBackImage string, data schemas.ContractCreateSchema) models.Book {
book.FullName = data.FullName
book.Email = data.Email
book.PenName = data.PenName
Expand All @@ -152,10 +155,14 @@ func (b BookManager) SetContract(db *gorm.DB, book models.Book, data schemas.Con
book.Synopsis = data.Synopsis
book.Outline = data.Outline
book.IntendedContract = data.IntendedContract
book.FullPurchaseMode = data.FullPurchaseMode
username := book.Author.Username
book.IDFrontImage = username
book.IDBackImage = username
book.FullPurchaseMode = data.FullPurchaseMode
if idFrontImage != "" {
book.IDFrontImage = idFrontImage
}
if idBackImage != "" {
book.IDBackImage = idBackImage
}

if book.ContractStatus == choices.CTS_DECLINED {
book.ContractStatus = choices.CTS_UPDATED
}
Expand Down
10 changes: 0 additions & 10 deletions models/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,6 @@ func (user User) SubscriptionExpired() bool {
return time.Now().After(*user.SubscriptionExpiry)
}

func (u User) AvatarUrl() *string {
avatar := u.Avatar
if avatar != "" {
avatarUrl := fmt.Sprintf("%s/%s/%s", cfg.S3EndpointUrl, cfg.UserImagesBucket, u.Avatar)
return &avatarUrl
}
return &avatar
}

func (user User) BooksCount() int {
return len(user.Books)
}
Expand All @@ -75,7 +66,6 @@ func (user User) FullName() string {

func (user *User) BeforeCreate(tx *gorm.DB) (err error) {
user.Password = utils.HashPassword(user.Password)
user.Avatar = user.Username
return
}

Expand Down
24 changes: 0 additions & 24 deletions models/book.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package models

import (
"fmt"
"strings"

"github.com/LitPad/backend/models/choices"
Expand Down Expand Up @@ -81,28 +80,6 @@ type Book struct {
ContractStatus choices.ContractStatusChoice `gorm:"default:PENDING"`
}

func (b Book) CoverImageUrl() string {
return fmt.Sprintf("%s/%s/%s", cfg.S3EndpointUrl, cfg.BookCoverImagesBucket, b.CoverImage)
}

func (b Book) IDFrontImageUrl() *string {
imageText := b.IDFrontImage
if imageText != "" {
image := fmt.Sprintf("%s/%s/%s", cfg.S3EndpointUrl, cfg.IDFrontImagesBucket, imageText)
return &image
}
return nil
}

func (b Book) IDBackImageUrl() *string {
imageText := b.IDBackImage
if imageText != "" {
image := fmt.Sprintf("%s/%s/%s", cfg.S3EndpointUrl, cfg.IDBackImagesBucket, imageText)
return &image
}
return nil
}

func (b Book) ViewsCount() int {
views := b.Views
if len(views) > 0 {
Expand Down Expand Up @@ -150,7 +127,6 @@ func (b *Book) GenerateUniqueSlug(tx *gorm.DB) string {
func (b *Book) BeforeCreate(tx *gorm.DB) (err error) {
slug := b.GenerateUniqueSlug(tx)
b.Slug = slug
b.CoverImage = slug
return
}

Expand Down
37 changes: 21 additions & 16 deletions routes/books.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,9 @@ func (ep Endpoint) CreateBook(c *fiber.Ctx) error {
return c.Status(422).JSON(err)
}

book := bookManager.Create(db, *author, data, genre, "", tags)
// Upload File
UploadFile(file, book.CoverImage, cfg.BookCoverImagesBucket)
coverImage := UploadFile(file, "BOOK_COVER_IMAGES")
book := bookManager.Create(db, *author, data, genre, coverImage, tags)
response := schemas.BookResponseSchema{
ResponseSchema: ResponseMessage("Book created successfully"),
Data: schemas.BookSchema{}.Init(book),
Expand Down Expand Up @@ -307,11 +307,14 @@ func (ep Endpoint) UpdateBook(c *fiber.Ctx) error {
return c.Status(422).JSON(err)
}

updatedBook := bookManager.Update(db, *book, data, genre, tags)
// Upload File
coverImage := ""
if file != nil {
UploadFile(file, updatedBook.CoverImage, cfg.BookCoverImagesBucket)
coverImage = UploadFile(file, "BOOK_COVER_IMAGES")
}

updatedBook := bookManager.Update(db, *book, data, genre, coverImage, tags)

response := schemas.BookResponseSchema{
ResponseSchema: ResponseMessage("Book updated successfully"),
Data: schemas.BookSchema{}.Init(updatedBook),
Expand Down Expand Up @@ -902,25 +905,27 @@ func (ep Endpoint) SetContract(c *fiber.Ctx) error {
if book.FullName == "" {
imageRequired = true
}
id_front_image_file, id_front_image_file_err := ValidateImage(c, "id_front_image", imageRequired)
if id_front_image_file_err != nil {
return c.Status(422).JSON(id_front_image_file_err)
idFrontImageFile, idFrontImageFileErr := ValidateImage(c, "id_front_image", imageRequired)
if idFrontImageFileErr != nil {
return c.Status(422).JSON(idFrontImageFileErr)
}

id_back_image_file, id_back_image_file_err := ValidateImage(c, "id_back_image", imageRequired)
if id_back_image_file_err != nil {
return c.Status(422).JSON(id_back_image_file_err)
idBackImageFile, idBackImageFileErr := ValidateImage(c, "id_back_image", imageRequired)
if idBackImageFileErr != nil {
return c.Status(422).JSON(idBackImageFileErr)
}

updatedBook := bookManager.SetContract(db, *book, data)

// Upload File
if id_front_image_file != nil {
UploadFile(id_front_image_file, updatedBook.IDFrontImage, cfg.IDFrontImagesBucket)
var idFrontImage string
var idBackImage string
if idFrontImageFile != nil {
idFrontImage = UploadFile(idFrontImageFile, "ID_FRONT_IMAGES")
}
if id_back_image_file != nil {
UploadFile(id_back_image_file, updatedBook.IDBackImage, cfg.IDBackImagesBucket)
if idBackImageFile != nil {
idBackImage = UploadFile(idBackImageFile, "ID_BACK_IMAGES")
}

updatedBook := bookManager.SetContract(db, *book, idFrontImage, idBackImage, data)
response := schemas.ContractResponseSchema{
ResponseSchema: ResponseMessage("Contract set successfully"),
Data: schemas.ContractSchema{}.Init(updatedBook),
Expand Down
70 changes: 37 additions & 33 deletions routes/file_uploader.go
Original file line number Diff line number Diff line change
@@ -1,51 +1,55 @@
package routes

import (
"context"
"fmt"
"log"
"mime/multipart"
"net/http"

"github.com/LitPad/backend/utils"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/gofiber/fiber/v2"

"github.com/cloudinary/cloudinary-go/v2"
"github.com/cloudinary/cloudinary-go/v2/api/uploader"
)

var sess *session.Session

func init() {
var err error
// Configure the S3 client
sess, err = session.NewSession(&aws.Config{
Region: aws.String("us-east-1"), // Dummy region, replace if necessary
Credentials: credentials.NewStaticCredentials(cfg.S3AccessKey, cfg.S3SecretKey, ""),
Endpoint: aws.String(cfg.S3EndpointUrl),
S3ForcePathStyle: aws.Bool(true),
})
var cld *cloudinary.Cloudinary
var err error

func init () {
// Initialize Cloudinary client
cld, err = cloudinary.NewFromParams(cfg.CloudinaryCloudName, cfg.CloudinaryApiKey, cfg.CloudinaryApiSecret)
if err != nil {
log.Fatalf("Failed to create session: %v", err)
fmt.Println("failed to initialize Cloudinary client: %w", err)
}
}

// uploadToCloudinary uploads the file to Cloudinary and returns the URL of the uploaded file
func UploadFile(fileHeader *multipart.FileHeader, key string, folder string) {
file, err := fileHeader.Open()
func UploadFile(file *multipart.FileHeader, folder string) string {
if cfg.Debug {
folder = fmt.Sprintf("test/%s", folder)
} else {
folder = fmt.Sprintf("live/%s", folder)
}

// Open the file
src, err := file.Open()
if err != nil {
log.Println("failed to open file")
fmt.Println("failed to open file: %w", err)
return ""
}
defer file.Close()
uploader := s3manager.NewUploader(sess)

_, err = uploader.Upload(&s3manager.UploadInput{
Bucket: aws.String(folder),
Key: aws.String(key),
Body: file,
})
defer src.Close()

// Upload the file to Cloudinary
uploadResult, err := cld.Upload.Upload(context.Background(), src, uploader.UploadParams{Folder: folder})
if err != nil {
log.Println("failed to upload file")
}
fmt.Println("failed to upload to Cloudinary: %w", err)
return ""
}
log.Println("Hahalalalla")

// Return the secure URL of the uploaded file
return uploadResult.SecureURL
}

func ValidateImage(c *fiber.Ctx, name string, required bool) (*multipart.FileHeader, *utils.ErrorResponse) {
Expand All @@ -68,7 +72,7 @@ func ValidateImage(c *fiber.Ctx, name string, required bool) (*multipart.FileHea
if err != nil {
return nil, &errData
}

defer fileHandle.Close()

// Read the first 512 bytes for content type detection
Expand All @@ -81,8 +85,8 @@ func ValidateImage(c *fiber.Ctx, name string, required bool) (*multipart.FileHea
// Detect the content type
contentType := http.DetectContentType(buffer)
switch contentType {
case "image/jpeg", "image/png", "image/gif":
return file, nil
case "image/jpeg", "image/png", "image/gif":
return file, nil
}
return nil, &errData
}
Expand Down
4 changes: 2 additions & 2 deletions schemas/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ type UserDataSchema struct {
// For short user data
FullName string `json:"full_name"`
Username string `json:"username"`
Avatar *string `json:"avatar"`
Avatar string `json:"avatar"`
}

func (u UserDataSchema) Init(user models.User) UserDataSchema {
u.FullName = user.FullName()
u.Username = user.Username
u.Avatar = user.AvatarUrl()
u.Avatar = user.Avatar
return u
}
Loading

0 comments on commit 6b41428

Please sign in to comment.