Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/aws integration #100

Merged
merged 18 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
3424d9f
feat:added upload middleware; added route to test file upload to s3;
Manjish Feb 26, 2024
3ae61c8
feat: added cognito auth middleware
Manjish Feb 26, 2024
e4458d5
feat: added admin seed; changes in user model; added auto migration u…
Manjish Feb 26, 2024
c01e188
refactor:made auto-migrate optional
Manjish Feb 26, 2024
b07b345
feat:sending simple email using Amazon SES
Manjish Feb 26, 2024
2de07ae
:wrench: chore: remove gcp and firebase related services
paudelgaurav Jun 6, 2024
514d870
:sparkles: feat: added atlas as migation tool
paudelgaurav Jun 6, 2024
02d6fd0
:wrench: chore: merge branch develop into refactor/enhancement-aws-in…
paudelgaurav Jun 6, 2024
b21b15e
:wrench: chore: update go version to 1.22 in workflow file
paudelgaurav Jun 6, 2024
1d4db2c
:wrench: chore: running migration in github runner
paudelgaurav Jun 6, 2024
bfc8f90
:wrench: chore: downloading atlas in github runner
paudelgaurav Jun 6, 2024
da39f7b
:wrench: chore: remove env flag while applying migration
paudelgaurav Jun 6, 2024
c95f131
:wrench: chore: remove apply migration in runner
paudelgaurav Jun 6, 2024
aea044b
:wrench: chore: fix command to serve and check health
paudelgaurav Jun 6, 2024
ace0efd
:wrench: chore: fix command to migrate
paudelgaurav Jun 6, 2024
f6ec64e
:hammer: updated make file for migrating to previous version
Denes-cilwal Jun 7, 2024
a849067
:hammer: added port forward in env
Denes-cilwal Jun 7, 2024
16da18e
Merge pull request #114 from wesionaryTEAM/refactor/enhancement-in-aw…
Denes-cilwal Jun 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ STORAGE_BUCKET_NAME=
DEBUG_PORT=5002

TIMEZONE=

STORAGE_BUCKET_NAME=

AWS_REGION=
AWS_ACCESS_KEY_ID=
COGNITO_CLIENT_ID=
COGNITO_USER_POOL_ID=
AWS_SECRET_ACCESS_KEY=
2 changes: 2 additions & 0 deletions domain/constants/user.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package constants

type UserRole string

