o
    RhrI                     @   s  d dl Z d dl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
mZmZmZmZmZmZ ddlmZ ddlmZ ddlmZmZ eeZerQd dlZe	G dd	 d	Ze	G d
d dZe	G dd dZed&dddefddZ dddee fddZ!dddeddfddZ"d&dddeddfddZ#dddefddZ$d&dddedefd d!Z%defd"d#Z&d&dedeeeef fd$d%Z'dS )'    N)	dataclass)TYPE_CHECKINGDictListOptionalTupleUnion   )	constants)whoami)experimental	get_tokenc                   @   sz   e Zd ZU dZeed< eed< eed< eed< eed< dZee ed< dZ	ee ed	< dZ
ee ed
< dZee ed< dS )OAuthOrgInfoab  
    Information about an organization linked to a user logged in with OAuth.

    Attributes:
        sub (`str`):
            Unique identifier for the org. OpenID Connect field.
        name (`str`):
            The org's full name. OpenID Connect field.
        preferred_username (`str`):
            The org's username. OpenID Connect field.
        picture (`str`):
            The org's profile picture URL. OpenID Connect field.
        is_enterprise (`bool`):
            Whether the org is an enterprise org. Hugging Face field.
        can_pay (`Optional[bool]`, *optional*):
            Whether the org has a payment method set up. Hugging Face field.
        role_in_org (`Optional[str]`, *optional*):
            The user's role in the org. Hugging Face field.
        pending_sso (`Optional[bool]`, *optional*):
            Indicates if the user granted the OAuth app access to the org but didn't complete SSO. Hugging Face field.
        missing_mfa (`Optional[bool]`, *optional*):
            Indicates if the user granted the OAuth app access to the org but didn't complete MFA. Hugging Face field.
    subnamepreferred_usernamepictureis_enterpriseNcan_payrole_in_orgpending_ssomissing_mfa)__name__
__module____qualname____doc__str__annotations__boolr   r   r   r   r    r   r   X/home/air/sanwanet/backup_V2/venv/lib/python3.10/site-packages/huggingface_hub/_oauth.pyr      s   
 r   c                   @   s   e Zd ZU dZeed< eed< eed< ee ed< ee ed< eed< eed< ee ed	< eed
< ee ed< eee	  ed< dS )OAuthUserInfoa  
    Information about a user logged in with OAuth.

    Attributes:
        sub (`str`):
            Unique identifier for the user, even in case of rename. OpenID Connect field.
        name (`str`):
            The user's full name. OpenID Connect field.
        preferred_username (`str`):
            The user's username. OpenID Connect field.
        email_verified (`Optional[bool]`, *optional*):
            Indicates if the user's email is verified. OpenID Connect field.
        email (`Optional[str]`, *optional*):
            The user's email address. OpenID Connect field.
        picture (`str`):
            The user's profile picture URL. OpenID Connect field.
        profile (`str`):
            The user's profile URL. OpenID Connect field.
        website (`Optional[str]`, *optional*):
            The user's website URL. OpenID Connect field.
        is_pro (`bool`):
            Whether the user is a pro user. Hugging Face field.
        can_pay (`Optional[bool]`, *optional*):
            Whether the user has a payment method set up. Hugging Face field.
        orgs (`Optional[List[OrgInfo]]`, *optional*):
            List of organizations the user is part of. Hugging Face field.
    r   r   r   email_verifiedemailr   profilewebsiteis_pror   orgsN)
r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   ;   s   
 r!   c                   @   s@   e Zd ZU dZeed< ejed< eed< ee ed< eed< dS )	OAuthInfoa  
    Information about the OAuth login.

    Attributes:
        access_token (`str`):
            The access token.
        access_token_expires_at (`datetime.datetime`):
            The expiration date of the access token.
        user_info ([`OAuthUserInfo`]):
            The user information.
        state (`str`, *optional*):
            State passed to the OAuth provider in the original request to the OAuth provider.
        scope (`str`):
            Granted scope.
    access_tokenaccess_token_expires_at	user_infostatescopeN)	r   r   r   r   r   r   datetimer!   r   r   r   r   r    r(   f   s   
 
r(   /appzfastapi.FastAPIroute_prefixc              
   C   s   zddl m} W n ty } ztd|d}~ww tjpdd }| j|t| 	 ddd	 |
