U
    8[Sea                    @   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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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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*Z$d dl+Z+e+,dZ-G dd de.Z.dd Z/ee0Z1dddZ2G dd de3Z4dd Z5G dd de!Z6e.e7de8j9dZ:e6e:_;de:_<de:_=g e:_>g e:_?g e:_@g e:_Ag e:_Bg e:_Cde:_Dd e:j8d< i e:_Ed dlFmGZGmHZH d dlImJZJ d dlImKZK d dlLZLdd!d"ZMG d#d$ d$ZNeN ZOd%d& ZPd'd( ZQeRe8d)re8jSd* d+ d,kre8jSd* T ZUeUVd+ d-eUkreUVd- eLjWf eUeO_LeXjYZd.reOjLdkre[d/e:d0e8j\d1d2Z]eRe8d)re8jSd* d+ d,kre8jSd* d3 Z^e8jSd* Zd4r8d5e8jSd* d4  d6e^ Z_eJe_d7d1d8Z`e`e]d9< nd:Zad;e8jSd* kr^eae8jSd* d; 7 Zad<e8jSd* kread=e8jSd* d<  d>7 Zaeae8jSd* d? 7 Zaead=e8jSd* Zd@dA 7 ZaeadBe^ 7 Zaeae]dC< d dDlbmcZc dEec_deGf e]ZIeKe8j\dFZeeKe8j\dFZfeXjghe8j9dG r<eie8j9dG Zjejk l e8_mW 5 Q R X eRe8d)re8jSd* d+ d,krje4eOjLdHZnn(e8jSd* d+ dIkre4ddJZnne[dKne4 ZneOe:_Ode:_od e:_peqjrddLdMdN Zse:te[dOdP Zue:ve[eu ee8j9dQ Zwee8j9dR Zxd dSlymzZz ewh r ez{ew| e:_}exh r:ez{ex| e:_~dTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgge:_dhdi Z<djdk Zdldm Zdndo Zdpdq Z=de:_de:_drds Zdtdu Zdvdw Zee<ee_<ee<ee_eeee_eeee_eeee_eeee_eeee_ee=ee_=dxdy Zeeee_dzd{ Zeeee_dd~dZdddZe:jdd ZdddZdddZdd Zdd Zdd Zdd ZdddZdd Zdd Zdd Zdd Zdd Ze:jdd Zdd Zdd Zdd Ze:jdd Ze:jdddZdddZdBddg dddZdd ZdddZdd Zdd Zdd Zdd ZG dd dZdd ZdddZdd ZddĄ ZddƄ ZddȄ Zddʄ Zed˜dd̈́ZeedΜddЄZi e:_i e:_i e:_dZdadadddӄZddՄ Zddd؄ZdS )    N)OrderedDictdefaultdict)Path)urlparseparse_qs	urlencodequote)SHA256)
PKCS1_v1_5)abortResponse)JSONEncoder)HTTPExceptionfields)*)basez^.*\.(png|jpeg|ico)|^(/sso/|/drawio/|/pub/|/docs/|/share/|/files/|/tinymce/|/app/assets/|/socket.io/).*|^.*/forms/CmfForm:.*|^.*(styles|vendor|runtime|polyfills|main)-(es5|es2015).*\.js$|/styles.*\.css$c                       s$   e Zd Z fddZdd Z  ZS )Flaskc                    s   t  j|| d S N)super__init__selfargskwargs	__class__ ./cmf/app.pyr   '   s    zFlask.__init__c                    s    fdd}|S )Nc                    sn     dd }| j}|dd }|dkr6d|  }n}|d krP|d | j }j||| f  t| | S )Nendpoint.index/)pop
__module__split__name__add_url_ruleprint)fr   module_pathZmodule_nameurloptionsruler   r   r   	decorator+   s    zFlask.route.<locals>.decoratorr   )r   r/   r.   r0   r   r-   r   route*   s    zFlask.route)r'   r%   __qualname__r   r1   __classcell__r   r   r   r   r   &   s   r   c                 O   s   | rt || d S r   )r)   )Zcondr   r   r   r   r   print_debug<   s    r4   c                    s    fdd}|S )Nc                    s   t   |  | S r   )_server_event_channelsappend)funcchannelr   r   r0   E   s    z"on_server_event.<locals>.decoratorr   )r9   patternr0   r   r8   r   on_server_eventB   s    r;   c                   @   s  e Zd ZdZdZdZdZdZdZdZ	dZ
daddddZdd Zdd	 Zd
d Zdd ZdbddZdd Zdd Zdd Zdd ZeeedddZeedddZedcddZd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Z ddd.d/Z!d0d1 Z"d2d3 Z#d4d5 Z$d6d7 Z%d8d9 Z&d:d; Z'd<d= Z(d>d? Z)d@dA Z*dBdC Z+dDdE Z,dedFdGZ-dfdIdJZ.dKdL Z/dgdMdNZ0dOdP Z1e2dQdR Z3e2dSdT Z4e2dhdUdVZ5ee6dWdXdYdZ Z7e2d[d\ Z8e2d]d^ Z9e2d_d` Z:dS )iCmfCacheNFreturnc                 C   sH   t  | _t  | _|| _|| _i | _| jrD| jdd | jdd d S )Nstat_hitr   	stat_miss)dict	cache_objcache_invalidateredis_dbmemoryZtexcom_growcache_hack_cacheincrby)r   rD   rE   r   r   r   r   U   s    zCmfCache.__init__c                 C   sj   t tjp| jdtjd | jr*| j  nt | _t | _	| j
dtd  | j
dtddi d S )NzCmfCache.flushdb!!!filezCmfCache:flushdbCmfCache:inmemory_delkeysALL)r4   configDEBUGsysstderrrD   flushdbrA   rB   rC   publishjsondumpsr   r   r   r   rP   `   s    zCmfCache.flushdbc                 C   s   t tjp| jdtjd tt}| j }| jj	dddD ]p}t | jd| dtjd |dd	 
 }| j|}|d	kr~q:t|}|d
 }|d || |< || q:|  | | d	S )u)   Инвалидируем весь jscachezCmfCache.flush_jscache!!!rG   zobj:jshash:*  countz"CmfCache.flush_jscache invalidate z!!!   Ncurrent_person_idjsver)r4   rL   rM   rN   rO   r   rA   rD   pipeline	scan_iterdecodegetpickleloadsdeleteexecuteemit)r   emit_msgpipekeyjshashjsresjspersonr   r   r   flush_jscachej   s    

zCmfCache.flush_jscachec                 C   s   t tjp| jdtjd d}| j }| jjdddD ]"}|drFq6|d7 }|	| q6|
  t tjpn| jd	| d
tjd dS )u+   Инвалидируем весь obj cachezCmfCache.flush_all_obj!!!rG   r   zobj:*rU   rV   s
   obj:jshash   zCmfCache.flush_all_obj: z recordsN)r4   rL   rM   rN   rO   rD   r[   r\   
startswithra   rb   )r   rW   re   rf   r   r   r   flush_all_obj|   s    

zCmfCache.flush_all_objc                    s<  dd l |} fdd ttjj dd   d d dkrXtjj S |D ]}|d  | }q\d|kr|d t|d  }t	|
 D ]*\}}|dkrq|d | d	  | }q| jrd
|dd  d |   }|dd	}|dd}n| d	|   }t| jd| |S )Nr   c              
      sh  dd l }ddlm} t| tjjr4| jr0| j} nd} d}t| t	t
tfrt| t	r| dd dkrz.|j| }||j}|jddd}|} W n" tk
r } zW 5 d }~X Y nX t	| }nt| tr| D ]}| | d }qnt| tr.|  D ]2\}}|| }|r"| d	 | }q|d }qn6| d kr>d
}n&dt| j d	 t|   }|S )Nr   )timezonez...    Z20)secondZmicrosecond,:Nonez
todo2:obj:)Zdateutil.parserdatetimern   
isinstancecmfr   CmfType
is_definedvaluestrintfloatparserparseZ
astimezoneutcreplace	ExceptionlistrA   itemstyper'   md5r_   rS   	hexdigest)valdateutilrn   resZval1evk_all2strhashlibr   r   r      s<    


&zCmfCache.hash.<locals>._all2strrX   Z3123|idz|id:rs   zHASH:i  z|md5:
 _zDEBUG_CACHE HASH:)r   r   r{   rw   r   CmfDatenowencoder   sortedr   rM   r   r4   )r   prefixr   r   sr   rf   r   r   r   hash   s(    +2&zCmfCache.hashc                 C   s2  |d krt  }|s|S tt|j}t  }|j D ]}|j|d }|sJq2|drh|	|d d  n
|	| t
|tjjrt||jd }|r| j||d q2t
|tjjtjjfr2t||jd }|r|D ]}| j||d q| D ]"}	d|j d|	j }
|	|
 qq2|	|jd dt|  |S )N_idr!   )r   ref_r   r   rr   )setgetattrmodels
class_name__dict__rJ   r   r^   endswithadd
issubclassrw   CmfRelationBasesimple_objects_id_recursive
CmfM2MBaseCmfBackrefBaserelated_modelsr   joinr   )r   objr   modelfields_str_set
field_nameZ	field_clsZfield_valuerel_obj	rel_modelrefr   r   r   r      s6    

z$CmfCache.simple_objects_id_recursivec                 C   s  |sg S g }t  }|jddD ]}|jdrD||jdd  n||j t|tjjrp|	| 
|j t|tjjtjjfr|jr|jD ]}|	| 
| q| D ]"}d|j d|j }|| qq||jjd d	t|  tt |}|S )
u   
        Собираем ид связанных обьектов 2 уровня для настройки инвалидации
        :param obj:
        :return:
        Try   r   Nr!   r   r   r   rr   )r   valuesr   r   r   rv   rw   r   r   extendobjects_id_recursiverz   r   r   r   r   r6   r   r   r   )r   r   r   r   fieldr   r   r   r   r   r   r      s(    
 zCmfCache.objects_id_recursivec                 C   sT   t |tjkrtddd dS | jr<| jd| | dS | jrP|| j|< dS d S )NuU   DEV: Слишком большой объект для кэширования — keyT)
debug_onlyFobj:)lenrL   ZCACHE_MAX_OBJ_SIZE	cmf_alertrD   r   rE   rB   )r   rf   Zstr_valr   r   r   _obj_dict_set  s    
zCmfCache._obj_dict_setc                 G   sr   t  }|D ]}|d|  q
| jrD| jj| t|kr>dS dS n*| jrj|D ]}| j|sN dS qNdS d S d S )Nr   TF)r   r   rD   existsr   rE   rB   r^   )r   rJ   Zhkeysrf   r   r   r   _obj_dict_exists#  s    zCmfCache._obj_dict_existsc                 C   sX   | j r>| j d| }|d k	r.| j d n| j d |S | jrP| j|S d S d S )Nr   r?   r@   )rD   r^   rF   rE   rB   )r   rf   r   r   r   r   _obj_dict_get5  s    zCmfCache._obj_dict_getrg   inv_payloadc                 C   s   |  d| S )N::r   r   r   r   r   %_jshash_invalidate_confirm_member_keyB  s    z.CmfCache._jshash_invalidate_confirm_member_keyZ
member_keyc                 C   s   | j dddS )Nr   rk   )maxsplitr&   r   r   r   r   +_jshash_invalidate_confirm_member_key_splitF  s    z4CmfCache._jshash_invalidate_confirm_member_key_splitc                 C   s    | r| n| dd }d| S )Nrs   zjscache-invalidate-confirm-set:r   )cache_idrg   set_keyr   r   r   "_jshash_invalidate_confirm_set_keyJ  s    z+CmfCache._jshash_invalidate_confirm_set_keyc           	      C   s   t t}| D ]Z\}}td| |d |gd | D ]0\}}|dr8|| j|d | || q8q| jr| D ]\}}| jj	|f|  qzd S )Nzinvalidate-)roomevent_personsjshash:rg   )
r   r   r   cmf_emit_eventrl   r   r6   r   rD   sadd)	r   ZmsgsZconfirmationsZ	person_idinv_dictrg   r   r   confirm_listr   r   r   rc   Q  s    

zCmfCache.emitc                 C   sb   | j r^|r^|d d }| j|d}t }|D ]}|| |d |d  q,| j j|f|  d S )Nr   r   rk   )rD   r   r   r6   r   srem)r   Zconfirm_dictZsample_jshashZkey_cache_idr   Zconfirmr   r   r   jshash_invalidate_confirm`  s    
z"CmfCache.jshash_invalidate_confirmc                    s.    j r* |} fdd j |D S d S )Nc                    s   g | ]}  | qS r   )r   r]   ).0memberrT   r   r   
<listcomp>q  s   z;CmfCache.jshash_invalidate_confirm_list.<locals>.<listcomp>)rD   r   smembers)r   r   r   r   rT   r   jshash_invalidate_confirm_listl  s
    


z'CmfCache.jshash_invalidate_confirm_listc              	   C   s  |sd S | j r| j jdd |D   t| | | i }|D ]}| jrdd|krdtd|  t| jd|  | j d| }|rBt| jd|  | jrtd|  |D ]}|	d	}| jrd|krtd
| d|  t| jd|  | j 
d| }	|	d krqt|	}	|	r|	d }
|
|krBt ||
< |dkrt|rtdtdd |jddD }nd}|	d  d| d| d| }|||
 |< | j d|  q| j d|  | | qBn.| jr |D ]}|| jkr| j|= qnd S d S )Nc                 S   s   g | ]}d | qS )r   r   r   rf   r   r   r   r   y  s     z+CmfCache._obj_dict_mdel.<locals>.<listcomp>rW   z#DEBUG_CACHE JSHASH: try invalidate z*DEBUG_CACHE JSHASH: try invalidate:jshash:invalidate:jshash:z*DEBUG_CACHE JSHASH: got invalidate:jshash:z#DEBUG_CACHE JSHASH: got invalidate utf-8z"DEBUG_CACHE JSHASH: do invalidate r   z)DEBUG_CACHE JSHASH: do invalidate jshash:r   rY   updater   c                 S   s   g | ]}|d kr|qS ))Zcache_fieldscmf_modified_atcmf_viewed_atZcmf_modified_by_idr   )r   r   r   r   r   r     s    T)
is_changedONLYFORUPDATESrZ   )rD   ra   	CMF_CACHEinmemory_delprofiler_invalidaterM   r   r4   r   r]   r^   r_   r`   rA   r   r   rJ   rc   rE   rB   )r   rJ   r   obj_idactionrd   rf   Zinvjsrg   rh   ri   changed_fieldsr   r   r   r   _obj_dict_mdelu  sX    







zCmfCache._obj_dict_mdelc              	   C   s   | j rN| j  6}| D ]\}}|jd| f|  q|  W 5 Q R X nD| jr|D ]2}|| jkr|| j| ||  qX|| | j|< qXnd S d S Ninvalidate:)rD   r[   r   r   rb   rE   rC   r   )r   r   re   rf   r   r   r   r   _invalidate_dict_mset  s    
zCmfCache._invalidate_dict_msetc                 C   sH   | j r.| j d| }|r*dd |D S |S | jr@| j|S d S d S )Nr   c                 S   s   g | ]}| d qS )r   r]   r   r   r   r   r     s     z1CmfCache._invalidate_dict_get.<locals>.<listcomp>)rD   r   rE   rC   r^   )r   namer   r   r   r   _invalidate_dict_get  s    zCmfCache._invalidate_dict_getc              	   C   s   | j rT| j  <}| D ]$\}}|r| j jd| f|  q|  W 5 Q R X nJ| jr| D ]4\}}|D ]&}|| j|g krn| j| | qnqbnd S d S r   )	rD   r[   r   r   rb   rE   rC   r^   remove)r   r   re   r   r   Zkey_listrf   r   r   r   _invalidate_dict_mdel  s    zCmfCache._invalidate_dict_mdelc                    s  t jdrdt_d S t|rBdt_tjdt	|  d S 
|}tj|tj}||k rdt_tjdtj d
|  d S i tjj|}fdd  fdd	}|rt|tst|d
r|| d}	t|jtjkrtd|j dtj  d S n~|rFt|trFt|d d
rFd}	|| nN|d k	r|d}	t|tkrt|tkrttkrn|sd}	d}ntdd}
|r|d rtjd| |	dkr|j|d kr|d D ]D}||j d|j dfkrd}
|j krtd  qq|
sg }d*|jD ] }||d kr2|d | }q2|s`dg}t|tjd< |D ]}|dkrd}|d D ]h}| d d }||krȈ d!|   d!| d" n* d#| d$|   d#| d$| d" qqr|d D ]} d!| d" q|r*|d s: d!| d" jrfD ]}tjd%| d&  qFt!"|}#|sdt_$t%|t&| d'tkrtj'rtjd( dtj'  jrt(d( tj' )d) tj'fi ) d S )+NNO_CACHETz%DEBUG_CACHE ADD SKIP CACHE LOCKED_BY z#DEBUG_CACHE ADD SKIP too old trans r   c                    sT   |  d\}}}| kr"t  |< |r@ |  d|  n |   d S )Nr   )	partitionr   r6   )Zbind_and_fieldsbindr   r   )r   rf   r   r   bind_add  s    
zCmfCache.add.<locals>.bind_addc                    sd   t | tr| }n| g}g }|D ]@}t |jtjjr>|}nt|}|D ]} | qPqdS )u   
            Собираем списки ключей инвалидации
            :param val:
            :param invalidate_dict:
            :return:
            N)rv   r   r   rw   r   rx   r   r   )r   Zobj_listr   itemr   )r   r   r   r   bind_add_recursive  s    
z(CmfCache.add.<locals>.bind_add_recursiver   r   zSkip add to cache z  g.skipcache_select_for_update: r   r   ZcustomemptyZEmptyuG   Невозможный объект для хранения в кешеFr   zDEBUG_CACHE WHERE: r   z.idz.codezDEV: Obj in not in inv_dictparentZcache_clustersZScopeAll)ZNullZNULLZnullrt   ZnoneNrt   r    where_ScopeAll__insdelwhere_r   zDEBUG_CACHE BIND: z = rg   #DEBUG_CACHE JSHASH: add invalidate r   )r   )*osenvironr^   gno_jscache_forcer   cache_is_lockedr4   rM   cache_locked_byget_last_invalidatecache_lockscache_transaction_startrw   utilcmfutilget_model_by_namerv   r   hasattrr{   r   skipcache_select_for_updater)   r   r|   r}   r   r   r   cache_cluster_fieldsprofiler_datar&   r_   rS   r   Zcache_store_errorinmemory_addr   rg   r   r   )r   rf   r   obj_typeZquery_paramsZlir  	obj_modelr   Zobj_caseZwhere_pkr   Zscopesc_fieldZscope
model_nameZbindidZstr_objr   )r   r   rf   r   r   r     s    

 "

&



zCmfCache.addc              
   C   s   zdt krt t _W n( tk
r< } z
W Y d S d }~X Y nX dt jkrXt|t jd< nt jd  t|7  < tjrdt jkrg t jd< t jd | d S )Nr  rC   Zcache_invalidate_keys)r  rA   r  r   r   r<   DEBUG_PROFILE_VERBOSEr6   )r   rJ   r   r   r   r   r     s    


zCmfCache.profiler_invalidatec              
   C   s   zdt krt t _W n( tk
r< } z
W Y d S d }~X Y nX dt jkrTdt jd< nt jd  d7  < dt jkrzdt jd< tjrdt jkrg t jd< t jd | d S )Nr  redis_cache_hitrk   redis_cache_missr   Zredis_cache_hit_keysr  rA   r  r   r<   r  r6   r   rf   r   r   r   r   profiler_redis_data_hit  s    




z CmfCache.profiler_redis_data_hitc              
   C   s   zdt krt t _W n( tk
r< } z
W Y d S d }~X Y nX dt jkrTdt jd< nt jd  d7  < dt jkrzdt jd< |t jd< tjrdt jkrg t jd< t jd | d S )Nr  r  rk   r  r   Zredis_cache_miss_lastZredis_cache_miss_keysr  r  r   r   r   profiler_redis_data_miss  s    





