U
    >id                     @   sf   d dl Z d dlZd dlmZ d dlmZmZ d dlmZ d dl	m
Z
 d dlmZmZ G dd dZdS )	    N)sha1)ListOptional)app_settings)Authenticator)decryptencryptc                   @   s   e Zd ZeddddZed dddZeeddd	Ze	e
e  dd
dZe
e dddZeedddZeddddZe
e dddZee	e dddZeedddZdS )RecoveryCodesN)instancereturnc                 C   s
   || _ d S N)r
   )selfr
    r   L/tmp/pip-unpacked-wheel-upujnpc2/allauth/mfa/recovery_codes/internal/auth.py__init__   s    zRecoveryCodes.__init__)r   c                 C   sT   t jj|t jjd }|r$| |S t |t jjt|  ddd}|  | |S )N)usertyper   )seed	used_mask)r   r   data)	r   ZobjectsfilterTypeZRECOVERY_CODESfirstr   generate_seedsave)clsr   r
   r   r   r   activate   s     

zRecoveryCodes.activatec                 C   s   t d}|S )N(   )secretsZ	token_hex)r   keyr   r   r   r   !   s    
zRecoveryCodes.generate_seedc                 C   s(   | j jd}|d k	r$dd |D S d S )Nmigrated_codesc                 S   s   g | ]}t |qS r   )r   ).0coder   r   r   
<listcomp>)   s     z5RecoveryCodes._get_migrated_codes.<locals>.<listcomp>)r
   r   get)r   codesr   r   r   _get_migrated_codes&   s    z!RecoveryCodes._get_migrated_codesc           	      C   s   |   }|d k	r|S g }t| jjd }tj|dd td}tt	j
d |j}tt	jD ]`}||ddd tj| d | dd	d
}|dt	j
 ; }t|t	j
}|| qZ|S )Nr   ascii)r   msg	digestmod   3,zutf-8bigF)	byteordersigned
   )r&   r   r
   r   hmacnewencoder   minr   ZRECOVERY_CODE_DIGITSdigest_sizerangeZRECOVERY_CODE_COUNTupdateint
from_bytesdigeststrzfillappend)	r   r    retr   hZ
byte_countivalueZ	fmt_valuer   r   r   generate_codes,   s$      zRecoveryCodes.generate_codes)r@   r   c                 C   s   | j jd }t|d|> @ S Nr      )r
   r   boolr   r@   r   r   r   r   _is_code_used?   s    zRecoveryCodes._is_code_usedc                 C   s2   | j jd }|d|> O }|| j jd< | j   d S rC   )r
   r   r   rF   r   r   r   _mark_code_usedC   s    zRecoveryCodes._mark_code_usedc                 C   sH   |   }|d k	r|S g }t|  D ]\}}| |r8q$|| q$|S r   )r&   	enumeraterB   rG   r=   )r   r    r>   r@   r"   r   r   r   get_unused_codesI   s    
zRecoveryCodes.get_unused_codes)r"   r   c                 C   s|   |   }|d krd S z||}W n tk
r8   Y dS X | jjd }t|tsTt|| || jjd< | j	  dS d S )NFr    T)
r&   index
ValueErrorr
   r   
isinstancelistAssertionErrorpopr   )r   r"   r    idxr   r   r   _validate_migrated_codeU   s    

z%RecoveryCodes._validate_migrated_codec                 C   sT   |  |}|d k	r|S t|  D ],\}}| |r6q"||kr"| |  dS q"dS )NTF)rR   rI   rB   rG   rH   )r   r"   r>   r@   cr   r   r   validate_codee   s    


zRecoveryCodes.validate_code)__name__
__module____qualname__r   r   classmethodr   r;   r   r   r   r&   rB   r8   rE   rG   rH   rJ   rR   rT   r   r   r   r   r	      s   r	   )r1   r   hashlibr   typingr   r   Zallauth.mfar   Zallauth.mfa.modelsr   Zallauth.mfa.utilsr   r   r	   r   r   r   r   <module>   s   