From a0e6949ddb601a1565b908570d82acb19a7eb990 Mon Sep 17 00:00:00 2001 From: falscherwiener1-svg Date: Wed, 22 Jul 2026 16:13:27 +0200 Subject: [PATCH] fix(sharepoint): skip license error when access control sync is disabled (#4139) The scheduling loop logs an ERROR every ~30s when a connector supports DLS but the Elasticsearch license is not Platinum. This is misleading when the user has not enabled access control sync at all. Only check the license when access control sync scheduling is actually enabled by the user. If it's disabled, skip silently. --- .../connectors/services/job_scheduling.py | 5 +- .../tests/services/test_job_scheduling.py | 67 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/app/connectors_service/connectors/services/job_scheduling.py b/app/connectors_service/connectors/services/job_scheduling.py index 020e39197..0f9bba913 100644 --- a/app/connectors_service/connectors/services/job_scheduling.py +++ b/app/connectors_service/connectors/services/job_scheduling.py @@ -127,7 +127,10 @@ async def _schedule(self, connector): finally: await data_source.close() - if connector.features.document_level_security_enabled(): + if ( + connector.features.document_level_security_enabled() + and connector.access_control_sync_scheduling.get("enabled", False) + ): ( is_platinum_license_enabled, license_enabled, diff --git a/app/connectors_service/tests/services/test_job_scheduling.py b/app/connectors_service/tests/services/test_job_scheduling.py index 7aacf1f91..8571a8be9 100644 --- a/app/connectors_service/tests/services/test_job_scheduling.py +++ b/app/connectors_service/tests/services/test_job_scheduling.py @@ -88,6 +88,7 @@ def mock_connector( ) connector.validate_filtering = AsyncMock() connector.next_sync = Mock(return_value=next_sync) + connector.access_control_sync_scheduling = {"enabled": True} connector.close = AsyncMock() connector.prepare = AsyncMock(side_effect=prepare_exception) @@ -228,6 +229,39 @@ async def test_connector_scheduled_access_control_sync_with_insufficient_license assert sync_job_index_mock.create.await_count == 1 +@pytest.mark.asyncio +async def test_connector_scheduled_access_control_sync_with_sync_disabled( + connector_index_mock, + sync_job_index_mock, + set_env, +): + # DLS is supported (e.g. SharePoint Online) but the user has NOT enabled + # access control sync scheduling. Even on a non-Platinum license the + # license must not be checked and no error should be logged. (#4139) + connector = mock_connector(next_sync=datetime.now(timezone.utc)) + connector.access_control_sync_scheduling = {"enabled": False} + connector_index_mock.supported_connectors.return_value = AsyncIterator([connector]) + connector_index_mock.has_active_license_enabled = AsyncMock( + return_value=(False, License.BASIC) + ) + + await create_and_run_service(JobSchedulingService) + + connector.prepare.assert_awaited() + connector.heartbeat.assert_awaited() + + # license is not checked because access control sync scheduling is disabled + connector_index_mock.has_active_license_enabled.assert_not_awaited() + + # only a scheduled full sync is created + sync_job_index_mock.create.assert_any_await( + connector=connector, + trigger_method=JobTriggerMethod.SCHEDULED, + job_type=JobType.FULL, + ) + assert sync_job_index_mock.create.await_count == 1 + + @pytest.mark.asyncio @pytest.mark.parametrize( "incremental_sync_enabled, service_type, schedule_incremental_sync", @@ -274,6 +308,39 @@ async def test_connector_scheduled_incremental_sync( assert sync_job_index_mock.create.await_count == 1 +@pytest.mark.asyncio +async def test_connector_scheduled_access_control_sync_with_sync_disabled( + connector_index_mock, + sync_job_index_mock, + set_env, +): + # DLS is supported (e.g. SharePoint Online) but the user has NOT enabled + # access control sync scheduling. Even on a non-Platinum license the + # license must not be checked and no error should be logged. (#4139) + connector = mock_connector(next_sync=datetime.now(timezone.utc)) + connector.access_control_sync_scheduling = {"enabled": False} + connector_index_mock.supported_connectors.return_value = AsyncIterator([connector]) + connector_index_mock.has_active_license_enabled = AsyncMock( + return_value=(False, License.BASIC) + ) + + await create_and_run_service(JobSchedulingService) + + connector.prepare.assert_awaited() + connector.heartbeat.assert_awaited() + + # license is not checked because access control sync scheduling is disabled + connector_index_mock.has_active_license_enabled.assert_not_awaited() + + # only a scheduled full sync is created + sync_job_index_mock.create.assert_any_await( + connector=connector, + trigger_method=JobTriggerMethod.SCHEDULED, + job_type=JobType.FULL, + ) + assert sync_job_index_mock.create.await_count == 1 + + @pytest.mark.asyncio @pytest.mark.parametrize( "connector_status",