z!CmfCache.profiler_redis_data_missc                 C   s  t jdrd S d}t|}t| jd |dkrVd}| |}|rVt	|}t
|}|dk	rdtkrtjr| d| tjfi t| jd| d	tj  | jrtd
| tj t| jd|  t| jd| |s| | t||| |S | | t| jd|  d S )Nr   TZCACHE.Frg   r   z*DEBUG_CACHE JSHASH: add invalidate jshash:r   r   zDEBUG_CACHE HIT: zDEBUG_CACHE GET:zDEBUG_CACHE MISS: )r   r   r^   r   inmemory_getr4   rM   r   r_   r`   r   r  rg   r   r   r  r  r  )r   rf   Zfrom_inmemoryr   r   obj_sizer   r   r   r^     s4    




zCmfCache.getc                 C   s   dS S )Nr   z%DEBUG_CACHE TRANS get_last_invalidatecache_last_invalidate_r4   rM   r|   rD   r^   r   r  r   r   r   r    s     zCmfCache.get_last_invalidatec                 C   s   t | jd |  t_d S )Nz)DEBUG_CACHE TRANS cache_transaction_start)r4   rM   gen_time_usr  r  rT   r   r   r   r    s    z CmfCache.cache_transaction_startc                 C   s   t tjtjjdS )Nz%Y%m%d%H%M%S%f)r|   ru   r   rn   r   strftimerT   r   r   r   r     s    zCmfCache.gen_time_usc                 C   s   d S d S )NzDEBUG_CACHE TRANS cache_lockr  cache_lock_)	r4   rM   r  r   rD   r   r  r  r  )r   r  lr   r   r   
cache_lock   s          zCmfCache.cache_lockc                 C   s\   d S t j D ]H\}}| |}||ks6t j|d krt| jd | jd| d qd S )Nr   zDEBUG_CACHE TRANS cache_unlockr"  0)	r  r  r   r  r  r4   rM   rD   r   )r   r  Ztr_startZlock_trr   r   r   cache_unlock  s      
zCmfCache.cache_unlockc                 C   s   dS S )Nr   z%DEBUG_CACHE TRANS get cache_locked_byr"  r  r  r   r   r   r  !  s     zCmfCache.cache_locked_byc                 C   s   dS dS dS )NFr   r%  z/DEBUG_CACHE TRANS cache_is_locked drop deadlockr"  r&  T)	r  r  r  r^   r  r4   rM   rD   r   )r   r  Z_cache_locked_byr  r   r   r   r  &  s           zCmfCache.cache_is_lockedc                 C   s   g }|d kr|j }|D ]:}|| D ],}d|krD||dd  q"|| q"q| |||| | | | jrtd| d| | d S )Nr   r   invaldebug--)r   r6   r&   r   r   rM   r   )r   r   r   r   r   Zinv_listr   Zinv_valr   r   r   _do_invalidate5  s    
zCmfCache._do_invalidater   c              	   C   s(  t jdrd S |d kr$| dh}|s,d S | | t| jd| d| dt|  t }t }t }i }i }|D ]f}	| j	d|	 d}
|
D ]>}| j
|}|r|D ]$}|dd }|| |	||< qq||
 qv|D ]}| j
d	|  }||}	|r|D ]}|dd }|| | jd
|  }|sJqt|}|d }||krpt ||< d}|d  d| d|	 d| }||| | < qq|dd |D dd |D dd |D }|rtd| d| d|  | jj|  ntd| d| d | | d S )Nr   rs   z!DEBUG_CACHE start invalidate_ids r   zinvalidate:*r       r   r   r   rY   r   rZ   r   c                 s   s   | ]}d |   V  qdS r   Nr   r   	query_keyr   r   r   	<genexpr>  s     z*CmfCache.invalidate_ids.<locals>.<genexpr>c                 s   s   | ]}d |   V  qdS )r   Nr   r-  r   r   r   r/    s     c                 s   s   | ]}d |   V  qdS r,  r   )r   rg   r   r   r   r/    s     zinvalidate_ids(, ): z): no keys found.)r   r   r^   r$  r4   rM   r   r   rD   rJ   r   r&   r   r   r]   r_   r`   rA   r  debugra   rc   )r   r  idsr   Zinvalidate_keysZ
query_keysZjshashesrd   Zobj_id_by_query_keyid_rJ   rf   Zinv_membersZ
inv_memberr.  Zquery_jshashesrg   rh   ri   r   r   Z	keys_listr   r   r   invalidate_idsF  sd    
"





zCmfCache.invalidate_idsc                    s   d fdd	}t jdr"d S |s*d S | tjd  d|  i |D ]6}|d| d| d	 ||d
 jd  |d qTd S )Nro   c                    s6    | }|r2|| < tjd  d| |   d S )NDEBUG_CACHE INVAL: r   )r   r4   rM   )invalr2  invdr   r   r   r   r   _check_inval  s    
z8CmfCache.invalidate_ids_as_wrapper.<locals>._check_invalr   DEBUG_CACHE start invalidate r   r   r   ref=obj.id=)r   )ro   )r   r   r^   r$  r4   rM   r*  )r   r  r3  r   r:  r4  r   r9  r   invalidate_ids_as_wrapper  s    

z"CmfCache.invalidate_ids_as_wrapperc              
      s@  d* fdd	}ddl m} tjdr.d S |j tjd  d|j  |j}i j	rtdd l
}|  |jd	kr||j d
  dkr|d|j d|j d |std ||j d|gd |d|j dd |d|j d|j dd |  d S t }	|jddD ]8\}
}|jdkr>q$t|tjjr dkr|r|jr|d|j d|j d  dkr|jr|j|jkr|d|jj d|j d |d|jj d|j d |	|
 q$t|tjjr dkr|jr|	|
 q$|jr<t|tjjr<|	|
 q$|jr$|j|jkr$|	|
 q$t|	dkr dkrtjd  d|j d S dg}|jD ]}|| q||  dkr||j d  dkr||j d|	d  dkr|	D ]
}
d+|jD ]}t||s"qt t!|| tjjrj|| D ]$}|d|j d| d!|
 d qBnt t!|| tjjr|d||d"   d| d!|
 d nFt t!|| tjj"r|d||  d| d!|
 d ntd#dd$ q|d| d!|
 d qd%}d,|jD ]8}t||r|| jr|| j|| jkrd}q dksd|rd-|jD ]}t||sqnt t!|| tjjr|| D ] }|d|j d| dd& q|| jr|| jr|| jD ] }|d|j d| dd' qnt t!|| tjjr~|d||d"   d| dd || jr|| jr|d|| jj d| dd( nzt t!|| tjj"r|d||  d| dd || jr|| jr|d|| jj d| dd( ntd#dd$ qn|d| d t#j$r.t%j&d)g g t%j&d)< |  d S ).Nro   c                    s   | }g }|r|rt|}g }|D ]}d|kr@|| q(|d^}}}|rtd|  d|  td|  d| d| dd || q(t|d}	||	@ r(|| q(|| < n|| < tjd  d| |   i }
||
| < t	j
rtjdg |
g tjd< d S )	Nr   z=cmfCache.invalidate(): ValueError: too many values to unpack(r1  Tr   rr   r6  r8  )r   r   r6   r&   r  r2  r   r4   rM   r<   r  r  r^   )r7  r2  change_fieldsr8  Zinvd_affectedir   Zi_fieldstailZi_set_fieldsZtmpr9  r   r   r:    s4    



z)CmfCache.invalidate.<locals>._check_invalr   )r   r   r;  r   ZRelationCachezRelationCache.parent.id=)r6   r   r   r   r<  uY   DEV: FATAL в инвалидацию м2м поля не передали имя поляr=  )r@  r   r   zwhere=r   Tr   )r   cmf_modified_byr   Zcmf_viewed_byZcmf_versionro   )createra   r   zref_new=zref_old=zDEBUG_CACHE ivalidate: z not fields_have_changesz--r   r    r   u   Ошибка конфигурации моделей: cache_cluseter_fields может быть только по m2m и relation полямr?  Fz
where_m2m=zwhere_m2m_old=z
where_old=r   )ro   N)r   )r   )r   )'collectionsr   r   r   r^   r$  r   r4   rM   TRACEpdbZ	set_traceZ	parent_idr   r   r*  r   r   rv   rw   r   r   r   oldnewr6   r   r   r   r  load_fieldsr  r   r   ZCmfTUUIDr<   r  r  r  )r   r   r   r   Zm2m_field_namer:  r   r  rG  r@  r   r   Zcluster_load_fieldsr  Zcc_field_nameZ
cc_clusterZcluster_field_is_changedr   r9  r   
invalidate  s    % 

 
"







$&"
  ""
