diff --git a/configs/test.yaml b/configs/test.yaml index 52aa729..932572a 100644 --- a/configs/test.yaml +++ b/configs/test.yaml @@ -46,5 +46,10 @@ sendgrid: sender_email: xxx recaptcha: - site_key: xxx - secret_key: xxx + # For reCAPTCHA v2, use the following test keys. + # You will always get No CAPTCHA and all verification requests will pass. + # The reCAPTCHA widget will show a warning message to ensure it's not used + # for production traffic. + site_key: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI + secret_key: 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe + diff --git a/global/init.go b/global/init.go index 9ef35c1..6277107 100644 --- a/global/init.go +++ b/global/init.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "log" + "os" "strings" "sync" @@ -13,18 +14,31 @@ import ( ) var ( - once = new(sync.Once) - configName = flag.String("config", "development", "config file name, default is development") + once = new(sync.Once) + configName = flag.String( + "config", + "development", + "config file name, default is development", + ) ShowVersionInfo = flag.Bool("v", false, "show version info or not") ) func Init() { once.Do(func() { - if !flag.Parsed() { + isTest := false + for _, arg := range os.Args { + if strings.Contains(arg, "test") { + isTest = true + break + } + } + + if !isTest && !flag.Parsed() { flag.Parse() } + if err := initConfig(); err != nil { - panic(fmt.Errorf("initconfig failed: %s \n", err)) + panic(fmt.Errorf("initconfig failed: %s", err)) } watchConfig() @@ -33,16 +47,38 @@ func Init() { } func initConfig() error { + if err := setConfigNameAndType(); err != nil { + return fmt.Errorf("setting config name and type failed: %w", err) + } + + addConfigPaths() + + if err := setupEnvironmentVariables(); err != nil { + return fmt.Errorf("setting up environment variables failed: %w", err) + } + + if err := viper.ReadInConfig(); err != nil { + return fmt.Errorf("reading config failed: %w", err) + } + + return nil +} + +func setConfigNameAndType() error { viper.SetConfigName(*configName) + viper.SetConfigType("yaml") + return nil +} + +func addConfigPaths() { viper.AddConfigPath("configs") viper.AddConfigPath(App.RootDir + "/configs") - viper.SetConfigType("yaml") +} + +func setupEnvironmentVariables() error { viper.AutomaticEnv() replacer := strings.NewReplacer(".", "_") viper.SetEnvKeyReplacer(replacer) - if err := viper.ReadInConfig(); err != nil { - return err - } return nil } diff --git a/go.mod b/go.mod index b55c904..956c700 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/ic3network/mccs-alpha go 1.19 require ( - github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/fsnotify/fsnotify v1.6.0 github.com/gofrs/uuid v3.2.0+incompatible + github.com/golang-jwt/jwt/v5 v5.0.0 github.com/gorilla/mux v1.7.3 github.com/jinzhu/gorm v1.9.16 github.com/jinzhu/now v1.1.5 @@ -14,7 +14,7 @@ require ( github.com/robfig/cron v1.2.0 github.com/segmentio/ksuid v1.0.2 github.com/sendgrid/sendgrid-go v3.5.0+incompatible - github.com/shirou/gopsutil v2.19.12+incompatible + github.com/shirou/gopsutil v3.21.11+incompatible github.com/spf13/viper v1.17.0 github.com/stretchr/testify v1.8.4 github.com/unrolled/render v1.0.1 @@ -25,9 +25,8 @@ require ( ) require ( - github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/go-ole/go-ole v1.2.4 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect @@ -49,10 +48,13 @@ require ( github.com/spf13/cast v1.5.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect go.uber.org/multierr v1.10.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/sync v0.3.0 // indirect diff --git a/go.sum b/go.sum index 66f6a36..69e8caf 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -56,8 +54,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -75,12 +71,14 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -208,8 +206,8 @@ github.com/sendgrid/rest v2.4.1+incompatible h1:HDib/5xzQREPq34lN3YMhQtMkdXxS/qL github.com/sendgrid/rest v2.4.1+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= github.com/sendgrid/sendgrid-go v3.5.0+incompatible h1:kosbgHyNVYVaqECDYvFVLVD9nvThweBd6xp7vaCT3GI= github.com/sendgrid/sendgrid-go v3.5.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= -github.com/shirou/gopsutil v2.19.12+incompatible h1:WRstheAymn1WOPesh+24+bZKFkqrdCR8JOc77v4xV3Q= -github.com/shirou/gopsutil v2.19.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= @@ -232,6 +230,10 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/unrolled/render v1.0.1 h1:VDDnQQVfBMsOsp3VaCJszSO0nkBIVEYoPWeRThk9spY= github.com/unrolled/render v1.0.1/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -247,6 +249,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE= go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -374,6 +378,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -403,6 +408,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/internal/app/http/controller/account_handler.go b/internal/app/http/controller/account_handler.go index 7bdf564..8ff0ea3 100644 --- a/internal/app/http/controller/account_handler.go +++ b/internal/app/http/controller/account_handler.go @@ -41,8 +41,12 @@ func (a *accountHandler) RegisterRoutes( a.once.Do(func() { private.Path("/account").HandlerFunc(a.accountPage()).Methods("GET") private.Path("/account").HandlerFunc(a.updateAccount()).Methods("POST") - adminPrivate.Path("/accounts").HandlerFunc(a.searchAccountPage()).Methods("GET") - adminPrivate.Path("/accounts/search").HandlerFunc(a.searchAccount()).Methods("GET") + adminPrivate.Path("/accounts"). + HandlerFunc(a.searchAccountPage()). + Methods("GET") + adminPrivate.Path("/accounts/search"). + HandlerFunc(a.searchAccount()). + Methods("GET") }) } @@ -122,7 +126,12 @@ func (a *accountHandler) searchAccount() func(http.ResponseWriter, *http.Request res := sreachResponse{FormData: f, Result: new(findAccountResult)} if f.Filter != "business" && f.LastName == "" && f.Email == "" { - t.Render(w, r, res, []string{"Please enter at least one search criteria."}) + t.Render( + w, + r, + res, + []string{"Please enter at least one search criteria."}, + ) return } @@ -284,7 +293,10 @@ func (a *accountHandler) updateAccount() func(http.ResponseWriter, *http.Request // Validate the user inputs. errorMessages := []string{} if formData.CurrentPassword != "" { - _, err := service.User.Login(formData.User.Email, formData.CurrentPassword) + _, err := service.User.Login( + formData.User.Email, + formData.CurrentPassword, + ) if err != nil { l.Logger.Error("appServer UpdateAccount failed", zap.Error(err)) t.Error(w, r, formData, err) @@ -298,7 +310,10 @@ func (a *accountHandler) updateAccount() func(http.ResponseWriter, *http.Request errorMessages = append(errorMessages, data.Validate()...) } if len(errorMessages) > 0 { - l.Logger.Info("appServer UpdateAccount failed", zap.Strings("input invalid", errorMessages)) + l.Logger.Info( + "appServer UpdateAccount failed", + zap.Strings("input invalid", errorMessages), + ) t.Render(w, r, formData, errorMessages) return } @@ -311,14 +326,24 @@ func (a *accountHandler) updateAccount() func(http.ResponseWriter, *http.Request return } - offersAdded, offersRemoved := helper.TagDifference(formData.Business.Offers, oldBusiness.Offers) + offersAdded, offersRemoved := helper.TagDifference( + formData.Business.Offers, + oldBusiness.Offers, + ) formData.Business.OffersAdded = offersAdded formData.Business.OffersRemoved = offersRemoved - wantsAdded, wantsRemoved := helper.TagDifference(formData.Business.Wants, oldBusiness.Wants) + wantsAdded, wantsRemoved := helper.TagDifference( + formData.Business.Wants, + oldBusiness.Wants, + ) formData.Business.WantsAdded = wantsAdded formData.Business.WantsRemoved = wantsRemoved - err = service.Business.UpdateBusiness(user.CompanyID, formData.Business, false) + err = service.Business.UpdateBusiness( + user.CompanyID, + formData.Business, + false, + ) if err != nil { l.Logger.Error("appServer UpdateAccount failed", zap.Error(err)) t.Error(w, r, formData, err) @@ -326,7 +351,10 @@ func (a *accountHandler) updateAccount() func(http.ResponseWriter, *http.Request } if formData.CurrentPassword != "" && formData.ConfirmPassword != "" { - err = service.User.ResetPassword(user.Email, formData.ConfirmPassword) + err = service.User.ResetPassword( + user.Email, + formData.ConfirmPassword, + ) if err != nil { l.Logger.Error("appServer UpdateAccount failed", zap.Error(err)) t.Error(w, r, formData, err) @@ -335,9 +363,19 @@ func (a *accountHandler) updateAccount() func(http.ResponseWriter, *http.Request } go func() { - err := service.UserAction.Log(log.User.ModifyAccount(user, formData.User, oldBusiness, formData.Business)) + err := service.UserAction.Log( + log.User.ModifyAccount( + user, + formData.User, + oldBusiness, + formData.Business, + ), + ) if err != nil { - l.Logger.Error("BuildModifyAccountAction failed", zap.Error(err)) + l.Logger.Error( + "BuildModifyAccountAction failed", + zap.Error(err), + ) } }() diff --git a/internal/app/http/controller/admin_business_handler.go b/internal/app/http/controller/admin_business_handler.go index e0dbe21..593df97 100644 --- a/internal/app/http/controller/admin_business_handler.go +++ b/internal/app/http/controller/admin_business_handler.go @@ -42,10 +42,16 @@ func (a *adminBusinessHandler) RegisterRoutes( adminPrivate *mux.Router, ) { a.once.Do(func() { - adminPrivate.Path("/businesses/{id}").HandlerFunc(a.adminBusinessPage()).Methods("GET") - adminPrivate.Path("/businesses/{id}").HandlerFunc(a.updateBusiness()).Methods("POST") + adminPrivate.Path("/businesses/{id}"). + HandlerFunc(a.adminBusinessPage()). + Methods("GET") + adminPrivate.Path("/businesses/{id}"). + HandlerFunc(a.updateBusiness()). + Methods("POST") - adminPrivate.Path("/api/businesses/{id}").HandlerFunc(a.deleteBusiness()).Methods("DELETE") + adminPrivate.Path("/api/businesses/{id}"). + HandlerFunc(a.deleteBusiness()). + Methods("DELETE") }) } @@ -97,12 +103,18 @@ func (a *adminBusinessHandler) updateBusiness() func(http.ResponseWriter, *http. errorMessages := validator.UpdateBusiness(d.Business) maxPosBal, err := strconv.ParseFloat(r.FormValue("max_pos_bal"), 64) if err != nil { - errorMessages = append(errorMessages, "Max pos balance should be a number") + errorMessages = append( + errorMessages, + "Max pos balance should be a number", + ) } d.Balance.MaxPosBal = math.Abs(maxPosBal) maxNegBal, err := strconv.ParseFloat(r.FormValue("max_neg_bal"), 64) if err != nil { - errorMessages = append(errorMessages, "Max neg balance should be a number") + errorMessages = append( + errorMessages, + "Max neg balance should be a number", + ) } if math.Abs(maxNegBal) == 0 { d.Balance.MaxNegBal = 0 @@ -118,10 +130,22 @@ func (a *adminBusinessHandler) updateBusiness() func(http.ResponseWriter, *http. return } if account.Balance > d.Balance.MaxPosBal { - errorMessages = append(errorMessages, "The current account balance ("+fmt.Sprintf("%.2f", account.Balance)+") has exceed your max pos balance input") + errorMessages = append( + errorMessages, + "The current account balance ("+fmt.Sprintf( + "%.2f", + account.Balance, + )+") has exceed your max pos balance input", + ) } if account.Balance < -math.Abs(d.Balance.MaxNegBal) { - errorMessages = append(errorMessages, "The current account balance ("+fmt.Sprintf("%.2f", account.Balance)+") has exceed your max neg balance input") + errorMessages = append( + errorMessages, + "The current account balance ("+fmt.Sprintf( + "%.2f", + account.Balance, + )+") has exceed your max neg balance input", + ) } if len(errorMessages) > 0 { l.Logger.Error("UpdateBusiness failed", zap.Error(err)) @@ -136,10 +160,16 @@ func (a *adminBusinessHandler) updateBusiness() func(http.ResponseWriter, *http. t.Error(w, r, d, err) return } - offersAdded, offersRemoved := helper.TagDifference(d.Business.Offers, oldBusiness.Offers) + offersAdded, offersRemoved := helper.TagDifference( + d.Business.Offers, + oldBusiness.Offers, + ) d.Business.OffersAdded = offersAdded d.Business.OffersRemoved = offersRemoved - wantsAdded, wantsRemoved := helper.TagDifference(d.Business.Wants, oldBusiness.Wants) + wantsAdded, wantsRemoved := helper.TagDifference( + d.Business.Wants, + oldBusiness.Wants, + ) d.Business.WantsAdded = wantsAdded d.Business.WantsRemoved = wantsRemoved err = service.Business.UpdateBusiness(bID, d.Business, true) @@ -156,7 +186,11 @@ func (a *adminBusinessHandler) updateBusiness() func(http.ResponseWriter, *http. t.Error(w, r, d, err) return } - err = service.BalanceLimit.Update(account.ID, d.Balance.MaxPosBal, d.Balance.MaxNegBal) + err = service.BalanceLimit.Update( + account.ID, + d.Balance.MaxPosBal, + d.Balance.MaxNegBal, + ) if err != nil { l.Logger.Error("UpdateBusiness failed", zap.Error(err)) t.Error(w, r, d, err) @@ -175,12 +209,27 @@ func (a *adminBusinessHandler) updateBusiness() func(http.ResponseWriter, *http. adminUser, err := service.AdminUser.FindByID(objID) user, err := service.User.FindByBusinessID(bID) if err != nil { - l.Logger.Error("log.Admin.ModifyBusiness failed", zap.Error(err)) + l.Logger.Error( + "log.Admin.ModifyBusiness failed", + zap.Error(err), + ) return } - err = service.UserAction.Log(log.Admin.ModifyBusiness(adminUser, user, oldBusiness, d.Business, oldBalance, d.Balance)) + err = service.UserAction.Log( + log.Admin.ModifyBusiness( + adminUser, + user, + oldBusiness, + d.Business, + oldBalance, + d.Balance, + ), + ) if err != nil { - l.Logger.Error("log.Admin.ModifyBusiness failed", zap.Error(err)) + l.Logger.Error( + "log.Admin.ModifyBusiness failed", + zap.Error(err), + ) } }() @@ -190,21 +239,33 @@ func (a *adminBusinessHandler) updateBusiness() func(http.ResponseWriter, *http. // 2. When the business is in accepted status. // - only update added tags. go func() { - if !util.IsAcceptedStatus(oldBusiness.Status) && util.IsAcceptedStatus(d.Business.Status) { - err := service.Business.UpdateAllTagsCreatedAt(oldBusiness.ID, time.Now()) + if !util.IsAcceptedStatus(oldBusiness.Status) && + util.IsAcceptedStatus(d.Business.Status) { + err := service.Business.UpdateAllTagsCreatedAt( + oldBusiness.ID, + time.Now(), + ) if err != nil { - l.Logger.Error("UpdateAllTagsCreatedAt failed", zap.Error(err)) + l.Logger.Error( + "UpdateAllTagsCreatedAt failed", + zap.Error(err), + ) } - err = TagHandler.SaveOfferTags(helper.GetTagNames(d.Business.Offers)) + err = TagHandler.SaveOfferTags( + helper.GetTagNames(d.Business.Offers), + ) if err != nil { l.Logger.Error("saveOfferTags failed", zap.Error(err)) } - err = TagHandler.SaveWantTags(helper.GetTagNames(d.Business.Wants)) + err = TagHandler.SaveWantTags( + helper.GetTagNames(d.Business.Wants), + ) if err != nil { l.Logger.Error("saveWantTags failed", zap.Error(err)) } } - if util.IsAcceptedStatus(oldBusiness.Status) && util.IsAcceptedStatus(d.Business.Status) { + if util.IsAcceptedStatus(oldBusiness.Status) && + util.IsAcceptedStatus(d.Business.Status) { err := TagHandler.SaveOfferTags(d.Business.OffersAdded) if err != nil { l.Logger.Error("saveOfferTags failed", zap.Error(err)) @@ -217,7 +278,9 @@ func (a *adminBusinessHandler) updateBusiness() func(http.ResponseWriter, *http. }() go func() { // Set timestamp when first trading status applied. - if oldBusiness.MemberStartedAt.IsZero() && (oldBusiness.Status == constant.Business.Accepted) && (d.Business.Status == constant.Trading.Accepted) { + if oldBusiness.MemberStartedAt.IsZero() && + (oldBusiness.Status == constant.Business.Accepted) && + (d.Business.Status == constant.Trading.Accepted) { service.Business.SetMemberStartedAt(bID) } }() diff --git a/internal/app/http/controller/admin_history_handler.go b/internal/app/http/controller/admin_history_handler.go index 6f5854e..fe2ed63 100644 --- a/internal/app/http/controller/admin_history_handler.go +++ b/internal/app/http/controller/admin_history_handler.go @@ -33,7 +33,9 @@ func (h *adminHistoryHandler) RegisterRoutes( adminPrivate *mux.Router, ) { h.once.Do(func() { - adminPrivate.Path("/history/{id}").HandlerFunc(h.historyPage()).Methods("GET") + adminPrivate.Path("/history/{id}"). + HandlerFunc(h.historyPage()). + Methods("GET") }) } @@ -59,7 +61,10 @@ func (h *adminHistoryHandler) historyPage() func(http.ResponseWriter, *http.Requ page, err := strconv.Atoi(q.Get("page")) if err != nil { - l.Logger.Error("controller.AdminHistory.HistoryPage failed", zap.Error(err)) + l.Logger.Error( + "controller.AdminHistory.HistoryPage failed", + zap.Error(err), + ) t.Error(w, r, nil, err) return } @@ -71,7 +76,10 @@ func (h *adminHistoryHandler) historyPage() func(http.ResponseWriter, *http.Requ } user, err := UserHandler.FindByBusinessID(bID) if err != nil { - l.Logger.Error("controller.AdminHistory.HistoryPage failed", zap.Error(err)) + l.Logger.Error( + "controller.AdminHistory.HistoryPage failed", + zap.Error(err), + ) t.Error(w, r, nil, err) return } @@ -80,7 +88,10 @@ func (h *adminHistoryHandler) historyPage() func(http.ResponseWriter, *http.Requ // Get the account balance. account, err := service.Account.FindByBusinessID(bID) if err != nil { - l.Logger.Error("controller.AdminHistory.HistoryPage failed", zap.Error(err)) + l.Logger.Error( + "controller.AdminHistory.HistoryPage failed", + zap.Error(err), + ) t.Error(w, r, nil, err) return } @@ -94,7 +105,10 @@ func (h *adminHistoryHandler) historyPage() func(http.ResponseWriter, *http.Requ page, ) if err != nil { - l.Logger.Error("controller.AdminHistory.HistoryPage failed", zap.Error(err)) + l.Logger.Error( + "controller.AdminHistory.HistoryPage failed", + zap.Error(err), + ) t.Error(w, r, nil, err) return } diff --git a/internal/app/http/controller/admin_tag_handler.go b/internal/app/http/controller/admin_tag_handler.go index b99a480..7cf37e1 100644 --- a/internal/app/http/controller/admin_tag_handler.go +++ b/internal/app/http/controller/admin_tag_handler.go @@ -37,13 +37,25 @@ func (a *adminTagHandler) RegisterRoutes( adminPrivate *mux.Router, ) { a.once.Do(func() { - adminPrivate.Path("/admin-tags").HandlerFunc(a.adminTagPage()).Methods("GET") - adminPrivate.Path("/admin-tags/search").HandlerFunc(a.searchAdminTags()).Methods("GET") - - public.Path("/api/admin-tags/list/{prefix}").HandlerFunc(a.list()).Methods("GET") - adminPrivate.Path("/api/admin-tags").HandlerFunc(a.createAdminTag()).Methods("POST") - adminPrivate.Path("/api/admin-tags/{id}").HandlerFunc(a.renameAdminTag()).Methods("PUT") - adminPrivate.Path("/api/admin-tags/{id}").HandlerFunc(a.deleteAdminTag()).Methods("DELETE") + adminPrivate.Path("/admin-tags"). + HandlerFunc(a.adminTagPage()). + Methods("GET") + adminPrivate.Path("/admin-tags/search"). + HandlerFunc(a.searchAdminTags()). + Methods("GET") + + public.Path("/api/admin-tags/list/{prefix}"). + HandlerFunc(a.list()). + Methods("GET") + adminPrivate.Path("/api/admin-tags"). + HandlerFunc(a.createAdminTag()). + Methods("POST") + adminPrivate.Path("/api/admin-tags/{id}"). + HandlerFunc(a.renameAdminTag()). + Methods("PUT") + adminPrivate.Path("/api/admin-tags/{id}"). + HandlerFunc(a.deleteAdminTag()). + Methods("DELETE") }) } @@ -107,12 +119,20 @@ func (a *adminTagHandler) createAdminTag() func(http.ResponseWriter, *http.Reque objID, _ := primitive.ObjectIDFromHex(r.Header.Get("userID")) adminUser, err := service.AdminUser.FindByID(objID) if err != nil { - l.Logger.Error("log.Admin.CreateAdminTag failed", zap.Error(err)) + l.Logger.Error( + "log.Admin.CreateAdminTag failed", + zap.Error(err), + ) return } - err = service.UserAction.Log(log.Admin.CreateAdminTag(adminUser, req.Name)) + err = service.UserAction.Log( + log.Admin.CreateAdminTag(adminUser, req.Name), + ) if err != nil { - l.Logger.Error("log.Admin.CreateAdminTag failed", zap.Error(err)) + l.Logger.Error( + "log.Admin.CreateAdminTag failed", + zap.Error(err), + ) } }() @@ -233,12 +253,20 @@ func (a *adminTagHandler) renameAdminTag() func(http.ResponseWriter, *http.Reque objID, _ := primitive.ObjectIDFromHex(r.Header.Get("userID")) adminUser, err := service.AdminUser.FindByID(objID) if err != nil { - l.Logger.Error("log.Admin.ModifyAdminTag failed", zap.Error(err)) + l.Logger.Error( + "log.Admin.ModifyAdminTag failed", + zap.Error(err), + ) return } - err = service.UserAction.Log(log.Admin.ModifyAdminTag(adminUser, oldName, req.Name)) + err = service.UserAction.Log( + log.Admin.ModifyAdminTag(adminUser, oldName, req.Name), + ) if err != nil { - l.Logger.Error("log.Admin.ModifyAdminTag failed", zap.Error(err)) + l.Logger.Error( + "log.Admin.ModifyAdminTag failed", + zap.Error(err), + ) } }() @@ -281,12 +309,20 @@ func (a *adminTagHandler) deleteAdminTag() func(http.ResponseWriter, *http.Reque objID, _ := primitive.ObjectIDFromHex(r.Header.Get("userID")) adminUser, err := service.AdminUser.FindByID(objID) if err != nil { - l.Logger.Error("log.Admin.DeleteAdminTag failed", zap.Error(err)) + l.Logger.Error( + "log.Admin.DeleteAdminTag failed", + zap.Error(err), + ) return } - err = service.UserAction.Log(log.Admin.DeleteAdminTag(adminUser, adminTag.Name)) + err = service.UserAction.Log( + log.Admin.DeleteAdminTag(adminUser, adminTag.Name), + ) if err != nil { - l.Logger.Error("log.Admin.DeleteAdminTag failed", zap.Error(err)) + l.Logger.Error( + "log.Admin.DeleteAdminTag failed", + zap.Error(err), + ) } }() @@ -301,14 +337,20 @@ func (a *adminTagHandler) list() func(http.ResponseWriter, *http.Request) { tags, err := service.AdminTag.TagStartWith(prefix) if err != nil { - l.Logger.Error("controller.AdminTagHandler.List failed", zap.Error(err)) + l.Logger.Error( + "controller.AdminTagHandler.List failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } js, err := json.Marshal(tags) if err != nil { - l.Logger.Error("controller.AdminTagHandler.List failed", zap.Error(err)) + l.Logger.Error( + "controller.AdminTagHandler.List failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } diff --git a/internal/app/http/controller/admin_transaction_handler.go b/internal/app/http/controller/admin_transaction_handler.go index ec8b0ae..56646ee 100644 --- a/internal/app/http/controller/admin_transaction_handler.go +++ b/internal/app/http/controller/admin_transaction_handler.go @@ -39,11 +39,19 @@ func (tr *adminTransactionHandler) RegisterRoutes( adminPrivate *mux.Router, ) { tr.once.Do(func() { - adminPrivate.Path("/transaction").HandlerFunc(tr.transactionPage()).Methods("GET") - adminPrivate.Path("/transaction").HandlerFunc(tr.transaction()).Methods("POST") + adminPrivate.Path("/transaction"). + HandlerFunc(tr.transactionPage()). + Methods("GET") + adminPrivate.Path("/transaction"). + HandlerFunc(tr.transaction()). + Methods("POST") - adminPrivate.Path("/api/pendingTransactions").HandlerFunc(tr.pendingTransactions()).Methods("GET") - adminPrivate.Path("/api/cancelTransaction").HandlerFunc(tr.cancelTransaction()).Methods("POST") + adminPrivate.Path("/api/pendingTransactions"). + HandlerFunc(tr.pendingTransactions()). + Methods("GET") + adminPrivate.Path("/api/cancelTransaction"). + HandlerFunc(tr.cancelTransaction()). + Methods("POST") }) } @@ -90,15 +98,25 @@ func (tr *adminTransactionHandler) transaction() func(http.ResponseWriter, *http // Validate user inputs. errorMessages := []string{} if !util.IsValidEmail(f.FromEmail) { - errorMessages = append(errorMessages, "Please enter a valid sender email address.") + errorMessages = append( + errorMessages, + "Please enter a valid sender email address.", + ) } if !util.IsValidEmail(f.ToEmail) { - errorMessages = append(errorMessages, "Please enter a valid recipient email address.") + errorMessages = append( + errorMessages, + "Please enter a valid recipient email address.", + ) } amount, err := strconv.ParseFloat(r.FormValue("amount"), 64) // Amount should be positive value and with up to two decimal places. - if err != nil || amount <= 0 || !util.IsDecimalValid(r.FormValue("amount")) { - errorMessages = append(errorMessages, "Please enter a valid numeric amount to send with up to two decimal places.") + if err != nil || amount <= 0 || + !util.IsDecimalValid(r.FormValue("amount")) { + errorMessages = append( + errorMessages, + "Please enter a valid numeric amount to send with up to two decimal places.", + ) } res.FormData.Amount = amount if len(errorMessages) > 0 { @@ -122,14 +140,28 @@ func (tr *adminTransactionHandler) transaction() func(http.ResponseWriter, *http // Only allow transfers with accounts that also have "trading-accepted" status if from.Status != constant.Trading.Accepted { - t.Render(w, r, res, []string{"Sender is not a trading member. You can only make transfers from businesses that have trading member status."}) + t.Render( + w, + r, + res, + []string{ + "Sender is not a trading member. You can only make transfers from businesses that have trading member status.", + }, + ) return } else if to.Status != constant.Trading.Accepted { t.Render(w, r, res, []string{"Receiver is not a trading member. You can only make transfers to businesses that have trading member status."}) return } if f.FromEmail == f.ToEmail { - t.Render(w, r, res, []string{"You cannot create a transaction from and to the same account."}) + t.Render( + w, + r, + res, + []string{ + "You cannot create a transaction from and to the same account.", + }, + ) return } @@ -157,14 +189,26 @@ func (tr *adminTransactionHandler) transaction() func(http.ResponseWriter, *http return } err = service.UserAction.Log( - log.Admin.Transfer(adminUser, f.FromEmail, f.ToEmail, f.Amount, f.Description), + log.Admin.Transfer( + adminUser, + f.FromEmail, + f.ToEmail, + f.Amount, + f.Description, + ), ) if err != nil { l.Logger.Error("log.Admin.Transaction failed", zap.Error(err)) } }() - flash.Success(w, f.FromEmail+" has transferred "+fmt.Sprintf("%.2f", f.Amount)+" Credits to "+f.ToEmail) + flash.Success( + w, + f.FromEmail+" has transferred "+fmt.Sprintf( + "%.2f", + f.Amount, + )+" Credits to "+f.ToEmail, + ) http.Redirect(w, r, "/admin/transaction", http.StatusFound) } } @@ -178,19 +222,28 @@ func (tr *adminTransactionHandler) pendingTransactions() func(http.ResponseWrite user, err := UserHandler.FindByBusinessID(q.Get("business_id")) if err != nil { - l.Logger.Error("AdminTransactionHandler.pendingTransactions failed", zap.Error(err)) + l.Logger.Error( + "AdminTransactionHandler.pendingTransactions failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } account, err := AccountHandler.FindByUserID(user.ID.Hex()) if err != nil { - l.Logger.Error("AdminTransactionHandler.pendingTransactions failed", zap.Error(err)) + l.Logger.Error( + "AdminTransactionHandler.pendingTransactions failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } transactions, err := service.Transaction.FindPendings(account.ID) if err != nil { - l.Logger.Error("AdminTransactionHandler.pendingTransactions failed", zap.Error(err)) + l.Logger.Error( + "AdminTransactionHandler.pendingTransactions failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -201,13 +254,18 @@ func (tr *adminTransactionHandler) pendingTransactions() func(http.ResponseWrite } } -func (tr *adminTransactionHandler) isInitiatedStatus(w http.ResponseWriter, t *types.Transaction) (bool, error) { +func (tr *adminTransactionHandler) isInitiatedStatus( + w http.ResponseWriter, + t *types.Transaction, +) (bool, error) { type response struct { Error string `json:"error"` } if t.Status == constant.Transaction.Completed { - js, err := json.Marshal(response{Error: "The transaction has already been completed."}) + js, err := json.Marshal( + response{Error: "The transaction has already been completed."}, + ) if err != nil { return false, err } @@ -238,21 +296,30 @@ func (tr *adminTransactionHandler) cancelTransaction() func(http.ResponseWriter, decoder := json.NewDecoder(r.Body) err := decoder.Decode(&req) if err != nil { - l.Logger.Error("AdminTransactionHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "AdminTransactionHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } transaction, err := service.Transaction.Find(req.TransactionID) if err != nil { - l.Logger.Error("AdminTransactionHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "AdminTransactionHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } shouldContinue, err := tr.isInitiatedStatus(w, transaction) if err != nil { - l.Logger.Error("AdminTransactionHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "AdminTransactionHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -262,7 +329,10 @@ func (tr *adminTransactionHandler) cancelTransaction() func(http.ResponseWriter, err = service.Transaction.Cancel(req.TransactionID, req.Reason) if err != nil { - l.Logger.Error("AdminTransactionHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "AdminTransactionHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } diff --git a/internal/app/http/controller/admin_user_handler.go b/internal/app/http/controller/admin_user_handler.go index a9b5eb0..e1a659a 100644 --- a/internal/app/http/controller/admin_user_handler.go +++ b/internal/app/http/controller/admin_user_handler.go @@ -44,9 +44,15 @@ func (a *adminUserHandler) RegisterRoutes( adminPrivate.Path("").HandlerFunc(a.dashboardPage()).Methods("GET") adminPublic.Path("/login").HandlerFunc(a.loginPage()).Methods("GET") adminPublic.Path("/login").HandlerFunc(a.loginHandler()).Methods("POST") - adminPrivate.Path("/logout").HandlerFunc(a.logoutHandler()).Methods("GET") - adminPrivate.Path("/users/{id}").HandlerFunc(a.userPage()).Methods("GET") - adminPrivate.Path("/users/{id}").HandlerFunc(a.updateUser()).Methods("POST") + adminPrivate.Path("/logout"). + HandlerFunc(a.logoutHandler()). + Methods("GET") + adminPrivate.Path("/users/{id}"). + HandlerFunc(a.userPage()). + Methods("GET") + adminPrivate.Path("/users/{id}"). + HandlerFunc(a.updateUser()). + Methods("POST") }) } @@ -77,7 +83,12 @@ func (a *adminUserHandler) loginPage() func(http.ResponseWriter, *http.Request) RecaptchaSitekey string } return func(w http.ResponseWriter, r *http.Request) { - t.Render(w, r, formData{RecaptchaSitekey: viper.GetString("recaptcha.site_key")}, nil) + t.Render( + w, + r, + formData{RecaptchaSitekey: viper.GetString("recaptcha.site_key")}, + nil, + ) } } @@ -100,7 +111,10 @@ func (a *adminUserHandler) loginHandler() func(http.ResponseWriter, *http.Reques if viper.GetString("env") == "production" { isValid := recaptcha.Verify(*r) if !isValid { - l.Logger.Error("AdminLoginHandler failed", zap.Strings("errs", recaptcha.Error())) + l.Logger.Error( + "AdminLoginHandler failed", + zap.Strings("errs", recaptcha.Error()), + ) t.Render(w, r, f, recaptcha.Error()) return } @@ -114,19 +128,27 @@ func (a *adminUserHandler) loginHandler() func(http.ResponseWriter, *http.Reques user, err := service.AdminUser.FindByEmail(f.Email) if err != nil { if !e.IsUserNotFound(err) { - l.Logger.Error("BuildLoginFailureAction failed", zap.Error(err)) + l.Logger.Error( + "BuildLoginFailureAction failed", + zap.Error(err), + ) } return } - err = service.UserAction.Log(log.Admin.LoginFailure(user, ip.FromRequest(r))) + err = service.UserAction.Log( + log.Admin.LoginFailure(user, ip.FromRequest(r)), + ) if err != nil { - l.Logger.Error("BuildLoginFailureAction failed", zap.Error(err)) + l.Logger.Error( + "BuildLoginFailureAction failed", + zap.Error(err), + ) } }() return } - token, err := jwt.GenerateToken(user.ID.Hex(), true) + token, err := jwt.NewJWTManager().Generate(user.ID.Hex(), true) http.SetCookie(w, cookie.CreateCookie(token)) go func() { @@ -136,7 +158,9 @@ func (a *adminUserHandler) loginHandler() func(http.ResponseWriter, *http.Reques } }() go func() { - err := service.UserAction.Log(log.Admin.LoginSuccess(user, ip.FromRequest(r))) + err := service.UserAction.Log( + log.Admin.LoginSuccess(user, ip.FromRequest(r)), + ) if err != nil { l.Logger.Error("log.Admin.LoginSuccess failed", zap.Error(err)) } @@ -192,8 +216,12 @@ func (a *adminUserHandler) updateUser() func(http.ResponseWriter, *http.Request) errorMessages := validator.ValidateUser(updateData.User) - if (r.FormValue("origin_email") != updateData.User.Email) && service.User.UserEmailExists(updateData.User.Email) { - errorMessages = append(errorMessages, "Email address is already registered") + if (r.FormValue("origin_email") != updateData.User.Email) && + service.User.UserEmailExists(updateData.User.Email) { + errorMessages = append( + errorMessages, + "Email address is already registered", + ) } if len(errorMessages) > 0 { @@ -217,13 +245,22 @@ func (a *adminUserHandler) updateUser() func(http.ResponseWriter, *http.Request) } if updateData.User.Password != "" || updateData.ConfirmPassword != "" { - errorMessages := validator.ValidatePassword(updateData.User.Password, updateData.ConfirmPassword) + errorMessages := validator.ValidatePassword( + updateData.User.Password, + updateData.ConfirmPassword, + ) if len(errorMessages) > 0 { - l.Logger.Error("UpdateUser failed", zap.Strings("input invalid", errorMessages)) + l.Logger.Error( + "UpdateUser failed", + zap.Strings("input invalid", errorMessages), + ) t.Render(w, r, updateData, errorMessages) return } - err = service.User.ResetPassword(updateData.User.Email, updateData.ConfirmPassword) + err = service.User.ResetPassword( + updateData.User.Email, + updateData.ConfirmPassword, + ) if err != nil { l.Logger.Error("UpdateUser failed", zap.Error(err)) t.Error(w, r, updateData, err) @@ -238,7 +275,9 @@ func (a *adminUserHandler) updateUser() func(http.ResponseWriter, *http.Request) l.Logger.Error("log.Admin.ModifyUser failed", zap.Error(err)) return } - err = service.UserAction.Log(log.Admin.ModifyUser(adminUser, oldUser, updateData.User)) + err = service.UserAction.Log( + log.Admin.ModifyUser(adminUser, oldUser, updateData.User), + ) if err != nil { l.Logger.Error("log.Admin.ModifyUser failed", zap.Error(err)) } diff --git a/internal/app/http/controller/business_handler.go b/internal/app/http/controller/business_handler.go index 2e22a24..9e51773 100644 --- a/internal/app/http/controller/business_handler.go +++ b/internal/app/http/controller/business_handler.go @@ -40,15 +40,31 @@ func (b *businessHandler) RegisterRoutes( adminPrivate *mux.Router, ) { b.once.Do(func() { - public.Path("/businesses").HandlerFunc(b.searchBusinessPage()).Methods("GET") - public.Path("/businesses/search").HandlerFunc(b.searchBusiness()).Methods("GET") - public.Path("/businessPage/{id}").HandlerFunc(b.businessPage()).Methods("GET") - private.Path("/businesses/search/match-tags").HandlerFunc(b.searhMatchTags()).Methods("GET") - - private.Path("/api/businessStatus").HandlerFunc(b.businessStatus()).Methods("GET") - private.Path("/api/getBusinessName").HandlerFunc(b.getBusinessName()).Methods("GET") - private.Path("/api/tradingMemberStatus").HandlerFunc(b.tradingMemberStatus()).Methods("GET") - private.Path("/api/contactBusiness").HandlerFunc(b.contactBusiness()).Methods("POST") + public.Path("/businesses"). + HandlerFunc(b.searchBusinessPage()). + Methods("GET") + public.Path("/businesses/search"). + HandlerFunc(b.searchBusiness()). + Methods("GET") + public.Path("/businessPage/{id}"). + HandlerFunc(b.businessPage()). + Methods("GET") + private.Path("/businesses/search/match-tags"). + HandlerFunc(b.searhMatchTags()). + Methods("GET") + + private.Path("/api/businessStatus"). + HandlerFunc(b.businessStatus()). + Methods("GET") + private.Path("/api/getBusinessName"). + HandlerFunc(b.getBusinessName()). + Methods("GET") + private.Path("/api/tradingMemberStatus"). + HandlerFunc(b.tradingMemberStatus()). + Methods("GET") + private.Path("/api/contactBusiness"). + HandlerFunc(b.contactBusiness()). + Methods("POST") }) } @@ -114,7 +130,9 @@ func (b *businessHandler) searchBusinessPage() func(http.ResponseWriter, *http.R t.Error(w, r, nil, err) return } - res := searchBusinessResponse{Categories: helper.GetAdminTagNames(adminTags)} + res := searchBusinessResponse{ + Categories: helper.GetAdminTagNames(adminTags), + } _, err = UserHandler.FindByID(r.Header.Get("userID")) if err != nil { res.IsUserLoggedIn = false @@ -266,7 +284,13 @@ func (b *businessHandler) contactBusiness() func(http.ResponseWriter, *http.Requ receiver := businessOwner.FirstName + " " + businessOwner.LastName replyToName := user.FirstName + " " + user.LastName - err = email.SendContactBusiness(receiver, businessOwner.Email, replyToName, user.Email, req.Body) + err = email.SendContactBusiness( + receiver, + businessOwner.Email, + replyToName, + user.Email, + req.Body, + ) if err != nil { l.Logger.Error("ContactBusiness failed", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) @@ -280,7 +304,12 @@ func (b *businessHandler) contactBusiness() func(http.ResponseWriter, *http.Requ func (b *businessHandler) searhMatchTags() func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/businesses/search?"+r.URL.Query().Encode(), http.StatusFound) + http.Redirect( + w, + r, + "/businesses/search?"+r.URL.Query().Encode(), + http.StatusFound, + ) } } @@ -297,13 +326,19 @@ func (b *businessHandler) businessStatus() func(http.ResponseWriter, *http.Reque if q.Get("business_id") != "" { objID, err := primitive.ObjectIDFromHex(q.Get("business_id")) if err != nil { - l.Logger.Error("BusinessHandler.businessStatus failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.businessStatus failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } business, err = service.Business.FindByID(objID) if err != nil { - l.Logger.Error("BusinessHandler.businessStatus failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.businessStatus failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -319,7 +354,10 @@ func (b *businessHandler) businessStatus() func(http.ResponseWriter, *http.Reque res := &response{Status: business.Status} js, err := json.Marshal(res) if err != nil { - l.Logger.Error("BusinessHandler.businessStatus failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.businessStatus failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -338,14 +376,20 @@ func (b *businessHandler) getBusinessName() func(http.ResponseWriter, *http.Requ user, err := service.User.FindByEmail(q.Get("email")) if err != nil { - l.Logger.Error("BusinessHandler.getBusinessName failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.getBusinessName failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } business, err := service.Business.FindByID(user.CompanyID) if err != nil { - l.Logger.Error("BusinessHandler.getBusinessName failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.getBusinessName failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -353,7 +397,10 @@ func (b *businessHandler) getBusinessName() func(http.ResponseWriter, *http.Requ res := response{Name: business.BusinessName} js, err := json.Marshal(res) if err != nil { - l.Logger.Error("BusinessHandler.getBusinessName failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.getBusinessName failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -373,21 +420,30 @@ func (b *businessHandler) tradingMemberStatus() func(http.ResponseWriter, *http. objID, err := primitive.ObjectIDFromHex(q.Get("business_id")) if err != nil { - l.Logger.Error("BusinessHandler.tradingMemberStatus failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.tradingMemberStatus failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } other, err := service.Business.FindByID(objID) if err != nil { - l.Logger.Error("BusinessHandler.tradingMemberStatus failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.tradingMemberStatus failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } self, err := BusinessHandler.FindByUserID(r.Header.Get("userID")) if err != nil { - l.Logger.Error("BusinessHandler.tradingMemberStatus failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.tradingMemberStatus failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -401,7 +457,10 @@ func (b *businessHandler) tradingMemberStatus() func(http.ResponseWriter, *http. } js, err := json.Marshal(res) if err != nil { - l.Logger.Error("BusinessHandler.tradingMemberStatus failed", zap.Error(err)) + l.Logger.Error( + "BusinessHandler.tradingMemberStatus failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } diff --git a/internal/app/http/controller/dashboard_handler.go b/internal/app/http/controller/dashboard_handler.go index ad1f756..11d72bd 100644 --- a/internal/app/http/controller/dashboard_handler.go +++ b/internal/app/http/controller/dashboard_handler.go @@ -67,13 +67,19 @@ func (d *dashBoardHandler) dashboardPage() func(http.ResponseWriter, *http.Reque lastLoginDate = user.LastLoginDate } - matchedOffers, err := service.Tag.MatchOffers(helper.GetTagNames(business.Offers), lastLoginDate) + matchedOffers, err := service.Tag.MatchOffers( + helper.GetTagNames(business.Offers), + lastLoginDate, + ) if err != nil { l.Logger.Error("DashboardPage failed", zap.Error(err)) t.Error(w, r, nil, err) return } - matchedWants, err := service.Tag.MatchWants(helper.GetTagNames(business.Wants), lastLoginDate) + matchedWants, err := service.Tag.MatchWants( + helper.GetTagNames(business.Wants), + lastLoginDate, + ) if err != nil { l.Logger.Error("DashboardPage failed", zap.Error(err)) t.Error(w, r, nil, err) diff --git a/internal/app/http/controller/history.handler.go b/internal/app/http/controller/history.handler.go index 2d38232..9cad94b 100644 --- a/internal/app/http/controller/history.handler.go +++ b/internal/app/http/controller/history.handler.go @@ -35,7 +35,9 @@ func (h *historyHandler) RegisterRoutes( ) { h.once.Do(func() { private.Path("/history").HandlerFunc(h.historyPage()).Methods("GET") - private.Path("/history/search").HandlerFunc(h.searchHistory()).Methods("GET") + private.Path("/history/search"). + HandlerFunc(h.searchHistory()). + Methods("GET") }) } @@ -69,7 +71,10 @@ func (h *historyHandler) searchHistory() func(http.ResponseWriter, *http.Request page, err := strconv.Atoi(q.Get("page")) if err != nil { - l.Logger.Error("controller.History.HistoryPage failed", zap.Error(err)) + l.Logger.Error( + "controller.History.HistoryPage failed", + zap.Error(err), + ) t.Error(w, r, nil, err) return } @@ -83,7 +88,10 @@ func (h *historyHandler) searchHistory() func(http.ResponseWriter, *http.Request user, err := UserHandler.FindByID(r.Header.Get("userID")) if err != nil { - l.Logger.Error("controller.History.HistoryPage failed", zap.Error(err)) + l.Logger.Error( + "controller.History.HistoryPage failed", + zap.Error(err), + ) t.Error(w, r, nil, err) return } @@ -91,7 +99,10 @@ func (h *historyHandler) searchHistory() func(http.ResponseWriter, *http.Request // Get the account balance. account, err := service.Account.FindByBusinessID(user.CompanyID.Hex()) if err != nil { - l.Logger.Error("controller.History.HistoryPage failed", zap.Error(err)) + l.Logger.Error( + "controller.History.HistoryPage failed", + zap.Error(err), + ) t.Error(w, r, nil, err) return } @@ -105,7 +116,10 @@ func (h *historyHandler) searchHistory() func(http.ResponseWriter, *http.Request page, ) if err != nil { - l.Logger.Error("controller.History.HistoryPage failed", zap.Error(err)) + l.Logger.Error( + "controller.History.HistoryPage failed", + zap.Error(err), + ) t.Error(w, r, nil, err) return } diff --git a/internal/app/http/controller/log_handler.go b/internal/app/http/controller/log_handler.go index 80923a8..f01a47b 100644 --- a/internal/app/http/controller/log_handler.go +++ b/internal/app/http/controller/log_handler.go @@ -34,7 +34,9 @@ func (lh *logHandler) RegisterRoutes( ) { lh.once.Do(func() { adminPrivate.Path("/log").HandlerFunc(lh.logPage()).Methods("GET") - adminPrivate.Path("/log/search").HandlerFunc(lh.searchLog()).Methods("GET") + adminPrivate.Path("/log/search"). + HandlerFunc(lh.searchLog()). + Methods("GET") }) } @@ -85,7 +87,10 @@ func (lh *logHandler) searchLog() func(http.ResponseWriter, *http.Request) { DateTo: util.ParseTime(f.DateTo), } - userAction, totalPages, err := service.UserAction.Find(&c, int64(f.Page)) + userAction, totalPages, err := service.UserAction.Find( + &c, + int64(f.Page), + ) res.TotalPages = totalPages res.UserActions = userAction if err != nil { diff --git a/internal/app/http/controller/service_discovery.go b/internal/app/http/controller/service_discovery.go index e0e6a84..6139be1 100644 --- a/internal/app/http/controller/service_discovery.go +++ b/internal/app/http/controller/service_discovery.go @@ -73,7 +73,15 @@ func (s *serviceDiscovery) diskCheck(w http.ResponseWriter, r *http.Request) { text = "WARNING" } - message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent) + message := fmt.Sprintf( + "%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", + text, + usedMB, + usedGB, + totalMB, + totalGB, + usedPercent, + ) w.WriteHeader(status) w.Write([]byte("\n" + message)) } @@ -98,7 +106,14 @@ func (s *serviceDiscovery) cpuCheck(w http.ResponseWriter, r *http.Request) { text = "WARNING" } - message := fmt.Sprintf("%s - Load average: %.2f, %.2f, %.2f | Cores: %d", text, l1, l5, l15, cores) + message := fmt.Sprintf( + "%s - Load average: %.2f, %.2f, %.2f | Cores: %d", + text, + l1, + l5, + l15, + cores, + ) w.WriteHeader(status) w.Write([]byte("\n" + message)) } @@ -124,7 +139,15 @@ func (s *serviceDiscovery) ramCheck(w http.ResponseWriter, r *http.Request) { text = "WARNING" } - message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent) + message := fmt.Sprintf( + "%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", + text, + usedMB, + usedGB, + totalMB, + totalGB, + usedPercent, + ) w.WriteHeader(status) w.Write([]byte("\n" + message)) } diff --git a/internal/app/http/controller/tag_handler.go b/internal/app/http/controller/tag_handler.go index 4a08c7d..d760eb4 100644 --- a/internal/app/http/controller/tag_handler.go +++ b/internal/app/http/controller/tag_handler.go @@ -38,12 +38,22 @@ func (h *tagHandler) RegisterRoutes( ) { h.once.Do(func() { adminPrivate.Path("/user-tags").HandlerFunc(h.tagPage()).Methods("GET") - adminPrivate.Path("/user-tags/search").HandlerFunc(h.searchTags()).Methods("GET") - - public.Path("/api/tags/{tagName}").HandlerFunc(h.getTagSuggestions()).Methods("GET") - adminPrivate.Path("/api/user-tags").HandlerFunc(h.createTag()).Methods("POST") - adminPrivate.Path("/api/user-tags/{id}").HandlerFunc(h.renameTag()).Methods("PUT") - adminPrivate.Path("/api/user-tags/{id}").HandlerFunc(h.deleteTag()).Methods("DELETE") + adminPrivate.Path("/user-tags/search"). + HandlerFunc(h.searchTags()). + Methods("GET") + + public.Path("/api/tags/{tagName}"). + HandlerFunc(h.getTagSuggestions()). + Methods("GET") + adminPrivate.Path("/api/user-tags"). + HandlerFunc(h.createTag()). + Methods("POST") + adminPrivate.Path("/api/user-tags/{id}"). + HandlerFunc(h.renameTag()). + Methods("PUT") + adminPrivate.Path("/api/user-tags/{id}"). + HandlerFunc(h.deleteTag()). + Methods("DELETE") }) } @@ -175,7 +185,9 @@ func (h *tagHandler) createTag() func(http.ResponseWriter, *http.Request) { l.Logger.Error("log.Admin.CreateTag failed", zap.Error(err)) return } - err = service.UserAction.Log(log.Admin.CreateTag(adminUser, tagName)) + err = service.UserAction.Log( + log.Admin.CreateTag(adminUser, tagName), + ) if err != nil { l.Logger.Error("log.Admin.CreateTag failed", zap.Error(err)) } @@ -300,7 +312,9 @@ func (h *tagHandler) renameTag() func(http.ResponseWriter, *http.Request) { l.Logger.Error("log.Admin.ModifyTag failed", zap.Error(err)) return } - err = service.UserAction.Log(log.Admin.ModifyTag(adminUser, oldName, req.Name)) + err = service.UserAction.Log( + log.Admin.ModifyTag(adminUser, oldName, req.Name), + ) if err != nil { l.Logger.Error("log.Admin.ModifyTag failed", zap.Error(err)) } @@ -348,7 +362,9 @@ func (h *tagHandler) deleteTag() func(http.ResponseWriter, *http.Request) { l.Logger.Error("log.Admin.DeleteTag failed", zap.Error(err)) return } - err = service.UserAction.Log(log.Admin.DeleteTag(adminUser, tag.Name)) + err = service.UserAction.Log( + log.Admin.DeleteTag(adminUser, tag.Name), + ) if err != nil { l.Logger.Error("log.Admin.DeleteTag failed", zap.Error(err)) } diff --git a/internal/app/http/controller/trading_handler.go b/internal/app/http/controller/trading_handler.go index 435c450..9e6c49a 100644 --- a/internal/app/http/controller/trading_handler.go +++ b/internal/app/http/controller/trading_handler.go @@ -37,10 +37,14 @@ func (th *tradingHandler) RegisterRoutes( adminPrivate *mux.Router, ) { th.once.Do(func() { - private.Path("/member-signup").HandlerFunc(th.signupPage()).Methods("GET") + private.Path("/member-signup"). + HandlerFunc(th.signupPage()). + Methods("GET") private.Path("/member-signup").HandlerFunc(th.signup()).Methods("POST") - private.Path("/api/is-trading-member").HandlerFunc(th.isMember()).Methods("GET") + private.Path("/api/is-trading-member"). + HandlerFunc(th.isMember()). + Methods("GET") }) } @@ -96,7 +100,10 @@ func (th *tradingHandler) signup() func(http.ResponseWriter, *http.Request) { } } if len(errorMessages) > 0 { - l.Logger.Info("TradingHandler.Signup failed", zap.Strings("input invalid", errorMessages)) + l.Logger.Info( + "TradingHandler.Signup failed", + zap.Strings("input invalid", errorMessages), + ) t.Render(w, r, data, errorMessages) return } @@ -131,7 +138,11 @@ func (th *tradingHandler) signup() func(http.ResponseWriter, *http.Request) { // Send thank you email to the User's email address. go func() { - err := email.SendThankYouEmail(data.FirstName, data.LastName, user.Email) + err := email.SendThankYouEmail( + data.FirstName, + data.LastName, + user.Email, + ) if err != nil { l.Logger.Error("email.SendThankYouEmail failed", zap.Error(err)) } @@ -140,7 +151,10 @@ func (th *tradingHandler) signup() func(http.ResponseWriter, *http.Request) { go func() { err := email.SendNewMemberSignupEmail(data.BusinessName, user.Email) if err != nil { - l.Logger.Error("email.SendNewMemberSignupEmail failed", zap.Error(err)) + l.Logger.Error( + "email.SendNewMemberSignupEmail failed", + zap.Error(err), + ) } }() diff --git a/internal/app/http/controller/transaction_handler.go b/internal/app/http/controller/transaction_handler.go index 5126a8d..1ab5c02 100644 --- a/internal/app/http/controller/transaction_handler.go +++ b/internal/app/http/controller/transaction_handler.go @@ -44,22 +44,45 @@ func (tr *transactionHandler) RegisterRoutes( adminPrivate *mux.Router, ) { tr.once.Do(func() { - private.Path("/transaction").HandlerFunc(tr.proposeTransactionPage()).Methods("GET") - private.Path("/transaction").HandlerFunc(tr.proposeTransaction()).Methods("POST") - private.Path("/transaction/cancelPropose").HandlerFunc(tr.cancelPropose()).Methods("GET") - - private.Path("/pending_transactions").HandlerFunc(tr.pendingTransactionsPage()).Methods("GET") - - private.Path("/api/accountBalance").HandlerFunc(tr.getBalance()).Methods("GET") - private.Path("/api/pendingTransactions").HandlerFunc(tr.pendingTransactions()).Methods("GET") - private.Path("/api/acceptTransaction").HandlerFunc(tr.acceptTransaction()).Methods("POST") - private.Path("/api/cancelTransaction").HandlerFunc(tr.cancelTransaction()).Methods("POST") - private.Path("/api/rejectTransaction").HandlerFunc(tr.rejectTransaction()).Methods("POST") - private.Path("/api/recentTransactions").HandlerFunc(tr.recentTransactions()).Methods("GET") + private.Path("/transaction"). + HandlerFunc(tr.proposeTransactionPage()). + Methods("GET") + private.Path("/transaction"). + HandlerFunc(tr.proposeTransaction()). + Methods("POST") + private.Path("/transaction/cancelPropose"). + HandlerFunc(tr.cancelPropose()). + Methods("GET") + + private.Path("/pending_transactions"). + HandlerFunc(tr.pendingTransactionsPage()). + Methods("GET") + + private.Path("/api/accountBalance"). + HandlerFunc(tr.getBalance()). + Methods("GET") + private.Path("/api/pendingTransactions"). + HandlerFunc(tr.pendingTransactions()). + Methods("GET") + private.Path("/api/acceptTransaction"). + HandlerFunc(tr.acceptTransaction()). + Methods("POST") + private.Path("/api/cancelTransaction"). + HandlerFunc(tr.cancelTransaction()). + Methods("POST") + private.Path("/api/rejectTransaction"). + HandlerFunc(tr.rejectTransaction()). + Methods("POST") + private.Path("/api/recentTransactions"). + HandlerFunc(tr.recentTransactions()). + Methods("GET") }) } -func (tr *transactionHandler) getMaxNegBal(r *http.Request, res *response) error { +func (tr *transactionHandler) getMaxNegBal( + r *http.Request, + res *response, +) error { // Get the user max negative balance. account, err := AccountHandler.FindByUserID(r.Header.Get("userID")) if err != nil { @@ -191,12 +214,19 @@ func (tr *transactionHandler) proposeTransaction() func(http.ResponseWriter, *ht // Validate the user inputs. errorMessages := []string{} if !util.IsValidEmail(f.Email) { - errorMessages = append(errorMessages, "Please enter a valid email address.") + errorMessages = append( + errorMessages, + "Please enter a valid email address.", + ) } amount, err := strconv.ParseFloat(r.FormValue("amount"), 64) // Amount should be positive value and with up to two decimal places. - if err != nil || amount <= 0 || !util.IsDecimalValid(r.FormValue("amount")) { - errorMessages = append(errorMessages, "Please enter a valid numeric amount to send with up to two decimal places.") + if err != nil || amount <= 0 || + !util.IsDecimalValid(r.FormValue("amount")) { + errorMessages = append( + errorMessages, + "Please enter a valid numeric amount to send with up to two decimal places.", + ) } res.FormData.Amount = amount if len(errorMessages) > 0 { @@ -235,13 +265,25 @@ func (tr *transactionHandler) proposeTransaction() func(http.ResponseWriter, *ht // Only allow transfers with accounts that also have "trading-accepted" status if (proposeInfo.FromStatus != constant.Trading.Accepted) || (proposeInfo.ToStatus != constant.Trading.Accepted) { - t.Render(w, r, res, []string{"Recipient is not a trading member. You can only make transfers to other businesses that have trading member status."}) + t.Render( + w, + r, + res, + []string{ + "Recipient is not a trading member. You can only make transfers to other businesses that have trading member status.", + }, + ) return } // Check if the user is doing the transaction to himself. if proposeInfo.FromID == proposeInfo.ToID { - t.Render(w, r, res, []string{"You cannot create a transaction with yourself."}) + t.Render( + w, + r, + res, + []string{"You cannot create a transaction with yourself."}, + ) return } @@ -261,7 +303,13 @@ func (tr *transactionHandler) proposeTransaction() func(http.ResponseWriter, *ht t.Error(w, r, res, err) return } - flash.Success(w, "You have proposed a transfer of "+fmt.Sprintf("%.2f", f.Amount)+" Credits with "+f.Email) + flash.Success( + w, + "You have proposed a transfer of "+fmt.Sprintf( + "%.2f", + f.Amount, + )+" Credits with "+f.Email, + ) http.Redirect(w, r, "/#transactions", http.StatusFound) go func() { @@ -279,7 +327,10 @@ func (tr *transactionHandler) proposeTransaction() func(http.ResponseWriter, *ht go func() { err := email.Transaction.Initiate(f.Type, transaction) if err != nil { - l.Logger.Error("email.Transaction.Initiate failed", zap.Error(err)) + l.Logger.Error( + "email.Transaction.Initiate failed", + zap.Error(err), + ) } }() } @@ -310,13 +361,19 @@ func (tr *transactionHandler) pendingTransactions() func(http.ResponseWriter, *h return func(w http.ResponseWriter, r *http.Request) { account, err := AccountHandler.FindByUserID(r.Header.Get("userID")) if err != nil { - l.Logger.Error("TransferHandler.pendingTransactions failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.pendingTransactions failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } transactions, err := service.Transaction.FindPendings(account.ID) if err != nil { - l.Logger.Error("TransferHandler.pendingTransactions failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.pendingTransactions failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -334,13 +391,19 @@ func (tr *transactionHandler) recentTransactions() func(http.ResponseWriter, *ht return func(w http.ResponseWriter, r *http.Request) { account, err := AccountHandler.FindByUserID(r.Header.Get("userID")) if err != nil { - l.Logger.Error("TransferHandler.recentTransactions failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.recentTransactions failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } transactions, err := service.Transaction.FindRecent(account.ID) if err != nil { - l.Logger.Error("TransferHandler.recentTransactions failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.recentTransactions failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -351,13 +414,20 @@ func (tr *transactionHandler) recentTransactions() func(http.ResponseWriter, *ht } } -func (tr *transactionHandler) isInitiatedStatus(w http.ResponseWriter, t *types.Transaction) (bool, error) { +func (tr *transactionHandler) isInitiatedStatus( + w http.ResponseWriter, + t *types.Transaction, +) (bool, error) { type response struct { Error string `json:"error"` } if t.Status == constant.Transaction.Completed { - js, err := json.Marshal(response{Error: "The transaction has already been completed by the counterparty."}) + js, err := json.Marshal( + response{ + Error: "The transaction has already been completed by the counterparty.", + }, + ) if err != nil { return false, err } @@ -387,27 +457,39 @@ func (tr *transactionHandler) cancelTransaction() func(http.ResponseWriter, *htt decoder := json.NewDecoder(r.Body) err := decoder.Decode(&req) if err != nil { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } account, err := AccountHandler.FindByUserID(r.Header.Get("userID")) if err != nil { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } transaction, err := service.Transaction.Find(req.TransactionID) if err != nil { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } shouldContinue, err := tr.isInitiatedStatus(w, transaction) if err != nil { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -416,13 +498,19 @@ func (tr *transactionHandler) cancelTransaction() func(http.ResponseWriter, *htt } if account.ID != transaction.InitiatedBy { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } err = service.Transaction.Cancel(req.TransactionID, req.Reason) if err != nil { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -431,7 +519,10 @@ func (tr *transactionHandler) cancelTransaction() func(http.ResponseWriter, *htt go func() { err := email.Transaction.Cancel(transaction, req.Reason) if err != nil { - l.Logger.Error("email.Transaction.Cancel failed", zap.Error(err)) + l.Logger.Error( + "email.Transaction.Cancel failed", + zap.Error(err), + ) } }() } @@ -447,21 +538,30 @@ func (tr *transactionHandler) rejectTransaction() func(http.ResponseWriter, *htt decoder := json.NewDecoder(r.Body) err := decoder.Decode(&req) if err != nil { - l.Logger.Error("TransferHandler.rejectTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.rejectTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } transaction, err := service.Transaction.Find(req.TransactionID) if err != nil { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } shouldContinue, err := tr.isInitiatedStatus(w, transaction) if err != nil { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -471,7 +571,10 @@ func (tr *transactionHandler) rejectTransaction() func(http.ResponseWriter, *htt err = service.Transaction.Cancel(req.TransactionID, req.Reason) if err != nil { - l.Logger.Error("TransferHandler.rejectTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.rejectTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -480,7 +583,10 @@ func (tr *transactionHandler) rejectTransaction() func(http.ResponseWriter, *htt go func() { err := email.Transaction.Reject(transaction) if err != nil { - l.Logger.Error("email.Transaction.Reject failed", zap.Error(err)) + l.Logger.Error( + "email.Transaction.Reject failed", + zap.Error(err), + ) } }() } @@ -495,21 +601,30 @@ func (tr *transactionHandler) acceptTransaction() func(http.ResponseWriter, *htt decoder := json.NewDecoder(r.Body) err := decoder.Decode(&req) if err != nil { - l.Logger.Error("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } transaction, err := service.Transaction.Find(req.TransactionID) if err != nil { - l.Logger.Error("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } shouldContinue, err := tr.isInitiatedStatus(w, transaction) if err != nil { - l.Logger.Error("TransferHandler.cancelTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.cancelTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -519,21 +634,33 @@ func (tr *transactionHandler) acceptTransaction() func(http.ResponseWriter, *htt from, err := service.Account.FindByID(transaction.FromID) if err != nil { - l.Logger.Error("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } to, err := service.Account.FindByID(transaction.ToID) if err != nil { - l.Logger.Error("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } // Check the account balance. - exceed, err := service.BalanceLimit.IsExceedLimit(from.ID, from.Balance-transaction.Amount) + exceed, err := service.BalanceLimit.IsExceedLimit( + from.ID, + from.Balance-transaction.Amount, + ) if err != nil { - l.Logger.Info("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Info( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -541,7 +668,10 @@ func (tr *transactionHandler) acceptTransaction() func(http.ResponseWriter, *htt reason := "The sender will exceed its credit limit so this transaction has been cancelled." err = service.Transaction.Cancel(req.TransactionID, reason) if err != nil { - l.Logger.Error("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -550,14 +680,23 @@ func (tr *transactionHandler) acceptTransaction() func(http.ResponseWriter, *htt go func() { err := email.Transaction.CancelBySystem(transaction, reason) if err != nil { - l.Logger.Error("email.Transaction.Cancel failed", zap.Error(err)) + l.Logger.Error( + "email.Transaction.Cancel failed", + zap.Error(err), + ) } }() return } - exceed, err = service.BalanceLimit.IsExceedLimit(to.ID, to.Balance+transaction.Amount) + exceed, err = service.BalanceLimit.IsExceedLimit( + to.ID, + to.Balance+transaction.Amount, + ) if err != nil { - l.Logger.Info("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Info( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -565,7 +704,10 @@ func (tr *transactionHandler) acceptTransaction() func(http.ResponseWriter, *htt reason := "The recipient will exceed its maximum positive balance threshold so this transaction has been cancelled." err = service.Transaction.Cancel(req.TransactionID, reason) if err != nil { - l.Logger.Error("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -574,15 +716,26 @@ func (tr *transactionHandler) acceptTransaction() func(http.ResponseWriter, *htt go func() { err := email.Transaction.CancelBySystem(transaction, reason) if err != nil { - l.Logger.Error("email.Transaction.Cancel failed", zap.Error(err)) + l.Logger.Error( + "email.Transaction.Cancel failed", + zap.Error(err), + ) } }() return } - err = service.Transaction.Accept(transaction.ID, from.ID, to.ID, transaction.Amount) + err = service.Transaction.Accept( + transaction.ID, + from.ID, + to.ID, + transaction.Amount, + ) if err != nil { - l.Logger.Error("TransferHandler.acceptTransaction failed", zap.Error(err)) + l.Logger.Error( + "TransferHandler.acceptTransaction failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) return } @@ -591,7 +744,10 @@ func (tr *transactionHandler) acceptTransaction() func(http.ResponseWriter, *htt go func() { err := email.Transaction.Accept(transaction) if err != nil { - l.Logger.Error("email.Transaction.Accept failed", zap.Error(err)) + l.Logger.Error( + "email.Transaction.Accept failed", + zap.Error(err), + ) } }() } diff --git a/internal/app/http/controller/user_handler.go b/internal/app/http/controller/user_handler.go index 1f9deeb..2ed9374 100644 --- a/internal/app/http/controller/user_handler.go +++ b/internal/app/http/controller/user_handler.go @@ -50,15 +50,29 @@ func (u *userHandler) RegisterRoutes( public.Path("/signup").HandlerFunc(u.registerHandler()).Methods("POST") public.Path("/login").HandlerFunc(u.loginPage()).Methods("GET") public.Path("/login").HandlerFunc(u.loginHandler()).Methods("POST") - public.Path("/lost-password").HandlerFunc(u.lostPasswordPage()).Methods("GET") - public.Path("/lost-password").HandlerFunc(u.lostPassword()).Methods("POST") - public.Path("/password-resets/{token}").HandlerFunc(u.passwordResetPage()).Methods("GET") - public.Path("/password-resets/{token}").HandlerFunc(u.passwordReset()).Methods("POST") + public.Path("/lost-password"). + HandlerFunc(u.lostPasswordPage()). + Methods("GET") + public.Path("/lost-password"). + HandlerFunc(u.lostPassword()). + Methods("POST") + public.Path("/password-resets/{token}"). + HandlerFunc(u.passwordResetPage()). + Methods("GET") + public.Path("/password-resets/{token}"). + HandlerFunc(u.passwordReset()). + Methods("POST") private.Path("/logout").HandlerFunc(u.logoutHandler()).Methods("GET") - private.Path("/api/users/removeFromFavoriteBusinesses").HandlerFunc(u.removeFromFavoriteBusinesses()).Methods("POST") - private.Path("/api/users/toggleShowRecentMatchedTags").HandlerFunc(u.toggleShowRecentMatchedTags()).Methods("POST") - private.Path("/api/users/addToFavoriteBusinesses").HandlerFunc(u.addToFavoriteBusinesses()).Methods("POST") + private.Path("/api/users/removeFromFavoriteBusinesses"). + HandlerFunc(u.removeFromFavoriteBusinesses()). + Methods("POST") + private.Path("/api/users/toggleShowRecentMatchedTags"). + HandlerFunc(u.toggleShowRecentMatchedTags()). + Methods("POST") + private.Path("/api/users/addToFavoriteBusinesses"). + HandlerFunc(u.addToFavoriteBusinesses()). + Methods("POST") }) } @@ -106,7 +120,10 @@ func (u *userHandler) registerHandler() func(http.ResponseWriter, *http.Request) errorMessages := validator.Register(d) if service.User.UserEmailExists(d.User.Email) { - errorMessages = append(errorMessages, "Email address is already registered.") + errorMessages = append( + errorMessages, + "Email address is already registered.", + ) } if viper.GetString("env") == "production" { @@ -117,7 +134,10 @@ func (u *userHandler) registerHandler() func(http.ResponseWriter, *http.Request) } if len(errorMessages) > 0 { - l.Logger.Info("RegisterHandler failed", zap.Strings("input invalid", errorMessages)) + l.Logger.Info( + "RegisterHandler failed", + zap.Strings("input invalid", errorMessages), + ) t.Render(w, r, d, errorMessages) return } @@ -144,7 +164,7 @@ func (u *userHandler) registerHandler() func(http.ResponseWriter, *http.Request) return } - token, err := jwt.GenerateToken(d.User.ID.Hex(), false) + token, err := jwt.NewJWTManager().Generate(d.User.ID.Hex(), false) if err != nil { l.Logger.Error("RegisterHandler failed", zap.Error(err)) http.Redirect(w, r, "/login", http.StatusFound) @@ -168,9 +188,15 @@ func (u *userHandler) registerHandler() func(http.ResponseWriter, *http.Request) if !viper.GetBool("receive_signup_notifications") { return } - err := email.SendSignupNotification(d.Business.BusinessName, d.User.Email) + err := email.SendSignupNotification( + d.Business.BusinessName, + d.User.Email, + ) if err != nil { - l.Logger.Error("email.SendSignupNotification failed", zap.Error(err)) + l.Logger.Error( + "email.SendSignupNotification failed", + zap.Error(err), + ) } }() go func() { @@ -222,7 +248,10 @@ func (u *userHandler) loginHandler() func(http.ResponseWriter, *http.Request) { if viper.GetString("env") == "production" { isValid := recaptcha.Verify(*r) if !isValid { - l.Logger.Error("UpdateLoginAttempts failed", zap.Strings("errs", recaptcha.Error())) + l.Logger.Error( + "UpdateLoginAttempts failed", + zap.Strings("errs", recaptcha.Error()), + ) t.Render(w, r, f, recaptcha.Error()) return } @@ -247,23 +276,36 @@ func (u *userHandler) loginHandler() func(http.ResponseWriter, *http.Request) { user, err := service.User.FindByEmail(f.Email) if err != nil { if !e.IsUserNotFound(err) { - l.Logger.Error("log.User.LoginFailure failed", zap.Error(err)) + l.Logger.Error( + "log.User.LoginFailure failed", + zap.Error(err), + ) } return } - err = service.UserAction.Log(log.User.LoginFailure(user, ip.FromRequest(r))) + err = service.UserAction.Log( + log.User.LoginFailure(user, ip.FromRequest(r)), + ) if err != nil { - l.Logger.Error("log.User.LoginFailure failed", zap.Error(err)) + l.Logger.Error( + "log.User.LoginFailure failed", + zap.Error(err), + ) } }() return } - token, err := jwt.GenerateToken(user.ID.Hex(), false) + token, err := jwt.NewJWTManager().Generate(user.ID.Hex(), false) http.SetCookie(w, cookie.CreateCookie(token)) // CurrentLoginDate and CurrentLoginIP are the previous informations. - flash.Info(w, "You last logged in on "+util.FormatTime(user.CurrentLoginDate)+" from "+user.CurrentLoginIP) + flash.Info( + w, + "You last logged in on "+util.FormatTime( + user.CurrentLoginDate, + )+" from "+user.CurrentLoginIP, + ) go func() { err := service.User.UpdateLoginInfo(user.ID, ip.FromRequest(r)) @@ -272,13 +314,20 @@ func (u *userHandler) loginHandler() func(http.ResponseWriter, *http.Request) { } }() go func() { - err := service.UserAction.Log(log.User.LoginSuccess(user, ip.FromRequest(r))) + err := service.UserAction.Log( + log.User.LoginSuccess(user, ip.FromRequest(r)), + ) if err != nil { l.Logger.Error("log.User.LoginSuccess failed", zap.Error(err)) } }() - http.Redirect(w, r, r.URL.Query().Get("redirect_login"), http.StatusFound) + http.Redirect( + w, + r, + r.URL.Query().Get("redirect_login"), + http.StatusFound, + ) } } @@ -299,7 +348,12 @@ func (u *userHandler) lostPasswordPage() func(http.ResponseWriter, *http.Request RecaptchaSitekey string } return func(w http.ResponseWriter, r *http.Request) { - t.Render(w, r, formData{RecaptchaSitekey: viper.GetString("recaptcha.site_key")}, nil) + t.Render( + w, + r, + formData{RecaptchaSitekey: viper.GetString("recaptcha.site_key")}, + nil, + ) } } @@ -321,7 +375,10 @@ func (u *userHandler) lostPassword() func(http.ResponseWriter, *http.Request) { if viper.GetString("env") == "production" { isValid := recaptcha.Verify(*r) if !isValid { - l.Logger.Info("LostPassword failed", zap.Strings("errs", recaptcha.Error())) + l.Logger.Info( + "LostPassword failed", + zap.Strings("errs", recaptcha.Error()), + ) t.Render(w, r, f, recaptcha.Error()) return } @@ -417,9 +474,15 @@ func (u *userHandler) passwordReset() func(http.ResponseWriter, *http.Request) { ConfirmPassword: r.FormValue("confirm_password"), } - errorMessages := validator.ValidatePassword(f.Password, f.ConfirmPassword) + errorMessages := validator.ValidatePassword( + f.Password, + f.ConfirmPassword, + ) if len(errorMessages) > 0 { - l.Logger.Error("PasswordReset failed", zap.Strings("input invalid", errorMessages)) + l.Logger.Error( + "PasswordReset failed", + zap.Strings("input invalid", errorMessages), + ) t.Render(w, r, f, errorMessages) return } @@ -448,7 +511,10 @@ func (u *userHandler) passwordReset() func(http.ResponseWriter, *http.Request) { go func() { user, err := service.User.FindByEmail(lost.Email) if err != nil { - l.Logger.Error("BuildChangePasswordAction failed", zap.Error(err)) + l.Logger.Error( + "BuildChangePasswordAction failed", + zap.Error(err), + ) return } service.UserAction.Log(log.User.ChangePassword(user)) @@ -490,7 +556,10 @@ func (u *userHandler) addToFavoriteBusinesses() func(http.ResponseWriter, *http. err := decoder.Decode(&req) if err != nil || req.ID == "" { if err != nil { - l.Logger.Error("AppServer AddToFavoriteBusinesses failed", zap.Error(err)) + l.Logger.Error( + "AppServer AddToFavoriteBusinesses failed", + zap.Error(err), + ) } else { l.Logger.Error("AppServer AddToFavoriteBusinesses failed", zap.String("error", "request business id is empty")) } @@ -500,7 +569,10 @@ func (u *userHandler) addToFavoriteBusinesses() func(http.ResponseWriter, *http. } bID, err := primitive.ObjectIDFromHex(req.ID) if err != nil { - l.Logger.Error("AppServer AddToFavoriteBusinesses failed", zap.Error(err)) + l.Logger.Error( + "AppServer AddToFavoriteBusinesses failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Something went wrong. Please try again later.")) return @@ -508,7 +580,10 @@ func (u *userHandler) addToFavoriteBusinesses() func(http.ResponseWriter, *http. uID, err := primitive.ObjectIDFromHex(r.Header.Get("userID")) if err != nil { - l.Logger.Error("AppServer AddToFavoriteBusinesses failed", zap.Error(err)) + l.Logger.Error( + "AppServer AddToFavoriteBusinesses failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Something went wrong. Please try again later.")) return @@ -516,7 +591,10 @@ func (u *userHandler) addToFavoriteBusinesses() func(http.ResponseWriter, *http. err = service.User.AddToFavoriteBusinesses(uID, bID) if err != nil { - l.Logger.Error("AppServer AddToFavoriteBusinesses failed", zap.Error(err)) + l.Logger.Error( + "AppServer AddToFavoriteBusinesses failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Something went wrong. Please try again later.")) return @@ -536,7 +614,10 @@ func (u *userHandler) removeFromFavoriteBusinesses() func(http.ResponseWriter, * err := decoder.Decode(&req) if err != nil || req.ID == "" { if err != nil { - l.Logger.Error("AppServer RemoveFromFavoriteBusinesses failed", zap.Error(err)) + l.Logger.Error( + "AppServer RemoveFromFavoriteBusinesses failed", + zap.Error(err), + ) } else { l.Logger.Error("AppServer RemoveFromFavoriteBusinesses failed", zap.String("error", "request business id is empty")) } @@ -546,7 +627,10 @@ func (u *userHandler) removeFromFavoriteBusinesses() func(http.ResponseWriter, * } bID, err := primitive.ObjectIDFromHex(req.ID) if err != nil { - l.Logger.Error("AppServer RemoveFromFavoriteBusinesses failed", zap.Error(err)) + l.Logger.Error( + "AppServer RemoveFromFavoriteBusinesses failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Something went wrong. Please try again later.")) return @@ -554,7 +638,10 @@ func (u *userHandler) removeFromFavoriteBusinesses() func(http.ResponseWriter, * uID, err := primitive.ObjectIDFromHex(r.Header.Get("userID")) if err != nil { - l.Logger.Error("AppServer RemoveFromFavoriteBusinesses failed", zap.Error(err)) + l.Logger.Error( + "AppServer RemoveFromFavoriteBusinesses failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Something went wrong. Please try again later.")) return @@ -562,7 +649,10 @@ func (u *userHandler) removeFromFavoriteBusinesses() func(http.ResponseWriter, * err = service.User.RemoveFromFavoriteBusinesses(uID, bID) if err != nil { - l.Logger.Error("AppServer RemoveFromFavoriteBusinesses failed", zap.Error(err)) + l.Logger.Error( + "AppServer RemoveFromFavoriteBusinesses failed", + zap.Error(err), + ) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Something went wrong. Please try again later.")) return diff --git a/internal/app/http/middleware/auth.go b/internal/app/http/middleware/auth.go index c5a1aae..11a5307 100644 --- a/internal/app/http/middleware/auth.go +++ b/internal/app/http/middleware/auth.go @@ -18,7 +18,7 @@ func GetLoggedInUser() mux.MiddlewareFunc { return } mccsToken := cookie.Value - claims, err := jwt.ValidateToken(mccsToken) + claims, err := jwt.NewJWTManager().Validate(mccsToken) if err != nil { next.ServeHTTP(w, r) return @@ -39,7 +39,12 @@ func RequireUser() mux.MiddlewareFunc { // 2. If it's on the other page, redirect to the targeting page after logging in. if userID == "" { if url.QueryEscape(r.URL.String()) == url.QueryEscape("/") { - http.Redirect(w, r, "/businesses/search?page=1", http.StatusFound) + http.Redirect( + w, + r, + "/businesses/search?page=1", + http.StatusFound, + ) } else { http.Redirect(w, r, "/login?redirect_login="+url.QueryEscape(r.URL.String()), http.StatusFound) } diff --git a/internal/app/http/middleware/cache.go b/internal/app/http/middleware/cache.go index c7edff7..ffbf219 100644 --- a/internal/app/http/middleware/cache.go +++ b/internal/app/http/middleware/cache.go @@ -9,9 +9,15 @@ import ( func NoCache() mux.MiddlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Cache-Control", "no-cache, must-revalidate, no-store") // HTTP 1.1. - w.Header().Set("Pragma", "no-cache") // HTTP 1.0. - w.Header().Set("Expires", "0") // Proxies. + w.Header(). + Set("Cache-Control", "no-cache, must-revalidate, no-store") + // HTTP 1.1. + w.Header(). + Set("Pragma", "no-cache") + // HTTP 1.0. + w.Header(). + Set("Expires", "0") + // Proxies. next.ServeHTTP(w, r) }) } diff --git a/internal/app/http/middleware/logging.go b/internal/app/http/middleware/logging.go index 1ce41ca..5cfb417 100644 --- a/internal/app/http/middleware/logging.go +++ b/internal/app/http/middleware/logging.go @@ -21,7 +21,9 @@ func Logging() mux.MiddlewareFunc { defer func() { uri := r.RequestURI // Skip for the health check and static requests. - if uri == "/health" || uri == "/ram" || uri == "/cpu" || uri == "/disk" || strings.HasPrefix(uri, "/static") { + if uri == "/health" || uri == "/ram" || uri == "/cpu" || + uri == "/disk" || + strings.HasPrefix(uri, "/static") { return } elapse := time.Now().Sub(startTime) diff --git a/internal/app/http/middleware/recover.go b/internal/app/http/middleware/recover.go index 7fcc9dd..67bcadd 100644 --- a/internal/app/http/middleware/recover.go +++ b/internal/app/http/middleware/recover.go @@ -16,7 +16,11 @@ func Recover() mux.MiddlewareFunc { if err := recover(); err != nil { buf := make([]byte, 1024) runtime.Stack(buf, false) - l.Logger.Error("recover, error", zap.Any("err", err), zap.ByteString("method", buf)) + l.Logger.Error( + "recover, error", + zap.Any("err", err), + zap.ByteString("method", buf), + ) } }() next.ServeHTTP(w, r) diff --git a/internal/app/http/routes.go b/internal/app/http/routes.go index 203167c..9809afa 100644 --- a/internal/app/http/routes.go +++ b/internal/app/http/routes.go @@ -10,33 +10,130 @@ import ( func RegisterRoutes(r *mux.Router) { public := r.PathPrefix("/").Subrouter() - public.Use(middleware.Recover(), middleware.NoCache(), middleware.Logging(), middleware.GetLoggedInUser()) + public.Use( + middleware.Recover(), + middleware.NoCache(), + middleware.Logging(), + middleware.GetLoggedInUser(), + ) private := r.PathPrefix("/").Subrouter() - private.Use(middleware.Recover(), middleware.NoCache(), middleware.Logging(), middleware.GetLoggedInUser(), middleware.RequireUser()) + private.Use( + middleware.Recover(), + middleware.NoCache(), + middleware.Logging(), + middleware.GetLoggedInUser(), + middleware.RequireUser(), + ) adminPublic := r.PathPrefix("/admin").Subrouter() - adminPublic.Use(middleware.Recover(), middleware.NoCache(), middleware.Logging(), middleware.GetLoggedInUser()) + adminPublic.Use( + middleware.Recover(), + middleware.NoCache(), + middleware.Logging(), + middleware.GetLoggedInUser(), + ) adminPrivate := r.PathPrefix("/admin").Subrouter() - adminPrivate.Use(middleware.Recover(), middleware.NoCache(), middleware.Logging(), middleware.GetLoggedInUser(), middleware.RequireAdmin()) + adminPrivate.Use( + middleware.Recover(), + middleware.NoCache(), + middleware.Logging(), + middleware.GetLoggedInUser(), + middleware.RequireAdmin(), + ) // Serving static files. fs := http.FileServer(http.Dir("web/static")) public.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs)) - controller.ServiceDiscovery.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.DashBoardHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.BusinessHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.UserHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.TransactionHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.HistoryHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.TradingHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) + controller.ServiceDiscovery.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.DashBoardHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.BusinessHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.UserHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.TransactionHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.HistoryHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.TradingHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) - controller.AdminBusinessHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.AdminUserHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.AdminHistoryHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.AdminTransactionHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.AdminTagHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.LogHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) + controller.AdminBusinessHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.AdminUserHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.AdminHistoryHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.AdminTransactionHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.AdminTagHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.LogHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) - controller.AccountHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) - controller.TagHandler.RegisterRoutes(public, private, adminPublic, adminPrivate) + controller.AccountHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) + controller.TagHandler.RegisterRoutes( + public, + private, + adminPublic, + adminPrivate, + ) } diff --git a/internal/app/repositories/es/business_es.go b/internal/app/repositories/es/business_es.go index cef4e38..5ca6e25 100644 --- a/internal/app/repositories/es/business_es.go +++ b/internal/app/repositories/es/business_es.go @@ -28,7 +28,10 @@ func (es *business) Register(client *elastic.Client) { es.index = "businesses" } -func (es *business) Create(id primitive.ObjectID, data *types.BusinessData) error { +func (es *business) Create( + id primitive.ObjectID, + data *types.BusinessData, +) error { body := types.BusinessESRecord{ BusinessID: id.Hex(), BusinessName: data.BusinessName, @@ -67,8 +70,14 @@ func matchTags(q *elastic.BoolQuery, c *types.SearchCriteria) { // weighted is used to make sure the tags are shown in order. weighted := 2.0 for _, o := range c.Tags { - qq.Should(newFuzzyWildcardTimeQueryForTag("offers", o.Name, c.CreatedOnOrAfter). - Boost(weighted)) + qq.Should( + newFuzzyWildcardTimeQueryForTag( + "offers", + o.Name, + c.CreatedOnOrAfter, + ). + Boost(weighted), + ) weighted *= 0.9 } // Must match one of the "Should" queries. @@ -87,7 +96,10 @@ func matchTags(q *elastic.BoolQuery, c *types.SearchCriteria) { } } -func (es *business) Find(c *types.SearchCriteria, page int64) ([]string, int, int, error) { +func (es *business) Find( + c *types.SearchCriteria, + page int64, +) ([]string, int, int, error) { if page < 0 || page == 0 { return nil, 0, 0, e.New(e.InvalidPageNumber, "find business failed") } @@ -101,7 +113,8 @@ func (es *business) Find(c *types.SearchCriteria, page int64) ([]string, int, in q.Should(elastic.NewMatchQuery("status", constant.Trading.Accepted)) if c.ShowUserFavoritesOnly { - idQuery := elastic.NewIdsQuery().Ids(util.ToIDStrings(c.FavoriteBusinesses)...) + idQuery := elastic.NewIdsQuery(). + Ids(util.ToIDStrings(c.FavoriteBusinesses)...) q.Must(idQuery) } @@ -149,7 +162,10 @@ func (es *business) Find(c *types.SearchCriteria, page int64) ([]string, int, in return ids, int(numberOfResults), totalPages, nil } -func (es *business) UpdateBusiness(id primitive.ObjectID, data *types.BusinessData) error { +func (es *business) UpdateBusiness( + id primitive.ObjectID, + data *types.BusinessData, +) error { params := map[string]interface{}{ "businessName": data.BusinessName, "locationCity": data.LocationCity, @@ -223,7 +239,10 @@ func (es *business) UpdateBusiness(id primitive.ObjectID, data *types.BusinessDa return nil } -func (es *business) UpdateTradingInfo(id primitive.ObjectID, data *types.TradingRegisterData) error { +func (es *business) UpdateTradingInfo( + id primitive.ObjectID, + data *types.TradingRegisterData, +) error { doc := map[string]interface{}{ "businessName": data.BusinessName, "locationCity": data.LocationCity, @@ -241,7 +260,10 @@ func (es *business) UpdateTradingInfo(id primitive.ObjectID, data *types.Trading return nil } -func (es *business) UpdateAllTagsCreatedAt(id primitive.ObjectID, t time.Time) error { +func (es *business) UpdateAllTagsCreatedAt( + id primitive.ObjectID, + t time.Time, +) error { params := map[string]interface{}{ "createdAt": t, } diff --git a/internal/app/repositories/es/helper.go b/internal/app/repositories/es/helper.go index 5de90c2..4f63db3 100644 --- a/internal/app/repositories/es/helper.go +++ b/internal/app/repositories/es/helper.go @@ -16,22 +16,41 @@ func newFuzzyWildcardQuery(name, text string) *elastic.BoolQuery { } // Should match one of the three queries. (MatchQuery, WildcardQuery, RegexpQuery) -func newFuzzyWildcardTimeQueryForTag(tagField, tagName string, createdOnOrAfter time.Time) *elastic.NestedQuery { +func newFuzzyWildcardTimeQueryForTag( + tagField, tagName string, + createdOnOrAfter time.Time, +) *elastic.NestedQuery { q := elastic.NewBoolQuery() qq := elastic.NewBoolQuery() - qq.Must((elastic.NewMatchQuery(tagField+".name", tagName).Fuzziness("auto").Boost(2))) - qq.Must(elastic.NewRangeQuery(tagField + ".createdAt").Gte(createdOnOrAfter)) + qq.Must( + (elastic.NewMatchQuery(tagField+".name", tagName).Fuzziness("auto").Boost(2)), + ) + qq.Must( + elastic.NewRangeQuery(tagField + ".createdAt").Gte(createdOnOrAfter), + ) q.Should(qq) qq = elastic.NewBoolQuery() - qq.Must(elastic.NewWildcardQuery(tagField+".name", strings.ToLower(tagName)+"*").Boost(1.5)) - qq.Must(elastic.NewRangeQuery(tagField + ".createdAt").Gte(createdOnOrAfter)) + qq.Must( + elastic.NewWildcardQuery(tagField+".name", strings.ToLower(tagName)+"*"). + Boost(1.5), + ) + qq.Must( + elastic.NewRangeQuery(tagField + ".createdAt").Gte(createdOnOrAfter), + ) q.Should(qq) qq = elastic.NewBoolQuery() - qq.Must(elastic.NewRegexpQuery(tagField+".name", ".*"+strings.ToLower(tagName)+".*")) - qq.Must(elastic.NewRangeQuery(tagField + ".createdAt").Gte(createdOnOrAfter)) + qq.Must( + elastic.NewRegexpQuery( + tagField+".name", + ".*"+strings.ToLower(tagName)+".*", + ), + ) + qq.Must( + elastic.NewRangeQuery(tagField + ".createdAt").Gte(createdOnOrAfter), + ) q.Should(qq) nestedQ := elastic.NewNestedQuery(tagField, q) @@ -40,7 +59,11 @@ func newFuzzyWildcardTimeQueryForTag(tagField, tagName string, createdOnOrAfter } // Should match one of the three queries. (MatchQuery, WildcardQuery, RegexpQuery) -func newTagQuery(tag string, lastLoginDate time.Time, timeField string) *elastic.BoolQuery { +func newTagQuery( + tag string, + lastLoginDate time.Time, + timeField string, +) *elastic.BoolQuery { q := elastic.NewBoolQuery() // The default value for both offerAddedAt and wantAddedAt is 0001-01-01T00:00:00.000+0000. diff --git a/internal/app/repositories/es/index.go b/internal/app/repositories/es/index.go index 6f9843c..5c445b1 100644 --- a/internal/app/repositories/es/index.go +++ b/internal/app/repositories/es/index.go @@ -25,7 +25,9 @@ func checkIndex(client *elastic.Client, index string) { return } - createIndex, err := client.CreateIndex(index).BodyString(indexMappings[index]).Do(ctx) + createIndex, err := client.CreateIndex(index). + BodyString(indexMappings[index]). + Do(ctx) if err != nil { panic(err) } diff --git a/internal/app/repositories/es/tag_es.go b/internal/app/repositories/es/tag_es.go index 9396423..866457a 100644 --- a/internal/app/repositories/es/tag_es.go +++ b/internal/app/repositories/es/tag_es.go @@ -156,7 +156,10 @@ func (es *tag) DeleteByID(id string) error { } // MatchOffer matches wants for the given offer. -func (es *tag) MatchOffer(offer string, lastLoginDate time.Time) ([]string, error) { +func (es *tag) MatchOffer( + offer string, + lastLoginDate time.Time, +) ([]string, error) { q := newTagQuery(offer, lastLoginDate, "wantAddedAt") res, err := es.c.Search(). Index(es.index). @@ -181,7 +184,10 @@ func (es *tag) MatchOffer(offer string, lastLoginDate time.Time) ([]string, erro } // MatchWant matches offers for the given want. -func (es *tag) MatchWant(want string, lastLoginDate time.Time) ([]string, error) { +func (es *tag) MatchWant( + want string, + lastLoginDate time.Time, +) ([]string, error) { q := newTagQuery(want, lastLoginDate, "offerAddedAt") res, err := es.c.Search(). Index(es.index). diff --git a/internal/app/repositories/es/user_es.go b/internal/app/repositories/es/user_es.go index a85208a..fcad78f 100644 --- a/internal/app/repositories/es/user_es.go +++ b/internal/app/repositories/es/user_es.go @@ -106,7 +106,10 @@ func (es *user) Update(u *types.User) error { return nil } -func (es *user) UpdateTradingInfo(id primitive.ObjectID, data *types.TradingRegisterData) error { +func (es *user) UpdateTradingInfo( + id primitive.ObjectID, + data *types.TradingRegisterData, +) error { doc := map[string]interface{}{ "firstName": data.FirstName, "lastName": data.LastName, diff --git a/internal/app/repositories/mongo/admin_tag_mongo.go b/internal/app/repositories/mongo/admin_tag_mongo.go index aaff989..7c0d20a 100644 --- a/internal/app/repositories/mongo/admin_tag_mongo.go +++ b/internal/app/repositories/mongo/admin_tag_mongo.go @@ -31,7 +31,9 @@ func (a *adminTag) Create(name string) error { } filter := bson.M{"name": name} - update := bson.M{"$setOnInsert": bson.M{"name": name, "createdAt": time.Now()}} + update := bson.M{ + "$setOnInsert": bson.M{"name": name, "createdAt": time.Now()}, + } _, err := a.c.UpdateOne( context.Background(), filter, @@ -67,7 +69,10 @@ func (a *adminTag) FindByID(id primitive.ObjectID) (*types.AdminTag, error) { return &adminTag, nil } -func (a *adminTag) FindTags(name string, page int64) (*types.FindAdminTagResult, error) { +func (a *adminTag) FindTags( + name string, + page int64, +) (*types.FindAdminTagResult, error) { if page < 0 || page == 0 { return nil, e.New(e.InvalidPageNumber, "AdminTagMongo FindTags failed") } diff --git a/internal/app/repositories/mongo/admin_user.go b/internal/app/repositories/mongo/admin_user.go index ac76dd5..9d413ed 100644 --- a/internal/app/repositories/mongo/admin_user.go +++ b/internal/app/repositories/mongo/admin_user.go @@ -54,7 +54,9 @@ func (a *adminUser) FindByID(id primitive.ObjectID) (*types.AdminUser, error) { return &adminUser, nil } -func (a *adminUser) GetLoginInfo(id primitive.ObjectID) (*types.LoginInfo, error) { +func (a *adminUser) GetLoginInfo( + id primitive.ObjectID, +) (*types.LoginInfo, error) { loginInfo := &types.LoginInfo{} filter := bson.M{"_id": id} projection := bson.M{ @@ -65,14 +67,18 @@ func (a *adminUser) GetLoginInfo(id primitive.ObjectID) (*types.LoginInfo, error } findOneOptions := options.FindOne() findOneOptions.SetProjection(projection) - err := a.c.FindOne(context.Background(), filter, findOneOptions).Decode(&loginInfo) + err := a.c.FindOne(context.Background(), filter, findOneOptions). + Decode(&loginInfo) if err != nil { return nil, e.Wrap(err, "AdminUserMongo GetLoginInfo failed") } return loginInfo, nil } -func (a *adminUser) UpdateLoginInfo(id primitive.ObjectID, i *types.LoginInfo) error { +func (a *adminUser) UpdateLoginInfo( + id primitive.ObjectID, + i *types.LoginInfo, +) error { filter := bson.M{"_id": id} update := bson.M{"$set": bson.M{ "currentLoginIP": i.CurrentLoginIP, diff --git a/internal/app/repositories/mongo/business_mongo.go b/internal/app/repositories/mongo/business_mongo.go index ffd7359..849c5b6 100644 --- a/internal/app/repositories/mongo/business_mongo.go +++ b/internal/app/repositories/mongo/business_mongo.go @@ -6,8 +6,8 @@ import ( "github.com/ic3network/mccs-alpha/global/constant" "github.com/ic3network/mccs-alpha/internal/app/types" - "github.com/ic3network/mccs-alpha/internal/pkg/helper" "github.com/ic3network/mccs-alpha/internal/pkg/e" + "github.com/ic3network/mccs-alpha/internal/pkg/helper" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" @@ -37,7 +37,10 @@ func (b *business) FindByID(id primitive.ObjectID) (*types.Business, error) { return &business, nil } -func (b *business) UpdateTradingInfo(id primitive.ObjectID, data *types.TradingRegisterData) error { +func (b *business) UpdateTradingInfo( + id primitive.ObjectID, + data *types.TradingRegisterData, +) error { filter := bson.M{"_id": id} update := bson.M{"$set": bson.M{ "businessName": data.BusinessName, @@ -120,7 +123,9 @@ func (b *business) UpdateBusiness( var writes []mongo.WriteModel for _, upd := range updates { - model := mongo.NewUpdateOneModel().SetFilter(bson.M{"_id": id}).SetUpdate(upd) + model := mongo.NewUpdateOneModel(). + SetFilter(bson.M{"_id": id}). + SetUpdate(upd) writes = append(writes, model) } @@ -148,7 +153,9 @@ func (b *business) SetMemberStartedAt(id primitive.ObjectID) error { } // Create creates a business record in the table. -func (b *business) Create(data *types.BusinessData) (primitive.ObjectID, error) { +func (b *business) Create( + data *types.BusinessData, +) (primitive.ObjectID, error) { doc := bson.M{ "businessName": data.BusinessName, "businessPhone": data.BusinessPhone, @@ -174,7 +181,10 @@ func (b *business) Create(data *types.BusinessData) (primitive.ObjectID, error) return res.InsertedID.(primitive.ObjectID), nil } -func (b *business) UpdateAllTagsCreatedAt(id primitive.ObjectID, t time.Time) error { +func (b *business) UpdateAllTagsCreatedAt( + id primitive.ObjectID, + t time.Time, +) error { filter := bson.M{"_id": id} update := bson.M{"$set": bson.M{ "offers.$[].createdAt": t, diff --git a/internal/app/repositories/mongo/lost_password_mongo.go b/internal/app/repositories/mongo/lost_password_mongo.go index 7a3ce94..bc3842b 100644 --- a/internal/app/repositories/mongo/lost_password_mongo.go +++ b/internal/app/repositories/mongo/lost_password_mongo.go @@ -45,7 +45,8 @@ func (l *lostPassword) FindByToken(token string) (*types.LostPassword, error) { return nil, e.New(e.TokenInvalid, "token not found") } lostPassword := types.LostPassword{} - err := l.c.FindOne(context.Background(), types.LostPassword{Token: token}).Decode(&lostPassword) + err := l.c.FindOne(context.Background(), types.LostPassword{Token: token}). + Decode(&lostPassword) if err != nil { return nil, e.New(e.TokenInvalid, "token not found") } @@ -57,7 +58,8 @@ func (l *lostPassword) FindByEmail(email string) (*types.LostPassword, error) { return nil, e.New(e.TokenInvalid, "token not found") } lostPassword := types.LostPassword{} - err := l.c.FindOne(context.Background(), types.LostPassword{Email: email}).Decode(&lostPassword) + err := l.c.FindOne(context.Background(), types.LostPassword{Email: email}). + Decode(&lostPassword) if err != nil { return nil, e.New(e.TokenInvalid, "token not found") } diff --git a/internal/app/repositories/mongo/mongo.go b/internal/app/repositories/mongo/mongo.go index 5f45331..7e23da7 100644 --- a/internal/app/repositories/mongo/mongo.go +++ b/internal/app/repositories/mongo/mongo.go @@ -37,7 +37,9 @@ func registerCollections(db *mongo.Database) { func New() *mongo.Database { ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) - client, err := mongo.NewClient(options.Client().ApplyURI(viper.GetString("mongo.url"))) + client, err := mongo.NewClient( + options.Client().ApplyURI(viper.GetString("mongo.url")), + ) if err != nil { log.Fatal(err) } diff --git a/internal/app/repositories/mongo/tag_mongo.go b/internal/app/repositories/mongo/tag_mongo.go index 2f3a295..d54e41b 100644 --- a/internal/app/repositories/mongo/tag_mongo.go +++ b/internal/app/repositories/mongo/tag_mongo.go @@ -59,7 +59,9 @@ func (t *tag) UpdateOffer(name string) (primitive.ObjectID, error) { context.Background(), filter, update, - options.FindOneAndUpdate().SetUpsert(true).SetReturnDocument(options.After), + options.FindOneAndUpdate(). + SetUpsert(true). + SetReturnDocument(options.After), ) if res.Err() != nil { return primitive.ObjectID{}, res.Err() @@ -89,7 +91,9 @@ func (t *tag) UpdateWant(name string) (primitive.ObjectID, error) { context.Background(), filter, update, - options.FindOneAndUpdate().SetUpsert(true).SetReturnDocument(options.After), + options.FindOneAndUpdate(). + SetUpsert(true). + SetReturnDocument(options.After), ) if res.Err() != nil { return primitive.ObjectID{}, res.Err() diff --git a/internal/app/repositories/mongo/user_action.go b/internal/app/repositories/mongo/user_action.go index 8cb7d2a..2eb9462 100644 --- a/internal/app/repositories/mongo/user_action.go +++ b/internal/app/repositories/mongo/user_action.go @@ -41,10 +41,16 @@ func (u *userAction) Log(a *types.UserAction) error { return nil } -func (u *userAction) Find(c *types.UserActionSearchCriteria, page int64) ([]*types.UserAction, int, error) { +func (u *userAction) Find( + c *types.UserActionSearchCriteria, + page int64, +) ([]*types.UserAction, int, error) { ctx := context.Background() if page < 0 || page == 0 { - return nil, 0, e.New(e.InvalidPageNumber, "mongo.userAction.Find failed") + return nil, 0, e.New( + e.InvalidPageNumber, + "mongo.userAction.Find failed", + ) } var results []*types.UserAction diff --git a/internal/app/repositories/mongo/user_mongo.go b/internal/app/repositories/mongo/user_mongo.go index 33463e3..70c4c1e 100644 --- a/internal/app/repositories/mongo/user_mongo.go +++ b/internal/app/repositories/mongo/user_mongo.go @@ -68,7 +68,10 @@ func (u *user) FindByBusinessID(id primitive.ObjectID) (*types.User, error) { return &user, nil } -func (u *user) UpdateTradingInfo(id primitive.ObjectID, data *types.TradingRegisterData) error { +func (u *user) UpdateTradingInfo( + id primitive.ObjectID, + data *types.TradingRegisterData, +) error { filter := bson.M{"_id": id} update := bson.M{"$set": bson.M{ "firstName": data.FirstName, @@ -176,7 +179,9 @@ func (u *user) FindByIDs(ids []string) ([]*types.User, error) { func (u *user) UpdatePassword(user *types.User) error { filter := bson.M{"_id": user.ID} - update := bson.M{"$set": bson.M{"password": user.Password, "updatedAt": time.Now()}} + update := bson.M{ + "$set": bson.M{"password": user.Password, "updatedAt": time.Now()}, + } _, err := u.c.UpdateOne( context.Background(), filter, @@ -234,7 +239,11 @@ func (u *user) AdminUpdateUser(user *types.User) error { return nil } -func (u *user) UpdateLoginAttempts(email string, attempts int, lockUser bool) error { +func (u *user) UpdateLoginAttempts( + email string, + attempts int, + lockUser bool, +) error { filter := bson.M{"email": email} set := bson.M{ "loginAttempts": attempts, @@ -266,14 +275,18 @@ func (u *user) GetLoginInfo(id primitive.ObjectID) (*types.LoginInfo, error) { } findOneOptions := options.FindOne() findOneOptions.SetProjection(projection) - err := u.c.FindOne(context.Background(), filter, findOneOptions).Decode(&loginInfo) + err := u.c.FindOne(context.Background(), filter, findOneOptions). + Decode(&loginInfo) if err != nil { return nil, e.Wrap(err, "UserMongo GetLoginInfo failed") } return loginInfo, nil } -func (u *user) UpdateLoginInfo(id primitive.ObjectID, i *types.LoginInfo) error { +func (u *user) UpdateLoginInfo( + id primitive.ObjectID, + i *types.LoginInfo, +) error { filter := bson.M{"_id": id} update := bson.M{"$set": bson.M{ "currentLoginIP": i.CurrentLoginIP, @@ -339,13 +352,16 @@ func (u *user) ToggleShowRecentMatchedTags(id primitive.ObjectID) error { projection := bson.M{"showRecentMatchedTags": 1} findOneOptions := options.FindOne() findOneOptions.SetProjection(projection) - err := u.c.FindOne(context.Background(), filter, findOneOptions).Decode(&res) + err := u.c.FindOne(context.Background(), filter, findOneOptions). + Decode(&res) if err != nil { return e.Wrap(err, "UserMongo ToggleShowRecentMatchedTags failed") } filter = bson.M{"_id": id} - update := bson.M{"$set": bson.M{"showRecentMatchedTags": !res.ShowRecentMatchedTags}} + update := bson.M{ + "$set": bson.M{"showRecentMatchedTags": !res.ShowRecentMatchedTags}, + } _, err = u.c.UpdateOne(context.Background(), filter, update) if err != nil { return e.Wrap(err, "UserMongo ToggleShowRecentMatchedTags failed") diff --git a/internal/app/repositories/pg/balance_limit.go b/internal/app/repositories/pg/balance_limit.go index b72f329..0251402 100644 --- a/internal/app/repositories/pg/balance_limit.go +++ b/internal/app/repositories/pg/balance_limit.go @@ -26,7 +26,9 @@ func (b balanceLimit) Create(tx *gorm.DB, accountID uint) error { return nil } -func (b balanceLimit) FindByAccountID(accountID uint) (*types.BalanceLimit, error) { +func (b balanceLimit) FindByAccountID( + accountID uint, +) (*types.BalanceLimit, error) { balance := new(types.BalanceLimit) err := db.Where("account_id = ?", accountID).First(balance).Error if err != nil { @@ -35,7 +37,11 @@ func (b balanceLimit) FindByAccountID(accountID uint) (*types.BalanceLimit, erro return balance, nil } -func (b balanceLimit) Update(id uint, maxPosBal float64, maxNegBal float64) error { +func (b balanceLimit) Update( + id uint, + maxPosBal float64, + maxNegBal float64, +) error { if math.Abs(maxNegBal) == 0 { maxNegBal = 0 } else { diff --git a/internal/app/repositories/pg/posting.go b/internal/app/repositories/pg/posting.go index 219f55e..91a7586 100644 --- a/internal/app/repositories/pg/posting.go +++ b/internal/app/repositories/pg/posting.go @@ -11,7 +11,10 @@ type posting struct{} var Posting = &posting{} -func (t *posting) FindInRange(from time.Time, to time.Time) ([]*types.Posting, error) { +func (t *posting) FindInRange( + from time.Time, + to time.Time, +) ([]*types.Posting, error) { var result []*types.Posting err := db.Raw(` SELECT P.amount, P.created_at diff --git a/internal/app/repositories/pg/transaction.go b/internal/app/repositories/pg/transaction.go index b3c7c50..403e861 100644 --- a/internal/app/repositories/pg/transaction.go +++ b/internal/app/repositories/pg/transaction.go @@ -53,24 +53,38 @@ func (t *transaction) Create( journalID := journalRecord.ID // Create postings. - err = tx.Create(&types.Posting{AccountID: fromID, JournalID: journalID, Amount: -amount}).Error + err = tx.Create( + &types.Posting{ + AccountID: fromID, + JournalID: journalID, + Amount: -amount, + }, + ).Error if err != nil { tx.Rollback() return e.Wrap(err, "pg.Transaction.Create") } - err = tx.Create(&types.Posting{AccountID: toID, JournalID: journalID, Amount: amount}).Error + err = tx.Create( + &types.Posting{AccountID: toID, JournalID: journalID, Amount: amount}, + ).Error if err != nil { tx.Rollback() return e.Wrap(err, "pg.Transaction.Create") } // Update accounts' balance. - err = tx.Model(&types.Account{}).Where("id = ?", fromID).Update("balance", gorm.Expr("balance - ?", amount)).Error + err = tx.Model(&types.Account{}). + Where("id = ?", fromID). + Update("balance", gorm.Expr("balance - ?", amount)). + Error if err != nil { tx.Rollback() return e.Wrap(err, "pg.Transaction.Create") } - err = tx.Model(&types.Account{}).Where("id = ?", toID).Update("balance", gorm.Expr("balance + ?", amount)).Error + err = tx.Model(&types.Account{}). + Where("id = ?", toID). + Update("balance", gorm.Expr("balance + ?", amount)). + Error if err != nil { tx.Rollback() return e.Wrap(err, "pg.Transaction.Create") @@ -189,12 +203,18 @@ func (t *transaction) Accept( } // Update accounts' balance. - err = tx.Model(&types.Account{}).Where("id = ?", fromID).Update("balance", gorm.Expr("balance - ?", amount)).Error + err = tx.Model(&types.Account{}). + Where("id = ?", fromID). + Update("balance", gorm.Expr("balance - ?", amount)). + Error if err != nil { tx.Rollback() return e.Wrap(err, "pg.Transaction.Accept") } - err = tx.Model(&types.Account{}).Where("id = ?", toID).Update("balance", gorm.Expr("balance + ?", amount)).Error + err = tx.Model(&types.Account{}). + Where("id = ?", toID). + Update("balance", gorm.Expr("balance + ?", amount)). + Error if err != nil { tx.Rollback() return e.Wrap(err, "pg.Transaction.Accept") @@ -252,7 +272,12 @@ func (t *transaction) FindRecent(id uint) ([]*types.Transaction, error) { } // FindInRange finds the completed transactions in specific time range. -func (t *transaction) FindInRange(id uint, dateFrom time.Time, dateTo time.Time, page int) ([]*types.Transaction, int, error) { +func (t *transaction) FindInRange( + id uint, + dateFrom time.Time, + dateTo time.Time, + page int, +) ([]*types.Transaction, int, error) { limit := viper.GetInt("page_size") offset := viper.GetInt("page_size") * (page - 1) @@ -277,7 +302,9 @@ func (t *transaction) FindInRange(id uint, dateFrom time.Time, dateTo time.Time, `, id, dateFrom, dateTo, limit, offset).Scan(&result).Error var numberOfResults int64 - db.Model(&types.Posting{}).Where("account_id = ? AND (created_at BETWEEN ? AND ?)", id, dateFrom, dateTo).Count(&numberOfResults) + db.Model(&types.Posting{}). + Where("account_id = ? AND (created_at BETWEEN ? AND ?)", id, dateFrom, dateTo). + Count(&numberOfResults) totalPages := pagination.Pages(numberOfResults, viper.GetInt64("page_size")) if err != nil { diff --git a/internal/app/service/admin_tag.go b/internal/app/service/admin_tag.go index 55028ee..57458a2 100644 --- a/internal/app/service/admin_tag.go +++ b/internal/app/service/admin_tag.go @@ -35,7 +35,10 @@ func (a *adminTag) FindByID(id primitive.ObjectID) (*types.AdminTag, error) { return adminTag, nil } -func (a *adminTag) FindTags(name string, page int64) (*types.FindAdminTagResult, error) { +func (a *adminTag) FindTags( + name string, + page int64, +) (*types.FindAdminTagResult, error) { result, err := mongo.AdminTag.FindTags(name, page) if err != nil { return nil, e.Wrap(err, "AdminTagService FindTags failed") diff --git a/internal/app/service/admin_user.go b/internal/app/service/admin_user.go index e609932..cdf6077 100644 --- a/internal/app/service/admin_user.go +++ b/internal/app/service/admin_user.go @@ -12,7 +12,10 @@ type adminUser struct{} var AdminUser = &adminUser{} -func (a *adminUser) Login(email string, password string) (*types.AdminUser, error) { +func (a *adminUser) Login( + email string, + password string, +) (*types.AdminUser, error) { user, err := mongo.AdminUser.FindByEmail(email) if err != nil { return &types.AdminUser{}, e.Wrap(err, "login admin user failed") diff --git a/internal/app/service/balance_limit.go b/internal/app/service/balance_limit.go index ba25154..014f64c 100644 --- a/internal/app/service/balance_limit.go +++ b/internal/app/service/balance_limit.go @@ -55,13 +55,18 @@ func (b balanceLimit) IsExceedLimit(id uint, balance float64) (bool, error) { return false, e.Wrap(err, "service.BalanceLimit.FindByAccountID failed") } // MaxNegBal should be positive in the DB. - if balance < -(math.Abs(balanceLimitRecord.MaxNegBal)) || balance > balanceLimitRecord.MaxPosBal { + if balance < -(math.Abs(balanceLimitRecord.MaxNegBal)) || + balance > balanceLimitRecord.MaxPosBal { return true, nil } return false, nil } -func (b balanceLimit) Update(id uint, maxPosBal float64, maxNegBal float64) error { +func (b balanceLimit) Update( + id uint, + maxPosBal float64, + maxNegBal float64, +) error { err := pg.BalanceLimit.Update(id, maxPosBal, maxNegBal) if err != nil { return err diff --git a/internal/app/service/balancecheck/balancecheck.go b/internal/app/service/balancecheck/balancecheck.go index 9785046..42002f2 100644 --- a/internal/app/service/balancecheck/balancecheck.go +++ b/internal/app/service/balancecheck/balancecheck.go @@ -28,7 +28,10 @@ func Run() { if sum != 0.0 { err := email.Balance.NonZeroBalance(from, to) if err != nil { - l.Logger.Error("sending NonZeroBalance email failed", zap.Error(err)) + l.Logger.Error( + "sending NonZeroBalance email failed", + zap.Error(err), + ) } } } diff --git a/internal/app/service/business.go b/internal/app/service/business.go index 485a0d6..3c6a043 100644 --- a/internal/app/service/business.go +++ b/internal/app/service/business.go @@ -22,7 +22,9 @@ func (b *business) FindByID(id primitive.ObjectID) (*types.Business, error) { return bs, nil } -func (b *business) Create(business *types.BusinessData) (primitive.ObjectID, error) { +func (b *business) Create( + business *types.BusinessData, +) (primitive.ObjectID, error) { id, err := mongo.Business.Create(business) if err != nil { return primitive.ObjectID{}, e.Wrap(err, "create business failed") @@ -58,7 +60,10 @@ func (b *business) SetMemberStartedAt(id primitive.ObjectID) error { return nil } -func (b *business) UpdateAllTagsCreatedAt(id primitive.ObjectID, t time.Time) error { +func (b *business) UpdateAllTagsCreatedAt( + id primitive.ObjectID, + t time.Time, +) error { err := es.Business.UpdateAllTagsCreatedAt(id, t) if err != nil { return e.Wrap(err, "BusinessService UpdateAllTagsCreatedAt failed") @@ -70,7 +75,10 @@ func (b *business) UpdateAllTagsCreatedAt(id primitive.ObjectID, t time.Time) er return nil } -func (b *business) FindBusiness(c *types.SearchCriteria, page int64) (*types.FindBusinessResult, error) { +func (b *business) FindBusiness( + c *types.SearchCriteria, + page int64, +) (*types.FindBusinessResult, error) { ids, numberOfResults, totalPages, err := es.Business.Find(c, page) if err != nil { return nil, e.Wrap(err, "BusinessService FindBusiness failed") diff --git a/internal/app/service/dailyemail/dailyemail.go b/internal/app/service/dailyemail/dailyemail.go index 91f2dc4..a2dd235 100644 --- a/internal/app/service/dailyemail/dailyemail.go +++ b/internal/app/service/dailyemail/dailyemail.go @@ -37,7 +37,8 @@ func createEmailWorker(u *types.User) func() { l.Logger.Error("dailyemail failed", zap.Error(err)) return } - if len(matchedTags.MatchedOffers) == 0 && len(matchedTags.MatchedWants) == 0 { + if len(matchedTags.MatchedOffers) == 0 && + len(matchedTags.MatchedWants) == 0 { return } err = email.SendDailyEmailList(u, matchedTags) @@ -57,11 +58,17 @@ func getMatchTags(user *types.User) (*types.MatchedTags, error) { return nil, e.Wrap(err, "getMatchTags failed") } - matchedOffers, err := service.Tag.MatchOffers(helper.GetTagNames(business.Offers), user.LastNotificationSentDate) + matchedOffers, err := service.Tag.MatchOffers( + helper.GetTagNames(business.Offers), + user.LastNotificationSentDate, + ) if err != nil { return nil, e.Wrap(err, "getMatchTags failed") } - matchedWants, err := service.Tag.MatchWants(helper.GetTagNames(business.Wants), user.LastNotificationSentDate) + matchedWants, err := service.Tag.MatchWants( + helper.GetTagNames(business.Wants), + user.LastNotificationSentDate, + ) if err != nil { return nil, e.Wrap(err, "getMatchTags failed") } diff --git a/internal/app/service/lostpassword.go b/internal/app/service/lostpassword.go index 22a2c27..72084ce 100644 --- a/internal/app/service/lostpassword.go +++ b/internal/app/service/lostpassword.go @@ -46,7 +46,13 @@ func (s *lostpassword) SetTokenUsed(token string) error { } func (s *lostpassword) TokenInvalid(l *types.LostPassword) bool { - if time.Now().Sub(l.CreatedAt).Seconds() >= viper.GetFloat64("reset_password_timeout") || l.TokenUsed == true { + if time.Now(). + Sub(l.CreatedAt). + Seconds() >= + viper.GetFloat64( + "reset_password_timeout", + ) || + l.TokenUsed == true { return true } return false diff --git a/internal/app/service/tag.go b/internal/app/service/tag.go index 3725301..c194bc3 100644 --- a/internal/app/service/tag.go +++ b/internal/app/service/tag.go @@ -102,7 +102,10 @@ func (t *tag) DeleteByID(id primitive.ObjectID) error { // MatchOffers loops through user's offers and finds out the matched wants. // Only add to the result when matches more than one tag. -func (t *tag) MatchOffers(offers []string, lastLoginDate time.Time) (map[string][]string, error) { +func (t *tag) MatchOffers( + offers []string, + lastLoginDate time.Time, +) (map[string][]string, error) { resultMap := make(map[string][]string, len(offers)) for _, offer := range offers { @@ -120,7 +123,10 @@ func (t *tag) MatchOffers(offers []string, lastLoginDate time.Time) (map[string] // MatchWants loops through user's wants and finds out the matched offers. // Only add to the result when matches more than one tag. -func (t *tag) MatchWants(wants []string, lastLoginDate time.Time) (map[string][]string, error) { +func (t *tag) MatchWants( + wants []string, + lastLoginDate time.Time, +) (map[string][]string, error) { resultMap := make(map[string][]string, len(wants)) for _, want := range wants { diff --git a/internal/app/service/trading.go b/internal/app/service/trading.go index dd6cdd0..fce5aa5 100644 --- a/internal/app/service/trading.go +++ b/internal/app/service/trading.go @@ -11,7 +11,10 @@ type trading struct{} var Trading = &trading{} -func (t *trading) UpdateBusiness(id primitive.ObjectID, data *types.TradingRegisterData) error { +func (t *trading) UpdateBusiness( + id primitive.ObjectID, + data *types.TradingRegisterData, +) error { err := es.Business.UpdateTradingInfo(id, data) if err != nil { return err @@ -23,7 +26,10 @@ func (t *trading) UpdateBusiness(id primitive.ObjectID, data *types.TradingRegis return nil } -func (t *trading) UpdateUser(id primitive.ObjectID, data *types.TradingRegisterData) error { +func (t *trading) UpdateUser( + id primitive.ObjectID, + data *types.TradingRegisterData, +) error { err := es.User.UpdateTradingInfo(id, data) if err != nil { return err diff --git a/internal/app/service/transaction.go b/internal/app/service/transaction.go index 9194e97..b3ec870 100644 --- a/internal/app/service/transaction.go +++ b/internal/app/service/transaction.go @@ -15,7 +15,10 @@ type transaction struct{} // Transaction services. var Transaction = &transaction{} -func (t *transaction) maxBalanceCanBeTransferred(a *types.Account, kind string) (float64, error) { +func (t *transaction) maxBalanceCanBeTransferred( + a *types.Account, + kind string, +) (float64, error) { if kind == "positive" { maxPosBal, err := BalanceLimit.GetMaxPosBalance(a.ID) if err != nil { @@ -74,7 +77,12 @@ func (t *transaction) Propose( if err != nil { return nil, e.Wrap(err, "service.Transaction.Propose") } - return nil, e.CustomMessage("Sender will exceed its credit limit." + " The maximum amount that can be sent is: " + fmt.Sprintf("%.2f", amount)) + return nil, e.CustomMessage( + "Sender will exceed its credit limit." + " The maximum amount that can be sent is: " + fmt.Sprintf( + "%.2f", + amount, + ), + ) } exceed, err = BalanceLimit.IsExceedLimit(to.ID, to.Balance+amount) if err != nil { @@ -85,7 +93,12 @@ func (t *transaction) Propose( if err != nil { return nil, e.Wrap(err, "service.Transaction.Propose") } - return nil, e.CustomMessage("Receiver will exceed its maximum balance limit." + " The maximum amount that can be received is: " + fmt.Sprintf("%.2f", amount)) + return nil, e.CustomMessage( + "Receiver will exceed its maximum balance limit." + " The maximum amount that can be received is: " + fmt.Sprintf( + "%.2f", + amount, + ), + ) } transaction, err := pg.Transaction.Propose( @@ -113,7 +126,9 @@ func (t *transaction) Find(transactionID uint) (*types.Transaction, error) { return transaction, nil } -func (t *transaction) FindPendings(accountID uint) ([]*types.Transaction, error) { +func (t *transaction) FindPendings( + accountID uint, +) ([]*types.Transaction, error) { transactions, err := pg.Transaction.FindPendings(accountID) if err != nil { return nil, err @@ -155,8 +170,18 @@ func (t *transaction) FindRecent(accountID uint) ([]*types.Transaction, error) { return transactions, nil } -func (t *transaction) FindInRange(accountID uint, dateFrom time.Time, dateTo time.Time, page int) ([]*types.Transaction, int, error) { - transactions, totalPages, err := pg.Transaction.FindInRange(accountID, dateFrom, dateTo, page) +func (t *transaction) FindInRange( + accountID uint, + dateFrom time.Time, + dateTo time.Time, + page int, +) ([]*types.Transaction, int, error) { + transactions, totalPages, err := pg.Transaction.FindInRange( + accountID, + dateFrom, + dateTo, + page, + ) if err != nil { return nil, 0, err } diff --git a/internal/app/service/user.go b/internal/app/service/user.go index fb408bb..caa5bce 100644 --- a/internal/app/service/user.go +++ b/internal/app/service/user.go @@ -69,7 +69,12 @@ func (u *user) Login(email string, password string) (*types.User, error) { return &types.User{}, e.Wrap(err, "login user failed") } - if time.Now().Sub(user.LastLoginFailDate).Seconds() <= viper.GetFloat64("login_attempts_timeout") { + if time.Now(). + Sub(user.LastLoginFailDate). + Seconds() <= + viper.GetFloat64( + "login_attempts_timeout", + ) { return &types.User{}, e.New(e.AccountLocked, "") } @@ -90,7 +95,10 @@ func (u *user) UserEmailExists(email string) bool { return true } -func (u *user) FindUsers(user *types.User, page int64) (*types.FindUserResult, error) { +func (u *user) FindUsers( + user *types.User, + page int64, +) (*types.FindUserResult, error) { ids, numberOfResults, totalPages, err := es.User.Find(user, page) if err != nil { return nil, e.Wrap(err, "UserService FindUsers failed") @@ -236,7 +244,9 @@ func (u *user) ToggleShowRecentMatchedTags(id primitive.ObjectID) error { return nil } -func (u *user) AddToFavoriteBusinesses(uID, businessID primitive.ObjectID) error { +func (u *user) AddToFavoriteBusinesses( + uID, businessID primitive.ObjectID, +) error { err := mongo.User.AddToFavoriteBusinesses(uID, businessID) if err != nil { return e.Wrap(err, "UserService AddToFavoriteBusinesses failed") @@ -244,7 +254,9 @@ func (u *user) AddToFavoriteBusinesses(uID, businessID primitive.ObjectID) error return nil } -func (u *user) RemoveFromFavoriteBusinesses(uID, businessID primitive.ObjectID) error { +func (u *user) RemoveFromFavoriteBusinesses( + uID, businessID primitive.ObjectID, +) error { err := mongo.User.RemoveFromFavoriteBusinesses(uID, businessID) if err != nil { return e.Wrap(err, "UserService RemoveFromFavoriteBusinesses failed") diff --git a/internal/app/service/user_action.go b/internal/app/service/user_action.go index ae8eb3a..a2a3d38 100644 --- a/internal/app/service/user_action.go +++ b/internal/app/service/user_action.go @@ -21,7 +21,10 @@ func (u *userAction) Log(log *types.UserAction) error { return nil } -func (u *userAction) Find(c *types.UserActionSearchCriteria, page int64) ([]*types.UserAction, int, error) { +func (u *userAction) Find( + c *types.UserActionSearchCriteria, + page int64, +) ([]*types.UserAction, int, error) { userActions, totalPages, err := mongo.UserAction.Find(c, page) if err != nil { return nil, 0, e.Wrap(err, "UserActionService Find failed") diff --git a/internal/app/types/admin_tag.go b/internal/app/types/admin_tag.go index 63d7991..a2149d0 100644 --- a/internal/app/types/admin_tag.go +++ b/internal/app/types/admin_tag.go @@ -8,7 +8,7 @@ import ( // AdminTag is the model representation of an admin tag in the data model. type AdminTag struct { - ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` + ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` DeletedAt time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"` diff --git a/internal/app/types/admin_user.go b/internal/app/types/admin_user.go index 25843e4..2fa6fa9 100644 --- a/internal/app/types/admin_user.go +++ b/internal/app/types/admin_user.go @@ -8,18 +8,18 @@ import ( // AdminUser is the model representation of an admin user in the data model. type AdminUser struct { - ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` + ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` DeletedAt time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"` - Email string `json:"email,omitempty" bson:"email,omitempty"` - Name string `json:"name,omitempty" bson:"name,omitempty"` + Email string `json:"email,omitempty" bson:"email,omitempty"` + Name string `json:"name,omitempty" bson:"name,omitempty"` Password string `json:"password,omitempty" bson:"password,omitempty"` - Roles []string `json:"roles,omitempty" bson:"roles,omitempty"` + Roles []string `json:"roles,omitempty" bson:"roles,omitempty"` - CurrentLoginIP string `json:"currentLoginIP,omitempty" bson:"currentLoginIP,omitempty"` + CurrentLoginIP string `json:"currentLoginIP,omitempty" bson:"currentLoginIP,omitempty"` CurrentLoginDate time.Time `json:"currentLoginDate,omitempty" bson:"currentLoginDate,omitempty"` - LastLoginIP string `json:"lastLoginIP,omitempty" bson:"lastLoginIP,omitempty"` - LastLoginDate time.Time `json:"lastLoginDate,omitempty" bson:"lastLoginDate,omitempty"` + LastLoginIP string `json:"lastLoginIP,omitempty" bson:"lastLoginIP,omitempty"` + LastLoginDate time.Time `json:"lastLoginDate,omitempty" bson:"lastLoginDate,omitempty"` } diff --git a/internal/app/types/business.go b/internal/app/types/business.go index 28e24a6..b35cd27 100644 --- a/internal/app/types/business.go +++ b/internal/app/types/business.go @@ -8,33 +8,33 @@ import ( // Business is the model representation of a business in the data model. type Business struct { - ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` + ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` DeletedAt time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"` - BusinessName string `json:"businessName,omitempty" bson:"businessName,omitempty"` - BusinessPhone string `json:"businessPhone,omitempty" bson:"businessPhone,omitempty"` - IncType string `json:"incType,omitempty" bson:"incType,omitempty"` - CompanyNumber string `json:"companyNumber,omitempty" bson:"companyNumber,omitempty"` - Website string `json:"website,omitempty" bson:"website,omitempty"` - Turnover int `json:"turnover,omitempty" bson:"turnover,omitempty"` - Offers []*TagField `json:"offers,omitempty" bson:"offers,omitempty"` - Wants []*TagField `json:"wants,omitempty" bson:"wants,omitempty"` - Description string `json:"description,omitempty" bson:"description,omitempty"` - LocationAddress string `json:"locationAddress,omitempty" bson:"locationAddress,omitempty"` - LocationCity string `json:"locationCity,omitempty" bson:"locationCity,omitempty"` - LocationRegion string `json:"locationRegion,omitempty" bson:"locationRegion,omitempty"` + BusinessName string `json:"businessName,omitempty" bson:"businessName,omitempty"` + BusinessPhone string `json:"businessPhone,omitempty" bson:"businessPhone,omitempty"` + IncType string `json:"incType,omitempty" bson:"incType,omitempty"` + CompanyNumber string `json:"companyNumber,omitempty" bson:"companyNumber,omitempty"` + Website string `json:"website,omitempty" bson:"website,omitempty"` + Turnover int `json:"turnover,omitempty" bson:"turnover,omitempty"` + Offers []*TagField `json:"offers,omitempty" bson:"offers,omitempty"` + Wants []*TagField `json:"wants,omitempty" bson:"wants,omitempty"` + Description string `json:"description,omitempty" bson:"description,omitempty"` + LocationAddress string `json:"locationAddress,omitempty" bson:"locationAddress,omitempty"` + LocationCity string `json:"locationCity,omitempty" bson:"locationCity,omitempty"` + LocationRegion string `json:"locationRegion,omitempty" bson:"locationRegion,omitempty"` LocationPostalCode string `json:"locationPostalCode,omitempty" bson:"locationPostalCode,omitempty"` - LocationCountry string `json:"locationCountry,omitempty" bson:"locationCountry,omitempty"` - Status string `json:"status,omitempty" bson:"status,omitempty"` - AdminTags []string `json:"adminTags,omitempty" bson:"adminTags,omitempty"` + LocationCountry string `json:"locationCountry,omitempty" bson:"locationCountry,omitempty"` + Status string `json:"status,omitempty" bson:"status,omitempty"` + AdminTags []string `json:"adminTags,omitempty" bson:"adminTags,omitempty"` // Timestamp when trading status applied - MemberStartedAt time.Time `json:"memberStartedAt,omitempty" bson:"memberStartedAt,omitempty"` + MemberStartedAt time.Time `json:"memberStartedAt,omitempty" bson:"memberStartedAt,omitempty"` } type TagField struct { - Name string `json:"name,omitempty" bson:"name,omitempty"` + Name string `json:"name,omitempty" bson:"name,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"` } diff --git a/internal/app/types/lost_password.go b/internal/app/types/lost_password.go index 544cae7..05c45e3 100644 --- a/internal/app/types/lost_password.go +++ b/internal/app/types/lost_password.go @@ -8,9 +8,9 @@ import ( // LostPassword is the model representation of a lost password in the data model. type LostPassword struct { - ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` + ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"` - Email string `json:"email,omitempty" bson:"email,omitempty"` - Token string `json:"token,omitempty" bson:"token,omitempty"` + Email string `json:"email,omitempty" bson:"email,omitempty"` + Token string `json:"token,omitempty" bson:"token,omitempty"` TokenUsed bool `json:"tokenUsed,omitempty" bson:"tokenUsed,omitempty"` } diff --git a/internal/app/types/tag.go b/internal/app/types/tag.go index f3a5bed..8e4d11a 100644 --- a/internal/app/types/tag.go +++ b/internal/app/types/tag.go @@ -8,14 +8,14 @@ import ( // Tag is the model representation of a tag in the data model. type Tag struct { - ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` + ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` DeletedAt time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"` - Name string `json:"name,omitempty" bson:"name,omitempty"` + Name string `json:"name,omitempty" bson:"name,omitempty"` OfferAddedAt time.Time `json:"offerAddedAt,omitempty" bson:"offerAddedAt,omitempty"` - WantAddedAt time.Time `json:"wantAddedAt,omitempty" bson:"wantAddedAt,omitempty"` + WantAddedAt time.Time `json:"wantAddedAt,omitempty" bson:"wantAddedAt,omitempty"` } type TagESRecord struct { diff --git a/internal/app/types/trading.go b/internal/app/types/trading.go index 3ee8888..da823c2 100644 --- a/internal/app/types/trading.go +++ b/internal/app/types/trading.go @@ -69,8 +69,12 @@ func (t *TradingRegisterData) Validate() []string { } else if len(t.Description) > 500 { errs = append(errs, "Business description cannot exceed 500 characters.") } - if t.Website != "" && !strings.HasPrefix(t.Website, "http://") && !strings.HasPrefix(t.Website, "https://") { - errs = append(errs, "Website URL should start with http:// or https://.") + if t.Website != "" && !strings.HasPrefix(t.Website, "http://") && + !strings.HasPrefix(t.Website, "https://") { + errs = append( + errs, + "Website URL should start with http:// or https://.", + ) } else if len(t.Website) > 100 { errs = append(errs, "Website URL cannot exceed 100 characters.") } @@ -119,7 +123,10 @@ func (t *TradingRegisterData) Validate() []string { errs = append(errs, "Telephone cannot exceed 25 characters.") } if t.Authorised != "on" { - errs = append(errs, "Please confirm you have read and agree to the Membership Agreement on behalf of your business.") + errs = append( + errs, + "Please confirm you have read and agree to the Membership Agreement on behalf of your business.", + ) } return errs @@ -146,8 +153,12 @@ func (t *TradingUpdateData) Validate() []string { } else if len(t.Description) > 500 { errs = append(errs, "Business description cannot exceed 500 characters.") } - if t.Website != "" && !strings.HasPrefix(t.Website, "http://") && !strings.HasPrefix(t.Website, "https://") { - errs = append(errs, "Website URL should start with http:// or https://.") + if t.Website != "" && !strings.HasPrefix(t.Website, "http://") && + !strings.HasPrefix(t.Website, "https://") { + errs = append( + errs, + "Website URL should start with http:// or https://.", + ) } else if len(t.Website) > 100 { errs = append(errs, "Website URL cannot exceed 100 characters.") } diff --git a/internal/app/types/user.go b/internal/app/types/user.go index ee5fbbe..7840f26 100644 --- a/internal/app/types/user.go +++ b/internal/app/types/user.go @@ -8,37 +8,37 @@ import ( // LoginInfo is shared by user and admin user model. type LoginInfo struct { - CurrentLoginIP string `json:"currentLoginIP,omitempty" bson:"currentLoginIP,omitempty"` + CurrentLoginIP string `json:"currentLoginIP,omitempty" bson:"currentLoginIP,omitempty"` CurrentLoginDate time.Time `json:"currentLoginDate,omitempty" bson:"currentLoginDate,omitempty"` - LastLoginIP string `json:"lastLoginIP,omitempty" bson:"lastLoginIP,omitempty"` - LastLoginDate time.Time `json:"lastLoginDate,omitempty" bson:"lastLoginDate,omitempty"` + LastLoginIP string `json:"lastLoginIP,omitempty" bson:"lastLoginIP,omitempty"` + LastLoginDate time.Time `json:"lastLoginDate,omitempty" bson:"lastLoginDate,omitempty"` } // User is the model representation of an user in the data model. type User struct { - ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` + ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` DeletedAt time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"` FirstName string `json:"firstName,omitempty" bson:"firstName,omitempty"` - LastName string `json:"lastName,omitempty" bson:"lastName,omitempty"` - Email string `json:"email,omitempty" bson:"email,omitempty"` - Password string `json:"password,omitempty" bson:"password,omitempty"` + LastName string `json:"lastName,omitempty" bson:"lastName,omitempty"` + Email string `json:"email,omitempty" bson:"email,omitempty"` + Password string `json:"password,omitempty" bson:"password,omitempty"` Telephone string `json:"telephone,omitempty" bson:"telephone,omitempty"` CompanyID primitive.ObjectID `json:"companyID,omitempty" bson:"companyID,omitempty"` - CurrentLoginIP string `json:"currentLoginIP,omitempty" bson:"currentLoginIP,omitempty"` + CurrentLoginIP string `json:"currentLoginIP,omitempty" bson:"currentLoginIP,omitempty"` CurrentLoginDate time.Time `json:"currentLoginDate,omitempty" bson:"currentLoginDate,omitempty"` - LastLoginIP string `json:"lastLoginIP,omitempty" bson:"lastLoginIP,omitempty"` - LastLoginDate time.Time `json:"lastLoginDate,omitempty" bson:"lastLoginDate,omitempty"` + LastLoginIP string `json:"lastLoginIP,omitempty" bson:"lastLoginIP,omitempty"` + LastLoginDate time.Time `json:"lastLoginDate,omitempty" bson:"lastLoginDate,omitempty"` - LoginAttempts int `json:"loginAttempts,omitempty" bson:"loginAttempts,omitempty"` + LoginAttempts int `json:"loginAttempts,omitempty" bson:"loginAttempts,omitempty"` LastLoginFailDate time.Time `json:"lastLoginFailDate,omitempty" bson:"lastLoginFailDate,omitempty"` - ShowRecentMatchedTags bool `json:"showRecentMatchedTags,omitempty" bson:"showRecentMatchedTags,omitempty"` - FavoriteBusinesses []primitive.ObjectID `json:"favoriteBusinesses,omitempty" bson:"favoriteBusinesses,omitempty"` - DailyNotification bool `json:"dailyNotification,omitempty" bson:"dailyNotification,omitempty"` + ShowRecentMatchedTags bool `json:"showRecentMatchedTags,omitempty" bson:"showRecentMatchedTags,omitempty"` + FavoriteBusinesses []primitive.ObjectID `json:"favoriteBusinesses,omitempty" bson:"favoriteBusinesses,omitempty"` + DailyNotification bool `json:"dailyNotification,omitempty" bson:"dailyNotification,omitempty"` LastNotificationSentDate time.Time `json:"lastNotificationSentDate,omitempty" bson:"lastNotificationSentDate,omitempty"` } diff --git a/internal/app/types/user_action.go b/internal/app/types/user_action.go index 2be1092..cdfdb08 100644 --- a/internal/app/types/user_action.go +++ b/internal/app/types/user_action.go @@ -8,16 +8,16 @@ import ( // UserAction is the model representation of an user action in the data model. type UserAction struct { - ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` + ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` DeletedAt time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"` - UserID primitive.ObjectID `json:"userID,omitempty" bson:"userID,omitempty"` - Email string `json:"email,omitempty" bson:"email,omitempty"` - Action string `json:"action,omitempty" bson:"action,omitempty"` + UserID primitive.ObjectID `json:"userID,omitempty" bson:"userID,omitempty"` + Email string `json:"email,omitempty" bson:"email,omitempty"` + Action string `json:"action,omitempty" bson:"action,omitempty"` ActionDetails string `json:"actionDetails,omitempty" bson:"actionDetails,omitempty"` - Category string `json:"category,omitempty" bson:"category,omitempty"` + Category string `json:"category,omitempty" bson:"category,omitempty"` } type UserActionSearchCriteria struct { diff --git a/internal/pkg/bcrypt/bcrypt.go b/internal/pkg/bcrypt/bcrypt.go index f52013b..e910c18 100644 --- a/internal/pkg/bcrypt/bcrypt.go +++ b/internal/pkg/bcrypt/bcrypt.go @@ -14,7 +14,10 @@ func Hash(password string) (string, error) { // CompareHash compares the hashedPassword with plainPassword. func CompareHash(hashedPassword string, plainPassword string) error { - err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(plainPassword)) + err := bcrypt.CompareHashAndPassword( + []byte(hashedPassword), + []byte(plainPassword), + ) if err != nil { return err } diff --git a/internal/pkg/email/balance.go b/internal/pkg/email/balance.go index 455844c..3bf5ac7 100644 --- a/internal/pkg/email/balance.go +++ b/internal/pkg/email/balance.go @@ -11,7 +11,11 @@ type balance struct{} var Balance = &balance{} func (b *balance) NonZeroBalance(from time.Time, to time.Time) error { - body := "Non-zero balance encountered! Please check the timespan from " + from.Format("2006-01-02 15:04:05") + " to " + to.Format("2006-01-02 15:04:05") + " in the posting table." + body := "Non-zero balance encountered! Please check the timespan from " + from.Format( + "2006-01-02 15:04:05", + ) + " to " + to.Format( + "2006-01-02 15:04:05", + ) + " in the posting table." d := emailData{ receiver: viper.GetString("email_from"), diff --git a/internal/pkg/email/email.go b/internal/pkg/email/email.go index ccc1f24..4f130d4 100644 --- a/internal/pkg/email/email.go +++ b/internal/pkg/email/email.go @@ -33,7 +33,10 @@ func New() *Email { e := new(Email) e.serverAddr = viper.GetString("url") // Always send from MCCS - e.from = mail.NewEmail(viper.GetString("email_from"), viper.GetString("sendgrid.sender_email")) + e.from = mail.NewEmail( + viper.GetString("email_from"), + viper.GetString("sendgrid.sender_email"), + ) e.client = sendgrid.NewSendClient(viper.GetString("sendgrid.key")) return e } @@ -165,7 +168,12 @@ func (e *Email) sendNewMemberSignupEmail(businessName, email string) error { func SendResetEmail(receiver string, email string, token string) error { return e.sendResetEmail(receiver, email, token) } -func (e *Email) sendResetEmail(receiver string, email string, token string) error { + +func (e *Email) sendResetEmail( + receiver string, + email string, + token string, +) error { text := "Your password reset link is: " + e.serverAddr + "/password-resets/" + token d := emailData{ receiver: receiver, @@ -182,10 +190,17 @@ func (e *Email) sendResetEmail(receiver string, email string, token string) erro } // SendDailyEmailList sends the matching tags for a user. -func SendDailyEmailList(user *types.User, matchedTags *types.MatchedTags) error { +func SendDailyEmailList( + user *types.User, + matchedTags *types.MatchedTags, +) error { return e.sendDailyEmailList(user, matchedTags) } -func (e *Email) sendDailyEmailList(user *types.User, matchedTags *types.MatchedTags) error { + +func (e *Email) sendDailyEmailList( + user *types.User, + matchedTags *types.MatchedTags, +) error { t, err := template.NewEmailView("dailyEmail") if err != nil { return err @@ -224,10 +239,21 @@ func (e *Email) sendDailyEmailList(user *types.User, matchedTags *types.MatchedT } // SendContactBusiness sends the contact to the business owner. -func SendContactBusiness(receiver, receiverEmail, replyToName, replyToEmail, body string) error { - return e.sendContactBusiness(receiver, receiverEmail, replyToName, replyToEmail, body) +func SendContactBusiness( + receiver, receiverEmail, replyToName, replyToEmail, body string, +) error { + return e.sendContactBusiness( + receiver, + receiverEmail, + replyToName, + replyToEmail, + body, + ) } -func (e *Email) sendContactBusiness(receiver, receiverEmail, replyToName, replyToEmail, body string) error { + +func (e *Email) sendContactBusiness( + receiver, receiverEmail, replyToName, replyToEmail, body string, +) error { d := emailData{ receiver: receiver, receiverEmail: receiverEmail, @@ -267,7 +293,11 @@ func (e *Email) sendContactBusiness(receiver, receiverEmail, replyToName, replyT func SendSignupNotification(businessName string, contactEmail string) error { return e.sendSignupNotification(businessName, contactEmail) } -func (e *Email) sendSignupNotification(businessName string, contactEmail string) error { + +func (e *Email) sendSignupNotification( + businessName string, + contactEmail string, +) error { body := "Business Name: " + businessName + ", Contact Email: " + contactEmail d := emailData{ receiver: viper.GetString("email_from"), diff --git a/internal/pkg/email/transaction.go b/internal/pkg/email/transaction.go index e22220c..3519243 100644 --- a/internal/pkg/email/transaction.go +++ b/internal/pkg/email/transaction.go @@ -39,13 +39,19 @@ func (tr *transaction) getEmailInfo(t *types.Transaction) *emailInfo { } } -func (tr *transaction) Initiate(transactionType string, t *types.Transaction) error { +func (tr *transaction) Initiate( + transactionType string, + t *types.Transaction, +) error { info := tr.getEmailInfo(t) url := viper.GetString("url") + "/pending_transactions" var body string if transactionType == "send" { - body = info.InitiatorBusinessName + " wants to send " + fmt.Sprintf("%.2f", t.Amount) + " Credits to you. Click here to review this pending transaction." + body = info.InitiatorBusinessName + " wants to send " + fmt.Sprintf( + "%.2f", + t.Amount, + ) + " Credits to you. Click here to review this pending transaction." } else { body = info.InitiatorBusinessName + " wants to receive " + fmt.Sprintf("%.2f", t.Amount) + " Credits from you. Click here to review this pending transaction." } @@ -69,7 +75,10 @@ func (tr *transaction) Accept(t *types.Transaction) error { var body string if t.InitiatedBy == t.FromID { - body = info.ReceiverBusinessName + " has accepted the transaction you initiated for -" + fmt.Sprintf("%.2f", t.Amount) + " Credits." + body = info.ReceiverBusinessName + " has accepted the transaction you initiated for -" + fmt.Sprintf( + "%.2f", + t.Amount, + ) + " Credits." } else { body = info.ReceiverBusinessName + " has accepted the transaction you initiated for +" + fmt.Sprintf("%.2f", t.Amount) + " Credits." } @@ -93,7 +102,10 @@ func (tr *transaction) Cancel(t *types.Transaction, reason string) error { var body string if t.InitiatedBy == t.FromID { - body = info.InitiatorBusinessName + " has cancelled the transaction it initiated for +" + fmt.Sprintf("%.2f", t.Amount) + " Credits." + body = info.InitiatorBusinessName + " has cancelled the transaction it initiated for +" + fmt.Sprintf( + "%.2f", + t.Amount, + ) + " Credits." } else { body = info.InitiatorBusinessName + " has cancelled the transaction it initiated for -" + fmt.Sprintf("%.2f", t.Amount) + " Credits." } @@ -116,7 +128,10 @@ func (tr *transaction) Cancel(t *types.Transaction, reason string) error { return nil } -func (tr *transaction) CancelBySystem(t *types.Transaction, reason string) error { +func (tr *transaction) CancelBySystem( + t *types.Transaction, + reason string, +) error { info := tr.getEmailInfo(t) body := "The system has cancelled the transaction you initiated with " + info.ReceiverBusinessName + " for the following reason: " + reason d := emailData{ @@ -138,7 +153,10 @@ func (tr *transaction) Reject(t *types.Transaction) error { var body string if t.InitiatedBy == t.FromID { - body = info.ReceiverBusinessName + " has rejected the transaction you initiated for -" + fmt.Sprintf("%.2f", t.Amount) + " Credits." + body = info.ReceiverBusinessName + " has rejected the transaction you initiated for -" + fmt.Sprintf( + "%.2f", + t.Amount, + ) + " Credits." } else { body = info.ReceiverBusinessName + " has rejected the transaction you initiated for +" + fmt.Sprintf("%.2f", t.Amount) + " Credits." } diff --git a/internal/pkg/helper/user.go b/internal/pkg/helper/user.go index 3889429..fbd3c35 100644 --- a/internal/pkg/helper/user.go +++ b/internal/pkg/helper/user.go @@ -30,14 +30,18 @@ func GetUpdateData(r *http.Request) *types.UpdateAccountData { func GetBusiness(r *http.Request) *types.BusinessData { turnover, _ := strconv.Atoi(r.FormValue("turnover")) b := &types.BusinessData{ - BusinessName: r.FormValue("business_name"), // 100 chars - IncType: r.FormValue("inc_type"), // 25 chars - CompanyNumber: r.FormValue("company_number"), // 20 chars - BusinessPhone: r.FormValue("business_phone"), // 25 chars - Website: r.FormValue("website"), // 100 chars - Turnover: turnover, // 20 chars - Offers: GetTags(r.FormValue("offers")), // 500 chars (max 50 chars per tag) - Wants: GetTags(r.FormValue("wants")), // 500 chars (max 50 chars per tag) + BusinessName: r.FormValue("business_name"), // 100 chars + IncType: r.FormValue("inc_type"), // 25 chars + CompanyNumber: r.FormValue("company_number"), // 20 chars + BusinessPhone: r.FormValue("business_phone"), // 25 chars + Website: r.FormValue("website"), // 100 chars + Turnover: turnover, // 20 chars + Offers: GetTags( + r.FormValue("offers"), + ), // 500 chars (max 50 chars per tag) + Wants: GetTags( + r.FormValue("wants"), + ), // 500 chars (max 50 chars per tag) Description: r.FormValue("description"), // 500 chars LocationAddress: r.FormValue("location_address"), // 255 chars LocationCity: r.FormValue("location_city"), // 50 chars diff --git a/internal/pkg/jwt/jwt.go b/internal/pkg/jwt/jwt.go index eb9724e..20d1569 100644 --- a/internal/pkg/jwt/jwt.go +++ b/internal/pkg/jwt/jwt.go @@ -4,80 +4,92 @@ import ( "crypto/rsa" "errors" "log" + "os" "time" - jwt "github.com/dgrijalva/jwt-go" - "github.com/ic3network/mccs-alpha/global" + jwtlib "github.com/golang-jwt/jwt/v5" "github.com/spf13/viper" ) -var j *JWT - -func init() { - global.Init() - j = New() -} - -// JWT is a prioritized configuration registry. -type JWT struct { +// JWTManager manages JWT operations. +type JWTManager struct { signKey *rsa.PrivateKey verifyKey *rsa.PublicKey } -// New returns an initialized JWT instance. -func New() *JWT { - signKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(viper.GetString("jwt.private_key"))) +// NewJWTManager initializes and returns a new JWTManager instance. +func NewJWTManager() *JWTManager { + privateKeyPEM := getEnvOrFallback("jwt.private_key", "JWT_PRIVATE_KEY") + publicKeyPEM := getEnvOrFallback("jwt.public_key", "JWT_PUBLIC_KEY") + + signKey, err := jwtlib.ParseRSAPrivateKeyFromPEM([]byte(privateKeyPEM)) if err != nil { log.Fatal(err) } - verifyKey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(viper.GetString("jwt.public_key"))) + + verifyKey, err := jwtlib.ParseRSAPublicKeyFromPEM([]byte(publicKeyPEM)) if err != nil { log.Fatal(err) } - j := new(JWT) - j.signKey = signKey - j.verifyKey = verifyKey - return j + return &JWTManager{ + signKey: signKey, + verifyKey: verifyKey, + } } -type claims struct { - jwt.StandardClaims +type userClaims struct { + jwtlib.RegisteredClaims UserID string `json:"userID"` Admin bool `json:"admin"` } -// GenerateToken generates a jwt token. -func GenerateToken(id string, admin bool) (string, error) { return j.generateToken(id, admin) } -func (j *JWT) generateToken(id string, admin bool) (string, error) { - c := claims{ - UserID: id, - Admin: admin, - StandardClaims: jwt.StandardClaims{ - ExpiresAt: time.Now().Add(24 * time.Hour).Unix(), +// GenerateToken generates a JWT token for a user. +func (jm *JWTManager) Generate( + userID string, + isAdmin bool, +) (string, error) { + claims := userClaims{ + UserID: userID, + Admin: isAdmin, + RegisteredClaims: jwtlib.RegisteredClaims{ + ExpiresAt: jwtlib.NewNumericDate(time.Now().Add(24 * time.Hour)), }, } - token := jwt.NewWithClaims(jwt.SigningMethodRS256, c) - tokenString, err := token.SignedString(j.signKey) + token := jwtlib.NewWithClaims(jwtlib.SigningMethodRS256, claims) + return token.SignedString(jm.signKey) +} + +// Validate validates a JWT token and returns the associated claims. +func (jm *JWTManager) Validate(tokenString string) (*userClaims, error) { + claims := &userClaims{} + token, err := jwtlib.ParseWithClaims( + tokenString, + claims, + func(token *jwtlib.Token) (interface{}, error) { + return jm.verifyKey, nil + }, + ) + if err != nil { - return "", err + return nil, err } - return tokenString, nil + + if !token.Valid { + return nil, errors.New("invalid token") + } + + return claims, nil } -// ValidateToken validate a jwt token. -func ValidateToken(tokenString string) (*claims, error) { return j.validateToken(tokenString) } -func (j *JWT) validateToken(tokenString string) (*claims, error) { - c := &claims{} - tkn, err := jwt.ParseWithClaims(tokenString, c, func(token *jwt.Token) (interface{}, error) { - return j.verifyKey, nil - }) - if err != nil { - return &claims{}, err +func getEnvOrFallback(viperKey, envKey string) string { + value := viper.GetString(viperKey) + if value == "" { + value = os.Getenv(viperKey) } - if !tkn.Valid { - return &claims{}, errors.New("Invalid token") + if value == "" { + value = os.Getenv(envKey) } - return c, nil + return value } diff --git a/internal/pkg/jwt/jwt_test.go b/internal/pkg/jwt/jwt_test.go new file mode 100644 index 0000000..9b5f3e2 --- /dev/null +++ b/internal/pkg/jwt/jwt_test.go @@ -0,0 +1,84 @@ +package jwt_test + +import ( + "testing" + + "github.com/ic3network/mccs-alpha/internal/pkg/jwt" + "github.com/stretchr/testify/require" +) + +const ( + TEST_PRIVATE_KEY = `-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA1vl/vENflHIgomF0qxfPg9l9FqwguCYtGNIbAfvVXSsLueAV +D23ZDtazisA67y+dO8TQk+KTGeCbM2Otcvvs7mdsRsbFe+demdSfydQHAp2tGb7O +DBQPGJeyCnyfePB2GmqjVrBB1BjjWgnwwNaXJQkmtLruG8Sgrwl3nKjTeC3x8LjB +l0gGU6UFON6SBF+/CovbOHn+P8eUC/LJrvX8dGpXfGoTzk18WKU5GzThrSgoGkL7 +CToAN8/JoW8G/1gtiuhFRAi53oxpt058An8ORBP8PkxGj+enjq59C/5YMYLwfKHj +lylu0uRpfbmih4/46pgbYjjUyOhSXxHd1k5VmwIDAQABAoIBAQCMb29X0HeXJTtW +eO3be3GQA7to3Ud+pUnephsIn7iR5bYCVnXLn4ol3HJr2QpnCKbhzcAoa+KHDCi3 +WI2NyS/Nynh8gAuw1sQBIFrGYaG2vsS/RdubHluCSE8B9MnFGuk8dp9/2SMX6K5V +Opsxjr4sbp7/gAJe14PU9Q1TpSKIpeBvH3li+mF405YIo6JTcxZToJtJcRMB7V7P +E8KI6F+cwczAmc282pMtpT8/TL1PHq7JYH8LJ18+EwQOvEvo6A8KJIDlFqEaK+yu +oQhHdUxxO9ZxAlTcb48g6o2laLd+v6k8N9yQagEyqHof/cSNXA24ZnqGHS3sECri +TpV1gDypAoGBAPLzXtxV2zseEDH5dYQ3vh6bdEudBFy/3YGFIMrtbMZCP8dx2Lie +P9ABWJqYEUrQpSNnKk6XdNQQGiuwFmygOuZMvyw4svuGKHIIQsSFQRtn+oO6lqSe +cOW+59UgBipBBjRuNvdSh3g4i+JI33bDwVedO5Qp+OinenVHMx27NHNNAoGBAOKF +c2/W7PYllHMGPIfjW1/+otkHdwPyLiBleamUgs33do8YGJekddX0+2BgR1ZIoIWQ +MsiWA/FcsTKERaZv220s7iz58w0GTcpbHQQW7e6D9cl+5DIXnEyG6vQ+hSiUOQXe +LjblgGQJHitrH2wUW/eEjQvXYLIduKlTcOWGZ6iHAoGBAJUtLJUcPsX4+rbE1wy9 +cYa3q1v2aMROp0MtLGqOCJlf+muLkyghO0uMWAxszUlj/dJUOV0SkJDZ5kfnEo3W +gPQCMeyEUBozUUhbnCuxKr4aRW93NaKVCvt3EkECLebqEFZHSobobPg7uGDUoCn7 +nw8eI4QhlY29sGqssk1SMq2NAoGBAIW12n8w8e0WH7uJ+d8IoJ5Yc44CbwlgQkQT +Qi6MoG2t3kj3I0UX6gqismOgUVuoQUC17pQioS8u1NYJ6AcnzfFy7SCVZhfRGcgR +4l3QnyAEuuf2xAKhlzxBA52q7fUXEVXaYZM8A36JN0rPz9t/ZQ4FKzDLMKPTEXa5 +71E89iEvAoGASgN2hEjcF4lwe5ahgrLAheibPzC+6DFdSCBw9CbL183C5s3r4JDh +VDH3H2SHpB0qmBa+YLRwRvHxpWU9uq/unaJvc+AQ3JwZX3bQ8ixvyVfpeBXZF6Dh +KoQ0MewWRNtrpGFa5qdWBfcenKdhWgWrdMnroNhqCHfXEIiYsj3qqWs= +-----END RSA PRIVATE KEY-----` + + TEST_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1vl/vENflHIgomF0qxfP +g9l9FqwguCYtGNIbAfvVXSsLueAVD23ZDtazisA67y+dO8TQk+KTGeCbM2Otcvvs +7mdsRsbFe+demdSfydQHAp2tGb7ODBQPGJeyCnyfePB2GmqjVrBB1BjjWgnwwNaX +JQkmtLruG8Sgrwl3nKjTeC3x8LjBl0gGU6UFON6SBF+/CovbOHn+P8eUC/LJrvX8 +dGpXfGoTzk18WKU5GzThrSgoGkL7CToAN8/JoW8G/1gtiuhFRAi53oxpt058An8O +RBP8PkxGj+enjq59C/5YMYLwfKHjlylu0uRpfbmih4/46pgbYjjUyOhSXxHd1k5V +mwIDAQAB +-----END PUBLIC KEY-----` +) + +func TestJWT(t *testing.T) { + tests := []struct { + name string + userID string + isAdmin bool + }{ + { + name: "Valid User Admin", + userID: "123", + isAdmin: true, + }, + { + name: "Valid User Not Admin", + userID: "456", + isAdmin: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Setenv("jwt.private_key", TEST_PRIVATE_KEY) + t.Setenv("jwt.public_key", TEST_PUBLIC_KEY) + j := jwt.NewJWTManager() + + token, err := j.Generate(tt.userID, tt.isAdmin) + require.NoError(t, err) + + claims, err := j.Validate(token) + require.NoError(t, err) + + require.Equal(t, tt.userID, claims.UserID) + require.Equal(t, tt.isAdmin, claims.Admin) + }) + } +} diff --git a/internal/pkg/log/admin.go b/internal/pkg/log/admin.go index 4539bee..2d4baf1 100644 --- a/internal/pkg/log/admin.go +++ b/internal/pkg/log/admin.go @@ -13,7 +13,10 @@ type admin struct{} var Admin = admin{} -func (a admin) LoginSuccess(admin *types.AdminUser, ip string) *types.UserAction { +func (a admin) LoginSuccess( + admin *types.AdminUser, + ip string, +) *types.UserAction { admin.Email = strings.ToLower(admin.Email) return &types.UserAction{ UserID: admin.ID, @@ -25,7 +28,10 @@ func (a admin) LoginSuccess(admin *types.AdminUser, ip string) *types.UserAction } } -func (a admin) LoginFailure(admin *types.AdminUser, ip string) *types.UserAction { +func (a admin) LoginFailure( + admin *types.AdminUser, + ip string, +) *types.UserAction { admin.Email = strings.ToLower(admin.Email) return &types.UserAction{ UserID: admin.ID, @@ -47,24 +53,62 @@ func (a admin) ModifyBusiness( ) *types.UserAction { modifiedFields := util.CheckDiff(oldBusiness, newBusiness, nil) if !helper.SameTags(newBusiness.Offers, oldBusiness.Offers) { - modifiedFields = append(modifiedFields, "offers: "+strings.Join(helper.GetTagNames(oldBusiness.Offers), " ")+" -> "+strings.Join(helper.GetTagNames(newBusiness.Offers), " ")) + modifiedFields = append( + modifiedFields, + "offers: "+strings.Join( + helper.GetTagNames(oldBusiness.Offers), + " ", + )+" -> "+strings.Join( + helper.GetTagNames(newBusiness.Offers), + " ", + ), + ) } if !helper.SameTags(newBusiness.Wants, oldBusiness.Wants) { - modifiedFields = append(modifiedFields, "wants: "+strings.Join(helper.GetTagNames(oldBusiness.Wants), " ")+" -> "+strings.Join(helper.GetTagNames(newBusiness.Wants), " ")) - } - if strings.Join(newBusiness.AdminTags, " ") != strings.Join(oldBusiness.AdminTags, " ") { - modifiedFields = append(modifiedFields, "adminTags: "+strings.Join(oldBusiness.AdminTags, " ")+" -> "+strings.Join(newBusiness.AdminTags, " ")) - } - modifiedFields = append(modifiedFields, util.CheckDiff(oldBalance, newBalance, map[string]bool{})...) + modifiedFields = append( + modifiedFields, + "wants: "+strings.Join( + helper.GetTagNames(oldBusiness.Wants), + " ", + )+" -> "+strings.Join( + helper.GetTagNames(newBusiness.Wants), + " ", + ), + ) + } + if strings.Join( + newBusiness.AdminTags, + " ", + ) != strings.Join( + oldBusiness.AdminTags, + " ", + ) { + modifiedFields = append( + modifiedFields, + "adminTags: "+strings.Join( + oldBusiness.AdminTags, + " ", + )+" -> "+strings.Join( + newBusiness.AdminTags, + " ", + ), + ) + } + modifiedFields = append( + modifiedFields, + util.CheckDiff(oldBalance, newBalance, map[string]bool{})...) if len(modifiedFields) == 0 { return nil } return &types.UserAction{ - UserID: user.ID, - Email: user.Email, - Action: "admin modified business details", - ActionDetails: admin.Email + " - " + user.Email + " - " + strings.Join(modifiedFields, ", "), - Category: "admin", + UserID: user.ID, + Email: user.Email, + Action: "admin modified business details", + ActionDetails: admin.Email + " - " + user.Email + " - " + strings.Join( + modifiedFields, + ", ", + ), + Category: "admin", } } @@ -82,15 +126,21 @@ func (a admin) ModifyUser( return nil } return &types.UserAction{ - UserID: oldUser.ID, - Email: newUser.Email, - Action: "admin modified user details", - ActionDetails: admin.Email + " - " + newUser.Email + ": " + strings.Join(modifiedFields, ", "), - Category: "admin", + UserID: oldUser.ID, + Email: newUser.Email, + Action: "admin modified user details", + ActionDetails: admin.Email + " - " + newUser.Email + ": " + strings.Join( + modifiedFields, + ", ", + ), + Category: "admin", } } -func (a admin) CreateTag(admin *types.AdminUser, tagName string) *types.UserAction { +func (a admin) CreateTag( + admin *types.AdminUser, + tagName string, +) *types.UserAction { admin.Email = strings.ToLower(admin.Email) return &types.UserAction{ UserID: admin.ID, @@ -101,7 +151,11 @@ func (a admin) CreateTag(admin *types.AdminUser, tagName string) *types.UserActi } } -func (a admin) ModifyTag(admin *types.AdminUser, old string, new string) *types.UserAction { +func (a admin) ModifyTag( + admin *types.AdminUser, + old string, + new string, +) *types.UserAction { admin.Email = strings.ToLower(admin.Email) return &types.UserAction{ UserID: admin.ID, @@ -112,7 +166,10 @@ func (a admin) ModifyTag(admin *types.AdminUser, old string, new string) *types. } } -func (a admin) DeleteTag(admin *types.AdminUser, tagName string) *types.UserAction { +func (a admin) DeleteTag( + admin *types.AdminUser, + tagName string, +) *types.UserAction { admin.Email = strings.ToLower(admin.Email) return &types.UserAction{ UserID: admin.ID, @@ -123,7 +180,10 @@ func (a admin) DeleteTag(admin *types.AdminUser, tagName string) *types.UserActi } } -func (a admin) CreateAdminTag(admin *types.AdminUser, tagName string) *types.UserAction { +func (a admin) CreateAdminTag( + admin *types.AdminUser, + tagName string, +) *types.UserAction { admin.Email = strings.ToLower(admin.Email) return &types.UserAction{ UserID: admin.ID, @@ -134,7 +194,11 @@ func (a admin) CreateAdminTag(admin *types.AdminUser, tagName string) *types.Use } } -func (a admin) ModifyAdminTag(admin *types.AdminUser, old string, new string) *types.UserAction { +func (a admin) ModifyAdminTag( + admin *types.AdminUser, + old string, + new string, +) *types.UserAction { admin.Email = strings.ToLower(admin.Email) return &types.UserAction{ UserID: admin.ID, @@ -145,7 +209,10 @@ func (a admin) ModifyAdminTag(admin *types.AdminUser, old string, new string) *t } } -func (a admin) DeleteAdminTag(admin *types.AdminUser, tagName string) *types.UserAction { +func (a admin) DeleteAdminTag( + admin *types.AdminUser, + tagName string, +) *types.UserAction { admin.Email = strings.ToLower(admin.Email) return &types.UserAction{ UserID: admin.ID, @@ -169,7 +236,10 @@ func (a admin) Transfer( Email: admin.Email, Action: "admin transfer for user", // admin - [from] -> [to] - [amount] - ActionDetails: admin.Email + " - " + fromEmail + " -> " + toEmail + " - " + fmt.Sprintf("%.2f", amount) + " - " + desc, - Category: "admin", + ActionDetails: admin.Email + " - " + fromEmail + " -> " + toEmail + " - " + fmt.Sprintf( + "%.2f", + amount, + ) + " - " + desc, + Category: "admin", } } diff --git a/internal/pkg/log/user.go b/internal/pkg/log/user.go index ca65450..e057218 100644 --- a/internal/pkg/log/user.go +++ b/internal/pkg/log/user.go @@ -78,28 +78,55 @@ func (us user) ModifyAccount( newBusiness *types.BusinessData, ) *types.UserAction { // check for business - modifiedFields := util.CheckDiff(oldBusiness, newBusiness, map[string]bool{"Status": true}) + modifiedFields := util.CheckDiff( + oldBusiness, + newBusiness, + map[string]bool{"Status": true}, + ) if !helper.SameTags(newBusiness.Offers, oldBusiness.Offers) { - modifiedFields = append(modifiedFields, "offers: "+strings.Join(helper.GetTagNames(oldBusiness.Offers), " ")+" -> "+strings.Join(helper.GetTagNames(newBusiness.Offers), " ")) + modifiedFields = append( + modifiedFields, + "offers: "+strings.Join( + helper.GetTagNames(oldBusiness.Offers), + " ", + )+" -> "+strings.Join( + helper.GetTagNames(newBusiness.Offers), + " ", + ), + ) } if !helper.SameTags(newBusiness.Wants, oldBusiness.Wants) { - modifiedFields = append(modifiedFields, "wants: "+strings.Join(helper.GetTagNames(oldBusiness.Wants), " ")+" -> "+strings.Join(helper.GetTagNames(newBusiness.Wants), " ")) + modifiedFields = append( + modifiedFields, + "wants: "+strings.Join( + helper.GetTagNames(oldBusiness.Wants), + " ", + )+" -> "+strings.Join( + helper.GetTagNames(newBusiness.Wants), + " ", + ), + ) } // check for user - modifiedFields = append(modifiedFields, util.CheckDiff(oldUser, newUser, map[string]bool{ - "CurrentLoginIP": true, - "Password": true, - "LastLoginIP": true, - })...) + modifiedFields = append( + modifiedFields, + util.CheckDiff(oldUser, newUser, map[string]bool{ + "CurrentLoginIP": true, + "Password": true, + "LastLoginIP": true, + })...) if len(modifiedFields) == 0 { return nil } return &types.UserAction{ - UserID: oldUser.ID, - Email: newUser.Email, - Action: "modified account details", - ActionDetails: newUser.Email + " - " + strings.Join(modifiedFields, ", "), - Category: "user", + UserID: oldUser.ID, + Email: newUser.Email, + Action: "modified account details", + ActionDetails: newUser.Email + " - " + strings.Join( + modifiedFields, + ", ", + ), + Category: "user", } } @@ -116,8 +143,11 @@ func (us user) ProposeTransfer( Email: proposer.Email, Action: "user proposed a transfer", // [proposer] - [from] - [to] - [amount] - [desc] - ActionDetails: proposer.Email + " - " + fromEmail + " - " + toEmail + " - " + fmt.Sprintf("%.2f", amount) + " - " + desc, - Category: "user", + ActionDetails: proposer.Email + " - " + fromEmail + " - " + toEmail + " - " + fmt.Sprintf( + "%.2f", + amount, + ) + " - " + desc, + Category: "user", } } @@ -133,7 +163,10 @@ func (us user) Transfer( Email: u.Email, Action: "user transfer", // [from] - [to] - [amount] - [desc] - ActionDetails: u.Email + " - " + toEmail + " - " + fmt.Sprintf("%.2f", amount) + " - " + desc, - Category: "user", + ActionDetails: u.Email + " - " + toEmail + " - " + fmt.Sprintf( + "%.2f", + amount, + ) + " - " + desc, + Category: "user", } } diff --git a/internal/pkg/passlib/passlib.go b/internal/pkg/passlib/passlib.go index 57a2bb2..c11d60d 100644 --- a/internal/pkg/passlib/passlib.go +++ b/internal/pkg/passlib/passlib.go @@ -28,7 +28,12 @@ func Validate(password string) []string { } if len(password) < minLen { - messages = append(messages, "Password must be at least "+strconv.Itoa(minLen)+" characters long.") + messages = append( + messages, + "Password must be at least "+strconv.Itoa( + minLen, + )+" characters long.", + ) } else if len(password) > 100 { messages = append(messages, "Password cannot exceed 100 characters.") } @@ -36,10 +41,16 @@ func Validate(password string) []string { messages = append(messages, "Password must have at least one letter.") } if !hasNumber { - messages = append(messages, "Password must have at least one numeric value.") + messages = append( + messages, + "Password must have at least one numeric value.", + ) } if !hasSpecial { - messages = append(messages, "Password must have at least one special character.") + messages = append( + messages, + "Password must have at least one special character.", + ) } return messages diff --git a/internal/pkg/recaptcha/recaptcha.go b/internal/pkg/recaptcha/recaptcha.go index cb0e628..af531b7 100644 --- a/internal/pkg/recaptcha/recaptcha.go +++ b/internal/pkg/recaptcha/recaptcha.go @@ -57,7 +57,10 @@ func (r *Recaptcha) verifyResponse(response string) bool { return false } client := &http.Client{Timeout: 5 * time.Second} - resp, err := client.PostForm(postURL, url.Values{"secret": {r.Secret}, "response": {response}}) + resp, err := client.PostForm( + postURL, + url.Values{"secret": {r.Secret}, "response": {response}}, + ) if err != nil { r.errMsg = err.Error() return false diff --git a/internal/pkg/template/template.go b/internal/pkg/template/template.go index a17c513..4f014fa 100644 --- a/internal/pkg/template/template.go +++ b/internal/pkg/template/template.go @@ -80,7 +80,12 @@ func NewEmailView(templateName string) (*template.Template, error) { } // Render is used to render the view with the predefined layout. -func (v *View) Render(w http.ResponseWriter, r *http.Request, yield interface{}, ErrorMessages []string) { +func (v *View) Render( + w http.ResponseWriter, + r *http.Request, + yield interface{}, + ErrorMessages []string, +) { w.Header().Set("Content-Type", "text/html") var vd Data @@ -100,7 +105,12 @@ func (v *View) Render(w http.ResponseWriter, r *http.Request, yield interface{}, } // Success renders the self defined success message. -func (v *View) Success(w http.ResponseWriter, r *http.Request, yield interface{}, message string) { +func (v *View) Success( + w http.ResponseWriter, + r *http.Request, + yield interface{}, + message string, +) { w.Header().Set("Content-Type", "text/html") var vd Data @@ -118,7 +128,12 @@ func (v *View) Success(w http.ResponseWriter, r *http.Request, yield interface{} } // Error renders the self defined error message. -func (v *View) Error(w http.ResponseWriter, r *http.Request, yield interface{}, err error) { +func (v *View) Error( + w http.ResponseWriter, + r *http.Request, + yield interface{}, + err error, +) { w.Header().Set("Content-Type", "text/html") var vd Data diff --git a/internal/pkg/util/check_field_diff.go b/internal/pkg/util/check_field_diff.go index 8febffb..0c32d83 100644 --- a/internal/pkg/util/check_field_diff.go +++ b/internal/pkg/util/check_field_diff.go @@ -10,7 +10,11 @@ import ( // CheckDiff checks what fields have been changed. // Only checks "String", "Int" and "Float64" types. -func CheckDiff(old interface{}, new interface{}, fieldsToSkip map[string]bool) []string { +func CheckDiff( + old interface{}, + new interface{}, + fieldsToSkip map[string]bool, +) []string { modifiedFields := make([]string, 0) structItems, _ := reflections.Items(old) @@ -19,13 +23,21 @@ func CheckDiff(old interface{}, new interface{}, fieldsToSkip map[string]bool) [ continue } fieldKind, _ := reflections.GetFieldKind(old, field) - if fieldKind != reflect.String && fieldKind != reflect.Int && fieldKind != reflect.Float64 { + if fieldKind != reflect.String && fieldKind != reflect.Int && + fieldKind != reflect.Float64 { continue } newValue, _ := reflections.GetField(new, field) if newValue != oldValue { if fieldKind == reflect.Int { - modifiedFields = append(modifiedFields, field+": "+strconv.Itoa(oldValue.(int))+" -> "+strconv.Itoa(newValue.(int))) + modifiedFields = append( + modifiedFields, + field+": "+strconv.Itoa( + oldValue.(int), + )+" -> "+strconv.Itoa( + newValue.(int), + ), + ) } else if fieldKind == reflect.Float64 { modifiedFields = append(modifiedFields, field+": "+fmt.Sprintf("%.2f", oldValue.(float64))+" -> "+fmt.Sprintf("%.2f", newValue.(float64))) } else { diff --git a/internal/pkg/util/email.go b/internal/pkg/util/email.go index 4949284..f793707 100644 --- a/internal/pkg/util/email.go +++ b/internal/pkg/util/email.go @@ -2,7 +2,9 @@ package util import "regexp" -var emailRe = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") +var emailRe = regexp.MustCompile( + "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", +) // IsValidEmail checks if email is valid. func IsValidEmail(email string) bool { diff --git a/internal/pkg/validator/password.go b/internal/pkg/validator/password.go index 36372ac..e5780eb 100644 --- a/internal/pkg/validator/password.go +++ b/internal/pkg/validator/password.go @@ -18,7 +18,11 @@ func ValidatePassword(password string, confirmPassword string) []string { return errorMessages } -func validateUpdatePassword(currentPass string, newPass string, confirmPass string) []string { +func validateUpdatePassword( + currentPass string, + newPass string, + confirmPass string, +) []string { errorMessages := []string{} if currentPass == "" && newPass == "" && confirmPass == "" { @@ -26,7 +30,10 @@ func validateUpdatePassword(currentPass string, newPass string, confirmPass stri } if currentPass == "" { - errorMessages = append(errorMessages, "Please enter your current password.") + errorMessages = append( + errorMessages, + "Please enter your current password.", + ) } else if newPass != confirmPass { errorMessages = append(errorMessages, "New password and confirmation password do not match.") } else { diff --git a/internal/pkg/validator/register.go b/internal/pkg/validator/register.go index 4246df9..2a2f24b 100644 --- a/internal/pkg/validator/register.go +++ b/internal/pkg/validator/register.go @@ -16,8 +16,12 @@ func ValidateBusiness(b *types.BusinessData) []string { } else if len(b.BusinessName) > 100 { errs = append(errs, "Business Name cannot exceed 100 characters.") } - if b.Website != "" && !strings.HasPrefix(b.Website, "http://") && !strings.HasPrefix(b.Website, "https://") { - errs = append(errs, "Website URL should start with http:// or https://.") + if b.Website != "" && !strings.HasPrefix(b.Website, "http://") && + !strings.HasPrefix(b.Website, "https://") { + errs = append( + errs, + "Website URL should start with http:// or https://.", + ) } else if len(b.Website) > 100 { errs = append(errs, "Website URL cannot exceed 100 characters.") } diff --git a/internal/pkg/validator/tag.go b/internal/pkg/validator/tag.go index adfaf66..f573ba8 100644 --- a/internal/pkg/validator/tag.go +++ b/internal/pkg/validator/tag.go @@ -9,27 +9,39 @@ func validateTagsLimit(b *types.BusinessData) []string { errorMessages := []string{} if len(b.Offers) == 0 { - errorMessages = append(errorMessages, "Missing at least one valid tag for Products/Services Offered.") + errorMessages = append( + errorMessages, + "Missing at least one valid tag for Products/Services Offered.", + ) } else if len(b.Offers) > viper.GetInt("tags_limit") { errorMessages = append(errorMessages, "No more than "+viper.GetString("tags_limit")+" tags can be specified for Products/Services Offered.") } if len(b.Wants) == 0 { - errorMessages = append(errorMessages, "Missing at least one valid tag for Products/Services Wanted.") + errorMessages = append( + errorMessages, + "Missing at least one valid tag for Products/Services Wanted.", + ) } else if len(b.Wants) > viper.GetInt("tags_limit") { errorMessages = append(errorMessages, "No more than "+viper.GetString("tags_limit")+" tags can be specified for Products/Services Wanted.") } for _, offer := range b.Offers { if len(offer.Name) > 50 { - errorMessages = append(errorMessages, "An Offer tag cannot exceed 50 characters.") + errorMessages = append( + errorMessages, + "An Offer tag cannot exceed 50 characters.", + ) break } } for _, want := range b.Wants { if len(want.Name) > 50 { - errorMessages = append(errorMessages, "A Want tag cannot exceed 50 characters.") + errorMessages = append( + errorMessages, + "A Want tag cannot exceed 50 characters.", + ) break } } diff --git a/internal/pkg/validator/validator.go b/internal/pkg/validator/validator.go index ee96d24..d6bf033 100644 --- a/internal/pkg/validator/validator.go +++ b/internal/pkg/validator/validator.go @@ -8,13 +8,21 @@ func Register(d *types.RegisterData) []string { errorMessages := []string{} errorMessages = append(errorMessages, ValidateBusiness(d.Business)...) errorMessages = append(errorMessages, ValidateUser(d.User)...) - errorMessages = append(errorMessages, ValidatePassword(d.User.Password, d.ConfirmPassword)...) + errorMessages = append( + errorMessages, + ValidatePassword(d.User.Password, d.ConfirmPassword)...) if d.User.Email != d.ConfirmEmail { - errorMessages = append(errorMessages, "The email addresses you entered do not match.") + errorMessages = append( + errorMessages, + "The email addresses you entered do not match.", + ) } if d.Terms != "on" { - errorMessages = append(errorMessages, "Please confirm you accept to have your business listed in OCN's directory.") + errorMessages = append( + errorMessages, + "Please confirm you accept to have your business listed in OCN's directory.", + ) } return errorMessages } @@ -23,7 +31,13 @@ func Account(d *types.UpdateAccountData) []string { errorMessages := []string{} errorMessages = append(errorMessages, ValidateBusiness(d.Business)...) errorMessages = append(errorMessages, ValidateUser(d.User)...) - errorMessages = append(errorMessages, validateUpdatePassword(d.CurrentPassword, d.User.Password, d.ConfirmPassword)...) + errorMessages = append( + errorMessages, + validateUpdatePassword( + d.CurrentPassword, + d.User.Password, + d.ConfirmPassword, + )...) return errorMessages } diff --git a/internal/seed/seed.go b/internal/seed/seed.go index ba8dbf1..5a672d0 100644 --- a/internal/seed/seed.go +++ b/internal/seed/seed.go @@ -76,7 +76,9 @@ func Run() { // Generate users and businesses. for i, b := range businessData { - res, err := mongo.DB().Collection("businesses").InsertOne(context.Background(), b) + res, err := mongo.DB(). + Collection("businesses"). + InsertOne(context.Background(), b) if err != nil { log.Fatal(err) } @@ -111,7 +113,9 @@ func Run() { u.CompanyID = b.ID hashedPassword, _ := bcrypt.Hash(u.Password) u.Password = hashedPassword - res, err = mongo.DB().Collection("users").InsertOne(context.Background(), u) + res, err = mongo.DB(). + Collection("users"). + InsertOne(context.Background(), u) if err != nil { log.Fatal(err) } @@ -141,7 +145,9 @@ func Run() { for _, u := range adminUserData { hashedPassword, _ := bcrypt.Hash(u.Password) u.Password = hashedPassword - _, err := mongo.DB().Collection("adminUsers").InsertOne(context.Background(), u) + _, err := mongo.DB(). + Collection("adminUsers"). + InsertOne(context.Background(), u) if err != nil { log.Fatal(err) } @@ -149,7 +155,9 @@ func Run() { // Generate user tags. for _, t := range tagData { - res, err := mongo.DB().Collection("tags").InsertOne(context.Background(), t) + res, err := mongo.DB(). + Collection("tags"). + InsertOne(context.Background(), t) if err != nil { log.Fatal(err) } @@ -177,7 +185,9 @@ func Run() { // Generate admin tags. for _, a := range adminTagData { - _, err := mongo.DB().Collection("adminTags").InsertOne(context.Background(), a) + _, err := mongo.DB(). + Collection("adminTags"). + InsertOne(context.Background(), a) if err != nil { log.Fatal(err) }