107 lines
5 KiB
Python
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()
|