diff --git a/beat/web/accounts/management/commands/postpone_users_validation.py b/beat/web/accounts/management/commands/postpone_users_validation.py new file mode 100644 index 0000000000000000000000000000000000000000..63b46d6c565a83a7177243de1fd46fad36afa908 --- /dev/null +++ b/beat/web/accounts/management/commands/postpone_users_validation.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : +# encoding: utf-8 + +############################################################################### +# # +# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ # +# Contact: beat.support@idiap.ch # +# # +# This file is part of the beat.web module of the BEAT platform. # +# # +# Commercial License Usage # +# Licensees holding valid commercial BEAT licenses may use this file in # +# accordance with the terms contained in a written agreement between you # +# and Idiap. For further information contact tto@idiap.ch # +# # +# Alternatively, this file may be used under the terms of the GNU Affero # +# Public License version 3 as published by the Free Software and appearing # +# in the file LICENSE.AGPL included in the packaging of this file. # +# The BEAT platform is distributed in the hope that it will be useful, but # +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # +# or FITNESS FOR A PARTICULAR PURPOSE. # +# # +# You should have received a copy of the GNU Affero Public License along # +# with the BEAT platform. If not, see http://www.gnu.org/licenses/. # +# # +############################################################################### + + +import datetime +import sys + +from django.core.management.base import BaseCommand +from django.conf import settings + +from ....ui.registration.models import RegistrationProfile + +from ...models import SupervisionTrack +from ...models import Profile + + +class Command(BaseCommand): + + help = "Postpone user(s) validation process" + + def add_arguments(self, parser): + parser.add_argument( + "--noinput", + action="store_false", + dest="interactive", + default=False, + help=("Tells Django to NOT prompt the user for input of any kind."), + ) + + def handle(self, *args, **options): + + if options["interactive"]: + try: + answer = self.get_input_data( + "Postpone user(s) validation process? (y/n)? ", "y" + ).lower() + except KeyboardInterrupt: + self.stderr.write("\nOperation canceled.") + sys.exit(1) + + if answer != "y": + self.stdout.write("Postpone canceled") + sys.exit(0) + + invalid_userprofiles_new_users = Profile.objects.filter(status=Profile.NEWUSER) + invalid_userprofiles_waiting_validation = Profile.objects.filter( + status=Profile.WAITINGVALIDATION + ) + count = 0 + postpone_count = 0 + now = datetime.datetime.now() + + expiration_date_delta_new_users = datetime.timedelta( + days=settings.ACCOUNT_ACTIVATION_DAYS + ) + + expiration_date_delta_waiting_validation = datetime.timedelta( + days=settings.ACCOUNT_ACTIVATION_DAYS_FROM_SUPERVISOR + ) + + count += self.check_invalid_profiles( + invalid_userprofiles_new_users, expiration_date_delta_new_users, now + ) + count += self.check_invalid_profiles( + invalid_userprofiles_waiting_validation, + expiration_date_delta_waiting_validation, + now, + ) + + supervisiontracks = SupervisionTrack.objects.all() + expiration_date_delta = datetime.timedelta( + days=settings.ACCOUNT_BLOCKAGE_AFTER_FIRST_REJECTION_DAYS + ) + extra_days_delta = datetime.timedelta( + days=(settings.ACCOUNT_BLOCKAGE_AFTER_FIRST_REJECTION_DAYS + 1) + ) + + for supervisiontrack in supervisiontracks: + if ( + supervisiontrack.is_valid + and supervisiontrack.expiration_date < now + expiration_date_delta + ): + postpone_count += 1 + postpone_date = now + extra_days_delta + supervisiontrack.expiration_date = postpone_date + supervisiontrack.save() + supervisee_profile = Profile.objects.get( + user=supervisiontrack.supervisee + ) + if supervisee_profile.status == Profile.YEARREVALIDATION: + supervisee_profile.status = Profile.ACCEPTED + supervisee_profile.save() + + self.stdout.write( + "{} Invalid user(s) successfully cleaned/{} Total user(s) checked".format( + count, + invalid_userprofiles_new_users.count() + + invalid_userprofiles_waiting_validation.count(), + ) + ) + self.stdout.write( + "{} Valid user(s) postponed/{} Total supervision track(s) checked".format( + postpone_count, supervisiontracks.count() + ) + ) + + def check_invalid_profiles(self, invalid_profiles_list, expiration_date_delta, now): + """ + Cleanup invalid profiles + """ + count_updated_users = 0 + for invalid_profile in invalid_profiles_list: + user = invalid_profile.user + + if user.profile.registration_date + expiration_date_delta <= now: + count_updated_users += 1 + user.delete() + invalid_profile.delete() + SupervisionTrack.objects.filter( + supervision_key=invalid_profile.supervision_key + ).delete() + RegistrationProfile.objects.filter(user=invalid_profile.user).delete() + + return count_updated_users + + def get_input_data(self, message, default=None): + """ + Override this method if you want to customize data inputs or + validation exceptions. + """ + raw_value = input(message) + + if default and raw_value == "": + raw_value = default + + return raw_value