Add server-backed file property filters

This commit is contained in:
2026-07-30 05:22:09 +02:00
parent 632cc6cf7d
commit 85606d5580
11 changed files with 483 additions and 13 deletions
+69 -2
View File
@@ -6,7 +6,7 @@ from pathlib import PurePosixPath
from typing import Any, Iterable
from uuid import uuid4
from sqlalchemy import and_, or_
from sqlalchemy import and_, exists, func, or_
from sqlalchemy.orm import Session
from govoplan_core.core.campaigns import CAPABILITY_CAMPAIGNS_ACCESS, CampaignAccessProvider
@@ -352,6 +352,8 @@ def list_assets_for_user(
owner_id: str | None = None,
campaign_id: str | None = None,
path_prefix: str | None = None,
campaign_usage: str | None = None,
audit_relevant: bool | None = None,
include_deleted: bool = False,
is_admin: bool = False,
) -> list[FileAsset]:
@@ -363,6 +365,8 @@ def list_assets_for_user(
owner_id=owner_id,
campaign_id=campaign_id,
path_prefix=path_prefix,
campaign_usage=campaign_usage,
audit_relevant=audit_relevant,
include_deleted=include_deleted,
is_admin=is_admin,
)
@@ -378,6 +382,8 @@ def list_assets_for_user_window(
owner_id: str | None = None,
campaign_id: str | None = None,
path_prefix: str | None = None,
campaign_usage: str | None = None,
audit_relevant: bool | None = None,
include_deleted: bool = False,
is_admin: bool = False,
page_size: int,
@@ -393,6 +399,8 @@ def list_assets_for_user_window(
owner_id=owner_id,
campaign_id=campaign_id,
path_prefix=path_prefix,
campaign_usage=campaign_usage,
audit_relevant=audit_relevant,
include_deleted=include_deleted,
is_admin=is_admin,
)
@@ -417,6 +425,8 @@ def _asset_visibility_query_for_user(
owner_id: str | None = None,
campaign_id: str | None = None,
path_prefix: str | None = None,
campaign_usage: str | None = None,
audit_relevant: bool | None = None,
include_deleted: bool = False,
is_admin: bool = False,
):
@@ -451,7 +461,64 @@ def _asset_visibility_query_for_user(
prefix = normalize_folder(path_prefix)
if prefix:
query = query.filter(FileAsset.display_path.like(f"{prefix}/%"))
return query
campaign_share_exists = exists().where(
FileShare.tenant_id == tenant_id,
FileShare.file_asset_id == FileAsset.id,
FileShare.target_type == "campaign",
FileShare.revoked_at.is_(None),
)
campaign_use_exists = exists().where(
CampaignAttachmentUse.tenant_id == tenant_id,
CampaignAttachmentUse.file_asset_id == FileAsset.id,
)
if campaign_usage == "linked":
query = query.filter(or_(campaign_share_exists, campaign_use_exists))
elif campaign_usage == "unlinked":
query = query.filter(~or_(campaign_share_exists, campaign_use_exists))
if audit_relevant is not None:
sent_use_exists = exists().where(
CampaignAttachmentUse.tenant_id == tenant_id,
CampaignAttachmentUse.file_asset_id == FileAsset.id,
CampaignAttachmentUse.use_stage == "sent",
)
query = query.filter(sent_use_exists if audit_relevant else ~sent_use_exists)
return query.distinct()
def count_assets_for_user(
session: Session,
*,
tenant_id: str,
user_id: str,
owner_type: str | None = None,
owner_id: str | None = None,
campaign_id: str | None = None,
path_prefix: str | None = None,
campaign_usage: str | None = None,
audit_relevant: bool | None = None,
include_deleted: bool = False,
is_admin: bool = False,
) -> int:
query = _asset_visibility_query_for_user(
session,
tenant_id=tenant_id,
user_id=user_id,
owner_type=owner_type,
owner_id=owner_id,
campaign_id=campaign_id,
path_prefix=path_prefix,
campaign_usage=campaign_usage,
audit_relevant=audit_relevant,
include_deleted=include_deleted,
is_admin=is_admin,
)
return int(
query.order_by(None)
.with_entities(func.count(func.distinct(FileAsset.id)))
.scalar()
or 0
)
def current_version_and_blob(session: Session, asset: FileAsset) -> tuple[FileVersion, FileBlob]: