Login va Register to'girlandi
This commit is contained in:
@@ -29,6 +29,7 @@ class CustomUserAdmin(admin.UserAdmin, ModelAdmin):
|
|||||||
"groups",
|
"groups",
|
||||||
"user_permissions",
|
"user_permissions",
|
||||||
"role",
|
"role",
|
||||||
|
"validated_at",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -4,9 +4,16 @@ from django.utils.translation import gettext as _
|
|||||||
from rest_framework import exceptions, serializers
|
from rest_framework import exceptions, serializers
|
||||||
|
|
||||||
OTP_SIZE = env.int("OTP_SIZE", 4)
|
OTP_SIZE = env.int("OTP_SIZE", 4)
|
||||||
|
|
||||||
|
|
||||||
class LoginSerializer(serializers.Serializer):
|
class LoginSerializer(serializers.Serializer):
|
||||||
username = serializers.CharField(max_length=255)
|
phone = serializers.CharField(max_length=255)
|
||||||
password = serializers.CharField(max_length=255)
|
|
||||||
|
def validate_phone(self, value):
|
||||||
|
user = get_user_model().objects.filter(phone=value, validated_at__isnull=False).exists()
|
||||||
|
if not user:
|
||||||
|
raise exceptions.ValidationError(_("Phone Not Found"))
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class RegisterSerializer(serializers.ModelSerializer):
|
class RegisterSerializer(serializers.ModelSerializer):
|
||||||
@@ -20,13 +27,7 @@ class RegisterSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = get_user_model()
|
model = get_user_model()
|
||||||
fields = ["first_name", "last_name", "phone", "password"]
|
fields = ["phone"]
|
||||||
extra_kwargs = {
|
|
||||||
"first_name": {
|
|
||||||
"required": True,
|
|
||||||
},
|
|
||||||
"last_name": {"required": True},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ConfirmSerializer(serializers.Serializer):
|
class ConfirmSerializer(serializers.Serializer):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Accounts app urls
|
|||||||
|
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework_simplejwt import views as jwt_views
|
from rest_framework_simplejwt import views as jwt_views
|
||||||
from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView
|
from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView, LoginView
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
@@ -12,7 +12,7 @@ router.register("auth", RegisterView, basename="auth")
|
|||||||
router.register("auth", ResetPasswordView, basename="reset-password")
|
router.register("auth", ResetPasswordView, basename="reset-password")
|
||||||
router.register("auth", MeView, basename="me")
|
router.register("auth", MeView, basename="me")
|
||||||
router.register("auth", ChangePasswordView, basename="change-password")
|
router.register("auth", ChangePasswordView, basename="change-password")
|
||||||
|
router.register("login", LoginView, basename="login")
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", include(router.urls)),
|
path("", include(router.urls)),
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
from .auth import * # noqa
|
from .auth import * # noqa
|
||||||
|
from .login import * # noqa
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class RegisterView(BaseViewSetMixin, GenericViewSet, UserService):
|
|||||||
data = ser.data
|
data = ser.data
|
||||||
phone = data.get("phone")
|
phone = data.get("phone")
|
||||||
# Create pending user
|
# Create pending user
|
||||||
self.create_user(phone, data.get("first_name"), data.get("last_name"), data.get("password"))
|
self.create_user(phone)
|
||||||
self.send_confirmation(phone) # Send confirmation code for sms eskiz.uz
|
self.send_confirmation(phone) # Send confirmation code for sms eskiz.uz
|
||||||
return Response(
|
return Response(
|
||||||
{"detail": _("Sms %(phone)s raqamiga yuborildi") % {"phone": phone}},
|
{"detail": _("Sms %(phone)s raqamiga yuborildi") % {"phone": phone}},
|
||||||
|
|||||||
61
core/apps/accounts/views/login.py
Normal file
61
core/apps/accounts/views/login.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
from drf_spectacular.utils import extend_schema
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.decorators import action
|
||||||
|
from django_core.mixins.base import BaseViewSetMixin
|
||||||
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
from core.services import UserService, SmsService
|
||||||
|
from ..serializers import LoginSerializer, ConfirmSerializer
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from rest_framework.exceptions import PermissionDenied
|
||||||
|
from django_core import exceptions
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema(tags=["Login"])
|
||||||
|
class LoginView(BaseViewSetMixin, GenericViewSet, UserService):
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
match self.action:
|
||||||
|
case "send_code":
|
||||||
|
return LoginSerializer
|
||||||
|
case "send_confirm":
|
||||||
|
return ConfirmSerializer
|
||||||
|
case _:
|
||||||
|
return LoginSerializer
|
||||||
|
|
||||||
|
@action(detail=False, methods=["post"], url_path="send_code")
|
||||||
|
def send_code(self, request):
|
||||||
|
ser = self.get_serializer(data=request.data)
|
||||||
|
ser.is_valid(raise_exception=True)
|
||||||
|
data = ser.validated_data
|
||||||
|
phone = data.get('phone')
|
||||||
|
self.send_confirmation(phone)
|
||||||
|
return Response(
|
||||||
|
{"detail": _("Sms %(phone)s raqamiga yuborildi") % {"phone": phone}},
|
||||||
|
status=status.HTTP_202_ACCEPTED,
|
||||||
|
)
|
||||||
|
|
||||||
|
@action(detail=False, methods=["post"], url_path="send_confirm")
|
||||||
|
def send_confirm(self, request):
|
||||||
|
ser = self.get_serializer(data=request.data)
|
||||||
|
ser.is_valid(raise_exception=True)
|
||||||
|
data = ser.validated_data
|
||||||
|
phone = data.get("phone")
|
||||||
|
code = data.get("code")
|
||||||
|
try:
|
||||||
|
if SmsService.check_confirm(phone, code=code):
|
||||||
|
token = self.get_token(get_user_model().objects.filter(phone=phone).first())
|
||||||
|
return Response(
|
||||||
|
data={
|
||||||
|
"detail": _("Tasdiqlash ko'di qabul qilindi"),
|
||||||
|
"token": token,
|
||||||
|
},
|
||||||
|
status=status.HTTP_202_ACCEPTED,
|
||||||
|
)
|
||||||
|
except exceptions.SmsException as e:
|
||||||
|
raise PermissionDenied(e) # Response exception for APIException
|
||||||
|
except Exception as e:
|
||||||
|
raise PermissionDenied(e) # Api exception for APIException
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#type: ignore
|
# type: ignore
|
||||||
import random
|
import random
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
@@ -23,15 +23,17 @@ class SmsService:
|
|||||||
code = "".join(str(random.randint(0, 9)) for _ in range(env.int("OTP_SIZE", 4)))
|
code = "".join(str(random.randint(0, 9)) for _ in range(env.int("OTP_SIZE", 4)))
|
||||||
else:
|
else:
|
||||||
code = env.int("OTP_DEFAULT", 1111)
|
code = env.int("OTP_DEFAULT", 1111)
|
||||||
|
print("ishlayapti01")
|
||||||
sms_confirm, status = models.SmsConfirm.objects.get_or_create(phone=phone, defaults={"code": code})
|
sms_confirm, status = models.SmsConfirm.objects.get_or_create(phone=phone, defaults={"code": code})
|
||||||
|
print(sms_confirm)
|
||||||
|
print(status)
|
||||||
sms_confirm.sync_limits()
|
sms_confirm.sync_limits()
|
||||||
|
print("ishlayapti")
|
||||||
if sms_confirm.resend_unlock_time is not None:
|
if sms_confirm.resend_unlock_time is not None:
|
||||||
expired = sms_confirm.interval(sms_confirm.resend_unlock_time)
|
expired = sms_confirm.interval(sms_confirm.resend_unlock_time)
|
||||||
exception = exceptions.SmsException(f"Resend blocked, try again in {expired}", expired=expired)
|
exception = exceptions.SmsException(f"Resend blocked, try again in {expired}", expired=expired)
|
||||||
raise exception
|
raise exception
|
||||||
|
print("ishlayapti2")
|
||||||
|
|
||||||
sms_confirm.code = code
|
sms_confirm.code = code
|
||||||
sms_confirm.try_count = 0
|
sms_confirm.try_count = 0
|
||||||
@@ -41,9 +43,11 @@ class SmsService:
|
|||||||
sms_confirm.resend_unlock_time = datetime.now() + timedelta(
|
sms_confirm.resend_unlock_time = datetime.now() + timedelta(
|
||||||
seconds=models.SmsConfirm.SMS_EXPIRY_SECONDS
|
seconds=models.SmsConfirm.SMS_EXPIRY_SECONDS
|
||||||
) # noqa
|
) # noqa
|
||||||
|
print("ishlayapti3")
|
||||||
sms_confirm.save()
|
sms_confirm.save()
|
||||||
|
|
||||||
SendConfirm.delay(phone, code)
|
SendConfirm.delay(phone, code)
|
||||||
|
print("ishlayapti4")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from core.services import sms
|
from core.services import sms
|
||||||
from django.contrib.auth import get_user_model, hashers
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django_core import exceptions
|
from django_core import exceptions
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
@@ -17,20 +17,19 @@ class UserService(sms.SmsService):
|
|||||||
"access": str(refresh.access_token),
|
"access": str(refresh.access_token),
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_user(self, phone, first_name, last_name, password):
|
def create_user(self, phone):
|
||||||
get_user_model().objects.update_or_create(
|
user, created = get_user_model().objects.update_or_create(
|
||||||
phone=phone,
|
phone=phone,
|
||||||
defaults={
|
defaults={
|
||||||
"phone": phone,
|
"phone": phone,
|
||||||
"first_name": first_name,
|
|
||||||
"last_name": last_name,
|
|
||||||
"password": hashers.make_password(password),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
user.set_unusable_password()
|
||||||
|
user.save()
|
||||||
|
|
||||||
def send_confirmation(self, phone) -> bool:
|
def send_confirmation(self, phone) -> bool:
|
||||||
try:
|
try:
|
||||||
self.send_confirm(phone)
|
sms.SmsService.send_confirm(phone)
|
||||||
return True
|
return True
|
||||||
except exceptions.SmsException as e:
|
except exceptions.SmsException as e:
|
||||||
raise PermissionDenied(_("Qayta sms yuborish uchun kuting: {}").format(e.kwargs.get("expired")))
|
raise PermissionDenied(_("Qayta sms yuborish uchun kuting: {}").format(e.kwargs.get("expired")))
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ volumes:
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
nginx:
|
nginx:
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
networks:
|
networks:
|
||||||
- uzxarid
|
- uzxarid
|
||||||
ports:
|
ports:
|
||||||
@@ -23,6 +21,8 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- web
|
- web
|
||||||
web:
|
web:
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
networks:
|
networks:
|
||||||
- uzxarid
|
- uzxarid
|
||||||
build:
|
build:
|
||||||
|
|||||||
Reference in New Issue
Block a user