zCmfCache.invalidatec                 C   s<   | j D ]\}}td| q| j D ]\}}td| q$d S )NzDEBUG CmfCache.dumps)rB   r)   rC   r   )r   rf   r   r   r   r   rS     s    zCmfCache.dumpsc                 C   s   | dd }tjr"| dd }ztjj|}W n tk
rJ   Y dS X tj	st|j
rf|jtjkrfn| | dS |tjkr| | dS tj| }||d}|dkr| | |S || | | t|S d S )Nr    r   rs   rk   .)r&   r<   rM   rw   r  r	  r
  KeyErrorr  in_memory_cachecache_inmemoryr   in_memory_cache_skip_modelsprofiler_inmemory_data_skipAPPINMEM_CACHEprofiler_inmemory_data_missr^   move_to_endprofiler_inmemory_data_hitr_   r`   )clsrf   r  r   model_cacheretr   r   r   r    s.    




	

zCmfCache.inmemory_getc                 C   s  |dkrt |tjjs t|r,d| }nJ|rvt |trvt |d tjjsZt|d rvd|d j dt| d}t	| j
d| d|  d S t|}t	| j
d|  |d	d }tj
r|d
d }ztjj|}W n tk
r   Y d S X tjs|jsd S d}|jrd}|tjkr6t tj|< tj| }||krz|| |krvtd| d| d||   d S |||< t||kr|jdd\}	}
t	| j
d|	  d S )Ni  r0  r   []u/   DEV: skip inmemory_cache obj_size > 128000 — u	    байтzCmfCache:inmemory_add add key r    rs   rk   d     zInmemory cache error! key:z	 try_add:z exists:F)Zlastz"CmfCache:inmemory_add evicted key )rv   rw   r   	BaseModeldataclassesZis_dataclassr   r   r   r4   rM   r_   rS   r&   r<   r  r	  r
  rL  r  rM  rN  rQ  rR  r   r)   popitem)rV  rf   r   r  Zdetailr  r   Z	LRU_LIMITrW  Zevicted_keyr   r   r   r   r    sH    


zCmfCache.inmemory_addc              	   C   s   g }|dkr"t | jd i t_d S |D ]}|dd }tjrL|dd }ztjj	|}W n t
k
rv   Y q&Y nX || |tjkrq&tj| }|D ]}||d  qq&|s|rtjdt|t dg d S )	NrK   uS   CmfCache:inmemory_del Полный сброс inmemory_cache при REDISDB.flushdbr    r   rs   rk   rI   )rJ   skip_app_id)r4   rM   rQ  rR  r&   r<   rw   r  r	  r
  rL  r6   r$   r  delayed_redis_eventsrR   rS   r   getpid)rV  rJ   
from_eventZ
event_keysrf   r  r   rW  r   r   r   r     s*    



zCmfCache.inmemory_delrI   r8   c                    s6   | sd S | d   fdd}t tjd t| d S )NrJ   c                      s    t tjd  tj dd d S )Nz*CmfCache:on_inmemory_del event with keys: T)rc  )r4   r<   rM   r   r   r   rJ   r   r   handler-  s    z)CmfCache.on_inmemory_del.<locals>.handlerz&CmfCache:on_inmemory_del spawn handler)r4   r<   rM   geventspawn)data_kwargsre  r   rd  r   on_inmemory_del%  s    zCmfCache.on_inmemory_delc              
   C   s   zdt krt t _W n( tk
r< } z
W Y d S d }~X Y nX dt jkrTdt jd< nt jd  d7  < dt jkrzdt jd< tjrdt jkrg t jd< t jd | d S )Nr  inmemory_cache_hitrk   inmemory_cache_missr   Zinmemory_cache_hit_keysr  rV  rf   r   r   r   r   rU  5  s    




z#CmfCache.profiler_inmemory_data_hitc              
   C   s   zdt krt t _W n( tk
r< } z
W Y d S d }~X Y nX dt jkrTdt jd< nt jd  d7  < tjrdt jkrg t jd< t jd | d S )Nr  Zinmemory_cache_skiprk   Zinmemory_cache_skip_keysr  rm  r   r   r   rP  I  s    


z$CmfCache.profiler_inmemory_data_skipc              
   C   s   zdt krt t _W n( tk
r< } z
W Y d S d }~X Y nX dt jkrTdt jd< nt jd  d7  < dt jkrzdt jd< tjrdt jkrg t jd< t jd | d S )Nr  rl  rk   rk  r   Zinmemory_cache_miss_keysr  rm  r   r   r   rS  [  s    




z$CmfCache.profiler_inmemory_data_miss)NF)N)NN)N)N)r   )NN)F);r'   r%   r2   rB   rC   rD   rE   rM   r  rF  PROCESS_EVICTED_FLUSHr   rP   rj   rm   r   r   r   r   r   r   staticmethodr{   r   r   r   rc   r   r   r   r   r   r   r   r   r  r  r^   r  r  r   r$  r'  r  r  r*  r5  r>  rK  rS   classmethodr  r  r   r;   rj  rU  rP  rS  r   r   r   r   r<   K   s   
E
#	8
 H

R 
 i
+
.

r<   c                 C   sJ   t | }| D ]4\}}t|trztj|||< W q   Y qX q|S r   )r   r   rv   r{   r   r~   r   )ZlstZdctr   r   r   r   r   CustomJSONDecoderq  s    
rq  c                   @   s   e Zd Zdd ZdS )CustomJSONEncoderc                 C   s   znt |tjtjfr|j}t |tjs2t |tjrP|jsF| d W S | W S t |tj	rd|jW S t
|}W n tk
r   Y n
X t|S t| |S )NZ)rv   r   ZCmfDateTimer   rz   ru   dateZtzinfoZ	isoformatrx   iter	TypeErrorr   r   default)r   r   iterabler   r   r   rw  }  s    
zCustomJSONEncoder.defaultN)r'   r%   r2   rw  r   r   r   r   rr  |  s   rr  )Zstatic_folderZ	root_pathTZSEND_FILE_MAX_AGE_DEFAULT)SocketIO	Namespace)RedisManager)Clientro   c              
   C   s   dd dD D ]v}t j|| }tj|s:tj||}ztj|sLW qW n" tt	fk
rp   t j
 Y nX t jj|dd  S tjD ]$}|| }|rt jj|dd  S qt jdS )Nc                 S   s   g | ]}t jtj|qS r   )r   pathr   rL   PROJECT_DIR)r   dr   r   r   r     s     zsend_static.<locals>.<listcomp>)zcustom/static/zcommon/static/zcmf/static/zdist/cmf-angular/T)Zconditionalzdist/cmf-angular/index.html)flaskZhelpersZ	safe_joinr   r}  isabsr   isfilerv  
ValueErrorZ
BadRequestZ	send_filerQ  HOOK_STATIC_NOTFOUND)Zreq_filenameZ	directoryfilenamehookr   r   r   send_static  s    
r  c                   @   s   e Zd ZdZdejdddZdd Zedd	 Zed
d	 Zedd Z	edd Z
edd ZedddZedd Zedd ZdS )CmfRedisMemoryWrapperut    Если есть self.redis - используется он
        Если нет - нужен фолбэк
    N)redisc                 C   s   || _ i | _d S r   )r  
memstorage)r   r  r   r   r   r     s    zCmfRedisMemoryWrapper.__init__c                    s    fdd}|S )Nc                    s6   | j rt| j  j||S td | f||S d S )Nu&   Redis memory wrapper запрещен!)r  r   r'   CmfAbortErrorr   r*   r   r   wrapper  s    z/CmfRedisMemoryWrapper.fallback.<locals>.wrapperr   )r*   r  r   r  r   fallback  s    zCmfRedisMemoryWrapper.fallbackc                 O   s   t d S r   NotImplementedErrorr   r   r   r   r     s    zCmfRedisMemoryWrapper.smembersc                 O   s   t d S r   r  r   r   r   r   r     s    c                 C   s   | j |S r   r  r^   )r   rf   r   r   r   r^     s    zCmfRedisMemoryWrapper.getc                 C   s   | j   d S r   )r  clearrT   r   r   r   rP     s    zCmfRedisMemoryWrapper.flushdbc                 C   s$   | j |d}||7 }|| j |< |S )Nr   r  )r   rf   amountrz   r   r   r   rF     s    
zCmfRedisMemoryWrapper.incrbyrk   c                 C   s   |  ||S r   )rF   )r   rf   r  r   r   r   incr  s    zCmfRedisMemoryWrapper.incrc                 G   s$   d}|D ]}|| j kr|d7 }q|S )Nr   rk   r  )r   namesrnr   r   r   r     s
    

zCmfRedisMemoryWrapper.existsc                 C   s   || j |< d S r   r  )r   rf   rz   r   r   r   r     s    zCmfRedisMemoryWrapper.set)N)rk   )r'   r%   r2   __doc__r  Redisr   r  r   r^   rP   rF   r  r   r   r   r   r   r   r    s&   






r  c                  C   s|  d ddd} t d d }zJztdt  trtdt  tj }d gtd< |jtt  |	 D ]}td|  |d	 d
krp|d 
 }t|g }|D ]T}|dkrttd|  td tjjjrq|r|t   d krtd qt   }dtjj_tddJ}z6t|tjtjB  td tjj  t d W n   Y nX W 5 Q R X dtjj_qtd|  t|d }|r|dd }	|	rt|	tt krtd| d|	  qtd|  d| d| d tj| |||d qqpW n\ ttfk
r$    Y nB t k
rd }
 z"td |
  t!"d |
  W 5 d }
~
X Y nX W 5 t d X qd S )!N)
handler_fnc                 _   s   zFt d|  d| d| d t  | ||W  5 Q R  W S Q R X W nN tk
r   t d|  d| d| d td|  d| d| d Y nX d S )NzRun server event handler z(*z, **)z+_spawn_server_event_listener handler error )r)   cmf_contextr   logging	exception)r  r   r   r   r   r   spawn_handler  s    "z3_spawn_server_event_listener.<locals>.spawn_handler   z._spawn_server_event_listener: listen channels z	Channels z__keyevent@7__:evictedz*_spawn_server_event_listener: got message r   messager9   u   WARNING! Сервер Redis выгрузил ключи из-за нехватки памяти. Если это происходит слишком часто, нужно увеличить память для Redis. Ключ: uT   Кеши больше не валидные, запускаем сброс кеша!<   skip_evicted_timerTz/tmp/eva-app_flushdb.lockwz;on_project_permission_change handler do CMF_CACHE.flushdb()rp   Fz7_spawn_server_event_listener: gevent.spawn got message rh  r`  zSkip event z skip_app_id=os.getpid()=zRUN gevent.spawn(z, data=z
, message=r  )r  rh  r  z#_spawn_server_event_listener error )#timesleepr)   r5   REDIS_DBr  pubsubZ	subscriber   Zlistenr]   r^   rw   appr   rn  openfcntlZflockZLOCK_EXZLOCK_NBrP   rR   r`   r$   r{   r   rb  rf  rg  
SystemExitKeyboardInterruptr   r  r  )r  r  r  r  r9   Zhandlersre  r*   Z
event_datar`  r   r   r   r   _spawn_server_event_listener  sh    







&r  c                   C   s   t t d S r   )rf  rg  r  r   r   r   r   spawn_server_event_listenerR  s    r  cache_settingsrw  r   r  Z	celery_dbZ	run_uwsgiu?   При работе через uwsgi обязателен Redisr   F)r  Zcors_allowed_originsloggerZengineio_loggerdbZunix_socket_pathzunix://z?db=zflask-socketio)r9   Z
write_onlyclient_managerzredis://ZusernameZpasswordrs   @ZhostportZ6379r#   message_queue)Payloadr[  )r  z/custom/org_name)rD   rE   )rE   u&   Неизвестный тип кеша)Zsystem_taskc               
   K   s`   t jD ]T}td z
|  W q ttfk
r6    Y q tk
rX   td|  Y qX qd S )Nscheduler_minutelyuJ   Ошибка выполнения периодической задачи )rQ  HOOK_CRON_MINUTELYr)   r  r  r   r  r  )ri  taskr   r   r   r    s    

