prepair to using go concurrent
This commit is contained in:
parent
ce0508294c
commit
47816debd3
2
.env
2
.env
|
|
@ -1,5 +1,5 @@
|
||||||
MONGO_URI="mongodb://adminLinh:linhporo1@localhost:27017"
|
MONGO_URI="mongodb://adminLinh:linhporo1@localhost:27017"
|
||||||
API_TEST_PORT=":8080"
|
API_TEST_PORT=":8080"
|
||||||
REDIS_URI="redis://localhost:6479/0"
|
REDIS_URI="redis://localhost:6379/0"
|
||||||
STMP_PASS="btmp judz ebys pfxw"
|
STMP_PASS="btmp judz ebys pfxw"
|
||||||
EMAIL_VERIFY_SECRET="WDc&4+&vYP(n'}?LHNE#5M?IE|g(c812"
|
EMAIL_VERIFY_SECRET="WDc&4+&vYP(n'}?LHNE#5M?IE|g(c812"
|
||||||
3
go.mod
3
go.mod
|
|
@ -11,14 +11,17 @@ require (
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.16.0 // indirect
|
github.com/go-playground/validator/v10 v10.16.0 // indirect
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
|
||||||
github.com/golang/snappy v0.0.1 // indirect
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/joho/godotenv v1.5.1 // indirect
|
github.com/joho/godotenv v1.5.1 // indirect
|
||||||
github.com/klauspost/compress v1.13.6 // indirect
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
|
github.com/mervick/aes-everywhere/go/aes256 v0.0.0-20220903070135-f13ed3789ae1 // indirect
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||||
github.com/pquerna/otp v1.4.0 // indirect
|
github.com/pquerna/otp v1.4.0 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.3.0 // indirect
|
github.com/redis/go-redis/v9 v9.3.0 // indirect
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
github.com/xdg-go/scram v1.1.2 // indirect
|
github.com/xdg-go/scram v1.1.2 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
|
|
|
||||||
6
go.sum
6
go.sum
|
|
@ -18,6 +18,8 @@ github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqR
|
||||||
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
|
@ -29,6 +31,8 @@ github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQ
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||||
|
github.com/mervick/aes-everywhere/go/aes256 v0.0.0-20220903070135-f13ed3789ae1 h1:RLYNaO6dcj6hms2FSzwsXlZsyjxQBJi8qO/8Vkilhz0=
|
||||||
|
github.com/mervick/aes-everywhere/go/aes256 v0.0.0-20220903070135-f13ed3789ae1/go.mod h1:Eb5RMoo9kOQra/2uRiUTGP+LfNuM13Vqm7y7P34+KKo=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
|
@ -36,6 +40,8 @@ github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||||
github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0=
|
github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0=
|
||||||
github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ type PreusersMongo struct {
|
||||||
HashPassword string `bson:"hash_password" json:"hash_password"`
|
HashPassword string `bson:"hash_password" json:"hash_password"`
|
||||||
PhoneNumber string `bson:"phone_number" json:"phone_number"`
|
PhoneNumber string `bson:"phone_number" json:"phone_number"`
|
||||||
CreatedDate time.Time `bson:"created_date" json:"created_date"`
|
CreatedDate time.Time `bson:"created_date" json:"created_date"`
|
||||||
|
UpdateDate time.Time `bson:"update_date" json:"update_date"`
|
||||||
VerifySentCount int `bson:"verify_sent_count" json:"verify_sent_count"`
|
VerifySentCount int `bson:"verify_sent_count" json:"verify_sent_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -27,6 +28,7 @@ type UsersMongo struct {
|
||||||
PhoneNumber string `bson:"phone_number" json:"phone_number"`
|
PhoneNumber string `bson:"phone_number" json:"phone_number"`
|
||||||
Active bool `bson:"active" json:"active"`
|
Active bool `bson:"active" json:"active"`
|
||||||
CreatedDate time.Time `bson:"created_date" json:"created_date"`
|
CreatedDate time.Time `bson:"created_date" json:"created_date"`
|
||||||
|
UpdateDate time.Time `bson:"update_date" json:"update_date"`
|
||||||
VerifySentCount int `bson:"verify_sent_count" json:"verify_sent_count"`
|
VerifySentCount int `bson:"verify_sent_count" json:"verify_sent_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,13 @@ package rest_api
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"linhdevtran99/rest-api/models"
|
||||||
"linhdevtran99/rest-api/rest-api/routes"
|
"linhdevtran99/rest-api/rest-api/routes"
|
||||||
|
"linhdevtran99/rest-api/rest-api/services"
|
||||||
|
"linhdevtran99/rest-api/utils"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type APIServer struct {
|
type APIServer struct {
|
||||||
|
|
@ -30,11 +34,13 @@ func (s *APIServer) Run() {
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
|
|
||||||
routes.AuthRouterSetup(router)
|
routes.AuthRouterSetup(router)
|
||||||
|
|
||||||
|
router.HandleFunc("/test", utils.MakeHTTPHandlerFn(s.TestRoute))
|
||||||
|
|
||||||
startMuxServer(s, router)
|
startMuxServer(s, router)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *APIServer) AuthRoute(w http.ResponseWriter, r *http.Request) error {
|
func (s *APIServer) TestRoute(w http.ResponseWriter, r *http.Request) error {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
|
|
||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
fmt.Println("hit")
|
fmt.Println("hit")
|
||||||
|
|
@ -56,23 +62,29 @@ func (s *APIServer) AuthRoute(w http.ResponseWriter, r *http.Request) error {
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//serect := os.Getenv("EMAIL_VERIFY_SECRET")
|
//serect := os.Getenv("EMAIL_VERIFY_SECRET")
|
||||||
//isPass, _ := generatorOtp("hello", "nhocdl.poro1@gmail.com", 12, serect)
|
|
||||||
//fmt.Println(isPass)
|
//_, otp := services.GeneratorOtp("hello", "nhocdl.poro1@gmail.com", 12, serect)
|
||||||
//cipherBase64 := createLinkVerify(&models.CreateUser{
|
//fmt.Println(otp.HashOTP)
|
||||||
// Username: "thewind121212",
|
//fmt.Println(otp.PureOTP)
|
||||||
// Email: "nhocdl.poro1@gmail.com",
|
|
||||||
// Password: "linhporoQ1@",
|
//utils.EncryptAESMailLink("nhocdl.poro2@gmail.com", serect, w)
|
||||||
// ConfirmPassword: "linhporoQ1@",
|
|
||||||
//}, serect)
|
//jsonData, _ := json.Marshal(map[string]string{"email": "nhocdl.poro1@gmail.com", "user": "thewind121212"})
|
||||||
|
////
|
||||||
|
//utils.Redis.Set(context.Background(), "otp:nhocdl.poro1@gmail.com", string(jsonData), time.Minute)
|
||||||
//
|
//
|
||||||
//key := []byte(serect)
|
//utils.CheckAndWriteRedis("nhocdl.poro1@gmail.com", "thewind121212", "lasdjflasdjlfj")
|
||||||
|
|
||||||
|
services.CheckAndWritePreuser(&models.PreusersMongo{
|
||||||
|
Username: "thewind121212",
|
||||||
|
Email: "nhocdl.poro2@gmail.com",
|
||||||
|
PhoneNumber: "0918327132",
|
||||||
|
VerifySentCount: 0,
|
||||||
|
CreatedDate: time.Now(),
|
||||||
|
UpdateDate: time.Now(),
|
||||||
|
})
|
||||||
|
|
||||||
//
|
//
|
||||||
//i, err := utils.DecryptAES(cipherBase64, key)
|
|
||||||
//if err != nil {
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//fmt.Println(string(i))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,28 +2,47 @@ package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"linhdevtran99/rest-api/models"
|
"linhdevtran99/rest-api/models"
|
||||||
"linhdevtran99/rest-api/rest-api/services"
|
"linhdevtran99/rest-api/rest-api/services"
|
||||||
"linhdevtran99/rest-api/utils"
|
"linhdevtran99/rest-api/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterNewAccount(w http.ResponseWriter, r *http.Request) error {
|
func RegisterNewAccount(w http.ResponseWriter, r *http.Request) error {
|
||||||
client := utils.MongoDB
|
|
||||||
if r.Method == http.MethodPost {
|
if r.Method == http.MethodPost {
|
||||||
var registerInfo models.CreateUser
|
var registerInfo models.CreateUser
|
||||||
|
|
||||||
_ = json.NewDecoder(r.Body).Decode(®isterInfo)
|
_ = json.NewDecoder(r.Body).Decode(®isterInfo)
|
||||||
//call function check info user type in
|
//call function check info user type in
|
||||||
validRegisterInfo := services.CheckAndValidRegisterFiled(®isterInfo, w)
|
validRegisterInfo, responseAPI := services.CheckAndValidRegisterFiled(®isterInfo)
|
||||||
//call function check data user use in past or not
|
if responseAPI != nil {
|
||||||
isValidData := services.CheckAccountExist(client, registerInfo.Username, registerInfo.Email, w)
|
return utils.WriteJSON(w, responseAPI.Code, responseAPI.Err.Error())
|
||||||
|
|
||||||
if isValidData == false || validRegisterInfo == false {
|
|
||||||
return errors.New("USER DON'T HAVE VALID INFO FOR REGISTER ACCOUNT")
|
|
||||||
}
|
}
|
||||||
|
//call function check data user use in past or not
|
||||||
|
isValidData, responseAPI := services.CheckAccountExist(utils.MongoDB, registerInfo.Username, registerInfo.Email)
|
||||||
|
if responseAPI != nil {
|
||||||
|
return utils.WriteJSON(w, responseAPI.Code, responseAPI.Err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
preUserData := &models.PreusersMongo{
|
||||||
|
Username: registerInfo.Username,
|
||||||
|
Email: registerInfo.Email,
|
||||||
|
PhoneNumber: registerInfo.PhoneNumber,
|
||||||
|
HashPassword: registerInfo.Password,
|
||||||
|
CreatedDate: time.Now(),
|
||||||
|
UpdateDate: time.Now(),
|
||||||
|
VerifySentCount: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
services.CheckAndWritePreuser(preUserData)
|
||||||
|
|
||||||
|
//debug
|
||||||
|
if isValidData == true || validRegisterInfo == true {
|
||||||
|
return utils.WriteJSON(w, http.StatusOK, "USER HAVE VALID INFO FOR REGISTER ACCOUNT")
|
||||||
|
}
|
||||||
|
//debug
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ package services
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/pquerna/otp"
|
"github.com/pquerna/otp"
|
||||||
|
|
@ -15,10 +15,16 @@ import (
|
||||||
"linhdevtran99/rest-api/models"
|
"linhdevtran99/rest-api/models"
|
||||||
"linhdevtran99/rest-api/utils"
|
"linhdevtran99/rest-api/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check the user register field is valid or not
|
type ResponseError struct {
|
||||||
func CheckAndValidRegisterFiled(registerData *models.CreateUser, w http.ResponseWriter) bool {
|
Code int
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckAndValidRegisterFiled Check the user register field is valid or not
|
||||||
|
func CheckAndValidRegisterFiled(registerData *models.CreateUser) (bool, *ResponseError) {
|
||||||
_ = models.Validate.RegisterValidation("customPassword", models.PasswordValidator)
|
_ = models.Validate.RegisterValidation("customPassword", models.PasswordValidator)
|
||||||
errs := models.Validate.Struct(registerData)
|
errs := models.Validate.Struct(registerData)
|
||||||
var errStack []string
|
var errStack []string
|
||||||
|
|
@ -27,49 +33,45 @@ func CheckAndValidRegisterFiled(registerData *models.CreateUser, w http.Response
|
||||||
switch err.Field() {
|
switch err.Field() {
|
||||||
case "Email":
|
case "Email":
|
||||||
{
|
{
|
||||||
fmt.Println("Email không hợp lệ")
|
fmt.Println("Internal Log: Email không hợp lệ")
|
||||||
errStack = append(errStack, "Email")
|
errStack = append(errStack, "Email")
|
||||||
}
|
}
|
||||||
case "Username":
|
case "Username":
|
||||||
{
|
{
|
||||||
fmt.Println("User không hợp lệ")
|
fmt.Println("Internal Log: User không hợp lệ")
|
||||||
errStack = append(errStack, "User")
|
errStack = append(errStack, "User")
|
||||||
}
|
}
|
||||||
case "Password":
|
case "Password":
|
||||||
{
|
{
|
||||||
fmt.Println("Password không hợp lệ")
|
fmt.Println("Internal Log: Password không hợp lệ")
|
||||||
errStack = append(errStack, "Password")
|
errStack = append(errStack, "Password")
|
||||||
}
|
}
|
||||||
case "ConfirmPassword":
|
case "ConfirmPassword":
|
||||||
{
|
{
|
||||||
fmt.Println("Nhập lại mật khẩu sai")
|
fmt.Println("Internal Log: Nhập lại mật khẩu sai")
|
||||||
errStack = append(errStack, "ConfirmPassword")
|
errStack = append(errStack, "ConfirmPassword")
|
||||||
}
|
}
|
||||||
case "PhoneNumber":
|
case "PhoneNumber":
|
||||||
{
|
{
|
||||||
fmt.Println("SĐT không hợp lệ")
|
fmt.Println("Internal Log: SĐT không hợp lệ")
|
||||||
errStack = append(errStack, "PhoneNumber")
|
errStack = append(errStack, "PhoneNumber")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//handle repose error
|
//handle repose error
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
jsonData, _ := json.Marshal(errStack)
|
||||||
err := json.NewEncoder(w).Encode(errStack)
|
return false, &ResponseError{Code: http.StatusBadRequest, Err: errors.New(string(jsonData))}
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("There is error in write reponse at checking info user")
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checking in db is user input same data in
|
// CheckAccountExist Checking in db is user input same data in
|
||||||
func CheckAccountExist(mongoClient *mongo.Client, userName string, email string, w http.ResponseWriter) bool {
|
func CheckAccountExist(mongoClient *mongo.Client, userName string, email string) (bool, *ResponseError) {
|
||||||
//filter in mongodb
|
//filter in mongodb
|
||||||
var isValid bool
|
var isValid bool
|
||||||
|
var errAPI *ResponseError
|
||||||
|
|
||||||
filter := bson.D{
|
filter := bson.D{
|
||||||
{"$or", bson.A{
|
{"$or", bson.A{
|
||||||
|
|
@ -78,27 +80,24 @@ func CheckAccountExist(mongoClient *mongo.Client, userName string, email string,
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
userData := mongoClient.Database("Totoday-shop").Collection("users")
|
_, err := utils.PreUserData.FindOne(context.TODO(), filter).Raw()
|
||||||
|
|
||||||
var result models.UsersMongo
|
|
||||||
err := userData.FindOne(context.TODO(), filter).Decode(&result)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
isValid = true
|
isValid = true
|
||||||
}
|
errAPI = nil
|
||||||
if err == nil {
|
} else {
|
||||||
fmt.Println("Email or username already had register")
|
fmt.Println("Internal Log: Email or username already had register")
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
err := json.NewEncoder(w).Encode("Your username or email had been register before")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("There is error in write reponse at checking data user register")
|
|
||||||
}
|
|
||||||
isValid = false
|
isValid = false
|
||||||
|
errAPI = &ResponseError{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
Err: errors.New("your username or email had been register before"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isValid
|
return isValid, errAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate HOtp for confirm infomation
|
// GeneratorOtp Generate HOtp for confirm information
|
||||||
|
|
||||||
func GeneratorOtp(userName string, email string, counter uint64, serect string) (bool, *models.OtpGenerate) {
|
func GeneratorOtp(userName string, email string, counter uint64, serect string) (bool, *models.OtpGenerate) {
|
||||||
|
|
||||||
serectBase32 := base32.StdEncoding.EncodeToString([]byte(serect + userName + email))
|
serectBase32 := base32.StdEncoding.EncodeToString([]byte(serect + userName + email))
|
||||||
|
|
@ -109,19 +108,13 @@ func GeneratorOtp(userName string, email string, counter uint64, serect string)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Fail to create OTP")
|
fmt.Println("Fail to create OTP")
|
||||||
return false, &models.OtpGenerate{
|
return false, nil
|
||||||
PureOTP: "none",
|
|
||||||
HashOTP: "none",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hashed, err := bcrypt.GenerateFromPassword([]byte(passCode), 5)
|
hashed, err := bcrypt.GenerateFromPassword([]byte(passCode), 5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Fail to create OTP")
|
fmt.Println("Fail to create OTP")
|
||||||
return false, &models.OtpGenerate{
|
return false, nil
|
||||||
PureOTP: "none",
|
|
||||||
HashOTP: "none",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, &models.OtpGenerate{
|
return true, &models.OtpGenerate{
|
||||||
|
|
@ -130,15 +123,43 @@ func GeneratorOtp(userName string, email string, counter uint64, serect string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a alternative verify link
|
// CreateLinkVerify Create a alternative verify link
|
||||||
func CreateLinkVerify(registerInfo *models.CreateUser, secrect string) string {
|
func CreateLinkVerify(registerInfo string, secrect string) string {
|
||||||
|
return "linh"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// check and write pre use into mongo db
|
||||||
|
func CheckAndWritePreuser(registerInfo *models.PreusersMongo) {
|
||||||
|
//checking
|
||||||
|
email := registerInfo.Email
|
||||||
|
filter := bson.D{{"email", email}}
|
||||||
|
_, err := utils.PreUserData.FindOne(context.Background(), filter).Raw()
|
||||||
|
if err != nil {
|
||||||
|
hashed, err := bcrypt.GenerateFromPassword([]byte(registerInfo.HashPassword), 10)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Fail to create OTP")
|
||||||
|
}
|
||||||
|
registerInfo.HashPassword = string(hashed)
|
||||||
|
_, err = utils.PreUserData.InsertOne(context.Background(), registerInfo)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Something Went Wrong")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
update := bson.D{
|
||||||
|
{"$inc", bson.D{
|
||||||
|
{"verify_sent_count", 1},
|
||||||
|
}},
|
||||||
|
{"$set", bson.D{
|
||||||
|
{"update_date", time.Now()},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
|
||||||
|
_, err := utils.PreUserData.UpdateOne(context.Background(), filter, update)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Internal log: update document fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
data, _ := json.Marshal(registerInfo)
|
|
||||||
key := []byte(secrect)
|
|
||||||
|
|
||||||
ciphertext, _ := utils.EncryptAES(data, key)
|
|
||||||
|
|
||||||
cipherTextBase64 := base64.StdEncoding.EncodeToString(ciphertext)
|
|
||||||
|
|
||||||
return cipherTextBase64
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
118
utils/crypto.go
118
utils/crypto.go
|
|
@ -1,79 +1,83 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
"github.com/skip2/go-qrcode"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EncryptAES(data []byte, key []byte) ([]byte, error) {
|
//Mail
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
|
type MyCustomClaims struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
jwt.RegisteredClaims
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildTokenLink(token string, w http.ResponseWriter) (string, string) {
|
||||||
|
tokenCustomTrim := strings.ReplaceAll(token, ".", "&")
|
||||||
|
emailVerifyLink := "http://www.totoday.com/?p=" + tokenCustomTrim
|
||||||
|
fmt.Println(emailVerifyLink)
|
||||||
|
png, err := qrcode.Encode(emailVerifyLink, qrcode.Low, 200)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
fmt.Println("Internal log: error create qr ")
|
||||||
|
_ = WriteJSONInternalError(w, "error create QR code")
|
||||||
|
}
|
||||||
|
base64Image := base64.StdEncoding.EncodeToString(png)
|
||||||
|
dataURL := "data:image/png;base64," + base64Image
|
||||||
|
|
||||||
|
return emailVerifyLink, dataURL
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a random IV (Initialization Vector)
|
func EncryptAESMailLink(data string, key string, w http.ResponseWriter) (string, string) {
|
||||||
iv := make([]byte, aes.BlockSize)
|
claims := MyCustomClaims{
|
||||||
if _, err := rand.Read(iv); err != nil {
|
data,
|
||||||
fmt.Println("error generating IV:", err)
|
jwt.RegisteredClaims{
|
||||||
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
|
||||||
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||||
|
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||||
|
Issuer: "totodayShop",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pad the data to a multiple of the block size
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
data = pkcs7Pad(data, aes.BlockSize)
|
token.Header["purpose"] = "Email_Verify"
|
||||||
|
|
||||||
// Create a CBC mode cipher block
|
tokenString, err := token.SignedString([]byte(key))
|
||||||
mode := cipher.NewCBCEncrypter(block, iv)
|
|
||||||
|
|
||||||
// Encrypt the data
|
|
||||||
ciphertext := make([]byte, len(data))
|
|
||||||
mode.CryptBlocks(ciphertext, data)
|
|
||||||
|
|
||||||
// Prepend the IV to the ciphertext
|
|
||||||
ciphertext = append(iv, ciphertext...)
|
|
||||||
|
|
||||||
return ciphertext, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecryptAES(base64Ciphertext string, key []byte) ([]byte, error) {
|
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
fmt.Println("Internal Log: Error signed token fail", err.Error())
|
||||||
|
_ = WriteJSONInternalError(w, "Error signing token fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode base64
|
return buildTokenLink(tokenString, w)
|
||||||
ciphertext, err := base64.StdEncoding.DecodeString(base64Ciphertext)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("error decoding base64:", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the IV from the ciphertext
|
//
|
||||||
iv := ciphertext[:aes.BlockSize]
|
//func DecryptAESMailLink(data string, key string) string {
|
||||||
ciphertext = ciphertext[aes.BlockSize:]
|
//}
|
||||||
|
|
||||||
// Create a CBC mode cipher block
|
//OTP
|
||||||
mode := cipher.NewCBCDecrypter(block, iv)
|
//Write preuser to mongo db
|
||||||
|
|
||||||
// Decrypt the data
|
//func WriteToMongo(registerInfo *models.PreusersMongo) {
|
||||||
mode.CryptBlocks(ciphertext, ciphertext)
|
//
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
// Remove padding
|
//Write otp to redis
|
||||||
ciphertext = pkcs7Unpad(ciphertext)
|
|
||||||
|
|
||||||
return ciphertext, nil
|
//func CheckAndWriteRedis(email string, username string, hashOTP string) {
|
||||||
}
|
// //checking does it valid or have in redis or not
|
||||||
|
// //var count int
|
||||||
// pkcs7Pad pads the input to a multiple of blockSize using PKCS#7 padding
|
// exists, err := Redis.Exists(context.Background(), "otp:nhocdl.poro1@gmail.com").Result()
|
||||||
func pkcs7Pad(data []byte, blockSize int) []byte {
|
// if err != nil {
|
||||||
padding := blockSize - len(data)%blockSize
|
// fmt.Println("something went wrong")
|
||||||
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
// }
|
||||||
return append(data, padText...)
|
// if exists == 0 {
|
||||||
}
|
// //count = 0
|
||||||
|
//
|
||||||
// pkcs7Unpad removes PKCS#7 padding from the input
|
// }
|
||||||
func pkcs7Unpad(data []byte) []byte {
|
//}
|
||||||
padding := int(data[len(data)-1])
|
|
||||||
return data[:len(data)-padding]
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var MongoDB *mongo.Client
|
var MongoDB *mongo.Client
|
||||||
|
var PreUserData *mongo.Collection
|
||||||
|
|
||||||
func InitMongoDriver(mongoUri string) *mongo.Client {
|
func InitMongoDriver(mongoUri string) *mongo.Client {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
@ -30,6 +31,7 @@ func InitMongoDriver(mongoUri string) *mongo.Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
MongoDB = client
|
MongoDB = client
|
||||||
|
PreUserData = MongoDB.Database("Totoday-shop").Collection("preusers")
|
||||||
|
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,21 @@ import (
|
||||||
func WriteJSON(w http.ResponseWriter, status int, v any) error {
|
func WriteJSON(w http.ResponseWriter, status int, v any) error {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
return json.NewEncoder(w).Encode(v)
|
err := json.NewEncoder(w).Encode(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteJSONInternalError(w http.ResponseWriter, v any) error {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
err := json.NewEncoder(w).Encode(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiError struct {
|
type ApiError struct {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue