U
    5i                     @   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Zd dlZd dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lT ddlmZ ddlmZ ddlmZ ddlm Z  G dd dej!Z!dS )    N)pbkdf2_hmac)translit)AES)SHA256)RSA)get_random_bytes)
PKCS1_v1_5)pad)*   )
send_email   )auth)LdapStatusCode)
Supervisorc                	       sB  e Zd ZdZdZejeej	
ejdddgejdZedd Zed	d
 Zdd Zedd ZdhddZedd ZdiddZdd ZdjddZeedddZdkedd d!Zedld"d#Z ed$d% Z!ed&d' Z"ed(d) Z#ed*d+ Z$d,d- Z%d.d/ Z&d0d1 Z'd2d3 Z(d4d5 Z)ed6d7 Z*ed8d9 Z+ed:d; Z,d<d= Z-d>d? Z.dmd@dAZ/dndBdCZ0edDdE Z1edFdG Z2dodIdJZ3dpe4e5e5e5edKdLdMZ6edNdO Z7edqdPdQZ8 fdRdSZ9dTdU Z:edVdW Z;ee<dXdYdZZ=ed[d\ Z>ed]d^ Z?ed_d` Z@edrdadbZAeeBddcddddedfdg ZC  ZDS )sCmfAuth    
   modulesr   Z	templates)loaderZ
autoescapec                 C   s   t | jdd S )N$base64	b64decode	pass_hashsplitself r   ./modules/auth/models/auth.pykey'   s    zCmfAuth.keyc                 C   s   t | jdd S )Nr   r   r   r   r   r    salt+   s    zCmfAuth.saltc                 C   s2   t | j}|ttt 7 }|| j 7 }|S N)secrets	token_hextoken_lengthstrinttimer#   hex)r   server_challenger   r   r    gen_server_challenge/   s    zCmfAuth.gen_server_challengec                 C   s   d| j d  }}||| }||d  }}||| }|t| }}t||| }td| |d}	t| j }
||
 | | }t	t
j}t
|	t
j|}|t| t
j}||  S )Nr   r   r   sha256順 )r'   lenbytesfromhexhashlibr   encoder%   r&   r   r   Z
block_sizenewZMODE_CBCZencryptr	   r+   )clsloginpasswordr,   startendZserver_randomZserver_timestampZserver_saltZtest_keyZclient_randomsecretZivZcipherZencrypted_secretr   r   r    test_gen_server_challenge_resp5   s$       
z&CmfAuth.test_gen_server_challenge_resprestore_passwordFc                 C   sv   | j dd t| jd}|dkr*| j|d< |rPtdd d| d	tj| S tdd d
| d	tj| S dS )u   
        Сформируем ссылку на сброс и отправим её пользователю.
        Альтернативно переиспользуется для приглашения нового пользователя.
        F)reset)hr=   r7   T)absolutezservicedesk/auth/?zauth/N)reset_pass_set_datadictreset_password_hashr7   auth_base_hrefurllibparse	urlencode)r   ZendpointZsdeskparamsr   r   r    reset_pass_linkP   s    
"zCmfAuth.reset_pass_linkc              	   C   s2  t jj|dddgd}|sRt " t jjddd |ddd	d
 W 5 Q R X td|jr|jt		 kr|jd t		 d krt " t jjddd |ddd	d
 W 5 Q R X t
ddtj }| }| jd}|j|td}t j }|j|jj||d t   t jjddd d|idd
 W 5 Q R X d S )Nreset_password_expiresr7   emailr7   fieldsZrestore_password_get_linkr   zLogin not foundr7   reasonfail)operatecmf_model_nameparent
audit_dataresult_statusu,   Такого пользователя нетQ i,  zAlready sentu   Вам на почту уже отправлена ссылка для сброса пароля. Для повторной отправки повторите попытку позже.uC   Ссылка для восстановления доступа к zreset_password_email.html)Zrestore_linkconfig)subjectok)modelsr   getcmfutildisable_aclCmfAuditaudit_eventZCmfAuthErrorrK   r*   ZCmfErrorrX   HOSTNAME_FQDNrJ   
_jinja_envZget_templateZrenderZCmfPluginMailBoxZget_local_mailboxZsend_messagerL   value)r6   r7   r   rY   linktemplatemessageZmail_boxr   r   r    send_pass_link_   sB    

 

 


 zCmfAuth.send_pass_linkTc                 C   s:   |rdnt d| _|rdntt d | _|   dS )u  
        Выставляем (или сбрасываем) секретик для сброса пароля
        Не очень хорошо, наверное хранить его в чистом виде, если упрут базу account будет печально,
        т.к. по сути даст доступ ко всем, кто в течение часа до угона БД запросил восстановление пароля.
        По хорошему хэшировать чем-то, что хранится отдельно от БД и периодически менять.
        Но это TODO-преTODO, т.к. паранойя.
        12 байт рандома дают нам 2**(8*12)=79,2E+27 значений. Перебирать по 1 в сек по сети - 2,5E+21 лет.
        :param reset - если True, выставляем всё в None, если False - генерируем новые значения
        N   rW   )r%   Ztoken_urlsaferD   r)   r*   rK   save)r   r>   r   r   r    rB      s    
