
    LCj
              	           d Z ddlmZ ddlmZ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 dd	lmZ dd
lmZ  e       Ze G d d             Z ee       edd      fdede
dedz  defdZy)u7  
Dual-mode authentication for endpoints reachable both by the SaaS
customer dashboard (JWT-authenticated) and by service/integration
callers (API-key-authenticated).

/analyze is the main consumer of this — a logged-in customer using the
dashboard hits it with a Bearer token, while a server-to-server
integration the client sets up later can keep using an API key. Either
is accepted; the resulting AuthContext tells the route handler which
one was used and, if a user, who they are — so the analysis can be
correctly attributed and saved against their account.
    )	dataclass)DependsHeaderRequest)select)AsyncSession)decode_token)get_settings)AuthenticationError)User)get_db_sessionc                   \    e Zd ZU eed<   dZedz  ed<   dZedz  ed<   ededz  fd       Z	y)AuthContext	auth_typeNuserapi_keyreturnc                 J    | j                   r| j                   j                  S d S )N)r   id)selfs    ?C:\Crop_Prediction\Backend\crop-ai-system\app\core\dual_auth.pyuser_idzAuthContext.user_id#   s    #yytyy||2d2    )
__name__
__module____qualname__str__annotations__r   r   r   propertyr    r   r   r   r      s@    ND$+GS4Z3t 3 3r   r   Nz	X-API-Key)aliasrequestdb	x_api_keyr   c                   K   | j                   j                  d      }|r|j                         j                  d      r|dd  }t	        |d      }|j                  d      }|j                  t        t              j                  t        j                  |k(               d {   }|j                         }|t        d      |j                  st        d	      t        d
|      S |rXt        j                  }	|	s)t        j                   rt        d      t        d|      S ||	vrt        d      t        d|      S t        d      7 w)NAuthorizationzbearer    access)expected_typesubzUser account no longer exists)messagez3This account has been deactivated. Contact support.r   )r   r   z'Service misconfigured. Contact support.r   )r   r   zInvalid or missing API keyzuAuthentication required. Provide either a Bearer token (logged-in user) or an X-API-Key header (service integration).)headersgetlower
startswithr	   executer   r   wherer   scalar_one_or_noner   	is_activer   settingsvalid_api_keys_listis_production)
r"   r#   r$   auth_headertokenpayloadr   resultr   
valid_keyss
             r   get_auth_contextr<   (   s/    
 //%%o6K{((*55i@ABuH=++e$zz&,"4"4TWW5G"HII((*<%.MNN~~%.cddV$7711
%%)2[\\IFFJ&%.JKKY	BB
@ + Js   B!E#E$B.E)__doc__dataclassesr   fastapir   r   r   
sqlalchemyr   sqlalchemy.ext.asyncior   app.core.auth_tokensr	   app.core.configr
   app.core.exceptionsr   app.db.modelsr   app.db.sessionr   r4   r   r   r<   r    r   r   <module>rG      s    " , ,  / - ( 3  )> 3 3 3 ~."4{;$$$ Tz$ 	$r   