deploy login & reCaptcha

This commit is contained in:
2025-05-04 15:24:28 +03:30
parent 3ab3fa2d13
commit 70fa849840
36 changed files with 494 additions and 5 deletions

View File

View File

View File

@@ -0,0 +1,27 @@
from apps.authentication.api.v1.serializers.jwt import CustomizedTokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from apps.authentication.models import User
from django.db import transaction
class CustomizedTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomizedTokenObtainPairSerializer
class Authentication(ModelViewSet):
queryset = User
serializer_class = ''
permission_classes = ''
@action(
methods=['post', ],
detail=False,
name='login',
url_name='login',
url_path='login'
)
@transaction.atomic
def login(self, request):
pass

View File

@@ -0,0 +1,55 @@
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from apps.captcha_app import exceptions as captcha_exception
from rest_framework_simplejwt.settings import api_settings
from django.contrib.auth.models import update_last_login
from rest_framework import exceptions
from django.core.cache import cache
from typing import Any
class CustomizedTokenObtainPairSerializer(TokenObtainPairSerializer): # noqa
"""
customize jwt token
'set new variables in generated token'
"""
def validate(self, attrs: dict[str, Any]) -> dict[str, str]:
"""
override validate method to add more conditions
"""
captcha_code, captcha_key = attrs['captcha_code'], attrs['captcha_key']
if captcha_code != cache.get(captcha_key) or captcha_code not in attrs.keys():
raise captcha_exception.CaptchaFailed()
data = super().validate(attrs)
refresh = self.get_token(self.user)
data["refresh"] = str(refresh)
data["access"] = str(refresh.access_token)
data["otp_status"] = self.user.otp_status
if not self.user.is_active:
raise exceptions.AuthenticationFailed(
self.error_messages["no_active_account"],
"no_active_account",
)
if api_settings.UPDATE_LAST_LOGIN:
update_last_login(None, self.user)
return data
@classmethod
def get_token(cls, user):
"""
set variables in encoded jwt token
"""
token = super().get_token(user)
# Add custom claims
token['name'] = user.username
return token

View File

@@ -0,0 +1,14 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView
)
from .api import CustomizedTokenObtainPairView
urlpatterns = [
path('login/', CustomizedTokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('token/verify/', TokenVerifyView.as_view(), name='token_verify'),
]

View File

@@ -0,0 +1,45 @@
# Generated by Django 5.0 on 2025-05-03 07:35
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0002_alter_user_id'),
]
operations = [
migrations.AddField(
model_name='user',
name='province',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_province', to='authentication.province'),
),
migrations.CreateModel(
name='City',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_date', models.DateTimeField(auto_now_add=True)),
('modify_date', models.DateTimeField(auto_now=True)),
('trash', models.BooleanField(default=False)),
('name', models.CharField(max_length=50)),
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL)),
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='organization',
name='city',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_organization', to='authentication.city'),
),
migrations.AddField(
model_name='user',
name='city',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_city', to='authentication.city'),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.0 on 2025-05-03 08:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0003_user_province_city_organization_city_user_city'),
]
operations = [
migrations.AddField(
model_name='user',
name='otp_status',
field=models.BooleanField(default=False),
),
]

View File

@@ -9,6 +9,19 @@ class User(AbstractUser, BaseModel):
mobile = models.CharField(max_length=18)
national_code = models.CharField(max_length=16)
photo = models.CharField(max_length=50)
province = models.ForeignKey(
'Province',
on_delete=models.CASCADE,
related_name='user_province',
null=True
)
city = models.ForeignKey(
'City',
on_delete=models.CASCADE,
related_name='user_city',
null=True
)
otp_status = models.BooleanField(default=False)
def __str__(self):
return f'{self.username} {self.last_name}-{self.last_login}'
@@ -27,6 +40,16 @@ class Province(BaseModel):
super(Province, self).save(*args, **kwargs)
class City(BaseModel):
name = models.CharField(max_length=50)
def __str__(self):
return f'{self.name}'
def save(self, *args, **kwargs):
super(City, self).save(*args, **kwargs)
class Organization(BaseModel):
name = models.CharField(max_length=50)
type = models.CharField(max_length=50)
@@ -36,6 +59,12 @@ class Organization(BaseModel):
related_name="province_organization",
null=True
)
city = models.ForeignKey(
'City',
on_delete=models.CASCADE,
related_name='city_organization',
null=True
)
parent_organization = models.ForeignKey(
'Organization',
on_delete=models.CASCADE,

View File

@@ -0,0 +1,10 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('', '', basename='')
app_name = "authentication"
urlpatterns = [
path('api/v1/', include('apps.authentication.api.v1.urls')),
]