Increase security and reformat
This commit is contained in:
@@ -25,27 +25,26 @@ from django.urls import NoReverseMatch, reverse
|
||||
from django.utils import timezone as dj_timezone
|
||||
from django.views import View
|
||||
|
||||
from core.clients import transport
|
||||
from core.assist.engine import process_inbound_assist
|
||||
from core.clients import transport
|
||||
from core.commands.base import CommandContext
|
||||
from core.commands.engine import process_inbound_message
|
||||
from core.commands.policies import ensure_variant_policies_for_profile
|
||||
from core.events.ledger import append_event_sync
|
||||
from core.messaging import ai as ai_runner
|
||||
from core.messaging import history
|
||||
from core.messaging import media_bridge
|
||||
from core.messaging import history, media_bridge
|
||||
from core.messaging.utils import messages_to_string
|
||||
from core.models import (
|
||||
AI,
|
||||
Chat,
|
||||
ChatSession,
|
||||
ChatTaskSource,
|
||||
CommandAction,
|
||||
CommandChannelBinding,
|
||||
CommandProfile,
|
||||
Message,
|
||||
MessageEvent,
|
||||
PatternMitigationPlan,
|
||||
ChatTaskSource,
|
||||
Person,
|
||||
PersonIdentifier,
|
||||
PlatformChatLink,
|
||||
@@ -54,8 +53,8 @@ from core.models import (
|
||||
from core.presence import get_settings as get_availability_settings
|
||||
from core.presence import latest_state_for_people, spans_for_range
|
||||
from core.realtime.typing_state import get_person_typing_state
|
||||
from core.transports.capabilities import supports, unsupported_reason
|
||||
from core.translation.engine import process_inbound_translation
|
||||
from core.transports.capabilities import supports, unsupported_reason
|
||||
from core.views.workspace import (
|
||||
INSIGHT_METRICS,
|
||||
_build_engage_payload,
|
||||
@@ -234,11 +233,7 @@ def _compose_availability_payload(
|
||||
range_end: int,
|
||||
) -> tuple[bool, list[dict], dict]:
|
||||
settings_row = get_availability_settings(user)
|
||||
if (
|
||||
person is None
|
||||
or not settings_row.enabled
|
||||
or not settings_row.show_in_chat
|
||||
):
|
||||
if person is None or not settings_row.enabled or not settings_row.show_in_chat:
|
||||
return False, [], {}
|
||||
|
||||
service_key = str(service or "").strip().lower()
|
||||
@@ -735,7 +730,9 @@ def _serialize_message(msg: Message) -> dict:
|
||||
),
|
||||
"reply_preview": reply_preview,
|
||||
"message_meta": {
|
||||
"origin_tag": str((getattr(msg, "message_meta", {}) or {}).get("origin_tag") or "")
|
||||
"origin_tag": str(
|
||||
(getattr(msg, "message_meta", {}) or {}).get("origin_tag") or ""
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -998,9 +995,11 @@ def _build_gap_fragment(is_outgoing_reply, lag_ms, snapshot):
|
||||
if snapshot is not None:
|
||||
score_value = getattr(
|
||||
snapshot,
|
||||
"outbound_response_score"
|
||||
if is_outgoing_reply
|
||||
else "inbound_response_score",
|
||||
(
|
||||
"outbound_response_score"
|
||||
if is_outgoing_reply
|
||||
else "inbound_response_score"
|
||||
),
|
||||
None,
|
||||
)
|
||||
if score_value is None:
|
||||
@@ -1383,9 +1382,9 @@ def _trend_meta(current, previous, higher_is_better=True):
|
||||
improves = is_up if higher_is_better else not is_up
|
||||
return {
|
||||
"direction": "up" if is_up else "down",
|
||||
"icon": "fa-solid fa-arrow-trend-up"
|
||||
if is_up
|
||||
else "fa-solid fa-arrow-trend-down",
|
||||
"icon": (
|
||||
"fa-solid fa-arrow-trend-up" if is_up else "fa-solid fa-arrow-trend-down"
|
||||
),
|
||||
"class_name": "has-text-success" if improves else "has-text-danger",
|
||||
"meaning": "Improving signal" if improves else "Risk signal",
|
||||
}
|
||||
@@ -1872,7 +1871,9 @@ def _latest_signal_bridge_ref(message: Message | None) -> dict:
|
||||
return best
|
||||
|
||||
|
||||
def _build_whatsapp_reply_metadata(reply_to: Message | None, channel_identifier: str) -> dict:
|
||||
def _build_whatsapp_reply_metadata(
|
||||
reply_to: Message | None, channel_identifier: str
|
||||
) -> dict:
|
||||
if reply_to is None:
|
||||
return {}
|
||||
target_message_id = ""
|
||||
@@ -1880,13 +1881,17 @@ def _build_whatsapp_reply_metadata(reply_to: Message | None, channel_identifier:
|
||||
|
||||
source_service = str(getattr(reply_to, "source_service", "") or "").strip().lower()
|
||||
if source_service == "whatsapp":
|
||||
target_message_id = str(getattr(reply_to, "source_message_id", "") or "").strip()
|
||||
target_message_id = str(
|
||||
getattr(reply_to, "source_message_id", "") or ""
|
||||
).strip()
|
||||
participant = str(getattr(reply_to, "sender_uuid", "") or "").strip()
|
||||
|
||||
if not target_message_id:
|
||||
bridge_ref = _latest_whatsapp_bridge_ref(reply_to)
|
||||
target_message_id = str(bridge_ref.get("upstream_message_id") or "").strip()
|
||||
participant = participant or str(bridge_ref.get("upstream_author") or "").strip()
|
||||
participant = (
|
||||
participant or str(bridge_ref.get("upstream_author") or "").strip()
|
||||
)
|
||||
|
||||
if not target_message_id:
|
||||
return {}
|
||||
@@ -1902,7 +1907,9 @@ def _build_whatsapp_reply_metadata(reply_to: Message | None, channel_identifier:
|
||||
}
|
||||
|
||||
|
||||
def _build_signal_reply_metadata(reply_to: Message | None, channel_identifier: str) -> dict:
|
||||
def _build_signal_reply_metadata(
|
||||
reply_to: Message | None, channel_identifier: str
|
||||
) -> dict:
|
||||
if reply_to is None:
|
||||
return {}
|
||||
|
||||
@@ -1933,10 +1940,13 @@ def _build_signal_reply_metadata(reply_to: Message | None, channel_identifier: s
|
||||
if source_chat_id:
|
||||
quote_author = source_chat_id
|
||||
if (
|
||||
str(getattr(reply_to, "custom_author", "") or "").strip().upper() in {"USER", "BOT"}
|
||||
str(getattr(reply_to, "custom_author", "") or "").strip().upper()
|
||||
in {"USER", "BOT"}
|
||||
or not quote_author
|
||||
):
|
||||
quote_author = str(getattr(settings, "SIGNAL_NUMBER", "") or "").strip() or quote_author
|
||||
quote_author = (
|
||||
str(getattr(settings, "SIGNAL_NUMBER", "") or "").strip() or quote_author
|
||||
)
|
||||
if not quote_author:
|
||||
quote_author = source_chat_id
|
||||
if not quote_author:
|
||||
@@ -1969,9 +1979,13 @@ def _reaction_actor_key(user_id, service: str) -> str:
|
||||
return f"web:{int(user_id)}:{str(service or '').strip().lower()}"
|
||||
|
||||
|
||||
def _resolve_reaction_target(message: Message, service: str, channel_identifier: str) -> dict:
|
||||
def _resolve_reaction_target(
|
||||
message: Message, service: str, channel_identifier: str
|
||||
) -> dict:
|
||||
service_key = _default_service(service)
|
||||
message_source_service = str(getattr(message, "source_service", "") or "").strip().lower()
|
||||
message_source_service = (
|
||||
str(getattr(message, "source_service", "") or "").strip().lower()
|
||||
)
|
||||
source_message_id = str(getattr(message, "source_message_id", "") or "").strip()
|
||||
sender_uuid = str(getattr(message, "sender_uuid", "") or "").strip()
|
||||
source_chat_id = str(getattr(message, "source_chat_id", "") or "").strip()
|
||||
@@ -1998,12 +2012,13 @@ def _resolve_reaction_target(message: Message, service: str, channel_identifier:
|
||||
target_author = sender_uuid
|
||||
if not target_author:
|
||||
target_author = str(bridge_ref.get("upstream_author") or "").strip()
|
||||
if (
|
||||
str(getattr(message, "custom_author", "") or "").strip().upper()
|
||||
in {"USER", "BOT"}
|
||||
):
|
||||
if str(getattr(message, "custom_author", "") or "").strip().upper() in {
|
||||
"USER",
|
||||
"BOT",
|
||||
}:
|
||||
target_author = (
|
||||
str(getattr(settings, "SIGNAL_NUMBER", "") or "").strip() or target_author
|
||||
str(getattr(settings, "SIGNAL_NUMBER", "") or "").strip()
|
||||
or target_author
|
||||
)
|
||||
if not target_author:
|
||||
target_author = source_chat_id or str(channel_identifier or "").strip()
|
||||
@@ -2017,7 +2032,9 @@ def _resolve_reaction_target(message: Message, service: str, channel_identifier:
|
||||
}
|
||||
|
||||
if service_key == "whatsapp":
|
||||
target_message_id = source_message_id if message_source_service == "whatsapp" else ""
|
||||
target_message_id = (
|
||||
source_message_id if message_source_service == "whatsapp" else ""
|
||||
)
|
||||
target_ts = delivered_ts or local_ts
|
||||
bridge_ref = _latest_whatsapp_bridge_ref(message)
|
||||
if not target_message_id:
|
||||
@@ -2123,7 +2140,9 @@ def _toggle_command_for_channel(
|
||||
enabled: bool,
|
||||
) -> tuple[bool, str]:
|
||||
service_key = _default_service(service)
|
||||
canonical_identifier = _canonical_command_channel_identifier(service_key, identifier)
|
||||
canonical_identifier = _canonical_command_channel_identifier(
|
||||
service_key, identifier
|
||||
)
|
||||
if not canonical_identifier:
|
||||
return (False, "missing_identifier")
|
||||
|
||||
@@ -2133,9 +2152,7 @@ def _toggle_command_for_channel(
|
||||
profile = _ensure_codex_profile(user)
|
||||
else:
|
||||
profile = (
|
||||
CommandProfile.objects.filter(user=user, slug=slug)
|
||||
.order_by("id")
|
||||
.first()
|
||||
CommandProfile.objects.filter(user=user, slug=slug).order_by("id").first()
|
||||
)
|
||||
if profile is None:
|
||||
return (False, f"unknown_command:{slug}")
|
||||
@@ -2178,9 +2195,7 @@ def _toggle_command_for_channel(
|
||||
def _command_options_for_channel(user, service: str, identifier: str) -> list[dict]:
|
||||
service_key = _default_service(service)
|
||||
variants = _command_channel_identifier_variants(service_key, identifier)
|
||||
profiles = list(
|
||||
CommandProfile.objects.filter(user=user).order_by("slug", "id")
|
||||
)
|
||||
profiles = list(CommandProfile.objects.filter(user=user).order_by("slug", "id"))
|
||||
by_slug = {str(row.slug or "").strip(): row for row in profiles}
|
||||
if "bp" not in by_slug:
|
||||
by_slug["bp"] = CommandProfile(
|
||||
@@ -2212,7 +2227,9 @@ def _command_options_for_channel(user, service: str, identifier: str) -> list[di
|
||||
enabled=True,
|
||||
).exists()
|
||||
if slug == "bp":
|
||||
policies = ensure_variant_policies_for_profile(profile) if profile.id else {}
|
||||
policies = (
|
||||
ensure_variant_policies_for_profile(profile) if profile.id else {}
|
||||
)
|
||||
label_by_key = {
|
||||
"bp": "bp",
|
||||
"bp_set": "bp set",
|
||||
@@ -2228,7 +2245,11 @@ def _command_options_for_channel(user, service: str, identifier: str) -> list[di
|
||||
"enabled_here": bool(enabled_here),
|
||||
"profile_enabled": bool(profile.enabled),
|
||||
"mode_label": str(
|
||||
(policies.get("bp").generation_mode if policies.get("bp") else "ai")
|
||||
(
|
||||
policies.get("bp").generation_mode
|
||||
if policies.get("bp")
|
||||
else "ai"
|
||||
)
|
||||
).upper(),
|
||||
},
|
||||
{
|
||||
@@ -2239,7 +2260,11 @@ def _command_options_for_channel(user, service: str, identifier: str) -> list[di
|
||||
"enabled_here": bool(enabled_here),
|
||||
"profile_enabled": bool(profile.enabled),
|
||||
"mode_label": str(
|
||||
(policies.get("bp_set").generation_mode if policies.get("bp_set") else "verbatim")
|
||||
(
|
||||
policies.get("bp_set").generation_mode
|
||||
if policies.get("bp_set")
|
||||
else "verbatim"
|
||||
)
|
||||
).upper(),
|
||||
},
|
||||
{
|
||||
@@ -2261,7 +2286,9 @@ def _command_options_for_channel(user, service: str, identifier: str) -> list[di
|
||||
)
|
||||
for row in options:
|
||||
if row.get("slug") in label_by_key:
|
||||
row["enabled_label"] = "Enabled" if row.get("enabled_here") else "Disabled"
|
||||
row["enabled_label"] = (
|
||||
"Enabled" if row.get("enabled_here") else "Disabled"
|
||||
)
|
||||
else:
|
||||
options.append(
|
||||
{
|
||||
@@ -2283,11 +2310,7 @@ def _bp_binding_summary_for_channel(user, service: str, identifier: str) -> dict
|
||||
variants = _command_channel_identifier_variants(service_key, identifier)
|
||||
if not variants:
|
||||
return {"ingress_count": 0, "egress_count": 0}
|
||||
profile = (
|
||||
CommandProfile.objects.filter(user=user, slug="bp")
|
||||
.order_by("id")
|
||||
.first()
|
||||
)
|
||||
profile = CommandProfile.objects.filter(user=user, slug="bp").order_by("id").first()
|
||||
if profile is None:
|
||||
return {"ingress_count": 0, "egress_count": 0}
|
||||
ingress_count = CommandChannelBinding.objects.filter(
|
||||
@@ -2315,7 +2338,9 @@ def _toggle_task_announce_for_channel(
|
||||
enabled: bool,
|
||||
) -> tuple[bool, str]:
|
||||
service_key = _default_service(service)
|
||||
canonical_identifier = _canonical_command_channel_identifier(service_key, identifier)
|
||||
canonical_identifier = _canonical_command_channel_identifier(
|
||||
service_key, identifier
|
||||
)
|
||||
if not canonical_identifier:
|
||||
return (False, "missing_identifier")
|
||||
variants = _command_channel_identifier_variants(service_key, canonical_identifier)
|
||||
@@ -3411,7 +3436,9 @@ class ComposeContactCreateAll(LoginRequiredMixin, View):
|
||||
skipped_count += 1
|
||||
|
||||
if errors:
|
||||
message = f"Created {created_count} contacts. Errors: {'; '.join(errors[:5])}"
|
||||
message = (
|
||||
f"Created {created_count} contacts. Errors: {'; '.join(errors[:5])}"
|
||||
)
|
||||
level = "warning"
|
||||
elif created_count > 0:
|
||||
message = f"Created {created_count} new contact{'s' if created_count != 1 else ''}. Skipped {skipped_count}."
|
||||
@@ -3538,7 +3565,9 @@ class ComposeThread(LoginRequiredMixin, View):
|
||||
counterpart_identifiers = _counterpart_identifiers_for_person(
|
||||
request.user, base["person"]
|
||||
)
|
||||
range_start = int(messages[0].ts or 0) if messages else max(0, int(after_ts or 0))
|
||||
range_start = (
|
||||
int(messages[0].ts or 0) if messages else max(0, int(after_ts or 0))
|
||||
)
|
||||
range_end = int(latest_ts or 0)
|
||||
if range_start <= 0 or range_end <= 0:
|
||||
now_ts = int(time.time() * 1000)
|
||||
@@ -3947,7 +3976,9 @@ class ComposeToggleCommand(LoginRequiredMixin, View):
|
||||
service, str(identifier or "")
|
||||
)
|
||||
if not channel_identifier:
|
||||
return JsonResponse({"ok": False, "error": "missing_identifier"}, status=400)
|
||||
return JsonResponse(
|
||||
{"ok": False, "error": "missing_identifier"}, status=400
|
||||
)
|
||||
if service not in {"web", "xmpp", "signal", "whatsapp"}:
|
||||
return JsonResponse(
|
||||
{"ok": False, "error": f"unsupported_service:{service}"},
|
||||
@@ -3996,9 +4027,7 @@ class ComposeToggleCommand(LoginRequiredMixin, View):
|
||||
if enabled
|
||||
else f"{slug} disabled for this chat."
|
||||
)
|
||||
scoped_settings_url = (
|
||||
f"{reverse('command_routing')}?{urlencode({'service': service, 'identifier': channel_identifier})}"
|
||||
)
|
||||
scoped_settings_url = f"{reverse('command_routing')}?{urlencode({'service': service, 'identifier': channel_identifier})}"
|
||||
return JsonResponse(
|
||||
{
|
||||
"ok": True,
|
||||
@@ -4014,6 +4043,7 @@ class ComposeToggleCommand(LoginRequiredMixin, View):
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ComposeBindBP(ComposeToggleCommand):
|
||||
def post(self, request):
|
||||
service, identifier, _ = _request_scope(request, "POST")
|
||||
@@ -4296,9 +4326,11 @@ class ComposeQuickInsights(LoginRequiredMixin, View):
|
||||
or conversation.get_stability_state_display(),
|
||||
"stability_state": conversation.get_stability_state_display(),
|
||||
"thread": conversation.platform_thread_id or "",
|
||||
"last_event": _format_ts_label(conversation.last_event_ts or 0)
|
||||
if conversation.last_event_ts
|
||||
else "",
|
||||
"last_event": (
|
||||
_format_ts_label(conversation.last_event_ts or 0)
|
||||
if conversation.last_event_ts
|
||||
else ""
|
||||
),
|
||||
"last_ai_run": (
|
||||
dj_timezone.localtime(conversation.last_ai_run_at).strftime(
|
||||
"%Y-%m-%d %H:%M"
|
||||
@@ -4607,11 +4639,15 @@ class ComposeSend(LoginRequiredMixin, View):
|
||||
log_prefix = (
|
||||
f"[ComposeSend] service={base['service']} identifier={base['identifier']}"
|
||||
)
|
||||
if bool(getattr(settings, "CAPABILITY_ENFORCEMENT_ENABLED", True)) and not supports(
|
||||
if bool(
|
||||
getattr(settings, "CAPABILITY_ENFORCEMENT_ENABLED", True)
|
||||
) and not supports(
|
||||
str(base["service"] or "").strip().lower(),
|
||||
"send",
|
||||
):
|
||||
reason = unsupported_reason(str(base["service"] or "").strip().lower(), "send")
|
||||
reason = unsupported_reason(
|
||||
str(base["service"] or "").strip().lower(), "send"
|
||||
)
|
||||
return self._response(
|
||||
request,
|
||||
ok=False,
|
||||
@@ -4786,7 +4822,9 @@ class ComposeSend(LoginRequiredMixin, View):
|
||||
source_chat_id=str(base["identifier"] or ""),
|
||||
reply_to=reply_to,
|
||||
reply_source_service="web" if reply_to is not None else None,
|
||||
reply_source_message_id=str(reply_to.id) if reply_to is not None else None,
|
||||
reply_source_message_id=(
|
||||
str(reply_to.id) if reply_to is not None else None
|
||||
),
|
||||
message_meta={},
|
||||
)
|
||||
try:
|
||||
@@ -4858,7 +4896,9 @@ class ComposeReact(LoginRequiredMixin, View):
|
||||
service_key = _default_service(service)
|
||||
if service_key not in {"signal", "whatsapp"}:
|
||||
return JsonResponse({"ok": False, "error": "service_not_supported"})
|
||||
if bool(getattr(settings, "CAPABILITY_ENFORCEMENT_ENABLED", True)) and not supports(service_key, "reactions"):
|
||||
if bool(
|
||||
getattr(settings, "CAPABILITY_ENFORCEMENT_ENABLED", True)
|
||||
) and not supports(service_key, "reactions"):
|
||||
return JsonResponse(
|
||||
{
|
||||
"ok": False,
|
||||
|
||||
Reference in New Issue
Block a user