Skip to content

Commit

Permalink
feat : added mail verification
Browse files Browse the repository at this point in the history
  • Loading branch information
surajhub255 committed Sep 9, 2024
1 parent b5c7faa commit 0992743
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 0 deletions.
33 changes: 33 additions & 0 deletions controllers/send_otp_handler_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package controllers

import (
"net/http"
"app.myriadflow.com/utils"
"app.myriadflow.com/models"
"github.com/gin-gonic/gin"
)

func SendOTPHandler(c *gin.Context) {
var request struct {
Email string `json:"email"`
}

if err := c.BindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}

// Generate OTP and expiration time
otp, expiration := utils.GenerateOTP()

// Send OTP via email
if err := utils.SendOTP(request.Email, otp); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err})
return
}

// Save OTP and expiration in the store (model)
models.SaveOTP(request.Email, otp, expiration)

c.JSON(http.StatusOK, gin.H{"message": "OTP sent successfully"})
}
26 changes: 26 additions & 0 deletions controllers/verify_otp_handler_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package controllers

import (
"net/http"
"app.myriadflow.com/models"
"github.com/gin-gonic/gin"
)

func VerifyOTPHandler(c *gin.Context) {
var request struct {
Email string `json:"email"`
OTP string `json:"otp"`
}

if err := c.BindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}

// Verify OTP from the store (model)
if models.VerifyOTP(request.Email, request.OTP) {
c.JSON(http.StatusOK, gin.H{"message": "OTP verified successfully"})
} else {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired OTP"})
}
}
45 changes: 45 additions & 0 deletions models/otpstore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package models

import (
"sync"
"time"
)

type OTPData struct {
otp string
expiration time.Time
}

type OTPStore struct {
data map[string]OTPData
mu sync.RWMutex
}

var store = OTPStore{
data: make(map[string]OTPData),
}

func SaveOTP(email, otp string, expiration time.Time) {
store.mu.Lock()
defer store.mu.Unlock()
store.data[email] = OTPData{
otp: otp,
expiration: expiration,
}
}

func VerifyOTP(email, otp string) bool {
store.mu.RLock()
defer store.mu.RUnlock()

// Fetch the stored OTP data for the email
data, exists := store.data[email]

// Return false if the OTP doesn't exist or if it has expired
if !exists || time.Now().After(data.expiration) {
return false
}

// Return true if the OTP matches
return data.otp == otp
}
4 changes: 4 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ func Routes(r *gin.Engine) {
r.DELETE("/cart/:wallet_address/:phygital_id", controllers.RemoveFromCart)
r.GET("/cart/:wallet_address", controllers.GetCartItems)

// OTP routes
r.POST("/send-otp", controllers.SendOTPHandler)
r.POST("/verify-otp", controllers.VerifyOTPHandler)

}


17 changes: 17 additions & 0 deletions utils/generate_otp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package utils

import (
"crypto/rand"
"time"
)

func GenerateOTP() (string, time.Time) {
otp := make([]byte, 6)
rand.Read(otp)
for i := range otp {
otp[i] = (otp[i] % 10) + '0' // generates numbers 0-9
}
// OTP valid for 5 minutes
expiration := time.Now().Add(5 * time.Minute)
return string(otp), expiration
}
19 changes: 19 additions & 0 deletions utils/send_otp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package utils

import (
"fmt"
"net/smtp"
)

func SendOTP(email, otp string) error {
from := "contact@myriadflow.com"
// password := os.Getenv("SMTP_PASSWORD")
password := ""
smtpHost := "smtp.zoho.com"
smtpPort := "587"

msg := []byte(fmt.Sprintf("Subject: OTP Verification\n\nYour OTP is: %s ", otp))

auth := smtp.PlainAuth("", from, password, smtpHost)
return smtp.SendMail(smtpHost+":"+smtpPort, auth, from, []string{email}, msg)
}

0 comments on commit 0992743

Please sign in to comment.