- Add end-to-end tests for complete workflow validation - Include integration tests for API and database interactions - Add unit tests for all major components and utilities - Include performance tests for payload handling - Add CLI API integration tests - Include Podman container integration tests - Add WebSocket and queue execution tests - Include shell script tests for setup validation Provides comprehensive test coverage ensuring platform reliability and functionality across all components and interactions.
185 lines
4.1 KiB
Go
185 lines
4.1 KiB
Go
package auth
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/jfraeys/fetch_ml/internal/auth"
|
|
)
|
|
|
|
func TestGenerateAPIKey(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
key1 := auth.GenerateAPIKey()
|
|
|
|
if len(key1) != 64 { // 32 bytes = 64 hex chars
|
|
t.Errorf("Expected key length 64, got %d", len(key1))
|
|
}
|
|
|
|
// Test uniqueness
|
|
key2 := auth.GenerateAPIKey()
|
|
|
|
if key1 == key2 {
|
|
t.Error("Generated keys should be unique")
|
|
}
|
|
}
|
|
|
|
func TestHashAPIKey(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
key := "test-key-123"
|
|
hash := auth.HashAPIKey(key)
|
|
|
|
if len(hash) != 64 { // SHA256 = 64 hex chars
|
|
t.Errorf("Expected hash length 64, got %d", len(hash))
|
|
}
|
|
|
|
// Test consistency
|
|
hash2 := auth.HashAPIKey(key)
|
|
if hash != hash2 {
|
|
t.Error("Hash should be consistent for same key")
|
|
}
|
|
|
|
// Test different keys produce different hashes
|
|
hash3 := auth.HashAPIKey("different-key")
|
|
if hash == hash3 {
|
|
t.Error("Different keys should produce different hashes")
|
|
}
|
|
}
|
|
|
|
func TestValidateAPIKey(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
config := auth.AuthConfig{
|
|
Enabled: true,
|
|
APIKeys: map[auth.Username]auth.APIKeyEntry{
|
|
"admin": {
|
|
Hash: auth.APIKeyHash(auth.HashAPIKey("admin-key")),
|
|
Admin: true,
|
|
},
|
|
"data_scientist": {
|
|
Hash: auth.APIKeyHash(auth.HashAPIKey("ds-key")),
|
|
Admin: false,
|
|
},
|
|
},
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
apiKey string
|
|
wantErr bool
|
|
wantUser string
|
|
wantAdmin bool
|
|
}{
|
|
{
|
|
name: "valid admin key",
|
|
apiKey: "admin-key",
|
|
wantErr: false,
|
|
wantUser: "admin",
|
|
wantAdmin: true,
|
|
},
|
|
{
|
|
name: "valid user key",
|
|
apiKey: "ds-key",
|
|
wantErr: false,
|
|
wantUser: "data_scientist",
|
|
wantAdmin: false,
|
|
},
|
|
{
|
|
name: "invalid key",
|
|
apiKey: "wrong-key",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty key",
|
|
apiKey: "",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
user, err := config.ValidateAPIKey(tt.apiKey)
|
|
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Error("Expected error but got none")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if user.Name != tt.wantUser {
|
|
t.Errorf("Expected user %s, got %s", tt.wantUser, user.Name)
|
|
}
|
|
|
|
if user.Admin != tt.wantAdmin {
|
|
t.Errorf("Expected admin %v, got %v", tt.wantAdmin, user.Admin)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateAPIKeyAuthDisabled(t *testing.T) {
|
|
t.Setenv("FETCH_ML_ALLOW_INSECURE_AUTH", "1")
|
|
defer t.Setenv("FETCH_ML_ALLOW_INSECURE_AUTH", "")
|
|
|
|
config := auth.AuthConfig{
|
|
Enabled: false,
|
|
APIKeys: map[auth.Username]auth.APIKeyEntry{}, // Empty
|
|
}
|
|
|
|
user, err := config.ValidateAPIKey("any-key")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error when auth disabled: %v", err)
|
|
}
|
|
|
|
if user == nil {
|
|
t.Fatal("Expected user, got nil")
|
|
}
|
|
|
|
if user.Name != "default" {
|
|
t.Errorf("Expected default user, got %s", user.Name)
|
|
}
|
|
|
|
if !user.Admin {
|
|
t.Error("Default user should be admin")
|
|
}
|
|
}
|
|
|
|
func TestAdminDetection(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
config := auth.AuthConfig{
|
|
Enabled: true,
|
|
APIKeys: map[auth.Username]auth.APIKeyEntry{
|
|
"admin": {Hash: auth.APIKeyHash(auth.HashAPIKey("key1")), Admin: true},
|
|
"admin_user": {Hash: auth.APIKeyHash(auth.HashAPIKey("key2")), Admin: true},
|
|
"superadmin": {Hash: auth.APIKeyHash(auth.HashAPIKey("key3")), Admin: true},
|
|
"regular": {Hash: auth.APIKeyHash(auth.HashAPIKey("key4")), Admin: false},
|
|
"user_admin": {Hash: auth.APIKeyHash(auth.HashAPIKey("key5")), Admin: false},
|
|
},
|
|
}
|
|
|
|
tests := []struct {
|
|
apiKey string
|
|
expected bool
|
|
}{
|
|
{"key1", true}, // admin
|
|
{"key2", true}, // admin_user
|
|
{"key3", true}, // superadmin
|
|
{"key4", false}, // regular
|
|
{"key5", false}, // user_admin (not admin based on explicit flag)
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.apiKey, func(t *testing.T) {
|
|
user, err := config.ValidateAPIKey(tt.apiKey)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
if user.Admin != tt.expected {
|
|
t.Errorf("Expected admin=%v for key %s, got %v", tt.expected, tt.apiKey, user.Admin)
|
|
}
|
|
})
|
|
}
|
|
}
|