Fascicoli+Tassonomia+permessi

This commit is contained in:
2026-06-17 21:47:46 +02:00
parent e31676d22e
commit 3fd3c72f06
42 changed files with 4554 additions and 99 deletions
+54 -3
View File
@@ -190,11 +190,44 @@ class RoutingRuleService:
return False
for cond in conditions:
field_value = self._get_field_value(message, cond.field)
if not self._evaluate_condition(field_value, cond.operator, cond.value):
return False
# has_label è una condizione speciale: verifica presenza di MessageLabel
if cond.field == "has_label":
if not await self._condition_has_label(message, cond.operator, cond.value):
return False
else:
field_value = self._get_field_value(message, cond.field)
if not self._evaluate_condition(field_value, cond.operator, cond.value):
return False
return True
async def _condition_has_label(
self, message: Message, operator: str, value: str
) -> bool:
"""
Verifica se il messaggio ha (o non ha) una specifica etichetta.
operator 'equals' / 'contains' → True se il messaggio HA la label con UUID=value
operator 'not_contains' → True se il messaggio NON HA la label
"""
try:
label_id = uuid.UUID(value)
except (ValueError, AttributeError):
return False
existing = await self.db.execute(
select(MessageLabel).where(
MessageLabel.message_id == message.id,
MessageLabel.label_id == label_id,
)
)
has_it = existing.scalar_one_or_none() is not None
if operator in ("equals", "contains", "starts_with", "ends_with"):
return has_it
elif operator == "not_contains":
return not has_it
return has_it
def _get_field_value(self, message: Message, field: str) -> str:
"""Estrae il valore del campo dal messaggio come stringa per il confronto."""
if field == "from_address":
@@ -207,6 +240,11 @@ class RoutingRuleService:
return str(message.mailbox_id)
elif field == "pec_type":
return message.pec_type or ""
# Rischio e Riservatezza (N3)
elif field == "risk_level":
return message.risk_level or ""
elif field == "confidentiality":
return message.confidentiality or ""
return ""
def _evaluate_condition(
@@ -241,12 +279,25 @@ class RoutingRuleService:
try:
if action.action_type == "apply_label" and action.action_value:
await self._action_apply_label(message, uuid.UUID(action.action_value))
elif action.action_type == "apply_taxonomy" and action.action_value:
# Applica un nodo tassonomico: identico a apply_label
# Il nodo è una Label con parent_id valorizzato (Processo o Classificazione)
await self._action_apply_label(message, uuid.UUID(action.action_value))
elif action.action_type == "mark_read":
message.is_read = True
elif action.action_type == "mark_starred":
message.is_starred = True
elif action.action_type == "notify_webhook" and action.action_value:
await self._action_notify_webhook(message, action.action_value)
# Rischio e Riservatezza (N3)
elif action.action_type == "set_risk_level" and action.action_value:
valid_levels = {"low", "medium", "high", "critical"}
if action.action_value in valid_levels:
message.risk_level = action.action_value
elif action.action_type == "set_confidentiality" and action.action_value:
valid_levels = {"public", "internal", "confidential", "secret"}
if action.action_value in valid_levels:
message.confidentiality = action.action_value
except Exception:
# Le azioni non devono interrompere il flusso principale
pass