zCmfAuth.reset_pass_set_datac                 C   s   | j  pt | j kS )u_    Проверяем что ссылка для сброса пароля не протухла )rK   r*   r   r   r   r    reset_pass_is_expired   s    zCmfAuth.reset_pass_is_expiredNc                 C   st   ddd}|d kr6| j jtt d|  | jjd}tt|	 
 }tt|	 
 }| d| S )NZRS256ZJWT)ZalgtyprW   )r7   expscope.)r7   rc   r)   r*   rm   r   	b64encodejsondumpsr4   decode)r   dayspayloadheaderr   r   r    
create_jwt   s    
zCmfAuth.create_jwt)jwtc                 C   sF   t t| d   }t t| d   }| d| S )Nru   rt   rn   )r   ro   rp   rq   r4   rr   )rw   ru   rt   r   r   r    
jwt_to_str   s    zCmfAuth.jwt_to_strc                 C   s^   |d kr|  |}ttj}t }||  ||}t	
| }| d| }|S )Nrn   )rv   r   r5   APPZrsa_private_keyr   updater4   signr   ro   rr   )r   rs   rw   Zsignerdigestr{   resr   r   r    rsa_sign_pack_jwt   s    

zCmfAuth.rsa_sign_pack_jwtc           	      C   s   |  d\}}}t }| d| }||  t|}ttj	}|
||}|s^d S t| }t| }t|}t|}|rtt t|d krtdt |d  d S ||dS )Nrn   rl   u9   Время жизни токена закончилосьru   rt   )r   r   r5   rz   r4   r   r   r   ry   rsa_public_keyverifyrr   rp   loadsr)   r*   gdebug)	rjwtZ	check_expru   rt   	signaturer|   rw   verifierZverifiedr   r   r    rsa_verify_unpack_jwt   s"    


zCmfAuth.rsa_verify_unpack_jwtc                 C   sJ   |  d\}}}t| }t| }t|}t|}||dS )Nrn   r   )r   r   r   rr   rp   r   )r   ru   rt   r   r   r   r    rsa_unpack_jwt   s    

zCmfAuth.rsa_unpack_jwtc              
   C   s   |  d\}}}t }| d| }||  t|}d}z$t|}t	|}	|	
||}W n@ tk
r }
 z"d|
 }t| t||
W 5 d }
~
X Y nX |S )Nrn   Fu,   Не удалось разобрать JWT: )r   r   r5   rz   r4   r   r   r   Z
import_keyr   r   
ValueErrorloggingerror)r   Zrsa_public_key_bytesru   rt   r   r|   rw   r}   r   r   er   r   r   r    rsa_verify_jwt   s    




zCmfAuth.rsa_verify_jwtc              
   C   s|  t d |st d d S z| |}W n2 tk
r\ } ztjd d }W 5 d }~X Y nX |spt d d S | dd}|d d |_|d d |_|d d	 |_	d |_
d |_d }tjtd
 rttd
 }|  }W 5 Q R X | |_|j	pddD ]T}|r|| dr"d|_|dkr t jjr t d|  d|_
d|_q t d|j d|j	 d|j  |S )Nzfrom_jwt: startzfrom_jwt: warn not jwtzfail unpack jwtz2from_jwt: warn not cls.rsa_verify_unpack_jwt(rjwt)T)emptyrt   r7   rm   z/custom/org_name  :r
   uC   from_jwt: Доступ по билету тех поддержки zfrom_jwt: jwt is ok, z, z, is_local=)r   r   r   	Exceptionry   logger	exceptionr7   rL   rm   Zjwt_is_supportZjwt_is_match_orgospathexistsPROJECT_DIRopenreadstripr   
startswithglobal_settingsZsupport_mode)r6   r   rw   r   objorg_namefZpermr   r   r    from_jwt   s@    




