293 lines
9.4 KiB
Python
293 lines
9.4 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Literal
|
|
from sqlalchemy.orm import Session
|
|
|
|
from govoplan_core.auth import ApiPrincipal
|
|
from govoplan_core.api.v1.schemas import DeltaDeletedItem
|
|
from govoplan_core.core.change_sequence import (
|
|
ChangeSequenceEntry,
|
|
)
|
|
from govoplan_files.backend.change_tracking import (
|
|
FILES_CONNECTOR_CREDENTIALS_COLLECTION,
|
|
FILES_CONNECTOR_POLICIES_COLLECTION,
|
|
FILES_CONNECTOR_PROFILES_COLLECTION,
|
|
FILES_CONNECTOR_SPACES_COLLECTION,
|
|
)
|
|
from govoplan_files.backend.schemas import (
|
|
FileConnectorCredentialResponse,
|
|
FileConnectorSettingsDeltaResponse,
|
|
FileConnectorPolicyResponse,
|
|
FileConnectorProfileResponse,
|
|
)
|
|
from govoplan_files.backend.db.models import FileConnectorSpace
|
|
from govoplan_files.backend.storage.connector_credential_store import (
|
|
ConnectorCredential,
|
|
)
|
|
from govoplan_files.backend.storage.connector_profiles import ConnectorProfile
|
|
from govoplan_files.backend.storage.connector_policy_store import (
|
|
connector_policy_response,
|
|
)
|
|
|
|
|
|
from govoplan_files.backend.route_support import (
|
|
FILES_CONNECTOR_CREDENTIAL_RESOURCE,
|
|
FILES_CONNECTOR_PROFILE_RESOURCE,
|
|
FILES_CONNECTOR_SPACE_RESOURCE,
|
|
_can_read_disabled_connector_profiles,
|
|
_connector_deleted_item,
|
|
_connector_space_response,
|
|
_ensure_campaign_file_access,
|
|
_file_connector_settings_response_watermark,
|
|
_file_connector_settings_watermark,
|
|
_visible_connector_credentials,
|
|
_visible_connector_profiles,
|
|
_visible_connector_spaces,
|
|
)
|
|
|
|
|
|
def _full_file_connector_settings_delta_response(
|
|
session: Session,
|
|
principal: ApiPrincipal,
|
|
*,
|
|
scope_type: str,
|
|
scope_id: str | None,
|
|
provider: str | None,
|
|
campaign_id: str | None,
|
|
include_disabled: bool,
|
|
include_inactive: bool,
|
|
owner_type: Literal["user", "group"] | None,
|
|
owner_id: str | None,
|
|
) -> FileConnectorSettingsDeltaResponse:
|
|
if campaign_id:
|
|
_ensure_campaign_file_access(session, principal, campaign_id)
|
|
profiles = _visible_connector_profiles(
|
|
session,
|
|
principal,
|
|
provider=provider,
|
|
campaign_id=campaign_id,
|
|
include_disabled=include_disabled
|
|
and _can_read_disabled_connector_profiles(principal),
|
|
include_admin_scopes=_can_read_disabled_connector_profiles(principal),
|
|
include_effective_policy=False,
|
|
)
|
|
credentials = _visible_connector_credentials(
|
|
session,
|
|
principal,
|
|
provider=provider,
|
|
include_disabled=include_disabled,
|
|
)
|
|
spaces = _visible_connector_spaces(
|
|
session,
|
|
principal,
|
|
owner_type=owner_type,
|
|
owner_id=owner_id,
|
|
include_inactive=include_inactive,
|
|
)
|
|
return FileConnectorSettingsDeltaResponse(
|
|
profiles=[
|
|
FileConnectorProfileResponse(**profile.to_response())
|
|
for profile in profiles
|
|
],
|
|
credentials=[
|
|
FileConnectorCredentialResponse(**credential.to_response())
|
|
for credential in credentials
|
|
],
|
|
spaces=[_connector_space_response(space) for space in spaces],
|
|
policy=FileConnectorPolicyResponse(
|
|
**connector_policy_response(
|
|
session,
|
|
tenant_id=principal.tenant_id,
|
|
scope_type=scope_type,
|
|
scope_id=scope_id,
|
|
)
|
|
),
|
|
changed_sections=["profiles", "credentials", "spaces", "policy"],
|
|
deleted=[],
|
|
watermark=_file_connector_settings_watermark(
|
|
session, tenant_id=principal.tenant_id
|
|
),
|
|
has_more=False,
|
|
full=True,
|
|
)
|
|
|
|
|
|
def _changed_file_connector_setting_ids(
|
|
entries: list[ChangeSequenceEntry],
|
|
) -> tuple[set[str], set[str], set[str], bool]:
|
|
changed_profile_ids = {
|
|
entry.resource_id
|
|
for entry in entries
|
|
if entry.collection == FILES_CONNECTOR_PROFILES_COLLECTION
|
|
and entry.resource_type == FILES_CONNECTOR_PROFILE_RESOURCE
|
|
}
|
|
changed_credential_ids = {
|
|
entry.resource_id
|
|
for entry in entries
|
|
if entry.collection == FILES_CONNECTOR_CREDENTIALS_COLLECTION
|
|
and entry.resource_type == FILES_CONNECTOR_CREDENTIAL_RESOURCE
|
|
}
|
|
changed_space_ids = {
|
|
entry.resource_id
|
|
for entry in entries
|
|
if entry.collection == FILES_CONNECTOR_SPACES_COLLECTION
|
|
and entry.resource_type == FILES_CONNECTOR_SPACE_RESOURCE
|
|
}
|
|
policy_changed = any(
|
|
entry.collection == FILES_CONNECTOR_POLICIES_COLLECTION for entry in entries
|
|
)
|
|
return (
|
|
changed_profile_ids,
|
|
changed_credential_ids,
|
|
changed_space_ids,
|
|
policy_changed,
|
|
)
|
|
|
|
|
|
def _file_connector_settings_changed_sections(
|
|
*,
|
|
changed_profile_ids: set[str],
|
|
changed_credential_ids: set[str],
|
|
changed_space_ids: set[str],
|
|
policy_changed: bool,
|
|
profiles: list[ConnectorProfile],
|
|
) -> list[str]:
|
|
changed_sections = []
|
|
if changed_profile_ids or any(
|
|
profile.credential_profile_id
|
|
and profile.credential_profile_id in changed_credential_ids
|
|
for profile in profiles
|
|
):
|
|
changed_sections.append("profiles")
|
|
if changed_credential_ids:
|
|
changed_sections.append("credentials")
|
|
if changed_space_ids:
|
|
changed_sections.append("spaces")
|
|
if policy_changed:
|
|
changed_sections.append("policy")
|
|
return changed_sections
|
|
|
|
|
|
def _file_connector_settings_deleted_items(
|
|
entries: list[ChangeSequenceEntry],
|
|
*,
|
|
visible_profiles: dict[str, ConnectorProfile],
|
|
visible_credentials: dict[str, ConnectorCredential],
|
|
visible_spaces: dict[str, FileConnectorSpace],
|
|
) -> list[DeltaDeletedItem]:
|
|
return [
|
|
_connector_deleted_item(entry)
|
|
for entry in entries
|
|
if (
|
|
entry.resource_type == FILES_CONNECTOR_PROFILE_RESOURCE
|
|
and entry.resource_id not in visible_profiles
|
|
)
|
|
or (
|
|
entry.resource_type == FILES_CONNECTOR_CREDENTIAL_RESOURCE
|
|
and entry.resource_id not in visible_credentials
|
|
)
|
|
or (
|
|
entry.resource_type == FILES_CONNECTOR_SPACE_RESOURCE
|
|
and entry.resource_id not in visible_spaces
|
|
)
|
|
]
|
|
|
|
|
|
def _incremental_file_connector_settings_delta_response(
|
|
session: Session,
|
|
principal: ApiPrincipal,
|
|
*,
|
|
entries: list[ChangeSequenceEntry],
|
|
has_more: bool,
|
|
scope_type: str,
|
|
scope_id: str | None,
|
|
provider: str | None,
|
|
campaign_id: str | None,
|
|
include_disabled: bool,
|
|
include_inactive: bool,
|
|
owner_type: Literal["user", "group"] | None,
|
|
owner_id: str | None,
|
|
) -> FileConnectorSettingsDeltaResponse:
|
|
changed_profile_ids, changed_credential_ids, changed_space_ids, policy_changed = (
|
|
_changed_file_connector_setting_ids(entries)
|
|
)
|
|
profiles = _visible_connector_profiles(
|
|
session,
|
|
principal,
|
|
provider=provider,
|
|
campaign_id=campaign_id,
|
|
include_disabled=include_disabled
|
|
and _can_read_disabled_connector_profiles(principal),
|
|
include_admin_scopes=_can_read_disabled_connector_profiles(principal),
|
|
include_effective_policy=False,
|
|
)
|
|
visible_profiles = {
|
|
profile.id: profile
|
|
for profile in profiles
|
|
if profile.id in changed_profile_ids
|
|
or (
|
|
profile.credential_profile_id
|
|
and profile.credential_profile_id in changed_credential_ids
|
|
)
|
|
}
|
|
credentials = _visible_connector_credentials(
|
|
session,
|
|
principal,
|
|
provider=provider,
|
|
include_disabled=include_disabled,
|
|
)
|
|
visible_credentials = {
|
|
credential.id: credential
|
|
for credential in credentials
|
|
if credential.id in changed_credential_ids
|
|
}
|
|
spaces = _visible_connector_spaces(
|
|
session,
|
|
principal,
|
|
owner_type=owner_type,
|
|
owner_id=owner_id,
|
|
include_inactive=include_inactive,
|
|
)
|
|
visible_spaces = {
|
|
space.id: space for space in spaces if space.id in changed_space_ids
|
|
}
|
|
return FileConnectorSettingsDeltaResponse(
|
|
profiles=[
|
|
FileConnectorProfileResponse(**profile.to_response())
|
|
for profile in visible_profiles.values()
|
|
],
|
|
credentials=[
|
|
FileConnectorCredentialResponse(**credential.to_response())
|
|
for credential in visible_credentials.values()
|
|
],
|
|
spaces=[_connector_space_response(space) for space in visible_spaces.values()],
|
|
policy=FileConnectorPolicyResponse(
|
|
**connector_policy_response(
|
|
session,
|
|
tenant_id=principal.tenant_id,
|
|
scope_type=scope_type,
|
|
scope_id=scope_id,
|
|
)
|
|
)
|
|
if policy_changed
|
|
else None,
|
|
changed_sections=_file_connector_settings_changed_sections(
|
|
changed_profile_ids=changed_profile_ids,
|
|
changed_credential_ids=changed_credential_ids,
|
|
changed_space_ids=changed_space_ids,
|
|
policy_changed=policy_changed,
|
|
profiles=profiles,
|
|
),
|
|
deleted=_file_connector_settings_deleted_items(
|
|
entries,
|
|
visible_profiles=visible_profiles,
|
|
visible_credentials=visible_credentials,
|
|
visible_spaces=visible_spaces,
|
|
),
|
|
watermark=_file_connector_settings_response_watermark(
|
|
session, tenant_id=principal.tenant_id, entries=entries, has_more=has_more
|
|
),
|
|
has_more=has_more,
|
|
full=False,
|
|
)
|