o
    ;hF                     @  s   d dl mZ d dlZd dlZd dlmZmZ d dlmZm	Z	 d dl
mZmZmZmZ ddlmZ dd	lmZmZmZ G d
d deeeeZedde	dddG dd deZdS )    )annotationsN)ABCabstractmethod)versionaddedversionchanged)MongoClientMongoCollectionMongoDatabasecast   )get_dependency   )MovingWindowSupportSlidingWindowCounterSupportStoragec                      s  e Zd ZdZdgZ				dIdJ fddZedKddZedLddZedMddZ	edMddZ
edNd d!ZedOd#d$ZdPd%d&ZdQd(d)ZdRd+d,ZdSd.d/ZdTd1d2ZdUdVd6d7ZdWd8d9ZdXd<d=ZdUdYd>d?ZdZdAdBZ	3dUdYdCdDZd[dEdFZdPdGdHZ  ZS )\MongoDBStorageBasezV
    Rate limit storage with MongoDB as backend.

    Depends on :pypi:`pymongo`.
    pymongolimitscounterswindowsFuristrdatabase_namecounter_collection_namewindow_collection_namewrap_exceptionsbooloptionsint | str | boolreturnNonec                   s\   t  j|fd|i| || _||d| _| jd j| _td\| _}|| _	|| _
d| _dS )ai  
        :param uri: uri of the form ``mongodb://[user:password]@host:port?...``,
         This uri is passed directly to :class:`~pymongo.mongo_client.MongoClient`
        :param database_name: The database to use for storing the rate limit
         collections.
        :param counter_collection_name: The collection name to use for individual counters
         used in fixed window strategies
        :param window_collection_name: The collection name to use for sliding & moving window
         storage
        :param wrap_exceptions: Whether to wrap storage exceptions in
         :exc:`limits.errors.StorageError` before raising it.
        :param options: all remaining keyword arguments are passed to the
         constructor of :class:`~pymongo.mongo_client.MongoClient`
        :raise ConfigurationError: when the :pypi:`pymongo` library is not available
        r   )r   r   r   zpymongo.errorsN)super__init___database_name_collection_mappingdependenciesmodulelibr   
lib_errors_storage_uri_storage_options_storage)selfr   r   r   r   r   r   _	__class__ I/var/www/html/venv/lib/python3.10/site-packages/limits/storage/mongodb.pyr"      s   
zMongoDBStorageBase.__init__r   c                 C  s0   | j d u r| j| jfi | j| _ |   | j S N)r+   _init_mongo_clientr)   r*   (_MongoDBStorageBase__initialize_databaser,   r0   r0   r1   storageD   s   
zMongoDBStorageBase.storager	   c                 C  s   | j | j S r2   )r6   r#   r5   r0   r0   r1   	_databaseM   s   zMongoDBStorageBase._databaser   c                 C     | j | jd  S )Nr   r7   r$   r5   r0   r0   r1   r   Q      zMongoDBStorageBase.countersc                 C  r8   )Nr   r9   r5   r0   r0   r1   r   U   r:   zMongoDBStorageBase.windows
str | Nonec                 K  s   t  r2   )NotImplementedErrorr,   r   r   r0   r0   r1   r3   Y   s   z%MongoDBStorageBase._init_mongo_client-type[Exception] | tuple[type[Exception], ...]c                 C  s   | j jS r2   )r(   ZPyMongoErrorr5   r0   r0   r1   base_exceptions_   s   z"MongoDBStorageBase.base_exceptionsc                 C  s$   | j jddd | jjddd d S )NexpireAtr   )ZexpireAfterSeconds)r   Zcreate_indexr   r5   r0   r0   r1   Z__initialize_databasee   s   z(MongoDBStorageBase.__initialize_database
int | Nonec                 C  s4   | j i | ji  }| j   | j  t|S )z^
        Delete all rate limit keys in the rate limit collections (counters, windows)
        )r   Zcount_documentsr   Zdropint)r,   Znum_keysr0   r0   r1   reseti   s   

zMongoDBStorageBase.resetkeyc                 C  s$   | j d|i | jd|i dS )z>
        :param key: the key to clear rate limits for
        _idN)r   Zfind_one_and_deleter   )r,   rD   r0   r0   r1   clears   s   zMongoDBStorageBase.clearfloatc                 C  s6   | j d|i}|r|d ntj jtjjd S )z;
        :param key: the key to get the expiry for
        rE   r@   tzinfo)r   find_onedatetimenowreplacetimezoneutc	timestampr,   rD   Zcounterr0   r0   r1   
get_expiryz   s   zMongoDBStorageBase.get_expiryrB   c                 C  s8   | j j|dtjtjjiddgd}|r|d pdS )zB
        :param key: the key to get the counter value for
        $gte)rE   r@   count)
projectionr   )r   rJ   rK   rL   rN   rO   rQ   r0   r0   r1   get   s   zMongoDBStorageBase.getr   expiryamountc              
   C  s   t j t jjt j|d }t| jjd|idddddgi|dd	|gid
iddddgi|dd
idigddg| jj	j
dd S )z
        increments the counter for a given rate limit key

        :param key: the key to increment
        :param expiry: amount in seconds for the key to expire in
        :param amount: the number to increment by
        secondsrE   $set$condz$lt	$expireAt$$NOW$addz$countifZthenelse)rT   r@   TrT   )upsertrU   return_document)rK   rL   rN   rO   	timedeltarB   r   find_one_and_updater'   ReturnDocumentAFTER)r,   rD   rW   rX   Z
expirationr0   r0   r1   incr   s:   


zMongoDBStorageBase.incrc                 C  s   z| j   W dS    Y dS )zm
        Check if storage is healthy by calling :meth:`pymongo.mongo_client.MongoClient.server_info`
        TF)r6   Zserver_infor5   r0   r0   r1   check   s
   
zMongoDBStorageBase.checklimittuple[float, int]c                 C  s|   t   }t| jdd|iiddddddd	|| gid
iiidddiddidig }r:|d d |d d fS |dfS )z
        returns the starting point and the number of entries in the moving
        window

        :param key: rate limit key
        :param expiry: expiry of entry
        :return: (start of window, number of acquired entries)
        z$matchrE   z$projectZfilteredEntriesz$filterz$entriesentryrS   z$$entry)inputasZcondz$minz$filteredEntriesz$size)minrT   r   rp   rT   )timelistr   Z	aggregate)r,   rD   rk   rW   rP   resultr0   r0   r1   get_moving_window   s0   	
z$MongoDBStorageBase.get_moving_windowc                 C  s   ||krdS t   }z7d|g| d|didtjtjjtj|d id}| jjd|d	||  d
d|| iii|dd W dS  | jj	j
yN   Y dS w )z
        :param key: rate limit key to acquire an entry in
        :param limit: amount of entries allowed
        :param expiry: expiry of the entry
        :param amount: the number of entries to acquire
        Fentriesr   )z$eachz	$positionz$slicer@   rY   )z$pushr[   rE   zentries.z$notrS   T)rc   )rq   rK   rL   rN   rO   re   r   Z
update_oner'   errorsZDuplicateKeyError)r,   rD   rk   rW   rX   rP   Zupdatesr0   r0   r1   acquire_entry   s8   
	z MongoDBStorageBase.acquire_entrytuple[int, float, int, float]c              
   C  s  |d }| j jd|iddddddgi|gid	d
dgid	ddgididddddgi|gidd	d
dgididddddgi|gidd|giddidig| jjjg dd }r|dri|d jtjj	d
 nt }td|t  }td|d r|| nd}|d ||d |fS dS )N  rE   r[   r\   $lte	$subtractr]   r^   $ifNull$currentCountr   $previousCountr`   r_   )previousCountcurrentCountr@   )r   r   r@   )rd   rU   r@   rH   r   r   )r           r   r   )r   rf   r'   rg   rh   rV   rM   rK   rN   rO   rP   rq   max)r,   rD   rW   	expiry_msrs   Z
expires_atZcurrent_ttlZprev_ttlr0   r0   r1   get_sliding_window  sj   





,
3z%MongoDBStorageBase.get_sliding_windowc                 C  sl  |d }| j jd|iddddddd	gi|gid
ddgid
ddgidiiidddddd	gi|gidd
ddgididdddd	gi|giddddgidd|gidd	d| gididdididdddddddddddd	|gigigi|gigidgiiiidddddd|gi|gidd|giddiiiddddd|gi|giiiddgig| jjjdd}tt|d S )Nry   rE   r[   r   r\   rz   r{   r]   r^   r|   r}   r   r~   r`   z$gtr_   r   )r   r@   ZcurWeightedCountz$floorz	$multiplyz$dividez$maxr   z$curWeightedCountZ	_acquiredz$unsetT)rd   rc   )r   rf   r'   rg   rh   r
   r   )r,   rD   rk   rW   rX   r   rs   r0   r0   r1   acquire_sliding_window_entry]  s   







#&

qvz/MongoDBStorageBase.acquire_sliding_window_entryc                 C  s
   |  |S r2   )rF   )r,   rD   rW   r0   r0   r1   clear_sliding_window  s   
z'MongoDBStorageBase.clear_sliding_windowc                 C  s   | j r
| j   d S d S r2   )r6   closer5   r0   r0   r1   __del__  s   zMongoDBStorageBase.__del__)r   r   r   F)r   r   r   r   r   r   r   r   r   r   r   r   r   r    )r   r   )r   r	   )r   r   r   r;   r   r   r   r   )r   r>   )r   r    )r   rA   )rD   r   r   r    )rD   r   r   rG   )rD   r   r   rB   )r   )rD   r   rW   rB   rX   rB   r   rB   )r   r   )rD   r   rk   rB   rW   rB   r   rl   )
rD   r   rk   rB   rW   rB   rX   rB   r   r   )rD   r   rW   rB   r   rx   )rD   r   rW   rB   r   r    )__name__
__module____qualname____doc__ZDEPENDENCIESr"   propertyr6   r7   r   r   r   r3   r?   r4   rC   rF   rR   rV   ri   rj   rt   rw   r   r   r   r   __classcell__r0   r0   r.   r1   r      sD    %






)
%
,F
|r   z2.1)versionz3.14.0zEAdded option to select custom collection names for windows & counters)r   reasonc                   @  s   e Zd ZddgZdd	d
ZdS )MongoDBStorageZmongodbzmongodb+srvr   r;   r   r   r   r   c                 K  s   t t| jj|fi |S r2   )r
   r   r'   r=   r0   r0   r1   r3     s   z!MongoDBStorage._init_mongo_clientNr   )r   r   r   ZSTORAGE_SCHEMEr3   r0   r0   r0   r1   r     s    r   )
__future__r   rK   rq   abcr   r   Zdeprecated.sphinxr   r   Zlimits.typingr   r   r	   r
   utilr   baser   r   r   r   r   r0   r0   r0   r1   <module>   s(    
   P