"zCmfAuth.from_jwtc           
      C   s  | j dd|gdgd}|s0| j dd|gdgd}|sJ| j dd|gdgd}|stjj & tjjddd d|id	d
||d W 5 Q R X d S |jrt	
d|j d tjj . tjjddd |jddd	d
|j|jd W 5 Q R X tdt	jj d d S |jj dr|jd\}}tjj|drtjj|dgdD ]}z||jj|}W n: tk
r } zt	
d| d|  W 5 d }~X Y nX |tjkr q\n|tjkrtd  q\n|tjkr>| r d S d|_|  d|  }	t j!"|	d tjj 4 tjjddd |jjddd d
|jj|jjd W 5 Q R X |  S q>tjj 4 tjjddd |jjddd	d
|jj|jjd W 5 Q R X |j#r||jj d!r|| rd S | $||j#jrBd"|_|  d|  }	t j!"|	d tjj ( tjjddd |d"dd d
||d W 5 Q R X |S tjj ( tjjddd |d"dd	d
||d W 5 Q R X |%  d|  }	t j!"|	d
 d S )#N	ext_loginZILIKEz***)filterrN   r7   rL   Zident_failedr   rQ   r   rR   rS   rT   rU   rV   security_levelparent_nameparent_codeus   Превышено количество попыток ввода пароля для учетной записи "u$   ", вход заблокированauth_failedzToo many failed login attemptsrO   un   Превышено количество попыток ввода пароля, повторите через u    минутZ
allow_ldap@)domainplugin.*)r   rN   u/   Ошибка авторизации через z: u6   Учетная запись заблокированаZldapzauth:user_last_login_fail:r   auth_successed)r7   typerZ   Z
allow_basebase)&r\   cmfutilr]   r^   r[   r_   r`   fail_block_end_dater   r   r7   	cmf_alertr   auth_fail_timeoutauth_optionsrc   r   CmfAuthLdapPlugincountlistZsigninr   r   r   ZINVALID_CREDENTIALSZUSER_DISABLEDSUCCESS_is_permanent_blocklast_auth_typeauth_success_hooklowerry   REDIS_DBsetr   check_secretauth_fail_hook)
r6   r7   Zchallenge_respr   _r   auth_pluginZldap_status_coder   db_keyr   r   r    get_by_challenge_resp  s    
   
(

   
   

   
   zCmfAuth.get_by_challenge_respc                 C   sr   t jjrn| jrnt d| j d tjj	 . t
jjddd | jdddd| j| jd	 W 5 Q R X td
 dS dS )Nu   Учетная запись "u3   " перманентно заблокированаr   r   zPermanent blockrO   rQ   r   r   ul   Учетная запись заблокирована, обратитесь к администраторуTF)r   r   auth_fail_permanent_blockfail_permanent_blockr   r7   r   r   r]   r^   r[   r_   r`   r   r   r   r   r    r   x  s     
zCmfAuth._is_permanent_blockc              
   C   s   t jjsd S | jdkrd S tjdd }d|  }tj	|}d
tjtjdd}tj	|| |stjjddd |d	d
dd||d td | }|r||krtjjddd |dd
dd||d td d S )Nr   captchazauth:user_login_captcha:r      kr   r   zRequire captcharO   rQ   r   r   i  zBad captcha)r   r   Zauth_check_captchafail_try_counterrequestvaluesr\   r   ry   r   joinrandomchoicesstringdigitsr   r[   r_   r`   abortrr   )r   r7   r   r   Z
db_captchaZnew_captchar   r   r    _auth_check_captcha  s<    

   
   zCmfAuth._auth_check_captchac                 C   s\   |  j d7  _ | j tjjkrPtjjr,d| _ntj tjtjj	j
d | _d| _ |   d S )Nr   T)Zminutesr   )r   r   r   Zauth_fail_try_countr   r   datetimenow	timedeltar   rc   r   ri   r   r   r   r    r     s    
zCmfAuth.auth_fail_hookc                 C   s   d| _ |   d S )Nr   )r   ri   r   r   r   r    r     s    zCmfAuth.auth_success_hookc              	   C   s   | j r| j dkrdS | j}|rVzt|}W n ttfk
rD   Y dS X |t krVdS tjj}|r| j	r| j	t
j|jd }|| j	 k rdS dS )u   
        Проверка необходимости смены пароля с учетом типа последней авторизации.
        r   FTrs   )r   Zpassword_expires_must_changefloat	TypeErrorr   r*   r   r   password_max_dayspassword_changed_dater   r   rc   r   )r   Zpassword_expires_valueZ
expires_tsr   Zexpire_dater   r   r    need_change_password  s     
zCmfAuth.need_change_passwordc                 C   s"   |  }||_ ||_||| |S r$   )r7   rL   set_pass_hash)r6   r7   hashr#   r   r   r   r    new_from_login_hash_salt  s
    z CmfAuth.new_from_login_hash_saltc           
      C   sl   | d}|d }|dkrZ|dd  \}}}t|}t|}	|	td| |t|kS td| d S )Nr   r   Zpbkdf2_sha256r   r.   zNot Implemented for )r   r   r   r   r4   r)   NotImplementedError)
r6   r;   Zsecret_hashZ
hash_partsZ	hash_algoZn_itersalt_b64hash_b64Zsalt_bZhash_br   r   r    r     s    


zCmfAuth.check_secretc                 C   s   | j |dddgd}|rd| ||jjrdtjj & tj	j
ddd|id dd||d	 W 5 Q R X |S tjj & tj	j
d
dd|id dd||d	 W 5 Q R X d S )Nr   r7   rm   rM   r   r   rZ   r   )rR   rS   rU   rT   rV   r   r   r   r   rQ   )r\   r   r   rc   r   r   r]   r^   r[   r_   r`   )r6   r7   r8   r   r   r   r    from_login_password  s.    
   
   zCmfAuth.from_login_passwordc                 C   sR   t jjsd S tjj| dgddgddgdD ]"}|jr*| ||jr*t|j	q*d S )Nz-cmf_created_atr   r   r   cmf_created_at)rT   Zorder_byslicerN   )
r   r   Zpassword_check_historyr[   CmfAuthHistoryZslistr   r   ZCmfAuthReusePasswordErrorr   )r   r8   historyr   r   r    check_history  s       
zCmfAuth.check_historyc           
      C   sN  t jjsd S | }tjj| jdddgd}g }|t	| j 
  |jrf|t	|j 
  |jr|t	|j 
  |jr|t	|j 
  t|D ]B}t|ddd}t|dd}||kr|| ||kr|| qttd	d
 |}|D ]D}t||dd  |dd  D ] }d|}	|	|kr$t q$qd S )N
first_name	last_namesecond_namerM   ruT)language_codereversed)r   c                 S   s   t | dkS )Nr   )r0   )ir   r   r    <lambda>$      z5CmfAuth.check_password_restrictions.<locals>.<lambda>r   r   r   )r   r   Zpassword_restrict_user_identityr   r[   	CmfPersonr\   r7   appendr(   r   r   r   r   r   r   r   zipr   ZCmfAuthRestrictUserIdentity)
r   r8   personZchecking_paramspZp1Zp2ZparamZcheck_tripletZ	check_strr   r   r    check_password_restrictions  s2    
 

z#CmfAuth.check_password_restrictionsc                 C   s(   t |}t |}| j|||d d S )Nr8   )r1   r2   set_pass_hash_bytes)r   r   r#   r8   
hash_bytes
salt_bytesr   r   r    r   .  s    

zCmfAuth.set_pass_hashc              	   C   s   |d k	r|  | | | t| }t| }d| d| | _| j  tj	j
| jd}|r|j  d|_t  |jdd W 5 Q R X d S )Nzpbkdf2_sha256$100000$r   r7   FT)Z	only_data)r   r   r   ro   rr   r   r   Zset_nowr[   r   r\   r7   Zpassword_must_changer]   r^   ri   )r   r   r   r8   r   r   r   r   r   r    r   3  s    




zCmfAuth.set_pass_hash_bytesc                 C   s   t jS r$   )r   r   )r6   r   r   r    current_authD  s    zCmfAuth.current_authc                 C   s:   g }t dD ]}|ttjtj  qd|dS )N   r   zutf-8)	ranger   r   choicer   ascii_lettersr   r   r4   )r6   charsr   r   r   r    gen_saltH  s    zCmfAuth.gen_salt   c           	      C   s   |  dg |sPttjjj|}tjjj}tjjj}tjjj}| j	||||d}t
|  }td| |d}| j|||o~|d tjj , tjjddd| jidd	| j| jd
d W 5 Q R X |S )uO   
        Генерирует новый пароль
        :return:
        r7   )lengthis_upper_symbol	is_numberis_special_symbolr.   r/   r   reset_passwordr   NrZ   r   )rR   rS   rU   rT   rV   r   r   r   )Zload_fieldsmaxr   r   Zpassword_min_lengthrc   Zpassword_min_upper_symbolZpassword_min_numbersZpassword_min_special_symbol_generate_passwordr   r  r3   r   r4   r   r   r   r]   r^   r[   r_   r`   r7   )	r   r  r8   forcer  r	  r
  r#   r   r   r   r    r  O  s2    


  
   zCmfAuth.reset_password)r  r
  r	  r  returnc                 C   s   g }t jt j t j }|r6|t j7 }|tt j |rL|tt j |rb|tt j tj||t	| d}|
| t| d|S )Nr   r   )r   r  r   Zascii_uppercaseZpunctuationr   r   r  r   r0   extendZshuffler   )r   r  r
  r	  r  Zpassword_dataZlettersZextra_symbolsr   r   r    r  l  s    


zCmfAuth._generate_passwordc                 C   s\   dt j }d|g}t||| tjj & tjj	ddd d|id||dd W 5 Q R X d S )	Nu&   Пароль для доступа к u   Пароль:send_passwordr   rL   rZ   r   )rR   rS   rT   rU   rV   r   r   r   )
rX   ra   r   r   r   r]   r^   r[   r_   r`   )r6   r8   rL   rY   Zmsg_contentsr   r   r    r    s    
   zCmfAuth.send_passwordc                 C   sn   ddl m} | }tj||d}|  |jtddd d|ddd}|jd	kr\td
t	|j
ddS )Nr   )session)r7   rg_member_ofT)r@   Zinternalzauth/signup)r7   Zgen_pwd)data   u>   Не удалось создать учётную записьaccess_token)r  )Zrequestsr  r[   r   ri   ZpostrE   Zstatus_coder   rC   Zcookiesr\   )r6   r7   r  r  sr   rr   r   r    create_person  s    
zCmfAuth.create_personc              	      s   | j jrZd| _| j jsZ| j D ].}| j | D ]}|  jd| d| 7  _q*q| jj | _t j||}| jjrt	
  tj| | jd  W 5 Q R X |S )Nr   r   r   )rT   r   )groups
is_changedrm   is_nullrc   r   superri   r   r]   r^   r[   r   )r   argskwargsr   Zgrp_namer}   	__class__r   r    ri     s    

zCmfAuth.savec                 C   s&   | j jrg S tdd | j dD S )Nc                 S   s   g | ]}| d d qS )r   r   )r   ).0r   r   r   r    
<listcomp>  s     z)CmfAuth.prepare_scope.<locals>.<listcomp>r   )rm   r  r   r   r   r   r   r    prepare_scope  s    zCmfAuth.prepare_scopec                 C   s   |  |}tjdkr|S |d d }zt|}W n  tk
rR   d}t|Y nX | ||}|sd|d d  d}t	| t||S )NFalsert   issuJ   Не удалось прочитать публичный ключ EvaTeamuE   Не удалось валидировать токен от EVA_APP r   !)
r   rX   ZEVA_ACCOUNT_USEr   Zread_crm_pub_keyRuntimeErrorr   r   r   r   )r6   eva_app_tokenrw   r&  Zcrm_pub_keyr   r   r   r   r    check_token  s    


zCmfAuth.check_token)usersc             
   O   sj  |  |}|d d }|D ]D}zt|d   }dddddd	d
dg}	d}
|dr| jt|d   |	d}
|
r||
_q| j||	d}
n| j||	d}
|
stj|d}
t	d|  |

  |dpd}t|  p||
_|d	pd}t|  pd|
_|
jjr$i |
_|
js2g |
_||
jkrJ|
j| g |
j|< |d rt	d|| ||
jkr|
j| |
j|= d|
j_|

  W q|d D ]:}t	d| d| d|  |
j| | d|
j_q|d |
_t	d|  t	d|
j  |

  t  t	d|
j  W q tk
r^   td|   Y qX qddiS ) u   
        Метод вызывается из eva_app при синхронизации
        создает и привязывает пользователей
        https://bcrm.carbonsoft.ru/project/Document/DOC-003025#spec-0-ldap
        rt   r   r7   r  rm   r   reg_org_name_listrL   r   Z
is_supportZis_adminNZ	old_loginrM   r   u(   Создали пользователя r   Zcmf_deletedu4   Пользователь {} удален из Eva {}Tr  u,   Добавляем пользователю u    права u    в Eva r   z
user_dict=zuser.groups=zuser.scope=u)   Не удалось обработать resultrZ   )r*  r(   r   r   r\   r7   r[   r   r   r   ri   rL   r   r  r  r,  r   formatremover  r   
cmf_commitrm   r   r   )r6   r)  r+  r  r  rw   r   Z	user_dictr7   _fieldsuserrL   r   Zgrp_coder   r   r    rpc_account_sync_push  sp    

    





zCmfAuth.rpc_account_sync_pushc                O   s  t js
d S dd }t jsd S | |}|d d }|D ]}tjj|d d dgd}	|	s`t }	||	|d  |d d |	_|	  tjj|d dd	gd}
|
st }
||
| ||
_	|d |
_|	|
_
|
  q6tjjd
ddd |D gdD ]}	|	  qddiS )Nc                 S   sF   |D ]<}|dks| ds|dr&qt| |rt| |||  qd S )N)idcodeZext_ipZcmf_Z_id)r   endswithhasattrsetattr)r   Zobj_dictZ
field_namer   r   r    copy_f  s    
z/CmfAuth.rpc_account_plugin_push.<locals>.copy_frt   r   pluginr4  r
   )ext_idrN   r   r;  zNOT INc                 S   s   g | ]}|d  qS )r4  r   )r"  r   r   r   r    r#  ,  s     z3CmfAuth.rpc_account_plugin_push.<locals>.<listcomp>)r   r-  rZ   )rX   ZIS_BOX_VERSIONr*  r[   Z	CmfPluginr\   r;  ri   r   r   r:  r   delete)r6   r)  Zauth_pluginsr  r  r9  rw   r   r   r:  Zauth_plugin_objr   r   r    rpc_account_plugin_push  s2    



"
zCmfAuth.rpc_account_plugin_pushc                 K   sl   | j tj| jjd tjtjd }ttdtj	}|j
d|  f||dddd| tj|||f| d S )N)Zsecondsr   ZAUTH_SESSION_COOKIE_DOMAINZsession_tokenTLaxr   expiresZsecureZhttponlyZsamesite)Zreauth_dater   r   Zaccess_token_expires_inrc   rX   PROLONG_DAYSgetattrr   host
set_cookieZ	get_tokenr   set_nginx_token)r  responsecookie_kwargsr@  cookie_domainr   r   r    set_session_token0  s    $  	zCmfAuth.set_session_tokenc                 K   sL   |j d| jtjd df|tj tjtjtj d dddd| d S )Nr  r   r   Tr>  r?  )rD  r~   rX   TOKEN_TTL_DAYSr   r   r   rA  )r   rF  rH  rG  r   r   r    set_access_tokenB  s    
  
zCmfAuth.set_access_tokenc                 K   s<   |st j  t jtjd }| jd||dddd| d S )Nr   nginx_auth_tokenpassword123Tr>  r?  )rL  rM  )r   r   r   rX   rJ  rD  )rF  rH  r@  rG  r   r   r    rE  Q  s        zCmfAuth.set_nginx_tokenu_   Разблокировка учетных записей по истечению времениz	@minutely)Z	only_oncedescriptionZ
system_jobZschedulec                  C   s^   t jjrd S tj } tjjdgdd| gddgd}|s:qZ|D ]}d |_|	  q>t
  qd S )Nr   <r   d   )rN   r   r   )r   r   r   r   r   r[   r   r   r   ri   r0  )r   Zblocked_usersr   r   r   r    )cron_unblock_users_after_block_expiration^  s    

z1CmfAuth.cron_unblock_users_after_block_expiration)r=   F)T)r   N)r   N)T)N)N)r  NN)FFF)N)N)E__name__
__module____qualname__r'   Z	ts_lengthZjinja2ZEnvironmentZFileSystemLoaderr   r   r   rX   r   ry   Zselect_jinja_autoescaperb   propertyr!   r#   r-   classmethodr<   rJ   rg   rB   rj   rv   staticmethodrC   rx   r(   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r)   boolr  r  r  ri   r$  r*  r   r3  r=  rI  rK  rE  Zcmf_deferred_jobrQ  __classcell__r   r   r   r    r      s   




 





'
f



!




      


B
!

r   )"r   r   r3   rp   r   r%   r   r*   rF   r   Ztransliterater   ZCrypto.Cipherr   ZCrypto.Hashr   ZCrypto.PublicKeyr   ZCrypto.Randomr   ZCrypto.Signaturer   ZCrypto.Util.Paddingr	   Zcmf.includerL   r   rN   r   Zenumsr   Z
supervisorr   r   r   r   r   r    <module>   s,   