Просмотр исходного кода

WIP move own account deletion off the http thread

Rafał Pitoń 7 лет назад
Родитель
Сommit
37ecb21eee

+ 1 - 0
misago/project_template/cron.txt

@@ -8,3 +8,4 @@
 25 0 * * * python manage.py clearreadtracker
 25 0 * * * python manage.py clearsessions
 25 0 * * * python manage.py invalidatebans
+1 0 * * * python manage.py deleterequesteduseraccounts

+ 7 - 8
misago/users/api/users.py

@@ -152,6 +152,13 @@ class UserViewSet(viewsets.GenericViewSet):
         return edit_details_endpoint(request, profile)
 
     @detail_route(methods=['post'])
+    def delete_own_account(self, request, pk=None):
+        serializer = DeleteAccountSerializer(data=request.data, context={'user': request.user})
+        serializer.is_valid(raise_exception=True)
+        serializer.delete_account(request)
+        return Response({})
+        
+    @detail_route(methods=['post'])
     def follow(self, request, pk=None):
         profile = self.get_user(request, pk)
         allow_follow_user(request.user, profile)
@@ -207,14 +214,6 @@ class UserViewSet(viewsets.GenericViewSet):
     @detail_route(methods=['get', 'post'])
     def delete(self, request, pk=None):
         profile = self.get_user(request, pk)
-
-        if request.method == 'POST' and 'password' in request.data:
-            serializer = DeleteAccountSerializer(data=request.data, context={'user': request.user})
-            serializer.is_valid(raise_exception=True)
-            with transaction.atomic():
-                serializer.delete_account(request)
-            return Response({})
-        
         allow_delete_user(request.user, profile)
 
         if request.method == 'POST':

+ 1 - 1
misago/users/management/commands/createsuperuser.py

@@ -24,7 +24,7 @@ class NotRunningInTTYException(Exception):
 
 
 class Command(BaseCommand):
-    help = 'Used to create a superuser.'
+    help = "Used to create a superuser."
 
     def add_arguments(self, parser):
         parser.add_argument(

+ 3 - 4
misago/users/management/commands/deleteprofilefield.py

@@ -3,14 +3,13 @@ from __future__ import unicode_literals
 from django.contrib.auth import get_user_model
 from django.core.management.base import CommandError, BaseCommand
 
+from misago.core.pgutils import chunk_queryset
 
 UserModel = get_user_model()
 
 
 class Command(BaseCommand):
-    help = (
-        "Deletes specified profile field from database."
-    )
+    help = "Deletes specified profile field from database."
 
     def add_arguments(self, parser):
         parser.add_argument(
@@ -31,7 +30,7 @@ class Command(BaseCommand):
             profile_fields__has_keys=[fieldname],
         )
 
-        for user in queryset.iterator():
+        for user in chunk_queryset(queryset):
             if fieldname in user.profile_fields.keys():
                 user.profile_fields.pop(fieldname)
                 user.save(update_fields=['profile_fields'])

+ 24 - 0
misago/users/management/commands/deleterequesteduseraccounts.py

@@ -0,0 +1,24 @@
+from __future__ import unicode_literals
+
+from django.contrib.auth import get_user_model
+from django.core.management.base import CommandError, BaseCommand
+
+from misago.core.pgutils import chunk_queryset
+
+
+UserModel = get_user_model()
+
+
+class Command(BaseCommand):
+    help = "Deletes accounts of users that have choosen to delete their account."
+
+    def handle(self, *args, **options):
+        deleted = 0
+
+        queryset = UserModel.objects.filter(delete_own_account=True)
+
+        for user in chunk_queryset(queryset):
+            user.delete()
+            deleted += 1
+
+        self.stdout.write('{} user accounts have been deleted.'.format(deleted))

+ 4 - 4
misago/users/management/commands/listusedprofilefields.py

@@ -3,19 +3,19 @@ from __future__ import unicode_literals
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 
+from misago.core.pgutils import chunk_queryset
+
 
 UserModel = get_user_model()
 
 
 class Command(BaseCommand):
-    help = (
-        "Lists all profile fields in use."
-    )
+    help = "Lists all profile fields in use."
 
     def handle(self, *args, **options):
         keys = {}
 
-        for user in UserModel.objects.all().iterator():
+        for user in chunk_queryset(UserModel.objects.all()):
             for key in user.profile_fields.keys():
                 keys.setdefault(key, 0)
                 keys[key] += 1

+ 4 - 3
misago/users/management/commands/populateonlinetracker.py

@@ -1,6 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 
+from misago.core.pgutils import chunk_queryset
 from misago.users.models import Online
 
 
@@ -8,12 +9,12 @@ UserModel = get_user_model()
 
 
 class Command(BaseCommand):
-    help = 'Populates online tracker for user accounts that lack it.'
+    help = "Populates online tracker for user accounts that lack it."
 
     def handle(self, *args, **options):
         entries_created = 0
         queryset = UserModel.objects.filter(online_tracker__isnull=True)
-        for user in queryset.iterator():
+        for user in chunk_queryset(queryset):
             Online.objects.create(
                 user=user,
                 current_ip=user.joined_from_ip,
@@ -21,4 +22,4 @@ class Command(BaseCommand):
             )
             entries_created += 1
 
-        self.stdout.write('Tracker entries created: %s' % entries_created)
+        self.stdout.write("Tracker entries created: %s" % entries_created)

+ 25 - 0
misago/users/migrations/0011_auto_20180326_1926.py

@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.9 on 2018-03-26 19:26
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import misago.core.pgutils
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('misago_users', '0010_user_profile_fields'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='user',
+            name='delete_own_account',
+            field=models.BooleanField(default=False),
+        ),
+        migrations.AddIndex(
+            model_name='user',
+            index=misago.core.pgutils.PgPartialIndex(fields=['delete_own_account'], name='misago_user_delete__8d97e7_part', where={'delete_own_account': True}),
+        ),
+    ]

+ 6 - 0
misago/users/models/user.py

@@ -266,6 +266,8 @@ class User(AbstractBaseUser, PermissionsMixin):
 
     profile_fields = HStoreField(default=dict)
 
+    delete_own_account = models.BooleanField(default=False)
+
     USERNAME_FIELD = 'slug'
     REQUIRED_FIELDS = ['email']
 
@@ -281,6 +283,10 @@ class User(AbstractBaseUser, PermissionsMixin):
                 fields=['requires_activation'],
                 where={'requires_activation__gt': 0},
             ),
+            PgPartialIndex(
+                fields=['delete_own_account'],
+                where={'delete_own_account': True},
+            ),
         ]
 
     def clean(self):