refactor: split calendar source setup orchestration
This commit is contained in:
@@ -8,7 +8,18 @@ from sqlalchemy import create_engine, inspect
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from govoplan_access.backend.db import models as access_models # noqa: F401 - populate users/accounts tables
|
||||
from govoplan_calendar.backend.caldav import CalDAVClient, CalDAVError, CalDAVNotFound, CalDAVObject, CalDAVPreconditionFailed, CalDAVReportResult, CalDAVWriteResult, parse_multistatus
|
||||
from govoplan_calendar.backend.caldav import (
|
||||
CalDAVClient,
|
||||
CalDAVDiscoveryCalendar,
|
||||
CalDAVError,
|
||||
CalDAVNotFound,
|
||||
CalDAVObject,
|
||||
CalDAVPreconditionFailed,
|
||||
CalDAVReportResult,
|
||||
CalDAVWriteResult,
|
||||
parse_discovery_multistatus,
|
||||
parse_multistatus,
|
||||
)
|
||||
from govoplan_calendar.backend.db.models import CalendarEvent, CalendarOutboxOperation, CalendarSyncCredential
|
||||
from govoplan_calendar.backend.manifest import manifest
|
||||
from govoplan_calendar.backend.outbox import dispatch_calendar_outbox
|
||||
@@ -23,6 +34,10 @@ from govoplan_calendar.backend.schemas import (
|
||||
from govoplan_calendar.backend.service import (
|
||||
CALDAV_INTERNAL_CREDENTIAL_PREFIX,
|
||||
CalendarError,
|
||||
_CalDAVDiscoveryAuth,
|
||||
_caldav_discovery_client,
|
||||
_caldav_discovery_response,
|
||||
_plan_sync_source_creation,
|
||||
caldav_client_for_source,
|
||||
caldav_source_response,
|
||||
create_calendar,
|
||||
@@ -41,6 +56,7 @@ from govoplan_calendar.backend.service import (
|
||||
update_caldav_source,
|
||||
update_event,
|
||||
)
|
||||
from govoplan_calendar.backend.router import _caldav_discovery_http_error
|
||||
from govoplan_core.db.base import Base
|
||||
from govoplan_core.security.credential_envelopes import create_credential_envelope
|
||||
from govoplan_core.tenancy.scope import create_scope_tables
|
||||
@@ -108,6 +124,84 @@ class FakeNotificationProvider:
|
||||
|
||||
|
||||
class CalDAVParsingTests(unittest.TestCase):
|
||||
def test_discovery_parser_is_independent_from_transport(self) -> None:
|
||||
result = parse_discovery_multistatus(
|
||||
b"""<?xml version="1.0" encoding="utf-8"?>
|
||||
<D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||
<D:response>
|
||||
<D:href>/calendars/ada/work/</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:displayname>Work</D:displayname>
|
||||
<D:resourcetype><D:collection/><C:calendar/></D:resourcetype>
|
||||
<C:supported-calendar-component-set>
|
||||
<C:comp name="VEVENT"/>
|
||||
</C:supported-calendar-component-set>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
</D:multistatus>"""
|
||||
)
|
||||
|
||||
self.assertEqual(1, len(result))
|
||||
self.assertEqual("Work", result[0].display_name)
|
||||
self.assertTrue(result[0].is_calendar)
|
||||
self.assertEqual(("VEVENT",), result[0].supported_components)
|
||||
|
||||
def test_discovery_auth_client_and_response_do_not_expose_secret(self) -> None:
|
||||
auth = _CalDAVDiscoveryAuth(
|
||||
auth_type="basic",
|
||||
username="ada",
|
||||
credential_ref=None,
|
||||
secret="calendar-secret",
|
||||
)
|
||||
client = _caldav_discovery_client(
|
||||
"https://dav.example.test/cal",
|
||||
auth,
|
||||
)
|
||||
response = _caldav_discovery_response(
|
||||
(
|
||||
CalDAVDiscoveryCalendar(
|
||||
collection_url="https://dav.example.test/cal/work/",
|
||||
href="/cal/work/",
|
||||
display_name="Work",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
self.assertNotIn("calendar-secret", repr(auth))
|
||||
self.assertEqual("calendar-secret", client.password)
|
||||
self.assertEqual("Work", response[0]["display_name"])
|
||||
self.assertNotIn("password", response[0])
|
||||
self.assertNotIn("credential_ref", response[0])
|
||||
|
||||
def test_discovery_error_translation_is_stable(self) -> None:
|
||||
error = _caldav_discovery_http_error(
|
||||
CalDAVError("CalDAV endpoint rejected PROPFIND")
|
||||
)
|
||||
|
||||
self.assertEqual(422, error.status_code)
|
||||
self.assertEqual(
|
||||
"CalDAV endpoint rejected PROPFIND",
|
||||
error.detail,
|
||||
)
|
||||
|
||||
def test_sync_source_creation_plan_is_secret_free(self) -> None:
|
||||
plan = _plan_sync_source_creation(
|
||||
CalendarCalDavSourceCreateRequest(
|
||||
calendar_id="calendar-1",
|
||||
collection_url="dav.example.test/cal",
|
||||
auth_type="basic",
|
||||
username="ada",
|
||||
password="calendar-secret",
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual("https://dav.example.test/cal/", plan.collection_url)
|
||||
self.assertTrue(plan.has_inline_secret)
|
||||
self.assertNotIn("calendar-secret", repr(plan))
|
||||
|
||||
def test_parse_multistatus_extracts_objects_sync_token_and_deletions(self) -> None:
|
||||
result = parse_multistatus(
|
||||
b"""<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
Reference in New Issue
Block a user