r  c                 C   s   t |  t t  t| tr||  }t| j	| j
| jt d|_d|_tjdd|jd< d|jd< d|jd	< |S t }d
|d< d|d< t| |d< t |d< t|}d
|_tjdd|jd< d|jd< d|jd	< |S d S )N)coder   description	tracebackapplication/jsonOriginr   Access-Control-Allow-Origintrue Access-Control-Allow-CredentialsContent-Type, x-ijtAccess-Control-Allow-Headersr\  r  zUnknown errorr   r  r  )r  r2  r  
format_excrv   r   Zget_responserR   rS   r  r   r  rh  content_typerequestheadersr^   rA   r{   Zjsonifystatus_code)r   Zresponser   r   r   handle_exception  s4    






r  Zjwt_rsazjwt_rsa.pub)RSAcmf_deletedrg_member_ofZdefault_projectZemailZphone
user_localZphone_internalZprimary_roleZonline_statusZvacation_startZvacation_endZon_vacationactivitydoes_not_workZis_admin
is_supportservicedesk_allowZ
first_name	last_nameztwo_factor.two_factor_optc                 C   sP   t js
d S ztjs&tjjdtjdt_W n  tk
rH   t	
d  Y nX tjS )Nz.CmfPerson:00000000-0000-0000-0000-000000000001r   r   zapp.system_person() error)rL   AUTH_ENABLEDrQ  system_personr   	CmfPersonr^   current_person_fieldsr   r  r  rT   r   r   r   r    s     
r  c            
      C   s  t jdrt jd} n^t js$dS ztt j}W n  tk
rT   t	
d Y dS X |dkrbdS t|tov|dd} | sdS t| }|jdsdS dt_t|jd	dgd
 }|rt|dkrdS |jdd }|sdS td| }r| \}}ndS |dks$|dks$|dkr,tj}nR|dksT|dksT|dksT|dkr\tj}n"|dksp|dkrxtj}ntj}t|tjjsdS d|kr|j|j d| ddgd}	n|j|ddgd}	|	sdS |t|	j krdt_!|	t_"dS )u  
    Проверяем, что пользователь пришел из share-ссылки
    Если идёт обращение к /files, то проверяем Referer
    Т.к. jsurl передаётся только в апи для других ендпоинтов не смысла путаться парсить body
      Вообще, для API тоже лучше использовать реферер, тогда не придётся по два раза парсить json
    Выставляем:
     - g.sharelink_access_request = True, если пользователь пришел по /share ссылке
     - g.sharelink_access_granted = True, если проверка hash прошла
     - g.sharelink_access_obj = объект, по которому проверяли ключ. Используется в API для доп.фильтрации
    /filesZRefererNu{   _check_sharelink_access не смогли распарсить request.data для проверки прав доступаjsurlro   z/share/Tr   r      r#   r   z*^(?P<obj_type>[^:-]*)[:-](?P<obj_code>.*)$docZDOCCmfDocumentZflZFLZIN_WORK	CmfFolderCmfListZEPIr)  rs   r   sharelink_hashr  )r  r   )#r  r}  rl   r  r^   rh  ujsonr`   r   r  r  rv   rA   r   r  sharelink_access_requestr   Zqueryr   r&   rematchgroupsr   r  r  r  r   rw   Z	CmfEntityr   r{   r  sharelink_access_grantedsharelink_access_obj)
r  Zjson_resr,   Z
hash_paramZobj_keyr  r  Zobj_coder  r   r   r   r   _check_sharelink_access  s^    
(
r  c                 C   s   | t _t jS )uh   !!! Эта функция не меняет контекст, только инициализирует.)r  _current_person)personr   r   r   set_current_person[  s    r  c                 C   sJ   t | dd }|dkr| jS tjs$d S |d k	r0|S td tjtjd d S )Nr  ZFAIL_recursionz#Warning!!! Lazy Calc Current PersonrG   )	r   r  rL   r  r)   r  print_stackrN   stdout)r   Zcpr   r   r   current_persona  s    r  c              	      s   zt jstjjdgd}|jsztjj J dd l	}dd l
|j|j  d fddtdD |_|  W 5 Q R X |jt _W n  tk
r   td  Y nX t jS )	Napp_keyr   r   ro   c                 3   s   | ]}  V  qd S r   )choice)r   r   Zalphabetsecretsr   r   r/  {  s     zapp_key.<locals>.<genexpr>    zapp.app_key() error)rQ  r  r   CmfGlobalSettingsr^   rw   r  r	  disable_aclstringr  Zascii_lettersdigitsr   rangesaver   r  r  )r   Zsettingsr  r   r  r   r  q  s     
r  c              	   C   s   t | dd d k	r| jS ztjs4tjjddtjdt_tj| _| jstjj	ddd}|
  zPtjjddtjd| _| jstjj  tj| j| _W 5 Q R X t  W 5 |  X | jW S  tk
r   td  Y nX d S )	N_anonymous_userzanonymous@evateam.ruTr  Zinclude_deletedr   zcreate-anonymous-user-lockr  timeoutzapp._anonymous_user() error)r   r  rQ  r   r  r^   r  r  r  lockacquirereleaserw   r  r	  r  system_dataZcreate_anonymous_userr  ddcommit_all_dsr   r  r  r   Z
redis_lockr   r   r   anonymous_user  s8      

r  c              	   C   s   t | dd d k	r| jS ztjs4tjjddtjdt_tj| _| jstjj	ddd}|
  zPtjjddtjd| _| jstjj  tj| j| _W 5 Q R X t  W 5 |  X | jW S  tk
r   td  Y nX d S )	N_sharelink_anonymous_userzsharelink-anonymous@evateam.ruTr  z$create-sharelink-anonymous-user-lockr  r  z%app._sharelink_anonymous_user() error)r   r  rQ  r   r  r^   r  r  r  r  r   r  rw   r  r	  r  r  Zcreate_sharelink_anonymous_userr  r  r  r   r  r  r  r   r   r   sharelink_anonymous_user  s<      

r  c              	   C   s   t | dd d k	r| jS ztjjddtjd| _| jstjj	ddd}|
  zPtjjddtjd| _| jstjj  tj| j| _W 5 Q R X t  W 5 |  X | jW S  tk
r   td  Y nX d S )	N_test_guest_userztest-guest@evateam.ruTr  zcreate-test-guest-user-lockr  r  zapp._test_guest_user() error)r   r	  r   r  r^   rQ  r  r  r  r  r   r  rw   r  r	  r  r  Zcreate_test_guest_userr  r  r  r   r  r  r  r   r   r   test_guest_user  s4      

r
  c              	   C   s   t | dr t| dd d k	r | jS tjjdgd| _| jstjj	 8 ddl
m} |  tjjdgd| _| jsxtdW 5 Q R X | jS )N_global_settingsr   r   r   )init_global_settingsu6   CmfGlobalSettings не инициализирован.)r  r   r  r   r  r^   rw   r  r	  r  cmf.system_datar  AssertionError)r   r  r   r   r   global_settings  s    r  c                 C   s:   t | dr t| dd d k	r | jS tjjddgd| _| jS )N_global_varZaccount_sync_statusZaccount_sync_lastr   )r  r   r  r   ZCmfGlobalVarr^   rT   r   r   r   
global_var  s    r  lineno   c                 C   s6  |  tddtddf} | j|dd}td|  t|d | dD ]\}}|jd }tj	|j
tjd	d  }td
|||j|jd f  t|j
|j }|rtd|  |j D ]}	t|	 qqJ||d  }
|
rtdd |
D }tdt|
|d f  tdd |D }td|d   d S )NFz<frozen importlib._bootstrap>z	<unknown>T)Z
cumulativezTop %s linesrk   r   z#%s: %s:%s: %.1f KiBi   z    %sc                 s   s   | ]}|j V  qd S r   sizer   statr   r   r   r/  (  s     zdisplay_top.<locals>.<genexpr>z%s other: %.1f KiBc                 s   s   | ]}|j V  qd S r   r  r  r   r   r   r/  *  s     zTotal allocated size: %.1f KiB)Zfilter_tracestracemallocZFilterZ
statisticsr)   	enumerater  r   sepr   r  r&   r  r  	linecachegetlinestripformatsumr   )ZsnapshotZkey_typelimitZ	top_statsr"   r  framer  lineZllotherr  totalr   r   r   display_top  s.    


r&  c              
   C   s  t jjjddd tjj| jtj	d}|sdd | j
ddD }tj|d	< tj|d
< tj|d< tjf |}|rd|_|jtj  d|_|jtj  |rd|_|jtjjdd t jj  |jdd W 5 Q R X t  |W  5 Q R  S Q R X d S )Nzcreate-current_person-lock
   r  )loginr   c                 S   s(   i | ] \}}| d s|dkr||qS )Zcmf_r   )rl   )r   r   r   r   r   r   
<dictcomp>4  s
   
  z+create_person_from_auth.<locals>.<dictcomp>Tr   	cmf_owner
cmf_authorrC  ZServiceDeskClient)r  )Z	only_data)rw   r  r	  ZCmfLockr   r  r^   r(  rQ  r  r   r  system_userr  r  r6   ZCmfPersonGroupZsupport_groupr  Z
user_groupr  r  r  r  r  )authr  is_servicedeskr  Zperson_valuesr   r   r   create_person_from_auth.  s,    



