Ë
    èU)j  ã                  óô   — d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
Z
 ej                  e«      ZdZdZdZdd„Z	 	 	 	 	 	 	 	 	 	 dd	„Zef	 	 	 	 	 	 	 	 	 dd
„Z G d„ d«      Zef	 	 	 	 	 	 	 	 	 dd„Zy)z÷eBay OAuth2 token management: exchange, refresh, and secure file-based storage.

Tokens are stored in a JSON file outside the repo (default: /var/lib/agent-samochodowy/ebay_tokens.json)
with 600 permissions so only the service user can read them.
é    )ÚannotationsN)ÚPathz-https://api.ebay.com/identity/v1/oauth2/tokena  https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.accountz+/var/lib/agent-samochodowy/ebay_tokens.jsonc                óx   — | › d|› �}dt        j                  |j                  «       «      j                  «       z   S )z#Build HTTP Basic auth header value.ú:zBasic )Úbase64Ú	b64encodeÚencodeÚdecode)Ú	client_idÚclient_secretÚcredss      úN/var/www/html/agent.samochodowy/src/agent_samochodowy/compliance/ebay_oauth.pyÚ_basic_authr   "   s7   € àˆk˜˜=˜/Ð*€EØ”f×&Ñ& u§|¡|£~Ó6×=Ñ=Ó?Ñ?Ð?ó    c                óž   — t        j                  t        dt        ||«      dœd| |dœd¬«      }|j	                  «        |j                  «       S )ztExchange an authorization code for access_token + refresh_token.

    Returns the raw eBay token response dict.
    ú!application/x-www-form-urlencoded©zContent-TypeÚAuthorizationÚauthorization_code)Ú
grant_typeÚcodeÚredirect_urié   ©ÚheadersÚdataÚtimeout©ÚhttpxÚpostÚEBAY_TOKEN_URLr   Úraise_for_statusÚjson)r   r   r   r   Úresps        r   Úexchange_code_for_tokensr%   (   sV   € ô �:‰:Üà?Ü(¨°MÓBñ
ð
 /ØØ(ñ
ð
 ô€Dð 	×ÑÔØ�9‰9‹;Ðr   c                óž   — t        j                  t        dt        ||«      dœd| |dœd¬«      }|j	                  «        |j                  «       S )zeUse a refresh_token to obtain a new access_token.

    Returns the raw eBay token response dict.
    r   r   Úrefresh_token)r   r'   Úscoper   r   r   )r'   r   r   Úscopesr$   s        r   Úrefresh_access_tokenr*   C   sV   € ô �:‰:Üà?Ü(¨°MÓBñ
ð
 *Ø*Øñ
ð
 ô€Dð 	×ÑÔØ�9‰9‹;Ðr   c                  ób   — e Zd ZdZefd	d„Zd
d„Zdd„Zedd„«       Z	edd„«       Z
edd„«       Zy)ÚEbayTokenStorezKManages eBay OAuth tokens in a local JSON file with restricted permissions.c                ó$   — t        |«      | _        y )N)r   Úpath)Úselfr.   s     r   Ú__init__zEbayTokenStore.__init__e   s   € Ü˜“Jˆ�	r   c                ó¢  — | j                  «       }|j                  |«       t        j                  «       |d<   | j                  j                  j                  dd¬«       | j                  j                  t        j                  |d¬«      «       t        j                  | j                  d«       t        j                  d| j                  «       y)	zºPersist token data to disk.

        Merges with existing data so that a refresh (which does NOT return a new
        refresh_token) does not overwrite the stored refresh_token.
        Ú
