forked from GithubBackups/healthchecks
pruneusers management command does not touch users with team memberships. Tests.
This commit is contained in:
parent
d0f9a624ed
commit
caa6b2758e
@ -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.
|
||||||
|
|
||||||
|
@ -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
hc/accounts/tests/test_pruneusers.py
Normal file
40
hc/accounts/tests/test_pruneusers.py
Normal 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…
x
Reference in New Issue
Block a user