r/  c                     s  t jdkrdS t  t  t  dt_i t_	i t_
g t_tjddkt_ddlm  ddlm}    t_tjt_d	| d
ddt_dt_g t_g t_dt_dt_dt_dt_dt_dt_dt_ dt_!dt_"dt_#dt_$dt_%t j&'dt_(dt_)dt_*t+j+,t+j-j.t_/dd t_,tj/0 t_1dd t_0dt_2i t_3i t_4g t_5dt_6dt_7dt_8dt_9g t_:i t_;i t_<t= t_>i t_?g t_@dd fdd
}|t_AtBjCD  tEjFstGd dS t j&'drdS d}t j&'dst j&'drt jHdpt jHdpt jId}|r|'dr8|tJdd }tBjKL|}tBjKj|dtMjNd}tAd|dd  d| d |  |stOd!d"d#d$S t j&d%krtBjPjQtMjNd&}t j&'d'r.d(}d)t jRkrt jRd) }tS|}|stTd)|i}tUtEjV d*| }t jHd+d,|jHd-< d.|jHd/< d0|jHd1< |S |sht jWd2}t jWd3}	|rhtBjXY|\t_t_*n|	r|tBjZ[|	t_tjrtEj\otBjZjtjjj]d4}
tEj\r|
sdt_tjrhtjjj]t_d5d6d7dgd8d7dggd9d7tjjgg}tBjKj|tMjNd:}|r&|j^rhtAd;|j d< d}nB|
s6tjj_rPt`|
pBtjtjj_d=}ntjajbrht`tjdd>}t j&'d?pt j&'d@pt j&'dA}dBdC }|rd}|r|jj]t_tjrtjj_t_tjjc t_ndt_dt_dt_ tG| nT|s| r2tjd}te  tj%rtjf}dt_dt_dt_ tG| ndt_ tGtjg tjpt j&'dDpt j&dEkpt j&'dFpt j&'dGpt j&dHkpt j&'dIpt j&'drt jRdJdKkrt jhdLkpt j&'dMpt j&dNkpt j&'dOpt j&'dPrt jhdLkpt j&'dQr"t jhdLkp| rDt j&'dRrDtBjij p| rft j&'dSrftBjij pt j&'dTr|tjptklt j&}tjm}tjg}tBjCn  |stjrdS tj(rtjr|stod;tj dUS |r|jps|jqsto S tj(r|jpstEj\s|jqstodVS nttjr>|s>tod;tj dUS t j&d(krh|rh|jqsh|jprhtUdS |r~|jqstEj\sto S tj rto S tj*rtj*r }|r|S dS )WuJ  
    Должны вернуть Response or None
    Особенности поведения:
      В случае web запроса:
        - response - view не выполняется, сразу отправляем response
        - None - выполняем view
        - Exception(в т.ч. и abort) - обработчик выводит трейс клиенту
      Системный контекст(shell, celery, socket, other with cmf_context):
        - None, Response - нет разницы
        - Exception - прерывает выполнение.
    ZOPTIONSNFZ
run_pytest1r   r  )choicesro   Z0123456789abcdef   )r   z/servicedeskc                   S   s   t jS r   )r  _nowr   r   r   r   <lambda>      z before_request.<locals>.<lambda>c                   S   s   t jS r   )r  _dater   r   r   r   r5    r6  T)forcec           
         s   t tdd s| rވ  }tt|tj d d}tt|tj d d}tdi dt }|dd}|dd}|d	d}t	j
d
}	ttjd|	d| d| dd| d| d| d|| |  ddf|    t_d S )NrM   rU   rp   r  Zselect_countZselectr   r   insertmr#   z(+z)mszs zu zi t)r   rL   r{   roundr  debug_start	debug_nowr^   rA   r  r   r)   
request_id)
r8  messagesr   r   r  ZscZscsZscuZscir:  r1  r   r   r2    s,    "	zbefore_request.<locals>.debugz/memZOK/api/z/files/zX-Eva-TokenZAuthorizationtokenzBearer )api_token_hashr  r   zAuth API Token(z...): hash=z	, person=zInvalid API token  
text/plainr  /pub/webhookr   z/auth/not_authorizedr#   next_url/auth/signin?r  r   r  r  r  r  r  session_tokenaccess_token)r(  ORr  z==r  r(  filterr   u   Учётная запись u    заблокирована.)r  )r.  z/pub/apiz/docsz/sharec                   S   s   t jdpt jdS )Nr  /socket.io/)r  r}  rl   r   r   r   r   is_allow_public	  s    
z'before_request.<locals>.is_allow_publicz
/auth/sync)z/auth/invitez/auth/restore_passwordz
/auth/signz/servicedesk/auth/signz"/servicedesk/auth/restore_passwordz/auth/two-factormoderootz	127.0.0.1z/crm/forms/z/manifest.webmanifestz/app/assets/z/forms/z/js/z/pub/z/sso/z	/helpdeskuQ    заблокирована. Обратитесь к администраторуuU   У вас нет доступа. Обратитесь к администратору)sr  methodcheck_db_lockr   r  r  before_requestr  r  r  flagsremove_filesr   r   r^   Ztestr  Zrandomr2  r>  r=  r   r?  Zsave_only_data_hackalertdeferred_tasksr-  Zpublic_accessr(  Zis_guest_userZis_anonymousr  Zis_system_contextZdisable_notifyZimport_modeZinteractive_shellr  r  r}  rl   request_servicedeskr  sessionru   r   rn   r   r4  rt  r7  Zrelaxed_bz_python_mode	emit_listsocket_eventsserver_eventsr  Zjscache_timelifeZTEXCOM_ENABLE_GROWCACHE_HACKrM  rO  Zacquired_locksZacquired_lock_timignsr   r  Zfulltext_search_headlinesra  r2  r   CmfAccessListZinit_contextrL   r  r  r  r   r   r  Z
hash_tokenrQ  r  r   Z
CmfWebhookZget_token_personr   check_sso_redirectr   redirectAUTH_SERVER_URLZcookiesZ
CmfSessionZ
from_tokenCmfAuthZfrom_jwtZIS_AUTHORIZATORrz   r  Zjwt_is_supportr/  r  Zservicedesk_allow_auth_guestsZjwt_is_match_orgr  r  r  r,  Zremote_addrZ	CmfPluginZcheck_secretSTATIC_URL_REr  r  Zsetup_contextreject_responser  r  Ztfa_check_two_factor)r2  r2  Zauth_personZ	api_tokenrC  rH  r  qsrJ  rK  Z	real_authZ_filterZis_force_publicrP  Zanon_personZis_allow_without_authr   r   r1  r   rU  L  s   




  $


$











	 




"
rU  c                 C   s&   t jjddgdd}|r"|| S d S )Nr   zplugin.*F)r   Zdisabled)r   ZCmfAuthOpenIdPluginr^   Zlogin_redirect)rH  Zopenidr   r   r   r`  	  s    r`  c                 C   s   t jds"t jds"t jdkr4t| p*ddddS dt ji}| rJ| |d	< t|}tjrntt	j
 d