const (
RoleIsAdmin = "admin"
RoleIsGeneralAdmin = "general"
Expand Down
41 changes: 25 additions & 16 deletions domain/models/user.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
package models

import (
"clean-architecture/domain/constants"
"clean-architecture/pkg/types"
"clean-architecture/pkg/utils"
"database/sql"
"time"

"github.com/google/uuid"
"gorm.io/gorm"
)

// User model
type User struct {
types.ModelBase
Name string `json:"name" form:"name"`
Email string `json:"email" form:"email"`
Age int `json:"age" form:"age"`
Birthday *time.Time `json:"time"`
MemberNumber sql.NullString `json:"member_number"`
ProfilePic utils.SignedURL `json:"profile_pic"`
CreatedAt time.Time `json:"created_at" form:"created_at"`
UpdatedAt time.Time `json:"updated_at" form:"updated_at"`
gorm.Model
UUID types.BinaryUUID `json:"uuid" gorm:"index;notnull"`
CognitoUID *string `json:"-" gorm:"index;size:50"`
FirstName string `json:"first_name" gorm:"size:255"`
LastName string `json:"last_name" gorm:"size:255"`
FirstNameJa string `json:"first_name_ja" gorm:"size:255"`
LastNameJa string `json:"last_name_ja" gorm:"size:255"`
Email string `json:"email" gorm:"notnull;index,unique;size:255"`
Role constants.UserRole `json:"role" gorm:"size:25" copier:"-"`
IsActive bool `json:"is_active" gorm:"default:false"`
IsEmailVerified bool `json:"is_email_verified" gorm:"default:false"`
IsAdmin bool `json:"-" gorm:"default:false"`
ProfilePic utils.SignedURL `json:"profile_pic"`
}

// BeforeCreate run this before creating user
func (t *User) BeforeCreate(_ *gorm.DB) error {
id, err := uuid.NewRandom()
t.ID = types.BinaryUUID(id)
return err
func (u *User) BeforeCreate(tx *gorm.DB) error {
if u.UUID.String() == (types.BinaryUUID{}).String() {
id, err := uuid.NewRandom()
u.UUID = types.BinaryUUID(id)
return err
}
return nil
}

func (*User) TableName() string {
return "users"
}
84 changes: 79 additions & 5 deletions domain/user/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,43 @@ import (
"clean-architecture/pkg/api_errors"
"clean-architecture/pkg/framework"
"clean-architecture/pkg/responses"
"clean-architecture/pkg/services"
"clean-architecture/pkg/types"
"clean-architecture/pkg/utils"
"fmt"
"net/http"

"github.com/gin-gonic/gin"
)

// UserController data type
type Controller struct {
service *Service
logger framework.Logger
service *Service
logger framework.Logger
s3BucketService services.S3Service
sesService services.SESService
env *framework.Env
}

type URLObject struct {
Name string `json:"name"`
URL string `json:"url"`
}

// NewUserController creates new user controller
func NewController(userService *Service, logger framework.Logger) *Controller {
func NewController(
userService *Service,
logger framework.Logger,
s3BucketService services.S3Service,
sesService services.SESService,
env *framework.Env,
) *Controller {
return &Controller{
service: userService,
logger: logger,
service: userService,
logger: logger,
s3BucketService: s3BucketService,
sesService: sesService,
env: env,
}
}

Expand Down Expand Up @@ -122,3 +142,57 @@ func (u *Controller) DeleteUser(c *gin.Context) {

c.JSON(200, gin.H{"data": "user deleted"})
}

func (c *Controller) UploadImage(ctx *gin.Context) {
metadata, _ := ctx.MustGet(framework.File).(types.UploadedFiles)

urls := make([]URLObject, 0, 1)

for _, file := range metadata.GetMultipleFiles("file") {
signedUrl, err := c.s3BucketService.GetSignedURL(file.URL)
if err != nil {
c.logger.Info("Failed to get the presigned url: ", err.Error())
return
}
urls = append(urls, URLObject{Name: file.FileName, URL: signedUrl})
}

ctx.JSON(http.StatusOK, gin.H{
"message": "Success",
"urls": urls,
})
}

func (c *Controller) SendEmail(ctx *gin.Context) {
var emailData services.EmailParams

if err := ctx.ShouldBindJSON(&emailData); err != nil {
c.logger.Fatalf("Cannot send email due to error: %v", err)

responses.ErrorJSON(ctx, http.StatusBadRequest, err.Error())
return
}
if len(emailData.To) == 0 {
responses.ErrorJSON(ctx, http.StatusBadRequest, "Email to cannot be empty")
return
}

err := c.sesService.SendEmail(&services.EmailParams{
From: c.env.AdminEmail,
To: emailData.To,
Subject: emailData.Subject,
Body: emailData.Body,
})

if err != nil {
c.logger.Fatalf("Cannot send email due to error: %v", err)

responses.ErrorJSON(ctx, http.StatusBadRequest, err.Error())
return
}

ctx.JSON(http.StatusOK, gin.H{
"message": "Success",
"data": fmt.Sprintf("Email sent to %s successfully", emailData.To),
})
}
3 changes: 3 additions & 0 deletions domain/user/module.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Manjish Let's remove this as auto migrate invocation and stick to writing migration for schema.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be fixed by #114

Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ var Module = fx.Module("user",
NewController,
NewRoute,
),
//If you want to enable auto-migrate add Migrate as shown below
// fx.Invoke(Migrate, RegisterRoute),

fx.Invoke(RegisterRoute),
))
16 changes: 16 additions & 0 deletions domain/user/repository.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package user

import (
"clean-architecture/domain/models"
"clean-architecture/pkg/framework"
"clean-architecture/pkg/infrastructure"

Expand All @@ -18,6 +19,21 @@ func NewRepository(db infrastructure.Database, logger framework.Logger) Reposito
return Repository{db, logger}
}

// For AutoMigrating (used in fx.Invoke)
func Migrate(r Repository) error {
r.logger.Info("[Migrating...User]")
if err := r.DB.AutoMigrate(&models.User{}); err != nil {
r.logger.Error("[Migration failed...User]")
return err
}
return nil
}

func (r *Repository) Create(user *models.User) error {
r.logger.Info("[UserRepository...Create]")
return r.DB.Create(&user).Error
}

// WithTrx delegate transaction from user repository
func (r Repository) WithTrx(trxHandle *gorm.DB) Repository {
if trxHandle != nil {
Expand Down
14 changes: 6 additions & 8 deletions domain/user/route.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package user

import (
"clean-architecture/domain/constants"
"clean-architecture/pkg/framework"
"clean-architecture/pkg/infrastructure"
"clean-architecture/pkg/middlewares"
Expand All @@ -12,7 +11,7 @@ type Route struct {
logger framework.Logger
handler infrastructure.Router
controller *Controller
authMiddleware middlewares.AuthMiddleware
authMiddleware middlewares.CognitoMiddleWare
uploadMiddleware middlewares.UploadMiddleware
middlewares.PaginationMiddleware
rateLimitMiddleware middlewares.RateLimitMiddleware
Expand All @@ -22,7 +21,7 @@ func NewRoute(
logger framework.Logger,
handler infrastructure.Router,
controller *Controller,
authMiddleware middlewares.FirebaseAuthMiddleware,
authMiddleware middlewares.CognitoAuthMiddleware,
uploadMiddleware middlewares.UploadMiddleware,
pagination middlewares.PaginationMiddleware,
rateLimit middlewares.RateLimitMiddleware,
Expand All @@ -43,10 +42,8 @@ func NewRoute(
func RegisterRoute(r *Route) {
r.logger.Info("Setting up routes")

// in HandleAuthWithRole() pass empty for authentication
// or pass user role for authentication along with authorization
api := r.handler.Group("/api").Use(r.authMiddleware.HandleAuthWithRole(constants.RoleIsAdmin),
r.rateLimitMiddleware.Handle())
// remove r.authMiddleware.Handle() if you don't have the access token
api := r.handler.Group("/api").Use(r.authMiddleware.Handle(), r.rateLimitMiddleware.Handle())

api.GET("/user", r.PaginationMiddleware.Handle(), r.controller.GetUser)
api.GET("/user/:id", r.controller.GetOneUser)
Expand All @@ -56,5 +53,6 @@ func RegisterRoute(r *Route) {
r.controller.UpdateUser,
)
api.DELETE("/user/:id", r.controller.DeleteUser)

api.POST("/upload-test", r.uploadMiddleware.Push(r.uploadMiddleware.Config().ThumbEnable(true).WebpEnable(true)).Handle(), r.controller.UploadImage)
api.POST("/send-test-email", r.controller.SendEmail)
}
2 changes: 1 addition & 1 deletion domain/user/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,5 @@ func (s Service) DeleteUser(uuid types.BinaryUUID) error {

// DeleteUser deletes the user
func (s Service) Create(user *models.User) error {
return s.repository.Create(&user).Error
return s.repository.Create(user)
}
35 changes: 32 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@ require (
cloud.google.com/go/firestore v1.12.0
cloud.google.com/go/storage v1.31.0
firebase.google.com/go v3.13.0+incompatible
github.com/aws/aws-sdk-go-v2 v1.25.2
github.com/aws/aws-sdk-go-v2/config v1.27.4
github.com/aws/aws-sdk-go-v2/credentials v1.17.4
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.6
github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.35.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.1
github.com/aws/aws-sdk-go-v2/service/sesv2 v1.26.1
github.com/aws/smithy-go v1.20.1
github.com/chai2010/webp v1.1.1
github.com/getsentry/sentry-go v0.23.0
github.com/gin-contrib/cors v1.4.0
github.com/gin-gonic/gin v1.9.1
github.com/go-sql-driver/mysql v1.7.1
github.com/google/uuid v1.3.0
github.com/joho/godotenv v1.5.1
github.com/lestrrat-go/jwx v1.2.28
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/rubenv/sql-migrate v1.5.2
github.com/spf13/cobra v1.7.0
Expand All @@ -33,9 +42,23 @@ require (
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.2 // indirect
cloud.google.com/go/longrunning v0.5.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.1 // indirect
github.com/bytedance/sonic v1.10.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // 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
Expand All @@ -54,9 +77,15 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
Expand All @@ -76,10 +105,10 @@ require (
go.uber.org/dig v1.17.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.4.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand Down
Loading
Loading