diff --git a/axes/admin.py b/axes/admin.py index 877ab75f..9cae2e60 100644 --- a/axes/admin.py +++ b/axes/admin.py @@ -6,29 +6,45 @@ from axes.models import AccessAttempt, AccessLog, AccessFailureLog +class IsLockedOutFilter(admin.SimpleListFilter): + title = _("Locked Out") + parameter_name = "locked_out" + + def lookups(self, request, model_admin): + return ( + ("yes", _("Yes")), + ("no", _("No")), + ) + + def queryset(self, request, queryset): + if self.value() == "yes": + return queryset.filter(failures_since_start__gte=settings.AXES_FAILURE_LIMIT) + elif self.value() == "no": + return queryset.filter(failures_since_start__lt=settings.AXES_FAILURE_LIMIT) + return queryset + + class AccessAttemptAdmin(admin.ModelAdmin): + list_display = [ + "attempt_time", + "ip_address", + "user_agent", + "username", + "path_info", + "failures_since_start", + ] + if settings.AXES_USE_ATTEMPT_EXPIRATION: - list_display = ( - "attempt_time", - "expiration", - "ip_address", - "user_agent", - "username", - "path_info", - "failures_since_start", - ) - else: - list_display = ( - "attempt_time", - "ip_address", - "user_agent", - "username", - "path_info", - "failures_since_start", - ) + list_display.append('expiration') list_filter = ["attempt_time", "path_info"] + if isinstance(settings.AXES_FAILURE_LIMIT, int) and settings.AXES_FAILURE_LIMIT > 0: + # This will only add the status field if AXES_FAILURE_LIMIT is set to a positive integer + # Because callable failure limit requires scope of request object + list_display.append("status") + list_filter.append(IsLockedOutFilter) + search_fields = ["ip_address", "username", "user_agent", "path_info"] date_hierarchy = "attempt_time" @@ -57,6 +73,10 @@ def has_add_permission(self, request: HttpRequest) -> bool: def expiration(self, obj: AccessAttempt): return obj.expiration.expires_at if hasattr(obj, "expiration") else _("Not set") + + def status(self, obj: AccessAttempt): + return f"{settings.AXES_FAILURE_LIMIT - obj.failures_since_start} "+_("Attempt Remaining") if \ + obj.failures_since_start < settings.AXES_FAILURE_LIMIT else _("Locked Out") class AccessLogAdmin(admin.ModelAdmin): list_display = (