from pickle import TRUE import random from datetime import datetime, timedelta from django.contrib.auth import get_user_model from rest_framework.authtoken.models import Token from rest_framework.decorators import api_view, authentication_classes, permission_classes from rest_framework.authentication import SessionAuthentication, TokenAuthentication from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework import status from django.contrib.auth.models import User from core.models.customer import Customer from core.serializers.UserSerializer import UserSerializer from core.serializers.CustomerSerializer import CustomerSerializer from core.serializers.ImageSerializer import ImageSerializer from core.serializers.GlbSerializer import GlbSerializer from core.serializers.VideoSerializer import VideoSerializer from core.serializers.PdfSerializer import PdfSerializer # utils.py from core.models.AssignedRule import AssignedRule from core.models.image import Image from core.models.video import Video from core.models.pdf import Pdf from core.models.glb import Glb from django.core.mail import EmailMultiAlternatives from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings from django.utils.dateparse import parse_date from datetime import datetime from django.core.files.storage import default_storage import os import requests import json import logging logger = logging.getLogger(__name__) from django.core.cache import cache import random import string import requests import json def send_sms(to_number, code): username = "09399112092" password = "Dadechin123!@##!" from_number = "+983000505" pattern_code = "lgfrblbdppyn202" url = "https://ippanel.com/patterns/pattern" to = [to_number] input_data = {"code": code} params = { "username": username, "password": password, "from": from_number, "to": json.dumps(to), "input_data": json.dumps(input_data), "pattern_code": pattern_code } try: response = requests.post(url, params=params, data=input_data) return response.text except Exception as e: return f"Error: {e}" def user_has_role(user, role_name): return AssignedRule.objects.filter(user=user, role__name=role_name).exists() @api_view(['POST']) def signup(request): # Check if username already exists if User.objects.filter(username=request.data['mobile_number']).exists(): return Response({'username': ['A user with that username already exists.']}, status=status.HTTP_400_BAD_REQUEST) # Ensure mobile number is provided if 'mobile_number' not in request.data: return Response({'mobile_number': ['This field is required.']}, status=status.HTTP_400_BAD_REQUEST) # Proceed with user creation user_serializer = UserSerializer(data=request.data) if user_serializer.is_valid(): user = user_serializer.save() user.set_password(request.data['password']) user.username = request.data['mobile_number'] user.first_name = request.data['first_name'] user.last_name = request.data['last_name'] user.save() customer_data = { 'user': user.id, 'mobile_number': request.data['mobile_number'], # Ensure mobile number is provided 'semat': request.data['semat'], } customer_serializer = CustomerSerializer(data=customer_data) if customer_serializer.is_valid(): customer_serializer.save() token = Token.objects.create(user=user) return Response({'token': token.key, 'customer': customer_serializer.data, 'user': user_serializer.data}, status=status.HTTP_201_CREATED) else: # If customer data is invalid, delete the created user user.delete() return Response(customer_serializer.errors, status=status.HTTP_400_BAD_REQUEST) else: return Response(user_serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(['POST']) def sendForgetPasswordCode(request): try: # Retrieve the associated customer object customer = Customer.objects.get(mobile_number=request.data['mobile_number']) # Generate a random verification code verification_code = str(random.randint(100000, 999999)) # Update user's verification_code and sms_time_for_valid customer.verification_email_code = verification_code customer.verification_sms_code = verification_code customer.save() sendEmail(customer.user.email,verification_code) return Response({"message": ("Email verification code sent successfully. " + customer.user.email)}) except Customer.DoesNotExist: # If no customer object exists for the user, return an error response return Response({'error': 'No customer data found for this user'}, status=404) from django.contrib.auth.hashers import make_password @api_view(['POST']) def sendCodeAndNewPassword(request): try: # Retrieve the associated customer object customer = Customer.objects.get(mobile_number=request.data['mobile_number'], verification_sms_code=request.data['verification_sms_code']) if customer: # Update the user's password customer.user.password = make_password(request.data['password']) customer.user.save() return Response({"message": "Password has been changed successfully."}) else: return Response({"message": "Wrong mobile number or verification code."}) except Customer.DoesNotExist: # If no customer object exists for the user, return an error response return Response({'message': 'No customer data found for this user'}, status=404) # @api_view(['POST']) # def login(request): # try: # customer = Customer.objects.get(mobile_number=request.data['mobile_number']) # except get_user_model().DoesNotExist: # return Response("User not found", status=status.HTTP_404_NOT_FOUND) # if not customer.user.check_password(request.data['password']): # return Response("Invalid password", status=status.HTTP_401_UNAUTHORIZED) # token, created = Token.objects.get_or_create(user=customer.user) # serializer = UserSerializer(customer.user) # return Response({'token': token.key, 'user': serializer.data}) # @api_view(['POST']) # def login(request): # try: # customer = Customer.objects.get(mobile_number=request.data['mobile_number']) # except Customer.DoesNotExist: # return Response({ # "status": 401, # "data": {}, # "message": "موبایل یا پسورد غلط است" # }, status=status.HTTP_401_UNAUTHORIZED) # if not customer.user.check_password(request.data['password']): # return Response({ # "status": 401, # "data": {}, # "message": "موبایل یا پسورد غلط است" # }, status=status.HTTP_401_UNAUTHORIZED) # token, created = Token.objects.get_or_create(user=customer.user) # serializer = UserSerializer(customer.user) # return Response({ # "status": 200, # "data": { # "token": token.key, # "user": serializer.data # }, # "message": "ورود با موفقیت انجام شد" # }, status=status.HTTP_200_OK) @api_view(['POST']) def login(request): mobile_number = request.data.get('mobile_number') password = request.data.get('password') if not mobile_number or not password: return Response({ "status": 403, "data": {}, "message": "برای ورود نیاز به شماره موبایل و پسورد است" }, status=status.HTTP_401_UNAUTHORIZED) try: customer = Customer.objects.get(mobile_number=mobile_number) except Customer.DoesNotExist: return Response({ "status": 401, "data": {}, "message": "موبایل یا پسورد غلط است" }, status=status.HTTP_401_UNAUTHORIZED) if not customer.user.check_password(password): return Response({ "status": 401, "data": {}, "message": "موبایل یا پسورد غلط است" }, status=status.HTTP_401_UNAUTHORIZED) token, created = Token.objects.get_or_create(user=customer.user) serializer = UserSerializer(customer.user) return Response({ "status": 200, "data": { "token": token.key, "user": serializer.data }, "message": "ورود با موفقیت انجام شد" }, status=status.HTTP_200_OK) @api_view(['GET']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def sendSmsVerification(request): # Retrieve the current user user = request.user # Assuming a OneToOneField relation between User and Customer try: # Retrieve the associated customer object customer = Customer.objects.get(user=user) # Generate a random verification code verification_code = str(random.randint(100000, 999999)) # Update user's verification_code and sms_time_for_valid customer.verification_sms_code = verification_code customer.sms_time_for_valid = datetime.now() + timedelta(minutes=10) # Set validity time to now + 10 minutes customer.save() sms_response = send_sms(customer.mobile_number, verification_code) # Send SMS with verification code (implement this part according to your SMS service provider's API) # send_sms(user.mobile_number, verification_code) # You need to implement this function return Response({ "message": "SMS verification code sent successfully.", "sms_response": sms_response }) except Customer.DoesNotExist: # If no customer object exists for the user, return an error response return Response({'error': 'No customer data found for this user'}, status=404) @api_view(['GET']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def getInfo(request): user = request.user try: customer = Customer.objects.get(user=user) user_images = Image.objects.filter(user=user).order_by('-created_at') user_pdfs = Pdf.objects.filter(user=user).order_by('-created_at') user_videos = Video.objects.filter(user=user).order_by('-created_at') user_glbs = Glb.objects.filter(user=user).order_by('-created_at') customer_serializer = CustomerSerializer(customer) image_serializer = ImageSerializer(user_images, many=True) pdf_serializer = PdfSerializer(user_pdfs, many=True) video_serializer = VideoSerializer(user_videos, many=True) glb_serializer = GlbSerializer(user_glbs, many=True) user_data = { 'id': user.id, 'first_name': user.first_name, 'last_name': user.last_name, } return Response({ 'status': 200, 'data': { 'customer': customer_serializer.data, 'user': user_data, 'images': image_serializer.data, 'pdfs': pdf_serializer.data, 'videos': video_serializer.data, 'glbs': glb_serializer.data, }, 'message': 'موفق' }, status=status.HTTP_200_OK) except Customer.DoesNotExist: return Response({ 'status': 404, 'data': {}, 'message': 'اطلاعات مشتری یافت نشد' }, status=status.HTTP_404_NOT_FOUND) @api_view(['GET']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def sendEmailVerification(request): # Retrieve the current user user = request.user # Assuming a OneToOneField relation between User and Customer try: # Retrieve the associated customer object customer = Customer.objects.get(user=user) # Generate a random verification code verification_code = str(random.randint(100000, 999999)) # Update user's verification_code and sms_time_for_valid customer.verification_email_code = verification_code customer.save() sendEmail(user.email,verification_code) return Response({"message": ("Email verification code sent successfully. " + user.email)}) except Customer.DoesNotExist: # If no customer object exists for the user, return an error response return Response({'error': 'No customer data found for this user'}, status=404) def sendEmail(email, verification_code): subject = 'WZK Bestätigungscode' context = {'verification_code': verification_code} # Render HTML content from a template # html_content = render_to_string('core/templates/emails/email_template.html', context) html_content = render_to_string('emails/verification_email_template2.html', context) # Create a plain text version of the email (optional) text_content = strip_tags(html_content) email_from = settings.DEFAULT_FROM_EMAIL recipient_list = [email] try: # Create an EmailMultiAlternatives object msg = EmailMultiAlternatives(subject, text_content, email_from, recipient_list) # Attach the HTML content to the email msg.attach_alternative(html_content, "text/html") # Send the email msg.send() print("Email has been sent! ") return True except Exception as e: print(f"Error sending email: {e}") return False @api_view(['POST']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def submitEmailVerification(request): try: user = request.user customer = Customer.objects.get(user=user) if customer.verification_email_code == request.data['verification_email_code'] : customer.is_email_verified = True customer.save() return Response({"message": "Email Verified!"}) # else : # return Response({"message": customer.verification_email_code}) except get_user_model().DoesNotExist: return Response("Not verified 1", status=status.HTTP_404_NOT_FOUND) return Response("Not verified ", status=status.HTTP_404_NOT_FOUND) @api_view(['POST']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def submitSmsVerification(request): try: user = request.user customer = Customer.objects.get(user=user) if customer.verification_sms_code == request.data['verification_sms_code'] : customer.is_sms_verified = True customer.save() return Response({"message": "SMS Verified!"}) # else : # return Response({"message": customer.verification_email_code}) except get_user_model().DoesNotExist: return Response("Not verified 1", status=status.HTTP_404_NOT_FOUND) return Response("Not verified ", status=status.HTTP_404_NOT_FOUND) # @api_view(['GET']) # @authentication_classes([SessionAuthentication, TokenAuthentication]) # @permission_classes([IsAuthenticated]) # def test_token(request): # if not user_has_role(request.user, 'admin'): # return Response({'message': 'No access'}, status=status.HTTP_403_FORBIDDEN) # return Response({'message': 'User has admin role'}) @api_view(['GET']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def test_token(request): if not user_has_role(request.user, 'admin'): return Response({ "status": 403, "data": {}, "message": "دسترسی غیرمجاز" }, status=status.HTTP_403_FORBIDDEN) return Response({ "status": 200, "data": { "username": request.user.username }, "message": "موفق" }, status=status.HTTP_200_OK) @api_view(['POST']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def upload_image(request): user = request.user try: customer = Customer.objects.get(user=user) except Customer.DoesNotExist: return Response( {'error': 'No customer profile found.'}, status=status.HTTP_403_FORBIDDEN ) if not request.FILES.get('image'): return Response( {'error': 'No image file provided.'}, status=status.HTTP_400_BAD_REQUEST ) uploaded_file = request.FILES['image'] # Generate the new path: "2025/1/23/filename.jpg" today = datetime.now() year = str(today.year) month = str(today.month) day = str(today.day) # New path format: "2025/1/23/original_filename.jpg" new_path = os.path.join(year, month, day, uploaded_file.name) # Save the file manually to the desired directory saved_path = default_storage.save(new_path, uploaded_file) # Now create the Image record with the new path image = Image.objects.create( user=user, image=saved_path, # This will be "2025/1/23/filename.jpg" name=request.data.get('name', uploaded_file.name), ) serializer = ImageSerializer(image) return Response(serializer.data, status=status.HTTP_201_CREATED) @api_view(['POST']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def upload_glb(request): user = request.user try: customer = Customer.objects.get(user=user) except Customer.DoesNotExist: return Response( {'error': 'No customer profile found.'}, status=status.HTTP_403_FORBIDDEN ) if not request.FILES.get('glb'): return Response( {'error': 'No glb file provided.'}, status=status.HTTP_400_BAD_REQUEST ) uploaded_file = request.FILES['glb'] # Generate the new path: "2025/1/23/filename.jpg" today = datetime.now() year = str(today.year) month = str(today.month) day = str(today.day) # New path format: "2025/1/23/original_filename.jpg" new_path = os.path.join(year, month, day, uploaded_file.name) # Save the file manually to the desired directory saved_path = default_storage.save(new_path, uploaded_file) glb = Glb.objects.create( user=user, glb=saved_path, # This will be "2025/1/23/filename.jpg" name=request.data.get('name', uploaded_file.name), ) serializer = GlbSerializer(glb) return Response(serializer.data, status=status.HTTP_201_CREATED) @api_view(['POST']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def upload_video(request): user = request.user try: customer = Customer.objects.get(user=user) except Customer.DoesNotExist: return Response( {'error': 'No customer profile found.'}, status=status.HTTP_403_FORBIDDEN ) if not request.FILES.get('video'): return Response( {'error': 'No video file provided.'}, status=status.HTTP_400_BAD_REQUEST ) uploaded_file = request.FILES['video'] # Generate the new path: "2025/1/23/filename.jpg" today = datetime.now() year = str(today.year) month = str(today.month) day = str(today.day) # New path format: "2025/1/23/original_filename.jpg" new_path = os.path.join(year, month, day, uploaded_file.name) # Save the file manually to the desired directory saved_path = default_storage.save(new_path, uploaded_file) video = Video.objects.create( user=user, video=saved_path, # This will be "2025/1/23/filename.jpg" name=request.data.get('name', uploaded_file.name), ) serializer = VideoSerializer(video) return Response(serializer.data, status=status.HTTP_201_CREATED) @api_view(['POST']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def upload_pdf(request): user = request.user try: customer = Customer.objects.get(user=user) except Customer.DoesNotExist: return Response( {'error': 'No customer profile found.'}, status=status.HTTP_403_FORBIDDEN ) if not request.FILES.get('pdf'): return Response( {'error': 'No pdf file provided.'}, status=status.HTTP_400_BAD_REQUEST ) uploaded_file = request.FILES['pdf'] # Generate the new path: "2025/1/23/filename.jpg" today = datetime.now() year = str(today.year) month = str(today.month) day = str(today.day) # New path format: "2025/1/23/original_filename.jpg" new_path = os.path.join(year, month, day, uploaded_file.name) # Save the file manually to the desired directory saved_path = default_storage.save(new_path, uploaded_file) pdf = Pdf.objects.create( user=user, pdf=saved_path, # This will be "2025/1/23/filename.jpg" name=request.data.get('name', uploaded_file.name), ) serializer = GlbSerializer(pdf) return Response(serializer.data, status=status.HTTP_201_CREATED) from django.core.files.storage import default_storage from datetime import datetime import os from django.core.files.uploadedfile import UploadedFile, InMemoryUploadedFile @api_view(['POST']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def editProfile(request): user = request.user try: customer = Customer.objects.get(user=user) except Customer.DoesNotExist: return Response({'error': 'Customer profile not found'}, status=status.HTTP_404_NOT_FOUND) # Update user fields if 'first_name' in request.data: user.first_name = request.data['first_name'] if 'last_name' in request.data: user.last_name = request.data['last_name'] if 'seamt' in request.data: customer.seamt = request.data['seamt'] # Initialize customer data dict customer_data = {} # Handle mobile number update if 'mobile_number' in request.data: if User.objects.exclude(pk=user.pk).filter(username=request.data['mobile_number']).exists(): return Response({'mobile_number': ['This mobile number is already in use.']}, status=status.HTTP_400_BAD_REQUEST) user.username = request.data['mobile_number'] customer_data['mobile_number'] = request.data['mobile_number'] # Handle mobile number update if 'profile_glb_url' in request.data: customer_data['profile_glb'] = request.data['profile_glb_url'] # Handle profile image upload if 'profile_img' in request.FILES: uploaded_img = request.FILES['profile_img'] today = datetime.now() img_path = os.path.join( str(today.year), str(today.month), str(today.day), f"profile_img_{user.id}_{uploaded_img.name}" ) saved_img_path = default_storage.save(img_path, uploaded_img) customer_data['profile_img'] = saved_img_path # Delete old image if it exists if customer.profile_img: try: default_storage.delete(customer.profile_img) except: pass # Handle profile GLB upload if 'profile_glb' in request.FILES: uploaded_glb = request.FILES['profile_glb'] today = datetime.now() glb_path = os.path.join( str(today.year), str(today.month), str(today.day), f"profile_glb_{user.id}_{uploaded_glb.name}" ) saved_glb_path = default_storage.save(glb_path, uploaded_glb) customer_data['profile_glb'] = saved_glb_path # Delete old GLB if it exists if customer.profile_glb: try: default_storage.delete(customer.profile_glb) except: pass # Also allow text-based updates (in case client sends path instead of file) if 'profile_img' in request.data and not isinstance(request.data['profile_img'], (UploadedFile, InMemoryUploadedFile)): customer_data['profile_img'] = request.data['profile_img'] if 'profile_glb' in request.data and not isinstance(request.data['profile_glb'], (UploadedFile, InMemoryUploadedFile)): customer_data['profile_glb'] = request.data['profile_glb'] # Serialize and validate customer data customer_serializer = CustomerSerializer(customer, data=customer_data, partial=True) if customer_serializer.is_valid(): user.save() customer_serializer.save() user_serializer = UserSerializer(user) return Response({ 'user': user_serializer.data, 'customer': customer_serializer.data }, status=status.HTTP_200_OK) else: return Response(customer_serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(['POST']) @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def resetPassword(request): user = request.user # Validate required fields if 'old_password' not in request.data or 'new_password' not in request.data: return Response( {'error': 'Both old_password and new_password are required'}, status=status.HTTP_400_BAD_REQUEST ) old_password = request.data['old_password'] new_password = request.data['new_password'] # Verify old password if not user.check_password(old_password): return Response( {'old_password': ['Wrong password.']}, status=status.HTTP_400_BAD_REQUEST ) # Set new password user.set_password(new_password) user.save() # If using JWT, you might want to blacklist the old token here # and optionally return a new token return Response({'message': 'Password updated successfully'}, status=status.HTTP_200_OK) def generate_code(length=6): """Generate a random verification code.""" return ''.join(random.choices(string.digits, k=length)) @api_view(['POST']) def requestResetCode(request): """ Request a password reset code for the given mobile number. Expects: {'mobile_number': 'string'} Returns: {'success': bool, 'message': 'string'} """ mobile_number = request.data.get('mobile_number') if not mobile_number: return Response( {'success': False, 'message': 'Mobile number is required'}, status=status.HTTP_400_BAD_REQUEST ) # Check if customer exists with the mobile number customer = Customer.objects.get(mobile_number=mobile_number) user = customer.user # Get the associated User # Generate verification code code = generate_code() # Store code in cache with 10-minute expiration cache_key = f"reset_code_{mobile_number}" cache.set(cache_key, code, timeout=600) # Send code via SMS sms_result = send_sms(mobile_number, code) if sms_result == 0: return Response( {'success': False, 'message': sms_result['message']}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) return Response( {'success': True, 'message': 'Verification code sent successfully'}, status=status.HTTP_200_OK ) @api_view(['POST']) def verifyResetCode(request): """ Verify the reset code and update the password. Expects: {'mobile_number': 'string', 'code': 'string', 'password': 'string'} Returns: {'success': bool, 'message': 'string'} """ mobile_number = request.data.get('mobile_number') code = request.data.get('code') new_password = request.data.get('password') if not all([mobile_number, code, new_password]): return Response( {'success': False, 'message': 'Mobile number, code, and new password are required'}, status=status.HTTP_400_BAD_REQUEST ) try: # Retrieve customer and associated user customer = Customer.objects.get(mobile_number=mobile_number) user = customer.user # Get the associated User # Check cached code cache_key = f"reset_code_{mobile_number}" stored_code = cache.get(cache_key) if not stored_code: return Response( {'success': False, 'message': 'Code has expired or is invalid'}, status=status.HTTP_400_BAD_REQUEST ) if stored_code != code: return Response( {'success': False, 'message': 'Invalid verification code'}, status=status.HTTP_400_BAD_REQUEST ) # Validate password (basic example; add more validation as needed) if len(new_password) < 6: return Response( {'success': False, 'message': 'Password must be at least 8 characters long'}, status=status.HTTP_400_BAD_REQUEST ) # Update password print(new_password) user.set_password(new_password) user.save() # Clear the cache cache.delete(cache_key) return Response( {'success': True, 'message': 'Password reset successfully'}, status=status.HTTP_200_OK ) except Customer.DoesNotExist: return Response( {'success': False, 'message': 'No user found with this mobile number'}, status=status.HTTP_404_NOT_FOUND ) except Exception as e: return Response( {'success': False, 'message': f'Error resetting password: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR )