111 lines
4.5 KiB
Python
111 lines
4.5 KiB
Python
"""Routes available only to staff, including isolated message attachment delivery."""
|
|
|
|
from django.contrib import messages
|
|
from django.db import transaction
|
|
from django.utils import timezone
|
|
from django.core.exceptions import PermissionDenied, ValidationError
|
|
from django.http import JsonResponse
|
|
from django.shortcuts import get_object_or_404, redirect
|
|
from django.views.decorators.cache import never_cache
|
|
from django.views.decorators.http import require_GET, require_POST
|
|
|
|
from apps.attachments.delivery import attachment_response
|
|
from apps.attachments.models import Attachment
|
|
from .models import MessageShare, Ticket, TicketReadState
|
|
from .policies import TicketPolicy
|
|
from apps.messaging.read_receipts import message_read_ids
|
|
from .staff_conversation import received_messages, unread_shares, visible_messages
|
|
from .sharing import mark_share_opened, revoke_staff_share
|
|
from .views import staff_required, mark_messages_read
|
|
|
|
|
|
def received_message_share(request, share_id):
|
|
from .dispatch_responses import can_read_response
|
|
grant = get_object_or_404(MessageShare.objects.select_related("message__author__staff_profile", "granted_by__staff_profile"), public_id=share_id)
|
|
profile = getattr(request.user, "staff_profile", None)
|
|
if not can_read_response(request.user, grant.message):
|
|
raise PermissionDenied
|
|
if (grant.user_id != request.user.pk or grant.revoked_at or grant.message.deleted_at
|
|
or not request.user.is_active or not profile or not profile.is_active):
|
|
raise PermissionDenied
|
|
return grant
|
|
|
|
|
|
def submit_share_form(request, form, save, success_message):
|
|
if not form.is_valid():
|
|
messages.error(request, "گیرنده، سطح دسترسی یا توضیح اشتراک معتبر نیست.")
|
|
return
|
|
try:
|
|
save()
|
|
except ValidationError as error:
|
|
messages.error(request, " ".join(error.messages))
|
|
else:
|
|
messages.success(request, success_message)
|
|
|
|
|
|
@staff_required
|
|
@require_GET
|
|
@never_cache
|
|
def inbox(request):
|
|
from django.urls import reverse
|
|
return redirect(reverse("staff_tickets:list") + "?tab=shared")
|
|
|
|
|
|
@staff_required
|
|
@require_POST
|
|
def revoke_message(request, public_id, share_id):
|
|
grant = get_object_or_404(MessageShare.objects.select_related("message__ticket"), public_id=share_id, message__ticket__public_id=public_id)
|
|
revoke_staff_share(grant, request.user)
|
|
messages.success(request, "دسترسی به پیام اشتراکی لغو شد؛ سابقه آن حفظ شده است.")
|
|
return redirect("staff_tickets:detail", public_id=public_id)
|
|
|
|
|
|
@staff_required
|
|
@require_GET
|
|
@never_cache
|
|
def shared_message(request, share_id):
|
|
grant = received_message_share(request, share_id)
|
|
return redirect("staff_tickets:detail", public_id=grant.message.ticket.public_id)
|
|
|
|
|
|
@staff_required
|
|
@require_POST
|
|
@never_cache
|
|
@transaction.atomic
|
|
def read_shared_messages(request, public_id):
|
|
from .dispatch_responses import can_record_ticket_read
|
|
ticket = get_object_or_404(Ticket.objects.select_for_update(), public_id=public_id)
|
|
allowed = visible_messages(ticket, request.user)
|
|
try:
|
|
ids = message_read_ids(request)
|
|
except ValidationError:
|
|
return JsonResponse({"ok": False, "error": "invalid_message_ids"}, status=400)
|
|
acknowledged = list(allowed.filter(public_id__in=ids, deleted_at__isnull=True))
|
|
mark_messages_read(acknowledged, request.user)
|
|
accepted = [item.public_id for item in acknowledged]
|
|
grants = received_messages(request.user, ticket).filter(message__public_id__in=accepted)
|
|
for grant in grants:
|
|
if grant.first_viewed_at is None:
|
|
mark_share_opened(grant, request.user)
|
|
latest = allowed.filter(deleted_at__isnull=True).order_by('-created_at', '-pk').first()
|
|
if latest and latest.public_id in accepted and can_record_ticket_read(ticket, request.user):
|
|
TicketReadState.objects.update_or_create(ticket=ticket, user=request.user,
|
|
defaults={'last_read_at': timezone.now(), 'last_read_message': latest})
|
|
return JsonResponse({"unread_shares": unread_shares(request.user), "read_ids": [str(value) for value in accepted]})
|
|
|
|
|
|
@staff_required
|
|
@require_GET
|
|
@never_cache
|
|
def unread_count(request):
|
|
return JsonResponse({"unread_shares": unread_shares(request.user)})
|
|
|
|
|
|
@staff_required
|
|
@require_GET
|
|
@never_cache
|
|
def shared_attachment(request, share_id, attachment_id, download=False):
|
|
grant = received_message_share(request, share_id)
|
|
attachment = get_object_or_404(Attachment, public_id=attachment_id, message_id=grant.message_id)
|
|
return attachment_response(attachment, download=download)
|