Skip to content

feat: add email verification flow#27

Merged
osama1998H merged 1 commit into
masterfrom
feat/email-verification-flow
Mar 28, 2026
Merged

feat: add email verification flow#27
osama1998H merged 1 commit into
masterfrom
feat/email-verification-flow

Conversation

@osama1998H

@osama1998H osama1998H commented Mar 28, 2026

Copy link
Copy Markdown
Owner

Summary

Add a complete email verification flow: token generation, email delivery, confirmation endpoint, auto-send on registration, and a JWT-protected resend endpoint. Mirrors the existing password reset pattern for consistency.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Refactoring

Related issues

Closes #15

Changes

  • New migration 000004 creating email_verification_tokens table (mirrors password_reset_tokens)
  • New domain error ErrEmailAlreadyVerified and audit actions user.email_verification_requested, user.email_verified
  • New config VERIFY_EMAIL_TOKEN_DURATION (default 24h)
  • New repository email_verifications.go with token CRUD + VerifyUserEmail and GetUserByIDGlobal on users store
  • New SendEmailVerification method on EmailService
  • Three new methods on AuthService: RequestEmailVerification, ConfirmEmailVerification, and private requestEmailVerificationInternal
  • Register now auto-sends verification email (best-effort, never fails registration)
  • Two new endpoints: POST /api/v1/auth/email/verify-request (JWT) and POST /api/v1/auth/email/verify-confirm (public)
  • Error mapping for ErrEmailAlreadyVerified → 409 Conflict
  • Swagger types + regenerated API docs
  • Updated README (API table, config table, roadmap checkbox, feature list), .env.example, and CLAUDE.md

Testing

Describe how you tested these changes:

  • Unit tests added/updated (internal/service/auth_verify_test.go — 5 test cases covering cleanup on delivery failure, already-verified guard, token persistence, confirm flow, and invalid token)
  • Integration tests pass (go test ./...)
  • Manually tested with docker compose up — verified migration applies, all endpoints return correct status codes (200/400/401/409), email_verified_at populates on confirm, single-use token enforcement, audit logs recorded

Checklist

  • Code follows the existing patterns (repository → service → handler)
  • No new global state introduced
  • Error handling uses fmt.Errorf("context: %w", err) pattern
  • New endpoints are registered in internal/api/router.go
  • New config values have defaults set in internal/config/config.go

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Implemented email verification system with automated verification email delivery
    • Users can request email verification and confirm ownership using a secure token
    • Verification tokens automatically expire after 24 hours
  • Documentation

    • Updated API documentation with new email verification endpoints and configuration options

Add complete email verification with token-based confirmation,
auto-send on registration, and JWT-protected resend endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 28, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR implements email verification for user accounts and organization-scoped user creation. It introduces email verification endpoints (request and confirm), adds the email_verification_tokens database table, implements token generation and validation logic in the service layer, and adds a POST /api/v1/users endpoint for org-admin user creation with comprehensive Swagger documentation.

Changes

Cohort / File(s) Summary
Configuration & Environment
.env.example, internal/config/config.go
Added VERIFY_EMAIL_TOKEN_DURATION=24h environment variable alongside auth token settings and updated comments to reflect email verification impact.
Database Schema & Migrations
migrations/000004_email_verification_tokens.up.sql, migrations/000004_email_verification_tokens.down.sql, sql/schema.sql
Created new email_verification_tokens table with UUID PK, user FK, unique token hash, expiry/usage timestamps, and reversible migration rollback.
SQL Queries
sql/queries/email_verifications.sql, sql/queries/users.sql
Added five named queries for token CRUD and retrieval (unused/non-expired checks), plus GetUserByIDGlobal for org-agnostic user lookups.
Domain Layer
internal/domain/errors.go, internal/domain/audit.go
Added ErrEmailAlreadyVerified error and audit action constants user.email_verification_requested and user.email_verified.
Repository Layer
internal/repository/postgres/email_verifications.go, internal/repository/postgres/users.go
Implemented token CRUD operations (create, get by hash, mark used, delete) and added GetUserByIDGlobal and VerifyUserEmail methods.
Service Layer
internal/service/auth.go, internal/service/email.go
Added RequestEmailVerification and ConfirmEmailVerification methods with token generation, hashing, email delivery, and error-driven cleanup; added SendEmailVerification email sender.
API Handler Layer
internal/api/handlers/auth.go, internal/api/handlers/swagger_types.go, internal/api/handlers/response.go
Implemented two email verification HTTP handlers, added VerifyEmailConfirmBody Swagger type, and mapped ErrEmailAlreadyVerified to HTTP 409.
Routing
internal/api/router.go
Registered POST /api/v1/auth/email/verify-request and POST /api/v1/auth/email/verify-confirm routes.
API Documentation
docs/docs.go, docs/swagger.json, docs/swagger.yaml
Added Swagger path definitions and schema types for email verification endpoints and POST /api/v1/users user creation endpoint with CreateUserRequest type.
Project Documentation
README.md, CLAUDE.md
Documented email verification feature as completed, added configuration reference for token duration, and listed new API endpoints with auth requirements.
Tests
internal/service/auth_verify_test.go
Added comprehensive unit tests covering email delivery failures with token cleanup, already-verified users, successful token persistence, confirmation flow, and invalid token handling.

