ó
    ² èiÄ0  ã                   ó¦  • S r SSKrSSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJ	r	  SS	K
Jr  SS
K
Jr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJ r   SSK!J"r"  SSK#J$r$  Sr% " S S\	5      r& " S S\5      r' " S S\5      r(S \)S!\*\)\4   4S" jr+ " S# S$\5      r, " S% S&\5      r-g)'z£Defines an auth handler to inject an Authorization header into each request.

Tokens are assumed to be installed onto a user's system via a separate CLI command.

é    N)Úfnmatch)Ú	lru_cache)ÚAny)Ú
NamedTuple)ÚOptional)ÚProtocol)ÚParseResult)Úurlparse)Ú
CondaError)ÚContext)ÚChannelAuthBase)Ú	BaseModel)ÚField)ÚValidationError)ÚPreparedRequest)ÚResponse)Úrepo_config)ÚTOKEN_DOMAIN_MAP)ÚCredentialType)ÚAnacondaAuthConfig)ÚTokenNotFoundError)Ú	TokenInfoz/repo/c                   ó*   • \ rS rSrS\S\S\4S jrSrg)ÚResponseHooké$   ÚresponseÚ_Úreturnc                 ó   • g ©N© )Úselfr   r   s      Ú6Lib\site-packages\anaconda_auth\_conda\auth_handler.pyÚ__call__ÚResponseHook.__call__&   s   € À#ó    r!   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__r   r   r$   Ú__static_attributes__r!   r&   r#   r   r   $   s   † àE ÐE°ÐE¸×Er&   r   c                   ó4   • \ rS rSr% Sr\\   \S'   \\S'   Sr	g)ÚAccessCredentialé)   zNRepresents a typed string containing an access credential (of CredentialType).ÚvalueÚtyper!   N)
r'   r(   r)   r*   Ú__doc__r   ÚstrÚ__annotations__r   r+   r!   r&   r#   r-   r-   )   s   ‡ ÙXð �C‰=ÓØ
Ör&   r-   c                   ó   • \ rS rSrSrSrg)ÚAnacondaAuthErroré1   zr
A generic error to raise that is a subclass of CondaError so we don't trigger the unhandled exception traceback.
r!   N)r'   r(   r)   r*   r1   r+   r!   r&   r#   r5   r5   1   s   † ôr&   r5   Úchannel_namer   c                 óì  • U nUR                  S5      (       d  US-  n[        U5      nUR                  (       a  UR                  (       d  0 $ 0 n[	        5       nUR
                   H‹  nUR                  SS5      nX`:X  a  UnM  [        U5      nUR                  UR                  :w  a  ME  UR                  UR                  -   nUR                  UR                  -   n	[        X‰5      (       d  M‰  UnM�     U$ )z=Find the correct channel settings from conda's configuration.Ú/ÚchannelÚ )	Úendswithr
   ÚschemeÚnetlocr   Úchannel_settingsÚgetÚpathr   )
r7   ÚurlÚ
parsed_urlr?   ÚcontextÚsettingsr:   Úparsed_settingÚurl_without_schemaÚpatterns
             r#   Ú_load_channel_settingsrI   7   sæ   € ð €CØ�<‰<˜×ÑØˆs‰
ˆä˜#“€JØ×× J×$5×$5Øˆ	ð ÐÜ‹i€GØ×,Ô,ˆØ—,‘,˜y¨"Ó-ˆØÓ"à'ÐÙä! 'Ó*ˆð × Ñ  J×$5Ñ$5Ó5Ùà'×.Ñ.°·±Ñ@ÐØ ×'Ñ'¨.×*=Ñ*=Ñ=ˆÜÐ%×/Ó/Ø'Òñ# -ð& Ðr&   c                   ón   • \ rS rSr% \" SSS9r\\   \S'   \" SSS9r	\\
   \S'   \S\S	S 4S
 j5       rSrg)Ú AnacondaAuthHandlerExtraSettingséd   NÚauth_domain)ÚdefaultÚaliasÚoverride_auth_domainÚcredential_typeÚoverride_credential_typer7   r   c                 ój   • [        U5      n U " S0 UD6$ ! [         a  n[        SU 35      eSnAff = f)z3Load extra settings for a channel, with validation.zIError when loading anaconda-auth extra configuration from your condarc.

Nr!   )rI   r   r5   )Úclsr7   rE   Úes       r#   Úfrom_channel_nameÚ2AnacondaAuthHandlerExtraSettings.from_channel_namej   sH   € ô *¨,Ó7ˆð	Ù‘?˜‘?Ð"øÜó 	Ü#Ø_Ð`aÐ_bÐeóð ûð	ús   � •
2Ÿ-­2r!   )r'   r(   r)   r*   r   rP   r   r2   r3   rR   r   ÚclassmethodrV   r+   r!   r&   r#   rK   rK   d   sX   ‡ Ù*/¸ÀMÑ*RÐ˜( 3™-ÓRÙ9>ØÐ-ñ:Ð˜h ~Ñ6ó ð ð¨Sð Ð5Wó ó ór&   rK   c            	       ó  ^ • \ rS rSrS\S\S\4U 4S jjrS\S\\\	4   4S jr
S	\S
\	S\S\\   4S jr\S\S\\   4S j5       r\S\S\4S j5       r\S\S\\\   \	4   4S j5       rS
\	S\4S jrS\S\4S jrSrU =r$ )ÚAnacondaAuthHandlerév   r7   ÚargsÚkwargsc                 ób   >• [         TU ]  " U/UQ70 UD6  [        R                  U5      U l        g r    )ÚsuperÚ__init__rK   rV   Ú_extras)r"   r7   r\   r]   Ú	__class__s       €r#   r`   ÚAnacondaAuthHandler.__init__w   s,   ø€ Ü‰Ò˜Ð7¨Ò7°Ò7Ü7×IÑIÈ,ÓWˆ�r&   rC   r   c                 ó¤  • UR                   R                  5       nUn[        R                  nU[        ;   a  [        U   u  p4n[        US9nUR                  (       a  [        R                  nU R                  R                  (       a  U R                  R                  nU R                  R                  (       a  U R                  R                  nX44$ )zéSelect the appropriate domain for token lookup based on a parsed URL.

