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
345
cloud/maplepress-backend/pkg/logger/sanitizer_test.go
Normal file
345
cloud/maplepress-backend/pkg/logger/sanitizer_test.go
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRedactEmail(t *testing.T) {
|
||||
redactor := NewSensitiveFieldRedactor()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "normal email",
|
||||
input: "john.doe@example.com",
|
||||
expected: "jo***@example.com",
|
||||
},
|
||||
{
|
||||
name: "short local part",
|
||||
input: "ab@example.com",
|
||||
expected: "**@example.com",
|
||||
},
|
||||
{
|
||||
name: "single character local part",
|
||||
input: "a@example.com",
|
||||
expected: "**@example.com",
|
||||
},
|
||||
{
|
||||
name: "empty email",
|
||||
input: "",
|
||||
expected: "[empty]",
|
||||
},
|
||||
{
|
||||
name: "invalid email",
|
||||
input: "notanemail",
|
||||
expected: "[invalid-email]",
|
||||
},
|
||||
{
|
||||
name: "long email",
|
||||
input: "very.long.email.address@subdomain.example.com",
|
||||
expected: "ve***@subdomain.example.com",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := redactor.RedactEmail(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("RedactEmail(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashForLogging(t *testing.T) {
|
||||
redactor := NewSensitiveFieldRedactor()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
}{
|
||||
{
|
||||
name: "email",
|
||||
input: "john.doe@example.com",
|
||||
},
|
||||
{
|
||||
name: "tenant slug",
|
||||
input: "my-company",
|
||||
},
|
||||
{
|
||||
name: "another email",
|
||||
input: "jane.smith@test.com",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hash1 := redactor.HashForLogging(tt.input)
|
||||
hash2 := redactor.HashForLogging(tt.input)
|
||||
|
||||
// Hash should be consistent
|
||||
if hash1 != hash2 {
|
||||
t.Errorf("HashForLogging is not consistent: %q != %q", hash1, hash2)
|
||||
}
|
||||
|
||||
// Hash should be 16 characters (8 bytes in hex)
|
||||
if len(hash1) != 16 {
|
||||
t.Errorf("HashForLogging length = %d, want 16", len(hash1))
|
||||
}
|
||||
|
||||
// Hash should not contain original value
|
||||
if hash1 == tt.input {
|
||||
t.Errorf("HashForLogging returned original value")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Different inputs should produce different hashes
|
||||
hash1 := redactor.HashForLogging("john.doe@example.com")
|
||||
hash2 := redactor.HashForLogging("jane.smith@example.com")
|
||||
if hash1 == hash2 {
|
||||
t.Error("Different inputs produced same hash")
|
||||
}
|
||||
|
||||
// Empty string
|
||||
emptyHash := redactor.HashForLogging("")
|
||||
if emptyHash != "[empty]" {
|
||||
t.Errorf("HashForLogging(\"\") = %q, want [empty]", emptyHash)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedactTenantSlug(t *testing.T) {
|
||||
redactor := NewSensitiveFieldRedactor()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "normal slug",
|
||||
input: "my-company",
|
||||
expected: "my***",
|
||||
},
|
||||
{
|
||||
name: "short slug",
|
||||
input: "abc",
|
||||
expected: "***",
|
||||
},
|
||||
{
|
||||
name: "very short slug",
|
||||
input: "ab",
|
||||
expected: "***",
|
||||
},
|
||||
{
|
||||
name: "empty slug",
|
||||
input: "",
|
||||
expected: "[empty]",
|
||||
},
|
||||
{
|
||||
name: "long slug",
|
||||
input: "very-long-company-name",
|
||||
expected: "ve***",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := redactor.RedactTenantSlug(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("RedactTenantSlug(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedactAPIKey(t *testing.T) {
|
||||
redactor := NewSensitiveFieldRedactor()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "live API key",
|
||||
input: "live_sk_abc123def456ghi789",
|
||||
expected: "live_sk_***i789",
|
||||
},
|
||||
{
|
||||
name: "test API key",
|
||||
input: "test_sk_xyz789uvw456rst123",
|
||||
expected: "test_sk_***t123",
|
||||
},
|
||||
{
|
||||
name: "short live key",
|
||||
input: "live_sk_abc",
|
||||
expected: "live_sk_***",
|
||||
},
|
||||
{
|
||||
name: "other format",
|
||||
input: "sk_abc123def456",
|
||||
expected: "***f456",
|
||||
},
|
||||
{
|
||||
name: "very short key",
|
||||
input: "abc",
|
||||
expected: "***",
|
||||
},
|
||||
{
|
||||
name: "empty key",
|
||||
input: "",
|
||||
expected: "[empty]",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := redactor.RedactAPIKey(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("RedactAPIKey(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedactJWTToken(t *testing.T) {
|
||||
redactor := NewSensitiveFieldRedactor()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "normal JWT",
|
||||
input: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
|
||||
expected: "eyJhbGci...P0THsR8U",
|
||||
},
|
||||
{
|
||||
name: "short token",
|
||||
input: "short",
|
||||
expected: "***",
|
||||
},
|
||||
{
|
||||
name: "empty token",
|
||||
input: "",
|
||||
expected: "[empty]",
|
||||
},
|
||||
{
|
||||
name: "minimum length token",
|
||||
input: "1234567890123456",
|
||||
expected: "12345678...90123456",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := redactor.RedactJWTToken(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("RedactJWTToken(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedactIPAddress(t *testing.T) {
|
||||
redactor := NewSensitiveFieldRedactor()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "IPv4 address",
|
||||
input: "192.168.1.100",
|
||||
expected: "192.168.*.*",
|
||||
},
|
||||
{
|
||||
name: "IPv4 public",
|
||||
input: "8.8.8.8",
|
||||
expected: "8.8.*.*",
|
||||
},
|
||||
{
|
||||
name: "IPv6 address",
|
||||
input: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
|
||||
expected: "2001:0db8:85a3:0000:****",
|
||||
},
|
||||
{
|
||||
name: "IPv6 shortened",
|
||||
input: "2001:db8::1",
|
||||
expected: "2001:db8::1:****",
|
||||
},
|
||||
{
|
||||
name: "empty IP",
|
||||
input: "",
|
||||
expected: "[empty]",
|
||||
},
|
||||
{
|
||||
name: "invalid IP",
|
||||
input: "notanip",
|
||||
expected: "***",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := redactor.RedactIPAddress(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("RedactIPAddress(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserIdentifier(t *testing.T) {
|
||||
userID := "user_123"
|
||||
email := "john.doe@example.com"
|
||||
|
||||
fields := UserIdentifier(userID, email)
|
||||
|
||||
if len(fields) != 3 {
|
||||
t.Errorf("UserIdentifier returned %d fields, want 3", len(fields))
|
||||
}
|
||||
|
||||
// Check that fields contain expected keys
|
||||
fieldKeys := make(map[string]bool)
|
||||
for _, field := range fields {
|
||||
fieldKeys[field.Key] = true
|
||||
}
|
||||
|
||||
expectedKeys := []string{"user_id", "email_hash", "email_redacted"}
|
||||
for _, key := range expectedKeys {
|
||||
if !fieldKeys[key] {
|
||||
t.Errorf("UserIdentifier missing key: %s", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTenantIdentifier(t *testing.T) {
|
||||
tenantID := "tenant_123"
|
||||
slug := "my-company"
|
||||
|
||||
fields := TenantIdentifier(tenantID, slug)
|
||||
|
||||
if len(fields) != 3 {
|
||||
t.Errorf("TenantIdentifier returned %d fields, want 3", len(fields))
|
||||
}
|
||||
|
||||
// Check that fields contain expected keys
|
||||
fieldKeys := make(map[string]bool)
|
||||
for _, field := range fields {
|
||||
fieldKeys[field.Key] = true
|
||||
}
|
||||
|
||||
expectedKeys := []string{"tenant_id", "tenant_slug_hash", "tenant_slug_redacted"}
|
||||
for _, key := range expectedKeys {
|
||||
if !fieldKeys[key] {
|
||||
t.Errorf("TenantIdentifier missing key: %s", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue