o
    id0                     @   s   d dl Z d dlZd dlZd dlmZmZ d dlmZ d dlmZm	Z	m
Z
mZ d dlmZmZ d dlmZ d dlmZ eeZG dd	 d	ZG d
d dZG dd dZG dd dZdd ZdS )    N)datetimetimezone)sleep)Any	AwaitableCallableUnion)RequestTokenErrTokenRenewalErr)IdentityProviderInterface)TokenResponsec                   @   s   e Zd ZdZdd Zedeeegdf e	f fddZ
e
jdeeegdf e	f ddfd	dZ
edeeegdf e	f fd
dZejdeeegdf e	f ddfddZdS )CredentialsListenerzz
    Listeners that will be notified on events related to credentials.
    Accepts callbacks and awaitable callbacks.
    c                 C   s   d | _ d | _d S N)_on_next	_on_errorself r   L/home/ubuntu/.local/lib/python3.10/site-packages/redis/auth/token_manager.py__init__      
zCredentialsListener.__init__returnNc                 C      | j S r   r   r   r   r   r   on_next      zCredentialsListener.on_nextcallbackc                 C   
   || _ d S r   r   r   r   r   r   r   r         
c                 C   r   r   r   r   r   r   r   on_error!   r   zCredentialsListener.on_errorc                 C   r   r   r    r   r   r   r   r!   %   r   )__name__
__module____qualname____doc__r   propertyr   r   r   r   r   setter	Exceptionr!   r   r   r   r   r      s    "&"*r   c                   @   s:   e Zd ZdedefddZdefddZdefdd	Zd
S )RetryPolicymax_attemptsdelay_in_msc                 C   s   || _ || _d S r   )r*   r+   )r   r*   r+   r   r   r   r   +   r   zRetryPolicy.__init__r   c                 C   r   )zW
        Retry attempts before exception will be thrown.

        :return: int
        )r*   r   r   r   r   get_max_attempts/      zRetryPolicy.get_max_attemptsc                 C   r   )zI
        Delay between retries in seconds.

        :return: int
        )r+   r   r   r   r   get_delay_in_ms7   r-   zRetryPolicy.get_delay_in_msN)r"   r#   r$   intfloatr   r,   r.   r   r   r   r   r)   *   s    r)   c                   @   s^   e Zd ZdedededefddZdefdd	Zdefd
dZdefddZ	defddZ
dS )TokenManagerConfigexpiration_refresh_ratiolower_refresh_bound_millis%token_request_execution_timeout_in_msretry_policyc                 C   s   || _ || _|| _|| _d S r   )_expiration_refresh_ratio_lower_refresh_bound_millis&_token_request_execution_timeout_in_ms_retry_policy)r   r2   r3   r4   r5   r   r   r   r   A   s
   
zTokenManagerConfig.__init__r   c                 C   r   )a&  
        Represents the ratio of a token's lifetime at which a refresh should be triggered. # noqa: E501
        For example, a value of 0.75 means the token should be refreshed
        when 75% of its lifetime has elapsed (or when 25% of its lifetime remains).

        :return: float
        )r6   r   r   r   r   get_expiration_refresh_ratioO   s   	z/TokenManagerConfig.get_expiration_refresh_ratioc                 C   r   )a  
        Represents the minimum time in milliseconds before token expiration
        to trigger a refresh, in milliseconds.
        This value sets a fixed lower bound for when a token refresh should occur,
        regardless of the token's total lifetime.
        If set to 0 there will be no lower bound and the refresh will be triggered
        based on the expirationRefreshRatio only.

        :return: int
        )r7   r   r   r   r   get_lower_refresh_bound_millisZ   s   z1TokenManagerConfig.get_lower_refresh_bound_millisc                 C   r   )z
        Represents the maximum time in milliseconds to wait
        for a token request to complete.

        :return: int
        )r8   r   r   r   r   )get_token_request_execution_timeout_in_msg   s   z<TokenManagerConfig.get_token_request_execution_timeout_in_msc                 C   r   )z_
        Represents the retry policy for token requests.

        :return: RetryPolicy
        )r9   r   r   r   r   get_retry_policyp   r-   z#TokenManagerConfig.get_retry_policyN)r"   r#   r$   r0   r/   r)   r   r:   r;   r<   r=   r   r   r   r   r1   @   s    
	r1   c                   @   s   e Zd ZdedefddZdd Z	d&ded	ed
e	g df fddZ
			d'dededed	ed
e	g df f
ddZdd Zd&d
efddZd&d
efddZdeded
efddZdefddZdedefdd Zd&d	efd!d"Z	d(d	ed#ejfd$d%ZdS ))TokenManageridentity_providerconfigc                 C   s(   || _ || _d | _d | _d | _d| _d S )Nr   )_idp_config_next_timer	_listener_init_timer_retries)r   r?   r@   r   r   r   r   z   s   
zTokenManager.__init__c                 C   s   t d |   d S )NzToken manager are disposed)loggerinfostopr   r   r   r   __del__   s   
zTokenManager.__del__Flistenerskip_initialr   Nc                    s   |_ zt W n' ty0   t t fdd}tj|dd}|  	  Y nw t   fdd}
|_td  	  jS )Nc                      s   t        d S r   )asyncioset_event_loopsetrun_foreverr   )loop
loop_readyr   r   
start_loop   s   
z&TokenManager.start.<locals>.start_loopT)targetdaemonc                      s$   z  W    d S    w r   )_renew_tokenrO   r   )	init_doner   rL   r   r   renew_with_callback   s   z/TokenManager.start.<locals>.renew_with_callbackToken manager started)rD   rM   get_running_loopRuntimeErrornew_event_loop	threadingEventThreadstartwaitcall_soon_threadsaferE   rG   rH   rI   )r   rK   rL   rS   threadrX   r   )rW   rQ   rR   r   rL   r   r`      s"   	
zTokenManager.startr   block_for_initialinitial_delay_in_msc                    s\   || _ t }t }t|| j||}||d || _t	d |r+|
 I d H  | jS )N  rY   )rD   rM   rZ   r^   _async_to_sync_wrapper_renew_token_async
call_laterrE   rG   rH   ra   rI   )r   rK   rd   re   rL   rQ   
init_eventwrappedr   r   r   start_async   s   

zTokenManager.start_asyncc                 C   s0   | j d ur
| j   | jd ur| j  d S d S r   )rE   cancelrC   r   r   r   r   rI      s
   


zTokenManager.stopc              
   C   s   z| j |}W n5 ty= } z)| j| j  k r7|  jd7  _t| j  d  | 	|W  Y d }~S |d }~ww d| _t
|S N   rf   r   )rA   request_tokenr	   rF   rB   r=   r,   r   r.   acquire_tokenr   r   force_refreshtokener   r   r   rq      s   zTokenManager.acquire_tokenc              
      s   z| j |}W n< tyE } z0| j| j  k r?|  jd7  _t| j 	 d I d H  | 
|I d H W  Y d }~S |d }~ww d| _t|S rn   )rA   rp   r	   rF   rB   r=   r,   rM   r   r.   acquire_token_asyncr   rr   r   r   r   rv      s   

z TokenManager.acquire_token_asyncexpire_date
issue_datec                 C   s4   |  |}| ||}t||}|dk rdS |d S )Nr   rf   )_delay_for_lower_refresh_delay_for_ratio_refreshmin)r   rw   rx   delay_for_lower_refreshdelay_for_ratio_refreshdelayr   r   r   _calculate_renewal_delay   s   

z%TokenManager._calculate_renewal_delayc                 C   s"   || j   ttj d  S Nrf   )rB   r;   r   nowr   utc	timestamp)r   rw   r   r   r   ry      s   z%TokenManager._delay_for_lower_refreshc                 C   s6   || }||| j    }|| ttj d  S r   )rB   r:   r   r   r   r   r   )r   rw   rx   	token_ttlrefresh_beforer   r   r   rz     s   z%TokenManager._delay_for_ratio_refreshc              
   C   s  zh| j dd}| |  |  }|  rtd| jjdu r-t	
d W dS |sJz
| j|  W n tyI } zt|d}~ww |dkrQW dS t }||| j| _t	d| d |W S  ty } z| jjdu rx|| j| W Y d}~dS d}~ww )	zq
        Task to renew token from identity provider.
        Schedules renewal tasks based on token TTL.
        Trs   Requested token is expiredN@No registered callback for token renewal task. Renewal cancelledr    Next token renewal scheduled in  seconds)rq   r   	get_tokenget_expires_at_msget_received_at_ms
is_expiredr
   rD   r   rG   warningr(   rM   rZ   ri   rV   rC   rH   r!   )r   rL   	token_resr~   ru   rQ   r   r   r   rV     s@   

zTokenManager._renew_tokenrj   c              
      sx  zz| j ddI dH }| |  |  }|  r$td| jjdu r;t	
d W W |r9|  dS dS |s[z| j| I dH  W n tyZ } zt|d}~ww |dkrkW W |ri|  dS dS t }t|| j}t	d| d ||| W n# ty } z| jjdu r|| j|I dH  W Y d}~nd}~ww W |r|  dS dS |r|  w w )	zx
        Async task to renew tokens from identity provider.
        Schedules renewal tasks based on token TTL.
        Tr   Nr   r   r   r   r   )rv   r   r   r   r   r   r
   rD   r   rG   r   rO   r(   rM   rZ   rg   rh   rH   ri   r!   )r   rL   rj   r   r~   ru   rQ   rk   r   r   r   rh   7  sZ   


zTokenManager._renew_token_async)F)Fr   F)FN)r"   r#   r$   r   r1   r   rJ   r   boolr   r`   r0   rl   rI   r   rq   rv   r   ry   rz   rV   rM   r^   rh   r   r   r   r   r>   y   sT    



3

*r>   c                    s    fdd}|S )a  
    Wraps an asynchronous function so it can be used with loop.call_later.

    :param loop: The event loop in which the coroutine will be executed.
    :param coro_func: The coroutine function to wrap.
    :param args: Positional arguments to pass to the coroutine function.
    :param kwargs: Keyword arguments to pass to the coroutine function.
    :return: A regular function suitable for loop.call_later.
    c                      s   t j i d d S )N)rQ   )rM   ensure_futurer   args	coro_funckwargsrQ   r   r   rk   q  s   z'_async_to_sync_wrapper.<locals>.wrappedr   )rQ   r   r   r   rk   r   r   r   rg   f  s   rg   )rM   loggingr]   r   r   timer   typingr   r   r   r   redis.auth.errr	   r
   redis.auth.idpr   redis.auth.tokenr   	getLoggerr"   rG   r   r)   r1   r>   rg   r   r   r   r   <module>   s     
9 n