package native import ( "context" "testing" "git.sendico.io/tech/sxchnge/bff/pkg/auth/internal/native/nstructures" "git.sendico.io/tech/sxchnge/bff/pkg/model" "github.com/stretchr/testify/require" "go.mongodb.org/mongo-driver/v2/bson" ) func TestEnforcer_EnforceHonorsObjectScope(t *testing.T) { ctx := context.Background() accountRef := bson.NewObjectID() organizationRef := bson.NewObjectID() permissionRef := bson.NewObjectID() roleRef := bson.NewObjectID() objectA := bson.NewObjectID() objectB := bson.NewObjectID() wildcard := bson.NilObjectID tests := []struct { name string policies []nstructures.PolicyAssignment objectRef bson.ObjectID wantAccess bool }{ { name: "matching object allow", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, &objectA), }, objectRef: objectA, wantAccess: true, }, { name: "different object does not inherit allow", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, &objectA), }, objectRef: objectB, wantAccess: false, }, { name: "nil object is wildcard", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, nil), }, objectRef: objectB, wantAccess: true, }, { name: "zero object is wildcard", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, &wildcard), }, objectRef: objectB, wantAccess: true, }, { name: "unrelated object deny does not override wildcard allow", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, nil), createTestPolicyAssignment(roleRef, model.EffectDeny, organizationRef, permissionRef, &objectA), }, objectRef: objectB, wantAccess: true, }, { name: "matching object deny overrides wildcard allow", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, nil), createTestPolicyAssignment(roleRef, model.EffectDeny, organizationRef, permissionRef, &objectA), }, objectRef: objectA, wantAccess: false, }, { name: "wildcard deny overrides matching object allow", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, &objectA), createTestPolicyAssignment(roleRef, model.EffectDeny, organizationRef, permissionRef, nil), }, objectRef: objectA, wantAccess: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { roles := &MockRolesDB{} policies := &MockPoliciesDB{} role := createTestRoleAssignment(roleRef, accountRef, organizationRef) roles.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{role}, nil) policies.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return(test.policies, nil) allowed, err := createTestEnforcer(policies, roles).Enforce( ctx, permissionRef, accountRef, organizationRef, test.objectRef, model.ActionRead, ) require.NoError(t, err) require.Equal(t, test.wantAccess, allowed) roles.AssertExpectations(t) policies.AssertExpectations(t) }) } } func TestEnforcer_EnforceBatchHonorsObjectScope(t *testing.T) { ctx := context.Background() accountRef := bson.NewObjectID() organizationRef := bson.NewObjectID() permissionRef := bson.NewObjectID() roleRef := bson.NewObjectID() objectA := &MockPermissionBoundStorable{ id: bson.NewObjectID(), permissionRef: permissionRef, organizationRef: organizationRef, } objectB := &MockPermissionBoundStorable{ id: bson.NewObjectID(), permissionRef: permissionRef, organizationRef: organizationRef, } tests := []struct { name string policies []nstructures.PolicyAssignment want map[bson.ObjectID]bool }{ { name: "specific allow applies only to matching object", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, &objectA.id), }, want: map[bson.ObjectID]bool{objectA.id: true, objectB.id: false}, }, { name: "specific deny affects only matching object", policies: []nstructures.PolicyAssignment{ createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, nil), createTestPolicyAssignment(roleRef, model.EffectDeny, organizationRef, permissionRef, &objectA.id), }, want: map[bson.ObjectID]bool{objectA.id: false, objectB.id: true}, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { roles := &MockRolesDB{} policies := &MockPoliciesDB{} role := createTestRoleAssignment(roleRef, accountRef, organizationRef) roles.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{role}, nil) policies.On("PoliciesForRoles", ctx, []bson.ObjectID{roleRef}, model.ActionRead).Return(test.policies, nil) result, err := createTestEnforcer(policies, roles).EnforceBatch( ctx, []model.PermissionBoundStorable{objectA, objectB}, accountRef, model.ActionRead, ) require.NoError(t, err) require.Equal(t, test.want, result) roles.AssertExpectations(t) policies.AssertExpectations(t) }) } }