Sequence Diagram(s)

sequenceDiagram
    actor User as Authenticated User
    participant Handler as RequestEmailVerification<br/>Handler
    participant Service as AuthService
    participant EmailSvc as EmailService
    participant Store as PostgreSQL Store
    participant SMTP as SMTP Server

    User->>Handler: POST /api/v1/auth/email/verify-request<br/>(with JWT)
    activate Handler
    Handler->>Service: RequestEmailVerification(userID, orgID)
    activate Service
    
    Service->>Store: GetUser(orgID, userID)
    Store-->>Service: user data
    
    alt Email already verified
        Service-->>Handler: ErrEmailAlreadyVerified
        Handler-->>User: 409 Conflict
    else User active & email not verified
        Service->>Service: requestEmailVerificationInternal()
        activate Service
        Service->>Service: Generate raw token
        Service->>Service: Hash token
        Service->>Store: CreateEmailVerificationToken()
        Store-->>Service: token record created
        
        Service->>EmailSvc: SendEmailVerification(email, rawToken)
        activate EmailSvc
        EmailSvc->>SMTP: Send email with verification link
        SMTP-->>EmailSvc: success
        EmailSvc-->>Service: nil
        deactivate EmailSvc
        
        Service->>Store: AuditLog(email_verification_requested)
        Service-->>Service: return nil
        deactivate Service
        
        Service-->>Handler: nil (success)
    end
    
    Handler-->>User: 200 OK<br/>"verification email sent"
    deactivate Service
    deactivate Handler
Loading
sequenceDiagram
    actor User as User (Public)
    participant Handler as ConfirmEmailVerification<br/>Handler
    participant Service as AuthService
    participant Store as PostgreSQL Store
    participant Webhook as Webhook Dispatcher

    User->>Handler: POST /api/v1/auth/email/verify-confirm<br/>{token: "xyz..."}
    activate Handler
    
    Handler->>Service: ConfirmEmailVerification(rawToken)
    activate Service
    
    Service->>Service: Hash token
    Service->>Store: GetEmailVerificationToken(tokenHash)
    Store-->>Service: token record or nil
    
    alt No token found (invalid/expired)
        Service-->>Handler: ErrTokenInvalid
        Handler-->>User: 401 Unauthorized
    else Token found & valid
        Service->>Store: GetUserByIDGlobal(userID)
        Store-->>Service: user data
        
        Service->>Store: VerifyUserEmail(userID)
        Store-->>Service: user.email_verified_at updated
        
        Service->>Store: MarkEmailVerificationTokenUsed(tokenID)
        Store-->>Service: success
        
        Service->>Store: AuditLog(user.email_verified)
        Service->>Webhook: Dispatch webhook
        
        Service-->>Handler: nil (success)
        Handler-->>User: 200 OK<br/>"email verified successfully"
    end
    
    deactivate Service
    deactivate Handler
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • PR #23: Implements the same POST /api/v1/users endpoint with identical CreateUserRequest Swagger type and router wiring.
  • PR #14: Modifies internal/service/email.go for email delivery handling (SendEmailVerification and SMTP absent behavior).
  • PR #20: Modifies handleServiceError in internal/api/handlers/response.go for error-to-HTTP status mapping.

Suggested labels

size/XL


🐰 A token springs forth with cryptographic grace,
Email verified in each user's place,
Tokens hashed and safely stored,
New org users warmly restored—
UniAuth blooms in the digital space! 🌱✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements email verification flow per #15, but #15's primary objective is organization-scoped user creation. The PR adds POST /api/v1/users endpoint for user creation, but lacks role-based authorization checks and related permission framework required by #15. Implement role-based authorization on POST /api/v1/users, add checks for users:write permission, and document how the user creation respects delegated admin permissions as outlined in #15 Phase 3.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: add email verification flow' clearly and concisely describes the main feature being added, aligning with the changeset's primary objective.
Description check ✅ Passed The PR description comprehensively covers all required sections: summary, type of change, related issues, detailed changes, testing evidence, and a complete checklist—all well-aligned with repository conventions.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the email verification feature and organization-scoped user creation outlined in the PR objectives and linked issue #15. No extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/email-verification-flow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@osama1998H osama1998H merged commit 29ccec2 into master Mar 28, 2026
3 of 4 checks passed
@osama1998H osama1998H deleted the feat/email-verification-flow branch March 28, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add organization-scoped user creation and invitations

1 participant