Ë
    LµCj  ã            	       óô   — d Z ddlmZmZ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  e«       Z e
dgd	¬
«      ZdZdZdZdedefd„Zdededefd„Zdededefd„Zdedefd„Zddededeeef   fd„Zy)uø  
Password hashing and JWT token utilities.

This is a separate authentication mechanism from app/core/security.py's
API-key auth. API keys identify a calling service/integration with a
long-lived static secret; JWTs here identify an individual logged-in
customer with a short-lived, expiring token â€” the standard pattern for
a user-facing SaaS login, not machine-to-machine API access.

Password hashing uses bcrypt via passlib â€” never store or compare
plaintext passwords anywhere in this codebase.
é    )ÚdatetimeÚ	timedeltaÚtimezone)ÚAny)ÚJWTErrorÚjwt)ÚCryptContext)Úget_settings)ÚAuthenticationErrorÚbcryptÚauto)ÚschemesÚ
deprecatedÚHS256i   é   Úplain_passwordÚreturnc                 ó,   — t         j                  | «      S ©N)Úpwd_contextÚhash)r   s    úAC:\Crop_Prediction\Backend\crop-ai-system\app\core\auth_tokens.pyÚhash_passwordr   #   s   € Ü×Ñ˜NÓ+Ð+ó    Úhashed_passwordc                 ó.   — t         j                  | |«      S r   )r   Úverify)r   r   s     r   Úverify_passwordr   '   s   € Ü×Ñ˜n¨oÓ>Ð>r   Úuser_idÚemailc                 ó  — t        j                  t        j                  «      t	        t
        ¬«      z   }| |d|t        j                  t        j                  «      dœ}t        j                  |t        j                  t        ¬«      S )N)ÚminutesÚaccess)Úsubr    ÚtypeÚexpÚiat©Ú	algorithm)r   Únowr   Úutcr   ÚACCESS_TOKEN_EXPIRE_MINUTESr   ÚencodeÚsettingsÚ
SECRET_KEYÚJWT_ALGORITHM)r   r    ÚexpireÚpayloads       r   Úcreate_access_tokenr3   +   s]   € Ü�\‰\œ(Ÿ,™,Ó'¬)Ô<WÔ*XÑX€FàØØØÜ�|‰|œHŸL™LÓ)ñ€Gô �:‰:�gœx×2Ñ2¼mÔLÐLr   c                 ó  — t        j                  t        j                  «      t	        t
        ¬«      z   }| d|t        j                  t        j                  «      dœ}t        j                  |t        j                  t        ¬«      S )N)ÚdaysÚrefresh)r$   r%   r&   r'   r(   )r   r*   r   r+   r   ÚREFRESH_TOKEN_EXPIRE_DAYSr   r-   r.   r/   r0   )r   r1   r2   s      r   Úcreate_refresh_tokenr8   7   sZ   € Ü�\‰\œ(Ÿ,™,Ó'¬)Ô9RÔ*SÑS€FàØØÜ�|‰|œHŸL™LÓ)ñ	€Gô �:‰:�gœx×2Ñ2¼mÔLÐLr   ÚtokenÚexpected_typec                 óâ   — 	 t        j                  | t        j                  t        g¬«      }|j                  d«      |k7  rt        d|› d�¬«      ‚|S # t
        $ r}t        d¬«      |‚d}~ww xY w)uA  
    Raises AuthenticationError (not a raw JWTError) on any failure â€”
    expired, malformed, wrong signature, or wrong token type used in the
    wrong place (e.g. a refresh token presented where an access token
    is required). Callers should never need to know about python-jose's
    exception types directly.
    )Ú
algorithmszInvalid or expired token)ÚmessageNr%   zExpected a z token)r   Údecoder.   r/   r0   r   r   Úget)r9   r:   r2   Úexcs       r   Údecode_tokenrA   B   sp   € ðOÜ—*‘*˜U¤H×$7Ñ$7Ä]ÀOÔTˆð ‡{�{�6Ó˜mÒ+Ü!¨K¸°ÀfÐ*MÔNÐNà€Nøô ò OÜ!Ð*DÔEÈ3ÐNûðOús   ‚+A Á	A.ÁA)Á)A.N)r#   )Ú__doc__r   r   r   Útypingr   Újoser   r   Úpasslib.contextr	   Úapp.core.configr
   Úapp.core.exceptionsr   r.   r   r0   r,   r7   Ústrr   Úboolr   r3   r8   ÚdictrA   © r   r   ú<module>rL      sÌ   ðñ÷ 3Ñ 2Ý ç Ý (å (Ý 3á‹>€ñ
  H :¸&ÔA€à€Ø%Ð ØÐ ð, #ð ,¨#ó ,ð? Cð ?¸#ð ?À$ó ?ð	M ð 	M¨Sð 	M°Só 	MðM #ð M¨#ó Mñ˜ð ¨Cð ¸tÀCÈÀH¹~ô r   