d
}tddurJtd t| |d dS td t| |d dS )a  
    Add OAuth endpoints to a FastAPI app to enable OAuth login with Hugging Face.

    How to use:
    - Call this method on your FastAPI app to add the OAuth endpoints.
    - Inside your route handlers, call `parse_huggingface_oauth(request)` to retrieve the OAuth info.
    - If user is logged in, an [`OAuthInfo`] object is returned with the user's info. If not, `None` is returned.
    - In your app, make sure to add links to `/oauth/huggingface/login` and `/oauth/huggingface/logout` for the user to log in and out.

    Example:
    ```py
    from huggingface_hub import attach_huggingface_oauth, parse_huggingface_oauth

    # Create a FastAPI app
    app = FastAPI()

    # Add OAuth endpoints to the FastAPI app
    attach_huggingface_oauth(app)

    # Add a route that greets the user if they are logged in
    @app.get("/")
    def greet_json(request: Request):
        # Retrieve the OAuth info from the request
        oauth_info = parse_huggingface_oauth(request)  # e.g. OAuthInfo dataclass
        if oauth_info is None:
            return {"msg": "Not logged in!"}
        return {"msg": f"Hello, {oauth_info.user_info.preferred_username}!"}
    ```
    r   )SessionMiddlewarezCannot initialize OAuth to due a missing library. Please run `pip install huggingface_hub[oauth]` or add `huggingface_hub[oauth]` to your requirements.txt file in order to install the required dependencies.N z-v1noneT)
secret_key	same_site
https_onlyr/   SPACE_IDz3OAuth is enabled in the Space. Adding OAuth routes.r1   z:App is not running in a Space. Adding mocked OAuth routes.)starlette.middleware.sessionsr2   ImportErrorr
   OAUTH_CLIENT_SECRETadd_middlewarehashlibsha256encode	hexdigeststriposgetenvloggerinfo_add_oauth_routes_add_mocked_oauth_routes)r0   r1   r2   esession_secretr   r   r    attach_huggingface_oauth   s.   %


rK   requestzfastapi.Requestreturnc                 C   s   d| j vrtd dS td | j d }|di }|dg }|r+dd |D nd}t|d	|d
|d|d|d|d|d|d|d|d|d}t|dtj|d||d|ddS )a  
    Returns the information from a logged in user as a [`OAuthInfo`] object.

    For flexibility and future-proofing, this method is very lax in its parsing and does not raise errors.
    Missing fields are set to `None` without a warning.

    Return `None`, if the user is not logged in (no info in session cookie).

    See [`attach_huggingface_oauth`] for an example on how to use this method.
    
oauth_infozNo OAuth info in session.Nz Parsing OAuth info from session.userinfor'   c                 S   s\   g | ]*}t |d |d|d|d|d|d|d|d|dd		qS )
r   r   r   r   isEnterprisecanPay	roleInOrg
pendingSSO
missingMFA)	r   r   r   r   r   r   r   r   r   )r   get).0orgr   r   r    
<listcomp>   s    z+parse_huggingface_oauth.<locals>.<listcomp>r   r   r   r"   r#   r   r$   r%   isProrQ   )r   r   r   r"   r#   r   r$   r%   r&   r   r'   r)   
expires_atr,   r-   )r)   r*   r+   r,   r-   )sessionrE   debugrU   r!   r(   r.   fromtimestamp)rL   
oauth_data	user_data	orgs_datar'   r+   r   r   r    parse_huggingface_oauth   sB   