| }nt }|stt	j
 d| }t jdd|jd< d|jd< d|jd< |S d S )NrO  rA  rG  znot authorizedrD  rE  rF  rH  r  z/servicedesk/auth/signin?rI  r  r   r  r  r  r  r  )r  r}  rl   r   r,   r   r  rZ  ra  rL   rb  r`  r  r^   )r  paramsrf  r  r   r   r   re  	  s(    




re  c                   C   s   t   t  t  d S r   )r  r  emit_eventsemit_server_eventsr   r   r   r   commit_with_event	  s    rj  c               	   C   sN   t dsd S t j D ]*\} }td|d  |d|ddd qi t _d S )Nr\  is_changed-r   r#   r   private)	namespacer   )r  r^   r\  r   r   )r   r   r   r   r   emit_list_apply	  s
    
$rn  c                 C   s  |   D ]\}}|D ]}|d }|d= t|d }|d= |d  }z"t| t| t| W nJ tk
r } z,td| d| d| d|  W Y qW 5 d }~X Y nX t|ts|j	|f|d |d	|d	 i q|d
 r,|d
 dks,|d
 |d
< |j	|f|d |d	|d	 i q|
dr|d rd|d d krj||d d d  d|d d kr|d d d D ]}|| q|D ]r}	t|	tjjrtd|	 d| d| d|  |	jj}
nt|	}
|
|d
< |j	|f|d |d	|d	 i qqqd S )Nsocket_clientr   r   uP   DEV: FATAL emit пришел с несериализуемыми данными z! socket_client:z; event_persons:z; event_param:r   rm  r   rl  r   event_current_personr   Zrelation_personsuY   DEV: INFO Кривой евент, в event_person попал объект, а не str: r   )r   r   copyrR   rS   r   r)   rv   ry  rc   rl   r   rw   r   r]  r   rz   r{   )Z
event_dictmsgZevent_param_listZevent_paramro  r   Zemit_kwargsr   Zuser_idevent_personevent_persons_strr   r   r   emit_events_dict	  sF    


 
""
 
ru  c                  C   s&   t   tdpi } i t_t|  d S )Nr]  )rn  r  r^   r]  ru  )r]  r   r   r   rh  	  s    rh  c                    s:    fdd}t   tdp i i t_r6t| dS )u   Запускаемся в контексте, но отправляем в отдельном таске вне контекста, после паузы, чтобы не держать запрос.c                      s   t   t d S r   )rf  r  ru  r   delayr]  r   r   emitter	  s    
z'emit_events_with_delay.<locals>.emitterr]  N)rn  r  r^   r]  rf  rg  )rw  rx  r   rv  r   emit_events_with_delay	  s    ry  c                  C   sP   t dpg } g t _| D ]2\}}t d| d|  tj|t| qd S )Nr^  zemit_server_events: r0  )	r  r^   r^  r2  r  r  rQ   rR   rS   )r^  r9   rh  r   r   r   ri  
  s
    ri  c                   C   s   t   i t_d S r   )r  Zrollback_all_dsr  r]  r   r   r   r   rollback_purge_event
  s    rz  c                  C   s$   t dg D ]} |  }qg t _d S )NrY  )r  r^   Zapply_asyncrY  )Ztask_signaturer   r   r   r   apply_deferred_run_tasks
  s    
r{  c                  C   s2   t dg D ]} tj| rt|  qg t _d S )NrW  )r  r^   r   r}  r   r   rW  r  r   r   r   apply_deferred_remove_files 
  s    r}  c                 C   s   t jrtjt j|  dS )u   Сессия может быть продлена через SSO, надо продлить куку

    Args:
        r (response): ответ браузеру в котором обновляем куки
    N)r  r[  r   rc  Zset_session_tokenr  r   r   r   update_cookies'
  s    r  c                 C   sV   t   td t  t  t  t|  tj	dd| jd< d| jd< d| jd< | S )	uk   
    Запускается только если небыло ошибок
    :param r:
    :return:
    rp   r  r   r  r  r  r  r  )
r  r  ry  ri  r{  r}  r  r  r  r^   r~  r   r   r   acao2
  s    

r  c                
   C   sT   t js
d S t jt_t , tjj	  tj
jj  W 5 Q R X W 5 Q R X t  d S r   )rL   r  ZDISABLE_PERMISSIONSrQ  disable_permissionsr  rw   r  r	  r  includer   r_  Zload_acl_datar  r   r   r   r   app_init_aclF
  s    "r  c                
   C   sN   t tjjdsd S t , tjj  tjjj	  W 5 Q R X W 5 Q R X d S )NCmfProjectPermScheme)
r  rw   r  r   r  r  r	  r  r  Zload_project_permission_datar   r   r   r   app_init_project_permissionQ
  s    r  c               z   C   s&  t tddkrd S tj } tjj| d d}|  tj }|r|  |  |	ddddg |	d	d
ddddg |	ddddddddg |	ddg |	dddddddddd d!d"d#g |	d$g |	dddd%ddd&d'd(d)g
 |	dd*d+d,g |	d+d,g |	d-d.d$g |	d/g |	d-d0d1g |	d2d3d4ddd+d,d5g |	d6d7dd8g |	d9dg |	dd:g |	dd;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMd	d3dNdOdPdQd4ddRdSd6dTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzd{d|d}d~dddddddddddddddd&dddddddddddddddddddddddd5dgs |	dddg |	d;dddtdddddddddg |	dddddddg |	ddddddddddd d!dd"d#g |	dg |	ddd;d<d=d>d?d@dAdBdCdDdEdFdGdHdIddJddKdLdMd	d3dNdOdPdQd4ddRdSd6dTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddeddfdgdhdidjdkdldmdndodpdqdrddtdudvdwdxdyddzd{d|d}d~dddddddddddddddddddddddddddddddddddddddd5dgx dddgddddgdddggfD ].}|dddgg}tj
j|dddddgdÍ qtj }|r|  |  |	ddddg |	ddddddg |	d6ddddddg tj }|r|  |  |	ddg |	ddddg |	d	d3ddddddddddg tj }|r"|  |  d S )Nr~  z/opt/eva-appr   )r   r  Z
logic_typer   Z	scheme_wfr+  ZdealZordernozparent.root_parent_idZroot_parent_idr*  z
perm_acl.*zperm_acl.cmf_ownerz!perm_acl.object_ownerperm_inheritZperm_effective_acl_idZperm_has_aclZperm_inherit_acl_idZperm_parentZparent_logic_prefixz0parent.sl_allow_executor_change_nofatal_deadlinezparent.sl_deadline_shiftzparent.sl_deny_no_approvezparent.sl_only_owner_approvezparent.sl_task_need_approvezparent.sl_task_only_owner_closezworkflow.enable_sl_controlz2workflow.sl_allow_executor_change_nofatal_deadlinezworkflow.sl_deadline_shiftzworkflow.sl_deny_no_approvezworkflow.sl_only_owner_approvezworkflow.sl_task_need_approvez!workflow.sl_task_only_owner_closez+root_parent.task_code_use_logic_type_prefixZperm_inheritZperm_policyZperm_policy_anonymousZperm_policy_guestZperm_policy_sharelinkZcmf_owner_assistantszparent.cmf_ownerzparent.cmf_owner_assistantszlogic_type.obj_code_prefixzroot_parent.task_code_prefixz!parent.default_agile_story_pointszparent.task_code_prefixz&parent.task_code_use_logic_type_prefixZcache_status_typeZcmf_created_atrC  Zwaiting_forr  ZhrefZui_nameZop_gantt_taskZtree_parent_idZagile_story_pointsZ
alarm_dateZapprovedZattachmentszattachments.cmf_created_atzattachments.urlzattachments.url_previewzattachments.url_preview_imgZchild_taskszchild_tasks.activityzchild_tasks.agile_story_pointszchild_tasks.cmf_deletedzchild_tasks.is_checkedzchild_tasks.listszchild_tasks.logic_prefixzchild_tasks.parent_taskzchild_tasks.responsiblezchild_tasks.statusZcloned_fromr  Zcmf_locked_atZcmf_locked_byr   zcmf_owner.avatar_filenameZcmf_owner_idzcomments.cmf_authorzcomments.cmf_created_atzcomments.cmf_ownerzcomments.importantzcomments.likeszcomments.log_levelzcomments.parentzcomments.person_views.personzcomments.privatezcomments.spectatorszcomments.textzcomments.tree_parentZcompanyzcompany.is_internalZ
componentsZdeadlineZ	executorsZext_idZgantt_projectZgit_brancheszgit_branches.urlZgit_commitszgit_commits.urlZgit_merge_requestszgit_merge_requests.mergedzgit_merge_requests.urlZhas_child_tasksZin_tasksZ
is_checkedZis_milestoneZis_templateuA   link:/?popup=1&obj=${id}&uiModule=acl:Настройки правZlistszlists.logic_prefixzlists.parent.logic_prefixzlists.sys_typeZlocal_linksZlogic_prefixzlogic_type.ui_colorZ	main_listZmarkZ
no_controlzop_gantt_task.actual_completeZ	out_tasksZoutline_numberzparent.logic_prefixzparent.logic_typezparent.main_gantt_projectZparent_taskz#parent_task.cache_branch_gantt_pathzparent_task.logic_typeZperiod_clear_checkboxZperiod_create_newZperiod_intervalZperiod_next_dateZperm_encryptZplan_end_dateZplan_start_datepriorityZremaining_estimateZresponsibleZresult_textZ
spectatorsstatusZstatus_closed_atZstatus_review_atZtagsz
tags.colorz%tags.tag_category.ui_separated_widgettextZtime_estimateZ
time_spentZtimetracker_historyZtimetracker_is_runningZtmplt_documentZtree_parentZui_view_formr  Zworkflowzparent.ui_form_schemezresponsible.namezstatus.status_codezstatus.status_typezcmf_author.user_localzcmf_owner.user_localzexecutors.user_localzparent.cmf_owner.user_localzresponsible.user_localzspectators.user_localzwaiting_for.user_localzparent.sl_readonly_closed_taskz workflow.sl_readonly_closed_taskz=root_parent.security_level_scheme.default_task_security_levelZaffected_versionszchild_tasks.logic_type.ui_colorzchild_tasks.priorityZfix_versionsu`   link:/?popup=1&obj=${id}&uiModule=acl:Настройки уровней безопасностиZperm_security_levelZcache_action=r  rL  rD  Z	cmf_modelCmfTaskZjson_filterZjson_entry_pointZjson_actionZ	func_nameZ	json_datarM  r   Zsys_typezparent.codez	parent.idzparent.logic_type.namezparent.nameZ	log_levelzparent.activityzparent.logic_type_idzparent.scheme_wfZ	importantZlikeszperson_views.personrl  )r   rL   r   r  Zcreate_dummy_taskr^   Zdelete_dummy_taskZsave_prepareZ_load_perm_fieldsrJ  Z
CmfTriggerr   r  Z
CmfCommentZ	CmfNotify)Zdummy_task_dataZ
dummy_taskr;  Z_fr#  cr  r   r   r   prepare_plan_cacheX
  sj    

$"($

"
r  c                   C   s6   t   t  t  t  tjr&t  tjr2t	  d S r   )
r  before_first_requestr  r  r  rL   WHATSAPP_MESSENGER_URLspawn_messenger_socketio_clientWHATSAPP_WEB_SOCKETspawn_whatsapp_socketio_clientr   r   r   r   r  
  s    r  c                 C   s   t j| d d S Nr  )r  r  r  r   r   r   teardown_request
  s    r  c              
   C   s   t d| d|d|d| |r0tjs0dS |dk	rH|tj krHdS |rrdt }t d|  t| | t j	krt j	
|  dS )u   
    Глобальная функция для оповещения фронта о предупреждениях
    :param msg:
    :return:
    zcmf_alert: msg=z abort=z debug_only=z devel_only=Nr   zcmf_alert Stack:
)r  r2  rL   rM   Z
PRODUCTIONr   r  format_stackr  rX  r6   )rr  r   r   Z
devel_onlyZ	stack_strr   r   r   r   
  s    "

r   rl  )rm  ro  r   r   c             
   O   s  |st }zdtkrt t_W n( tk
rD } z
W Y d S d }~X Y nX t|dkrldtjrdtjjjpfd ig}t	|d tkrdtkrtj
|d d< nd|d d< tjrtjjjpd |d d< t||||d}t| ||d< d	}	d
D ]}
| |
rd}	 q q|	rtdt   |s:tjg}|	s:tdt   g }|D ]4}t|tjjrf||jj n|t| qB||d< t|d  tj| g }||kr|| d S )Nr]  r   rY   session_tab_idro   rp  )r   r   rm  r   ro  F)
zevent-r(  ztask-comment-zaudit-task-comment-znotify-person-rk  zcomment-z	notify-osznotify-important-ZDEBUG_TuC   DEV: WARNING в cmf_emit_event не указали cmf_emit_event: u   DEV: FATAL!!!!!!!!!!!!!! Добавьте меня в спинт Баги реактивности. 10.10.2022 в cmf_emit_event не указали cmf_emit_event: r   )socketior  rA   r]  r   r   r  r   rz   r   r  rR   rS   rl   r)   localsr   rv   rw   r   r]  r6   r{   
setdefault)rr  rm  ro  r   r   r   r   r   Zevent_paramsZmutedZ
muted_debtrt  rs  Z
event_listr   r   r   r   
  sL    


r   c                 C   s"   dt krg t _t j| |f d S )Nr^  )r  r^  r6   )r9   rh  r   r   r   cmf_emit_server_event
  s    r  c                 C   s  |rd |nd}|rdnd}	|r&dnd}
d |	|| |
g}|rRddlm} | }tj|dtjtjd	}|r| \}}|r| }| }|j}|r|rt	d
| t	d| t	d| t
d| |g}|r|| || n||p| |r|| |  |S dS )u  
    :param command: собственно, команда которую необходимо выполнить
    :param sudo: необходимо ли команду выполнять от рута
    :param timeout: секунд на выполнение. Дальше команда получит SIGTERM.
    :param wait: True дождаться окончания выполнения команды, False запустить и забыть, вернёт (None, None)
    :param separate_out_and_err: отдельно stdout, отдельно stderr, иначе не ясно как это всё парсить
        False по умолчанию, чтобы никому ничего не сломать.
    :param do_decode: возвращать декодированные строки вместо байт
    :param do_raise: выбрасывать исключение в случае, если код возврата != 0 (удобно для логирования трэйсбэков)
    TODO: почему u''? Наследие python2 и биллинга или реальная необходимость?
    TODO: Можно перейти на f'{sudo}bash -c export BLA=BLA;{timeout}{cmd}{redirect}', читается лучше
    ztimeout -v {0} ro   zsudo z 2>&1z0{0} bash -c "export BOOTUP="noncolor";{1}{2}{3}"r   r1  T)shellr  rO   u6   Произошла ошибка при вызове %sz
