Merge pull request #2885 from modoboa/disable-inactive-accounts-option

Added ability to disable inactive accounts
This commit is contained in:
Antoine Nguyen
2023-03-03 10:33:15 +01:00
committed by GitHub
10 changed files with 45 additions and 4 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ module.exports = {
target:
process.env.DOCKER == "yes"
? "http://api:8000/"
: "http://localhost:8000",
: "http://127.0.0.1:8000",
},
},
},
+1
View File
@@ -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)
+1
View File
@@ -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,
+18
View File
@@ -455,6 +455,14 @@ 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 (in days) "
"beyond which an account is considered inactive "
"if the user hasn't logged in")
)
inactive_account_threshold = forms.IntegerField(
label=_("Inactive account threshold"),
initial=30,
@@ -518,6 +526,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):
@@ -1070,8 +1079,17 @@ 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 (in days) "
"beyond which an account is considered inactive "
"if the user hasn't logged in"
),
}),
("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"
@@ -43,6 +43,12 @@ 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")
qset = models.User.objects.filter(
+11 -2
View File
@@ -11,7 +11,7 @@ from django.test import TestCase
from django.urls import reverse
from django.utils import timezone
from modoboa.lib.tests import ModoTestCase
from modoboa.lib.tests import ModoTestCase, SimpleModoTestCase
from .. import factories, mocks, models
@@ -44,7 +44,7 @@ class AuthenticationTestCase(ModoTestCase):
self.assertTrue(response.url.endswith(reverse("core:dashboard")))
class ManagementCommandsTestCase(TestCase):
class ManagementCommandsTestCase(SimpleModoTestCase):
"""Test management commands."""
def test_change_default_admin(self):
@@ -84,6 +84,15 @@ class ManagementCommandsTestCase(TestCase):
"clean_inactive_accounts", "--verbose", "--dry-run", stdout=out)
self.assertIn("user1@domain.test", out.getvalue())
# Disable account account threshold
self.set_global_parameter("enable_inactive_accounts", False)
out = StringIO()
management.call_command(
"clean_inactive_accounts", "--verbose", stdout=out)
self.assertIn("Inactive accounts detection is disabled.",
out.getvalue())
self.set_global_parameter("enable_inactive_accounts", True)
management.call_command("clean_inactive_accounts", "--silent")
account.refresh_from_db()
self.assertFalse(account.is_active)
+1
View File
@@ -60,6 +60,7 @@ SETTINGS_SAMPLE = {
"core-default_password": "Toto1000",
"limits-deflt_user_quota_limit": "0",
"core-hide_features_widget": "False",
"core-enable_inactive_accounts": "True",
"core-inactive_account_threshold": "30",
"admin-domains_must_have_authorized_mx": False,
"core-random_password_length": "8",
+3
View File
@@ -52,6 +52,9 @@ class ParametersMixin(object):
self.localconfig.parameters.set_values(parameters, app=app)
self.localconfig.save()
class SimpleModoTestCase(ParametersMixin, TestCase):
"""Simple class to add parameters editing."""
class ModoTestCase(ParametersMixin, TestCase):
"""All test cases must inherit from this one."""
+1 -1
View File
@@ -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"]
+2
View File
@@ -9,6 +9,7 @@ from rest_framework import permissions
from rest_framework.views import APIView
from modoboa.admin.models import Domain
from modoboa.lib.throttle import UserLesserDdosUser
from .serializers import GetAccountCredentialsSerializer
@@ -22,6 +23,7 @@ class PDFCredentialView(APIView):
)
serializer_class = GetAccountCredentialsSerializer
throttle_classes = [UserLesserDdosUser]
def get_queryset(self):
"""Filter queryset based on current user."""