diff --git a/intranet/apps/auth/views.py b/intranet/apps/auth/views.py index 7f684ca51a6..6d6c45eb467 100644 --- a/intranet/apps/auth/views.py +++ b/intranet/apps/auth/views.py @@ -17,6 +17,7 @@ from django.urls import reverse from django.utils import timezone from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ from django.views.decorators.debug import sensitive_post_parameters from django.views.generic.base import View @@ -247,6 +248,11 @@ def post(self, request): return response else: + auth_errors = form.errors.get('__all__', []) + lockout_message = _("Your account has been locked due to too many failed login attempts. Please try again in a few minutes.") + for error in auth_errors: + if "locked" in error: + form.add_error(None, lockout_message) log_auth(request, "failed") logger.info("Login failed as %s", request.POST.get("username", "unknown")) return index_view(request, auth_form=form) diff --git a/intranet/templates/auth/login.html b/intranet/templates/auth/login.html index 17cf595a4ad..ac1fa1890cd 100644 --- a/intranet/templates/auth/login.html +++ b/intranet/templates/auth/login.html @@ -88,6 +88,13 @@ <h1>TJ Intranet</h1> {{ auth_message }} </div> {% endif %} + {% if form.non_field_errors %} + <div class="alert alert-danger"> + {% for error in form.non_field_errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} <form autocomplete="off" action="/login" method="post" name="auth_form"> {% if request.GET.next %} <input type="hidden" name="next" value="{{ request.GET.next|escape }}"> @@ -116,6 +123,9 @@ <h1>TJ Intranet</h1> <a href="{% url 'docs_accounts' %}">CSL Account Documentation</a> </div> {% endif %} + {% if lockout_message %} + <p class="error">{{ lockout_message }}</p> + {% endif %} </form> </div> <div class="schedule-outer{% if sports_events|length > 0 or school_events|length > 0 %} has-events{% endif %}">