old_console/core/services/authentication.py
2024-11-02 14:12:45 +03:00

107 lines
5 KiB
Python

import logging
from django.utils.translation import gettext_lazy
from core.models import ConsoleAuthSettings
from core.utils import dtnow
_log = logging.getLogger(__name__)
def create_authentication_log_message(action, message, ip_addr=None):
log_string = f'Authentication {action}'
if ip_addr:
log_string += f' from ip: {ip_addr}'
log_string += f': {message}'
return log_string
def handle_login_attempt(attempt_username_data, login_successful, ip_address):
if attempt_username_data.is_username_auth_blocked:
_log.info(create_authentication_log_message(
'attempt',
f'[{attempt_username_data.user.username}] account is blocked until '
f'{attempt_username_data.username_unlock_time}',
ip_address))
attempt_username_data.save()
return False, gettext_lazy('Authentication for this user is blocked. Please contact administrator')
if login_successful:
if attempt_username_data.failed_login_attempts == 0:
_log.info(create_authentication_log_message(
'attempt', f'[{attempt_username_data.user.username}] has been successfully authenticated',
ip_address))
attempt_username_data.save()
return True, None
else:
_log.info(create_authentication_log_message(
'attempt',
f'[{attempt_username_data.user.username}] has been successfully authenticated after '
f'{attempt_username_data.failed_login_attempts} '
f'tries. Failed login attempts counter has been reset',
ip_address))
attempt_username_data.failed_login_attempts = 0
attempt_username_data.save()
return True, None
else:
# Get authentication settings
auth_settings = ConsoleAuthSettings.get_solo()
_log.info(create_authentication_log_message(
'attempt',
f'[{attempt_username_data.user.username}] failed to authenticate. Amount of failed attempts: '
f'{attempt_username_data.failed_login_attempts + 1}/{auth_settings.login_attempts_limit}',
ip_address))
amount_of_failed_attempts = attempt_username_data.failed_login_attempts + 1
attempt_username_data.failed_login_attempts += 1
if (auth_settings.login_attempts_limit > 0 and
amount_of_failed_attempts == auth_settings.login_attempts_limit and
attempt_username_data.is_username_auth_blocked == False):
attempt_username_data.is_username_auth_blocked = True
user_unlock_time = dtnow() + auth_settings.login_block_timeout
_log.info(create_authentication_log_message(
'settings',
f'[{attempt_username_data.user.username}] Blocked authentication for '
f'{attempt_username_data.user.username} until {user_unlock_time} '
f'due to the exceeding the limit of login attempts',
ip_address))
attempt_username_data.username_unlock_time = user_unlock_time
attempt_username_data.save()
return False, gettext_lazy('Authentication for this user is blocked for {time}').format(
time=auth_settings.login_block_timeout)
elif attempt_username_data.is_username_auth_blocked:
_log.info(create_authentication_log_message(
'attempt',
f'[{attempt_username_data.user.username}] failed to authenticate due to timeout. '
f'Amount of failed attempts: '
f'{attempt_username_data.failed_login_attempts + 1}/{auth_settings.login_attempts_limit}',
ip_address))
return False, gettext_lazy(
"Authentication for this user is blocked, please contact system administrator"),
attempt_username_data.save()
return False, gettext_lazy('Please enter a correct username and password. '
'Note that both fields may be case-sensitive.')
def get_timeout_formatted(console_auth_settings):
""" Method for formatting DurationField into dict with corresponding time values
:return: dictionary with the following content:
{
'days': <days_integer>,
'hours': <hours_integer>,
'minutes': <minutes_integer>,
'seconds': <seconds_integer>
}
"""
formatted_timeout = {'days': console_auth_settings.login_block_timeout.days}
formatted_timeout['hours'], rem = divmod(console_auth_settings.login_block_timeout.seconds, 3600)
formatted_timeout["minutes"], formatted_timeout["seconds"] = divmod(rem, 60)
return formatted_timeout
def set_account_block(auth_data): # todo not used. remove?
""" Method for forbieden access to authentication for user account """
auth_data.is_username_auth_blocked = True
_log.info(create_authentication_log_message(
'settings', f'user [{auth_data.user.username}] has been blocked by Administrator'))
auth_data.save()