Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
105
cloud/maplefile-backend/pkg/validation/email.go
Normal file
105
cloud/maplefile-backend/pkg/validation/email.go
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
// Package validation provides shared input validation utilities.
|
||||
package validation
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/mail"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ValidateEmail validates an email address using Go's standard mail package.
|
||||
// Returns an error message if the email is invalid, or an empty string if valid.
|
||||
// This provides consistent email validation across all services.
|
||||
func ValidateEmail(email string) string {
|
||||
email = strings.TrimSpace(email)
|
||||
if email == "" {
|
||||
return "Email address is required"
|
||||
}
|
||||
|
||||
// Use Go's mail package for proper RFC 5322 email validation
|
||||
if _, err := mail.ParseAddress(email); err != nil {
|
||||
return "Please enter a valid email address"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsValidEmail returns true if the email is valid, false otherwise.
|
||||
// This is a convenience wrapper around ValidateEmail for simple boolean checks.
|
||||
func IsValidEmail(email string) bool {
|
||||
return ValidateEmail(email) == ""
|
||||
}
|
||||
|
||||
// MaskEmail masks an email address for safe logging.
|
||||
// Example: "john.doe@example.com" becomes "jo***@example.com"
|
||||
// This prevents PII exposure in logs while still allowing identification.
|
||||
func MaskEmail(email string) string {
|
||||
email = strings.TrimSpace(email)
|
||||
if email == "" {
|
||||
return "***"
|
||||
}
|
||||
|
||||
parts := strings.Split(email, "@")
|
||||
if len(parts) != 2 {
|
||||
return "***"
|
||||
}
|
||||
|
||||
localPart := parts[0]
|
||||
domain := parts[1]
|
||||
|
||||
// Mask local part based on length
|
||||
var maskedLocal string
|
||||
switch {
|
||||
case len(localPart) <= 1:
|
||||
maskedLocal = "*"
|
||||
case len(localPart) <= 3:
|
||||
maskedLocal = localPart[:1] + "***"
|
||||
default:
|
||||
maskedLocal = localPart[:2] + "***"
|
||||
}
|
||||
|
||||
return maskedLocal + "@" + domain
|
||||
}
|
||||
|
||||
// MaskIP masks an IP address for safe logging.
|
||||
// IPv4 example: "192.168.1.100" becomes "192.168.1.***"
|
||||
// IPv6 example: "2001:db8::1" becomes "2001:db8::***"
|
||||
// This prevents PII exposure in logs while still allowing network identification.
|
||||
func MaskIP(ip string) string {
|
||||
ip = strings.TrimSpace(ip)
|
||||
if ip == "" {
|
||||
return "***"
|
||||
}
|
||||
|
||||
// Remove port if present (format: "IP:port" or "[IPv6]:port")
|
||||
host, _, err := net.SplitHostPort(ip)
|
||||
if err == nil {
|
||||
ip = host
|
||||
}
|
||||
|
||||
// Parse to determine if IPv4 or IPv6
|
||||
parsedIP := net.ParseIP(ip)
|
||||
if parsedIP == nil {
|
||||
return "***"
|
||||
}
|
||||
|
||||
// Check if IPv4
|
||||
if ipv4 := parsedIP.To4(); ipv4 != nil {
|
||||
// Mask last octet: 192.168.1.100 -> 192.168.1.***
|
||||
parts := strings.Split(ip, ".")
|
||||
if len(parts) == 4 {
|
||||
return parts[0] + "." + parts[1] + "." + parts[2] + ".***"
|
||||
}
|
||||
return "***"
|
||||
}
|
||||
|
||||
// IPv6: mask last segment
|
||||
// Example: 2001:db8:85a3::8a2e:370:7334 -> 2001:db8:85a3::8a2e:370:***
|
||||
parts := strings.Split(ip, ":")
|
||||
if len(parts) > 1 {
|
||||
parts[len(parts)-1] = "***"
|
||||
return strings.Join(parts, ":")
|
||||
}
|
||||
|
||||
return "***"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue