web_defender/otpverification/views.py
2024-12-09 13:43:16 +05:30

728 lines
32 KiB
Python

from django.http import JsonResponse
from django.contrib.auth import get_user_model, login
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
import json
import random
import smtplib
from datetime import datetime, timedelta
from django.conf import settings
from django.utils import timezone
from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User
from Accounts.models import UserProfile
from Device.models import Devices
from .models import CheckDevice ,OTPVerification ,DeviceDetails
# @csrf_exempt
# def check_device_view(request):
# if request.method == 'POST':
# try:
# # Check if the body is empty
# if not request.body:
# return JsonResponse({'error': 'Empty request body'}, status=400)
# # Parse the JSON data from the request body
# try:
# data = json.loads(request.body)
# except json.JSONDecodeError as e:
# return JsonResponse({'error': 'Invalid JSON format', 'details': str(e)}, status=400)
# # Retrieve required fields from the parsed JSON
# user_profile_id = data.get('user_profile')
# unique_id = data.get('unique_id')
# mac_address = data.get('mac_address') # Get the MAC address
# # Validate that required fields are provided
# if not user_profile_id or not unique_id or not mac_address:
# return JsonResponse({'error': 'Missing required fields: user_profile, unique_id, or mac_address'}, status=400)
# # Check if the device is already registered for this user using unique_id and mac_address
# existing_device = CheckDevice.objects.filter(
# user_profile_id=user_profile_id,
# device__unique_id=unique_id,
# device__mac_address=mac_address # Assuming you have a mac_address field
# ).first()
# if existing_device:
# return JsonResponse({
# "message": "Device is already registered.",
# "device_info": {
# "unique_id": existing_device.device.unique_id,
# "mac_address": existing_device.device.mac_address, # Include MAC address
# "user_profile_id": existing_device.user_profile_id,
# "registered_at": existing_device.registered_at
# }
# }, status=200)
# else:
# return JsonResponse({'message': 'You have to register.'}, status=201)
# except Exception as e:
# return JsonResponse({'error': str(e)}, status=500)
# elif request.method == 'GET':
# try:
# # Get all records from CheckDevice table
# all_devices = CheckDevice.objects.all()
# print(all_devices)
# # Serialize the data
# device_data = []
# for device in all_devices:
# device_data.append({
# "unique_id": device.device.unique_id,
# "mac_address": device.device.mac_address,
# "user_profile_id": device.user_profile_id,
# "registered_at": device.registered_at
# })
# # Return the serialized data
# return JsonResponse({"all_devices": device_data}, status=200)
# except Exception as e:
# return JsonResponse({'error': str(e)}, status=500)
@csrf_exempt
def check_device_view(request):
if request.method == 'POST':
try:
# Check if the body is empty
if not request.body:
return JsonResponse({'error': 'Empty request body'}, status=400)
# Parse the JSON data from the request body
try:
data = json.loads(request.body)
except json.JSONDecodeError as e:
return JsonResponse({'error': 'Invalid JSON format', 'details': str(e)}, status=400)
# Retrieve required fields from the parsed JSON
user_id = data.get('user_id') # Get the user ID
unique_id = data.get('unique_id') # Get the unique ID
mac_address = data.get('mac_address') # Get the MAC address
# Validate that required fields are provided
if not user_id or not unique_id or not mac_address:
return JsonResponse({'error': 'Missing required fields: user_id, unique_id, or mac_address'}, status=400)
# Fetch the user profile using the user ID
try:
user = User.objects.get(id=user_id) # Fetch the User instance based on user_id
user_profile = UserProfile.objects.get(user=user) # Fetch the UserProfile based on the User
except User.DoesNotExist:
return JsonResponse({'error': 'User not found'}, status=404)
except UserProfile.DoesNotExist:
return JsonResponse({'error': 'UserProfile not found'}, status=404)
# Check if the device is already registered for this user using unique_id and mac_address
existing_device = CheckDevice.objects.filter(
user_profile=user_profile, # Filter by UserProfile instance
device__unique_id=unique_id,
device__mac_address=mac_address
).first()
if existing_device:
return JsonResponse({
"message": "Device is already registered.",
"device_info": {
"unique_id": existing_device.device.unique_id,
"mac_address": existing_device.device.mac_address,
"user_profile_id": existing_device.user_profile_id,
"registered_at": existing_device.registered_at
}
}, status=200)
else:
return JsonResponse({'message': 'You have to register.'}, status=201)
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
elif request.method == 'GET':
try:
# Get all records from CheckDevice table
all_devices = CheckDevice.objects.all()
# Serialize the data
device_data = []
for device in all_devices:
device_data.append({
"unique_id": device.device.unique_id,
"mac_address": device.device.mac_address,
"user_profile_id": device.user_profile_id,
"registered_at": device.registered_at
})
# Return the serialized data
return JsonResponse({"all_devices": device_data}, status=200)
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
#====================================================================================================================================================================================
def send_otp_to_email(email):
otp = str(random.randint(100000, 999999)) # Generate 6-digit OTP
# Prepare the email message
message = f"Subject: Your OTP Code\n\nYour OTP is {otp}"
try:
sender_email = settings.EMAIL_HOST_USER
sender_password = settings.EMAIL_HOST_PASSWORD
# SMTP setup
server = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT)
server.starttls() # Start TLS encryption
server.login(sender_email, sender_password)
server.sendmail(sender_email, email, message)
server.quit()
return otp # Return OTP for further processing
except Exception as e:
print(f"Failed to send OTP: {e}")
return None
#=================================================================================================
# Generate a unique 6-digit OTP (for mapping)
def generate_server_otp():
return random.randint(100000, 999999)
#================================================================================================
# @csrf_exempt
# def send_otp(request):
# if request.method == 'POST':
# try:
# # Access the email from form data
# email = request.POST.get('email')
# # Validate that the email is provided
# if not email:
# return JsonResponse({'error': 'Email is required'}, status=400)
# # # Fetch the user by email
# # user = get_object_or_404(UserProfile, email=email)
# # Send OTP to email
# if send_otp_to_email(email):
# return JsonResponse({"message": "OTP sent to email"}, status=200)
# else:
# return JsonResponse({"error": "Failed to send OTP"}, status=500)
# except Exception as e:
# return JsonResponse({"error": str(e)}, status=500)
# return JsonResponse({"error": "Invalid request method"}, status=405)
@csrf_exempt
def send_otp(request):
if request.method == 'POST':
try:
# Access the email from form data
email = request.POST.get('email')
# Validate that the email is provided
if not email:
return JsonResponse({'error': 'Email is required'}, status=400)
# Send OTP to email
otp = send_otp_to_email(email)
if otp:
# Create an OTPVerification entry with the email and OTP code
OTPVerification.objects.create(email=email, otp_code=otp)
return JsonResponse({"message": "OTP sent to email"}, status=200)
else:
return JsonResponse({"error": "Failed to send OTP"}, status=500)
except Exception as e:
return JsonResponse({"error": str(e)}, status=500)
return JsonResponse({"error": "Invalid request method"}, status=405)
#========================================================================================================================================
@csrf_exempt
def re_registration(request):
if request.method == 'POST':
try:
# Access the email from form data
email = request.POST.get('email')
# Validate that the email is provided
if not email:
return JsonResponse({'error': 'Email is required'}, status=400)
# Fetch the user by email
user = get_object_or_404(UserProfile, email=email)
# You can add additional logic here if needed for re-registration
# Send OTP to email
if send_otp_to_email(email, user):
return JsonResponse({"message": "OTP sent for re-registration to email"}, status=200)
else:
return JsonResponse({"error": "Failed to send OTP"}, status=500)
except Exception as e:
return JsonResponse({"error": str(e)}, status=500)
return JsonResponse({"error": "Invalid request method"}, status=405)
#==================================================================================================================================
# @csrf_exempt
# def verify_otp(request):
# if request.method == 'POST':
# try:
# # Retrieve email and otp_code from POST request
# email = request.POST.get('email')
# otp_code = request.POST.get('otp_code')
# # Debugging: Print email and OTP code received
# print(f"Email: {email}, OTP Code: {otp_code}")
# # Validate that both fields are provided
# if not email or not otp_code:
# return JsonResponse({'error': 'Email and OTP code are required'}, status=400)
# # Retrieve the most recent OTPVerification entry for the email
# otp_verification = OTPVerification.objects.filter(email=email).order_by('-created_at').first()
# # If an OTP exists, debug its stored values
# if otp_verification:
# print(f"Stored OTP: {otp_verification.otp_code}, Is Valid: {otp_verification.is_valid}")
# # Check if the OTP exists, matches the submitted OTP, and is valid
# if otp_verification and str(otp_verification.otp_code) == str(otp_code) and otp_verification.is_valid:
# # Mark the OTP as used (is_valid = False)
# otp_verification.is_valid = False
# otp_verification.save()
# return JsonResponse({"message": "OTP verified successfully"}, status=200)
# else:
# return JsonResponse({"error": "Invalid or expired OTP"}, status=400)
# except Exception as e:
# return JsonResponse({"error": str(e)}, status=500)
# return JsonResponse({"error": "Invalid request method"}, status=405)
@csrf_exempt
def verify_otp(request):
if request.method == 'POST':
try:
# Retrieve email and otp_code from POST request
email = request.POST.get('email')
otp_code = request.POST.get('otp_code')
# Debugging: Print email and OTP code received
print(f"Email: {email}, OTP Code: {otp_code}")
# Validate that both fields are provided
if not email or not otp_code:
return JsonResponse({'error': 'Email and OTP code are required'}, status=400)
# Retrieve the most recent OTPVerification entry for the email
otp_verification = OTPVerification.objects.filter(email=email).order_by('-created_at').first()
# If an OTP exists, debug its stored values
if otp_verification:
print(f"Stored OTP: {otp_verification.otp_code}, Is Valid: {otp_verification.is_valid}, Is Expired: {otp_verification.is_expired()}")
# Check if the OTP exists, matches the submitted OTP, and is valid, and not expired
if (otp_verification and
str(otp_verification.otp_code) == str(otp_code) and
otp_verification.is_valid and
not otp_verification.is_expired()):
# Mark the OTP as used (is_valid = False)
otp_verification.is_valid = False
otp_verification.save()
return JsonResponse({"message": "OTP verified successfully"}, status=200)
else:
return JsonResponse({"error": "Invalid or expired OTP"}, status=400)
except Exception as e:
return JsonResponse({"error": str(e)}, status=500)
return JsonResponse({"error": "Invalid request method"}, status=405)
#====================================================================================================================================
@csrf_exempt
def register_device(request):
if request.method == 'POST':
try:
print("Received POST request")
if not request.POST:
print("Request body is empty")
return JsonResponse({'error': 'Empty request body'}, status=400)
print(f"Request data: {request.POST}")
# Retrieve required fields from the form data
user_profile_id = int(request.POST.get('user_profile_id')) # Convert to int
mac_address = request.POST.get('mac_address')
unique_id = request.POST.get('unique_id')
print(f"user_profile_id: {user_profile_id}, mac_address: {mac_address}, unique_id: {unique_id}")
# Convert user_profile_id to an integer
user_profile_id = int(user_profile_id)
print(f"User Profile ID (as integer): {user_profile_id}, Type: {type(user_profile_id)}")
# Validate that required fields are provided
if not user_profile_id or not mac_address or not unique_id:
print("Missing required fields")
return JsonResponse({'error': 'Missing required fields: user_profile_id, mac_address, or unique_id'}, status=400)
print(f"All UserProfiles: {UserProfile.objects.all()}") # Print all UserProfiles
print(f"UserProfile count: {UserProfile.objects.count()}") # Count of UserProfiles
# Fetch the user profile by ID
print(f"Fetching UserProfile with ID: {user_profile_id}")
user_profile = get_object_or_404(UserProfile, id=user_profile_id)
print(f"UserProfile found: {user_profile}")
# Create or fetch the device instance
print(f"Fetching or creating device with MAC address: {mac_address}")
device, created = Devices.objects.get_or_create(
mac_address=mac_address,
defaults={'unique_id': unique_id}
)
if created:
print(f"New device created with unique_id: {unique_id}")
else:
print(f"Existing device found with MAC address: {mac_address}")
# Create a CheckDevice entry
print("Creating CheckDevice entry")
check_device = CheckDevice.objects.create(user_profile=user_profile, device=device)
print("Device registered successfully")
return JsonResponse({
'message': 'Device registered successfully.',
'device_info': {
'unique_id': check_device.device.unique_id,
'mac_address': check_device.device.mac_address,
'registered_at': check_device.registered_at
}
}, status=201)
except Exception as e:
print(f"Error: {str(e)}")
return JsonResponse({'error': str(e)}, status=500)
print("Invalid request method")
return JsonResponse({'error': 'Invalid request method'}, status=405)
#========================================================================================================================
@csrf_exempt
# def generate_second_otp(request):
# if request.method == 'POST':
# # Extract the email from request parameters (query string)
# email = request.POST.get('email')
# if not email:
# return JsonResponse({'error': 'Email is required'}, status=400)
# try:
# # Fetch the associated UserProfile instance by email
# user_profile = UserProfile.objects.get(email=email)
# # Generate the second OTP
# second_otp = generate_server_otp()
# # Save the OTP to the OTPVerification model
# otp_verification = OTPVerification.objects.create(
# email=user_profile, # Set the foreign key relation to UserProfile
# second_otp=second_otp
# )
# return JsonResponse({
# 'second_otp': otp_verification.second_otp,
# 'message': 'Second OTP generated and saved successfully.'
# }, status=200)
# except UserProfile.DoesNotExist:
# return JsonResponse({'error': 'UserProfile not found'}, status=404)
def generate_second_otp(request):
if request.method == 'POST':
email = request.POST.get('email')
try:
# Get the user object by email
user = User.objects.get(email=email)
# Get the user profile associated with this user
user_profile = UserProfile.objects.get(user=user)
# Logic to generate the second OTP
second_otp = generate_server_otp() # Example OTP generation logic
# Create a new OTPVerification record
otp_record = OTPVerification(
user_profile=user_profile,
second_otp=second_otp,
is_valid=True,
created_at=timezone.now() # Set current time as created time
)
otp_record.save() # Save the record to the database
# Send the second OTP and user profile ID in the response
return JsonResponse({
"second_otp": second_otp,
"user_profile_id": user_profile.id # Return the user profile ID
})
except User.DoesNotExist:
return JsonResponse({"error": "User not found."}, status=404)
except UserProfile.DoesNotExist:
return JsonResponse({'error': 'UserProfile not found'}, status=404)
return JsonResponse({"error": "Invalid request method."}, status=405)
#============================================================================================================================
# @csrf_exempt
# def verify_second_otp(request):
# if request.method == 'POST':
# second_otp = request.POST.get('second_otp')
# print(second_otp)
# if not second_otp:
# return JsonResponse({"error": "Second OTP is required"}, status=400)
# # Find the OTP record with the provided second OTP and that is still valid
# otp_record = OTPVerification.objects.filter(second_otp=second_otp, is_valid=True).first()
# print(otp_record)
# if otp_record:
# # Check if OTP is not older than 10 minutes
# if otp_record.created_at >= (timezone.now() - timedelta(minutes=10)):
# # Mark OTP as used (invalid)
# otp_record.is_valid = False
# otp_record.save()
# return JsonResponse({"message": "Second OTP is valid"}, status=200)
# else:
# return JsonResponse({"error": "OTP expired"}, status=400)
# else:
# return JsonResponse({"error": "Invalid or used Second OTP"}, status=400)
# return JsonResponse({"error": "Invalid request method"}, status=405)
@csrf_exempt
def verify_second_otp(request):
if request.method == 'POST':
second_otp = request.POST.get('second_otp')
if not second_otp:
return JsonResponse({"error": "Second OTP is required"}, status=400)
# Find the OTP record with the provided second OTP and that is still valid
otp_record = OTPVerification.objects.filter(second_otp=second_otp, is_valid=True).first()
if otp_record:
# Check if OTP is not older than 10 minutes
if otp_record.created_at >= (timezone.now() - timedelta(minutes=10)):
# Mark OTP as used (invalid)
otp_record.is_valid = False
otp_record.save()
if otp_record.user_profile:
# Return the user_profile_id from the OTP record
return JsonResponse({
"message": "Second OTP is valid",
"user_profile_id": otp_record.user_profile.user.id
}, status=200)
else:
return JsonResponse({"error": "No user profile associated with this OTP record."}, status=400)
else:
return JsonResponse({"error": "OTP expired"}, status=400)
else:
return JsonResponse({"error": "Invalid or used Second OTP"}, status=400)
return JsonResponse({"error": "Invalid request method"}, status=405)
#===============================================================================================================================================
# @csrf_exempt # Disable CSRF protection; use with caution
# def send_device_info(request):
# if request.method == 'POST':
# second_otp = request.POST.get('second_otp')
# email = request.POST.get('email')
# if not second_otp or not email :
# return JsonResponse({"error": "Second OTP, email, and are required"}, status=400)
# try:
# # Extract data from the request body
# user_id = request.POST.get('user_id') # This should be the User ID, not UserProfile ID
# mac_address = request.POST.get('mac_address') # Extract mac_address from the request
# unique_id = request.POST.get('unique_id') # Extract unique_id from the request
# # Fetch the user instance directly from User model
# user = User.objects.get(id=user_id) # Retrieve User instance based on user_id
# # Fetch the user profile based on the user instance
# user_profile = UserProfile.objects.get(user=user) # Retrieve UserProfile based on the user instance
# # Create or fetch the device instance
# print(f"Fetching or creating device with MAC address: {mac_address}")
# device, created = Devices.objects.get_or_create(
# mac_address=mac_address,
# defaults={'unique_id': unique_id,
# 'used_by': user_profile } # Set the used_by field to the current user profile
# )
# if created:
# print(f"New device created with unique_id: {unique_id}")
# else:
# print(f"Existing device found with MAC address: {mac_address}")
# # Create a CheckDevice entry
# print("Creating CheckDevice entry")
# check_device = CheckDevice.objects.create(
# user_profile=user_profile,
# device=device,
# registered_at=timezone.now() # Automatically set the registration time
# )
# # Prepare a response with the created device info
# response_data = {
# 'user_id': check_device.user_profile.user.id,
# 'mac_address': check_device.mac_address,
# 'unique_id': check_device.unique_id,
# }
# return JsonResponse(response_data, status=201) # Return success response with created device info
# except UserProfile.DoesNotExist:
# return JsonResponse({"error": "UserProfile not found"}, status=404)
# return JsonResponse({"error": "Invalid request method"}, status=405)
#==============================================================================================================================================
# @csrf_exempt # Disable CSRF protection; use with caution
# def send_device_info(request):
# if request.method == 'POST':
# try:
# # Extract data from the request body
# data = json.loads(request.body) # Parse the incoming JSON data
# user_id = data.get('user_id') # Get the User ID
# mac_address = data.get('mac_address') # Get the MAC address
# unique_id = data.get('unique_id') # Get the Unique ID
# # Validate that required fields are provided
# if not user_id or not mac_address or not unique_id:
# return JsonResponse({'error': 'Missing required fields: user_id, mac_address, or unique_id'}, status=400)
# # Fetch the user instance directly from User model
# user = User.objects.get(id=user_id) # Retrieve User instance based on user_id
# print (user)
# # Fetch the user profile based on the user instance
# user_profile = UserProfile.objects.get(user=user) # Retrieve UserProfile based on the user instance
# print(user_profile)
# # Create or fetch the device instance
# device, created = Devices.objects.get_or_create(
# mac_address=mac_address,
# defaults={'unique_id': unique_id,
# 'used_by': user_profile} # Set the used_by field to the current user profile
# )
# # Create a CheckDevice entry with user.id directly
# check_device = CheckDevice.objects.create(
# user_profile=user_profile, # This still references the UserProfile
# device=device,
# registered_at=timezone.now() # Automatically set the registration time
# )
# # Prepare a response with the created device info
# response_data = {
# 'user_id': user.id, # Include the User ID from the User model
# 'user_profile_id': user_profile.id, # Include the UserProfile ID # Include the User ID
# 'mac_address': device.mac_address, # Get MAC address from the device
# 'unique_id': device.unique_id, # Get Unique ID from the device
# 'registered_at': check_device.registered_at, # Include registration timestamp
# }
# return JsonResponse(response_data, status=200
# ) # Return success response with created device info
# except UserProfile.DoesNotExist:
# return JsonResponse({'error': 'UserProfile not found'}, status=404)
# except User.DoesNotExist:
# return JsonResponse({'error': 'User not found'}, status=404)
# except json.JSONDecodeError:
# return JsonResponse({'error': 'Invalid JSON format'}, status=400)
# except Exception as e:
# return JsonResponse({'error': str(e)}, status=500) # Return error message for any other exceptions
# return JsonResponse({'error': 'Invalid request method'}, status=405)
@csrf_exempt # Disable CSRF protection; use with caution
def send_device_info(request):
if request.method == 'POST':
try:
# Extract data from the request body
data = json.loads(request.body) # Parse the incoming JSON data
user_profile_id = data.get('user_profile_id') # Get the User Profile ID
mac_address = data.get('mac_address') # Get the MAC address
unique_id = data.get('unique_id') # Get the Unique ID
# Validate that required fields are provided
if not user_profile_id or not mac_address or not unique_id:
return JsonResponse({'error': 'Missing required fields: user_profile_id, mac_address, or unique_id'}, status=400)
# Fetch the user profile directly from UserProfile model
user_profile = UserProfile.objects.get(id=user_profile_id) # Retrieve UserProfile instance based on user_profile_id
# Print for debugging
print(user_profile)
# Create or fetch the device instance
device, created = Devices.objects.get_or_create(
mac_address=mac_address,
defaults={'unique_id': unique_id,
'used_by': user_profile} # Set the used_by field to the current user profile
)
# Create a CheckDevice entry with user_profile directly
check_device = CheckDevice.objects.create(
user_profile=user_profile, # This references the UserProfile
device=device,
registered_at=timezone.now() # Automatically set the registration time
)
# Prepare a response with the created device info
response_data = {
'user_profile_id': user_profile.id, # Include the UserProfile ID
'mac_address': device.mac_address, # Get MAC address from the device
'unique_id': device.unique_id, # Get Unique ID from the device
'registered_at': check_device.registered_at, # Include registration timestamp
}
return JsonResponse(response_data, status=200) # Return success response with created device info
except UserProfile.DoesNotExist:
return JsonResponse({'error': 'UserProfile not found'}, status=404)
except json.JSONDecodeError:
return JsonResponse({'error': 'Invalid JSON format'}, status=400)
except Exception as e:
return JsonResponse({'error': str(e)}, status=500) # Return error message for any other exceptions
return JsonResponse({'error': 'Invalid request method'}, status=405)
def get_user_id(request):
user_id = request.session.get('user_id') # Retrieve user ID from session
if user_id:
return JsonResponse({"user_id": user_id}, status=200)
else:
return JsonResponse({"error": "User ID not found"}, status=404)