login in only single device at a time

This commit is contained in:
jain
2023-07-14 19:38:58 +05:30
parent 485dc83911
commit 5bd865a685
8 changed files with 126 additions and 23 deletions

View File

@ -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

View 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

View 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',
},
),
]

View File

@ -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

View File

@ -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)

View File

@ -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 = {

View File

@ -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"""

View File

@ -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'