
    )i                        d Z ddlZddlmZmZmZ ddlmZmZmZ ddl	m
Z
mZ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 erddlmZ ddlmZ ddlmZ ddlmZ  e       Z  e
e        e
e      fdee   deded   fdZ! e
e        e
e      fdededdfdZ" e
e"      f	 	 	 ddZ# e
e#      f	 	 	 ddZ$ e
e#      f	 	 	 ddZ%de&deded   fdZ' e
e"       e
e      fdddefdZ(d Z)y)z8
Authentication utilities and dependencies for FastAPI.
    N)datetime	timedeltatimezone)OptionalUnionTYPE_CHECKING)DependsHTTPExceptionstatus)
HTTPBearerHTTPAuthorizationCredentials)Session)select)Merchant)MerchantUsersUserAuthSession)get_db)jwt_managercredentialsdbreturnr   c                 P   K   | syt        | j                  |       d{   S 7 w)a   
    Get current user from JWT token (optional - returns None if no token or invalid).
    
    Args:
        credentials: HTTP Bearer token credentials
        db: Database session
        
    Returns:
        User model or None if not authenticated
    N)_verify_token_and_get_userr   )r   r   s     V/var/www/html/hwPaymentPortal-be-dev/hw-payment-portal-api/src/apps/auth/utils/auth.pyget_current_user_optionalr      s'      +K,C,CRHHHHs   &$&c                    K   t        | j                  |       d{   }|st        t        j                  dddi      |S 7 &w)a)  
    Get current user from JWT token (required - raises exception if not authenticated).
    
    Args:
        credentials: HTTP Bearer token credentials
        db: Database session
        
    Returns:
        User model
        
    Raises:
        HTTPException: If authentication fails
    NzCould not validate credentialszWWW-AuthenticateBearer)status_codedetailheaders)r   r   r
   r   HTTP_401_UNAUTHORIZED)r   r   users      r   get_current_userr&   /   sN     " ,K,C,CRHHD443'2
 	
 K Is   AA'Acurrent_userc                 \   K   | j                   st        t        j                  d      | S w)z
    Get current active user (must be authenticated and active).
    
    Args:
        current_user: Current authenticated user
        
    Returns:
        Active user model
        
    Raises:
        HTTPException: If user is inactive
    zInactive userr!   r"   )is_user_activer
   r   HTTP_400_BAD_REQUESTr'   s    r   get_current_active_userr-   L   s2      &&33"
 	

    *,c                 \   K   | j                   st        t        j                  d      | S w)a  
    Get current verified user (must be authenticated, active, and verified).
    
    Args:
        current_user: Current active user
        
    Returns:
        Verified user model
        
    Raises:
        HTTPException: If user is not verified
    zEmail not verifiedr)   )is_user_verifiedr
   r   r+   r,   s    r   get_current_verified_userr1   d   s2      ((33'
 	

 r.   c                 \   K   | j                   st        t        j                  d      | S w)z
    Get current superuser (must be authenticated, active, and superuser).
    
    Args:
        current_user: Current active user
        
    Returns:
        Superuser model
        
    Raises:
        HTTPException: If user is not a superuser
    zNot enough permissionsr)   )is_superuserr
   r   HTTP_403_FORBIDDENr,   s    r   get_current_superuserr5   |   s2      $$11+
 	

 r.   tokenc                   K   ddl m} ddlm} t	        j
                  |       }|sy|j                  d      }|sy|j                  d      }|syt        |      j                  |j                  | k(  |j                  dk(  |j                  dk(        }|j                  |      j                         }|sy|j                         r!|j                          |j!                          yt        |      j                  |j"                  |k(        }	|j                  |	      j                         }
|
sy|j%                          |j!                          |
S w)	z
    Verify JWT token and return the associated user.
    
    Args:
        token: JWT token string
        db: Database session
        
    Returns:
        User model or None if invalid
    r   r   r   Nr%   user_idTF)src.apps.users.models.userr   !src.apps.auth.models.auth_sessionr   r   verify_tokengetr   whereaccess_token	is_active
is_revokedexecutescalar_one_or_none
is_expiredrevokecommitidupdate_activity)r6   r   r   r   payload	user_datar8   stmtsession	user_stmtr%   s              r   r   r      s,     0= &&u-G F#ImmI&G +$$  E)%%'D
 jj113G 
		 t""477g#56I::i 335D IIKKs   EEc                 ^  K   t        t              j                  t        t        j                  t        j
                  k(        j                  t        j                  | j                  k(        }|j                  |      j                         }|st        t        j                  d      |S w)a$  
    Get current merchant from authenticated user.
    
    Args:
        current_user: Current authenticated user
        db: Database session
        
    Returns:
        Merchant model associated with the user
        
    Raises:
        HTTPException: If no merchant found for user
    z"No merchant found for current userr)   )r   r   joinr   rF   merchant_idr=   r8   rA   rB   r
   r   HTTP_404_NOT_FOUND)r'   r   rJ   merchants       r   get_current_merchantrR      s     & 	x	mX[[M,E,EE	F	}$$7	8 	
 zz$224H117
 	

 Os   B+B-c                       fd}|S )z
    Decorator to require authentication for a function.
    
    Usage:
        @require_auth
        def my_protected_function(current_user: User = Depends(get_current_user)):
            pass
    c                       | i |S )N )argskwargsfuncs     r   wrapperzrequire_auth.<locals>.wrapper   s    T$V$$    rU   )rX   rY   s   ` r   require_authr[      s    %NrZ   )r'   r   r   r   )*__doc__jwtr   r   r   typingr   r   r   fastapir	   r
   r   fastapi.securityr   r   sqlalchemy.ormr   
sqlalchemyr   "src.apps.merchants.models.merchantr   (src.apps.merchants.models.merchant_usersr   r9   r   r:   r   src.core.databaser   src.apps.auth.utils.jwtr   securityr   r&   r-   r1   r5   strr   rR   r[   rU   rZ   r   <module>ri      sg    2 2 1 1 2 2 E "  7 B /= $ / < ;B(:K&/I67II fI* 180A&/- < ##342 ##:;2 ##:;09C 9W 9&AQ 9z ##34&/DrZ   