diff --git a/.air.toml b/.air.toml new file mode 100644 index 0000000..49468ed --- /dev/null +++ b/.air.toml @@ -0,0 +1,46 @@ +root = "." +testdata_dir = "testdata" +tmp_dir = "tmp" + +[build] + args_bin = [] + bin = "./tmp/main" + cmd = "go build -o ./tmp/main ." + delay = 1000 + exclude_dir = ["assets", "tmp", "vendor", "testdata"] + exclude_file = [] + exclude_regex = ["_test.go"] + exclude_unchanged = false + follow_symlink = false + full_bin = "" + include_dir = [] + include_ext = ["go", "tpl", "tmpl", "html"] + include_file = [] + kill_delay = "0s" + log = "build-errors.log" + poll = false + poll_interval = 0 + post_cmd = [] + pre_cmd = [] + rerun = false + rerun_delay = 500 + send_interrupt = false + stop_on_error = false + +[color] + app = "" + build = "yellow" + main = "magenta" + runner = "green" + watcher = "cyan" + +[log] + main_only = false + time = false + +[misc] + clean_on_exit = false + +[screen] + clear_on_rebuild = false + keep_scroll = true diff --git a/bin/air b/bin/air new file mode 100755 index 0000000..70a878c Binary files /dev/null and b/bin/air differ diff --git a/models/models.go b/models/models.go index 831673a..076ad9b 100644 --- a/models/models.go +++ b/models/models.go @@ -113,3 +113,20 @@ type OTPVerify struct { Email string `json:"email"` UUID string `json:"uuid"` } + +// API +type ResponseError struct { + Code int + Err any +} + +type ErrorAPI struct { + Errors []string `json:"errors"` + Message string `json:"message"` + Type string `json:"type"` +} + +type SuccessAPI struct { + Message string `json:"message"` + Type string `json:"type"` +} diff --git a/rest-api/routes/auth.go b/rest-api/routes/auth.go index 7544898..8c1b0dd 100644 --- a/rest-api/routes/auth.go +++ b/rest-api/routes/auth.go @@ -23,7 +23,7 @@ func RegisterNewAccount(w http.ResponseWriter, r *http.Request) error { //[fairy ok] if responseAPI != nil { - return utils.WriteJSON(w, responseAPI.Code, responseAPI.Err.Error()) + return utils.WriteJSON(w, responseAPI.Code, responseAPI.Err) } fmt.Println(validRegisterInfo) @@ -35,7 +35,7 @@ func RegisterNewAccount(w http.ResponseWriter, r *http.Request) error { fmt.Println(isValidData) if isValidData != true { - return utils.WriteJSON(w, responseAPI.Code, responseAPI.Err.Error()) + return utils.WriteJSON(w, responseAPI.Code, responseAPI.Err) } preUserData := &models.PreusersMongo{ diff --git a/rest-api/services/register.go b/rest-api/services/register.go index 361eda2..825aa06 100644 --- a/rest-api/services/register.go +++ b/rest-api/services/register.go @@ -4,7 +4,6 @@ import ( "context" "encoding/base64" "encoding/json" - "errors" "fmt" "github.com/go-mail/mail" "github.com/go-playground/validator/v10" @@ -21,49 +20,48 @@ import ( "time" ) -type ResponseError struct { - Code int - Err error -} - // CheckAndValidRegisterFiled Check the user register field is valid or not -func CheckAndValidRegisterFiled(registerData *models.CreateUser) (bool, *ResponseError) { +func CheckAndValidRegisterFiled(registerData *models.CreateUser) (bool, *models.ResponseError) { _ = models.Validate.RegisterValidation("customPassword", models.PasswordValidator) errs := models.Validate.Struct(registerData) - var errStack []string + type errStack []string + errorAPI := models.ErrorAPI{ + Errors: make([]string, 0), + Message: "Error in input data please check again", + Type: "InvalidInput", + } if errs != nil { for _, err := range errs.(validator.ValidationErrors) { switch err.Field() { case "Email": { fmt.Println("Internal Log: Email không hợp lệ") - errStack = append(errStack, "Email") + errorAPI.Errors = append(errorAPI.Errors, "Email") } case "Username": { fmt.Println("Internal Log: User không hợp lệ") - errStack = append(errStack, "User") + errorAPI.Errors = append(errorAPI.Errors, "User") } case "Password": { fmt.Println("Internal Log: Password không hợp lệ") - errStack = append(errStack, "Password") + errorAPI.Errors = append(errorAPI.Errors, "Password") } case "ConfirmPassword": { fmt.Println("Internal Log: Nhập lại mật khẩu sai") - errStack = append(errStack, "ConfirmPassword") + errorAPI.Errors = append(errorAPI.Errors, "ConfirmPassword") } case "PhoneNumber": { fmt.Println("Internal Log: SĐT không hợp lệ") - errStack = append(errStack, "PhoneNumber") + errorAPI.Errors = append(errorAPI.Errors, "PhoneNumber") } } } //handle repose error - jsonData, _ := json.Marshal(errStack) - return false, &ResponseError{Code: http.StatusBadRequest, Err: errors.New(string(jsonData))} + return false, &models.ResponseError{Code: http.StatusTooManyRequests, Err: errorAPI} } return true, nil @@ -71,10 +69,10 @@ func CheckAndValidRegisterFiled(registerData *models.CreateUser) (bool, *Respons } // CheckAccountExist Checking in db is user input same data in -func CheckAccountValid(userName string, email string) (bool, *ResponseError) { +func CheckAccountValid(userName string, email string) (bool, *models.ResponseError) { //filter in mongodb var isValid bool - var errAPI *ResponseError + var errAPI *models.ResponseError var dataRedisRetrive models.RedisOTP filter := bson.D{ @@ -91,9 +89,13 @@ func CheckAccountValid(userName string, email string) (bool, *ResponseError) { } else { fmt.Println("Internal Log: Email or username already had register") isValid = false - errAPI = &ResponseError{ + errAPI = &models.ResponseError{ Code: http.StatusBadRequest, - Err: errors.New("your username or email had been register before"), + Err: models.ErrorAPI{ + Errors: []string{"Account existed"}, + Message: "Email or username already had register", + Type: "AccountExisted", + }, } } retrievedValue, err := utils.Redis.Get(context.Background(), "otp:"+email).Result() @@ -107,9 +109,13 @@ func CheckAccountValid(userName string, email string) (bool, *ResponseError) { if timeDiff < 30 { isValid = false fmt.Println("Internal Log: Rate limit send verify mail") - errAPI = &ResponseError{ + errAPI = &models.ResponseError{ Code: http.StatusBadRequest, - Err: errors.New("wait " + strconv.FormatInt(30-timeDiff, 10) + " to send verify mail again"), + Err: models.ErrorAPI{ + Errors: []string{"Rate limit send verify mail"}, + Message: "wait " + strconv.FormatInt(30-timeDiff, 10) + " to send verify mail again", + Type: "RateLimit", + }, } } @@ -139,7 +145,9 @@ func GenerateVerifyAccount(registerInfo *models.PreusersMongo, w http.ResponseWr go writeOTPInRedis(counter, registerInfo, otpChannel, w) wg.Wait() - err := utils.WriteJSON(w, http.StatusOK, "Success register account please verify your account") + err := utils.WriteJSON(w, http.StatusOK, models.SuccessAPI{ + Message: "Success register account please verify your account", + }) return err } @@ -258,7 +266,7 @@ func CreateUserAfterVerify(otpInfo *models.OTPVerify, redis *models.RedisOTP, w if err != nil { fmt.Println("Internal log: Can't get preuser data") - _ = utils.WriteJSONInternalError(w, "Please register again") + //_ = utils.WriteJSONInternalError(w, "Please register again") isValid = false } @@ -277,13 +285,16 @@ func CreateUserAfterVerify(otpInfo *models.OTPVerify, redis *models.RedisOTP, w if err != nil { fmt.Println("Internal log: Can't insert user data") - _ = utils.WriteJSONInternalError(w, "Can't insert user data") + //_ = utils.WriteJSONInternalError(w, "Can't insert user data") isValid = false } if isValid == true { fmt.Println("Internal log: Success verify account") - _ = utils.WriteJSON(w, http.StatusOK, "Success verify account") + _ = utils.WriteJSON(w, http.StatusOK, models.SuccessAPI{ + Message: "Success verify account", + Type: "SuccessVerify", + }) } return isValid @@ -300,7 +311,11 @@ func CheckUserVerify(otpInfo *models.OTPVerify, w http.ResponseWriter) bool { if user.Active == true { fmt.Println("Internal log: Account already verify") - _ = utils.WriteJSON(w, http.StatusBadRequest, "Account already verify") + _ = utils.WriteJSON(w, http.StatusBadRequest, models.ErrorAPI{ + Errors: []string{"Account already verify"}, + Message: "Account already verify", + Type: "AccountAlreadyVerify", + }) isVerified = true } @@ -317,7 +332,11 @@ func CheckOTPIsValid(otpInfo *models.OTPVerify, w http.ResponseWriter) bool { value, err := utils.Redis.Get(context.Background(), "otp:"+otpInfo.Email).Result() if err != nil { fmt.Println("Internal log: Email not valid") - _ = utils.WriteJSON(w, http.StatusBadRequest, "Email is not valid") + _ = utils.WriteJSON(w, http.StatusBadRequest, models.ErrorAPI{ + Errors: []string{"Email not valid"}, + Message: "Email not valid", + Type: "EmailNotValid", + }) isValid = false return false } @@ -326,7 +345,11 @@ func CheckOTPIsValid(otpInfo *models.OTPVerify, w http.ResponseWriter) bool { _, err = uuid.Parse(otpInfo.UUID) if err != nil { fmt.Println("Internal log: UUID not valid") - _ = utils.WriteJSON(w, http.StatusBadRequest, "UUID not valid") + _ = utils.WriteJSON(w, http.StatusBadRequest, models.ErrorAPI{ + Errors: []string{"UUID not valid"}, + Message: "UUID not valid", + Type: "UUIDNotValid", + }) isValid = false } diff --git a/tmp/build-errors.log b/tmp/build-errors.log new file mode 100644 index 0000000..370d558 --- /dev/null +++ b/tmp/build-errors.log @@ -0,0 +1 @@ +exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file diff --git a/tmp/main b/tmp/main new file mode 100755 index 0000000..8950cb2 Binary files /dev/null and b/tmp/main differ diff --git a/utils/crypto.go b/utils/crypto.go index 17cb1f0..29d6b8d 100644 --- a/utils/crypto.go +++ b/utils/crypto.go @@ -131,7 +131,11 @@ func VerifyOTP(otpInfo *models.OTPVerify, redisOTP models.RedisOTP, w http.Respo if isOTPMatch != true { fmt.Println("Internal log: OTP is not match") - _ = WriteJSON(w, http.StatusBadRequest, "OTP is not match") + _ = WriteJSON(w, http.StatusBadRequest, models.ErrorAPI{ + Errors: []string{"OTP is not match"}, + Message: "OTP is not match", + Type: "OTP", + }) } fmt.Println("isOTPMatch: ", isOTPMatch) return isOTPMatch