Skip to content

Commit

Permalink
added feature to send email once the user is blocked based on username
Browse files Browse the repository at this point in the history
  • Loading branch information
saurav-codes committed Feb 26, 2024
1 parent cc35032 commit f39e27f
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
6 changes: 6 additions & 0 deletions defender/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ def get_setting(variable, default=None):

USE_CELERY = get_setting("DEFENDER_USE_CELERY", False)

EMAIL_USER_ON_ACCOUNT_LOCKED = get_setting("DEFENDER_EMAIL_USER_ON_ACCOUNT_LOCKED", False)
# A 'user' instance is passed as context to lockout email template
LOCKOUT_EMAIL_TEMPLATE_PATH = get_setting("DEFENDER_LOCKOUT_EMAIL_TEMPLATE_PATH", "defender/lockout_email.html")

DEFAULT_FROM_EMAIL = get_setting("DEFENDER_DEFAULT_FROM_EMAIL")

STORE_ACCESS_ATTEMPTS = get_setting("DEFENDER_STORE_ACCESS_ATTEMPTS", True)

# Used by the management command to decide how long to keep access attempt
Expand Down
6 changes: 6 additions & 0 deletions defender/templates/defender/lockout_email.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Hi {{ user.username }},
<br>
<br>
Your account has been locked out due to too many failed login attempts.
Please contact the administrator to unlock your account.
<br>
28 changes: 28 additions & 0 deletions defender/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
from django.shortcuts import render
from django.core.validators import validate_ipv46_address
from django.core.exceptions import ValidationError
from django.core.mail import send_mail
from django.contrib.auth import get_user_model
from django.template.loader import render_to_string
from django.utils.module_loading import import_string

from .connection import get_redis_connection
Expand All @@ -23,6 +26,7 @@
REDIS_SERVER = get_redis_connection()

LOG = logging.getLogger(__name__)
User = get_user_model()


def is_valid_ip(ip_address):
Expand Down Expand Up @@ -270,6 +274,8 @@ def block_username(username):
REDIS_SERVER.set(key, "blocked")
if not already_blocked:
send_username_block_signal(username)
if config.EMAIL_USER_ON_ACCOUNT_LOCKED:
send_account_locked_email_to_user(username)

Check warning on line 278 in defender/utils.py

View check run for this annotation

Codecov / codecov/patch

defender/utils.py#L278

Added line #L278 was not covered by tests


def record_failed_attempt(ip_address, username):
Expand Down Expand Up @@ -460,3 +466,25 @@ def add_login_attempt_to_db(
store_login_attempt(
user_agent, ip_address, username, http_accept, path_info, login_valid
)


def send_account_locked_email_to_user(username:str):
""" Send an email to the user to notify them that their account has been locked """
try:
user = User.objects.get(username=username)
except User.DoesNotExist:

Check warning on line 475 in defender/utils.py

View check run for this annotation

Codecov / codecov/patch

defender/utils.py#L473-L475

Added lines #L473 - L475 were not covered by tests
# TODO: Handle the case where the user does not exist
return

Check warning on line 477 in defender/utils.py

View check run for this annotation

Codecov / codecov/patch

defender/utils.py#L477

Added line #L477 was not covered by tests

html_message = render_to_string(config.LOCKOUT_EMAIL_TEMPLATE_PATH, {"user": user})
plan_text_message = f"Hi {user.username}, Your account has been locked due to too many failed login attempts.Please contact an admin to unlock your account."
send_mail(

Check warning on line 481 in defender/utils.py

View check run for this annotation

Codecov / codecov/patch

defender/utils.py#L479-L481

Added lines #L479 - L481 were not covered by tests
'Account Locked',
plan_text_message,
from_email=config.DEFAULT_FROM_EMAIL,
recipient_list=[user.email],
html_message=html_message,
fail_silently=False
)


0 comments on commit f39e27f

Please sign in to comment.