added another test

This commit is contained in:
2026-01-27 09:21:22 +08:00
parent 6f64cb9766
commit 0f5ca8ee34
+272
View File
@@ -2,6 +2,7 @@ package services
import ( import (
"authorization/models" "authorization/models"
"strings"
"testing" "testing"
) )
@@ -687,3 +688,274 @@ func TestResolveVariablesAllAttributeTypes(t *testing.T) {
} }
} }
} }
func TestEvaluatePolicies_UserRegionMatchesResourceRegion(t *testing.T) {
// Test case from the logs: user.region = ${resource.region}
// User region should match the resource region provided in ResourceData
tests := []struct {
name string
userRegion string
resourceRegion string
shouldBeAllowed bool
description string
}{
{
name: "same region",
userRegion: "01",
resourceRegion: "01",
shouldBeAllowed: true,
description: "user region matches resource region",
},
{
name: "different region",
userRegion: "02",
resourceRegion: "01",
shouldBeAllowed: false,
description: "user region does not match resource region",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := &models.AuthorizationContext{
UserID: "U0000000001",
Resource: "personnel",
Action: "assign_role",
UserAttributes: map[string]string{
"region": tt.userRegion,
},
ResourceData: map[string]string{
"region": tt.resourceRegion,
},
}
policies := []models.PolicyAttribute{
{
AttributeType: "user",
AttributeName: "region",
Comparison: "=",
AttributeValue: "${resource.region}",
},
}
satisfied, reason := EvaluatePolicies(policies, ctx)
if satisfied != tt.shouldBeAllowed {
t.Errorf("%s: got satisfied=%v, want %v. Reason: %s", tt.description, satisfied, tt.shouldBeAllowed, reason)
}
})
}
}
func TestEvaluatePolicies_MissingResourceAttribute(t *testing.T) {
// Test case: when ResourceData doesn't have the required attribute
// The policy should fail because the placeholder cannot be resolved
ctx := &models.AuthorizationContext{
UserID: "U0000000001",
Resource: "personnel",
Action: "assign_role",
UserAttributes: map[string]string{
"region": "01",
},
ResourceData: map[string]string{
// Missing "region" key - this should cause policy to fail
},
}
policies := []models.PolicyAttribute{
{
AttributeType: "user",
AttributeName: "region",
Comparison: "=",
AttributeValue: "${resource.region}",
},
}
satisfied, reason := EvaluatePolicies(policies, ctx)
// When resource attribute is missing, the placeholder stays unresolved
// "01" != "${resource.region}", so policy fails
if satisfied {
t.Errorf("EvaluatePolicies should fail when resource attribute is missing. Reason: %s", reason)
}
if reason == "" {
t.Error("EvaluatePolicies should provide a reason when policy fails")
}
// Check that the error message indicates missing attributes
if !strings.Contains(reason, "Missing required attributes") || !strings.Contains(reason, "${resource.region}") {
t.Errorf("Expected error message about missing resource.region, got: %s", reason)
}
}
func TestHasUnresolvedPlaceholders(t *testing.T) {
tests := []struct {
name string
value string
expected bool
}{
{
name: "has unresolved placeholder",
value: "${resource.region}",
expected: true,
},
{
name: "multiple unresolved placeholders",
value: "${resource.region} and ${user.department}",
expected: true,
},
{
name: "no unresolved placeholders",
value: "US",
expected: false,
},
{
name: "mixed resolved and unresolved",
value: "US and ${resource.owner}",
expected: true,
},
{
name: "empty string",
value: "",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := hasUnresolvedPlaceholders(tt.value)
if result != tt.expected {
t.Errorf("hasUnresolvedPlaceholders(%q) = %v, want %v", tt.value, result, tt.expected)
}
})
}
}
func TestExtractUnresolvedPlaceholders(t *testing.T) {
tests := []struct {
name string
value string
expected []string
}{
{
name: "single placeholder",
value: "${resource.region}",
expected: []string{"${resource.region}"},
},
{
name: "multiple placeholders",
value: "${resource.region} and ${user.department}",
expected: []string{"${resource.region}", "${user.department}"},
},
{
name: "no placeholders",
value: "US",
expected: []string{},
},
{
name: "empty list when no matches",
value: "",
expected: []string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := extractUnresolvedPlaceholders(tt.value)
if len(result) != len(tt.expected) {
t.Errorf("extractUnresolvedPlaceholders(%q) returned %d items, want %d", tt.value, len(result), len(tt.expected))
}
for i, expected := range tt.expected {
if i >= len(result) || result[i] != expected {
t.Errorf("extractUnresolvedPlaceholders(%q)[%d] = %q, want %q", tt.value, i, result[i], expected)
}
}
})
}
}
func TestEvaluatePolicies_RegionBypassForAdminRoles(t *testing.T) {
// Test that region policies are skipped for roleID 1 (Super Admin) and 2 (Admin)
tests := []struct {
name string
roleID string
userRegion string
resourceRegion string
shouldBeAllowed bool
description string
}{
{
name: "roleID 1 bypasses region check",
roleID: "1",
userRegion: "02",
resourceRegion: "01",
shouldBeAllowed: true,
description: "Super Admin should bypass region check",
},
{
name: "roleID 2 bypasses region check",
roleID: "2",
userRegion: "03",
resourceRegion: "01",
shouldBeAllowed: true,
description: "Admin should bypass region check",
},
{
name: "other roleID respects region check",
roleID: "3",
userRegion: "02",
resourceRegion: "01",
shouldBeAllowed: false,
description: "Non-admin roles should not bypass region check",
},
{
name: "Super Admin role bypasses region check",
roleID: "Super Admin",
userRegion: "02",
resourceRegion: "01",
shouldBeAllowed: true,
description: "Super Admin role string should bypass region check",
},
{
name: "Admin role bypasses region check",
roleID: "Admin",
userRegion: "03",
resourceRegion: "01",
shouldBeAllowed: true,
description: "Admin role string should bypass region check",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := &models.AuthorizationContext{
UserID: "U0000000001",
Resource: "personnel",
Action: "assign_role",
RoleID: tt.roleID,
UserAttributes: map[string]string{
"region": tt.userRegion,
},
ResourceData: map[string]string{
"region": tt.resourceRegion,
},
}
policies := []models.PolicyAttribute{
{
AttributeType: "user",
AttributeName: "region",
Comparison: "=",
AttributeValue: "${resource.region}",
},
}
satisfied, reason := EvaluatePolicies(policies, ctx)
if satisfied != tt.shouldBeAllowed {
t.Errorf("%s: got satisfied=%v, want %v. Reason: %s", tt.description, satisfied, tt.shouldBeAllowed, reason)
}
})
}
}