diff --git a/account/migrations/0004_userdelete.py b/account/migrations/0004_userdelete.py new file mode 100644 index 0000000..10bd2aa --- /dev/null +++ b/account/migrations/0004_userdelete.py @@ -0,0 +1,31 @@ +# Generated by Django 4.2.2 on 2023-07-10 09:24 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('account', '0003_defaulttaskimages'), + ] + + operations = [ + migrations.CreateModel( + name='UserDelete', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('old_email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='Original Email')), + ('d_email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='Dummy Email')), + ('is_active', models.BooleanField(default=True)), + ('reason', models.TextField(blank=True, max_length=500, null=True, verbose_name='Reason for Leaving')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='delete_information_set', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'user_delete_information', + }, + ), + ] diff --git a/account/models.py b/account/models.py index ac23e79..31c592a 100644 --- a/account/models.py +++ b/account/models.py @@ -92,3 +92,24 @@ class DefaultTaskImages(models.Model): def __str__(self): """return phone as an object""" return self.task_name + +class UserDelete(models.Model): + """ + User delete information + """ + user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='delete_information_set') + """Old email""" + old_email = models.EmailField(blank=True, null=True, verbose_name='Original Email') + """Dummy email""" + d_email = models.EmailField(blank=True, null=True, verbose_name='Dummy Email') + is_active = models.BooleanField(default=True) + """reason for leaving""" + reason = models.TextField(max_length=500, blank=True, null=True, verbose_name='Reason for Leaving') + created_at = models.DateTimeField(auto_now_add=True) + + class Meta(object): + """ Meta information """ + db_table = 'user_delete_information' + + def __str__(self): + return self.user.email diff --git a/account/serializers.py b/account/serializers.py index db11233..4007e98 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -1,12 +1,13 @@ """Account serializer""" """Django Imoprt""" +import random from rest_framework import serializers from django.contrib.auth.models import User from rest_framework_simplejwt.tokens import RefreshToken """App import""" from guardian.models import Guardian from junior.models import Junior -from account.models import UserProfile, UserEmailOtp, UserPhoneOtp, DefaultTaskImages +from account.models import UserProfile, UserEmailOtp, UserPhoneOtp, DefaultTaskImages, UserDelete from base.constants import GUARDIAN, JUNIOR, SUPERUSER from base.messages import ERROR_CODE_REQUIRED, ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR @@ -218,3 +219,47 @@ class DefaultTaskImagesDetailsSerializer(serializers.ModelSerializer): """Meta info""" model = DefaultTaskImages fields = '__all__' + +class UserDeleteSerializer(serializers.ModelSerializer): + """User Delete Serializer""" + class Meta(object): + """Meta Information""" + model = UserDelete + fields = ['reason'] + def create(self, validated_data): + user = self.context['user'] + user_type = str(self.context['user_type']) + data = validated_data.get('reason') + random_num = random.randint(0,10000) + user_tb = User.objects.filter(id=user.id).last() + user_type_data = UserEmailOtp.objects.filter(email=user.email).last() + if user_type == '1' and user_type_data.user_type == '1': + junior_data = Junior.objects.filter(auth__email=user_tb.email).first() + if junior_data: + junior_data.is_active = False + junior_data.is_verified = False + junior_data.guardian_code = '{}' + junior_data.save() + elif user_type == '2' and user_type_data.user_type == '2': + guardian_data = Guardian.objects.filter(user__email=user_tb.email).first() + if guardian_data: + guardian_data.is_active = False + guardian_data.is_verified = False + guardian_data.save() + jun_data = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code)) + for data in jun_data: + data.guardian_code.remove(guardian_data.guardian_code) + data.save() + else: + raise serializers.ValidationError({"details":ERROR_CODE['2030'],"code":"400", "status":"failed"}) + + user_tb.email = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() + user_tb.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() + user_tb.password = 'None' + d_email = user_tb.email + o_mail = user.email + instance = UserDelete.objects.create(user=user_tb, d_email=d_email, old_email=o_mail, + is_active=True, reason=data) + user_tb.save() + + return instance diff --git a/account/urls.py b/account/urls.py index ffb2db6..b64f99d 100644 --- a/account/urls.py +++ b/account/urls.py @@ -7,7 +7,7 @@ from rest_framework import routers from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp, ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage, GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet, - DefaultImageAPIViewSet) + DefaultImageAPIViewSet, DeleteUserProfileAPIViewSet) """Router""" router = routers.SimpleRouter() @@ -29,6 +29,8 @@ router.register('profile', ProfileAPIViewSet, basename='profile') router.register('upload-default-task-image', UploadImageAPIViewSet, basename='upload-default-task-image') """Fetch default task image end point""" router.register('default-task-image', DefaultImageAPIViewSet, basename='default-task-image') +"""Delete user account""" +router.register('delete', DeleteUserProfileAPIViewSet, basename='delete') """Define url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), diff --git a/account/views.py b/account/views.py index 1324869..5657b4a 100644 --- a/account/views.py +++ b/account/views.py @@ -18,7 +18,7 @@ from django.contrib.auth.models import User from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer, ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer, GoogleLoginSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer, - DefaultTaskImagesSerializer, DefaultTaskImagesDetailsSerializer) + DefaultTaskImagesSerializer, DefaultTaskImagesDetailsSerializer, UserDeleteSerializer) from rest_framework_simplejwt.tokens import RefreshToken from base.messages import ERROR_CODE, SUCCESS_CODE from guardian.tasks import generate_otp @@ -417,3 +417,20 @@ class DefaultImageAPIViewSet(viewsets.ModelViewSet): queryset = DefaultTaskImages.objects.all() serializer = DefaultTaskImagesSerializer(queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) + + +class DeleteUserProfileAPIViewSet(viewsets.GenericViewSet): + """ Delete user API view set """ + + @action(detail=False, methods=['POST'], url_path='user-account',serializer_class=UserDeleteSerializer, + permission_classes=[IsAuthenticated]) + def account(self, request): + print("request.data===>",request.data) + print("request.user===>", request.user) + user_type = str(request.data['user_type']) + serializer = self.get_serializer(data=request.data, context={'request': request, 'user': request.user, + 'user_type':user_type}) + if serializer.is_valid(): + serializer.save() + return custom_response(SUCCESS_CODE['3005'], response_status=status.HTTP_200_OK) + return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) diff --git a/base/messages.py b/base/messages.py index f024a3d..b00bfbf 100644 --- a/base/messages.py +++ b/base/messages.py @@ -52,7 +52,8 @@ ERROR_CODE = { "2026": "New password should not same as old password", "2027": "data should contain `identityToken`", "2028": "You are not authorized person to sign up on this platform", - "2029": "Validity of otp verification is expired" + "2029": "Validity of otp verification is expired", + "2030": "Use correct user type and token" } SUCCESS_CODE = { # Success code for password @@ -64,7 +65,7 @@ SUCCESS_CODE = { # Success code for password reset "3004": "Password reset link has been sent to your email address", # Success code for link verified - "3005": "Your link has been verified, it's valid", + "3005": "Your account is deleted successfully.", # Success code for password reset "3006": "Your password has been reset successfully.", # Success code for password update diff --git a/junior/admin.py b/junior/admin.py index a2acfb6..3764f48 100644 --- a/junior/admin.py +++ b/junior/admin.py @@ -7,7 +7,7 @@ from .models import Junior, JuniorPoints @admin.register(Junior) class JuniorAdmin(admin.ModelAdmin): """Junior Admin""" - list_display = ['auth'] + list_display = ['auth', 'guardian_code'] def __str__(self): """Return email id"""