We also determine whether to use API key or legacy repo token. This method
handles a default set of rules, as well as user overrides via conda
channel_settings.

)Údomain)
r>   Úlowerr   ÚAPI_KEYr   r   Úuse_unified_repo_api_keyra   rP   rR   )r"   rC   Úchannel_domainÚtoken_domainrQ   r   Úconfigs          r#   Ú_load_token_domainÚ&AnacondaAuthHandler._load_token_domain{   s¥   € ð $×*Ñ*×0Ñ0Ó2ˆð &ˆÜ(×0Ñ0ˆð Ô-Ó-Ü/?ÀÑ/OÑ,ˆL¨1ô $¨<Ñ8ˆØ×*×*Ü,×4Ñ4ˆOà�<‰<×,×,ØŸ<™<×<Ñ<ˆLà�<‰<×0×0Ø"Ÿl™l×CÑCˆOàÐ,Ð,r&   rj   rQ   c                 ót  •  [         R                  " U5      nUR                  (       a8  U[        R
                  :X  a$  [        UR                  [        R
                  5      $ UR                  nUR                  [        5      (       a  U[        [        5      S nUR                  S5      u  n  n [        UR                  U5      [        R                  5      $ ! [         a     gf = f! [         a     Of = f [        UR                  S   R                  [        R                  5      $ ! [          a     gf = f)aâ  Attempt to load an appropriate token from the keyring.

We parse the requested URL, extract what may be an organization ID, and first
attempt to load the token for that specific organization. If that fails, we
then simply return the first token in the keyring (since this is in all likelihood
one of the default channels ('main', 'r', etc.).

If no token can be found in the keyring, we return None, which means that
the token will attempt to be read from via conda-token instead.

Nr9   r   )r   Úloadr   Úapi_keyr   rg   r-   rA   Ú
startswithÚ
URI_PREFIXÚlenÚ	partitionÚget_repo_tokenÚ
REPO_TOKENÚrepo_tokensÚtokenÚ
IndexError)r"   rj   rQ   rC   Ú
token_inforA   Ú	maybe_orgr   s           r#   Ú_load_token_from_keyringÚ,AnacondaAuthHandler._load_token_from_keyringš   s  € ð"	Ü"Ÿš¨Ó5ˆJð ×× /´^×5KÑ5KÓ"KÜ# J×$6Ñ$6¼×8NÑ8NÓOÐOð �‰ˆØ�?‰?œ:×&Ñ&ØœœJ›Ð)Ð*ˆDØŸ.™.¨Ó-‰ˆ	�1�að	Ü#Ø×)Ñ)¨)Ó4´n×6OÑ6Oóð øô# "ó 	áð	ûô( "ó 	Ùð	úð	Ü#Ø×&Ñ& qÑ)×/Ñ/´×1JÑ1Jóð øô ó 	Øàð	ús5   ‚C Â/(C( Ã
C%Ã$C%Ã(
C5Ã4C5Ã90D* Ä*
D7Ä6D7c                 ó6  • U R                   R                  5       n[        bx  [        R                  " 5       nUR	                  5        HO  u  p4[        U5      R                   nUR                  5       U:X  d  M0  Uc  M5  [        U[        R                  5      s  $    g r    )	r>   rf   r   Ú
token_listÚitemsr
   r-   r   rv   )rC   re   ÚtokensÚ	token_urlrx   Útoken_netlocs         r#   Ú_load_token_via_conda_tokenÚ/AnacondaAuthHandler._load_token_via_conda_tokenÎ   s}   € ð ×"Ñ"×(Ñ(Ó*ˆäÑ"Ü ×+Ò+Ó-ˆFØ$*§L¡L¦NÑ �	Ü'¨	Ó2×9Ñ9�Ø×%Ñ%Ó'¨6Õ1°eÓ6GÜ+¨E´>×3LÑ3LÓMÒMñ %3ð r&   rB   c                 óÀ   • [        U5      nU R                  U5      u  p4U R                  X4U5      =n(       a  U$ U R                  U5      =n(       a  U$ [	        SU5      $ )a)  Load the appropriate token based on URL matching.

First, attempts to load from the keyring. If that fails, we attempt
to load the legacy repo token via conda-token.

Cached for performance.

Args:
    url: The URL for the request.

Returns:
     The token, if it can be loaded. None, otherwise.

N)r
   rl   r|   r„   r-   )r"   rB   rC   rj   rQ   rx   s         r#   Ú_load_tokenÚAnacondaAuthHandler._load_tokenÜ   sp   € ô  ˜c“]ˆ
Ø(,×(?Ñ(?À
Ó(KÑ%ˆð ×1Ñ1Ø¨:ó
ð 
ˆ5õ 
ð ˆLØ×6Ñ6°zÓBÐBˆUÕBØˆLÜ  oÓ6Ð6r&   c                 ó¤  • [         R                  " S5      =n(       a  SU 3[        R                  4$  U R	                  U5      nUR
                  c  SUR                  4$ UR                  [        R                  :X  a  SUR
                   3UR                  4$ SUR
                   3UR                  4$ ! [         a    SWR                  4s $ f = f)z¸Build the Authorization header based on the request URL.

The result can vary in terms of "token" vs. "Bearer" as well as whether the
credential is a legacy repo token or an API key.

ÚANACONDA_AUTH_API_KEYzBearer Nztoken )	ÚosÚgetenvr   rg   r‡   r/   r0   rv   Ú	Exception)r"   rB   rp   rx   s       r#   Ú_build_headerÚ!AnacondaAuthHandler._build_headerø   sÃ   € ô —i’iÐ 7Ó8Ð8ˆ7Õ8Ø˜W˜IÐ&¬×(>Ñ(>Ð>Ð>ð	$Ø×$Ñ$ SÓ)ˆEØ�{‰{Ñ"Ø˜UŸZ™ZÐ'Ð'à�z‰zœ^×6Ñ6Ó6Ø §¡˜}Ð-¨u¯z©zÐ9Ð9à˜UŸ[™[˜MÐ*¨E¯J©JÐ6Ð6øÜó 	$à˜Ÿ™Ð#Ò#ð	$ús   ´+B4 Á 8B4 ÂB4 Â4CÃCc                 óp   ^ ^• U[         R                  :X  a  SOSmS[        S[        S[        4UU 4S jjnU$ )Nzanaconda token installzanaconda loginr   r   r   c                 óò   >• U R                   S;   ae  U R                  R                  R                  S5      b!  SU R                    STR                   ST S3nOSTR                   ST S3n[        U5      eU $ )	zBRaise a nice error message if the authentication token is missing.>   é‘  é“  ÚAuthorizationzReceived authentication error (z) when accessing z?. If your token is invalid or expired, please re-install with `z`.zToken not found for z. Please install token with `)Ústatus_codeÚrequestÚheadersr@   r7   r5   )r   r   ÚmessageÚinstructionr"   s      €€r#   ÚhandlerÚ<AnacondaAuthHandler._build_response_handler.<locals>.handler   s    ø€ à×#Ñ# zÓ1Ø×#Ñ#×+Ñ+×/Ñ/°Ó@ÑLà9¸(×:NÑ:NÐ9OÐO`Ðae×arÑarÐ`sð tXØXcÐWdÐdfðhñ ð /¨t×/@Ñ/@Ð.Að B6Ø6A°]À"ðFð ô (¨Ó0Ð0ØˆOr&   )r   rv   r   r   )r"   rQ   rš   r™   s   `  @r#   Ú_build_response_handlerÚ+AnacondaAuthHandler._build_response_handler  sF   ù€ ð ¤.×";Ñ";Ó;ñ %à!ð 	ð	œhð 	¬Sð 	´X÷ 	ð 	ð  ˆr&   r–   c                 óÊ   • UR                   c  U$ U R                  UR                   5      u  p#UR                  SU R                  U5      5        U(       a  X!R                  S'   U$ )z<Inject the token as an Authorization header on each request.r   r”   )rB   rŽ   Úregister_hookrœ   r—   )r"   r–   ÚheaderrQ   s       r#   r$   ÚAnacondaAuthHandler.__call__2  sc   € ð �;‰;ÑØˆNð #'×"4Ñ"4°W·[±[Ó"AÑˆð 	×ÑØØ×(Ñ(¨Ó9ô	
ö
 Ø/5�O‰O˜OÑ,àˆr&   )ra   )r'   r(   r)   r*   r2   r   r`   r	   Útupler   rl   r   r-   r|   Ústaticmethodr„   r   r‡   rŽ   r   rœ   r   r$   r+   Ú__classcell__)rb   s   @r#   rZ   rZ   v   s  ø† ðX Sð X°ð XÀ÷ Xð-¨[ð -¸UÀ3ÈÐCVÑ=Wô -ð>2àð2ð (ð2ð  ð	2ð
 
Ð"Ñ	#ô2ðh ðØðà	Ð"Ñ	#óó ðð ð7˜sð 7Ð'7ó 7ó ð7ð6 ð$ ð $¨¨x¸©}¸nÐ/LÑ)Mó $ó ð$ð:à'ðð 
ôð8 ð °O÷ ò r&   rZ   ).r1   r‹   r   Ú	functoolsr   Útypingr   r   r   r   Úurllib.parser	   r
   Úcondar   Úconda.base.contextr   Úconda.plugins.typesr   Úpydanticr   r   r   Úrequestsr   r   Úanaconda_auth._condar   Úanaconda_auth._conda.configr   r   Úanaconda_auth.configr   Úanaconda_auth.exceptionsr   Úanaconda_auth.tokenr   rr   r   r-   r5   r2   ÚdictrI   rK   rZ   r!   r&   r#   Ú<module>r³      s²   ðñó 
Ý Ý Ý Ý Ý Ý Ý $Ý !å Ý &Ý /Ý Ý Ý $Ý $Ý å ,Ý 8Ý 6Ý 3Ý 7Ý )à€
ôF�8ô Fô
�zô ô˜
ô ð*¨ð *°°c¸3°h±ô *ôZ yô ô$P˜/õ Pr&   