Improve email verification flow and error handling
- Send verification email before creating user to prevent orphaned accounts - Detect SMTP authentication errors and fail fast without retries - Add field-level validation errors for better frontend UX - Configure docker-compose with explicit environment variables - Document dollar sign escaping in .env.example (use $$) - Implement welcome email on successful verification - Clean up unnecessary comments
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type PasswordResetToken struct {
|
||||
ID string
|
||||
UserID string
|
||||
Token string
|
||||
ExpiresAt time.Time
|
||||
UsedAt *time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func NewPasswordResetToken(userID, token string, expiresAt time.Time) *PasswordResetToken {
|
||||
return &PasswordResetToken{
|
||||
ID: uuid.NewString(),
|
||||
UserID: userID,
|
||||
Token: token,
|
||||
ExpiresAt: expiresAt,
|
||||
UsedAt: nil,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *PasswordResetToken) IsExpired() bool {
|
||||
return time.Now().After(t.ExpiresAt)
|
||||
}
|
||||
|
||||
func (t *PasswordResetToken) IsUsed() bool {
|
||||
return t.UsedAt != nil
|
||||
}
|
||||
|
||||
func (t *PasswordResetToken) MarkAsUsed() {
|
||||
now := time.Now()
|
||||
t.UsedAt = &now
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"apocapoc-api/internal/domain/entities"
|
||||
)
|
||||
|
||||
type PasswordResetTokenRepository interface {
|
||||
Create(ctx context.Context, token *entities.PasswordResetToken) error
|
||||
FindByToken(ctx context.Context, token string) (*entities.PasswordResetToken, error)
|
||||
Update(ctx context.Context, token *entities.PasswordResetToken) error
|
||||
DeleteExpired(ctx context.Context) error
|
||||
}
|
||||
@@ -12,4 +12,5 @@ type UserRepository interface {
|
||||
FindByEmail(ctx context.Context, email string) (*entities.User, error)
|
||||
FindByVerificationToken(ctx context.Context, token string) (*entities.User, error)
|
||||
Update(ctx context.Context, user *entities.User) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user