Run black autoformatting

This commit is contained in:
Aleksi Häkli 2026-02-11 21:54:13 +02:00
parent 5acae054b4
commit 4b77eb69ee
7 changed files with 51 additions and 19 deletions

View file

@ -19,7 +19,9 @@ class IsLockedOutFilter(admin.SimpleListFilter):
def queryset(self, request, queryset):
if self.value() == "yes":
return queryset.filter(failures_since_start__gte=settings.AXES_FAILURE_LIMIT)
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
@ -34,9 +36,9 @@ class AccessAttemptAdmin(admin.ModelAdmin):
"path_info",
"failures_since_start",
]
if settings.AXES_USE_ATTEMPT_EXPIRATION:
list_display.append('expiration')
list_display.append("expiration")
list_filter = ["attempt_time", "path_info"]
@ -51,7 +53,10 @@ class AccessAttemptAdmin(admin.ModelAdmin):
date_hierarchy = "attempt_time"
fieldsets = (
(None, {"fields": ("username", "path_info", "failures_since_start", "expiration")}),
(
None,
{"fields": ("username", "path_info", "failures_since_start", "expiration")},
),
(_("Form Data"), {"fields": ("get_data", "post_data")}),
(_("Meta Data"), {"fields": ("user_agent", "ip_address", "http_accept")}),
)
@ -69,9 +74,9 @@ class AccessAttemptAdmin(admin.ModelAdmin):
"expiration",
]
actions = ['cleanup_expired_attempts']
actions = ["cleanup_expired_attempts"]
@admin.action(description=_('Clean up expired attempts'))
@admin.action(description=_("Clean up expired attempts"))
def cleanup_expired_attempts(self, request, queryset):
count = self.handler.clean_expired_user_attempts(request=request)
self.message_user(request, _(f"Cleaned up {count} expired access attempts."))
@ -85,10 +90,15 @@ class AccessAttemptAdmin(admin.ModelAdmin):
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")
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 = (

View file

@ -235,4 +235,4 @@ def is_valid_callable(value) -> bool:
except ImportError:
return False
return True
return True

View file

@ -11,6 +11,7 @@ class JSONSerializableLazyObject(SimpleLazyObject):
Fixes jazzband/django-axes#1391
"""
def __json__(self):
return str(self)
@ -55,6 +56,7 @@ settings.AXES_ONLY_ADMIN_SITE = getattr(settings, "AXES_ONLY_ADMIN_SITE", False)
# show Axes logs in admin
settings.AXES_ENABLE_ADMIN = getattr(settings, "AXES_ENABLE_ADMIN", True)
# use a specific username field to retrieve from login POST data
def _get_username_field_default():
return get_user_model().USERNAME_FIELD
@ -106,7 +108,9 @@ settings.AXES_LOCKOUT_URL = getattr(settings, "AXES_LOCKOUT_URL", None)
settings.AXES_COOLOFF_TIME = getattr(settings, "AXES_COOLOFF_TIME", None)
settings.AXES_USE_ATTEMPT_EXPIRATION = getattr(settings, "AXES_USE_ATTEMPT_EXPIRATION", False)
settings.AXES_USE_ATTEMPT_EXPIRATION = getattr(
settings, "AXES_USE_ATTEMPT_EXPIRATION", False
)
settings.AXES_VERBOSE = getattr(settings, "AXES_VERBOSE", settings.AXES_ENABLED)

View file

@ -21,7 +21,12 @@ from axes.helpers import (
get_query_str,
get_attempt_expiration,
)
from axes.models import AccessAttempt, AccessAttemptExpiration, AccessFailureLog, AccessLog
from axes.models import (
AccessAttempt,
AccessAttemptExpiration,
AccessFailureLog,
AccessLog,
)
from axes.signals import user_locked_out
log = getLogger(__name__)
@ -223,15 +228,17 @@ class AxesDatabaseHandler(AbstractAxesHandler, AxesBaseHandler):
if settings.AXES_USE_ATTEMPT_EXPIRATION:
if not hasattr(attempt, "expiration") or attempt.expiration is None:
log.debug(
"AXES: Creating new AccessAttemptExpiration for %s", client_str
"AXES: Creating new AccessAttemptExpiration for %s",
client_str,
)
attempt.expiration = AccessAttemptExpiration.objects.create(
access_attempt=attempt,
expires_at=get_attempt_expiration(request)
expires_at=get_attempt_expiration(request),
)
else:
attempt.expiration.expires_at = max(
get_attempt_expiration(request), attempt.expiration.expires_at
get_attempt_expiration(request),
attempt.expiration.expires_at,
)
attempt.expiration.save()
@ -400,7 +407,9 @@ class AxesDatabaseHandler(AbstractAxesHandler, AxesBaseHandler):
if settings.AXES_USE_ATTEMPT_EXPIRATION:
threshold = timezone.now()
count, _ = AccessAttempt.objects.filter(expiration__expires_at__lte=threshold).delete()
count, _ = AccessAttempt.objects.filter(
expiration__expires_at__lte=threshold
).delete()
log.info(
"AXES: Cleaned up %s expired access attempts from database that expiry were older than %s",
count,
@ -408,7 +417,9 @@ class AxesDatabaseHandler(AbstractAxesHandler, AxesBaseHandler):
)
else:
threshold = get_cool_off_threshold(request)
count, _ = AccessAttempt.objects.filter(attempt_time__lte=threshold).delete()
count, _ = AccessAttempt.objects.filter(
attempt_time__lte=threshold
).delete()
log.info(
"AXES: Cleaned up %s expired access attempts from database that were older than %s",
count,

View file

@ -100,6 +100,7 @@ def get_cool_off_iso8601(delta: timedelta) -> str:
return f"P{days_str}T{time_str}"
return f"P{days_str}"
def get_attempt_expiration(request: Optional[HttpRequest] = None) -> datetime:
"""
Get threshold for fetching access attempts from the database.
@ -116,6 +117,7 @@ def get_attempt_expiration(request: Optional[HttpRequest] = None) -> datetime:
return datetime.now() + cool_off
return attempt_time + cool_off
def get_credentials(username: Optional[str] = None, **kwargs) -> dict:
"""
Calculate credentials for Axes to use internally from given username and kwargs.

View file

@ -60,6 +60,8 @@ class AxesMiddleware:
credentials = getattr(request, "axes_credentials", None)
response = await sync_to_async(
get_lockout_response, thread_sensitive=True
)(request, credentials) # type: ignore
)(
request, credentials
) # type: ignore
return response

View file

@ -68,9 +68,12 @@ class AccessAttemptExpiration(models.Model):
verbose_name = _("access attempt expiration")
verbose_name_plural = _("access attempt expirations")
class AccessLog(AccessBase):
logout_time = models.DateTimeField(_("Logout Time"), null=True, blank=True)
session_hash = models.CharField(_("Session key hash (sha256)"), default="", blank=True, max_length=64)
session_hash = models.CharField(
_("Session key hash (sha256)"), default="", blank=True, max_length=64
)
def __str__(self):
return f"Access Log for {self.username} @ {self.attempt_time}"