Release v0.1.5
This commit is contained in:
@@ -41,9 +41,11 @@ from govoplan_campaign.backend.schemas import (
|
||||
ReportEmailRequest,
|
||||
ReportEmailResponse,
|
||||
)
|
||||
from govoplan_core.auth.dependencies import ApiPrincipal, has_scope, require_scope
|
||||
from govoplan_access.backend.auth.dependencies import ApiPrincipal, has_scope, require_scope
|
||||
from govoplan_core.audit.logging import audit_from_principal
|
||||
from govoplan_campaign.backend.db.models import Campaign, CampaignJob, CampaignShare, CampaignVersion, Group, ImapAppendAttempt, RecipientImportMappingProfile, SendAttempt, User, UserGroupMembership
|
||||
from govoplan_core.core.access import CAPABILITY_ACCESS_DIRECTORY, AccessDirectory
|
||||
from govoplan_core.core.runtime import get_registry
|
||||
from govoplan_campaign.backend.db.models import Campaign, CampaignJob, CampaignShare, CampaignVersion, ImapAppendAttempt, RecipientImportMappingProfile, SendAttempt
|
||||
from govoplan_core.db.session import get_session
|
||||
from govoplan_campaign.backend.reports.campaigns import CampaignReportError, generate_campaign_report, generate_jobs_csv
|
||||
from govoplan_campaign.backend.reports.emailing import CampaignReportEmailError, send_campaign_report_email
|
||||
@@ -79,6 +81,16 @@ from govoplan_campaign.backend.persistence.versions import (
|
||||
router = APIRouter(prefix="/campaigns", tags=["campaigns"])
|
||||
|
||||
|
||||
def _access_directory() -> AccessDirectory:
|
||||
registry = get_registry()
|
||||
if registry is None or not hasattr(registry, "has_capability") or not registry.has_capability(CAPABILITY_ACCESS_DIRECTORY):
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Access directory capability is not configured")
|
||||
capability = registry.require_capability(CAPABILITY_ACCESS_DIRECTORY)
|
||||
if not isinstance(capability, AccessDirectory):
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Access directory capability is invalid")
|
||||
return capability
|
||||
|
||||
|
||||
def _get_campaign_for_tenant(session: Session, campaign_id: str, tenant_id: str) -> Campaign:
|
||||
campaign = session.get(Campaign, campaign_id)
|
||||
if not campaign or campaign.tenant_id != tenant_id:
|
||||
@@ -99,12 +111,8 @@ def _get_version_for_tenant(session: Session, version_id: str, tenant_id: str) -
|
||||
|
||||
|
||||
def _principal_group_ids(session: Session, principal: ApiPrincipal) -> set[str]:
|
||||
return {
|
||||
row[0]
|
||||
for row in session.query(UserGroupMembership.group_id)
|
||||
.filter(UserGroupMembership.tenant_id == principal.tenant_id, UserGroupMembership.user_id == principal.user.id)
|
||||
.all()
|
||||
}
|
||||
del session
|
||||
return {group.id for group in _access_directory().groups_for_user(principal.user.id, tenant_id=principal.tenant_id)}
|
||||
|
||||
|
||||
|
||||
@@ -1530,21 +1538,12 @@ def list_campaign_share_targets(
|
||||
principal: ApiPrincipal = Depends(require_scope("campaigns:campaign:share")),
|
||||
):
|
||||
_get_campaign_for_principal(session, campaign_id, principal, write=True)
|
||||
users = (
|
||||
session.query(User)
|
||||
.filter(User.tenant_id == principal.tenant_id, User.is_active.is_(True))
|
||||
.order_by(User.display_name.asc(), User.email.asc())
|
||||
.all()
|
||||
)
|
||||
groups = (
|
||||
session.query(Group)
|
||||
.filter(Group.tenant_id == principal.tenant_id, Group.is_active.is_(True))
|
||||
.order_by(Group.name.asc())
|
||||
.all()
|
||||
)
|
||||
directory = _access_directory()
|
||||
users = [user for user in directory.users_for_tenant(principal.tenant_id) if user.status == "active"]
|
||||
groups = [group for group in directory.groups_for_tenant(principal.tenant_id) if group.status == "active"]
|
||||
return CampaignShareTargetsResponse(
|
||||
users=[CampaignShareTargetItem(id=item.id, name=item.display_name or item.email, secondary=item.email) for item in users],
|
||||
groups=[CampaignShareTargetItem(id=item.id, name=item.name, secondary=item.slug) for item in groups],
|
||||
groups=[CampaignShareTargetItem(id=item.id, name=item.name, secondary=None) for item in groups],
|
||||
)
|
||||
|
||||
|
||||
@@ -1574,12 +1573,17 @@ def update_campaign_owner(
|
||||
campaign = _get_campaign_for_principal(session, campaign_id, principal, write=True)
|
||||
if payload.owner_user_id and payload.owner_group_id:
|
||||
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Choose either a user owner or a group owner, not both")
|
||||
directory = _access_directory()
|
||||
if payload.owner_user_id:
|
||||
owner = session.query(User).filter(User.id == payload.owner_user_id, User.tenant_id == principal.tenant_id, User.is_active.is_(True)).one_or_none()
|
||||
owner = directory.get_user(payload.owner_user_id)
|
||||
if owner is not None and (owner.tenant_id != principal.tenant_id or owner.status != "active"):
|
||||
owner = None
|
||||
if owner is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Owner user not found")
|
||||
if payload.owner_group_id:
|
||||
group = session.query(Group).filter(Group.id == payload.owner_group_id, Group.tenant_id == principal.tenant_id, Group.is_active.is_(True)).one_or_none()
|
||||
group = directory.get_group(payload.owner_group_id)
|
||||
if group is not None and (group.tenant_id != principal.tenant_id or group.status != "active"):
|
||||
group = None
|
||||
if group is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Owner group not found")
|
||||
campaign.owner_user_id = payload.owner_user_id
|
||||
@@ -1597,10 +1601,15 @@ def upsert_campaign_share(
|
||||
principal: ApiPrincipal = Depends(require_scope("campaigns:campaign:share")),
|
||||
):
|
||||
campaign = _get_campaign_for_principal(session, campaign_id, principal, write=True)
|
||||
directory = _access_directory()
|
||||
if payload.target_type == "user":
|
||||
target = session.query(User).filter(User.id == payload.target_id, User.tenant_id == principal.tenant_id, User.is_active.is_(True)).one_or_none()
|
||||
target = directory.get_user(payload.target_id)
|
||||
if target is not None and (target.tenant_id != principal.tenant_id or target.status != "active"):
|
||||
target = None
|
||||
else:
|
||||
target = session.query(Group).filter(Group.id == payload.target_id, Group.tenant_id == principal.tenant_id, Group.is_active.is_(True)).one_or_none()
|
||||
target = directory.get_group(payload.target_id)
|
||||
if target is not None and (target.tenant_id != principal.tenant_id or target.status != "active"):
|
||||
target = None
|
||||
if target is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Share target not found")
|
||||
share = (
|
||||
|
||||
Reference in New Issue
Block a user