STDOUT: %sz
STDERR: %su4   Произошла ошибка при вызове )NN)r  r  
subprocessPopenPIPEZcommunicater]   
returncoder  errorRuntimeErrorr6   )ZcommandZsudor  waitZseparate_out_and_errZ	do_decodeZdo_raiseZmeasure_runtimeZtimeout_cmdZ_sudoZ	_redirectcmdr  Zpopen_startZprocessouterrZerrcoderX  r   r   r   run_bash_command  sH    
r  c                 C   sL   t tj}t }||   ||}t	|
 }|  d| }|S )ua   
    Подписываем токен сертификатом
    :param jwt:
    :return:
    r    )r
   rI  rQ  rsa_private_keyr	   r   r   signbase64	b64encoder]   )jwtZsignerZdigestr  r   r   r   r   rsa_sign_pack_jwt:  s    
r  c                 C   sH   ddd}t t|  }t t|   } | d|  S )uD   
    Создаем токен
    :param payload:
    :return:
    ZRS256ZJWT)Zalgtypr    )r  r  rR   rS   r   r]   )payloadheaderr   r   r   
create_jwtI  s    
r  c                   C   s   t jS )u2   
    Текущая версия
    :return:
    )rL   ZCMF_VERSIONr   r   r   r   cmf_get_versionU  s    r  c                 C   s   | t jkrt j|  dS )ux   
    Удаления файлов после коммита транзакции
    :param filename:
    :return:
    N)r  rW  r6   r|  r   r   r   cmf_remove_file]  s    
r  c                   @   s,   e Zd Zd
ddddZdd Zdd	 ZdS )r  FNr=   c                 C   s   t d| _|| _d S )Nz/with-context)rQ  Ztest_request_contextctxinit_views_and_ds)r   r  r   r   r   r   h  s    zcmf_context.__init__c                 C   s*   | j   | jrt  t  t  d S r   )r  	__enter__r  start_viewsr  Zinit_dsrQ  Zpreprocess_requestrT   r   r   r   r  l  s
    
zcmf_context.__enter__c                 C   s<   t j|d |s(t  t  t  t  | j||| d S r  )r  r  rh  ri  r{  r}  r  __exit__)r   excrz   r  r   r   r   r  s  s    zcmf_context.__exit__)F)r'   r%   r2   r   r  r  r   r   r   r   r  g  s   r  c                  C   s   ddddddg} t jdd | D  }|D ]\}}}|tjd	}|d
r(|D ]\}|dsf|drN|dsNddd |dD }t	j
|d |dd  d d qNq(tjddtd tjddtd tjddtd d S )Nz	cmf/viewszcmf/modulescommonmoduleszcustom/commonzcustom/modulesc                 S   s&   g | ]}t jtj d | ddqS )r#   T)followlinks)r   walkrL   r~  )r   Z
search_dirr   r   r   r     s   zstart_views.<locals>.<listcomp>ro   z/viewsz.pyz.pycz__init__.pyr    c                 s   s   | ]}|r|V  qd S r   r   )r   r   r   r   r   r/    s      zstart_views.<locals>.<genexpr>r#   r   )packagerR  )r   Z	view_funcz/<path:req_filename>Zdistz/static/<path:req_filename>Zstatic)	itertoolschainr   rL   r~  r   rl   r   r&   	importlibimport_modulerQ  r(   r  )Zsearch_dirsZsearch_iterdirnamedirnames	filenamesr  r+   r   r   r   r  }  s$    

$  r  rp   c                 K   s4   t j| ||d}|jf d|i| tj| |S )N)r   r   	countdown)celery	signaturer   r  rY  r6   )r  r   r   r  r.   r  r   r   r   cmf_deferred_task  s    r  c                   C   s*   t jdd d kr&ttjdddg d S )NSOCKETIOZworkerz--poolrf  )r   r   r^   rf  rg  
celery_appZworker_mainr   r   r   r   spawn_task_worker  s    r  c                  C   s*   dd } t jdd d kr&td|  d S )Nc               	   S   sJ   ddl m}  t  | tdd  W 5 Q R X tdtjd td d S )Nr   Beatztmp/celerybeat-schedule)r  ZschedulezBeat die!!! Stop worker.rG   rk   )	Zcelery.apps.beatr  r  r  runr)   rN   rO   exitr  r   r   r   run_beat  s
    z&spawn_task_scheduler.<locals>.run_beatr  r  )r   r   r^   rf  Zspawn_later)r  r   r   r   spawn_task_scheduler  s    r  c                  C   s"   dd } t jrtj| dgd d S )Nc                 S   s2   i }t jdd rdtji}tjtj| |d d S )Nr  r   
namespacesr  )r   r   r^   rL   ORG_NAMEwhatsapp_sioconnectr  r  r   r   r   messenger_connect  s    
 z:spawn_messenger_socketio_client.<locals>.messenger_connectz	/whatsapp)r  )rL   r  rf  rg  )r  r   r   r   r    s    r  c                   C   s   t tjtj d S r   )rf  rg  whatsapp_go_sior  rL   r  r   r   r   r   r    s    r  c                  C   s<   dd l } tdtj dtj  | jtjtjdddd d S )Nr   uY   Подключаемся к удаленной отладке config.REMOTE_DEBUG_SERVER=z config.REMOTE_DEBUG_PORT=TF)r  ZstdoutToServerZstderrToServerZsuspend)pydevd_pycharmr)   rL   ZREMOTE_DEBUG_SERVERZREMOTE_DEBUG_PORTsettrace)r  r   r   r   cmf_pycharm_debug  s     r  r=   c                  C   sH   t tjtjttt ttt d tjj	dd} t
| }t|S )Nr  Zguid)ZissZorg_nameZiatZexpr  Zjti)rA   rL   ZAPP_FQDNr  r{   r|   r  r  r  rz   r  r  )r  r  r   r   r   gen_eva_app_token  s    r  )urirh  c           
      C   s   ddl m} tjrtjdkrPttj|d }|dg }|di }|||}n| }ddd	d
|_tj	 |  }t
 |d< |j|t|d}	|	jdkrtd| d|	j d|	j |	 }|rd|krtd| t| |S )Nr   )r[  FalserS  r   r   r  rE  r   )zContent-typeZAcceptzContent-EncodingZeva_app_token)rh     u9   Не удалось отправить запрос, url=z, status_code=z, res=r  u(   Сервер вернул ошибку: )Zrequestsr[  rL   ZEVA_ACCOUNT_USEr   r   rc  r^   r  rb  r  ZpostrR   rS   r  r   Zcontentr  r2  )
r  rh  r[  rS  Zmethod_argsZmethod_kwargsresultr   r,   r   r   r   r   call_eva_account  s.    


r  Zeva_db_upgrade_runningc                 C   s6   | st t } tjjt| ddds2tdt dS )u   Запускается перед миграций БД. Информирует приложение, что не следует открывать транзакции.r  T)exZnxzCannot lock N)r{   r   rb  r  r  r   _DB_LOCK_KEYCmfError)rz   r   r   r   app_db_upgrade_start  s    r  c                   C   s   t jt dS )u   Запускается после миграций БД. Информирует приложение, что можно продолжать работать.N)r  r  ra   r  r   r   r   r   app_db_upgrade_stop   s    r     c                 C   s^   dd }d}t   }| rZ| r.t   | |krF|rBtdt ndS |d7 }t d qdS )u   Проверяем не заблокировано ли использование БД, если заблокировано, то можем дождаться разблокировки.c                   S   s,   t rt t  dkr(tjtat a tS )uW   используем кеш 1sec, чтобы часто не ходить в редисrk   )_db_lock_cache_tsr  r  r  r^   r  _db_lock_cacher   r   r   r   
check_lock  s    z!check_db_lock.<locals>.check_lockr   z
DB locked Frk   T)r  r  r  r  )r  r  Zraise_errorr  rW   startr   r   r   rT    s    rT  )NN)ro   )r  r  )FF)N)N)r   )N)FFN)TNTFFFF)NNrp   )N)Tr  T)r^  r  r_   rN   r  r  Zcalendarru   r  r  r  rE  r   r   pathlibr   Zurllib.parser   r   r   r   r  r   rf  r  ZCrypto.Hashr	   ZCrypto.Signaturer
   r  r   r   Z
flask.jsonr   Zwerkzeug.exceptionsr   rw   r   Zcmf.includeZcmf.data_providersr   r  r  r  compilerd  r   r4   r   r5   r;   objectr<   rq  rr  r'   rL   r~  rQ  Zjson_encoderr  r  r  r  ZHOOK_CRON_HOURLYZHOOK_CRON_DAILYZHOOK_CRON_WEEKLYZHOOK_CRON_MONTHLYr  Zcache_in_project_roleZflask_socketiory  rz  r  r{  r|  r  r  r  r  r  r  r  r  rq  Zcfgr$   r  r   r   r^   r   rM   Zsocketio_kwargsr  r,   r  r  Zengineio.payloadr  Zmax_decode_packetsr  r  r}  r   r  r*   readr  r  r   ZREDIS_DB_IDZREDIS_DB_ID_TIMERr  r  r  Zerrorhandlerr  Zregister_error_handlerZprivate_key_pathZpublic_key_pathZCrypto.PublicKeyr  Z
import_keyZ
read_bytesr  Zrsa_public_keyr  r  r  r  r  r  r  r  r
  propertyr   r  r,  Zcurrent_userr  r  r&  r/  rU  r`  re  rj  rn  ru  rh  ry  ri  rz  r{  r}  r  Zafter_requestr  r  r  r  r  r  r   r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r{   r  rA   r  Zcache_notify_scheme_ruleZcache_person_notify_optrR  r  r  r  r  r  rT  r   r   r   r   <module>   s  

	          0

;U 


	 


	


!

                b "


  L

1

B

9    
5


