deploy login & reCaptcha
This commit is contained in:
0
apps/authentication/api/__init__.py
Normal file
0
apps/authentication/api/__init__.py
Normal file
0
apps/authentication/api/v1/__init__.py
Normal file
0
apps/authentication/api/v1/__init__.py
Normal file
27
apps/authentication/api/v1/api.py
Normal file
27
apps/authentication/api/v1/api.py
Normal 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
|
||||
0
apps/authentication/api/v1/serializers/__init__.py
Normal file
0
apps/authentication/api/v1/serializers/__init__.py
Normal file
55
apps/authentication/api/v1/serializers/jwt.py
Normal file
55
apps/authentication/api/v1/serializers/jwt.py
Normal 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
|
||||
14
apps/authentication/api/v1/urls.py
Normal file
14
apps/authentication/api/v1/urls.py
Normal 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'),
|
||||
]
|
||||
@@ -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'),
|
||||
),
|
||||
]
|
||||
18
apps/authentication/migrations/0004_user_otp_status.py
Normal file
18
apps/authentication/migrations/0004_user_otp_status.py
Normal 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),
|
||||
),
|
||||
]
|
||||
@@ -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,
|
||||
|
||||
10
apps/authentication/urls.py
Normal file
10
apps/authentication/urls.py
Normal 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')),
|
||||
]
|
||||
Reference in New Issue
Block a user