reinstall os

This commit is contained in:
Trần Duy Linh 2024-02-17 12:43:46 +07:00
parent b9c745c17c
commit ed6776df74
8 changed files with 150 additions and 36 deletions

View File

@ -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"`
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -127,7 +127,6 @@ func CheckAccountValid(userName string, email string) (bool, *models.ResponseErr
const (
otpDigits = 6
mailValidTime = time.Minute * 15
)
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
}

View File

@ -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

BIN
tmp/main

Binary file not shown.

View File

@ -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 + "&register_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//

View File

@ -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")