U
    Qh                     @   s   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZmZmZ G dd deZdd Zeedd Zeedd Zdd ZdS )au  
Enhanced Authentication System for Stream Processor

This module provides enhanced authentication features including:
- Two-Factor Authentication (2FA) with TOTP
- Enhanced session management
- Password policies and validation
- Account lockout protection
- Login attempt tracking
- Security logging

Author: Stream Processor Development Team
Version: 1.0.0
Created: 2025
    )	timedelta)models)User)ModelBackend)Session)user_logged_inuser_logged_out)receiver)ValidationError)gettext_lazy)TimestampedModel)UserProfileLoginAttemptUserSessionc                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )EnhancedAuthenticationBackendzA
    Enhanced authentication backend with security features.
    Nc              	   K   s   |dks|dkrdS zt jj|d}W n( t jk
rN   | ||dd Y dS X tjj|d\}}| r~| ||dd dS ||r|j	rdS |
  |r| ||_|jdgd | ||d	 |S |  | ||dd
 dS dS )zB
        Authenticate user with enhanced security checks.
        N)usernameFzUser not founduserzAccount lockedlast_login_ip)update_fieldsTzInvalid password)r   objectsgetDoesNotExist_log_login_attemptr   get_or_createis_account_lockedcheck_passwordis_2fa_enabledreset_failed_attempts_get_client_ipr   saveincrement_failed_attempts)selfrequestr   passwordkwargsr   profilecreated r(   G/var/www/html/StreamProcessor/src/apps/authentication/authentication.pyauthenticate(   s.    
z*EnhancedAuthenticationBackend.authenticatec                 C   s0   |j d}|r |dd }n|j d}|S )z5
        Get client IP address from request.
        HTTP_X_FORWARDED_FOR,r   REMOTE_ADDR)METAr   split)r"   r#   Zx_forwarded_foripr(   r(   r)   r   U   s
    z,EnhancedAuthenticationBackend._get_client_ip c                 C   s2   |sdS t jj|| ||jdd||d dS )z<
        Log login attempt for security monitoring.
        NHTTP_USER_AGENTr1   )r   
ip_address
user_agentsuccessfailure_reason)r   r   creater   r.   r   )r"   r#   r   r5   r6   r(   r(   r)   r   `   s    z0EnhancedAuthenticationBackend._log_login_attempt)NN)r1   )__name__
__module____qualname____doc__r*   r   r   r(   r(   r(   r)   r   #   s   
-r   c              	   C   s   g }t | dk r|td tdd | D s>|td tdd | D s^|td tdd | D s~|td	 td
d | D s|td dddddddddg	}|  |kr|td |rt|dS )z
    Validate password strength.
    
    Args:
        password: Password to validate
        
    Raises:
        ValidationError: If password doesn't meet requirements
       z-Password must be at least 12 characters long.c                 s   s   | ]}|  V  qd S N)isupper.0cr(   r(   r)   	<genexpr>   s     z+validate_strong_password.<locals>.<genexpr>z4Password must contain at least one uppercase letter.c                 s   s   | ]}|  V  qd S r=   )islowerr?   r(   r(   r)   rB      s     z4Password must contain at least one lowercase letter.c                 s   s   | ]}|  V  qd S r=   )isdigitr?   r(   r(   r)   rB      s     z)Password must contain at least one digit.c                 s   s   | ]}|d kV  qdS )z!@#$%^&*()_+-=[]{}|;:,.<>?Nr(   r?   r(   r(   r)   rB      s     z5Password must contain at least one special character.r$   Z123456Zpassword123adminZqwertyZletmeinZwelcomemonkeyZ
1234567890zPassword is too common.N)lenappend_anylowerr
   )r$   errorsZcommon_passwordsr(   r(   r)   validate_strong_passwordp   s2    
       rM   c           	   	   K   s   |sdS t jj|d\}}tjj||jjt ||j	
ddd tjj|ddd}| |jkr||jd }|D ]B}d	|_|  ztjj
|jd
  W qz tjk
r   Y qzX qzdS )zG
    Handle user login - create session record and enforce limits.
    Nr   r2   r1   )r   session_keyr3   r4   T)r   	is_activez-last_activityF)rN   )r   r   r   r   r7   sessionrN   r   r   r.   r   filterorder_bycountmax_concurrent_sessionsrO   r    r   deleter   )	senderr#   r   r%   r&   r'   active_sessionsZsessions_to_deactivaterP   r(   r(   r)   on_user_logged_in   s0    
rX   c                 K   sN   |r|sdS z&t jj||jjd}d|_|  W n t jk
rH   Y nX dS )z9
    Handle user logout - deactivate session record.
    N)r   rN   F)r   r   r   rP   rN   rO   r    r   )rV   r#   r   r%   rP   r(   r(   r)   on_user_logged_out   s    rY   c                  C   sx   t  tdd } tjj| d  t  tdd } tjjd| d  t  tdd }tjjd	|d
jdd dS )zw
    Clean up expired sessions and login attempts.
    This should be called periodically (e.g., via Celery task).
       )days)Zcreated_at__lt   F)rO   Zupdated_at__lt   )hoursT)rO   Zlast_activity__lt)rO   N)	timezonenowr   r   r   rQ   rU   r   update)Zcutoff_dateZinactive_cutoffr(   r(   r)   cleanup_expired_sessions   s    
rb   N) r;   datetimer   	django.dbr   django.contrib.auth.modelsr   Zdjango.contrib.auth.backendsr   django.contrib.sessions.modelsr   Zdjango.contrib.auth.signalsr   r   django.dispatchr	   django.core.exceptionsr
   django.utils.translationr   rI   Zapps.core.modelsr   Zapps.authentication.modelsr   r   r   r   rM   rX   rY   rb   r(   r(   r(   r)   <module>   s$   M)
&
