Browse Source

filtering chatrooms fo only showing group chats and related pv chats

master
Mohsen Taba 2 months ago
parent
commit
51f1c00aad
  1. 48
      apps/chat/admin.py
  2. 105
      apps/chat/admin_views.py

48
apps/chat/admin.py

@ -13,7 +13,7 @@ from django.contrib import messages
from apps.chat.models import RoomMessage, ChatMessage, MessageReadStatus from apps.chat.models import RoomMessage, ChatMessage, MessageReadStatus
from utils.admin import project_admin_site, admin_url_generator from utils.admin import project_admin_site, admin_url_generator
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db.models import Count, Q
User = get_user_model() User = get_user_model()
@ -47,6 +47,30 @@ def get_allowed_users_for_room(room):
return User.objects.filter(is_active=True, id__in=allowed_ids) return User.objects.filter(is_active=True, id__in=allowed_ids)
def get_rooms_queryset_for_user(user, queryset):
"""
Absolute Privacy Rule:
- NO ONE sees a PRIVATE chat unless they are the initiator or recipient.
- Admins/Consultants see ALL GROUP chats.
- Others see only their enrolled GROUP chats.
"""
# شرط پایه: چت‌هایی که خود شخص در آن‌ها حضور مستقیم دارد (خصوصی یا گروهی فرقی ندارد)
personal_q = Q(initiator=user) | Q(recipient=user)
if user.is_superuser or user.has_role('admin') or user.has_role('super_admin') or user.has_role('consultant'):
# ادمین‌ها و مشاورین: چت‌های خودشان + تمام چت‌های گروهی
return queryset.filter(
personal_q |
Q(room_type=RoomMessage.RoomTypeChoices.GROUP)
).distinct()
# اساتید و دانشجویان: چت‌های خودشان + چت‌های گروهی که در آن عضو هستند
return queryset.filter(
personal_q |
Q(room_type=RoomMessage.RoomTypeChoices.GROUP, course__professor=user) |
Q(room_type=RoomMessage.RoomTypeChoices.GROUP, course__participants__student=user, course__participants__is_active=True)
).distinct()
# --- WIDTH ENFORCEMENT FOR SELECT2 DROPDOWNS IN INLINES --- # --- WIDTH ENFORCEMENT FOR SELECT2 DROPDOWNS IN INLINES ---
class MinWidthInlineForm(forms.ModelForm): class MinWidthInlineForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -178,7 +202,7 @@ class RoomMessageAdmin(ModelAdmin):
queryset = queryset.annotate( queryset = queryset.annotate(
total_messages=Count('messages') total_messages=Count('messages')
) )
return queryset
return get_rooms_queryset_for_user(request.user, queryset)
@action( @action(
description=_("Manage All Messages"), description=_("Manage All Messages"),
@ -265,6 +289,26 @@ class ChatMessageAdmin(ModelAdmin):
) )
actions_list = ["back_to_chat_rooms"] actions_list = ["back_to_chat_rooms"]
def get_queryset(self, request):
queryset = super().get_queryset(request)
user = request.user
personal_q = Q(room__initiator=user) | Q(room__recipient=user)
if user.is_superuser or user.has_role('admin') or user.has_role('super_admin') or user.has_role('consultant'):
# ادمین‌ها و مشاورین: پیام‌های خودشان + تمام پیام‌های چت‌های گروهی
return queryset.filter(
personal_q |
Q(room__room_type=RoomMessage.RoomTypeChoices.GROUP)
).distinct()
# اساتید و دانشجویان
return queryset.filter(
personal_q |
Q(room__room_type=RoomMessage.RoomTypeChoices.GROUP, room__course__professor=user) |
Q(room__room_type=RoomMessage.RoomTypeChoices.GROUP, room__course__participants__student=user, room__course__participants__is_active=True)
).distinct()
# 🔔 FILTER THE SENDER DROPDOWN IN THE CHAT MESSAGE FORM # 🔔 FILTER THE SENDER DROPDOWN IN THE CHAT MESSAGE FORM
def formfield_for_foreignkey(self, db_field, request, **kwargs): def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "sender": if db_field.name == "sender":

105
apps/chat/admin_views.py

