fetch_ml/internal/auth/api_key_test.go
Jeremie Fraeys 803677be57 feat: implement Go backend with comprehensive API and internal packages
- Add API server with WebSocket support and REST endpoints
- Implement authentication system with API keys and permissions
- Add task queue system with Redis backend and error handling
- Include storage layer with database migrations and schemas
- Add comprehensive logging, metrics, and telemetry
- Implement security middleware and network utilities
- Add experiment management and container orchestration
- Include configuration management with smart defaults
2025-12-04 16:53:53 -05:00

229 lines
4.4 KiB
Go

package auth
import (
"testing"
)
func TestHashAPIKey(t *testing.T) {
tests := []struct {
name string
key string
expected string
}{
{
name: "known hash",
key: "password",
expected: "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8",
},
{
name: "another known hash",
key: "test",
expected: "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := HashAPIKey(tt.key)
if got != tt.expected {
t.Errorf("HashAPIKey() = %v, want %v", got, tt.expected)
}
})
}
}
func TestHashAPIKeyConsistency(t *testing.T) {
key := "my-secret-key"
hash1 := HashAPIKey(key)
hash2 := HashAPIKey(key)
if hash1 != hash2 {
t.Errorf("HashAPIKey() not consistent: %v != %v", hash1, hash2)
}
if len(hash1) != 64 {
t.Errorf("HashAPIKey() wrong length: got %d, want 64", len(hash1))
}
}
func TestGenerateAPIKey(t *testing.T) {
// Test that it generates keys
key1 := GenerateAPIKey()
if len(key1) != 64 {
t.Errorf("GenerateAPIKey() length = %d, want 64", len(key1))
}
// Test uniqueness (timing-based, should be different)
key2 := GenerateAPIKey()
if key1 == key2 {
t.Errorf("GenerateAPIKey() not unique: both generated %s", key1)
}
}
func TestUserHasPermission(t *testing.T) {
tests := []struct {
name string
user *User
permission string
want bool
}{
{
name: "wildcard grants all",
user: &User{
Permissions: map[string]bool{"*": true},
},
permission: "anything",
want: true,
},
{
name: "direct permission",
user: &User{
Permissions: map[string]bool{"jobs:create": true},
},
permission: "jobs:create",
want: true,
},
{
name: "hierarchical permission match",
user: &User{
Permissions: map[string]bool{"jobs": true},
},
permission: "jobs:create",
want: true,
},
{
name: "no permission",
user: &User{
Permissions: map[string]bool{"jobs:read": true},
},
permission: "jobs:create",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.user.HasPermission(tt.permission)
if got != tt.want {
t.Errorf("HasPermission() = %v, want %v", got, tt.want)
}
})
}
}
func TestUserHasRole(t *testing.T) {
tests := []struct {
name string
user *User
role string
want bool
}{
{
name: "has role",
user: &User{
Roles: []string{"admin", "user"},
},
role: "admin",
want: true,
},
{
name: "does not have role",
user: &User{
Roles: []string{"user"},
},
role: "admin",
want: false,
},
{
name: "empty roles",
user: &User{
Roles: []string{},
},
role: "admin",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.user.HasRole(tt.role)
if got != tt.want {
t.Errorf("HasRole() = %v, want %v", got, tt.want)
}
})
}
}
func TestAuthConfigValidateAPIKey(t *testing.T) {
config := &AuthConfig{
Enabled: true,
APIKeys: map[Username]APIKeyEntry{
"testuser": {
Hash: APIKeyHash(HashAPIKey("test-key")),
Admin: false,
Roles: []string{"user"},
Permissions: map[string]bool{
"jobs:read": true,
},
},
"admin": {
Hash: APIKeyHash(HashAPIKey("admin-key")),
Admin: true,
},
},
}
tests := []struct {
name string
key string
wantErr bool
wantAdmin bool
}{
{
name: "valid user key",
key: "test-key",
wantErr: false,
wantAdmin: false,
},
{
name: "valid admin key",
key: "admin-key",
wantErr: false,
wantAdmin: true,
},
{
name: "invalid key",
key: "wrong-key",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
user, err := config.ValidateAPIKey(tt.key)
if (err != nil) != tt.wantErr {
t.Errorf("ValidateAPIKey() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && user.Admin != tt.wantAdmin {
t.Errorf("ValidateAPIKey() admin = %v, want %v", user.Admin, tt.wantAdmin)
}
})
}
}
func TestAuthConfigDisabled(t *testing.T) {
config := &AuthConfig{
Enabled: false,
}
user, err := config.ValidateAPIKey("any-key")
if err != nil {
t.Errorf("ValidateAPIKey() with auth disabled should not error: %v", err)
}
if !user.Admin {
t.Error("ValidateAPIKey() with auth disabled should return admin user")
}
}