Browse Source

pruneusers management command does not touch users with team memberships. Tests.

pull/114/head
Pēteris Caune 8 years ago
parent
commit
caa6b2758e
3 changed files with 53 additions and 9 deletions
  1. +2
    -2
      README.md
  2. +11
    -7
      hc/accounts/management/commands/pruneusers.py
  3. +40
    -0
      hc/accounts/tests/test_pruneusers.py

+ 2
- 2
README.md View File

@ -198,9 +198,9 @@ There are separate Django management commands for each task:
```` ````
* Remove user accounts that match either of these conditions: * Remove user accounts that match either of these conditions:
* Account was created more than a month ago, and user has never logged in.
* Account was created more than 6 months ago, and user has never logged in.
These can happen when user enters invalid email address when signing up. These can happen when user enters invalid email address when signing up.
* Last login was more than a month ago, and the account has no checks.
* Last login was more than 6 months ago, and the account has no checks.
Assume the user doesn't intend to use the account any more and would Assume the user doesn't intend to use the account any more and would
probably *want* it removed. probably *want* it removed.


+ 11
- 7
hc/accounts/management/commands/pruneusers.py View File

@ -10,28 +10,32 @@ class Command(BaseCommand):
help = """Prune old, inactive user accounts. help = """Prune old, inactive user accounts.
Conditions for removing an user account: Conditions for removing an user account:
- created 1+ month ago and never logged in.
- created 6 months ago and never logged in. Does not belong
to any team.
Use case: visitor types in their email at the website but Use case: visitor types in their email at the website but
never follows through with login. never follows through with login.
- not logged in for 1 month, and has no checks
- not logged in for 6 months, and has no checks. Does not
belong to any team.
Use case: user wants to remove their account. So they Use case: user wants to remove their account. So they
remove all checks and leave the account at that. remove all checks and leave the account at that.
""" """
def handle(self, *args, **options): def handle(self, *args, **options):
cutoff = timezone.now() - timedelta(days=31)
cutoff = timezone.now() - timedelta(days=180)
# Old accounts, never logged in
# Old accounts, never logged in, no team memberships
q = User.objects q = User.objects
q = q.filter(date_joined__lt=cutoff, last_login=None)
q = q.annotate(n_teams=Count("member"))
q = q.filter(date_joined__lt=cutoff, last_login=None, n_teams=0)
n1, _ = q.delete() n1, _ = q.delete()
# Not logged in for 1 month, 0 checks
# Not logged in for 1 month, 0 checks, no team memberships
q = User.objects q = User.objects
q = q.annotate(n_checks=Count("check")) q = q.annotate(n_checks=Count("check"))
q = q.filter(last_login__lt=cutoff, n_checks=0)
q = q.annotate(n_teams=Count("member"))
q = q.filter(last_login__lt=cutoff, n_checks=0, n_teams=0)
n2, _ = q.delete() n2, _ = q.delete()
return "Done! Pruned %d user accounts." % (n1 + n2) return "Done! Pruned %d user accounts." % (n1 + n2)

+ 40
- 0
hc/accounts/tests/test_pruneusers.py View File

@ -0,0 +1,40 @@
from datetime import timedelta
from django.contrib.auth.models import User
from django.utils import timezone
from hc.accounts.management.commands.pruneusers import Command
from hc.api.models import Check
from hc.test import BaseTestCase
class PruneUsersTestCase(BaseTestCase):
year_ago = timezone.now() - timedelta(days=365)
def test_it_removes_old_never_logged_in_users(self):
self.charlie.date_joined = self.year_ago
self.charlie.save()
# Charlie has one demo check
Check(user=self.charlie).save()
Command().handle()
self.assertEqual(User.objects.filter(username="charlie").count(), 0)
self.assertEqual(Check.objects.count(), 0)
def test_it_removes_old_users_with_zero_checks(self):
self.charlie.date_joined = self.year_ago
self.charlie.last_login = self.year_ago
self.charlie.save()
Command().handle()
self.assertEqual(User.objects.filter(username="charlie").count(), 0)
def test_it_leaves_team_members_alone(self):
self.bob.date_joined = self.year_ago
self.bob.last_login = self.year_ago
self.bob.save()
Command().handle()
# Bob belongs to a team so should not get removed
self.assertEqual(User.objects.filter(username="bob").count(), 1)

Loading…
Cancel
Save