Compare commits

...
53 Commits
Author SHA1 Message Date
jain 22f1d01b94 requirement.txt file 2023-07-03 15:59:37 +05:30
jain a27c486c43 remove unused code 2023-07-03 15:53:25 +05:30
jain 28cbdf9cfa jira-5 social login 2023-07-03 14:57:07 +05:30
jain 014b5fe183 jira-5 apple login with first and last name 2023-07-03 12:58:06 +05:30
jain d2498f82ad jira-5 google login and apple login 2023-06-30 21:25:43 +05:30
jain 79ac140ddd jira-3 google login 2023-06-30 16:22:41 +05:30
jain 4a34dab570 Merge branch 'dev' of github.com:KiwiTechLLC/ZODBank-Backend into login_code 2023-06-30 16:10:09 +05:30
jain 245162b913 jira-274 user can use same number multiple time 2023-06-30 15:51:12 +05:30
jain 7376fc555b jira-5 google login 2023-06-30 15:21:00 +05:30
Ankitajain-kiwi ed2d7895ab Merge pull request #23 from KiwiTechLLC/login_code
reset password msg
2023-06-30 11:17:54 +05:30
jain c57968b7c0 reset password msg 2023-06-30 11:17:18 +05:30
dilipshrivastwa-kiwi e42d8af65b Merge pull request #20 from KiwiTechLLC/login_code
email changes
2023-06-29 21:44:33 +05:30
jain d254c5e5fa email changes 2023-06-29 21:39:36 +05:30
dilipshrivastwa-kiwi 118d73776b Merge pull request #17 from KiwiTechLLC/login_code
jira-7 email
2023-06-29 20:29:51 +05:30
jain c2713b8214 jira-7 email 2023-06-29 20:26:35 +05:30
dilipshrivastwa-kiwi 4dd95e74fb Merge pull request #16 from KiwiTechLLC/login_code
Login code
2023-06-29 18:22:14 +05:30
jain 70c136dde4 jira-9 changes in setting 2023-06-29 18:21:15 +05:30
jain 88a9e925ed jira-9 changes in setting 2023-06-29 18:20:07 +05:30
jain 3d3ccfb146 jira-9 changes in setting 2023-06-29 18:16:11 +05:30
jain be6725c66d jira-9 changes in setting 2023-06-29 18:14:49 +05:30
dilipshrivastwa-kiwi f3c41043e0 Merge pull request #15 from KiwiTechLLC/login_code
jira-4 login after email verified
2023-06-29 18:09:05 +05:30
jain ea2bd635ca jira-4 login after email verified 2023-06-29 18:03:27 +05:30
Ankitajain-kiwi eb4cde397f Merge pull request #14 from KiwiTechLLC/GoogleLogin
add requirement file
2023-06-29 13:05:17 +05:30
jain 4864d3b499 add requirement file 2023-06-29 13:03:40 +05:30
dilipshrivastwa-kiwi ef1f7ebeac Merge pull request #13 from KiwiTechLLC/GoogleLogin
Google login
2023-06-29 12:19:05 +05:30
jain c1ae88c32f jira-13 image upload changes 2023-06-29 11:49:40 +05:30
jain 9d7f265f40 jira-9 and jira-12 sendgrid and upload images in alibaba bucket 2023-06-29 11:40:04 +05:30
jain f0a2a4bd4b jira-13 update profile 2023-06-27 21:34:40 +05:30
jain 4a982f1baf changes in setting.py file 2023-06-27 20:44:42 +05:30
jain d849153bec changes in setting.py file 2023-06-27 20:43:22 +05:30
Ankitajain-kiwi 947119d4c2 Merge pull request #10 from KiwiTechLLC/26june_sprint1
changes in setting.py file
2023-06-27 20:18:12 +05:30
Ankitajain-kiwi a41e3a6f14 Merge branch 'dev' into 26june_sprint1 2023-06-27 20:18:04 +05:30
jain 7b02b7dfbc changes in setting.py file 2023-06-27 20:16:35 +05:30
Ankitajain-kiwi 3852e9bf03 Merge pull request #9 from KiwiTechLLC/26june_sprint1
26june sprint1
2023-06-27 19:34:27 +05:30
jain d208e5252c jira-13 update country name 2023-06-27 19:32:57 +05:30
jain 7b6d34f334 setting changes 2023-06-27 17:37:12 +05:30
jain 0006208cf8 Merge branch 'dev' of github.com:KiwiTechLLC/ZODBank-Backend into 26june_sprint1 2023-06-27 17:31:00 +05:30
Ankitajain-kiwi 352de6d630 Merge pull request #8 from KiwiTechLLC/server_demo
changes
2023-06-27 17:28:51 +05:30
jain ad582d77d7 changes 2023-06-27 17:27:19 +05:30
jain 019d028cb6 jira-5 google login 2023-06-27 17:22:59 +05:30
Ankitajain-kiwi e1e5b1838a Merge pull request #7 from KiwiTechLLC/server_demo
changes docker file position
2023-06-27 16:54:39 +05:30
jain 8ff142ce2f changes docker file position 2023-06-27 16:53:38 +05:30
jain 4537f1f4fa changes 2023-06-27 16:45:42 +05:30
Ankitajain-kiwi 2086dcb472 Merge pull request #6 from KiwiTechLLC/26june_sprint1
auth token changes
2023-06-27 15:18:43 +05:30
jain d4eaaada74 auth token changes 2023-06-27 15:17:46 +05:30
dilipshrivastwa-kiwi 396b4a32c3 Merge pull request #5 from KiwiTechLLC/26june_sprint1
26june sprint1
2023-06-27 15:07:19 +05:30
jain 232f082c77 jira-7 changes in requirment.txt file 2023-06-27 14:59:00 +05:30
jain aaa1730636 Jira-13 migrate file 2023-06-27 11:46:20 +05:30
jain 44b25dde3e Jira-13 sonar fixes 2023-06-27 11:44:00 +05:30
dilipshrivastwa-kiwi b52819c033 Merge pull request #4 from KiwiTechLLC/26june_sprint1
jira-9 changes in phone verification
2023-06-26 16:51:15 +05:30
jain 9bd31f9e86 jira-9 changes in phone verification 2023-06-26 16:44:32 +05:30
Ankitajain-kiwi 6374ea0a90 Merge pull request #3 from KiwiTechLLC/demo-dev1
Demo dev1
2023-06-26 12:44:05 +05:30
dilipshrivastwa-kiwi c115873972 Merge pull request #2 from KiwiTechLLC/demo-dev1
First Commit
2023-06-24 14:30:17 +05:30
67 changed files with 1014 additions and 463 deletions
+11
View File
@@ -0,0 +1,11 @@
FROM python:3.9
ENV PYTHONUNBUFFERED 1
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
COPY . .
RUN apt-get update
RUN apt-get install wkhtmltopdf -y
RUN apt install -y gdal-bin python3-gdal
RUN pip install -r requirements.txt
WORKDIR /usr/src/app
@@ -1,10 +1,12 @@
"""Account admin"""
from django.contrib import admin from django.contrib import admin
# Register your models here. """Import django app"""
from .models import UserProfile, UserEmailOtp, UserPhoneOtp from .models import UserProfile, UserEmailOtp, UserPhoneOtp
# Register your models here. # Register your models here.
@admin.register(UserProfile) @admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin): class UserProfileAdmin(admin.ModelAdmin):
"""User profile admin"""
list_display = ['user'] list_display = ['user']
def __str__(self): def __str__(self):
@@ -12,14 +14,18 @@ class UserProfileAdmin(admin.ModelAdmin):
@admin.register(UserEmailOtp) @admin.register(UserEmailOtp)
class UserEmailOtpAdmin(admin.ModelAdmin): class UserEmailOtpAdmin(admin.ModelAdmin):
"""User Email otp admin"""
list_display = ['email'] list_display = ['email']
def __str__(self): def __str__(self):
"""Return object in email and otp format"""
return self.email + '-' + self.otp return self.email + '-' + self.otp
@admin.register(UserPhoneOtp) @admin.register(UserPhoneOtp)
class UserPhoneOtpAdmin(admin.ModelAdmin): class UserPhoneOtpAdmin(admin.ModelAdmin):
"""User Phone otp admin"""
list_display = ['phone'] list_display = ['phone']
def __str__(self): def __str__(self):
"""Return object in phone number and otp format"""
return self.phone + '-' + self.otp return self.phone + '-' + self.otp
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-29 12:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='useremailotp',
name='user_type',
field=models.CharField(blank=True, choices=[('1', 'junior'), ('2', 'guardian'), ('3', 'superuser')], default=None, max_length=15, null=True),
),
]
@@ -59,6 +59,7 @@ class UserEmailOtp(models.Model):
"""otp details""" """otp details"""
otp = models.CharField(max_length=10) otp = models.CharField(max_length=10)
is_verified = models.BooleanField(default=False) is_verified = models.BooleanField(default=False)
user_type = models.CharField(max_length=15, choices=USER_TYPE, null=True, blank=True, default=None)
# OTP validity # OTP validity
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
@@ -12,7 +12,45 @@ from rest_framework import viewsets, status
from rest_framework.decorators import action from rest_framework.decorators import action
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from guardian.utils import upload_image_to_alibaba
from .utils import get_token
class GoogleLoginSerializer(serializers.Serializer):
access_token = serializers.CharField(max_length=5000, required=True)
class Meta:
"""meta class"""
fields = ('access_token',)
class UpdateGuardianImageSerializer(serializers.ModelSerializer):
"""Reset Password after verification"""
class Meta(object):
"""Meta info"""
model = Guardian
fields = '__all__'
def update(self, instance, validated_data):
"""update image """
instance.image = validated_data.get('image', instance.image)
instance.save()
return instance
class UpdateJuniorProfileImageSerializer(serializers.ModelSerializer):
"""Reset Password after verification"""
class Meta(object):
"""Meta info"""
model = Junior
fields = '__all__'
def update(self, instance, validated_data):
"""update image """
image = validated_data.get('image', instance.image)
filename = f"images/{image.name}"
image_url = upload_image_to_alibaba(image, filename)
instance.image = image_url
instance.save()
return instance
class ResetPasswordSerializer(serializers.Serializer): class ResetPasswordSerializer(serializers.Serializer):
"""Reset Password after verification""" """Reset Password after verification"""
verification_code = serializers.CharField(max_length=10) verification_code = serializers.CharField(max_length=10)
@@ -24,15 +62,12 @@ class ResetPasswordSerializer(serializers.Serializer):
def create(self, validated_data): def create(self, validated_data):
verification_code = validated_data.pop('verification_code') verification_code = validated_data.pop('verification_code')
password = validated_data.pop('password') password = validated_data.pop('password')
print("verification_code===>",verification_code)
print("password===>", password)
user_opt_details = UserEmailOtp.objects.filter(otp=verification_code, is_verified=True).last() user_opt_details = UserEmailOtp.objects.filter(otp=verification_code, is_verified=True).last()
print("user_opt_details===>",user_opt_details)
if user_opt_details: if user_opt_details:
print("qqqqqqqqqq")
user_details = User.objects.filter(email=user_opt_details.email).last() user_details = User.objects.filter(email=user_opt_details.email).last()
if user_details: if user_details:
print("333333333==>",user_details.password) if user_details.check_password(password):
raise serializers.ValidationError({"details":ERROR_CODE['2001'],"code":"400", "status":"failed"})
user_details.set_password(password) user_details.set_password(password)
user_details.save() user_details.save()
return {'password':password} return {'password':password}
@@ -52,17 +87,17 @@ class ChangePasswordSerializer(serializers.Serializer):
if self.context.password not in ('', None): if self.context.password not in ('', None):
if user.check_password(value): if user.check_password(value):
return value return value
raise serializers.ValidationError({"error":"Invalid Current password"}) raise serializers.ValidationError({"details":ERROR_CODE['2015']})
def create(self, validated_data): def create(self, validated_data):
new_password = validated_data.pop('new_password') new_password = validated_data.pop('new_password')
current_password = validated_data.pop('current_password')
if new_password == current_password:
raise serializers.ValidationError({"details": ERROR_CODE['2026']})
user_details = User.objects.filter(email=self.context).last() user_details = User.objects.filter(email=self.context).last()
print("user_details==>", user_details)
if user_details: if user_details:
print("333333333==>",user_details.password)
user_details.set_password(new_password) user_details.set_password(new_password)
user_details.save() user_details.save()
return {'password':new_password} return {'password':new_password}
return user_details
return '' return ''
@@ -91,11 +126,13 @@ class GuardianSerializer(serializers.ModelSerializer):
first_name = serializers.SerializerMethodField('get_first_name') first_name = serializers.SerializerMethodField('get_first_name')
last_name = serializers.SerializerMethodField('get_last_name') last_name = serializers.SerializerMethodField('get_last_name')
auth_token = serializers.SerializerMethodField('get_auth_token') auth_token = serializers.SerializerMethodField('get_auth_token')
refresh_token = serializers.SerializerMethodField('get_refresh_token')
def get_auth_token(self, obj): def get_auth_token(self, obj):
refresh = RefreshToken.for_user(obj.user) return get_token()['access']
access_token = str(refresh.access_token) def get_refresh_token(self, obj):
return access_token return get_token()['refresh']
def get_user_type(self, obj): def get_user_type(self, obj):
"""user type""" """user type"""
@@ -116,8 +153,8 @@ class GuardianSerializer(serializers.ModelSerializer):
class Meta(object): class Meta(object):
"""Meta info""" """Meta info"""
model = Guardian model = Guardian
fields = ['auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'family_name', 'gender', 'dob', fields = ['auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'family_name', 'gender', 'dob',
'referral_code', 'is_active', 'is_complete_profile', 'passcode', 'referral_code', 'is_active', 'is_complete_profile', 'passcode', 'image',
'created_at', 'updated_at', 'user_type'] 'created_at', 'updated_at', 'user_type']
@@ -128,11 +165,12 @@ class JuniorSerializer(serializers.ModelSerializer):
first_name = serializers.SerializerMethodField('get_first_name') first_name = serializers.SerializerMethodField('get_first_name')
last_name = serializers.SerializerMethodField('get_last_name') last_name = serializers.SerializerMethodField('get_last_name')
auth_token = serializers.SerializerMethodField('get_auth_token') auth_token = serializers.SerializerMethodField('get_auth_token')
refresh_token = serializers.SerializerMethodField('get_refresh_token')
def get_auth_token(self, obj): def get_auth_token(self, obj):
refresh = RefreshToken.for_user(obj.auth) return get_token()['access']
access_token = str(refresh.access_token) def get_refresh_token(self, obj):
return access_token return get_token()['refresh']
def get_user_type(self, obj): def get_user_type(self, obj):
return JUNIOR return JUNIOR
@@ -149,8 +187,8 @@ class JuniorSerializer(serializers.ModelSerializer):
class Meta(object): class Meta(object):
"""Meta info""" """Meta info"""
model = Junior model = Junior
fields = ['auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', fields = ['auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
'updated_at', 'user_type'] 'updated_at', 'user_type']
class EmailVerificationSerializer(serializers.ModelSerializer): class EmailVerificationSerializer(serializers.ModelSerializer):
+7 -4
View File
@@ -5,21 +5,24 @@ from rest_framework.decorators import api_view
"""Third party import""" """Third party import"""
from rest_framework import routers from rest_framework import routers
from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp, from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp,
ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView) ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage,
GoogleLoginViewSet, SigninWithApple)
"""Router""" """Router"""
router = routers.SimpleRouter() router = routers.SimpleRouter()
"""API End points with router""" """API End points with router"""
router.register('user', UserLogin, basename='user') router.register('user', UserLogin, basename='user')
router.register('superuser', UserLogin, basename='superuser') router.register('admin', UserLogin, basename='admin')
router.register('google-login', GoogleLoginViewSet, basename='admin')
router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp') router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp')
router.register('user-phone-verification', UserPhoneVerification, basename='user-phone-verification') router.register('user-phone-verification', UserPhoneVerification, basename='user-phone-verification')
router.register('user-email-verification', UserEmailVerification, basename='user-email-verification') router.register('user-email-verification', UserEmailVerification, basename='user-email-verification')
router.register('resend-email-otp', ReSendEmailOtp, basename='resend-email-otp') router.register('resend-email-otp', ReSendEmailOtp, basename='resend-email-otp')
urlpatterns = [ urlpatterns = [
path('api/v1/', include(router.urls)), path('api/v1/', include(router.urls)),
path('api/v1/forgot-password/', ForgotPasswordAPIView.as_view()), path('api/v1/forgot-password/', ForgotPasswordAPIView.as_view()),
path('api/v1/reset-password/', ResetPasswordAPIView.as_view()), path('api/v1/reset-password/', ResetPasswordAPIView.as_view()),
path('api/v1/change-password/', ChangePasswordAPIView.as_view()) path('api/v1/change-password/', ChangePasswordAPIView.as_view()),
path('api/v1/update-profile-image/', UpdateProfileImage.as_view()),
path('api/v1/apple-login/', SigninWithApple.as_view(), name='signup_with_apple'),
] ]
+93
View File
@@ -0,0 +1,93 @@
"""Account utils"""
"""Third party Django app"""
from django.conf import settings
from rest_framework import viewsets, status
from rest_framework.response import Response
from templated_email import send_templated_mail
import jwt
from datetime import datetime
from calendar import timegm
from uuid import uuid4
import secrets
def send_otp_email(recipient_email, otp):
from_email = settings.EMAIL_FROM_ADDRESS
recipient_list = [recipient_email]
send_templated_mail(
template_name='email_otp_verification.email',
from_email=from_email,
recipient_list=recipient_list,
context={
'otp': otp
}
)
return otp
def custom_response(detail, data=None, response_status=status.HTTP_200_OK):
"""Custom response code"""
if not data:
data = None
return Response({"data": data, "message": detail, "status": "success", "code": response_status})
def custom_error_response(detail, response_status):
"""
function is used for getting same global error response for all
:param detail: error message .
:param response_status: http status.
:return: Json response
"""
if not detail:
detail = {}
return Response({"error": detail, "status": "failed", "code": response_status})
def get_user_data(attrs):
"""
used to decode token
"""
user_data = jwt.decode(jwt=attrs['token'], options={'verify_signature': False},
algorithms=['RS256'])
return user_data
def generate_jwt_token(token_type: str, now_time: int, data: dict = dict):
"""
used to generate jwt token
"""
if type(data) == type:
data = {}
data.update({
'token_type': token_type,
'iss': 'your_site_url',
'iat': timegm(datetime.utcnow().utctimetuple()),
'jti': uuid4().hex
})
TOKEN_TYPE = ["access", "refresh"]
if token_type == TOKEN_TYPE[1]:
exp = now_time + settings.SIMPLE_JWT['REFRESH_TOKEN_LIFETIME']
else:
exp = now_time + settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME']
data.update({
"exp": timegm(exp.utctimetuple())
})
signing_key = secrets.token_hex(32)
return jwt.encode(payload=data, key=signing_key,
algorithm='HS256')
def get_token(data: dict = dict):
""" create access and refresh token """
now_time = datetime.utcnow()
access = generate_jwt_token('access', now_time, data)
refresh = generate_jwt_token('refresh', now_time, data)
return {
'access': access,
'refresh': refresh
}
+328
View File
@@ -0,0 +1,328 @@
from rest_framework import viewsets, status, views
from rest_framework.decorators import action
import random
import logging
import jwt
from django.contrib.auth import authenticate, login
from guardian.models import Guardian
from junior.models import Junior
from account.models import UserProfile, UserPhoneOtp, UserEmailOtp
from django.contrib.auth.models import User
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer,
GoogleLoginSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer)
from rest_framework_simplejwt.tokens import RefreshToken
from base.messages import ERROR_CODE, SUCCESS_CODE
from guardian.tasks import generate_otp
from account.utils import send_otp_email
from account.utils import custom_response, custom_error_response
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
from rest_framework.response import Response
import requests
from django.conf import settings
from .utils import get_token
class GoogleLoginMixin:
def google_login(self, request):
access_token = request.data.get('access_token')
user_type = request.data.get('user_type')
if not access_token:
return Response({'error': 'Access token is required.'}, status=status.HTTP_400_BAD_REQUEST)
try:
# Validate the access token and obtain the user's email and name
credentials = google.oauth2.credentials.Credentials.from_authorized_user_info(
info={
'access_token': access_token,
'token_uri': 'https://oauth2.googleapis.com/token',
'client_id': settings.GOOGLE_CLIENT_ID,
'client_secret': settings.GOOGLE_CLIENT_SECRET,
'refresh_token': None,
}
)
user_info_endpoint = f'https://www.googleapis.com/oauth2/v3/userinfo?access_token={access_token}'
headers = {'Authorization': f'Bearer {credentials.token}'}
response = requests.get(user_info_endpoint, headers=headers)
response.raise_for_status()
user_info = response.json()
email = user_info['email']
first_name = user_info['given_name']
last_name = user_info['family_name']
profile_picture = user_info['picture']
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
# Check if the user exists in your database or create a new user
# ...
user_data = User.objects.filter(email__iexact=email)
if user_data.exists():
if str(user_type) == '1':
junior_query = Junior.objects.filter(auth=user_data.last()).last()
serializer = JuniorSerializer(junior_query)
if str(user_type) == '2':
guardian_query = Guardian.objects.filter(user=user_data.last()).last()
serializer = GuardianSerializer(guardian_query)
return custom_response(SUCCESS_CODE['3003'], serializer.data,
response_status=status.HTTP_200_OK)
if not User.objects.filter(email__iexact=email).exists():
user_obj = User.objects.create(username=email, email=email, first_name=first_name, last_name=last_name)
if str(user_type) == '1':
junior_query = Junior.objects.create(auth=user_obj, is_verified=True, is_active=True,
image=profile_picture)
serializer = JuniorSerializer(junior_query)
if str(user_type) == '2':
guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True,
image=profile_picture)
serializer = GuardianSerializer(guardian_query)
# Return a JSON response with the user's email and name
return custom_response(SUCCESS_CODE['3003'], serializer.data,
response_status=status.HTTP_200_OK)
class GoogleLoginViewSet(GoogleLoginMixin, viewsets.GenericViewSet):
serializer_class = GoogleLoginSerializer
def create(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
return self.google_login(request)
class SigninWithApple(views.APIView):
"""This API is for sign in with Apple for app."""
def post(self, request):
token = request.data.get("access_token")
user_type = request.data.get("user_type")
if not token:
return custom_error_response(ERROR_CODE['2027'], response_status=status.HTTP_400_BAD_REQUEST)
try:
decoded_data = jwt.decode(token, options={"verify_signature": False})
user_data = {"email": decoded_data.get('email'), "username": decoded_data.get('email'), "is_active": True}
if decoded_data.get("email"):
try:
user = User.objects.get(email=decoded_data.get("email"))
if str(user_type) == '1':
junior_query = Junior.objects.filter(auth=user).last()
serializer = JuniorSerializer(junior_query)
if str(user_type) == '2':
guardian_query = Guardian.objects.filter(user=user).last()
serializer = GuardianSerializer(guardian_query)
return custom_response(SUCCESS_CODE['3003'], serializer.data,
response_status=status.HTTP_200_OK)
except User.DoesNotExist:
user = User.objects.create(**user_data)
if str(user_type) == '1':
junior_query = Junior.objects.create(auth=user, is_verified=True, is_active=True)
serializer = JuniorSerializer(junior_query)
if str(user_type) == '2':
guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True)
serializer = GuardianSerializer(guardian_query)
return custom_response(SUCCESS_CODE['3003'], serializer.data,
response_status=status.HTTP_200_OK)
except Exception as e:
logging.error(e)
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class UpdateProfileImage(views.APIView):
permission_classes = [IsAuthenticated]
def put(self, request, format=None):
if request.data['user_type'] == '1':
junior_query = Junior.objects.filter(auth=request.user).last()
serializer = UpdateJuniorProfileImageSerializer(junior_query, data=request.data, partial=True)
else:
guardian_query = Guardian.objects.filter(user=request.user).last()
serializer = UpdateGuardianImageSerializer(guardian_query, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return custom_response(SUCCESS_CODE['3017'], serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class ChangePasswordAPIView(views.APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
serializer = ChangePasswordSerializer(context=request.user, data=request.data)
if serializer.is_valid():
serializer.save()
return custom_response(SUCCESS_CODE['3007'], response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class ResetPasswordAPIView(views.APIView):
def post(self, request):
serializer = ResetPasswordSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return custom_response(SUCCESS_CODE['3006'], response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class ForgotPasswordAPIView(views.APIView):
def post(self, request):
serializer = ForgotPasswordSerializer(data=request.data)
if serializer.is_valid():
email = serializer.validated_data['email']
try:
User.objects.get(email=email)
except User.DoesNotExist:
return custom_error_response(ERROR_CODE['2004'], response_status=status.HTTP_404_NOT_FOUND)
verification_code = ''.join([str(random.randrange(9)) for _ in range(6)])
# Send the verification code to the user's email
from_email = settings.EMAIL_FROM_ADDRESS
recipient_list = [email]
send_templated_mail(
template_name='email_reset_verification.email',
from_email=from_email,
recipient_list=recipient_list,
context={
'verification_code': verification_code
}
)
user_data, created = UserEmailOtp.objects.get_or_create(email=email)
if user_data:
user_data.otp = verification_code
user_data.save()
return custom_response(SUCCESS_CODE['3015'],
response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class SendPhoneOtp(viewsets.ModelViewSet):
"""Send otp on phone"""
def create(self, request, *args, **kwargs):
otp = generate_otp()
phone_number = self.request.data['phone']
if phone_number.isdigit() and len(phone_number) == 10:
phone_otp, created = UserPhoneOtp.objects.get_or_create(country_code=self.request.data['country_code'],
phone=self.request.data['phone'])
if phone_otp:
phone_otp.otp = otp
phone_otp.save()
return custom_response(None, {'phone_otp':otp}, response_status=status.HTTP_200_OK)
return custom_error_response(ERROR_CODE['2020'], response_status=status.HTTP_400_BAD_REQUEST)
class UserPhoneVerification(viewsets.ModelViewSet):
"""Send otp on phone"""
def list(self, request, *args, **kwargs):
try:
phone_data = UserPhoneOtp.objects.filter(phone=self.request.GET.get('phone'),
otp=self.request.GET.get('otp')).last()
if phone_data:
phone_data.is_verified = True
phone_data.save()
return custom_response(SUCCESS_CODE['3012'], response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
except Exception:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
class UserLogin(viewsets.ViewSet):
@action(methods=['post'], detail=False)
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(request, username=username, password=password)
try:
if user is not None:
login(request, user)
guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last()
if guardian_data:
serializer = GuardianSerializer(guardian_data).data
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
if junior_data:
serializer = JuniorSerializer(junior_data).data
return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
except Exception as e:
logging.error(e)
email_verified = UserEmailOtp.objects.filter(email=username).last()
refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token)
data = {"auth_token":access_token, "is_profile_complete": False,
"user_type": email_verified.user_type,
}
is_verified = False
if email_verified:
is_verified = email_verified.is_verified
if not is_verified:
otp = generate_otp()
email_verified.otp = otp
email_verified.save()
data.update({"email_otp":otp})
return custom_response(ERROR_CODE['2024'], {"email_otp": otp, "is_email_verified": is_verified},
response_status=status.HTTP_200_OK)
data.update({"is_email_verified": is_verified})
return custom_response(None, data, response_status=status.HTTP_200_OK)
@action(methods=['post'], detail=False)
def admin_login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(request, username=username, password=password)
try:
if user is not None:
login(request, user)
if user.is_superuser:
serializer = SuperUserSerializer(user)
return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
except Exception as e:
logging.error(e)
refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token)
data = {"auth_token": access_token, "user_role": '3'}
return custom_response(None, data, response_status=status.HTTP_200_OK)
class UserEmailVerification(viewsets.ModelViewSet):
"""User Email verification"""
serializer_class = EmailVerificationSerializer
def list(self, request, *args, **kwargs):
try:
user_obj = User.objects.filter(username=self.request.GET.get('email')).last()
email_data = UserEmailOtp.objects.filter(email=self.request.GET.get('email'),
otp=self.request.GET.get('otp')).last()
if email_data:
email_data.is_verified = True
email_data.save()
if email_data.user_type == '1':
junior_data = Junior.objects.filter(auth__email=self.request.GET.get('email')).last()
if junior_data:
junior_data.is_verified = True
junior_data.save()
else:
guardian_data = Guardian.objects.filter(user__email=self.request.GET.get('email')).last()
if guardian_data:
guardian_data.is_verified = True
guardian_data.save()
refresh = RefreshToken.for_user(user_obj)
access_token = str(refresh.access_token)
return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token}, response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logging.error(e)
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
class ReSendEmailOtp(viewsets.ModelViewSet):
"""Send otp on phone"""
def create(self, request, *args, **kwargs):
otp = generate_otp()
if User.objects.filter(email=request.data['email']):
email_data, created = UserEmailOtp.objects.get_or_create(email=request.data['email'])
if email_data:
email_data.otp = otp
email_data.save()
send_otp_email(request.data['email'], otp)
return custom_response(SUCCESS_CODE['3016'], response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2023"], response_status=status.HTTP_400_BAD_REQUEST)
@@ -14,8 +14,7 @@ SUPER_ADMIN = "Super Admin"
JWT_TOKEN_EXPIRATION = 3 * 24 * 60 JWT_TOKEN_EXPIRATION = 3 * 24 * 60
# Define common file extention # Define common file extention
FILE_EXTENSION = ("gif", "jpeg", "jpg", "png", "svg", "csv", "doc", "docx", "odt", "pdf", "rtf", "txt", "wks", "wp", FILE_EXTENSION = ("gif", "jpeg", "jpg", "png", "svg")
"wpd")
# Define file size in bytes(5MB = 5 * 1024 * 1024) # Define file size in bytes(5MB = 5 * 1024 * 1024)
FILE_SIZE = 5 * 1024 * 1024 FILE_SIZE = 5 * 1024 * 1024
@@ -42,53 +41,6 @@ GUARDIAN = 'guardian'
JUNIOR = 'junior' JUNIOR = 'junior'
SUPERUSER = 'superuser' SUPERUSER = 'superuser'
# numbers used as a constant # numbers used as a constant
NUMBER = {
'point_zero': 0.0,
'zero': 0,
'one': 1,
'two': 2,
'three': 3,
'four': 4,
'five': 5,
'six': 6,
'seven': 7,
'eight': 8,
'nine': 9,
'ten': 10,
'eleven': 11,
'twelve': 12,
'thirteen': 13,
'fourteen': 14,
'fifteen': 15,
'sixteen': 16,
'seventeen': 17,
'eighteen': 18,
'nineteen': 19,
'twenty_four': 24,
'twenty_one': 21,
'twenty_two': 22,
'twenty_five': 25,
'thirty': 30,
'thirty_five': 35,
'thirty_six': 36,
'forty': 40,
'fifty': 50,
'fifty_nine': 59,
'sixty': 60,
'seventy_five': 75,
'eighty': 80,
'ninty_five': 95,
'ninty_six': 96,
'ninety_nine': 99,
'hundred': 100,
'one_one_nine': 119,
'one_twenty': 120,
'four_zero_four': 404,
'five_hundred': 500,
'minus_one': -1,
'point_three': 0.3,
'point_seven': 0.7
}
# Define the byte into kb # Define the byte into kb
BYTE_IMAGE_SIZE = 1024 BYTE_IMAGE_SIZE = 1024
+12 -7
View File
@@ -24,7 +24,7 @@ ERROR_CODE_REQUIRED = {
# Error code # Error code
ERROR_CODE = { ERROR_CODE = {
"2000": "Email not found.", "2000": "Email not found.",
"2001": "Your account has not been verified. Please check your email and verify it.", "2001": "This is your existing password. Please choose other one",
"2002": "Invalid login credentials.", "2002": "Invalid login credentials.",
"2003": "An account already exists with this email address.", "2003": "An account already exists with this email address.",
"2004": "User not found.", "2004": "User not found.",
@@ -35,7 +35,7 @@ ERROR_CODE = {
"2009": "The user provided cannot be found or the reset password token has become invalid/timed out.", "2009": "The user provided cannot be found or the reset password token has become invalid/timed out.",
"2010": "Invalid Link.", "2010": "Invalid Link.",
"2011": "Your profile has not been completed yet.", "2011": "Your profile has not been completed yet.",
"2012": "Password and Confirm password should be same.", "2012": "Phone number already used",
"2013": "Invalid token.", "2013": "Invalid token.",
"2014": "Your old password doesn't match.", "2014": "Your old password doesn't match.",
"2015": "Invalid old password.", "2015": "Invalid old password.",
@@ -45,9 +45,12 @@ ERROR_CODE = {
"2019": "Either File extension or File size doesn't meet the requirements", "2019": "Either File extension or File size doesn't meet the requirements",
"2020": "Enter valid mobile number", "2020": "Enter valid mobile number",
"2021": "Already register", "2021": "Already register",
"2022":"Invalid Guardian code", "2022": "Invalid Guardian code",
"2023":"Invalid user", "2023": "Invalid user",
"2024":"Email not verified" "2024": "Email not verified",
"2025": "Invalid input. Expected a list of strings.",
"2026": "New password should not same as old password",
"2027": "data should contain `identityToken`"
} }
SUCCESS_CODE = { SUCCESS_CODE = {
# Success code for password # Success code for password
@@ -63,7 +66,7 @@ SUCCESS_CODE = {
# Success code for password reset # Success code for password reset
"3006": "Your password has been reset successfully.", "3006": "Your password has been reset successfully.",
# Success code for password update # Success code for password update
"3007": "Your password has been updated successfully.", "3007": "Your password has been changed successfully.",
# Success code for valid link # Success code for valid link
"3008": "You have a valid link.", "3008": "You have a valid link.",
# Success code for logged out # Success code for logged out
@@ -74,7 +77,9 @@ SUCCESS_CODE = {
"3012": "Phone OTP Verified successfully", "3012": "Phone OTP Verified successfully",
"3013": "Valid Guardian code", "3013": "Valid Guardian code",
"3014": "Password has been updated successfully.", "3014": "Password has been updated successfully.",
"3015": "Verification code sent on your email." "3015": "Verification code sent on your email.",
"3016": "Send otp on your Email successfully",
"3017": "Profile image update successfully"
} }
STATUS_CODE_ERROR = { STATUS_CODE_ERROR = {
@@ -16,8 +16,8 @@ from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_200_OK
from base import constants from base import constants
from base.constants import NUMBER from base.constants import NUMBER
# local import # local import
from resourcekit.settings import base_settings as settings from zod_bank.settings import base_settings as settings
from resourcekit.settings.base_settings import BASE_DIR from zod_bank.settings.base_settings import BASE_DIR
def image_upload(folder, file_name, data): def image_upload(folder, file_name, data):
+18
View File
@@ -0,0 +1,18 @@
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "8000:8000"
volumes:
- ./nginx:/etc/nginx/conf.d
- .:/usr/src/app
depends_on:
- web
web:
build: .
container_name: django
command: bash -c "pip install -r requirements.txt && python manage.py collectstatic --noinput && python manage.py migrate && gunicorn zod_bank.wsgi -b 0.0.0.0:8000 -t 300 --log-level=info"
volumes:
- .:/usr/src/app
@@ -1,9 +1,14 @@
"""Guardian admin"""
"""Third party Django app"""
from django.contrib import admin from django.contrib import admin
"""Import Django app"""
from .models import Guardian from .models import Guardian
# Register your models here. # Register your models here.
@admin.register(Guardian) @admin.register(Guardian)
class GuardianAdmin(admin.ModelAdmin): class GuardianAdmin(admin.ModelAdmin):
"""Junior Admin"""
list_display = ['user', 'family_name'] list_display = ['user', 'family_name']
def __str__(self): def __str__(self):
"""Return email id"""
return self.user__email return self.user__email
@@ -1,6 +1,9 @@
"""Guardian app file"""
"""Third party Django app"""
from django.apps import AppConfig from django.apps import AppConfig
class CustodianConfig(AppConfig): class CustodianConfig(AppConfig):
"""Guardian config"""
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = 'django.db.models.BigAutoField'
name = 'guardian' name = 'guardian'
@@ -0,0 +1,17 @@
# Generated by Django 4.2.2 on 2023-06-27 06:15
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('guardian', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='guardian',
name='junior_code',
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-27 13:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('guardian', '0002_remove_guardian_junior_code'),
]
operations = [
migrations.AddField(
model_name='guardian',
name='country_name',
field=models.CharField(blank=True, default=None, max_length=30, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-28 06:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('guardian', '0003_guardian_country_name'),
]
operations = [
migrations.AddField(
model_name='guardian',
name='image',
field=models.ImageField(blank=True, default=None, null=True, upload_to='images/'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-29 06:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('guardian', '0004_guardian_image'),
]
operations = [
migrations.AlterField(
model_name='guardian',
name='image',
field=models.ImageField(blank=True, default=None, null=True, upload_to=''),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-29 12:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('guardian', '0005_alter_guardian_image'),
]
operations = [
migrations.AddField(
model_name='guardian',
name='is_verified',
field=models.BooleanField(default=False),
),
]
@@ -1,24 +1,35 @@
"""Guardian model file"""
"""Third party Django app"""
from django.db import models from django.db import models
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
"""Import Django app"""
from base.constants import GENDERS from base.constants import GENDERS
from django.contrib.postgres.fields import ArrayField
User = get_user_model() User = get_user_model()
# Create your models here. # Create your models here.
class Guardian(models.Model): class Guardian(models.Model):
"""Guardian model"""
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='guardian_profile', verbose_name='Email') user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='guardian_profile', verbose_name='Email')
"""Contact details"""
country_code = models.IntegerField(blank=True, null=True) country_code = models.IntegerField(blank=True, null=True)
phone = models.CharField(max_length=31, null=True, blank=True, default=None) phone = models.CharField(max_length=31, null=True, blank=True, default=None)
country_name = models.CharField(max_length=30, null=True, blank=True, default=None)
"""Image info"""
image = models.ImageField(null=True, blank=True, default=None)
"""Personal info"""
family_name = models.CharField(max_length=50, null=True, blank=True, default=None) family_name = models.CharField(max_length=50, null=True, blank=True, default=None)
gender = models.CharField(choices=GENDERS, max_length=15, null=True, blank=True, default=None) gender = models.CharField(choices=GENDERS, max_length=15, null=True, blank=True, default=None)
dob = models.DateField(max_length=15, null=True, blank=True, default=None) dob = models.DateField(max_length=15, null=True, blank=True, default=None)
guardian_code = models.CharField(max_length=10, null=True, blank=True, default=None) """Profile activity"""
junior_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True)
referral_code = models.CharField(max_length=10, null=True, blank=True, default=None)
referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None)
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
is_verified = models.BooleanField(default=False)
is_complete_profile = models.BooleanField(default=False) is_complete_profile = models.BooleanField(default=False)
passcode = models.IntegerField(null=True, blank=True, default=None) passcode = models.IntegerField(null=True, blank=True, default=None)
"""Codes"""
guardian_code = models.CharField(max_length=10, null=True, blank=True, default=None)
referral_code = models.CharField(max_length=10, null=True, blank=True, default=None)
referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None)
"""Profile created and updated time"""
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
@@ -28,4 +39,5 @@ class Guardian(models.Model):
verbose_name = 'Guardian' verbose_name = 'Guardian'
def __str__(self): def __str__(self):
"""Return email id"""
return f'{self.user}' return f'{self.user}'
@@ -1,91 +1,136 @@
from rest_framework import serializers """Serializer of Guardian"""
from django.contrib.auth.models import User """Third party Django app"""
from .models import Guardian import logging
from django.db import transaction
import random import random
from account.models import UserProfile from rest_framework import serializers
from junior.models import Junior
from base.constants import GENDERS, GUARDIAN, JUNIOR, SUPERUSER
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from django.db import transaction
from django.contrib.auth.models import User
"""Import Django app"""
from .models import Guardian
from account.models import UserProfile, UserEmailOtp
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from .utils import upload_image_to_alibaba
from junior.models import Junior
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
"""User serializer"""
auth_token = serializers.SerializerMethodField('get_auth_token') auth_token = serializers.SerializerMethodField('get_auth_token')
class Meta(object): class Meta(object):
"""Meta info"""
model = User model = User
fields = ['email', 'password', 'auth_token'] fields = ['email', 'password', 'auth_token']
def get_auth_token(self, obj): def get_auth_token(self, obj):
"""generate auth token"""
refresh = RefreshToken.for_user(obj) refresh = RefreshToken.for_user(obj)
access_token = str(refresh.access_token) access_token = str(refresh.access_token)
return access_token return access_token
def create(self, validated_data): def create(self, validated_data):
"""fetch data"""
email = validated_data.get('email') email = validated_data.get('email')
user_type = self.context user_type = self.context
password = validated_data.get('password') password = validated_data.get('password')
try: try:
"""Create user profile"""
user = User.objects.create_user(username=email, email=email, password=password) user = User.objects.create_user(username=email, email=email, password=password)
UserProfile.objects.create(user=user, user_type=user_type) UserProfile.objects.create(user=user, user_type=user_type)
if user_type == '1':
Junior.objects.create(auth=user)
if user_type == '2':
Guardian.objects.create(user=user)
return user return user
except: except Exception as e:
raise serializers.ValidationError({"details":ERROR_CODE['2021']}) """Error handling"""
logging.error(e)
def save(self, **kwargs): otp = UserEmailOtp.objects.filter(email=email).last()
with transaction.atomic(): otp_verified = False
instance = super().save(**kwargs) if otp and otp.is_verified:
return instance otp_verified = True
raise serializers.ValidationError({"details":ERROR_CODE['2021'], "otp_verified":bool(otp_verified),
"code": 400, "status":"failed",
})
class CreateGuardianSerializer(serializers.ModelSerializer): class CreateGuardianSerializer(serializers.ModelSerializer):
"""Create guardian serializer"""
"""Basic info"""
first_name = serializers.SerializerMethodField('get_first_name') first_name = serializers.SerializerMethodField('get_first_name')
last_name = serializers.SerializerMethodField('get_last_name') last_name = serializers.SerializerMethodField('get_last_name')
email = serializers.SerializerMethodField('get_email') email = serializers.SerializerMethodField('get_email')
"""Contact details"""
phone = serializers.CharField(max_length=20, required=False) phone = serializers.CharField(max_length=20, required=False)
family_name = serializers.CharField(max_length=100, required=False)
country_code = serializers.IntegerField(required=False) country_code = serializers.IntegerField(required=False)
family_name = serializers.CharField(max_length=100, required=False)
dob = serializers.DateField(required=False) dob = serializers.DateField(required=False)
referral_code = serializers.CharField(max_length=100, required=False) referral_code = serializers.CharField(max_length=100, required=False)
image = serializers.ImageField(required=False)
class Meta(object): class Meta(object):
"""Meta info"""
model = Guardian model = Guardian
fields = ['first_name', 'last_name', 'email', 'phone', 'family_name', 'gender', 'country_code', 'dob', 'referral_code', 'passcode', fields = ['first_name', 'last_name', 'email', 'phone', 'family_name', 'gender', 'country_code',
'is_complete_profile'] 'dob', 'referral_code', 'passcode', 'is_complete_profile', 'referral_code_used',
'country_name', 'image']
def get_first_name(self,obj): def get_first_name(self,obj):
"""first name of guardian"""
return obj.user.first_name return obj.user.first_name
def get_last_name(self,obj): def get_last_name(self,obj):
"""last name of guardian"""
return obj.user.last_name return obj.user.last_name
def get_email(self,obj): def get_email(self,obj):
"""emailof guardian"""
return obj.user.email return obj.user.email
def create(self, validated_data): def create(self, validated_data):
"""Create guardian profile"""
# phone_number = validated_data.get('phone', None)
# guardian_data = Guardian.objects.filter(phone=phone_number)
# junior_data = Junior.objects.filter(phone=phone_number)
# if phone_number and (guardian_data or junior_data):
# raise serializers.ValidationError({"details": ERROR_CODE['2012']})
user = User.objects.filter(username=self.context['user']).last() user = User.objects.filter(username=self.context['user']).last()
if user: if user:
"""Save first and last name of guardian"""
if self.context.get('first_name') != '' and self.context.get('last_name') != '':
user.first_name = self.context.get('first_name', user.first_name) user.first_name = self.context.get('first_name', user.first_name)
user.last_name = self.context.get('last_name', user.last_name) user.last_name = self.context.get('last_name', user.last_name)
user.save() user.save()
"""Create guardian data"""
guardian, created = Guardian.objects.get_or_create(user=self.context['user']) guardian, created = Guardian.objects.get_or_create(user=self.context['user'])
if created: if created:
"""Create referral code and guardian code"""
guardian.referral_code = ''.join([str(random.randrange(9)) for _ in range(4)]) guardian.referral_code = ''.join([str(random.randrange(9)) for _ in range(4)])
guardian.guardian_code = ''.join([str(random.randrange(9)) for _ in range(4)]) guardian.guardian_code = ''.join([str(random.randrange(9)) for _ in range(4)])
if guardian: if guardian:
guardian.phone = validated_data.get('phone', guardian.phone) """update details according to the data get from request"""
guardian.gender = validated_data.get('gender',guardian.gender) guardian.gender = validated_data.get('gender',guardian.gender)
guardian.family_name = validated_data.get('family_name', guardian.family_name) guardian.family_name = validated_data.get('family_name', guardian.family_name)
guardian.dob = validated_data.get('dob',guardian.dob) guardian.dob = validated_data.get('dob',guardian.dob)
"""Update country code and phone number"""
guardian.phone = validated_data.get('phone', guardian.phone)
guardian.country_code = validated_data.get('country_code', guardian.country_code)
guardian.passcode = validated_data.get('passcode', guardian.passcode) guardian.passcode = validated_data.get('passcode', guardian.passcode)
complete_profile_field = all([guardian.phone, guardian.gender, guardian.family_name, guardian.country_name = validated_data.get('country_name', guardian.country_name)
guardian.referral_code_used = validated_data.get('referral_code_used', guardian.referral_code_used)
"""Complete profile of the junior if below all data are filled"""
complete_profile_field = all([guardian.phone, guardian.gender, guardian.family_name, guardian.country_name,
guardian.dob, guardian.country_code, user.first_name, user.last_name]) guardian.dob, guardian.country_code, user.first_name, user.last_name])
guardian.is_complete_profile = False guardian.is_complete_profile = False
if complete_profile_field: if complete_profile_field:
guardian.is_complete_profile = True guardian.is_complete_profile = True
guardian.country_code = validated_data.get('country_code', guardian.country_code) image = validated_data.pop('image', None)
if image:
filename = f"images/{image.name}"
image_url = upload_image_to_alibaba(image, filename)
guardian.image = image_url
guardian.save() guardian.save()
return guardian return guardian
def save(self, **kwargs): def save(self, **kwargs):
"""Save the data into junior table"""
with transaction.atomic(): with transaction.atomic():
instance = super().save(**kwargs) instance = super().save(**kwargs)
return instance return instance
@@ -1,3 +1,5 @@
"""Test file of Guardian"""
"""Third party Django app"""
from django.test import TestCase from django.test import TestCase
# Create your tests here. # Create your tests here.
@@ -1,17 +1,19 @@
""" Urls files""" """ Urls files"""
"""Django import""" """Django import"""
from django.urls import path, include from django.urls import path, include
from rest_framework.decorators import api_view
from .views import SignupViewset, UpdateGuardianProfile from .views import SignupViewset, UpdateGuardianProfile
"""Third party import""" """Third party import"""
from rest_framework import routers from rest_framework import routers
"""Router""" """Define Router"""
router = routers.SimpleRouter() router = routers.SimpleRouter()
"""API End points with router""" """API End points with router"""
"""Sign up API"""
router.register('sign-up', SignupViewset, basename='sign-up') router.register('sign-up', SignupViewset, basename='sign-up')
router.register('complete-guardian-profile', UpdateGuardianProfile, basename='update-guardian-profile') """Create guardian profile API"""
router.register('create-guardian-profile', UpdateGuardianProfile, basename='update-guardian-profile')
"""Define Url pattern"""
urlpatterns = [ urlpatterns = [
path('api/v1/', include(router.urls)), path('api/v1/', include(router.urls)),
] ]
+13
View File
@@ -0,0 +1,13 @@
import oss2
from django.conf import settings
import tempfile
def upload_image_to_alibaba(image, filename):
# Save the image object to a temporary file
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
temp_file.write(image.read())
auth = oss2.Auth(settings.ALIYUN_OSS_ACCESS_KEY_ID, settings.ALIYUN_OSS_ACCESS_KEY_SECRET)
bucket = oss2.Bucket(auth, settings.ALIYUN_OSS_ENDPOINT, settings.ALIYUN_OSS_BUCKET_NAME)
# Upload the temporary file to Alibaba OSS
bucket.put_object_from_file(filename, temp_file.name)
return f"https://{settings.ALIYUN_OSS_BUCKET_NAME}.{settings.ALIYUN_OSS_ENDPOINT}/{filename}"
@@ -1,45 +1,48 @@
from django.shortcuts import render """Views of Guardian"""
from rest_framework import (pagination, viewsets, status, generics, mixins) """Third party Django app"""
from .serializers import CreateGuardianSerializer
from rest_framework.decorators import action
from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
from rest_framework import viewsets, status
from rest_framework.response import Response
from .serializers import UserSerializer
from django.contrib.auth.models import User
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from base.constants import GUARDIAN, JUNIOR, SUPERUSER from rest_framework import viewsets, status
"""Import Django app"""
from .serializers import UserSerializer, CreateGuardianSerializer
from .models import Guardian
from junior.models import Junior from junior.models import Junior
from account.models import UserEmailOtp from account.models import UserEmailOtp
from .tasks import generate_otp from .tasks import generate_otp
from account.utils import send_otp_email from account.utils import send_otp_email
from account.utils import custom_response, custom_error_response from account.utils import custom_response, custom_error_response
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
# Create your views here.
class SignupViewset(viewsets.ModelViewSet): class SignupViewset(viewsets.ModelViewSet):
"""Signup view set"""
serializer_class = UserSerializer serializer_class = UserSerializer
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
"""Create user profile"""
serializer = UserSerializer(context=request.data['user_type'], data=request.data) serializer = UserSerializer(context=request.data['user_type'], data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
"""Generate otp"""
otp = generate_otp() otp = generate_otp()
UserEmailOtp.objects.create(email=request.data['email'], otp=otp) UserEmailOtp.objects.create(email=request.data['email'], otp=otp, user_type=str(request.data['user_type']))
"""Send email to the register user"""
send_otp_email(request.data['email'], otp) send_otp_email(request.data['email'], otp)
return custom_response(SUCCESS_CODE['3001'], {"email_otp": otp}, return custom_response(SUCCESS_CODE['3001'], {"email_otp": otp},
response_status=status.HTTP_200_OK) response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class UpdateGuardianProfile(viewsets.ViewSet): class UpdateGuardianProfile(viewsets.ViewSet):
"""Update guardian profile"""
serializer_class = CreateGuardianSerializer serializer_class = CreateGuardianSerializer
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
serializer = CreateGuardianSerializer(context={"user":request.user,"first_name":request.data.get('first_name', ''), """Create guardian profile"""
"last_name": request.data.get('last_name',' ')}, data=request.data) serializer = CreateGuardianSerializer(context={"user":request.user,
"first_name":request.data.get('first_name', ''),
"last_name": request.data.get('last_name',' ')},
data=request.data)
if serializer.is_valid(): if serializer.is_valid():
"""save serializer"""
serializer.save() serializer.save()
return custom_response(None, serializer.data,response_status=status.HTTP_200_OK) return custom_response(None, serializer.data,response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
@@ -1,9 +1,14 @@
"""Junior admin"""
"""Third party Django app"""
from django.contrib import admin from django.contrib import admin
"""Import Django app"""
from .models import Junior from .models import Junior
# Register your models here. # Register your models here.
@admin.register(Junior) @admin.register(Junior)
class JuniorAdmin(admin.ModelAdmin): class JuniorAdmin(admin.ModelAdmin):
"""Junior Admin"""
list_display = ['auth'] list_display = ['auth']
def __str__(self): def __str__(self):
"""Return email id"""
return self.auth__email return self.auth__email
+3 -1
View File
@@ -1,6 +1,8 @@
"""App file"""
"""Import AppConfig"""
from django.apps import AppConfig from django.apps import AppConfig
class JuniorConfig(AppConfig): class JuniorConfig(AppConfig):
"""Junior config"""
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = 'django.db.models.BigAutoField'
name = 'junior' name = 'junior'
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-27 13:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('junior', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='junior',
name='country_name',
field=models.CharField(blank=True, default=None, max_length=30, null=True),
),
]
+18
View File
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-28 10:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('junior', '0002_junior_country_name'),
]
operations = [
migrations.AddField(
model_name='junior',
name='image',
field=models.ImageField(blank=True, default=None, null=True, upload_to='images/'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-29 06:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('junior', '0003_junior_image'),
]
operations = [
migrations.AlterField(
model_name='junior',
name='image',
field=models.ImageField(blank=True, default=None, null=True, upload_to=''),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-29 12:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('junior', '0004_alter_junior_image'),
]
operations = [
migrations.AddField(
model_name='junior',
name='is_verified',
field=models.BooleanField(default=False),
),
]
+14 -3
View File
@@ -1,25 +1,35 @@
"""Junior model """
"""Import django"""
from django.db import models from django.db import models
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from base.constants import GENDERS
from guardian.models import Guardian
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
"""Import django app"""
from base.constants import GENDERS
User = get_user_model() User = get_user_model()
# Create your models here. # Create your models here.
class Junior(models.Model): class Junior(models.Model):
"""Junior model"""
auth = models.ForeignKey(User, on_delete=models.CASCADE, related_name='junior_profile', verbose_name='Email') auth = models.ForeignKey(User, on_delete=models.CASCADE, related_name='junior_profile', verbose_name='Email')
"""Contact details"""
phone = models.CharField(max_length=31, null=True, blank=True, default=None) phone = models.CharField(max_length=31, null=True, blank=True, default=None)
country_code = models.IntegerField(blank=True, null=True) country_code = models.IntegerField(blank=True, null=True)
country_name = models.CharField(max_length=30, null=True, blank=True, default=None)
"""Personal info"""
gender = models.CharField(max_length=10, choices=GENDERS, null=True, blank=True, default=None) gender = models.CharField(max_length=10, choices=GENDERS, null=True, blank=True, default=None)
dob = models.DateField(max_length=15, null=True, blank=True, default=None) dob = models.DateField(max_length=15, null=True, blank=True, default=None)
# image = models.ImageField(upload_to='images/') image = models.ImageField(null=True, blank=True, default=None)
"""Codes"""
junior_code = models.CharField(max_length=10, null=True, blank=True, default=None) junior_code = models.CharField(max_length=10, null=True, blank=True, default=None)
guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True) guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True)
referral_code = models.CharField(max_length=10, null=True, blank=True, default=None) referral_code = models.CharField(max_length=10, null=True, blank=True, default=None)
referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None) referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None)
"""Profile activity"""
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
is_complete_profile = models.BooleanField(default=False) is_complete_profile = models.BooleanField(default=False)
passcode = models.IntegerField(null=True, blank=True, default=None) passcode = models.IntegerField(null=True, blank=True, default=None)
is_verified = models.BooleanField(default=False)
"""Profile created and updated time"""
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
@@ -29,4 +39,5 @@ class Junior(models.Model):
verbose_name = 'Junior' verbose_name = 'Junior'
def __str__(self): def __str__(self):
"""Return email id"""
return f'{self.auth}' return f'{self.auth}'
@@ -1,28 +1,32 @@
"""Serializer file for junior"""
"""Import Django 3rd party app"""
from rest_framework import serializers from rest_framework import serializers
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .models import Guardian
from django.db import transaction from django.db import transaction
import random import random
from account.models import UserProfile """Import django app"""
from junior.models import Junior from junior.models import Junior
from base.constants import GENDERS, GUARDIAN, JUNIOR, SUPERUSER from guardian.utils import upload_image_to_alibaba
from rest_framework_simplejwt.tokens import RefreshToken
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from django.contrib.postgres.fields import ArrayField from guardian.models import Guardian
class ListCharField(serializers.ListField): class ListCharField(serializers.ListField):
"""Serializer for Array field"""
child = serializers.CharField() child = serializers.CharField()
def to_representation(self, data): def to_representation(self, data):
"""to represent the data"""
return data return data
def to_internal_value(self, data): def to_internal_value(self, data):
"""internal value"""
if isinstance(data, list): if isinstance(data, list):
return data return data
raise serializers.ValidationError({"details":"Invalid input. Expected a list of strings."}) raise serializers.ValidationError({"details":ERROR_CODE['2025']})
class CreateJuniorSerializer(serializers.ModelSerializer): class CreateJuniorSerializer(serializers.ModelSerializer):
"""Create junior serializer"""
first_name = serializers.SerializerMethodField('get_first_name') first_name = serializers.SerializerMethodField('get_first_name')
last_name = serializers.SerializerMethodField('get_last_name') last_name = serializers.SerializerMethodField('get_last_name')
email = serializers.SerializerMethodField('get_email') email = serializers.SerializerMethodField('get_email')
@@ -31,43 +35,75 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
dob = serializers.DateField(required=False) dob = serializers.DateField(required=False)
referral_code = serializers.CharField(max_length=100, required=False) referral_code = serializers.CharField(max_length=100, required=False)
guardian_code = ListCharField(required=False) guardian_code = ListCharField(required=False)
image = serializers.ImageField(required=False)
class Meta(object): class Meta(object):
"""Meta info"""
model = Junior model = Junior
fields = ['first_name', 'last_name', 'email', 'phone', 'gender', 'country_code', 'dob', 'referral_code', fields = ['first_name', 'last_name', 'email', 'phone', 'gender', 'country_code', 'dob', 'referral_code',
'passcode', 'is_complete_profile', 'guardian_code'] 'passcode', 'is_complete_profile', 'guardian_code', 'referral_code_used',
'country_name', 'image']
def get_first_name(self,obj): def get_first_name(self,obj):
"""first name of junior"""
return obj.auth.first_name return obj.auth.first_name
def get_last_name(self,obj): def get_last_name(self,obj):
"""last name of junior"""
return obj.auth.last_name return obj.auth.last_name
def get_email(self,obj): def get_email(self,obj):
"""email of junior"""
return obj.auth.email return obj.auth.email
def create(self, validated_data): def create(self, validated_data):
"""Create junior profile"""
image = validated_data.get('image', None)
# phone_number = validated_data.get('phone', None)
# guardian_data = Guardian.objects.filter(phone=phone_number)
# junior_data = Junior.objects.filter(phone=phone_number)
# if phone_number and (junior_data or guardian_data):
# raise serializers.ValidationError({"details":ERROR_CODE['2012']})
user = User.objects.filter(username=self.context['user']).last() user = User.objects.filter(username=self.context['user']).last()
if user: if user:
"""Save first and last name of junior"""
if self.context.get('first_name') != '' and self.context.get('last_name') != '':
user.first_name = self.context.get('first_name', user.first_name) user.first_name = self.context.get('first_name', user.first_name)
user.last_name = self.context.get('last_name', user.last_name) user.last_name = self.context.get('last_name', user.last_name)
user.save() user.save()
"""Create junior data"""
junior, created = Junior.objects.get_or_create(auth=self.context['user']) junior, created = Junior.objects.get_or_create(auth=self.context['user'])
if created: if created:
"""Create referral code and junior code"""
junior.referral_code = ''.join([str(random.randrange(9)) for _ in range(4)]) junior.referral_code = ''.join([str(random.randrange(9)) for _ in range(4)])
junior.junior_code = ''.join([str(random.randrange(9)) for _ in range(4)]) junior.junior_code = ''.join([str(random.randrange(9)) for _ in range(4)])
if junior: if junior:
junior.phone = validated_data.get('phone', junior.phone) """update details according to the data get from request"""
junior.gender = validated_data.get('gender',junior.gender) junior.gender = validated_data.get('gender',junior.gender)
"""Update guardian code"""
junior.guardian_code = validated_data.get('guardian_code', junior.guardian_code) junior.guardian_code = validated_data.get('guardian_code', junior.guardian_code)
junior.dob = validated_data.get('dob',junior.dob) junior.dob = validated_data.get('dob',junior.dob)
junior.passcode = validated_data.get('passcode', junior.passcode) junior.passcode = validated_data.get('passcode', junior.passcode)
junior.is_complete_profile = validated_data.get('is_complete_profile', junior.is_complete_profile) junior.country_name = validated_data.get('country_name', junior.country_name)
"""Update country code and phone number"""
junior.phone = validated_data.get('phone', junior.phone)
junior.country_code = validated_data.get('country_code', junior.country_code) junior.country_code = validated_data.get('country_code', junior.country_code)
junior.referral_code_used = validated_data.get('referral_code_used', junior.referral_code_used)
"""Complete profile of the junior if below all data are filled"""
complete_profile_field = all([junior.phone, junior.gender, junior.country_name,
junior.dob, junior.country_code, user.first_name, user.last_name])
junior.is_complete_profile = False
if complete_profile_field:
junior.is_complete_profile = True
if image:
filename = f"images/{image.name}"
image_url = upload_image_to_alibaba(image, filename)
junior.image = image_url
junior.save() junior.save()
return junior return junior
def save(self, **kwargs): def save(self, **kwargs):
"""Save the data into junior table"""
with transaction.atomic(): with transaction.atomic():
instance = super().save(**kwargs) instance = super().save(**kwargs)
return instance return instance
@@ -1,3 +1,5 @@
"""Junior test file"""
"""Import TestCase"""
from django.test import TestCase from django.test import TestCase
# Create your tests here. # Create your tests here.
+4 -2
View File
@@ -1,7 +1,6 @@
""" Urls files""" """ Urls files"""
"""Django import""" """Django import"""
from django.urls import path, include from django.urls import path, include
from rest_framework.decorators import api_view
from .views import UpdateJuniorProfile, ValidateGuardianCode from .views import UpdateJuniorProfile, ValidateGuardianCode
"""Third party import""" """Third party import"""
from rest_framework import routers from rest_framework import routers
@@ -10,8 +9,11 @@ from rest_framework import routers
router = routers.SimpleRouter() router = routers.SimpleRouter()
"""API End points with router""" """API End points with router"""
router.register('complete-junior-profile', UpdateJuniorProfile, basename='profile-update') """Create junior profile API"""
router.register('create-junior-profile', UpdateJuniorProfile, basename='profile-update')
"""validate guardian code API"""
router.register('validate-guardian-code', ValidateGuardianCode, basename='validate-guardian-code') router.register('validate-guardian-code', ValidateGuardianCode, basename='validate-guardian-code')
"""Define url pattern"""
urlpatterns = [ urlpatterns = [
path('api/v1/', include(router.urls)), path('api/v1/', include(router.urls)),
] ]
+16 -16
View File
@@ -1,40 +1,40 @@
from django.shortcuts import render """Junior view file"""
from rest_framework import (pagination, viewsets, status, generics, mixins)
from rest_framework.decorators import action
from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
from rest_framework import viewsets, status from rest_framework import viewsets, status
from rest_framework.response import Response
from .serializers import CreateJuniorSerializer
from django.contrib.auth.models import User
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from base.constants import GUARDIAN, JUNIOR, SUPERUSER """Django app import"""
from junior.models import Junior from junior.models import Junior
from .serializers import CreateJuniorSerializer
from guardian.models import Guardian from guardian.models import Guardian
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from account.utils import custom_response, custom_error_response from account.utils import custom_response, custom_error_response
# Create your views here.
class UpdateJuniorProfile(viewsets.ViewSet): class UpdateJuniorProfile(viewsets.ViewSet):
"""Update junior profile"""
serializer_class = CreateJuniorSerializer serializer_class = CreateJuniorSerializer
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
serializer = CreateJuniorSerializer(context={"user":request.user,"first_name":request.data.get('first_name', ''), """Use CreateJuniorSerializer"""
"last_name": request.data.get('last_name',' ')}, data=request.data) serializer = CreateJuniorSerializer(context={"user":request.user,
"first_name":request.data.get('first_name', ''),
"last_name": request.data.get('last_name',' ')},
data=request.data)
if serializer.is_valid(): if serializer.is_valid():
"""save serializer"""
serializer.save() serializer.save()
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class ValidateGuardianCode(viewsets.ViewSet): class ValidateGuardianCode(viewsets.ViewSet):
"""Check guardian code exist or not"""
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
guardian_code = request.data.get('guardian_code') """check guardian code"""
guardian_code = self.request.GET.get('guardian_code').split(',')
for code in guardian_code: for code in guardian_code:
guardian_data = Guardian.objects.filter(guardian_code=code).exists() guardian_data = Guardian.objects.filter(guardian_code=code).exists()
if guardian_data: if guardian_data:
return custom_response(SUCCESS_CODE['3028'], response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3013'], response_status=status.HTTP_200_OK)
else: else:
return custom_error_response(ERROR_CODE["2022"], response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE["2022"], response_status=status.HTTP_400_BAD_REQUEST)
+4
View File
@@ -1,14 +1,18 @@
#!/usr/bin/env python #!/usr/bin/env python
"""Django's command-line utility for administrative tasks.""" """Django's command-line utility for administrative tasks."""
"""Django import"""
import os import os
import sys import sys
def main(): def main():
"""Main function"""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'zod_bank.settings') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'zod_bank.settings')
try: try:
"""Import execute from command line function"""
from django.core.management import execute_from_command_line from django.core.management import execute_from_command_line
except ImportError as exc: except ImportError as exc:
"""Show Exception error"""
raise ImportError( raise ImportError(
"Couldn't import Django. Are you sure it's installed and " "Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you " "available on your PYTHONPATH environment variable? Did you "
@@ -19,6 +19,6 @@ upstream web {
location /static { location /static {
autoindex on; autoindex on;
alias /usr/src/app/zod_bank/static/; alias /usr/src/app/static/;
} }
} }
@@ -1,19 +1,25 @@
aliyun-python-sdk-core==2.13.36 aliyun-python-sdk-core==2.13.36
aliyun-python-sdk-dysmsapi==2.1.2 aliyun-python-sdk-dysmsapi==2.1.2
aliyun-python-sdk-kms==2.16.1
aliyun-python-sdk-sts==3.1.1
amqp==5.1.1 amqp==5.1.1
asgiref==3.7.2 asgiref==3.7.2
async-timeout==4.0.2 async-timeout==4.0.2
billiard==4.1.0 billiard==4.1.0
boto3==1.26.157 boto3==1.26.157
botocore==1.29.157 botocore==1.29.157
cachetools==5.3.1
celery==5.3.1 celery==5.3.1
certifi==2023.5.7
cffi==1.15.1 cffi==1.15.1
channels==4.0.0 channels==4.0.0
channels-redis==4.1.0 channels-redis==4.1.0
charset-normalizer==3.1.0
click==8.1.3 click==8.1.3
click-didyoumean==0.3.0 click-didyoumean==0.3.0
click-plugins==1.1.1 click-plugins==1.1.1
click-repl==0.3.0 click-repl==0.3.0
crcmod==1.7
cron-descriptor==1.4.0 cron-descriptor==1.4.0
cryptography==41.0.1 cryptography==41.0.1
decouple==0.0.7 decouple==0.0.7
@@ -23,20 +29,33 @@ django-celery-results==2.5.1
django-cors-headers==4.1.0 django-cors-headers==4.1.0
django-dotenv==1.4.2 django-dotenv==1.4.2
django-extensions==3.2.3 django-extensions==3.2.3
django-phonenumber-field==7.1.0
django-render-block==0.9.2
django-ses==3.5.0 django-ses==3.5.0
django-smtp-ssl==1.0
django-storages==1.13.2 django-storages==1.13.2
django-templated-email==3.0.1
django-timezone-field==5.1 django-timezone-field==5.1
djangorestframework==3.14.0 djangorestframework==3.14.0
djangorestframework-simplejwt==5.2.2 djangorestframework-simplejwt==5.2.2
drf-yasg==1.21.6 drf-yasg==1.21.6
google-auth==2.21.0
gunicorn==20.1.0
idna==3.4
inflection==0.5.1 inflection==0.5.1
jmespath==0.10.0 jmespath==0.10.0
kombu==5.3.1 kombu==5.3.1
msgpack==1.0.5 msgpack==1.0.5
oss2==2.18.0
packaging==23.1 packaging==23.1
phonenumbers==8.13.15
Pillow==9.5.0
prompt-toolkit==3.0.38 prompt-toolkit==3.0.38
psycopg==3.1.9 psycopg==3.1.9
pyasn1==0.5.0
pyasn1-modules==0.3.0
pycparser==2.21 pycparser==2.21
pycryptodome==3.18.0
PyJWT==2.7.0 PyJWT==2.7.0
python-crontab==2.7.1 python-crontab==2.7.1
python-dateutil==2.8.2 python-dateutil==2.8.2
@@ -44,6 +63,8 @@ python-dotenv==1.0.0
pytz==2023.3 pytz==2023.3
PyYAML==6.0 PyYAML==6.0
redis==4.5.5 redis==4.5.5
requests==2.31.0
rsa==4.9
s3transfer==0.6.1 s3transfer==0.6.1
six==1.16.0 six==1.16.0
sqlparse==0.4.4 sqlparse==0.4.4
-38
View File
@@ -1,38 +0,0 @@
from django.core.mail import send_mail
from django.conf import settings
import random
from rest_framework import viewsets, status
from rest_framework.response import Response
from templated_email import send_templated_mail
def send_otp_email(recipient_email, otp):
from_email = settings.EMAIL_HOST_USER
recipient_list = [recipient_email]
send_templated_mail(
template_name='email_otp_verification.email',
from_email=from_email,
recipient_list=recipient_list,
context={
'otp': otp
}
)
return otp
def custom_response(detail, data=None, response_status=status.HTTP_200_OK):
"""Custom response code"""
if not data:
data = None
return Response({"data": data, "message": detail, "status": "success", "code": response_status})
def custom_error_response(detail, response_status):
"""
function is used for getting same global error response for all
:param detail: error message .
:param response_status: http status.
:return: Json response
"""
if not detail:
detail = {}
return Response({"error": detail, "status": "failed", "code": response_status})
-166
View File
@@ -1,166 +0,0 @@
from rest_framework import viewsets, status, views
from rest_framework.decorators import action
import random
from django.contrib.auth import authenticate, login
from guardian.models import Guardian
from junior.models import Junior
from account.models import UserProfile, UserPhoneOtp, UserEmailOtp
from django.contrib.auth.models import User
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer)
from django.views.decorators.csrf import csrf_exempt
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.tokens import RefreshToken
from base.messages import ERROR_CODE, SUCCESS_CODE
from guardian.tasks import generate_otp
from django.conf import settings
from account.utils import custom_response, custom_error_response
from django.core.mail import EmailMessage
from django.core.mail import send_mail
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from templated_email import send_templated_mail
import secrets
class ChangePasswordAPIView(views.APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
print("request.data====>",request.data)
print("request.user====>", request.user)
serializer = ChangePasswordSerializer(context=request.user, data=request.data)
if serializer.is_valid():
serializer.save()
return custom_response(SUCCESS_CODE['3006'], response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class ResetPasswordAPIView(views.APIView):
def post(self, request):
print("request.data====>",request.data)
serializer = ResetPasswordSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return custom_response(SUCCESS_CODE['3006'], response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class ForgotPasswordAPIView(views.APIView):
def post(self, request):
serializer = ForgotPasswordSerializer(data=request.data)
if serializer.is_valid():
email = serializer.validated_data['email']
try:
User.objects.get(email=email)
except User.DoesNotExist:
return custom_error_response(ERROR_CODE['2004'], response_status=status.HTTP_404_NOT_FOUND)
verification_code = ''.join([str(random.randrange(9)) for _ in range(6)])
# Send the verification code to the user's email
from_email = settings.EMAIL_HOST_USER
recipient_list = [email]
send_templated_mail(
template_name='email_reset_verification.email',
from_email=from_email,
recipient_list=recipient_list,
context={
'verification_code': verification_code
}
)
UserEmailOtp.objects.create(email=email, otp=verification_code)
return custom_response(SUCCESS_CODE['3015'], {'verification_code': verification_code},
response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class SendPhoneOtp(viewsets.ModelViewSet):
"""Send otp on phone"""
def create(self, request, *args, **kwargs):
otp = generate_otp()
UserPhoneOtp.objects.create(country_code=self.request.data['country_code'],
phone=self.request.data['phone'], otp=otp)
return custom_response(None, {'phone_otp':otp}, response_status=status.HTTP_200_OK)
class UserPhoneVerification(viewsets.ModelViewSet):
"""Send otp on phone"""
def list(self, request, *args, **kwargs):
try:
phone_data = UserPhoneOtp.objects.filter(phone=request.data['phone'],
otp=request.data['otp']).last()
if phone_data:
phone_data.is_verified = True
phone_data.save()
return custom_response(SUCCESS_CODE['3027'], response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
class UserLogin(viewsets.ViewSet):
@action(methods=['post'], detail=False)
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(request, username=username, password=password)
try:
if user is not None:
login(request, user)
guardian_data = Guardian.objects.filter(user__username=username, is_complete_profile=True).last()
if guardian_data:
serializer = GuardianSerializer(guardian_data)
junior_data = Junior.objects.filter(auth__username=username, is_complete_profile=True).last()
if junior_data:
serializer = JuniorSerializer(junior_data)
if user.is_superuser:
serializer = SuperUserSerializer(user)
return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
except Exception as e:
user_profile_data = UserProfile.objects.filter(user__username=username).last()
email_verified = UserEmailOtp.objects.filter(email=username).last()
refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token)
data = {"auth_token":access_token, "is_profile_complete": False,
"user_role": user_profile_data.user_type,
}
is_verified = False
if email_verified:
is_verified = email_verified.is_verified
if not is_verified:
otp = generate_otp()
email_verified.otp = otp
email_verified.save()
data.update({"email_otp":otp})
return custom_response(ERROR_CODE['2024'], {"email_otp":otp, "is_email_verified": is_verified},
response_status=status.HTTP_400_BAD_REQUEST)
data.update({"is_email_verified": is_verified})
return custom_response(None, data, response_status=status.HTTP_200_OK)
class UserEmailVerification(viewsets.ModelViewSet):
"""User Email verification"""
serializer_class = EmailVerificationSerializer
def list(self, request, *args, **kwargs):
try:
email_data = UserEmailOtp.objects.filter(email=request.data['email'],
otp=request.data['otp']).last()
if email_data:
email_data.is_verified = True
email_data.save()
return custom_response(SUCCESS_CODE['3011'], response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
class ReSendEmailOtp(viewsets.ModelViewSet):
"""Send otp on phone"""
def create(self, request, *args, **kwargs):
otp = generate_otp()
if User.objects.filter(email=request.data['email']):
UserEmailOtp.objects.create(email=request.data['email'], otp=otp)
return custom_response(None, {'email_otp': otp}, response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2023"], response_status=status.HTTP_400_BAD_REQUEST)
-16
View File
@@ -1,16 +0,0 @@
"""
module containing override conflict error class
"""
# third party imports
from django.utils.translation import ugettext_lazy as _
from rest_framework import status
from rest_framework.exceptions import APIException
class ConflictError(APIException):
"""
Override conflict error
"""
status_code = status.HTTP_409_CONFLICT
default_detail = _('Not allowed request.')
default_code = 'conflict_error'
-49
View File
@@ -1,49 +0,0 @@
"""
This module contains search methods that can be used to search over a particular field in a specific model.
Update SEARCH_MAP dict for searching with model name and fields name
"""
# python imports
import operator
from functools import reduce
# third party imports
from django.contrib.auth import get_user_model
from django.db.models import Q
SEARCH_MAP = {
get_user_model(): {'search_fields': ['first_name__icontains', 'last_name__icontains', 'username__icontains']}
}
def search_query(search_by, search_term):
"""
:param search_by: search fields
:param search_term: search value
:return: return query
"""
query = []
if search_by:
for key in search_by:
query.append({key: search_term})
return query
def get_search_fields(model):
"""
:param model: model name
:return: dict of searching field name
"""
return SEARCH_MAP[model]['search_fields']
def global_search(search_data, model_name):
"""
:param search_data: search value
:param model_name: model name
:return: query
"""
# get search fields for the above model
search_fields = get_search_fields(model_name)
# build query
query = search_query(search_fields, search_data)
return model_name.objects.filter(reduce(operator.or_, [Q(**x) for x in query]))
@@ -56,8 +56,9 @@ INSTALLED_APPS = [
'account', 'account',
'junior', 'junior',
'guardian', 'guardian',
# 'social_django'
] ]
# CSRF_COOKIE_SECURE = False
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
@@ -95,7 +96,7 @@ REST_FRAMEWORK = {
] ]
} }
SIMPLE_JWT = { SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15), 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=50),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7), 'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
} }
# Database # Database
@@ -168,35 +169,52 @@ CORS_ALLOW_HEADERS = (
'x-requested-with', 'x-requested-with',
) )
# Static files (CSS, JavaScript, Images) """Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/ https://docs.djangoproject.com/en/3.0/howto/static-files/"""
# AUTHENTICATION_BACKENDS = [
# 'social_core.backends.google.GoogleOAuth2',
# 'django.contrib.auth.backends.ModelBackend',
# ]
# #
# MAIL_MAILER='smtp' # LOGIN_URL = 'login'
# MAIL_HOST='smtp.gmail.com' # LOGIN_REDIRECT_URL = 'home'
# MAIL_PORT=587 # LOGOUT_URL = 'logout'
# mail_username='[email protected]' # LOGOUT_REDIRECT_URL = 'login'
# MAIL_PASSWORD='ghwdmznwwslvchga'
# MAIL_ENCRYPTION='tls'
# mail_from_address='[email protected]'
# MAIL_FROM_NAME="${APP_NAME}"
# MAIL_MAILER='smtp' # SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = ''
# MAIL_HOST='smtp.gmail.com' # SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = ''
# MAIL_PORT=587
# mail_username='[email protected]'
# MAIL_PASSWORD='jaijain0912@'
# MAIL_ENCRYPTION='tls'
# mail_from_address='[email protected]'
# MAIL_FROM_NAME="${APP_NAME}"
# Email settings GOOGLE_CLIENT_ID = "182276566528-hlbjncs19fo502jposod6kft2p9k4grk.apps.googleusercontent.com"
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' GOOGLE_CLIENT_SECRET = "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"
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'ghwdmznwwslvchga' # Replace with your Gmail email password or App password
# EMAIL_BACKEND = os.getenv('EMAIL_BACKEND')
# EMAIL_HOST = os.getenv('EMAIL_HOST')
# EMAIL_PORT = os.getenv('EMAIL_PORT')
# EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS')
# EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER') # Replace with your Gmail email address
# EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD') # Replace with your Gmail email password or App password
# EMAIL_FROM_ADDRESS = os.getenv('EMAIL_FROM_ADDRESS')
STATIC_URL = '/static/' EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST="smtp.sendgrid.net"
EMAIL_PORT="587"
EMAIL_USE_TLS="True"
EMAIL_HOST_USER="apikey" # Replace with your Gmail email address
EMAIL_HOST_PASSWORD="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"
EMAIL_FROM_ADDRESS="[email protected]"
# ALIYUN_OSS_ACCESS_KEY_ID = os.getenv('ALIYUN_OSS_ACCESS_KEY_ID')
# ALIYUN_OSS_ACCESS_KEY_SECRET = os.getenv('ALIYUN_OSS_ACCESS_KEY_SECRET')
# ALIYUN_OSS_BUCKET_NAME = os.getenv('ALIYUN_OSS_BUCKET_NAME')
# ALIYUN_OSS_ENDPOINT = os.getenv('ALIYUN_OSS_ENDPOINT')
# ALIYUN_OSS_REGION = os.getenv('ALIYUN_OSS_REGION')
ALIYUN_OSS_ACCESS_KEY_ID="LTAI5t7w1gq1CswJtvxtEZTd"
ALIYUN_OSS_ACCESS_KEY_SECRET="6yknAFpP2gVMhCWAJwbAjCEw2eehpf"
ALIYUN_OSS_BUCKET_NAME="zod-dev"
ALIYUN_OSS_ENDPOINT="oss-me-central-1.aliyuncs.com"
ALIYUN_OSS_REGION="Global"
STATIC_URL = 'static/'
STATIC_ROOT = 'static'