Source code for akvo.rsr.management.commands.user_cleanup

# -*- coding: utf-8 -*-

# Akvo Reporting is covered by the GNU Affero General Public License.
# See more details in the license.txt file located at the root folder of the Akvo RSR module.
# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.

from datetime import timedelta

from django.core.management.base import BaseCommand
from django.db.models import F
from django.utils import timezone

from ...models import User


[docs]class Command(BaseCommand): help = 'Script for cleaning up inactive user accounts'
[docs] def add_arguments(self, parser): parser.add_argument( '-n', '--num-days', action='store', dest='num_days', default=30, help='Filter users who joined more than \'n\' days ago' ) parser.add_argument( '-d', '--delete', action='store_true', dest='delete', default=False, help='Delete filtered users in addition to listing them' ) parser.add_argument( '-i', '--inactive', action='store_true', dest='inactive', default=False, help='Filter non-active users' ) parser.add_argument( '-e', '--no-employment', action='store_true', dest='no_employment', default=False, help='Filter users lacking employment' )
[docs] def handle(self, *args, **options): # parse options verbosity = int(options['verbosity']) delete = bool(options['delete']) num_days = int(options['num_days']) if bool(options['inactive']) and not bool(options['no_employment']): prune_inactive = True prune_employment = False elif not bool(options['inactive']) and bool(options['no_employment']): prune_inactive = False prune_employment = True else: prune_inactive = True prune_employment = True # initialize arrays non_active = [] no_activity = [] # prune users with 'date_joined' older than filter_date = timezone.now() - timedelta(days=num_days) if verbosity > 1: self.stdout.write('Pruning date: %s' % (filter_date)) users_queryset = User.objects.exclude(date_joined__gt=filter_date)\ .exclude(is_admin=True)\ .exclude(is_superuser=True) deleted_emails = set() # remove inactive accounts if prune_inactive: if verbosity > 0: self.stdout.write('Filtering all non-activated user accounts older than %s days.' % (num_days)) non_active = users_queryset.filter(is_active=False, last_login=F('date_joined')) deleted_emails = deleted_emails.union(non_active.values_list('email', flat=True)) if verbosity > 1: for n, u in enumerate(non_active): self.stdout.write('- %s (joined %s) [%s/%s]' % (u.username, u.date_joined, n + 1, len(non_active))) if delete: non_active.delete() # remove no employment accounts if prune_employment: if verbosity > 0: self.stdout.write('Filtering all non-admin/superuser user accounts without an employment older than %s days.' % (num_days)) no_activity = users_queryset\ .filter(employers__isnull=True)\ .filter(projectupdate__isnull=True)\ .filter(created_period_updates__isnull=True)\ .filter(approved_period_updates__isnull=True)\ .filter(indicatorperioddatacomment__isnull=True)\ .filter(user_projects__isnull=True)\ .filter(iati_exports__isnull=True)\ .filter(logentry__isnull=True) deleted_emails = deleted_emails.union(no_activity.values_list('email', flat=True)) if verbosity > 1: for n, u in enumerate(no_activity): self.stdout.write('- %s (joined %s) [%s/%s]' % (u.username, u.date_joined, n + 1, len(no_activity))) if delete: no_activity.delete() if delete: if verbosity > 0: self.stdout.write( '%s user(s) matched filter and were successfully removed.' % len(deleted_emails)) else: if verbosity > 0: self.stdout.write( '%s user(s) matched filter, use \'-d\' flag to remove them.' % len(deleted_emails))