✨ merge: implement JWT secret rotation with BDD scenario isolation - Implement JWT secret rotation mechanism (closes #8) - Add per-scenario state isolation for BDD tests (closes #14) - Validate password reset workflow via BDD tests (closes #7) - Fix port conflicts in test validation - Add state tracer for debugging test execution - Document BDD isolation strategies in ADR 0025 - Fix PostgreSQL configuration environment variables Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai> Co-authored-by: Gabriel Radureau <arcodange@gmail.com> Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
package user
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestJWTSecretManager(t *testing.T) {
|
|
// Create a new secret manager with initial secret
|
|
manager := NewJWTSecretManager("primary-secret")
|
|
|
|
// Test initial state
|
|
assert.Equal(t, "primary-secret", manager.GetPrimarySecret())
|
|
|
|
// Test GetAllValidSecrets initially
|
|
secrets := manager.GetAllValidSecrets()
|
|
assert.Len(t, secrets, 1)
|
|
assert.Equal(t, "primary-secret", secrets[0].Secret)
|
|
assert.True(t, secrets[0].IsPrimary)
|
|
assert.Nil(t, secrets[0].ExpiresAt)
|
|
|
|
// Add a secondary secret
|
|
manager.AddSecret("secondary-secret", false, 0) // 0 means no expiration
|
|
|
|
// Test after adding secondary secret
|
|
assert.Equal(t, "primary-secret", manager.GetPrimarySecret()) // Primary should not change
|
|
|
|
secrets = manager.GetAllValidSecrets()
|
|
assert.Len(t, secrets, 2)
|
|
|
|
// Find the secondary secret
|
|
foundSecondary := false
|
|
for _, secret := range secrets {
|
|
if secret.Secret == "secondary-secret" {
|
|
foundSecondary = true
|
|
assert.False(t, secret.IsPrimary)
|
|
assert.Nil(t, secret.ExpiresAt) // Should have no expiration
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, foundSecondary, "Secondary secret should be found in valid secrets")
|
|
|
|
// Test rotation
|
|
manager.RotateToSecret("new-primary-secret")
|
|
assert.Equal(t, "new-primary-secret", manager.GetPrimarySecret())
|
|
|
|
secrets = manager.GetAllValidSecrets()
|
|
assert.Len(t, secrets, 3) // Should have 3 secrets now
|
|
|
|
// Find the new primary secret
|
|
foundNewPrimary := false
|
|
for _, secret := range secrets {
|
|
if secret.Secret == "new-primary-secret" {
|
|
foundNewPrimary = true
|
|
assert.True(t, secret.IsPrimary)
|
|
assert.Nil(t, secret.ExpiresAt) // Should have no expiration
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, foundNewPrimary, "New primary secret should be found in valid secrets")
|
|
}
|
|
|
|
func TestJWTSecretExpiration(t *testing.T) {
|
|
manager := NewJWTSecretManager("primary-secret")
|
|
|
|
// Add a secret with expiration
|
|
manager.AddSecret("expiring-secret", false, 1*time.Hour) // Expires in 1 hour
|
|
|
|
// Should have 2 secrets initially
|
|
secrets := manager.GetAllValidSecrets()
|
|
assert.Len(t, secrets, 2)
|
|
|
|
// Test expiration logic
|
|
foundExpiring := false
|
|
for _, secret := range secrets {
|
|
if secret.Secret == "expiring-secret" {
|
|
foundExpiring = true
|
|
assert.NotNil(t, secret.ExpiresAt)
|
|
assert.True(t, secret.ExpiresAt.After(time.Now()))
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, foundExpiring)
|
|
}
|