package controllers import ( "context" "fmt" "log" "net/http" "time" "github.com/Uttkarsh-raj/To_Do_App/database" "github.com/Uttkarsh-raj/To_Do_App/helpers" "github.com/Uttkarsh-raj/To_Do_App/models" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "golang.org/x/crypto/bcrypt" ) var userCollection *mongo.Collection = database.OpenCollection(database.Client, "user") var validate = validator.New() // Now implement password hashing and verification in your controllers/userController.go file with the following code. // HashPassword is used to encrypt the password before it is stored in the DB func HashPassword(password string) string { bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) if err != nil { log.Panic(err) } return string(bytes) } // VerifyPassword checks the input password while verifying it with the passward in the DB. func VerifyPassword(userPassword string, providedPassword string) (bool, string) { err := bcrypt.CompareHashAndPassword([]byte(providedPassword), []byte(userPassword)) check := true msg := "" if err != nil { msg = fmt.Sprintf("login or passowrd is incorrect") check = false } return check, msg } // Now let's move on to implementing the signup and login service in your controllers/userController.go file with the following code. Kindly note that some functions such as helper.GenerateAllTokens and helper.UpdateAllTokens will not be available since you haven't written them yet. keep calm 😁😁 // CreateUser is the api used to tget a single user func SignUp() gin.HandlerFunc { return func(c *gin.Context) { var ctx, cancel = context.WithTimeout(context.Background(), 100*time.Second) var user models.User if err := c.BindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } validationErr := validate.Struct(user) if validationErr != nil { c.JSON(http.StatusBadRequest, gin.H{"error": validationErr.Error()}) return } count, err := userCollection.CountDocuments(ctx, bson.M{"email": user.Email}) defer cancel() if err != nil { log.Panic(err) c.JSON(http.StatusInternalServerError, gin.H{"error": "error occured while checking for the email"}) return } password := HashPassword(*user.Password) user.Password = &password count, err = userCollection.CountDocuments(ctx, bson.M{"phone": user.Phone}) defer cancel() if err != nil { log.Panic(err) c.JSON(http.StatusInternalServerError, gin.H{"error": "error occured while checking for the phone number"}) return } if count > 0 { c.JSON(http.StatusInternalServerError, gin.H{"error": "this email or phone number already exists"}) return } user.Created_at, _ = time.Parse(time.RFC3339, time.Now().Format(time.RFC3339)) user.Updated_at, _ = time.Parse(time.RFC3339, time.Now().Format(time.RFC3339)) user.ID = primitive.NewObjectID() user.User_id = user.ID.Hex() token, refreshToken, _ := helpers.GenerateAllTokens(*user.Email, *user.First_name, *user.Last_name, user.User_id) user.Token = &token user.Refresh_token = &refreshToken resultInsertionNumber, insertErr := userCollection.InsertOne(ctx, user) log.Printf("resultInsertionNumber %d", resultInsertionNumber) if insertErr != nil { msg := fmt.Sprintf("User item was not created") c.JSON(http.StatusInternalServerError, gin.H{"error": msg}) return } defer cancel() c.JSON(http.StatusOK, resultInsertionNumber) } } // Login is the api used to tget a single user func Login() gin.HandlerFunc { return func(c *gin.Context) { var ctx, cancel = context.WithTimeout(context.Background(), 100*time.Second) var user models.User var foundUser models.User if err := c.BindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } err := userCollection.FindOne(ctx, bson.M{"email": user.Email}).Decode(&foundUser) defer cancel() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "login or passowrd is incorrect"}) return } passwordIsValid, msg := VerifyPassword(*user.Password, *foundUser.Password) defer cancel() if passwordIsValid != true { c.JSON(http.StatusInternalServerError, gin.H{"error": msg}) return } token, refreshToken, _ := helpers.GenerateAllTokens(*foundUser.Email, *foundUser.First_name, *foundUser.Last_name, foundUser.User_id) helpers.UpdateAllToken(token, refreshToken, foundUser.User_id) c.JSON(http.StatusOK, foundUser) } }