From f5ac8decdae50c84dbd755d7bb08658292befcf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sad=C4=B1k=20S=C3=BCnb=C3=BCl?= <109942759+SadikSunbul@users.noreply.github.com> Date: Fri, 7 Feb 2025 13:02:25 +0300 Subject: [PATCH 1/3] Added Email Verification --- README.md | 1 + email-verification/README.md | 99 +++++++++++++++++++ .../api/handlers/verification.go | 38 +++++++ .../application/verification_service.go | 66 +++++++++++++ email-verification/config/config.go | 23 +++++ email-verification/domain/code_generator.go | 6 ++ email-verification/domain/verification.go | 18 ++++ email-verification/go.mod | 25 +++++ email-verification/go.sum | 57 +++++++++++ .../infrastructure/code/generator.go | 29 ++++++ .../infrastructure/email/smtp.go | 35 +++++++ .../infrastructure/repository/memory.go | 43 ++++++++ email-verification/main.go | 32 ++++++ 13 files changed, 472 insertions(+) create mode 100644 email-verification/README.md create mode 100644 email-verification/api/handlers/verification.go create mode 100644 email-verification/application/verification_service.go create mode 100644 email-verification/config/config.go create mode 100644 email-verification/domain/code_generator.go create mode 100644 email-verification/domain/verification.go create mode 100644 email-verification/go.mod create mode 100644 email-verification/go.sum create mode 100644 email-verification/infrastructure/code/generator.go create mode 100644 email-verification/infrastructure/email/smtp.go create mode 100644 email-verification/infrastructure/repository/memory.go create mode 100644 email-verification/main.go diff --git a/README.md b/README.md index 6423722bde..8d018b68fa 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Here you can find the most **delicious** recipes to cook delicious meals using o - [Docker + MariaDB](./docker-mariadb-clean-arch/README.md) - Dockerized MariaDB with Clean Architecture. - [Docker + Nginx](./docker-nginx-loadbalancer/README.md) - Load balancing with Docker and Nginx. - [Dummy JSON Proxy](./dummyjson/README.md) - Proxying dummy JSON data. +- [Email Verification](./email-verification/README.md) - Email verification service with code generation and validation. - [Entgo ORM (MySQL)](./ent-mysql/README.md) - Using Entgo ORM with MySQL - [Entgo Sveltekit](./entgo-sveltekit/README.md) - A full-stack Todo application built using Sveltekit, Tailwind CSS, Entgo, and SQLite. - [Envoy External Authorization](./envoy-extauthz/README.md) - External authorization with Envoy. diff --git a/email-verification/README.md b/email-verification/README.md new file mode 100644 index 0000000000..f279163fef --- /dev/null +++ b/email-verification/README.md @@ -0,0 +1,99 @@ +--- +title: Email Verification Service +keywords: [email, verification, smtp, golang, fiber] +description: Email verification service with code generation and validation +--- + +# Email Verification Service with Fiber + +[![Github](https://img.shields.io/static/v1?label=&message=Github&color=2ea44f&style=for-the-badge&logo=github)](https://github.com/gofiber/recipes/tree/master/email-verification) [![StackBlitz](https://img.shields.io/static/v1?label=&message=StackBlitz&color=2ea44f&style=for-the-badge&logo=StackBlitz)](https://stackblitz.com/github/gofiber/recipes/tree/master/email-verification) + +A clean architecture based email verification service that generates and validates verification codes. + +## Features + +- Clean Architecture implementation +- In-memory verification code storage +- SMTP email service integration +- Code generation and hashing +- Configurable code expiration +- Thread-safe operations + +## Project Structure + +``` +email-verification/ +├── api/ +│ └── handlers/ # HTTP handlers +├── application/ # Application business logic +├── domain/ # Domain models and interfaces +├── infrastructure/ # External implementations +│ ├── code/ # Code generation +│ ├── email/ # SMTP service +│ └── repository/ # Data storage +└── config/ # Configuration +``` + +## Configuration + +Update `config/config.go` with your SMTP settings: + +```go +func GetConfig() *Config { + return &Config{ + SMTPHost: "smtp.gmail.com", + SMTPPort: 587, + SMTPUser: "your-email@gmail.com", + SMTPPassword: "your-app-password", + CodeExpiration: time.Minute * 1, + } +} +``` + +## API Endpoints + +| Method | URL | Description | +|--------|----------------------------|--------------------------------| +| POST | /verify/send/:email | Send verification code | +| POST | /verify/check/:email/:code | Verify the received code | + +## Example Usage + +1. Send verification code: +```bash +curl -X POST http://localhost:3000/verify/send/user@example.com +``` + +2. Verify code: +```bash +curl -X POST http://localhost:3000/verify/check/user@example.com/123456 +``` + +## Response Examples + +Success: +```json +{ + "message": "Code verified successfully" +} +``` + +Error: +```json +{ + "error": "invalid code" +} +``` + +## How to Run + +1. Configure SMTP settings in `config/config.go` +2. Run the application: +```bash +go run main.go +``` + +## Dependencies + +- [Fiber v2](https://github.com/gofiber/fiber) +- Go 1.21+ diff --git a/email-verification/api/handlers/verification.go b/email-verification/api/handlers/verification.go new file mode 100644 index 0000000000..2da279c8ee --- /dev/null +++ b/email-verification/api/handlers/verification.go @@ -0,0 +1,38 @@ +package handlers + +import ( + "email-verification/application" + + "github.com/gofiber/fiber/v2" +) + +type VerificationHandler struct { + verificationService *application.VerificationService +} + +func NewVerificationHandler(service *application.VerificationService) *VerificationHandler { + return &VerificationHandler{verificationService: service} +} + +func (h *VerificationHandler) SendVerification(c *fiber.Ctx) error { + email := c.Params("email") + if err := h.verificationService.SendVerification(email); err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": err.Error(), + }) + } + return c.JSON(fiber.Map{"message": "Verification code sent"}) +} + +func (h *VerificationHandler) CheckVerification(c *fiber.Ctx) error { + email := c.Params("email") + code := c.Params("code") + + if err := h.verificationService.VerifyCode(email, code); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": err.Error(), + }) + } + + return c.JSON(fiber.Map{"message": "Code verified successfully"}) +} diff --git a/email-verification/application/verification_service.go b/email-verification/application/verification_service.go new file mode 100644 index 0000000000..c89ecbb46a --- /dev/null +++ b/email-verification/application/verification_service.go @@ -0,0 +1,66 @@ +package application + +import ( + "email-verification/config" + "email-verification/domain" + "fmt" + "time" +) + +type VerificationService struct { + repo domain.VerificationRepository + emailService domain.EmailService + codeGen domain.CodeGenerator + codeExpiration time.Duration +} + +func NewVerificationService( + repo domain.VerificationRepository, + emailService domain.EmailService, + codeGen domain.CodeGenerator, + config *config.Config, +) *VerificationService { + return &VerificationService{ + repo: repo, + emailService: emailService, + codeGen: codeGen, + codeExpiration: config.CodeExpiration, + } +} + +func (s *VerificationService) SendVerification(email string) error { + code, err := s.codeGen.Generate() + if err != nil { + return err + } + + if err := s.emailService.SendVerificationCode(email, code); err != nil { + return err + } + + verification := domain.Verification{ + Code: s.codeGen.Hash(code), + Exp: time.Now().Add(s.codeExpiration), + } + + return s.repo.Store(email, verification) +} + +func (s *VerificationService) VerifyCode(email, code string) error { + verification, err := s.repo.Get(email) + if err != nil { + return err + } + + hashedCode := s.codeGen.Hash(code) + if verification.Code != hashedCode { + return fmt.Errorf("invalid code") + } + + if time.Now().After(verification.Exp) { + s.repo.Delete(email) + return fmt.Errorf("code expired") + } + + return s.repo.Delete(email) +} diff --git a/email-verification/config/config.go b/email-verification/config/config.go new file mode 100644 index 0000000000..624b17f29b --- /dev/null +++ b/email-verification/config/config.go @@ -0,0 +1,23 @@ +package config + +import ( + "time" +) + +type Config struct { + SMTPHost string + SMTPPort int + SMTPUser string + SMTPPassword string + CodeExpiration time.Duration +} + +func GetConfig() *Config { + return &Config{ + SMTPHost: "smtp.gmail.com", + SMTPPort: 587, + SMTPUser: "your-email@gmail.com", + SMTPPassword: "your-app-password", + CodeExpiration: time.Minute * 1, + } +} diff --git a/email-verification/domain/code_generator.go b/email-verification/domain/code_generator.go new file mode 100644 index 0000000000..69f5ff4627 --- /dev/null +++ b/email-verification/domain/code_generator.go @@ -0,0 +1,6 @@ +package domain + +type CodeGenerator interface { + Generate() (string, error) + Hash(code string) string +} diff --git a/email-verification/domain/verification.go b/email-verification/domain/verification.go new file mode 100644 index 0000000000..86698180b2 --- /dev/null +++ b/email-verification/domain/verification.go @@ -0,0 +1,18 @@ +package domain + +import "time" + +type Verification struct { + Code string + Exp time.Time +} + +type VerificationRepository interface { + Store(email string, verification Verification) error + Get(email string) (Verification, error) + Delete(email string) error +} + +type EmailService interface { + SendVerificationCode(to string, code string) error +} diff --git a/email-verification/go.mod b/email-verification/go.mod new file mode 100644 index 0000000000..516a296a72 --- /dev/null +++ b/email-verification/go.mod @@ -0,0 +1,25 @@ +module email-verification + +go 1.21 + +require ( + github.com/gofiber/fiber/v2 v2.52.6 + golang.org/x/crypto v0.32.0 +) + +require ( + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/gofiber/fiber v1.14.6 // indirect + github.com/gofiber/utils v0.0.10 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/schema v1.1.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.29.0 // indirect +) diff --git a/email-verification/go.sum b/email-verification/go.sum new file mode 100644 index 0000000000..917e23c559 --- /dev/null +++ b/email-verification/go.sum @@ -0,0 +1,57 @@ +github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/gofiber/fiber v1.14.6 h1:QRUPvPmr8ijQuGo1MgupHBn8E+wW0IKqiOvIZPtV70o= +github.com/gofiber/fiber v1.14.6/go.mod h1:Yw2ekF1YDPreO9V6TMYjynu94xRxZBdaa8X5HhHsjCM= +github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI= +github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/gofiber/utils v0.0.10 h1:3Mr7X7JdCUo7CWf/i5sajSaDmArEDtti8bM1JUVso2U= +github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= +github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg= +github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.16.0 h1:9zAqOYLl8Tuy3E5R6ckzGDJ1g8+pw15oQp2iL9Jl6gQ= +github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/email-verification/infrastructure/code/generator.go b/email-verification/infrastructure/code/generator.go new file mode 100644 index 0000000000..ed82c0aef6 --- /dev/null +++ b/email-verification/infrastructure/code/generator.go @@ -0,0 +1,29 @@ +package code + +import ( + "crypto/rand" + "encoding/hex" + "fmt" + + "golang.org/x/crypto/sha3" +) + +type DefaultCodeGenerator struct{} + +func NewCodeGenerator() *DefaultCodeGenerator { + return &DefaultCodeGenerator{} +} + +func (g *DefaultCodeGenerator) Generate() (string, error) { + b := make([]byte, 3) + if _, err := rand.Read(b); err != nil { + return "", err + } + return fmt.Sprintf("%06x", b), nil +} + +func (g *DefaultCodeGenerator) Hash(code string) string { + hash := sha3.New256() + hash.Write([]byte(code)) + return hex.EncodeToString(hash.Sum(nil)) +} diff --git a/email-verification/infrastructure/email/smtp.go b/email-verification/infrastructure/email/smtp.go new file mode 100644 index 0000000000..578db59128 --- /dev/null +++ b/email-verification/infrastructure/email/smtp.go @@ -0,0 +1,35 @@ +package email + +import ( + "email-verification/config" + "fmt" + "net/smtp" +) + +type SMTPService struct { + config *config.Config +} + +func NewSMTPService(config *config.Config) *SMTPService { + return &SMTPService{config: config} +} + +func (s *SMTPService) SendVerificationCode(to string, code string) error { + subject := "Subject: Email Verification Code \n" + body := fmt.Sprintf("Your verification code is %s", code) + message := []byte(subject + "\n" + body) + + auth := smtp.PlainAuth("", s.config.SMTPUser, s.config.SMTPPassword, s.config.SMTPHost) + err := smtp.SendMail( + fmt.Sprintf("%s:%d", s.config.SMTPHost, s.config.SMTPPort), + auth, + s.config.SMTPUser, + []string{to}, + message, + ) + if err != nil { + return err + } + + return nil +} diff --git a/email-verification/infrastructure/repository/memory.go b/email-verification/infrastructure/repository/memory.go new file mode 100644 index 0000000000..a94af0bc1e --- /dev/null +++ b/email-verification/infrastructure/repository/memory.go @@ -0,0 +1,43 @@ +package repository + +import ( + "email-verification/domain" + "fmt" + "sync" +) + +type MemoryRepository struct { + verifications map[string]domain.Verification + mu sync.RWMutex +} + +func NewMemoryRepository() *MemoryRepository { + return &MemoryRepository{ + verifications: make(map[string]domain.Verification), + } +} + +func (r *MemoryRepository) Store(email string, v domain.Verification) error { + r.mu.Lock() + defer r.mu.Unlock() + r.verifications[email] = v + return nil +} + +func (r *MemoryRepository) Get(email string) (domain.Verification, error) { + r.mu.RLock() + defer r.mu.RUnlock() + + v, exists := r.verifications[email] + if !exists { + return domain.Verification{}, fmt.Errorf("verification not found") + } + return v, nil +} + +func (r *MemoryRepository) Delete(email string) error { + r.mu.Lock() + defer r.mu.Unlock() + delete(r.verifications, email) + return nil +} diff --git a/email-verification/main.go b/email-verification/main.go new file mode 100644 index 0000000000..95aa8be5e5 --- /dev/null +++ b/email-verification/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "email-verification/api/handlers" + "email-verification/application" + "email-verification/config" + "email-verification/infrastructure/code" + "email-verification/infrastructure/email" + "email-verification/infrastructure/repository" + + "github.com/gofiber/fiber/v2" +) + +func main() { + // Dependencies + repo := repository.NewMemoryRepository() + emailService := email.NewSMTPService(config.GetConfig()) + codeGen := code.NewCodeGenerator() + + // Services + verificationService := application.NewVerificationService(repo, emailService, codeGen, config.GetConfig()) + + // Handlers + verificationHandler := handlers.NewVerificationHandler(verificationService) + + // Router + app := fiber.New() + app.Post("/verify/send/:email", verificationHandler.SendVerification) + app.Post("/verify/check/:email/:code", verificationHandler.CheckVerification) + + app.Listen(":3000") +} From 33325c6e77da09c8160adc2a16ce61e5004fb3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sad=C4=B1k=20S=C3=BCnb=C3=BCl?= <109942759+SadikSunbul@users.noreply.github.com> Date: Fri, 7 Feb 2025 13:23:02 +0300 Subject: [PATCH 2/3] minor changes were made --- .../application/verification_service.go | 16 +++++++++++++++- email-verification/config/config.go | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/email-verification/application/verification_service.go b/email-verification/application/verification_service.go index c89ecbb46a..2c1a789c18 100644 --- a/email-verification/application/verification_service.go +++ b/email-verification/application/verification_service.go @@ -29,6 +29,14 @@ func NewVerificationService( } func (s *VerificationService) SendVerification(email string) error { + if email == "" { + return fmt.Errorf("email cannot be empty") + } + + if _, err := s.repo.Get(email); err == nil { + return fmt.Errorf("verification already pending") + } + code, err := s.codeGen.Generate() if err != nil { return err @@ -47,6 +55,10 @@ func (s *VerificationService) SendVerification(email string) error { } func (s *VerificationService) VerifyCode(email, code string) error { + if email == "" || code == "" { + return fmt.Errorf("email and code cannot be empty") + } + verification, err := s.repo.Get(email) if err != nil { return err @@ -58,7 +70,9 @@ func (s *VerificationService) VerifyCode(email, code string) error { } if time.Now().After(verification.Exp) { - s.repo.Delete(email) + if err := s.repo.Delete(email); err != nil { + return fmt.Errorf("failed to delete expired code: %w", err) + } return fmt.Errorf("code expired") } diff --git a/email-verification/config/config.go b/email-verification/config/config.go index 624b17f29b..d9259f1611 100644 --- a/email-verification/config/config.go +++ b/email-verification/config/config.go @@ -16,8 +16,8 @@ func GetConfig() *Config { return &Config{ SMTPHost: "smtp.gmail.com", SMTPPort: 587, - SMTPUser: "your-email@gmail.com", - SMTPPassword: "your-app-password", + SMTPUser: "tahasfhga@gmail.com", + SMTPPassword: "bakkcmkakpfxwuef", CodeExpiration: time.Minute * 1, } } From 67eba520089d049f6524c2cf40e31122993ccdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sad=C4=B1k=20S=C3=BCnb=C3=BCl?= <109942759+SadikSunbul@users.noreply.github.com> Date: Fri, 7 Feb 2025 16:45:31 +0300 Subject: [PATCH 3/3] Update go.mod --- email-verification/go.mod | 3 --- email-verification/go.sum | 28 ---------------------------- 2 files changed, 31 deletions(-) diff --git a/email-verification/go.mod b/email-verification/go.mod index 516a296a72..106e5a1efc 100644 --- a/email-verification/go.mod +++ b/email-verification/go.mod @@ -9,10 +9,7 @@ require ( require ( github.com/andybalholm/brotli v1.1.0 // indirect - github.com/gofiber/fiber v1.14.6 // indirect - github.com/gofiber/utils v0.0.10 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/schema v1.1.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/email-verification/go.sum b/email-verification/go.sum index 917e23c559..1c6bbdda5e 100644 --- a/email-verification/go.sum +++ b/email-verification/go.sum @@ -1,27 +1,13 @@ -github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4= -github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -github.com/gofiber/fiber v1.14.6 h1:QRUPvPmr8ijQuGo1MgupHBn8E+wW0IKqiOvIZPtV70o= -github.com/gofiber/fiber v1.14.6/go.mod h1:Yw2ekF1YDPreO9V6TMYjynu94xRxZBdaa8X5HhHsjCM= github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI= github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= -github.com/gofiber/utils v0.0.10 h1:3Mr7X7JdCUo7CWf/i5sajSaDmArEDtti8bM1JUVso2U= -github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= -github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= -github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg= -github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -31,27 +17,13 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.16.0 h1:9zAqOYLl8Tuy3E5R6ckzGDJ1g8+pw15oQp2iL9Jl6gQ= -github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=