updated_atT)ÚparentsÚexist_oké   )Úindenti€  zeBay tokens saved to %sN)ÚloadÚupdateÚtimer.   ÚparentÚmkdirÚ
write_textr#   ÚdumpsÚosÚchmodÚloggerÚinfo)r/   Ú
token_dataÚexistings      r   ÚsavezEbayTokenStore.saveh   sŠ   € ð —9‘9“;ˆØ�‰˜
Ô#Ü!%§¡£ˆ�Ñà�	‰	×Ñ×Ñ t°dÐÔ;Ø�	‰	×ÑœTŸZ™Z¨¸Ô;Ô<Ü
�‰�—‘˜EÔ"Ü�‰Ð-¨t¯y©yÕ9r   c                ó(  — | j                   j                  «       si S 	 t        j                  | j                   j	                  «       «      S # t        j
                  t        f$ r-}t        j                  d| j                   |«       i cY d}~S d}~ww xY w)z7Load stored tokens. Returns empty dict if file missing.z Failed to read token file %s: %sN)	r.   Úexistsr#   ÚloadsÚ	read_textÚJSONDecodeErrorÚOSErrorr@   Úwarning)r/   Úes     r   r7   zEbayTokenStore.loadw   sm   € à�y‰y×ÑÔ!ØˆIð	Ü—:‘:˜dŸi™i×1Ñ1Ó3Ó4Ð4øÜ×$Ñ$¤gÐ.ò 	Ü�N‰NÐ=¸t¿y¹yÈ!ÔLØ�Iûð	ús   ž,A ÁBÁ$"BÂBÂBc                óD   — | j                  «       }|j                  d«      S )NÚaccess_token©r7   Úget©r/   r   s     r   rN   zEbayTokenStore.access_token�   s   € à�y‰y‹{ˆØ�x‰x˜Ó'Ð'r   c                óD   — | j                  «       }|j                  d«      S )Nr'   rO   rQ   s     r   r'   zEbayTokenStore.refresh_token†   s   € à�y‰y‹{ˆØ�x‰x˜Ó(Ð(r   c                ó®   — | j                  «       }|j                  dd«      }|j                  dd«      }|r|syt        j                  «       ||z   dz
  kD  S )zFConservative check: treat token as expired 5 min before actual expiry.r2   r   Ú
expires_inTi,  )r7   rP   r9   )r/   r   ÚupdatedrT   s       r   Ú
is_expiredzEbayTokenStore.is_expired‹   sR   € ð �y‰y‹{ˆØ—(‘(˜<¨Ó+ˆØ—X‘X˜l¨AÓ.ˆ
Ù™jØÜ�y‰y‹{˜g¨
Ñ2°SÑ8Ñ9Ð9r   N)r.   ÚstrÚreturnÚNone)rB   ÚdictrX   rY   )rX   rZ   )rX   z
str | None)rX   Úbool)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚDEFAULT_TOKEN_PATHr0   rD   r7   ÚpropertyrN   r'   rV   © r   r   r,   r,   b   sS   „ ÙUà#5ô ó:óð ò(ó ð(ð ò)ó ð)ð ò:ó ñ:r   r,   c                ó  — |j                   s|j                  }|r|S |j                  }|st        d«      ‚t        j                  d«       t        || ||«      }|j                  |«       t        j                  d«       |d   S )zuReturn a valid access token, refreshing if necessary.

    Raises RuntimeError if no refresh_token is available.
    z^No refresh_token available. Run the OAuth consent flow first: python scripts/ebay_authorize.pyz(eBay access token expired, refreshing...z(eBay access token refreshed successfullyrN   )rV   rN   r'   ÚRuntimeErrorr@   rA   r*   rD   )r   r   Útoken_storer)   ÚtokenÚrefresh_tokrB   s          r   Úget_valid_access_tokenrh   –   s…   € ð ×!Ò!Ø×(Ñ(ˆÙØˆLà×+Ñ+€KÙÜð/ó
ð 	
ô
 ‡K�KÐ:Ô;Ü% k°9¸mÈVÓT€JØ×Ñ�ZÔ Ü
‡K�KÐ:Ô;Ø�nÑ%Ð%r   )r   rW   r   rW   rX   rW   )
r   rW   r   rW   r   rW   r   rW   rX   rZ   )
r'   rW   r   rW   r   rW   r)   rW   rX   rZ   )
r   rW   r   rW   re   r,   r)   rW   rX   rW   )r_   Ú
__future__r   r   r#   Úloggingr>   r9   Úpathlibr   r   Ú	getLoggerr\   r@   r!   ÚDEFAULT_SCOPESr`   r   r%   r*   r,   rh   rb   r   r   ú<module>rn      s  ðñõ #ã Û Û Û 	Û Ý ã à	ˆ×	Ñ	˜8Ó	$€à@€ð8ð ð CÐ ó@ðØ
ðàðð ðð ð	ð
 
óð> !ð	Øðàðð ðð ð	ð
 
ó÷>1:ñ 1:ðp !ð	&Øð&àð&ð  ð&ð ð	&ð
 	ô&r   