diff --git a/frontend/src/components/parameters/ParametersForm.vue b/frontend/src/components/parameters/ParametersForm.vue index 15b4ed460..bc08e8d7b 100644 --- a/frontend/src/components/parameters/ParametersForm.vue +++ b/frontend/src/components/parameters/ParametersForm.vue @@ -133,6 +133,7 @@ export default { return params.filter(param => this.display(param)) }, save () { + this.formErrors = {} parameters.saveApplication(this.$route.params.app, this.parameters).then(() => { bus.$emit('notification', { msg: this.$gettext('Parameters updated') }) }).catch(error => { diff --git a/modoboa/core/api/v2/serializers.py b/modoboa/core/api/v2/serializers.py index 7afaff798..f766fd6ce 100644 --- a/modoboa/core/api/v2/serializers.py +++ b/modoboa/core/api/v2/serializers.py @@ -159,6 +159,7 @@ class CoreGlobalParametersSerializer(serializers.Serializer): send_statistics = serializers.BooleanField(default=True) # Misc settings + enable_inactive_accounts = serializers.BooleanField(default=True) inactive_account_threshold = serializers.IntegerField(default=30) top_notifications_check_interval = serializers.IntegerField(default=30) log_maximum_age = serializers.IntegerField(default=365) diff --git a/modoboa/core/api/v2/tests.py b/modoboa/core/api/v2/tests.py index 4caae77f7..079437e92 100644 --- a/modoboa/core/api/v2/tests.py +++ b/modoboa/core/api/v2/tests.py @@ -59,6 +59,7 @@ CORE_SETTINGS = { "send_new_versions_email": False, "new_versions_email_rcpt": "postmaster@yourdomain.test", "send_statistics": True, + "enable_inactive_accounts": True, "inactive_account_threshold": 30, "top_notifications_check_interval": 30, "log_maximum_age": 365, diff --git a/modoboa/core/app_settings.py b/modoboa/core/app_settings.py index 656b0ffbd..a30b85772 100644 --- a/modoboa/core/app_settings.py +++ b/modoboa/core/app_settings.py @@ -457,12 +457,19 @@ class GeneralParametersForm(param_forms.AdminParametersForm): sep3 = SeparatorField(label=ugettext_lazy("Miscellaneous")) + enable_inactive_accounts = YesNoField( + label=_("Enable inactive account tracking"), + initial=True, + help_text=_("Allow the administrator to set a threshold beyond which " + "an account is considered inactive if the user hasn't logged.") + ) + inactive_account_threshold = forms.IntegerField( label=_("Inactive account threshold"), initial=30, help_text=_( "An account with a last login date greater than this threshold " - "(in days) will be considered as inactive. Disabled if the number is negative." + "(in days) will be considered as inactive." ), ) @@ -520,6 +527,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm): "send_new_versions_email": "check_new_versions=True", "new_versions_email_rcpt": "check_new_versions=True", "sms_provider": "sms_password_recovery=True", + "inactive_account_threshold": "enable_inactive_accounts=True" } def __init__(self, *args, **kwargs): @@ -1072,12 +1080,19 @@ GLOBAL_PARAMETERS_STRUCT = collections.OrderedDict([ ("misc", { "label": ugettext_lazy("Miscellaneous"), "params": collections.OrderedDict([ + ("enable_inactive_accounts", { + "label": ugettext_lazy("Enable inactive account tracking"), + "help_text": ugettext_lazy( + "Allow the administrator to set a threshold beyond which " + "an account is considered inactive if the user hasn't logged." + ), + }), ("inactive_account_threshold", { "label": ugettext_lazy("Inactive account threshold"), + "display": "enable_inactive_accounts=true", "help_text": ugettext_lazy( "An account with a last login date greater than this " "threshold (in days) will be considered as inactive. " - "Disabled if the number is negative." ) }), ("top_notifications_check_interval", { diff --git a/modoboa/core/management/commands/clean_inactive_accounts.py b/modoboa/core/management/commands/clean_inactive_accounts.py index 23cd06e3a..2c48e4754 100644 --- a/modoboa/core/management/commands/clean_inactive_accounts.py +++ b/modoboa/core/management/commands/clean_inactive_accounts.py @@ -43,10 +43,14 @@ class Command(BaseCommand): def handle(self, *args, **options): """Command entry point.""" + if not param_tools.get_global_parameter( + "enable_inactive_accounts"): + if options["verbose"]: + print("Inactive accounts detection is disabled.", + file=self.stdout) + return inactive_account_threshold = param_tools.get_global_parameter( "inactive_account_threshold") - if inactive_account_threshold < 0: - return qset = models.User.objects.filter( is_active=True, is_superuser=False, last_login__lt=timezone.now() - diff --git a/modoboa/core/tests/test_core.py b/modoboa/core/tests/test_core.py index a738918d5..ef7b99688 100644 --- a/modoboa/core/tests/test_core.py +++ b/modoboa/core/tests/test_core.py @@ -84,14 +84,15 @@ class ManagementCommandsTestCase(SimpleModoTestCase): "clean_inactive_accounts", "--verbose", "--dry-run", stdout=out) self.assertIn("user1@domain.test", out.getvalue()) - # Set a negative number (means disabled) - self.set_global_parameter("inactive_account_threshold", -1) + # Disable account account threshold + self.set_global_parameter("enable_inactive_accounts", False) out = StringIO() management.call_command( - "clean_inactive_accounts", "--verbose", "--dry-run", stdout=out) - self.assertEqual("", out.getvalue()) + "clean_inactive_accounts", "--verbose", stdout=out) + self.assertIn("Inactive accounts detection is disabled.", + out.getvalue()) - self.set_global_parameter("inactive_account_threshold", 30) + self.set_global_parameter("enable_inactive_accounts", True) management.call_command("clean_inactive_accounts", "--silent") account.refresh_from_db() self.assertFalse(account.is_active) diff --git a/modoboa/parameters/tools.py b/modoboa/parameters/tools.py index cda90ba1e..54e3eaff5 100644 --- a/modoboa/parameters/tools.py +++ b/modoboa/parameters/tools.py @@ -63,7 +63,7 @@ class Registry(object): result = [{"name": key, "label": value["label"]} for key, value in self._registry2[level].items()] return result - + def get_label(self, level, app): return self._registry2[level][app]["label"]