Compare commits
2 Commits
dcf054046f
...
02a764c736
| Author | SHA1 | Date | |
|---|---|---|---|
| 02a764c736 | |||
| 6834ad7764 |
@@ -1,12 +1,93 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
"goyco/internal/config"
|
||||
"goyco/internal/database"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTokenExpirationHours = 24
|
||||
verificationTokenBytes = 32
|
||||
deletionTokenExpirationHours = 24
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidCredentials = errors.New("invalid credentials")
|
||||
ErrInvalidToken = errors.New("invalid or expired token")
|
||||
ErrUsernameTaken = errors.New("username already exists")
|
||||
ErrEmailTaken = errors.New("email already exists")
|
||||
ErrInvalidEmail = errors.New("invalid email address")
|
||||
ErrPasswordTooShort = errors.New("password too short")
|
||||
ErrEmailNotVerified = errors.New("email not verified")
|
||||
ErrAccountLocked = errors.New("account is locked")
|
||||
ErrInvalidVerificationToken = errors.New("invalid verification token")
|
||||
ErrEmailSenderUnavailable = errors.New("email sender not configured")
|
||||
ErrDeletionEmailFailed = errors.New("account deletion email failed")
|
||||
ErrInvalidDeletionToken = errors.New("invalid account deletion token")
|
||||
ErrUserNotFound = errors.New("user not found")
|
||||
ErrDeletionRequestNotFound = errors.New("deletion request not found")
|
||||
)
|
||||
|
||||
type AuthResult struct {
|
||||
AccessToken string `json:"access_token" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."`
|
||||
RefreshToken string `json:"refresh_token" example:"a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"`
|
||||
User *database.User `json:"user"`
|
||||
}
|
||||
|
||||
type RegistrationResult struct {
|
||||
User *database.User `json:"user"`
|
||||
VerificationSent bool `json:"verification_sent"`
|
||||
}
|
||||
|
||||
func normalizeEmail(email string) (string, error) {
|
||||
trimmed := strings.TrimSpace(email)
|
||||
if trimmed == "" {
|
||||
return "", fmt.Errorf("email is required")
|
||||
}
|
||||
|
||||
parsed, err := mail.ParseAddress(trimmed)
|
||||
if err != nil {
|
||||
return "", ErrInvalidEmail
|
||||
}
|
||||
|
||||
return strings.ToLower(parsed.Address), nil
|
||||
}
|
||||
|
||||
func generateVerificationToken() (string, string, error) {
|
||||
buf := make([]byte, verificationTokenBytes)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
return "", "", fmt.Errorf("generate verification token: %w", err)
|
||||
}
|
||||
|
||||
token := hex.EncodeToString(buf)
|
||||
hashed := HashVerificationToken(token)
|
||||
return token, hashed, nil
|
||||
}
|
||||
|
||||
func HashVerificationToken(token string) string {
|
||||
sum := sha256.Sum256([]byte(token))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func sanitizeUser(user *database.User) *database.User {
|
||||
if user == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
copy := *user
|
||||
copy.Password = ""
|
||||
copy.EmailVerificationToken = ""
|
||||
return ©
|
||||
}
|
||||
|
||||
type AuthFacade struct {
|
||||
registrationService *RegistrationService
|
||||
passwordResetService *PasswordResetService
|
||||
@@ -1,35 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"goyco/internal/database"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidCredentials = errors.New("invalid credentials")
|
||||
ErrInvalidToken = errors.New("invalid or expired token")
|
||||
ErrUsernameTaken = errors.New("username already exists")
|
||||
ErrEmailTaken = errors.New("email already exists")
|
||||
ErrInvalidEmail = errors.New("invalid email address")
|
||||
ErrPasswordTooShort = errors.New("password too short")
|
||||
ErrEmailNotVerified = errors.New("email not verified")
|
||||
ErrAccountLocked = errors.New("account is locked")
|
||||
ErrInvalidVerificationToken = errors.New("invalid verification token")
|
||||
ErrEmailSenderUnavailable = errors.New("email sender not configured")
|
||||
ErrDeletionEmailFailed = errors.New("account deletion email failed")
|
||||
ErrInvalidDeletionToken = errors.New("invalid account deletion token")
|
||||
ErrUserNotFound = errors.New("user not found")
|
||||
ErrDeletionRequestNotFound = errors.New("deletion request not found")
|
||||
)
|
||||
|
||||
type AuthResult struct {
|
||||
AccessToken string `json:"access_token" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."`
|
||||
RefreshToken string `json:"refresh_token" example:"a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"`
|
||||
User *database.User `json:"user"`
|
||||
}
|
||||
|
||||
type RegistrationResult struct {
|
||||
User *database.User `json:"user"`
|
||||
VerificationSent bool `json:"verification_sent"`
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
"goyco/internal/database"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTokenExpirationHours = 24
|
||||
verificationTokenBytes = 32
|
||||
deletionTokenExpirationHours = 24
|
||||
)
|
||||
|
||||
func normalizeEmail(email string) (string, error) {
|
||||
trimmed := strings.TrimSpace(email)
|
||||
if trimmed == "" {
|
||||
return "", fmt.Errorf("email is required")
|
||||
}
|
||||
|
||||
parsed, err := mail.ParseAddress(trimmed)
|
||||
if err != nil {
|
||||
return "", ErrInvalidEmail
|
||||
}
|
||||
|
||||
return strings.ToLower(parsed.Address), nil
|
||||
}
|
||||
|
||||
func generateVerificationToken() (string, string, error) {
|
||||
buf := make([]byte, verificationTokenBytes)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
return "", "", fmt.Errorf("generate verification token: %w", err)
|
||||
}
|
||||
|
||||
token := hex.EncodeToString(buf)
|
||||
hashed := HashVerificationToken(token)
|
||||
return token, hashed, nil
|
||||
}
|
||||
|
||||
func HashVerificationToken(token string) string {
|
||||
sum := sha256.Sum256([]byte(token))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func sanitizeUser(user *database.User) *database.User {
|
||||
if user == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
copy := *user
|
||||
copy.Password = ""
|
||||
copy.EmailVerificationToken = ""
|
||||
return ©
|
||||
}
|
||||
Reference in New Issue
Block a user