ra   c              
      s`  zddl }ddlm  ddlm} ddlm W n ty) } ztd|d}~ww d}tj	du r8t
|dtjdu rDt
|d	tjdu rPt
|d
tjdu r\t
|d| jdtj	tjdtjitjd d t|\}}| d|jdffdd}| |d|jdf fdd}	| |d|jdffdd}
dS )zIAdd OAuth routes to the FastAPI app (login, callback handler and logout).r   N)MismatchingStateError)OAuthRedirectResponseCannot initialize OAuth to due a missing library. Please run `pip install huggingface_hub[oauth]` or add `huggingface_hub[oauth]` to your requirements.txt file.zOAuth is required but '{}' environment variable is not set. Make sure you've enabled OAuth in your Space by setting `hf_oauth: true` in the Space metadata.OAUTH_CLIENT_IDr<   OAUTH_SCOPESOPENID_PROVIDER_URLhuggingfacer-   z!/.well-known/openid-configuration)r   	client_idclient_secretclient_kwargsserver_metadata_urlrL   rM   c                    s   t | } j| |I dH S )z)Endpoint that redirects to HF OAuth page.N)_generate_redirect_urirj   authorize_redirectrL   redirect_uri)oauthr   r    oauth_login(  s   z&_add_oauth_routes.<locals>.oauth_loginc                    s   zj | I dH }W nV  yb   t| jdd}| jd}d|d i}|r.||d<  dtj| }|tj	kr\t
jd}|du rMtddd	|d
 }||  Y S | Y S w td || jd< t| S ))Endpoint that handles the OAuth callback.N_nb_redirectsr   _target_urlr	   ?
SPACE_HOSTzoApp is not running in a Space (SPACE_HOST environment variable is not set). Cannot redirect to non-iframe view.https://r/   z@Successfully logged in with OAuth. Storing user info in session.rN   )rj   authorize_access_tokenintquery_paramsrU   urllibparse	urlencoder
   OAUTH_MAX_REDIRECTSrC   environRuntimeErrorrstriprE   r\   r[   _get_redirect_target)rL   rN   nb_redirects
target_urlr}   rr   hosthost_urlrb   re   	login_urirs   r   r    oauth_redirect_callback.  s2   


z2_add_oauth_routes.<locals>.oauth_redirect_callbackc                    s&   t d | jdd  t| S )zGEndpoint that logs out the user (e.g. delete info from cookie session).z7Logged out with OAuth. Removing user info from session.rN   N)rE   r\   r[   popr   rL   rd   r   r    oauth_logoutS  s   
z'_add_oauth_routes.<locals>.oauth_logout)fastapi'authlib.integrations.base_client.errorsrb   %authlib.integrations.starlette_clientrc   fastapi.responsesre   r;   r
   rg   
ValueErrorformatr<   rh   ri   register_get_oauth_urisrU   Request)r0   r1   r   rc   rI   msgcallback_uri
logout_urirt   r   r   r   r   r    rG      sL   



 $rG   c           	   
      s   zddl }ddlm  ddlm W n ty# } ztd|d}~ww td t t	|\}}| 
|d|jd f fd	d
}| 
d|jd f fdd}| 
|d|jd f fdd}dS )zAdd fake oauth routes if app is run locally and OAuth is enabled.

    Using OAuth will have the same behavior as in a Space but instead of authenticating with HF, a mocked user profile
    is added to the session.
    r   Nrd   )URLrf   zOAuth is not supported outside of a Space environment. To help you debug your app locally, the oauth endpoints are mocked to return your profile and token. To make it work, your machine must be logged in to Huggingface.rL   rM   c                    s&   t | } d tjd|i S )z.Fake endpoint that redirects to HF OAuth page.rx   rw   )ro   r~   r   r   rq   )re   r   r   r    rt   t  s   z-_add_mocked_oauth_routes.<locals>.oauth_loginc                    s   | j d<  t| S )ru   rN   )r[   r   r   )re   mocked_oauth_infor   r    r   {  s   
z9_add_mocked_oauth_routes.<locals>.oauth_redirect_callbackc                    s2   | j dd djdi | j} |ddS )z=Endpoint that logs out the user (e.g. delete cookie session).rN   Nr/   i.  )urlstatus_coder   )r[   r   include_query_paramsr}   )rL   
logout_url)re   r   r   r    r     s   z._add_mocked_oauth_routes.<locals>.oauth_logout)r   r   re   starlette.datastructuresr   r;   warningswarn_get_mocked_oauth_infor   rU   r   )	r0   r1   r   rI   r   r   rt   r   r   r   )re   r   r   r   r    rH   [  s.    rH   c                 C   s^   d| j v r| j d }n	dtj| j  }| dj|d}t|}|jdr-|	dd}|S )Nrw   z/?r   )rw   z	.hf.spacezhttp://rz   )
r}   r~   r   r   url_forr   r   netlocendswithreplace)rL   targetrr   redirect_uri_as_strr   r   r    ro     s   
ro   default_targetc                 C   s   | j d|S )Nrw   )r}   rU   )rL   r   r   r   r    r     s   r   c                  C   s   t  } | d u rtdt }|d dkrtd| ddddd	tt d d
|d |d d|d  |d dddddddddS )Na  Your machine must be logged in to HF to debug an OAuth app locally. Please run `huggingface-cli login` or set `HF_TOKEN` as environment variable with one of your access token. You can generate a new token in your settings page (https://huggingface.co/settings/tokens).typeuserzYour machine is not logged in with a personal account. Please use a personal access token. You can generate a new token in your settings page (https://huggingface.co/settings/tokens).bearerip  FOOBARzopenid profilehf_oauth__refresh_token
0123456789fullnamer   zhttps://huggingface.co/	avatarUrlr3   z$00000000-0000-0000-0000-000000000000idaaaaaaaaaaaaaaaaaaaidzhttps://huggingface.co)r   r   r   r$   r   r%   aud	auth_timenonceiatexpiss)r)   
token_type
expires_inid_tokenr-   refresh_tokenrZ   rO   )r   r   r   r|   time)tokenr   r   r   r    r     s>   r   c                 C   s4   |  d} | rd|  } |  d|  d|  dfS )Nr/   z/oauth/huggingface/loginz/oauth/huggingface/callbackz/oauth/huggingface/logout)rB   r9   r   r   r    r     s   

r   )r/   )(r.   r>   loggingrC   r   urllib.parser~   r   dataclassesr   typingr   r   r   r   r   r   r3   r
   hf_apir   utilsr   r   	getLoggerr   rE   r   r   r!   r(   r   rK   ra   rG   rH   ro   r   r   r   r   r   r   r    <module>   s<     
$*B>[."+