From 17b6c8eb2c6882602d535520f71a89fc2fe5dc27 Mon Sep 17 00:00:00 2001 From: zakhaev26 Date: Sat, 24 Feb 2024 19:27:14 +0530 Subject: [PATCH] feat/fix: adds otp verification --- auth/cmd/main/main.go | 9 --- auth/internal/handlers/callback_signup.go | 69 +++++++++++++++++++++++ auth/internal/handlers/signup_handler.go | 45 +++++++++++++-- auth/internal/otp_gen.go | 21 +++++++ auth/internal/router/routes.go | 2 +- auth/internal/unique_entries.go | 31 ++++++++++ auth/pkg/security/jwt_impl.go | 38 +++---------- schemas/pkg/models/user_model.go | 19 ++++++- 8 files changed, 186 insertions(+), 48 deletions(-) create mode 100644 auth/internal/handlers/callback_signup.go create mode 100644 auth/internal/otp_gen.go create mode 100644 auth/internal/unique_entries.go diff --git a/auth/cmd/main/main.go b/auth/cmd/main/main.go index d16f8f1..2e807e8 100644 --- a/auth/cmd/main/main.go +++ b/auth/cmd/main/main.go @@ -5,18 +5,9 @@ import ( "net/http" "github.com/p-society/gc-server/auth/internal/router" - "github.com/p-society/gc-server/auth/pkg/security" - model "github.com/p-society/gc-server/schemas/pkg/models" ) func main() { fmt.Println("Running...") - p := model.Player{ - FirstName: "Soubhik", - } - dat, err := security.Tokenize(&p) - fmt.Println(err) - px, _ := security.DecodeToken(dat) - fmt.Println(dat, "\n\nAfter decoding = ",px) http.ListenAndServe(":2609", router.AuthRouter()) } diff --git a/auth/internal/handlers/callback_signup.go b/auth/internal/handlers/callback_signup.go new file mode 100644 index 0000000..c232e3f --- /dev/null +++ b/auth/internal/handlers/callback_signup.go @@ -0,0 +1,69 @@ +package handlers + +import ( + "context" + "encoding/json" + "net/http" + "strings" + + "github.com/p-society/gc-server/auth/internal" + "github.com/p-society/gc-server/auth/internal/db" + "github.com/p-society/gc-server/auth/pkg/security" + model "github.com/p-society/gc-server/schemas/pkg/models" +) + +func CallbackVerification(w http.ResponseWriter, r *http.Request) { + + var ( + p model.Player + pv *model.ValidationSchema + reqBody struct { + OTP int `json:"otp"` + } + ) + + json.NewDecoder(r.Body).Decode(&reqBody) + authHeader := r.Header.Get("Authorization") + + if authHeader == "" && strings.Split(authHeader, " ")[0] != "Bearer" { + r.Header.Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]interface{}{ + "error": "Authorization Token Not found", + }) + return + } + + token := strings.Split(authHeader, " ")[1] + pv = security.ParseAccessToken(token) + + if err := pv.Valid(); err != nil { + r.Header.Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]interface{}{ + "error": err.Error(), + }) + return + } + + if err := internal.CheckOTP(pv.OTP, reqBody.OTP); err != nil { + r.Header.Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]interface{}{ + "error": err.Error(), + }) + return + } + + p = model.Player{ + FirstName: pv.FirstName, + LastName: pv.LastName, + Role: pv.Role, + Email: pv.Email, + Branch: pv.Branch, + Year: pv.Branch, + ContactNo: pv.ContactNo, + Social: pv.Social, + } + + res, _ := db.PlayerCollection.InsertOne(context.TODO(), p) + + json.NewEncoder(w).Encode(res.InsertedID) +} diff --git a/auth/internal/handlers/signup_handler.go b/auth/internal/handlers/signup_handler.go index eda6705..6748e74 100644 --- a/auth/internal/handlers/signup_handler.go +++ b/auth/internal/handlers/signup_handler.go @@ -4,21 +4,53 @@ import ( "encoding/json" "fmt" "net/http" + "time" + "github.com/golang-jwt/jwt" + "github.com/p-society/gc-server/auth/internal" + "github.com/p-society/gc-server/auth/pkg/security" model "github.com/p-society/gc-server/schemas/pkg/models" ) func SignUpHandler(w http.ResponseWriter, r *http.Request) { - var p model.Player + var pv model.ValidationSchema - err := json.NewDecoder(r.Body).Decode(&p) + err := json.NewDecoder(r.Body).Decode(&pv) defer r.Body.Close() if err != nil { json.NewEncoder(w).Encode(err) + return + } + err = pv.Valid() + + if err != nil { + json.NewEncoder(w).Encode(map[string]interface{}{ + "error": err.Error(), + }) + return + } + + fmt.Println("pv.Email @signup", pv.Email) + err = internal.IsUniqueInDB(pv.Email) + if err != nil { + r.Header.Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]interface{}{ + "error": err.Error(), + }) + return + } + + // TODO:Send OTP Mail + + pv.StandardClaims = jwt.StandardClaims{ + IssuedAt: time.Now().Unix(), + ExpiresAt: time.Now().Add(5 * time.Minute).Unix(), } - err = p.Valid() + pv.OTP = internal.GenerateOTP(6) + fmt.Println("uhTP : ", pv.OTP) + token, err := security.NewAccessToken(pv) if err != nil { json.NewEncoder(w).Encode(map[string]interface{}{ "error": err.Error(), @@ -26,6 +58,9 @@ func SignUpHandler(w http.ResponseWriter, r *http.Request) { return } - fmt.Println("player ok") - json.NewEncoder(w).Encode(p) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]interface{}{ + "accessToken": token, + "validity": "5 minutes", + }) } diff --git a/auth/internal/otp_gen.go b/auth/internal/otp_gen.go new file mode 100644 index 0000000..2d78128 --- /dev/null +++ b/auth/internal/otp_gen.go @@ -0,0 +1,21 @@ +package internal + +import ( + "fmt" + "math/rand" +) + +func GenerateOTP(len int) int { + prng := rand.Float64() + prng *= 100000 + return int(prng) +} + +func CheckOTP(actualOTP int, sentOTP int) error { + + if actualOTP == sentOTP { + return nil + } + + return fmt.Errorf("OTP Invalid") +} diff --git a/auth/internal/router/routes.go b/auth/internal/router/routes.go index cc925d6..dc66a26 100644 --- a/auth/internal/router/routes.go +++ b/auth/internal/router/routes.go @@ -9,6 +9,6 @@ func AuthRouter() *mux.Router { r := mux.NewRouter() r.HandleFunc("/v0/auth/signup", handlers.SignUpHandler).Methods("post") - + r.HandleFunc("/v0/auth/callback/signup", handlers.CallbackVerification).Methods("post") return r } diff --git a/auth/internal/unique_entries.go b/auth/internal/unique_entries.go new file mode 100644 index 0000000..05eada4 --- /dev/null +++ b/auth/internal/unique_entries.go @@ -0,0 +1,31 @@ +package internal + +import ( + "context" + "errors" + "fmt" + + "github.com/p-society/gc-server/auth/internal/db" + model "github.com/p-society/gc-server/schemas/pkg/models" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" +) + +func IsUniqueInDB(email string) error { + fmt.Println("db searching ..", email) + filter := bson.M{ + "email": email, + } + + var player model.Player + err := db.PlayerCollection.FindOne(context.TODO(), filter).Decode(&player) + if err != nil { + if errors.Is(err, mongo.ErrNoDocuments) { + return nil + } + return err + } + + fmt.Println("player", player) + return fmt.Errorf("player already exists") +} diff --git a/auth/pkg/security/jwt_impl.go b/auth/pkg/security/jwt_impl.go index 12cc887..141ea87 100644 --- a/auth/pkg/security/jwt_impl.go +++ b/auth/pkg/security/jwt_impl.go @@ -1,43 +1,19 @@ package security import ( - "fmt" - "github.com/golang-jwt/jwt" model "github.com/p-society/gc-server/schemas/pkg/models" ) -var _ jwt.Claims = model.Player{} - -func Tokenize(p *model.Player) (string, error) { - signingKey := []byte("saswat,tu23kranklekeiiitkyunaaya") - token := jwt.NewWithClaims(jwt.SigningMethodHS256, p) - - tokenString, err := token.SignedString(signingKey) - - if err != nil { - return "", err - } +func NewAccessToken(claims model.ValidationSchema) (string, error) { + accessToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - return tokenString, nil + return accessToken.SignedString([]byte("saswat,tu23kranklekeiiitkyunaaya")) } -func DecodeToken(tokenString string) (model.Player, error) { - signingKey := []byte("saswat,tu23kranklekeiiitkyunaaya") // Replace with actual secret key - - token, err := jwt.ParseWithClaims(tokenString, &model.Player{}, func(token *jwt.Token) (interface{}, error) { - return signingKey, nil +func ParseAccessToken(accessToken string) *model.ValidationSchema { + parsedAccessToken, _ := jwt.ParseWithClaims(accessToken, &model.ValidationSchema{}, func(token *jwt.Token) (interface{}, error) { + return []byte([]byte("saswat,tu23kranklekeiiitkyunaaya")), nil }) - - if err != nil { - fmt.Println("err heer") - return model.Player{}, err - } - - if claims, ok := token.Claims.(*model.Player); ok && token.Valid { - fmt.Println("fname = ",&claims.FirstName) - return *claims, nil - } - - return model.Player{}, fmt.Errorf("invalid token claims") + return parsedAccessToken.Claims.(*model.ValidationSchema) } diff --git a/schemas/pkg/models/user_model.go b/schemas/pkg/models/user_model.go index 910f036..fc87c34 100644 --- a/schemas/pkg/models/user_model.go +++ b/schemas/pkg/models/user_model.go @@ -3,6 +3,7 @@ package model import ( "fmt" + "github.com/golang-jwt/jwt" enum "github.com/p-society/gc-server/enums/pkg" "go.mongodb.org/mongo-driver/bson/primitive" ) @@ -11,12 +12,26 @@ type Player struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` FirstName string `json:"firstName" bson:"firstName"` LastName string `json:"lastName" bson:"lastName"` - MailId string `json:"mailId" bson:"mailId"` + Email string `json:"email" bson:"email"` Role string `json:"role" bson:"role"` Branch string `json:"branch" bson:"branch"` Year string `json:"year" bson:"year"` ContactNo string `json:"contactNo" bson:"contactNo"` - Social []string `json:"socials" bson:"socials"` + Social []string `json:"socials,omitempty" bson:"socials,omitempty"` +} + +type ValidationSchema struct { + ID primitive.ObjectID `json:"_id,omitempty"` + FirstName string `json:"firstName"` + LastName string `json:"lastName"` + Email string `json:"email"` + Role string `json:"role"` + Branch string `json:"branch"` + Year string `json:"year"` + ContactNo string `json:"contactNo"` + Social []string `json:"socials,omitempty"` + OTP int `json:"otp"` + jwt.StandardClaims } func ValidateRole(p *Player) error {