package native import ( "context" "errors" "testing" "github.com/tech/sendico/pkg/auth/internal/native/nstructures" "github.com/tech/sendico/pkg/db/repository/builder" "github.com/tech/sendico/pkg/merrors" factory "github.com/tech/sendico/pkg/mlogger/factory" "github.com/tech/sendico/pkg/model" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "go.mongodb.org/mongo-driver/bson/primitive" ) // Mock implementations for testing type MockPoliciesDB struct { mock.Mock } func (m *MockPoliciesDB) PoliciesForPermissionAction(ctx context.Context, roleRef, permissionRef primitive.ObjectID, action model.Action) ([]nstructures.PolicyAssignment, error) { args := m.Called(ctx, roleRef, permissionRef, action) return args.Get(0).([]nstructures.PolicyAssignment), args.Error(1) } func (m *MockPoliciesDB) PoliciesForRole(ctx context.Context, roleRef primitive.ObjectID) ([]nstructures.PolicyAssignment, error) { args := m.Called(ctx, roleRef) return args.Get(0).([]nstructures.PolicyAssignment), args.Error(1) } func (m *MockPoliciesDB) PoliciesForRoles(ctx context.Context, roleRefs []primitive.ObjectID, action model.Action) ([]nstructures.PolicyAssignment, error) { args := m.Called(ctx, roleRefs, action) return args.Get(0).([]nstructures.PolicyAssignment), args.Error(1) } func (m *MockPoliciesDB) Policies(ctx context.Context, object model.PermissionBoundStorable, action model.Action) ([]nstructures.PolicyAssignment, error) { args := m.Called(ctx, object, action) return args.Get(0).([]nstructures.PolicyAssignment), args.Error(1) } func (m *MockPoliciesDB) Remove(ctx context.Context, policy *model.RolePolicy) error { args := m.Called(ctx, policy) return args.Error(0) } // Template DB methods - implement as needed for testing func (m *MockPoliciesDB) Create(ctx context.Context, assignment *nstructures.PolicyAssignment) error { args := m.Called(ctx, assignment) return args.Error(0) } func (m *MockPoliciesDB) Get(ctx context.Context, id primitive.ObjectID, assignment *nstructures.PolicyAssignment) error { args := m.Called(ctx, id, assignment) return args.Error(0) } func (m *MockPoliciesDB) Update(ctx context.Context, assignment *nstructures.PolicyAssignment) error { args := m.Called(ctx, assignment) return args.Error(0) } func (m *MockPoliciesDB) Patch(ctx context.Context, objectRef primitive.ObjectID, patch builder.Patch) error { args := m.Called(ctx, objectRef, patch) return args.Error(0) } func (m *MockPoliciesDB) Delete(ctx context.Context, id primitive.ObjectID) error { args := m.Called(ctx, id) return args.Error(0) } func (m *MockPoliciesDB) DeleteMany(ctx context.Context, query builder.Query) error { args := m.Called(ctx, query) return args.Error(0) } func (m *MockPoliciesDB) ListPermissionBound(ctx context.Context, accountRef, organizationRef primitive.ObjectID) ([]nstructures.PolicyAssignment, error) { args := m.Called(ctx, accountRef, organizationRef) return args.Get(0).([]nstructures.PolicyAssignment), args.Error(1) } func (m *MockPoliciesDB) ListIDs(ctx context.Context, query interface{}) ([]primitive.ObjectID, error) { args := m.Called(ctx, query) return args.Get(0).([]primitive.ObjectID), args.Error(1) } func (m *MockPoliciesDB) FindOne(ctx context.Context, query builder.Query, assignment *nstructures.PolicyAssignment) error { args := m.Called(ctx, query, assignment) return args.Error(0) } func (m *MockPoliciesDB) List(ctx context.Context, query builder.Query) ([]nstructures.PolicyAssignment, error) { args := m.Called(ctx, query) return args.Get(0).([]nstructures.PolicyAssignment), args.Error(1) } func (m *MockPoliciesDB) Name() string { return "mock_policies" } func (m *MockPoliciesDB) DeleteCascade(ctx context.Context, id primitive.ObjectID) error { args := m.Called(ctx, id) return args.Error(0) } func (m *MockPoliciesDB) InsertMany(ctx context.Context, objects []*nstructures.PolicyAssignment) error { args := m.Called(ctx, objects) return args.Error(0) } type MockRolesDB struct { mock.Mock } func (m *MockRolesDB) Roles(ctx context.Context, accountRef, organizationRef primitive.ObjectID) ([]nstructures.RoleAssignment, error) { args := m.Called(ctx, accountRef, organizationRef) return args.Get(0).([]nstructures.RoleAssignment), args.Error(1) } func (m *MockRolesDB) RolesForVenue(ctx context.Context, organizationRef primitive.ObjectID) ([]nstructures.RoleAssignment, error) { args := m.Called(ctx, organizationRef) return args.Get(0).([]nstructures.RoleAssignment), args.Error(1) } func (m *MockRolesDB) RemoveRole(ctx context.Context, roleRef, organizationRef, accountRef primitive.ObjectID) error { args := m.Called(ctx, roleRef, organizationRef, accountRef) return args.Error(0) } func (m *MockRolesDB) DeleteRole(ctx context.Context, roleRef primitive.ObjectID) error { args := m.Called(ctx, roleRef) return args.Error(0) } // Template DB methods - implement as needed for testing func (m *MockRolesDB) Create(ctx context.Context, assignment *nstructures.RoleAssignment) error { args := m.Called(ctx, assignment) return args.Error(0) } func (m *MockRolesDB) Get(ctx context.Context, id primitive.ObjectID, assignment *nstructures.RoleAssignment) error { args := m.Called(ctx, id, assignment) return args.Error(0) } func (m *MockRolesDB) Update(ctx context.Context, assignment *nstructures.RoleAssignment) error { args := m.Called(ctx, assignment) return args.Error(0) } func (m *MockRolesDB) Patch(ctx context.Context, objectRef primitive.ObjectID, patch builder.Patch) error { args := m.Called(ctx, objectRef, patch) return args.Error(0) } func (m *MockRolesDB) Delete(ctx context.Context, id primitive.ObjectID) error { args := m.Called(ctx, id) return args.Error(0) } func (m *MockRolesDB) DeleteMany(ctx context.Context, query builder.Query) error { args := m.Called(ctx, query) return args.Error(0) } func (m *MockRolesDB) ListPermissionBound(ctx context.Context, accountRef, organizationRef primitive.ObjectID) ([]nstructures.RoleAssignment, error) { args := m.Called(ctx, accountRef, organizationRef) return args.Get(0).([]nstructures.RoleAssignment), args.Error(1) } func (m *MockRolesDB) ListIDs(ctx context.Context, query interface{}) ([]primitive.ObjectID, error) { args := m.Called(ctx, query) return args.Get(0).([]primitive.ObjectID), args.Error(1) } func (m *MockRolesDB) FindOne(ctx context.Context, query builder.Query, assignment *nstructures.RoleAssignment) error { args := m.Called(ctx, query, assignment) return args.Error(0) } func (m *MockRolesDB) List(ctx context.Context, query builder.Query) ([]nstructures.RoleAssignment, error) { args := m.Called(ctx, query) return args.Get(0).([]nstructures.RoleAssignment), args.Error(1) } func (m *MockRolesDB) Name() string { return "mock_roles" } func (m *MockRolesDB) DeleteCascade(ctx context.Context, id primitive.ObjectID) error { args := m.Called(ctx, id) return args.Error(0) } func (m *MockRolesDB) InsertMany(ctx context.Context, objects []*nstructures.RoleAssignment) error { args := m.Called(ctx, objects) return args.Error(0) } // Test helper functions func createTestObjectID() primitive.ObjectID { return primitive.NewObjectID() } func createTestRoleAssignment(roleRef, accountRef, organizationRef primitive.ObjectID) nstructures.RoleAssignment { return nstructures.RoleAssignment{ Role: model.Role{ AccountRef: accountRef, DescriptionRef: roleRef, OrganizationRef: organizationRef, }, } } func createTestPolicyAssignment(roleRef primitive.ObjectID, action model.Action, effect model.Effect, organizationRef, descriptionRef primitive.ObjectID, objectRef *primitive.ObjectID) nstructures.PolicyAssignment { return nstructures.PolicyAssignment{ Policy: model.Policy{ OrganizationRef: organizationRef, DescriptionRef: descriptionRef, ObjectRef: objectRef, Effect: model.ActionEffect{ Action: action, Effect: effect, }, }, RoleRef: roleRef, } } func createTestEnforcer(pdb PoliciesDB, rdb RolesDB) *Enforcer { logger := factory.NewLogger(true) enforcer := &Enforcer{ logger: logger.Named("test"), pdb: pdb, rdb: rdb, } return enforcer } func TestEnforcer_Enforce(t *testing.T) { ctx := context.Background() // Test data accountRef := createTestObjectID() organizationRef := createTestObjectID() permissionRef := createTestObjectID() objectRef := createTestObjectID() roleRef := createTestObjectID() t.Run("Allow_SingleRole_SinglePolicy", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) // Mock policy assignment with ALLOW effect policyAssignment := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectAllow, organizationRef, permissionRef, &objectRef) mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{policyAssignment}, nil) // Create enforcer enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify require.NoError(t, err) assert.True(t, allowed) mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) t.Run("Deny_SingleRole_SinglePolicy", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) // Mock policy assignment with DENY effect policyAssignment := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectDeny, organizationRef, permissionRef, &objectRef) mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{policyAssignment}, nil) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify require.NoError(t, err) assert.False(t, allowed) mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) t.Run("DenyTakesPrecedence_MultipleRoles", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} role1Ref := createTestObjectID() role2Ref := createTestObjectID() // Mock multiple role assignments roleAssignment1 := createTestRoleAssignment(role1Ref, accountRef, organizationRef) roleAssignment2 := createTestRoleAssignment(role2Ref, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment1, roleAssignment2}, nil) // First role has ALLOW policy allowPolicy := createTestPolicyAssignment(role1Ref, model.ActionRead, model.EffectAllow, organizationRef, permissionRef, &objectRef) mockPDB.On("PoliciesForPermissionAction", ctx, role1Ref, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{allowPolicy}, nil) // Second role has DENY policy - should take precedence denyPolicy := createTestPolicyAssignment(role2Ref, model.ActionRead, model.EffectDeny, organizationRef, permissionRef, &objectRef) mockPDB.On("PoliciesForPermissionAction", ctx, role2Ref, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{denyPolicy}, nil) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify - DENY should take precedence require.NoError(t, err) assert.False(t, allowed) mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) t.Run("NoRoles_ReturnsFalse", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock no roles found mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{}, merrors.ErrNoData) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify require.NoError(t, err) assert.False(t, allowed) mockRDB.AssertExpectations(t) }) t.Run("EmptyRoles_ReturnsError", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock empty roles list (not NoData error) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{}, nil) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify require.Error(t, err) assert.False(t, allowed) assert.Contains(t, err.Error(), "No roles found for account") mockRDB.AssertExpectations(t) }) t.Run("DatabaseError_RolesDB", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock database error dbError := errors.New("database connection failed") mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{}, dbError) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify require.Error(t, err) assert.False(t, allowed) assert.Equal(t, dbError, err) mockRDB.AssertExpectations(t) }) t.Run("DatabaseError_PoliciesDB", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) // Mock database error in policies dbError := errors.New("policies database error") mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{}, dbError) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify require.Error(t, err) assert.False(t, allowed) assert.Equal(t, dbError, err) mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) t.Run("NoPolicies_ReturnsFalse", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) // Mock no policies found mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{}, merrors.ErrNoData) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify require.NoError(t, err) assert.False(t, allowed) mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) t.Run("CorruptedPolicy_ReturnsError", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) // Mock corrupted policy with invalid effect corruptedPolicy := createTestPolicyAssignment(roleRef, model.ActionRead, "invalid_effect", organizationRef, permissionRef, &objectRef) mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{corruptedPolicy}, nil) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify require.Error(t, err) assert.False(t, allowed) assert.Contains(t, err.Error(), "Corrupted action effect data") mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) } // Mock implementation for PermissionBoundStorable type MockPermissionBoundStorable struct { id primitive.ObjectID permissionRef primitive.ObjectID organizationRef primitive.ObjectID } func (m *MockPermissionBoundStorable) GetID() *primitive.ObjectID { return &m.id } func (m *MockPermissionBoundStorable) GetPermissionRef() primitive.ObjectID { return m.permissionRef } func (m *MockPermissionBoundStorable) GetOrganizationRef() primitive.ObjectID { return m.organizationRef } func (m *MockPermissionBoundStorable) Collection() string { return "test_objects" } func (m *MockPermissionBoundStorable) SetID(objID primitive.ObjectID) { m.id = objID } func (m *MockPermissionBoundStorable) Update() { // Do nothing for mock } func (m *MockPermissionBoundStorable) SetPermissionRef(permissionRef primitive.ObjectID) { m.permissionRef = permissionRef } func (m *MockPermissionBoundStorable) SetOrganizationRef(organizationRef primitive.ObjectID) { m.organizationRef = organizationRef } func (m *MockPermissionBoundStorable) IsArchived() bool { return false // Default to not archived for testing } func (m *MockPermissionBoundStorable) SetArchived(archived bool) { // No-op for testing } func TestEnforcer_EnforceBatch(t *testing.T) { ctx := context.Background() // Test data accountRef := createTestObjectID() organizationRef := createTestObjectID() permissionRef := createTestObjectID() roleRef := createTestObjectID() // Create test objects object1 := &MockPermissionBoundStorable{ id: createTestObjectID(), permissionRef: permissionRef, organizationRef: organizationRef, } object2 := &MockPermissionBoundStorable{ id: createTestObjectID(), permissionRef: permissionRef, organizationRef: organizationRef, } t.Run("BatchEnforce_MultipleObjects_SameVenue", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) // Mock policy assignment with ALLOW effect policyAssignment := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectAllow, organizationRef, permissionRef, nil) mockPDB.On("PoliciesForRoles", ctx, []primitive.ObjectID{roleRef}, model.ActionRead).Return([]nstructures.PolicyAssignment{policyAssignment}, nil) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute batch enforcement objects := []model.PermissionBoundStorable{object1, object2} results, err := enforcer.EnforceBatch(ctx, objects, accountRef, model.ActionRead) // Verify require.NoError(t, err) assert.Len(t, results, 2) assert.True(t, results[object1.id]) assert.True(t, results[object2.id]) mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) t.Run("BatchEnforce_NoRoles_AllObjectsDenied", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock no roles found mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{}, merrors.ErrNoData) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute batch enforcement objects := []model.PermissionBoundStorable{object1, object2} results, err := enforcer.EnforceBatch(ctx, objects, accountRef, model.ActionRead) // Verify require.NoError(t, err) assert.Len(t, results, 2) assert.False(t, results[object1.id]) assert.False(t, results[object2.id]) mockRDB.AssertExpectations(t) }) t.Run("BatchEnforce_DatabaseError", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock database error dbError := errors.New("database connection failed") mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{}, dbError) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute batch enforcement objects := []model.PermissionBoundStorable{object1, object2} results, err := enforcer.EnforceBatch(ctx, objects, accountRef, model.ActionRead) // Verify require.Error(t, err) assert.Nil(t, results) assert.Equal(t, dbError, err) mockRDB.AssertExpectations(t) }) } func TestEnforcer_GetRoles(t *testing.T) { ctx := context.Background() // Test data accountRef := createTestObjectID() organizationRef := createTestObjectID() roleRef := createTestObjectID() t.Run("GetRoles_Success", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute roles, err := enforcer.GetRoles(ctx, accountRef, organizationRef) // Verify require.NoError(t, err) assert.Len(t, roles, 1) assert.Equal(t, roleRef, roles[0].DescriptionRef) mockRDB.AssertExpectations(t) }) t.Run("GetRoles_NoRoles", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock no roles found mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{}, merrors.ErrNoData) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute roles, err := enforcer.GetRoles(ctx, accountRef, organizationRef) // Verify require.NoError(t, err) assert.Len(t, roles, 0) mockRDB.AssertExpectations(t) }) } func TestEnforcer_GetPermissions(t *testing.T) { ctx := context.Background() // Test data accountRef := createTestObjectID() organizationRef := createTestObjectID() roleRef := createTestObjectID() t.Run("GetPermissions_Success", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) // Mock policy assignment policyAssignment := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectAllow, organizationRef, createTestObjectID(), nil) mockPDB.On("PoliciesForRole", ctx, roleRef).Return([]nstructures.PolicyAssignment{policyAssignment}, nil) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute roles, permissions, err := enforcer.GetPermissions(ctx, accountRef, organizationRef) // Verify require.NoError(t, err) assert.Len(t, roles, 1) assert.Len(t, permissions, 1) assert.Equal(t, accountRef, permissions[0].AccountRef) mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) } // Security-focused test scenarios func TestEnforcer_SecurityScenarios(t *testing.T) { ctx := context.Background() // Test data accountRef := createTestObjectID() organizationRef := createTestObjectID() permissionRef := createTestObjectID() objectRef := createTestObjectID() roleRef := createTestObjectID() t.Run("Security_DenyAlwaysWins", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock role assignment roleAssignment := createTestRoleAssignment(roleRef, accountRef, organizationRef) mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil) // Mock multiple policies: both ALLOW and DENY allowPolicy := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectAllow, organizationRef, permissionRef, &objectRef) denyPolicy := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectDeny, organizationRef, permissionRef, &objectRef) mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{allowPolicy, denyPolicy}, nil) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify - DENY should always win require.NoError(t, err) assert.False(t, allowed) mockRDB.AssertExpectations(t) mockPDB.AssertExpectations(t) }) t.Run("Security_InvalidObjectID", func(t *testing.T) { mockPDB := &MockPoliciesDB{} mockRDB := &MockRolesDB{} // Mock database error for invalid ObjectID dbError := errors.New("invalid ObjectID") mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{}, dbError) enforcer := createTestEnforcer(mockPDB, mockRDB) // Execute with invalid ObjectID allowed, err := enforcer.Enforce(ctx, permissionRef, accountRef, organizationRef, objectRef, model.ActionRead) // Verify - should fail securely require.Error(t, err) assert.False(t, allowed) mockRDB.AssertExpectations(t) }) } // Note: This test provides comprehensive coverage of the native enforcer including: // 1. Basic enforcement logic with deny-takes-precedence // 2. Batch operations for performance // 3. Role and permission retrieval // 4. Security scenarios and edge cases // 5. Error handling and database failures // 6. All critical security paths are tested