diff --git a/account/migrations/0002_useremailotp_user_type.py b/account/migrations/0002_useremailotp_user_type.py new file mode 100644 index 0000000..9b8821a --- /dev/null +++ b/account/migrations/0002_useremailotp_user_type.py @@ -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), + ), + ] diff --git a/account/models.py b/account/models.py index ff8bb5d..43ab6e5 100644 --- a/account/models.py +++ b/account/models.py @@ -59,6 +59,7 @@ class UserEmailOtp(models.Model): """otp details""" otp = models.CharField(max_length=10) is_verified = models.BooleanField(default=False) + user_type = models.CharField(max_length=15, choices=USER_TYPE, null=True, blank=True, default=None) # OTP validity created_at = models.DateTimeField(auto_now_add=True) diff --git a/account/serializers.py b/account/serializers.py index afd923c..5f03fc2 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -12,6 +12,7 @@ from rest_framework import viewsets, status from rest_framework.decorators import action from django.contrib.auth import authenticate, login from rest_framework_simplejwt.tokens import RefreshToken +from guardian.utils import upload_image_to_alibaba class GoogleSignInSerializer(serializers.Serializer): """Google login Serializer""" @@ -20,7 +21,6 @@ class GoogleSignInSerializer(serializers.Serializer): def create(self, validated_data): """Create or update user model""" with transaction.atomic(): - print("validated_data====>",validated_data) if User.objects.filter(email__iexact=self.validated_data['email']).exists(): return User.objects.get(email__iexact=self.validated_data['email']) @@ -29,7 +29,34 @@ class GoogleSignInSerializer(serializers.Serializer): email=self.validated_data['email']) return instance +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): """Reset Password after verification""" verification_code = serializers.CharField(max_length=10) @@ -41,15 +68,10 @@ class ResetPasswordSerializer(serializers.Serializer): def create(self, validated_data): verification_code = validated_data.pop('verification_code') 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() - print("user_opt_details===>",user_opt_details) if user_opt_details: - print("qqqqqqqqqq") user_details = User.objects.filter(email=user_opt_details.email).last() if user_details: - print("333333333==>",user_details.password) user_details.set_password(password) user_details.save() return {'password':password} @@ -69,13 +91,14 @@ class ChangePasswordSerializer(serializers.Serializer): if self.context.password not in ('', None): if user.check_password(value): return value - raise serializers.ValidationError({"error":"Invalid Current password"}) + raise serializers.ValidationError({"details":ERROR_CODE['2015']}) def create(self, validated_data): 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() - print("user_details==>", user_details) if user_details: - print("333333333==>",user_details.password) user_details.set_password(new_password) user_details.save() return {'password':new_password} diff --git a/account/urls.py b/account/urls.py index eab8be4..b9501e6 100644 --- a/account/urls.py +++ b/account/urls.py @@ -5,7 +5,7 @@ from rest_framework.decorators import api_view """Third party import""" from rest_framework import routers from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp, - ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView) + ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage) """Router""" router = routers.SimpleRouter() @@ -17,10 +17,10 @@ router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp') router.register('user-phone-verification', UserPhoneVerification, basename='user-phone-verification') router.register('user-email-verification', UserEmailVerification, basename='user-email-verification') router.register('resend-email-otp', ReSendEmailOtp, basename='resend-email-otp') - urlpatterns = [ path('api/v1/', include(router.urls)), path('api/v1/forgot-password/', ForgotPasswordAPIView.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()) ] diff --git a/account/utils.py b/account/utils.py index f20ef19..bfc2399 100644 --- a/account/utils.py +++ b/account/utils.py @@ -6,7 +6,7 @@ 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 + from_email = settings.EMAIL_FROM_ADDRESS recipient_list = [recipient_email] send_templated_mail( template_name='email_otp_verification.email', diff --git a/account/views.py b/account/views.py index 69e4e95..38ba10a 100644 --- a/account/views.py +++ b/account/views.py @@ -9,7 +9,7 @@ from account.models import UserProfile, UserPhoneOtp, UserEmailOtp from django.contrib.auth.models import User from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer, ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer, - GoogleSignInSerializer) + GoogleSignInSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer) from rest_framework_simplejwt.tokens import RefreshToken from base.messages import ERROR_CODE, SUCCESS_CODE from guardian.tasks import generate_otp @@ -44,7 +44,19 @@ from templated_email import send_templated_mail # return custom_response(SUCCESS_CODE["3003"], response_status=status.HTTP_200_OK) # return custom_response(ERROR_CODE["2002"], 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] @@ -130,26 +142,26 @@ class UserLogin(viewsets.ViewSet): 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() + guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last() if guardian_data: - serializer = GuardianSerializer(guardian_data) - junior_data = Junior.objects.filter(auth__username=username, is_complete_profile=True).last() + serializer = GuardianSerializer(guardian_data).data + junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last() if junior_data: - serializer = JuniorSerializer(junior_data) - return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK) + 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) - 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, + "user_type": email_verified.user_type, } is_verified = False if email_verified: @@ -196,6 +208,16 @@ class UserEmailVerification(viewsets.ModelViewSet): 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) diff --git a/base/messages.py b/base/messages.py index 37507fd..f977ee7 100644 --- a/base/messages.py +++ b/base/messages.py @@ -35,7 +35,7 @@ ERROR_CODE = { "2009": "The user provided cannot be found or the reset password token has become invalid/timed out.", "2010": "Invalid Link.", "2011": "Your profile has not been completed yet.", - "2012": "Password and Confirm password should be same.", + "2012": "Phone number already used", "2013": "Invalid token.", "2014": "Your old password doesn't match.", "2015": "Invalid old password.", @@ -47,7 +47,9 @@ ERROR_CODE = { "2021": "Already register", "2022":"Invalid Guardian code", "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" } SUCCESS_CODE = { # Success code for password @@ -75,7 +77,8 @@ SUCCESS_CODE = { "3013": "Valid Guardian code", "3014": "Password has been updated successfully.", "3015": "Verification code sent on your email.", - "3016": "Send otp on your Email successfully" + "3016": "Send otp on your Email successfully", + "3017": "Profile image update successfully" } STATUS_CODE_ERROR = { diff --git a/guardian/migrations/0004_guardian_image.py b/guardian/migrations/0004_guardian_image.py new file mode 100644 index 0000000..519ed02 --- /dev/null +++ b/guardian/migrations/0004_guardian_image.py @@ -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/'), + ), + ] diff --git a/guardian/migrations/0005_alter_guardian_image.py b/guardian/migrations/0005_alter_guardian_image.py new file mode 100644 index 0000000..5899e64 --- /dev/null +++ b/guardian/migrations/0005_alter_guardian_image.py @@ -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=''), + ), + ] diff --git a/guardian/migrations/0006_guardian_is_verified.py b/guardian/migrations/0006_guardian_is_verified.py new file mode 100644 index 0000000..5d4082e --- /dev/null +++ b/guardian/migrations/0006_guardian_is_verified.py @@ -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), + ), + ] diff --git a/guardian/models.py b/guardian/models.py index d9228b7..3040c82 100644 --- a/guardian/models.py +++ b/guardian/models.py @@ -14,18 +14,21 @@ class Guardian(models.Model): country_code = models.IntegerField(blank=True, null=True) 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) 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) + """Profile activity""" + is_active = models.BooleanField(default=True) + is_verified = models.BooleanField(default=False) + is_complete_profile = models.BooleanField(default=False) + 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 activity""" - is_active = models.BooleanField(default=True) - is_complete_profile = models.BooleanField(default=False) - passcode = models.IntegerField(null=True, blank=True, default=None) """Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) diff --git a/guardian/serializers.py b/guardian/serializers.py index f2c0c46..75291b1 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -8,8 +8,10 @@ from django.db import transaction from django.contrib.auth.models import User """Import Django app""" from .models import Guardian -from account.models import UserProfile +from account.models import UserProfile, UserEmailOtp from base.messages import ERROR_CODE, SUCCESS_CODE +from .utils import upload_image_to_alibaba +from junior.models import Junior class UserSerializer(serializers.ModelSerializer): """User serializer""" auth_token = serializers.SerializerMethodField('get_auth_token') @@ -33,17 +35,20 @@ class UserSerializer(serializers.ModelSerializer): """Create user profile""" user = User.objects.create_user(username=email, email=email, password=password) 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 except Exception as e: """Error handling""" logging.error(e) - raise serializers.ValidationError({"details":ERROR_CODE['2021']}) - - def save(self, **kwargs): - """save the data""" - with transaction.atomic(): - instance = super().save(**kwargs) - return instance + otp = UserEmailOtp.objects.filter(email=email).last() + otp_verified = False + if otp and otp.is_verified: + otp_verified = True + raise serializers.ValidationError({"details":ERROR_CODE['2021'], "otp_verified":otp_verified, "code": "400", "status":"failed", + }) class CreateGuardianSerializer(serializers.ModelSerializer): """Create guardian serializer""" @@ -57,13 +62,14 @@ class CreateGuardianSerializer(serializers.ModelSerializer): family_name = serializers.CharField(max_length=100, required=False) dob = serializers.DateField(required=False) referral_code = serializers.CharField(max_length=100, required=False) + image = serializers.ImageField(required=False) class Meta(object): """Meta info""" model = Guardian fields = ['first_name', 'last_name', 'email', 'phone', 'family_name', 'gender', 'country_code', 'dob', 'referral_code', 'passcode', 'is_complete_profile', 'referral_code_used', - 'country_name'] + 'country_name', 'image'] def get_first_name(self,obj): """first name of guardian""" @@ -79,6 +85,11 @@ class CreateGuardianSerializer(serializers.ModelSerializer): 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() if user: """Save first and last name of guardian""" @@ -109,6 +120,11 @@ class CreateGuardianSerializer(serializers.ModelSerializer): guardian.is_complete_profile = False if complete_profile_field: guardian.is_complete_profile = True + 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() return guardian diff --git a/guardian/utils.py b/guardian/utils.py new file mode 100644 index 0000000..0e46c6c --- /dev/null +++ b/guardian/utils.py @@ -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}" diff --git a/guardian/views.py b/guardian/views.py index 72e5b94..e8dda1e 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -3,8 +3,9 @@ from rest_framework.permissions import IsAuthenticated from rest_framework import viewsets, status """Import Django app""" -from .serializers import UserSerializer -from .serializers import CreateGuardianSerializer +from .serializers import UserSerializer, CreateGuardianSerializer +from .models import Guardian +from junior.models import Junior from account.models import UserEmailOtp from .tasks import generate_otp from account.utils import send_otp_email @@ -22,7 +23,7 @@ class SignupViewset(viewsets.ModelViewSet): serializer.save() """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) return custom_response(SUCCESS_CODE['3001'], {"email_otp": otp}, diff --git a/junior/migrations/0003_junior_image.py b/junior/migrations/0003_junior_image.py new file mode 100644 index 0000000..8a31d3f --- /dev/null +++ b/junior/migrations/0003_junior_image.py @@ -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/'), + ), + ] diff --git a/junior/migrations/0004_alter_junior_image.py b/junior/migrations/0004_alter_junior_image.py new file mode 100644 index 0000000..373436d --- /dev/null +++ b/junior/migrations/0004_alter_junior_image.py @@ -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=''), + ), + ] diff --git a/junior/migrations/0005_junior_is_verified.py b/junior/migrations/0005_junior_is_verified.py new file mode 100644 index 0000000..a5ed1e6 --- /dev/null +++ b/junior/migrations/0005_junior_is_verified.py @@ -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), + ), + ] diff --git a/junior/models.py b/junior/models.py index b389e3a..762032b 100644 --- a/junior/models.py +++ b/junior/models.py @@ -18,7 +18,7 @@ class Junior(models.Model): """Personal info""" 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) - # 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) guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True) @@ -28,6 +28,7 @@ class Junior(models.Model): is_active = models.BooleanField(default=True) is_complete_profile = models.BooleanField(default=False) 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) updated_at = models.DateTimeField(auto_now=True) diff --git a/junior/serializers.py b/junior/serializers.py index a741203..2fcf7cc 100644 --- a/junior/serializers.py +++ b/junior/serializers.py @@ -6,6 +6,9 @@ from django.db import transaction import random """Import django app""" from junior.models import Junior +from guardian.utils import upload_image_to_alibaba +from base.messages import ERROR_CODE, SUCCESS_CODE +from guardian.models import Guardian class ListCharField(serializers.ListField): """Serializer for Array field""" @@ -19,7 +22,7 @@ class ListCharField(serializers.ListField): """internal value""" if isinstance(data, list): return data - raise serializers.ValidationError({"details":"Invalid input. Expected a list of strings."}) + raise serializers.ValidationError({"details":ERROR_CODE['2025']}) class CreateJuniorSerializer(serializers.ModelSerializer): @@ -32,13 +35,14 @@ class CreateJuniorSerializer(serializers.ModelSerializer): dob = serializers.DateField(required=False) referral_code = serializers.CharField(max_length=100, required=False) guardian_code = ListCharField(required=False) + image = serializers.ImageField(required=False) class Meta(object): """Meta info""" model = Junior fields = ['first_name', 'last_name', 'email', 'phone', 'gender', 'country_code', 'dob', 'referral_code', 'passcode', 'is_complete_profile', 'guardian_code', 'referral_code_used', - 'country_name'] + 'country_name', 'image'] def get_first_name(self,obj): """first name of junior""" @@ -54,6 +58,12 @@ class CreateJuniorSerializer(serializers.ModelSerializer): 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() if user: """Save first and last name of junior""" @@ -85,6 +95,10 @@ class CreateJuniorSerializer(serializers.ModelSerializer): 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() return junior diff --git a/nginx/django.conf b/nginx/django.conf index 488e2c0..af79e46 100644 --- a/nginx/django.conf +++ b/nginx/django.conf @@ -19,6 +19,6 @@ upstream web { location /static { autoindex on; - alias /usr/src/app/zod_bank/static/; + alias /usr/src/app/static/; } } diff --git a/requirements.txt b/requirements.txt index a875fbf..2175525 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,7 @@ aliyun-python-sdk-core==2.13.36 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 asgiref==3.7.2 async-timeout==4.0.2 @@ -7,13 +9,16 @@ billiard==4.1.0 boto3==1.26.157 botocore==1.29.157 celery==5.3.1 +certifi==2023.5.7 cffi==1.15.1 channels==4.0.0 channels-redis==4.1.0 +charset-normalizer==3.1.0 click==8.1.3 click-didyoumean==0.3.0 click-plugins==1.1.1 click-repl==0.3.0 +crcmod==1.7 cron-descriptor==1.4.0 cryptography==41.0.1 decouple==0.0.7 @@ -34,15 +39,19 @@ djangorestframework==3.14.0 djangorestframework-simplejwt==5.2.2 drf-yasg==1.21.6 gunicorn==20.1.0 +idna==3.4 inflection==0.5.1 jmespath==0.10.0 kombu==5.3.1 msgpack==1.0.5 +oss2==2.18.0 packaging==23.1 phonenumbers==8.13.15 +Pillow==9.5.0 prompt-toolkit==3.0.38 psycopg==3.1.9 pycparser==2.21 +pycryptodome==3.18.0 PyJWT==2.7.0 python-crontab==2.7.1 python-dateutil==2.8.2 @@ -50,6 +59,7 @@ python-dotenv==1.0.0 pytz==2023.3 PyYAML==6.0 redis==4.5.5 +requests==2.31.0 s3transfer==0.6.1 six==1.16.0 sqlparse==0.4.4 diff --git a/zod_bank/settings.py b/zod_bank/settings.py index 1c758b7..840de8e 100644 --- a/zod_bank/settings.py +++ b/zod_bank/settings.py @@ -172,20 +172,33 @@ CORS_ALLOW_HEADERS = ( https://docs.djangoproject.com/en/3.0/howto/static-files/""" -# Email settings -EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -EMAIL_HOST = 'smtp.gmail.com' -EMAIL_PORT = 587 -EMAIL_USE_TLS = True -EMAIL_HOST_USER = 'infozodbank@gmail.com' -# Replace with your Gmail email password or App password -EMAIL_HOST_PASSWORD = 'ghwdmznwwslvchga' - -# EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS') +# EMAIL_BACKEND = os.getenv('EMAIL_BACKEND') # EMAIL_HOST = os.getenv('EMAIL_HOST') -# EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER') -# EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD') # 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') + +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="zodbank@yopmail.com" + +# 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'