Prepare v0.1.0 release
This commit is contained in:
@@ -198,6 +198,40 @@ def _policy_from_attr(value: Any) -> dict[str, Any]:
|
||||
return normalize_mail_profile_policy(value if isinstance(value, dict) else {})
|
||||
|
||||
|
||||
|
||||
def _mail_policy_source_fields(policy: dict[str, Any], *, baseline: bool = False) -> list[str]:
|
||||
fields: list[str] = []
|
||||
if _meaningful_allow_patterns(policy.get("allowed_profile_ids") or []):
|
||||
fields.append("allowed_profile_ids")
|
||||
for key in ("allow_user_profiles", "allow_group_profiles", "allow_campaign_profiles"):
|
||||
if isinstance(policy.get(key), bool):
|
||||
fields.append(key)
|
||||
for key in ("smtp_credentials", "imap_credentials"):
|
||||
credential = policy.get(key) or {}
|
||||
if isinstance(credential, dict):
|
||||
if isinstance(credential.get("inherit"), bool):
|
||||
fields.append(f"{key}.inherit")
|
||||
if isinstance(credential.get("allow_override"), bool):
|
||||
fields.append(f"{key}.allow_override")
|
||||
for kind in ("whitelist", "blacklist"):
|
||||
rules = policy.get(kind) or {}
|
||||
if isinstance(rules, dict):
|
||||
for key in PROFILE_PATTERN_KEYS:
|
||||
if _clean_string_list(rules.get(key, [])):
|
||||
fields.append(f"{kind}.{key}")
|
||||
if baseline and not fields:
|
||||
fields.append("defaults")
|
||||
return fields
|
||||
|
||||
|
||||
def _mail_policy_source_step(source: str, source_id: str | None, label: str, policy: dict[str, Any], *, baseline: bool = False) -> dict[str, Any]:
|
||||
return {
|
||||
"scope_type": source,
|
||||
"scope_id": source_id,
|
||||
"label": label,
|
||||
"applied_fields": _mail_policy_source_fields(policy, baseline=baseline),
|
||||
}
|
||||
|
||||
def _merge_credential_policy(current: EffectiveCredentialPolicy, data: dict[str, Any], *, source: str) -> None:
|
||||
inherit = data.get("inherit")
|
||||
if isinstance(inherit, bool):
|
||||
@@ -216,9 +250,9 @@ def _merge_credential_policy(current: EffectiveCredentialPolicy, data: dict[str,
|
||||
current.allow_override = False
|
||||
|
||||
|
||||
def _merge_policy(policy: EffectiveMailProfilePolicy, data: dict[str, Any], *, source: str) -> None:
|
||||
def _merge_policy(policy: EffectiveMailProfilePolicy, data: dict[str, Any], *, source: str, source_id: str | None = None, label: str | None = None, baseline: bool = False) -> None:
|
||||
normalized = normalize_mail_profile_policy(data)
|
||||
policy.source_policies.append(normalized)
|
||||
policy.source_policies.append(_mail_policy_source_step(source, source_id, label or source.capitalize(), normalized, baseline=baseline))
|
||||
allowed_ids = _meaningful_allow_patterns(normalized.get("allowed_profile_ids") or [])
|
||||
if allowed_ids:
|
||||
policy.allowed_profile_id_sets.append(set(allowed_ids))
|
||||
@@ -280,18 +314,18 @@ def effective_mail_profile_policy(
|
||||
|
||||
policy = EffectiveMailProfilePolicy()
|
||||
system_settings = get_system_settings(session)
|
||||
_merge_policy(policy, _policy_from_settings(system_settings.settings or {}), source="system")
|
||||
_merge_policy(policy, _policy_from_settings(tenant.settings or {}), source="tenant")
|
||||
_merge_policy(policy, _policy_from_settings(system_settings.settings or {}), source="system", label="System", baseline=True)
|
||||
_merge_policy(policy, _policy_from_settings(tenant.settings or {}), source="tenant", source_id=tenant.id, label="Tenant")
|
||||
if owner_user_id:
|
||||
user = session.get(User, owner_user_id)
|
||||
if user and user.tenant_id == tenant_id:
|
||||
_merge_policy(policy, _policy_from_attr(user.mail_profile_policy), source="user")
|
||||
_merge_policy(policy, _policy_from_attr(user.mail_profile_policy), source="user", source_id=user.id, label="Owner user")
|
||||
if owner_group_id:
|
||||
group = session.get(Group, owner_group_id)
|
||||
if group and group.tenant_id == tenant_id:
|
||||
_merge_policy(policy, _policy_from_attr(group.mail_profile_policy), source="group")
|
||||
_merge_policy(policy, _policy_from_attr(group.mail_profile_policy), source="group", source_id=group.id, label="Owner group")
|
||||
if campaign is not None:
|
||||
_merge_policy(policy, _policy_from_attr(campaign.mail_profile_policy), source="campaign")
|
||||
_merge_policy(policy, _policy_from_attr(campaign.mail_profile_policy), source="campaign", source_id=campaign.id, label="Campaign")
|
||||
return policy
|
||||
|
||||
|
||||
@@ -309,11 +343,11 @@ def parent_mail_profile_policy(
|
||||
|
||||
policy = EffectiveMailProfilePolicy()
|
||||
system_settings = get_system_settings(session)
|
||||
_merge_policy(policy, _policy_from_settings(system_settings.settings or {}), source="system")
|
||||
_merge_policy(policy, _policy_from_settings(system_settings.settings or {}), source="system", label="System", baseline=True)
|
||||
if clean_scope == "tenant":
|
||||
return policy
|
||||
|
||||
_merge_policy(policy, _policy_from_settings(tenant.settings or {}), source="tenant")
|
||||
_merge_policy(policy, _policy_from_settings(tenant.settings or {}), source="tenant", source_id=tenant.id, label="Tenant")
|
||||
if clean_scope in {"user", "group"}:
|
||||
return policy
|
||||
|
||||
@@ -325,11 +359,11 @@ def parent_mail_profile_policy(
|
||||
if campaign.owner_user_id:
|
||||
user = session.get(User, campaign.owner_user_id)
|
||||
if user and user.tenant_id == tenant_id:
|
||||
_merge_policy(policy, _policy_from_attr(user.mail_profile_policy), source="user")
|
||||
_merge_policy(policy, _policy_from_attr(user.mail_profile_policy), source="user", source_id=user.id, label="Owner user")
|
||||
if campaign.owner_group_id:
|
||||
group = session.get(Group, campaign.owner_group_id)
|
||||
if group and group.tenant_id == tenant_id:
|
||||
_merge_policy(policy, _policy_from_attr(group.mail_profile_policy), source="group")
|
||||
_merge_policy(policy, _policy_from_attr(group.mail_profile_policy), source="group", source_id=group.id, label="Owner group")
|
||||
return policy
|
||||
|
||||
|
||||
@@ -454,7 +488,7 @@ def _ensure_scope_allows_profile_creation(
|
||||
if scope_type == "campaign":
|
||||
policy = effective_mail_profile_policy(session, tenant_id=tenant_id, campaign_id=scope_id)
|
||||
if not policy.allow_campaign_profiles:
|
||||
raise MailProfileError("Campaign-scoped mail-server profiles are disabled by policy")
|
||||
raise MailProfileError("Campaign-local mail profiles are disabled by policy")
|
||||
return
|
||||
if scope_type == "user":
|
||||
policy = effective_mail_profile_policy(session, tenant_id=tenant_id, owner_user_id=scope_id)
|
||||
@@ -694,6 +728,17 @@ def _assert_profile_credentials_allowed_for_server(profile: MailServerProfile, p
|
||||
raise MailProfileError(f"{protocol.upper()} credentials must be supplied by this campaign or scope policy")
|
||||
|
||||
|
||||
def _inline_transport_configured(value: Any) -> bool:
|
||||
if not isinstance(value, dict):
|
||||
return False
|
||||
if value.get("enabled") is True:
|
||||
return True
|
||||
for key in ("host", "username", "password"):
|
||||
if str(value.get(key) or "").strip():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def assert_campaign_mail_policy_allows_json(
|
||||
session: Session,
|
||||
*,
|
||||
@@ -737,6 +782,12 @@ def assert_campaign_mail_policy_allows_json(
|
||||
return
|
||||
smtp = server.get("smtp") if isinstance(server, dict) and isinstance(server.get("smtp"), dict) else None
|
||||
imap = server.get("imap") if isinstance(server, dict) and isinstance(server.get("imap"), dict) else None
|
||||
if campaign_id:
|
||||
policy = effective_mail_profile_policy(session, tenant_id=tenant_id, campaign_id=campaign_id)
|
||||
if not policy.allow_campaign_profiles and (_inline_transport_configured(smtp) or _inline_transport_configured(imap)):
|
||||
raise MailProfileError("Campaign-local inline mail settings are disabled by policy")
|
||||
_assert_transport_values_allowed(policy, smtp, imap)
|
||||
return
|
||||
assert_mail_policy_allows_transport(
|
||||
session,
|
||||
tenant_id=tenant_id,
|
||||
|
||||
Reference in New Issue
Block a user