reinstall os
This commit is contained in:
parent
b9c745c17c
commit
ed6776df74
|
|
@ -130,3 +130,8 @@ type SuccessAPI struct {
|
|||
Message string `json:"message"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type LinkVerify struct {
|
||||
JWT string `json:"jwt"`
|
||||
UUID string `json:"uuid"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package rest_api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"linhdevtran99/rest-api/models"
|
||||
"linhdevtran99/rest-api/rest-api/routes"
|
||||
"linhdevtran99/rest-api/utils"
|
||||
"log"
|
||||
|
|
@ -23,7 +25,7 @@ func NewAPIServer(listenAddr string) *APIServer {
|
|||
func startMuxServer(s *APIServer, router *mux.Router) {
|
||||
log.Println("Listening on", s.listenAddr)
|
||||
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
|
||||
originsOk := handlers.AllowedOrigins([]string{"https://app.wliafdew.dev"})
|
||||
originsOk := handlers.AllowedOrigins([]string{"https://app.wliafdew.dev", "http://localhost:4200"})
|
||||
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
|
||||
if err := http.ListenAndServe(s.listenAddr, handlers.CORS(originsOk, headersOk, methodsOk)(router)); err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
@ -42,8 +44,12 @@ func (s *APIServer) Run() {
|
|||
|
||||
func (s *APIServer) TestRoute(w http.ResponseWriter, r *http.Request) error {
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
//utils.VerifyOTP()
|
||||
if r.Method == http.MethodPost {
|
||||
var linkVerifyInfo models.LinkVerify
|
||||
|
||||
_ = json.NewDecoder(r.Body).Decode(&linkVerifyInfo)
|
||||
|
||||
utils.DecryptAESMailLink(&linkVerifyInfo, w)
|
||||
fmt.Println("hello")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package routes
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/mux"
|
||||
"linhdevtran99/rest-api/models"
|
||||
"linhdevtran99/rest-api/rest-api/services"
|
||||
|
|
@ -75,8 +76,34 @@ func VerifyWithOTP(w http.ResponseWriter, r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func VerifyWithJWT(w http.ResponseWriter, r *http.Request) error {
|
||||
fmt.Println("hello")
|
||||
if r.Method == http.MethodPost {
|
||||
var jwtInfo models.LinkVerify
|
||||
_ = json.NewDecoder(r.Body).Decode(&jwtInfo)
|
||||
_, err := uuid.Parse(jwtInfo.UUID)
|
||||
//checking uuid
|
||||
if err != nil {
|
||||
fmt.Println("Internal log: UUID not valid")
|
||||
_ = utils.WriteJSON(w, http.StatusBadRequest, models.ErrorAPI{
|
||||
Errors: []string{"UUID not valid"},
|
||||
Message: "UUID not valid",
|
||||
Type: "UUIDNotValid",
|
||||
})
|
||||
return err
|
||||
}
|
||||
//call function check jwt
|
||||
isValid, email := utils.DecryptAESMailLink(&jwtInfo, w)
|
||||
|
||||
if isValid == true {
|
||||
services.VerifyWithJWT(email, w)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func AuthRouterSetup(router *mux.Router) {
|
||||
authRouter := router.PathPrefix("/account").Subrouter()
|
||||
authRouter.Handle("/register", utils.MakeHTTPHandlerFn(RegisterNewAccount)).Methods("POST")
|
||||
authRouter.Handle("/register/verifyAccountOTP", utils.MakeHTTPHandlerFn(VerifyWithOTP)).Methods("POST")
|
||||
authRouter.Handle("/register/verifyAccountJWT", utils.MakeHTTPHandlerFn(VerifyWithJWT)).Methods("POST")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,8 +126,7 @@ func CheckAccountValid(userName string, email string) (bool, *models.ResponseErr
|
|||
// GeneratorOtp Generate OTP Verify Link and Qr Link
|
||||
|
||||
const (
|
||||
otpDigits = 6
|
||||
mailValidTime = time.Minute * 15
|
||||
otpDigits = 6
|
||||
)
|
||||
|
||||
func GenerateVerifyAccount(registerInfo *models.PreusersMongo, w http.ResponseWriter) error {
|
||||
|
|
@ -136,11 +135,11 @@ func GenerateVerifyAccount(registerInfo *models.PreusersMongo, w http.ResponseWr
|
|||
otpChannel := make(chan models.OtpGenerate, 1)
|
||||
mailChannel := make(chan models.MailVefiry, 1)
|
||||
|
||||
counter := CheckAndWritePreuser(registerInfo, w)
|
||||
counter, timerCreate := CheckAndWritePreuser(registerInfo, w)
|
||||
wg.Add(1)
|
||||
go utils.GenOTP(registerInfo, counter, otpDigits, w, otpChannel, &wg)
|
||||
wg.Add(1)
|
||||
go utils.EncryptAESMailLink(registerInfo, w, mailChannel, &wg)
|
||||
go utils.EncryptAESMailLink(registerInfo, w, mailChannel, &wg, timerCreate)
|
||||
go createMailVerify(registerInfo, otpChannel, mailChannel, w)
|
||||
go writeOTPInRedis(counter, registerInfo, otpChannel, w)
|
||||
|
||||
|
|
@ -166,7 +165,7 @@ func createMailVerify(registerInfo *models.PreusersMongo, otpChan chan models.Ot
|
|||
}
|
||||
|
||||
qrFileName := registerInfo.Email + registerInfo.Username + ".png"
|
||||
os.WriteFile("./temp/"+qrFileName, decodedImage, 0666)
|
||||
_ = os.WriteFile("./temp/"+qrFileName, decodedImage, 0666)
|
||||
emailBody := utils.BuildEmail(opt.PureOTP, mailVerify.LinkMail, qrFileName)
|
||||
|
||||
m.SetHeader("From", "admin@wliafdew.dev")
|
||||
|
|
@ -186,12 +185,15 @@ func createMailVerify(registerInfo *models.PreusersMongo, otpChan chan models.Ot
|
|||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("./temp/" + qrFileName)
|
||||
_ = os.Remove("./temp/" + qrFileName)
|
||||
}()
|
||||
}
|
||||
|
||||
// check and write pre use into mongo db
|
||||
func CheckAndWritePreuser(registerInfo *models.PreusersMongo, w http.ResponseWriter) uint64 {
|
||||
func CheckAndWritePreuser(registerInfo *models.PreusersMongo, w http.ResponseWriter) (uint64, time.Time) {
|
||||
//generate timestamp
|
||||
timeCreate := time.Now()
|
||||
registerInfo.CreatedDate = timeCreate
|
||||
//checking
|
||||
email := registerInfo.Email
|
||||
count := 1
|
||||
|
|
@ -200,8 +202,8 @@ func CheckAndWritePreuser(registerInfo *models.PreusersMongo, w http.ResponseWri
|
|||
if err != nil {
|
||||
hashed, err := bcrypt.GenerateFromPassword([]byte(registerInfo.HashPassword), 10)
|
||||
if err != nil {
|
||||
fmt.Println("Internal Log :Fail to create OTP")
|
||||
_ = utils.WriteJSONInternalError(w, "Fail to create OTP")
|
||||
fmt.Println("Internal Log :Fail to hash password")
|
||||
_ = utils.WriteJSONInternalError(w, "Fail to hash password")
|
||||
}
|
||||
registerInfo.HashPassword = string(hashed)
|
||||
_, err = utils.PreUserData.InsertOne(context.Background(), registerInfo)
|
||||
|
|
@ -209,14 +211,14 @@ func CheckAndWritePreuser(registerInfo *models.PreusersMongo, w http.ResponseWri
|
|||
fmt.Println("Internal Log: Can't Insert Data To PreUser")
|
||||
_ = utils.WriteJSONInternalError(w, "Can't Insert Data To PreUser")
|
||||
}
|
||||
return uint64(count)
|
||||
return uint64(count), timeCreate
|
||||
} else {
|
||||
update := bson.D{
|
||||
{"$inc", bson.D{
|
||||
{"verify_sent_count", 1},
|
||||
}},
|
||||
{"$set", bson.D{
|
||||
{"update_date", time.Now()},
|
||||
{"update_date", timeCreate},
|
||||
},
|
||||
}}
|
||||
|
||||
|
|
@ -227,7 +229,7 @@ func CheckAndWritePreuser(registerInfo *models.PreusersMongo, w http.ResponseWri
|
|||
}
|
||||
fmt.Println()
|
||||
count = int(raw.Lookup("verify_sent_count").Int32() + 1)
|
||||
return uint64(count)
|
||||
return uint64(count), timeCreate
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -258,10 +260,10 @@ func writeOTPInRedis(counter uint64, registerInfo *models.PreusersMongo, otpChan
|
|||
}
|
||||
|
||||
// ////////////////////////Create User Complete//////////////////////////
|
||||
func CreateUserAfterVerify(otpInfo *models.OTPVerify, redis *models.RedisOTP, w http.ResponseWriter) bool {
|
||||
func CreateUserAfterVerify(email string, w http.ResponseWriter) bool {
|
||||
isValid := true
|
||||
var preUserData models.PreusersMongo
|
||||
filter := bson.D{{"email", otpInfo.Email}}
|
||||
filter := bson.D{{"email", email}}
|
||||
err := utils.PreUserData.FindOne(context.Background(), filter).Decode(&preUserData)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -278,7 +280,7 @@ func CreateUserAfterVerify(otpInfo *models.OTPVerify, redis *models.RedisOTP, w
|
|||
Active: true,
|
||||
CreatedDate: time.Now(),
|
||||
UpdateDate: time.Now(),
|
||||
VerifySentCount: int(redis.Counter),
|
||||
VerifySentCount: preUserData.VerifySentCount,
|
||||
}
|
||||
|
||||
_, err = utils.User.InsertOne(context.Background(), user)
|
||||
|
|
@ -303,9 +305,9 @@ func CreateUserAfterVerify(otpInfo *models.OTPVerify, redis *models.RedisOTP, w
|
|||
|
||||
//////////////////////////Verify OTP//////////////////////////
|
||||
|
||||
func CheckUserVerify(otpInfo *models.OTPVerify, w http.ResponseWriter) bool {
|
||||
func CheckUserVerify(email string, w http.ResponseWriter) bool {
|
||||
isVerified := false
|
||||
filter := bson.D{{"email", otpInfo.Email}}
|
||||
filter := bson.D{{"email", email}}
|
||||
var user models.UsersMongo
|
||||
_ = utils.User.FindOne(context.Background(), filter).Decode(&user)
|
||||
|
||||
|
|
@ -353,14 +355,31 @@ func CheckOTPIsValid(otpInfo *models.OTPVerify, w http.ResponseWriter) bool {
|
|||
isValid = false
|
||||
}
|
||||
|
||||
if isVerified := CheckUserVerify(otpInfo, w); isVerified == true {
|
||||
if isVerified := CheckUserVerify(otpInfo.Email, w); isVerified == true {
|
||||
return false
|
||||
}
|
||||
|
||||
isValid = utils.VerifyOTP(otpInfo, dataRedis, w)
|
||||
|
||||
if isValid == true {
|
||||
CreateUserAfterVerify(otpInfo, &dataRedis, w)
|
||||
CreateUserAfterVerify(otpInfo.Email, w)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//////////////////////////Verify JWT//////////////////////////
|
||||
|
||||
func VerifyWithJWT(email string, w http.ResponseWriter) bool {
|
||||
var isValid bool
|
||||
isValid = true
|
||||
//verify uuid and email
|
||||
|
||||
if isVerified := CheckUserVerify(email, w); isVerified == true {
|
||||
return false
|
||||
}
|
||||
|
||||
if isValid == true {
|
||||
CreateUserAfterVerify(email, w)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +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
|
||||
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 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
||||
|
|
@ -1,18 +1,20 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/pquerna/otp"
|
||||
"github.com/pquerna/otp/hotp"
|
||||
"github.com/skip2/go-qrcode"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"linhdevtran99/rest-api/models"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -28,9 +30,8 @@ type MyCustomClaims struct {
|
|||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func buildTokenLink(token string, w http.ResponseWriter) (string, string) {
|
||||
tokenCustomTrim := strings.ReplaceAll(token, ".", "&")
|
||||
emailVerifyLink := "https://api.wliafdew.dev/?p=" + tokenCustomTrim
|
||||
func buildTokenLink(registerInfo *models.PreusersMongo, token string, w http.ResponseWriter) (string, string) {
|
||||
emailVerifyLink := "http://localhost:4200/register?uuid=" + registerInfo.UUID + "®ister_step=verify_with_jwt" + "&p=" + token
|
||||
png, err := qrcode.Encode(emailVerifyLink, qrcode.Low, 200)
|
||||
if err != nil {
|
||||
fmt.Println("Internal log: error create qr ")
|
||||
|
|
@ -41,27 +42,28 @@ func buildTokenLink(token string, w http.ResponseWriter) (string, string) {
|
|||
return emailVerifyLink, base64Image
|
||||
}
|
||||
|
||||
func EncryptAESMailLink(registerInfo *models.PreusersMongo, w http.ResponseWriter, mailChan chan models.MailVefiry, wg *sync.WaitGroup) chan models.MailVefiry {
|
||||
func EncryptAESMailLink(registerInfo *models.PreusersMongo, w http.ResponseWriter, mailChan chan models.MailVefiry, wg *sync.WaitGroup, timeCreate time.Time) chan models.MailVefiry {
|
||||
claims := MyCustomClaims{
|
||||
registerInfo.Email,
|
||||
jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(5 * time.Hour)),
|
||||
IssuedAt: jwt.NewNumericDate(timeCreate),
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
Issuer: "totodayShop",
|
||||
Issuer: "totodayShopRegister",
|
||||
},
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
token.Header["purpose"] = "Email_Verify"
|
||||
|
||||
tokenString, err := token.SignedString([]byte(serect))
|
||||
tokenString, err := token.SignedString([]byte(serect + registerInfo.UUID))
|
||||
if err != nil {
|
||||
fmt.Println("Internal Log: Error signed token fail", err.Error())
|
||||
_ = WriteJSONInternalError(w, "Error signing token fail")
|
||||
}
|
||||
tokenBS64 := base64.StdEncoding.EncodeToString([]byte(tokenString))
|
||||
|
||||
linkMail, imageB64 := buildTokenLink(tokenString, w)
|
||||
linkMail, imageB64 := buildTokenLink(registerInfo, tokenBS64, w)
|
||||
|
||||
data := models.MailVefiry{
|
||||
LinkMail: linkMail,
|
||||
|
|
@ -75,9 +77,62 @@ func EncryptAESMailLink(registerInfo *models.PreusersMongo, w http.ResponseWrite
|
|||
|
||||
}
|
||||
|
||||
//
|
||||
//func DecryptAESMailLink(data string, key string) string {
|
||||
//}
|
||||
func DecryptAESMailLink(linkVerifyInfo *models.LinkVerify, w http.ResponseWriter) (bool, string) {
|
||||
decodeBase64, err := base64.StdEncoding.DecodeString(linkVerifyInfo.JWT)
|
||||
token, err := jwt.ParseWithClaims(string(decodeBase64), &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(serect + linkVerifyInfo.UUID), nil
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("Internal log: Error decrypt token fail", err.Error())
|
||||
if errors.Is(err, jwt.ErrTokenMalformed) {
|
||||
_ = WriteJSON(w, http.StatusBadRequest, models.ErrorAPI{
|
||||
Errors: []string{"Token is malformed"},
|
||||
Message: "Token is invalid",
|
||||
Type: "TokenMalformed",
|
||||
})
|
||||
}
|
||||
if errors.Is(err, jwt.ErrSignatureInvalid) {
|
||||
_ = WriteJSON(w, http.StatusBadRequest, models.ErrorAPI{
|
||||
Errors: []string{"UUID is invalid"},
|
||||
Message: "UUID is invalid",
|
||||
Type: "UUIDInvalid",
|
||||
})
|
||||
}
|
||||
|
||||
if errors.Is(err, jwt.ErrTokenExpired) {
|
||||
_ = WriteJSON(w, http.StatusBadRequest, models.ErrorAPI{
|
||||
Errors: []string{"Token is expired"},
|
||||
Message: "Link is expired please register again",
|
||||
Type: "TokenExpired",
|
||||
})
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
if token.Valid && token.Header["purpose"] == "Email_Verify" && err == nil {
|
||||
//get update date from preuser
|
||||
var preUser models.PreusersMongo
|
||||
email := token.Claims.(*MyCustomClaims).Email
|
||||
err := PreUserData.FindOne(context.TODO(), bson.M{"email": email}).Decode(&preUser)
|
||||
if err != nil {
|
||||
//handler erorr later
|
||||
fmt.Println("Internal log: Error find preuser fail", err.Error())
|
||||
return false, ""
|
||||
}
|
||||
timeRegisterToken := preUser.UpdateDate.Unix()
|
||||
timeIssueToken, _ := token.Claims.GetIssuedAt()
|
||||
if timeRegisterToken != timeIssueToken.Unix() {
|
||||
//handler erorr later
|
||||
fmt.Println("Internal log: Error token is not valid to use")
|
||||
return false, ""
|
||||
}
|
||||
return true, email
|
||||
}
|
||||
|
||||
return false, ""
|
||||
|
||||
}
|
||||
|
||||
//OTP+++++++++++++OTP//
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ func BuildEmail(otp string, mailLink string, fileName string) string {
|
|||
QrCode: qrcodeURL,
|
||||
}
|
||||
|
||||
fmt.Println(data.AlternativeLink)
|
||||
|
||||
//tmpl, err := template.ParseFiles("./Template/email.html")
|
||||
tmpl, err := template.ParseFiles("./Template/email.html")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue