File size: 14,307 Bytes
3e8a166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# management/views.py
# -*- coding: utf-8 -*-
from django.utils import timezone
from rest_framework import generics, viewsets, status
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.views import APIView
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.tokens import RefreshToken
import datetime

from .models import (
    CustomUser, Panel, MarzbanAdmin, License, SecurityToken, Plan, Subscription,
    Payment, EndUser, PaymentMethod, PaymentSetting, PaymentDetail, TelegramUser
)
from .serializers import (
    PanelSerializer, LicenseSerializer, MarzbanAdminSerializer, CustomUserSerializer,
    SecurityTokenSerializer, PlanSerializer, SubscriptionSerializer,
    ReceiptUploadSerializer, PaymentMethodSerializer, PaymentDetailSerializer,
    EndUserPaymentDetailSerializer, AdminLevel3SubscriptionSerializer,
    PurchaseSubscriptionForUserSerializer,
)
from .tasks import (
    send_telegram_message, send_payment_receipt_to_admin,
    send_payment_confirmation_to_user,
)

# --- Authentication Views ---
class CustomTokenObtainPairView(TokenObtainPairView):
    def post(self, request, *args, **kwargs):
        response = super().post(request, *args, **kwargs)
        if response.status_code == 200:
            user = CustomUser.objects.get(username=request.data['username'])
            response.data['user_role'] = user.role
        return response

class LogoutAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            refresh_token = request.data["refresh_token"]
            token = RefreshToken(refresh_token)
            token.blacklist()
            return Response({"message": "Successfully logged out."}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({"error": "Invalid token or other error."}, status=status.HTTP_400_BAD_REQUEST)

# --- ADDED: Missing ViewSets ---

class PanelViewSet(viewsets.ModelViewSet):
    serializer_class = PanelSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        return Panel.objects.filter(owner=self.request.user)
    
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

class LicenseViewSet(viewsets.ModelViewSet):
    serializer_class = LicenseSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        if user.is_super_admin():
            return License.objects.all()
        return License.objects.filter(owner=user)

class MarzbanAdminViewSet(viewsets.ModelViewSet):
    serializer_class = MarzbanAdminSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        try:
            panel = Panel.objects.get(owner=self.request.user)
            return MarzbanAdmin.objects.filter(panel=panel)
        except Panel.DoesNotExist:
            return MarzbanAdmin.objects.none()

class PlanViewSet(viewsets.ModelViewSet):
    serializer_class = PlanSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        try:
            panel = Panel.objects.get(owner=self.request.user)
            return Plan.objects.filter(panel=panel)
        except Panel.DoesNotExist:
            return Plan.objects.none()

    def perform_create(self, serializer):
        try:
            panel = Panel.objects.get(owner=self.request.user)
            serializer.save(panel=panel)
        except Panel.DoesNotExist:
            return Response({"error": "You do not own a panel."}, status=status.HTTP_403_FORBIDDEN)

class EndUserViewSet(viewsets.ModelViewSet):
    serializer_class = SubscriptionSerializer # A better serializer can be created for EndUser
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        if self.request.user.role == 'AdminLevel3':
            try:
                panel = Panel.objects.get(owner=self.request.user)
                return EndUser.objects.filter(panel=panel)
            except Panel.DoesNotExist:
                return EndUser.objects.none()
        return EndUser.objects.none()

class SubscriptionViewSet(viewsets.ModelViewSet):
    serializer_class = SubscriptionSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        user = self.request.user
        if user.role == 'AdminLevel3':
            try:
                panel = Panel.objects.get(owner=user)
                return Subscription.objects.filter(panel=panel)
            except Panel.DoesNotExist:
                return Subscription.objects.none()
        elif user.role == 'EndUser':
            try:
                end_user = EndUser.objects.get(username=user.username)
                return Subscription.objects.filter(end_user=end_user)
            except EndUser.DoesNotExist:
                return Subscription.objects.none()
        return Subscription.objects.none()

class PaymentViewSet(viewsets.ModelViewSet):
    serializer_class = ReceiptUploadSerializer # A better serializer can be created for listing
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        if user.is_admin_level_3():
            return Payment.objects.filter(admin=user)
        return Payment.objects.none()
        
# --- Payment System Views ---
class PaymentMethodViewSet(viewsets.ModelViewSet):
    queryset = PaymentMethod.objects.all()
    serializer_class = PaymentMethodSerializer
    permission_classes = [IsAuthenticated]
    http_method_names = ['get', 'patch', 'put']

    def get_queryset(self):
        if self.request.user.is_authenticated and self.request.user.is_admin_level_2():
            return PaymentMethod.objects.all()
        return PaymentMethod.objects.none()

class PaymentDetailAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if not request.user.is_admin_level_3():
            return Response({'error': 'Permission denied.'}, status=status.HTTP_403_FORBIDDEN)
        details, _ = PaymentDetail.objects.get_or_create(admin_level_3=request.user)
        serializer = PaymentDetailSerializer(details)
        return Response(serializer.data)

    def put(self, request):
        if not request.user.is_admin_level_3():
            return Response({'error': 'Permission denied.'}, status=status.HTTP_403_FORBIDDEN)
        details, _ = PaymentDetail.objects.get_or_create(admin_level_3=request.user)
        serializer = PaymentDetailSerializer(details, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class EndUserPaymentOptionsAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if not request.user.role == 'EndUser':
            return Response({'error': 'Permission denied.'}, status=status.HTTP_403_FORBIDDEN)
        try:
            end_user = EndUser.objects.get(username=request.user.username)
            admin_level_3_user = end_user.panel.owner
            payment_settings = PaymentSetting.objects.filter(admin_level_3=admin_level_3_user, is_active=True)
            serializer = EndUserPaymentDetailSerializer(payment_settings, many=True)
            return Response(serializer.data)
        except EndUser.DoesNotExist:
            return Response({'error': 'User not found.'}, status=status.HTTP_404_NOT_FOUND)

# --- Subscription Management ---
class AdminLevel3SubscriptionViewSet(viewsets.ModelViewSet):
    serializer_class = AdminLevel3SubscriptionSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        if self.request.user.is_authenticated and self.request.user.role == 'AdminLevel3':
            try:
                return Subscription.objects.filter(panel__owner=self.request.user)
            except Panel.DoesNotExist:
                return Subscription.objects.none()
        return Subscription.objects.none()

    def perform_create(self, serializer):
        serializer.save()

# FIXED: Logic for purchasing subscription
class PurchaseSubscriptionForUserAPIView(APIView):
    serializer_class = PurchaseSubscriptionForUserSerializer
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        data = serializer.validated_data
        end_user_username = data.get('end_user_username')
        plan_id = data.get('plan_id')
        amount = data.get('amount')

        try:
            # The user making the request must be an EndUser
            if request.user.role != 'EndUser':
                return Response({'error': 'Only EndUsers can purchase subscriptions.'}, status=status.HTTP_403_FORBIDDEN)
            
            # Get the panel of the user making the request
            requester_end_user = EndUser.objects.get(username=request.user.username)
            panel = requester_end_user.panel
            admin_level_3_user = panel.owner

            plan = Plan.objects.get(id=plan_id, panel=panel)

            # Get or create the target end user within the same panel
            target_end_user, _ = EndUser.objects.get_or_create(
                username=end_user_username, defaults={'panel': panel}
            )

            subscription = Subscription.objects.create(
                end_user=target_end_user,
                plan=plan,
                panel=panel,
                status='pending',
            )

            payment = Payment.objects.create(
                subscription=subscription,
                admin=admin_level_3_user,
                amount=amount,
                status='pending',
            )

            return Response({
                "message": "Subscription request created successfully. Please upload the receipt.",
                "subscription_id": subscription.id,
                "payment_token": payment.payment_token
            }, status=status.HTTP_201_CREATED)

        except EndUser.DoesNotExist:
            return Response({'error': 'Requesting user profile not found.'}, status=status.HTTP_404_NOT_FOUND)
        except Plan.DoesNotExist:
            return Response({'error': 'Plan not found for your panel.'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

# --- Other Views ---

# ADDED: PaymentReceiptUploadAPIView (was missing)
class PaymentReceiptUploadAPIView(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = ReceiptUploadSerializer
    
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        try:
            payment = Payment.objects.get(payment_token=serializer.validated_data['payment_token'])
            
            # Update payment with receipt details
            payment.receipt_image = serializer.validated_data.get('receipt_image')
            payment.receipt_text = serializer.validated_data.get('receipt_text')
            payment.save()
            
            # Trigger celery task to notify admin
            send_payment_receipt_to_admin.delay(payment.id)
            
            return Response({"message": "Receipt uploaded successfully. Please wait for admin approval."}, status=status.HTTP_200_OK)
        except Payment.DoesNotExist:
            return Response({"error": "Invalid payment token."}, status=status.HTTP_404_NOT_FOUND)

# ADDED: GenerateTelegramTokenAPIView (was missing)
class GenerateTelegramTokenAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user
        expiration = timezone.now() + datetime.timedelta(minutes=5)
        # This assumes a direct relation between CustomUser and a Marzban Admin ID
        if not user.marzban_admin_id:
             return Response({'error': 'User is not linked to a Marzban admin.'}, status=status.HTTP_400_BAD_REQUEST)

        token, _ = SecurityToken.objects.update_or_create(
            admin_id=str(user.marzban_admin_id),
            defaults={'expiration_date': expiration}
        )
        return Response({'token': token.token})

class VerifyTelegramTokenAPIView(APIView):
    # This view is for unauthenticated users (the bot) to verify a token
    permission_classes = [] 

    def post(self, request):
        token_value = request.data.get('token')
        chat_id = request.data.get('chat_id')

        if not token_value or not chat_id:
            return Response({'error': 'Token and chat_id are required.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            token = SecurityToken.objects.get(token=token_value, expiration_date__gt=timezone.now())
            
            # Logic to find the main DB CustomUser and update their telegram_chat_id
            user = CustomUser.objects.get(marzban_admin_id=token.admin_id)
            
            # Assuming AdminLevel3 has a telegram_chat_id field
            if hasattr(user, 'admin_level_3'):
                user.admin_level_3.telegram_chat_id = chat_id
                user.admin_level_3.save()
            
            token.delete() # One-time use token
            return Response({'message': 'Telegram account linked successfully.'})
        except (SecurityToken.DoesNotExist, CustomUser.DoesNotExist):
            return Response({'error': 'Invalid or expired token.'}, status=status.HTTP_400_BAD_REQUEST)

class PushSubscriptionAPIView(APIView):
    permission_classes = [IsAuthenticated]
    def post(self, request, *args, **kwargs):
        # Implementation needed
        return Response({'message': 'Subscription created successfully.'})

# ADDED: TelegramWebhookView (was in urls.py but missing here)
class TelegramWebhookView(APIView):
    permission_classes = []
    
    def post(self, request, bot_token):
        # Your telegram bot logic here
        # print(request.data)
        return Response({'status': 'ok'})