mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-07-15 10:05:21 +00:00
login in only single device at a time
This commit is contained in:
@ -2,7 +2,7 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
"""Import django app"""
|
"""Import django app"""
|
||||||
from .models import UserEmailOtp, DefaultTaskImages, UserNotification, UserDelete
|
from .models import UserEmailOtp, DefaultTaskImages, UserNotification, UserDelete, UserDeviceDetails
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
|
|
||||||
@admin.register(UserDelete)
|
@admin.register(UserDelete)
|
||||||
@ -37,3 +37,10 @@ class UserEmailOtpAdmin(admin.ModelAdmin):
|
|||||||
"""Return object in email and otp format"""
|
"""Return object in email and otp format"""
|
||||||
return self.email + '-' + self.otp
|
return self.email + '-' + self.otp
|
||||||
|
|
||||||
|
@admin.register(UserDeviceDetails)
|
||||||
|
class UserDeviceDetailsAdmin(admin.ModelAdmin):
|
||||||
|
"""User profile admin"""
|
||||||
|
list_display = ['user', 'device_id']
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.user.email
|
||||||
|
36
account/custom_middleware.py
Normal file
36
account/custom_middleware.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"""middleware file"""
|
||||||
|
"""Django import"""
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.renderers import JSONRenderer
|
||||||
|
"""App django"""
|
||||||
|
from account.utils import custom_error_response
|
||||||
|
from account.models import UserDeviceDetails
|
||||||
|
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||||
|
|
||||||
|
"""Custom middleware
|
||||||
|
when user login with
|
||||||
|
multiple device simultaneously"""
|
||||||
|
class CustomMiddleware:
|
||||||
|
"""Custom middleware"""
|
||||||
|
def __init__(self, get_response):
|
||||||
|
"""response"""
|
||||||
|
self.get_response = get_response
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
|
# Code to be executed before the view is called
|
||||||
|
response = self.get_response(request)
|
||||||
|
# Code to be executed after the view is called
|
||||||
|
device_id = request.META['HTTP_DEVICE_ID']
|
||||||
|
if request.user.is_authenticated:
|
||||||
|
"""device details"""
|
||||||
|
device_details = UserDeviceDetails.objects.filter(user=request.user, device_id=device_id).last()
|
||||||
|
if not device_details:
|
||||||
|
custom_error = custom_error_response(ERROR_CODE['2037'], response_status=status.HTTP_404_NOT_FOUND)
|
||||||
|
response = Response(custom_error.data, status=status.HTTP_404_NOT_FOUND)
|
||||||
|
# Set content type header to "application/json"
|
||||||
|
response['Content-Type'] = 'application/json'
|
||||||
|
# Render the response as JSON
|
||||||
|
renderer = JSONRenderer()
|
||||||
|
response.content = renderer.render(response.data)
|
||||||
|
return response
|
31
account/migrations/0008_userdevicedetails.py
Normal file
31
account/migrations/0008_userdevicedetails.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Generated by Django 4.2.2 on 2023-07-14 11:08
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('account', '0007_alter_defaulttaskimages_options_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserDeviceDetails',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('device_id', models.CharField(max_length=500)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='user_device_details', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'User Device Details',
|
||||||
|
'verbose_name_plural': 'User Device Details',
|
||||||
|
'db_table': 'user_device_details',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -145,3 +145,23 @@ class UserNotification(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.user.email
|
return self.user.email
|
||||||
|
|
||||||
|
|
||||||
|
class UserDeviceDetails(models.Model):
|
||||||
|
"""
|
||||||
|
User notification details
|
||||||
|
"""
|
||||||
|
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_device_details')
|
||||||
|
"""Device ID"""
|
||||||
|
device_id = models.CharField(max_length=500)
|
||||||
|
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
|
class Meta(object):
|
||||||
|
""" Meta information """
|
||||||
|
db_table = 'user_device_details'
|
||||||
|
verbose_name = 'User Device Details'
|
||||||
|
verbose_name_plural = 'User Device Details'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.user.email
|
||||||
|
@ -5,17 +5,23 @@ from rest_framework import viewsets, status, views
|
|||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
import random
|
import random
|
||||||
import logging
|
import logging
|
||||||
from PIL import Image
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
import jwt
|
import jwt
|
||||||
from django.contrib.auth import logout
|
from django.contrib.auth import logout
|
||||||
"""App Import"""
|
|
||||||
from guardian.utils import upload_image_to_alibaba
|
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from templated_email import send_templated_mail
|
||||||
|
import google.oauth2.credentials
|
||||||
|
import google.auth.transport.requests
|
||||||
|
from rest_framework import status
|
||||||
|
import requests
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from django.conf import settings
|
||||||
|
"""App Import"""
|
||||||
from guardian.models import Guardian
|
from guardian.models import Guardian
|
||||||
from junior.models import Junior
|
from junior.models import Junior
|
||||||
from account.models import UserProfile, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification
|
from guardian.utils import upload_image_to_alibaba
|
||||||
|
from account.models import UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
"""Account serializer"""
|
"""Account serializer"""
|
||||||
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
|
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
|
||||||
@ -29,15 +35,6 @@ from base.constants import NUMBER, ZOD, JUN, GRD
|
|||||||
from guardian.tasks import generate_otp
|
from guardian.tasks import generate_otp
|
||||||
from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response,
|
from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response,
|
||||||
generate_code)
|
generate_code)
|
||||||
from rest_framework.permissions import IsAuthenticated
|
|
||||||
from templated_email import send_templated_mail
|
|
||||||
import google.oauth2.credentials
|
|
||||||
import google.auth.transport.requests
|
|
||||||
from rest_framework import status
|
|
||||||
import requests
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from django.conf import settings
|
|
||||||
from rest_framework_simplejwt.tokens import RefreshToken
|
|
||||||
from junior.serializers import JuniorProfileSerializer
|
from junior.serializers import JuniorProfileSerializer
|
||||||
from guardian.serializers import GuardianProfileSerializer
|
from guardian.serializers import GuardianProfileSerializer
|
||||||
|
|
||||||
@ -229,7 +226,6 @@ class ForgotPasswordAPIView(views.APIView):
|
|||||||
'verification_code': verification_code
|
'verification_code': verification_code
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expiry = timezone.now() + timezone.timedelta(days=1)
|
expiry = timezone.now() + timezone.timedelta(days=1)
|
||||||
user_data, created = UserEmailOtp.objects.get_or_create(email=email)
|
user_data, created = UserEmailOtp.objects.get_or_create(email=email)
|
||||||
if created:
|
if created:
|
||||||
@ -285,6 +281,7 @@ class UserLogin(viewsets.ViewSet):
|
|||||||
def login(self, request):
|
def login(self, request):
|
||||||
username = request.data.get('username')
|
username = request.data.get('username')
|
||||||
password = request.data.get('password')
|
password = request.data.get('password')
|
||||||
|
device_id = request.META.get('HTTP_DEVICE_ID')
|
||||||
user = authenticate(request, username=username, password=password)
|
user = authenticate(request, username=username, password=password)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -296,6 +293,10 @@ class UserLogin(viewsets.ViewSet):
|
|||||||
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
|
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
|
||||||
if junior_data:
|
if junior_data:
|
||||||
serializer = JuniorSerializer(junior_data).data
|
serializer = JuniorSerializer(junior_data).data
|
||||||
|
device_details, created = UserDeviceDetails.objects.get_or_create(user=user)
|
||||||
|
if device_details:
|
||||||
|
device_details.device_id = device_id
|
||||||
|
device_details.save()
|
||||||
return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK)
|
||||||
else:
|
else:
|
||||||
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
|
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
|
||||||
@ -347,7 +348,6 @@ class UserEmailVerification(viewsets.ModelViewSet):
|
|||||||
"""User Email verification"""
|
"""User Email verification"""
|
||||||
serializer_class = EmailVerificationSerializer
|
serializer_class = EmailVerificationSerializer
|
||||||
queryset = UserEmailOtp.objects.all()
|
queryset = UserEmailOtp.objects.all()
|
||||||
permission_classes = [IsAuthenticated]
|
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
@ -379,7 +379,8 @@ class UserEmailVerification(viewsets.ModelViewSet):
|
|||||||
refresh = RefreshToken.for_user(user_obj)
|
refresh = RefreshToken.for_user(user_obj)
|
||||||
access_token = str(refresh.access_token)
|
access_token = str(refresh.access_token)
|
||||||
refresh_token = str(refresh)
|
refresh_token = str(refresh)
|
||||||
return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token, "refresh_token":refresh_token},
|
return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token,
|
||||||
|
"refresh_token":refresh_token},
|
||||||
response_status=status.HTTP_200_OK)
|
response_status=status.HTTP_200_OK)
|
||||||
else:
|
else:
|
||||||
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
@ -429,8 +430,6 @@ class ProfileAPIViewSet(viewsets.ModelViewSet):
|
|||||||
serializer = GuardianProfileSerializer(guardian_data)
|
serializer = GuardianProfileSerializer(guardian_data)
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UploadImageAPIViewSet(viewsets.ModelViewSet):
|
class UploadImageAPIViewSet(viewsets.ModelViewSet):
|
||||||
"""Profile viewset"""
|
"""Profile viewset"""
|
||||||
queryset = DefaultTaskImages.objects.all()
|
queryset = DefaultTaskImages.objects.all()
|
||||||
@ -527,7 +526,6 @@ class SendSupportEmail(views.APIView):
|
|||||||
else:
|
else:
|
||||||
return custom_error_response(ERROR_CODE['2033'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2033'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
class LogoutAPIView(views.APIView):
|
class LogoutAPIView(views.APIView):
|
||||||
"""Log out API"""
|
"""Log out API"""
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = (IsAuthenticated,)
|
||||||
@ -550,3 +548,4 @@ class AccessTokenAPIView(views.APIView):
|
|||||||
access_token = str(refresh.access_token)
|
access_token = str(refresh.access_token)
|
||||||
data = {"auth_token": access_token}
|
data = {"auth_token": access_token}
|
||||||
return custom_response(None, data, response_status=status.HTTP_200_OK)
|
return custom_response(None, data, response_status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
@ -59,7 +59,8 @@ ERROR_CODE = {
|
|||||||
"2033": "Missing required fields",
|
"2033": "Missing required fields",
|
||||||
"2034": "Junior is not associated",
|
"2034": "Junior is not associated",
|
||||||
"2035": "Image should not be 0 kb",
|
"2035": "Image should not be 0 kb",
|
||||||
"2036": "Choose valid user"
|
"2036": "Choose valid user",
|
||||||
|
"2037": "You are already log in another device"
|
||||||
}
|
}
|
||||||
"""Success message code"""
|
"""Success message code"""
|
||||||
SUCCESS_CODE = {
|
SUCCESS_CODE = {
|
||||||
|
@ -9,7 +9,15 @@ from rest_framework import routers
|
|||||||
"""Define Router"""
|
"""Define Router"""
|
||||||
router = routers.SimpleRouter()
|
router = routers.SimpleRouter()
|
||||||
|
|
||||||
"""API End points with router"""
|
"""API End points with router
|
||||||
|
in this file
|
||||||
|
we define various api end point
|
||||||
|
that is covered in this guardian
|
||||||
|
section API:- like
|
||||||
|
sign-up, create guardian profile,
|
||||||
|
create-task,
|
||||||
|
all task list, top junior,
|
||||||
|
filter-task"""
|
||||||
"""Sign up API"""
|
"""Sign up API"""
|
||||||
router.register('sign-up', SignupViewset, basename='sign-up')
|
router.register('sign-up', SignupViewset, basename='sign-up')
|
||||||
"""Create guardian profile API"""
|
"""Create guardian profile API"""
|
||||||
|
@ -67,6 +67,7 @@ MIDDLEWARE = [
|
|||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
'account.custom_middleware.CustomMiddleware'
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'zod_bank.urls'
|
ROOT_URLCONF = 'zod_bank.urls'
|
||||||
|
Reference in New Issue
Block a user