@ -37,16 +37,23 @@ def live_chat_dashboard_view(request):
return render(request, "admin/chat/live_chat.html", context) return render(request, "admin/chat/live_chat.html", context)
def api_get_rooms(request): def api_get_rooms(request):
"""گرفتن لیست روم‌ها بر اساس دسترسی ادمین"""
"""گرفتن لیست روم‌ها بر اساس دسترسی و حریم خصوصی مطلق"""
user = request.user user = request.user
queryset = RoomMessage.objects.all().order_by('-updated_at')
# ادمین کل همه روم‌ها رو میبینه، استاد فقط روم‌های خودش رو
if user.is_superuser or user.has_role('admin'):
rooms = RoomMessage.objects.all().order_by('-updated_at')[:50]
personal_q = Q(initiator=user) | Q(recipient=user)
if user.is_superuser or user.has_role('admin') or user.has_role('super_admin') or user.has_role('consultant'):
rooms = queryset.filter(
personal_q |
Q(room_type=RoomMessage.RoomTypeChoices.GROUP)
).distinct()[:50]
else: else:
rooms = RoomMessage.objects.filter(
Q(initiator=user) | Q(recipient=user) | Q(course__professor=user)
).distinct().order_by('-updated_at')[:50]
rooms = queryset.filter(
personal_q |
Q(room_type=RoomMessage.RoomTypeChoices.GROUP, course__professor=user) |
Q(room_type=RoomMessage.RoomTypeChoices.GROUP, course__participants__student=user, course__participants__is_active=True)
).distinct()[:50]
data = [] data = []
for r in rooms: for r in rooms:
@ -145,5 +152,89 @@ def api_send_message(request, room_id):
threading.Thread(target=send_webhook_to_fastapi, args=(room_id, message_data)).start() threading.Thread(target=send_webhook_to_fastapi, args=(room_id, message_data)).start()
return JsonResponse({"success": True, "message_id": msg.id}) return JsonResponse({"success": True, "message_id": msg.id})
except Exception as e:
return JsonResponse({"error": str(e)}, status=500)
def api_get_users(request):
"""
برگرداندن لیست کاربران فعال که ایمیل دارند (برای شروع چت جدید)
"""
from django.contrib.auth import get_user_model
User = get_user_model()
search_term = request.GET.get('q', '').strip()
# کاربرانی که فعال هستند، خود شخصِ فعلی نیستند و حتماً ایمیل دارند
users_qs = User.objects.filter(
is_active=True,
email__isnull=False
).exclude(id=request.user.id)
if search_term:
users_qs = users_qs.filter(
Q(email__icontains=search_term) |
Q(fullname__icontains=search_term)
)
users_qs = users_qs.order_by('-date_joined')[:50] # محدود کردن به 50 نفر اول
data = []
for u in users_qs:
name = u.fullname or u.email
data.append({
"id": u.id,
"name": name,
"role": getattr(u, 'user_type', 'Member')
})
return JsonResponse({"users": data})
@require_http_methods(["POST"])
def api_create_or_get_room(request):
"""
اگر بین ادمین فعلی و کاربرِ انتخابی چت وجود داشت، آیدیاش را برمیگرداند
اگر وجود نداشت، یک Private Room جدید میسازد
"""
try:
body = json.loads(request.body)
recipient_id = body.get('user_id')
if not recipient_id:
return JsonResponse({"error": "No user ID provided"}, status=400)
from django.contrib.auth import get_user_model
User = get_user_model()
recipient = get_object_or_404(User, id=recipient_id)
# بررسی می‌کنیم آیا قبلا رومی بین این دو نفر ساخته شده؟
existing_room = RoomMessage.objects.filter(
room_type='private'
).filter(
Q(initiator=request.user, recipient=recipient) |
Q(initiator=recipient, recipient=request.user)
).first()
if existing_room:
# روم از قبل وجود دارد
return JsonResponse({
"success": True,
"room_id": existing_room.id,
"title": existing_room.name or recipient.fullname or recipient.email
})
# روم وجود ندارد، می‌سازیم
new_room = RoomMessage.objects.create(
name=f"Chat with {recipient.fullname or recipient.email}",
room_type='private',
initiator=request.user,
recipient=recipient
)
return JsonResponse({
"success": True,
"room_id": new_room.id,
"title": new_room.name
})
except Exception as e: except Exception as e:
return JsonResponse({"error": str(e)}, status=500) return JsonResponse({"error": str(e)}, status=500)
Loading…
Cancel
Save