U
    d                    @   sv  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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%G dd de,Z,dd Z-G dd de.Z/dd Z0G dd de"Z1e,e2de3j4dZ5e1e5_6de5_7de5_8g e5_9g e5_:g e5_;g e5_<g e5_=g e5_>de5_?d e5j3d< d dl@mAZAmBZB d dlCmDZD d dlCmEZE d dlFZFddd ZGG d!d" d"ZHeH ZIeeJZKd#d$ ZLd%d& ZMdd'd(ZNeOe3d)rte3jPd* d+ d,krte3jPd* Q ZReRSd+ eFjTf eReI_FeUjVWd-reIjFdkreXd.e5d/e3jYd0d1ZZeOe3d)re3jPd* d+ d,kre3jPd* d2 Z[e3jPd* Wd3rd4e3jPd* d3  d5e[ Z\eDe\d6d0d7Z]e]eZd8< nrd9Z^d:e3jPd* krFe^d;e3jPd* d:  d<7 Z^e^e3jPd* d= 7 Z^e^d;e3jPd* Wd>d? 7 Z^e^d@e[ 7 Z^e^eZdA< d dBl_m`Z` dCe`_aeAf eZZCeEe3jYdDZbeEe3jYdDZceUjdee3j4dE refe3j4dE Zgegh i e3_jW 5 Q R X eOe3d)rRe3jPd* d+ d,kr(e/eIjFdFZkn(e3jPd* d+ dGkrHe/ddHZkneXdIne/ ZkeIe5_IdJdK Zlel ZmemjndddLdMdN Zoe5peXdOdP Zqe5reXeq ee3j4dQ Zsee3j4dR Ztd dSlumvZv ese revwesx e5_yete revwetx e5_zdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcddge5_{dedf Z7dgdh Z|didj Z}dkdl Z~dmdn Z8dodp Zdqdr Zdsdt Zee7ee_7ee7ee_eeee_eeee_eeee_ee~ee_~ee~ee_ee8ee_8dudv Zeeee_dwdx Zeeee_dd{d|Zdd}d~Ze5jdd ZdddZdddZdd Zdd Zdd Zdd ZdddZdd Zdd Zdd Zdd Ze5jdd Zdd Zdd Ze5jdd Ze5jdddZdddZd@ddg dddZdd ZdddZdd Zdd Zdd Zdd ZG dd dZdd ZdddZdd Zdd Zdd Zdd Zdd ZedÜddńZeedƜddȄZdS )    N)OrderedDictdefaultdict)Path)urlparseparse_qs	urlencodequote)Celery)SHA256)
PKCS1_v1_5)abortResponse)JSONEncoder)HTTPExceptionfields)*)basec                       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   r0   r/   r1   r   r.   r   route(   s    zFlask.route)r(   r&   __qualname__r   r2   __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    r5   c                   @   sb  e Zd ZdZdZdZdZdZdZdZ	dJddddZ
dd Zdd	 Zd
d Zdd ZdKd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dLddZd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- ZdMd.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+dNdFdGZ,dHdI Z-dS )OCmfCacheNFreturnc                 C   sB   t  | _t  | _|| _|| _| jr>| jdd | jdd d S )Nstat_hitr   	stat_miss)dict	cache_objcache_invalidateredis_dbmemoryincrby)r   r>   r?   r   r   r   r   H   s    zCmfCache.__init__c                 C   s>   t tjp| jdtjd | jr*| j  nt | _t | _	d S )NzCmfCache.flushdb!!!file)
r5   configDEBUGsysstderrr>   flushdbr;   r<   r=   r   r   r   r   rG   R   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!!!rA   zobj:jshash:*  countz"CmfCache.flush_jscache invalidate z!!!   Ncurrent_person_idjsver)r5   rC   rD   rE   rF   r   r;   r>   pipeline	scan_iterdecodegetpickleloadsdeleteexecuteemit)r   emit_msgpipekeyjshashjsresjspersonr   r   r   flush_jscacheZ   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!!!rA   r   zobj:*rI   rJ   s
   obj:jshash   zCmfCache.flush_all_obj: z recordsN)r5   rC   rD   rE   rF   r>   rO   rP   
startswithrU   rV   )r   rK   rY   rZ   r   r   r   flush_all_objl   s    

zCmfCache.flush_all_objc                    s0  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	}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datetimerb   
isinstancecmfr   CmfType
is_definedvaluestrintfloatparserparseZ
astimezoneutcreplace	Exceptionlistr;   itemstyper(   md5rS   dumps	hexdigest)valdateutilrb   resZval1evk_all2strhashlibr   r   r   ~   s<    


&zCmfCache.hash.<locals>._all2strrL   Z0781|idz|id:rg   zHASH:i  z|md5:
zDEBUG_CACHE HASH:)r   rz   ro   rk   r   CmfDatenowencoder|   sortedrx   rD   ru   r5   )r   prefixr   r   sr}   rZ   r   r   r   hashz   s&    +2&zCmfCache.hashc           	      C   s   |d krt  }|s|S ||j tt|j}|j D ]}t||jsJq8t	|t
jjrzt||jd }|r| j||d q8t	|t
jjt
jjfr8t||jd }|r|D ]}| j||d q| D ]"}d|j d|j }|| qq8|S )N)r   ref__)setaddr   getattrmodels
class_namer   valueshasattr
issubclassrk   CmfRelationBasesimple_objects_id_recursive
CmfM2MBaseCmfBackrefBaserelated_models)	r   objr   ZmodelZ	field_clsZfield_valuerel_obj	rel_modelrefr   r   r   r      s,    z$CmfCache.simple_objects_id_recursivec                 C   s   |sg S |j jg}|jddD ]}t|tjjrB|| |j t|tjj	tjj
fr|jrz|jD ]}|| | qd| D ]"}d|j  d|j }|| qqtt|}|S )u   
        Собираем ид связанных обьектов 2 уровня для настройки инвалидации
        :param obj:
        :return:
        Trm   r   r   )r   rn   r   rj   rk   r   r   extendobjects_id_recursiver   r   r   r   appendrw   r   )r   r   r   fieldr   r   r   r   r   r   r      s    

zCmfCache.objects_id_recursivec                 C   s   t |}t|tjkrd}t|tjjs4t	
|r@d| }nJ|rt|trt|d tjjsnt	
|d rd|d j dt| d}tdt| d| dd	 d
S | jr| jd| | dS | jr|| j|< dS d S )Nrc   , r   []uR   DEV: Слишком большой объект для кэширования — u	    байтT)
debug_onlyFobj:)rS   r{   lenrC   ZCACHE_MAX_OBJ_SIZErj   rk   r   	BaseModeldataclassesZis_dataclassrw   r   	cmf_alertr>   r   r?   r<   )r   rZ   r}   Zstr_valZdetailr   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   r>   existsr   r?   r<   rR   )r   keysZhkeysrZ   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   r9   r:   )r>   rR   r@   r?   r<   r   rZ   r   r   r   r   _obj_dict_get  s    zCmfCache._obj_dict_getr[   inv_payloadc                 C   s   |  d| S )N::r   r   r   r   r   %_jshash_invalidate_confirm_member_key$  s    z.CmfCache._jshash_invalidate_confirm_member_keyZ
member_keyc                 C   s   | j dddS )Nr   r_   )maxsplitr'   r   r   r   r   +_jshash_invalidate_confirm_member_key_split(  s    z4CmfCache._jshash_invalidate_confirm_member_key_splitc                 C   s    | r| n| dd }d| S )Nrg   zjscache-invalidate-confirm-set:r   )cache_idr[   set_keyr   r   r   "_jshash_invalidate_confirm_set_key,  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:r[   )
r   rw   rx   cmf_emit_eventr`   r   r   r   r>   sadd)	r   ZmsgsZconfirmations	person_idinv_dictr[   r   r   confirm_listr   r   r   rW   3  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   r_   )r>   r   rw   r   r   srem)r   Zconfirm_dictZsample_jshashZkey_cache_idr   Zconfirmr   r   r   jshash_invalidate_confirmB  s    
z"CmfCache.jshash_invalidate_confirmc                    s.    j r* |} fdd j |D S d S )Nc                    s   g | ]}  | qS r   )r   rQ   ).0memberrH   r   r   
<listcomp>S  s   z;CmfCache.jshash_invalidate_confirm_list.<locals>.<listcomp>)r>   r   smembers)r   r   r   r   rH   r   jshash_invalidate_confirm_listN  s
    


z'CmfCache.jshash_invalidate_confirm_listc              	   C   s  |sd S | j r| j jdd |D   i }|D ]}| jrPd|krPtd|  t| jd|  | j d| }|r.t| 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r.t
 ||
< |dkrZdtdd |jddD }nd}|	d  d| d| d| }|||
 |< | j d|  q| j d|  | | q.n.| jr|D ]}|| jkr| j|= qnd S d S )Nc                 S   s   g | ]}d | qS )r   r   r   rZ   r   r   r   r   [  s     z+CmfCache._obj_dict_mdel.<locals>.<listcomp>rK   z#DEBUG_CACHE JSHASH: try invalidate z*DEBUG_CACHE JSHASH: try invalidate:jshash:zinvalidate:jshash:z*DEBUG_CACHE JSHASH: got invalidate:jshash:z#DEBUG_CACHE JSHASH: got invalidate utf-8z"DEBUG_CACHE JSHASH: do invalidate  z)DEBUG_CACHE JSHASH: do invalidate jshash:r   rM   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   z  s    T)
is_changedZONLYFORUPDATESrN   )r>   rU   rD   r   r5   r   rQ   rR   rS   rT   r;   joinr   r   rW   r?   r<   )r   r   r   Zobj_idactionrX   rZ   Zinvjsr[   r\   r]   Zchanged_fieldsr   r   r   r   _obj_dict_mdelW  sT    






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:)r>   rO   rx   r   rV   r?   r=   r   )r   r   rY   rZ   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   )rQ   r   r   r   r   r     s     z1CmfCache._invalidate_dict_get.<locals>.<listcomp>)r>   r   r?   r=   rR   )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   )	r>   rO   rx   r   rV   r?   r=   rR   remove)r   r   rY   r   r   Zkey_listrZ   r   r   r   _invalidate_dict_mdel  s    zCmfCache._invalidate_dict_mdelc                    s  t jdrdt_d S t r>dt_tjdt	   d S tj
 k rtdt_tjdtj
 d   d S i fdd  fdd	}|rt|tst|d
r|| d}nx|rt|trt|d d
rd}|| nN|d k	rd}t|tkr2t|tkr2ttkr2n|s*d}d}ntdd}|r|d rtjd| |dkr|j|d kr|d D ]:}||j d|j dfkrvd} |j   qqv|sg }	|d r|	|d 7 }	|d r|	|d 7 }	|d r|	|d 7 }	|	s
dg}	|	D ]}
|
dkr d}
|d D ]h}|dd }||krd d|   d| d  n* d!|
 d"|   d!|
 d"| d  q(q|d D ]} d| d  q|r|d sֈ d| d  jrD ]}tjd#| d$  q|sdt_d%tkrttjrttjd& dtj  jr\t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                    s$   |  krt   | <  |   d S r   )rw   r   )bind)r   rZ   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)rj   rw   r   rk   r   rl   r   r   )r   Zobj_listr   itemr   )r   r   r   r   bind_add_recursive  s    
z(CmfCache.add.<locals>.bind_add_recursiver   r   r   rw   ZcustomemptyZEmptyuG   Невозможный объект для хранения в кешеFr   zDEBUG_CACHE WHERE: r   z.idz.codeparentslistsZcache_clustersZScopeAll)ZNullZNULLZnullrh   ZnoneNrh   r!   where_ScopeAll__insdelwhere_r   zDEBUG_CACHE BIND: z = r[   #DEBUG_CACHE JSHASH: add invalidate r   )osenvironrR   gno_jscache_force	CMF_CACHEcache_is_lockedr5   rD   cache_locked_bycache_transaction_startget_last_invalidaterj   rw   r   ry   rp   rq   ro   rv   r   r   r'   r   Zcache_store_errorr[   r   r   )r   rZ   r   obj_typeZquery_paramsr   Zobj_caseZwhere_pk
field_nameZscopesZscopeZ
model_nameZbindidr   )r   r   rZ   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rTdt jd< nt jd  d7  < dt jkrzdt jd< d S )Nprofiler_data	cache_hitr_   
cache_missr   r   r;   r   rv   r   rZ   r   r   r   r   profiler_data_hite  s    

zCmfCache.profiler_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< d S )Nr   r   r_   r   r   Zcache_miss_lastr   r   r   r   r   profiler_data_misss  s    


zCmfCache.profiler_data_missc                 C   s   t jdrd S t| jd | |}|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	| | 
| t|S | | t| jd
|  d S )Nr   ZCACHEr[   r   z*DEBUG_CACHE JSHASH: add invalidate jshash:r   r   zDEBUG_CACHE HIT: zDEBUG_CACHE GET:zDEBUG_CACHE MISS: )r   r   rR   r5   rD   r   r   r[   r   r   r   rS   rT   r  r   r   r   r   rR     s"    



zCmfCache.getc                 C   s    t | jd t| jdpdS )Nz%DEBUG_CACHE TRANS get_last_invalidatecache_last_invalidater   r5   rD   rp   r>   rR   rH   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)r5   rD   gen_time_usr   r   rH   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)rp   ri   r   rb   rt   strftimerH   r   r   r   r    s    zCmfCache.gen_time_usc                 C   s:   t | jd |  s6| jdtj | jd|   d S )NzDEBUG_CACHE TRANS cache_lock
cache_lockr  )r5   rD   r   r>   r   r   r   r  rH   r   r   r   r    s    zCmfCache.cache_lockc                 C   sJ   dt krd S |  }t j|ks,t j|d krFt| jd | jdd d S )Nr   i zDEBUG_CACHE TRANS cache_unlockr  0)r   r   r   r5   rD   r>   r   )r   Zlock_trr   r   r   cache_unlock  s    zCmfCache.cache_unlockc                 C   s    t | jd t| jdpdS )Nz%DEBUG_CACHE TRANS get cache_locked_byr  r   r  rH   r   r   r   r     s    zCmfCache.cache_locked_byc                 C   s"   |   }|dkr|tjkrdS dS )Nr   TF)r   r   r   )r   Z_cache_locked_byr   r   r   r     s    zCmfCache.cache_is_lockedc                 C   sZ   g }|D ]}| ||  q| |||j| | | | jrVtd| d|j | d S )Ninvaldebug--)r   r   r   r   rD   r   )r   r   r   r   Zinv_listr   r   r   r   _do_invalidate  s    
zCmfCache._do_invalidatec              	      s  d& fdd	}ddl m} tjdr.d S   tjd  d|j  |j}i j	rpdd l
}|  |jd	kr||j d
  dkr|d|j d|j d ||j 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rh|
rh|
jrh|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r|tjd  d|j d S t|dr|j   dkr||j d  dkrb|D ]}	t|dr|d|j d| d |	 d t|d!r|d|j d| d |	 d t|drH|jD ]$}|d|j d| d |	 d" q"|d| d |	 d q dkst|d#r|j jst|d$r|j!jst|dr|jjst|dr|jjrt|dr|d|j d| dd t|d!r|d|j d| dd t|d#r^|j jr^|j jr^|j j|j jkr^|d|jj d| dd% t|d$r|j!jr|j!jr|j!j|j!jkr|d|jj d| dd% t|dr|jD ] }|d|j d| dd" q|d| d |  d S )'Nrc   c                    s6    | }|r2|| < tjd  d| |   d S )NzDEBUG_CACHE INVAL: r   )r   r5   rD   )ZinvaldebugZinvdr   r   r   r   r   _check_inval  s    
z)CmfCache.invalidate.<locals>._check_invalr   )r   r   zDEBUG_CACHE start invalidate r   ZRelationCachezRelationCache.parent.id=)r   r   r   r   zref=zobj.id=r   r   zwhere=r   Tr   )r   cmf_modified_byr   Zcmf_viewed_byrc   )createrU   r   zref_new=zref_old=zDEBUG_CACHE ivalidate: z not fields_have_changesr   )r   r  rU   cache_cluster_idr!   	parent_idz
where_lst=parentcache_clusterz
where_old=)rc   )"collectionsr   r   r   rR   r  r5   rD   r   TRACEpdbZ	set_tracer  r   r  rw   rx   rj   rk   r   r   r   oldnewr   r   r   r   r   r   loadr  r  r  )r   r   r   r   r  r   r   r  Zchange_fieldsr   r   lstr   r  r   
invalidate  s     
 
"





"
22
zCmfCache.invalidatec                 C   s<   | j D ]\}}td| q| j D ]\}}td| q$d S )NzDEBUG CmfCache.dumps)r<   r*   r=   rx   )r   rZ   r}   r   r   r   r{   V  s    zCmfCache.dumps)NF)N)NN)N)N).r(   r&   r3   r<   r=   r>   r?   rD   r  PROCESS_EVICTED_FLUSHr   rG   r^   ra   r   r   r   r   r   r   staticmethodro   r   r   r   rW   r   r   r   r   r   r   r   r   r  rR   r   r   r  r  r  r   r   r  r  r{   r   r   r   r   r6   ?   s\   
C
	6
 /
 r6   c                 C   sJ   t | }| D ]4\}}t|trztj|||< W q   Y qX q|S r   )r   rx   rj   ro   r~   rr   rs   )r  Zdctr   r   r   r   r   CustomJSONDecoder\  s    
r  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)rj   r   ZCmfDateTimer   rn   ri   dateZtzinfoZ	isoformatrl   iter	TypeErrorrw   r   default)r   r   iterabler   r   r   r%  h  s    
zCustomJSONEncoder.defaultN)r(   r&   r3   r%  r   r   r   r   r   g  s   r   )Zstatic_folderZ	root_pathTZSEND_FILE_MAX_AGE_DEFAULT)SocketIO	Namespace)RedisManager)Clientrc   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   rC   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   isfiler$  
ValueErrorZ
BadRequestZ	send_fileAPPHOOK_STATIC_NOTFOUND)Zreq_filenameZ	directoryfilenamehookr   r   r   send_static  s    
r6  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   )r8  
memstorage)r   r8  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 запрещен!)r8  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   r9  rR   )r   rZ   r   r   r   rR     s    zCmfRedisMemoryWrapper.getc                 C   s   | j   d S r   )r9  clearrH   r   r   r   rG     s    zCmfRedisMemoryWrapper.flushdbc                 C   s$   | j |d}||7 }|| j |< |S )Nr   r@  )r   rZ   amountrn   r   r   r   r@     s    
zCmfRedisMemoryWrapper.incrbyr_   c                 C   s   |  ||S r   )r@   )r   rZ   rB  r   r   r   incr  s    zCmfRedisMemoryWrapper.incrc                 G   s$   d}|D ]}|| j kr|d7 }q|S )Nr   r_   r9  )r   namesrnr   r   r   r     s
    

zCmfRedisMemoryWrapper.existsc                 C   s   || j |< d S r   rD  )r   rZ   rn   r   r   r   r     s    zCmfRedisMemoryWrapper.set)N)r_   )r(   r&   r3   __doc__r8  Redisr   r=  r   rR   rG   r@   rC  r   r   r   r   r   r   r7    s&   






r7  c                     s   fdd} t d d }zzttdt  trtdt  tj }|jtt  |	 D ]*}td|  |d dkrd|d	 
 }t|g }|D ] |d
krft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j| t|d |d qqdW n: ttfk
r    Y n  tk
r   td Y nX W 5 t d X qd S )Nc                     s~   zFt d  d|  d| d t   | |W  5 Q R  W S Q R X W n2 tk
rx   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_contextrv   logging	exceptionr   r   Zhandlerr   r   spawn_handler  s    "z3_spawn_server_event_listener.<locals>.spawn_handler   z._spawn_server_event_listener: listen channels z	Channels z*_spawn_server_event_listener: got message ry   messagechannelz__keyevent@7__:evictedu   WARNING! Сервер Redis выгрузил ключи из-за нехватки памяти. Если это происходит слишком часто, нужно увеличить память для Redis. Ключ: uT   Кеши больше не валидные, запускаем сброс кеша!<   skip_evicted_timerTz/tmp/eva-app_flushdb.lockwz;on_project_permission_change handler do CMF_CACHE.flushdb()rd   Fz7_spawn_server_event_listener: gevent.spawn got message data)rW  rR  z"_spawn_server_event_listener error)timesleepr*   _server_event_channelsREDIS_DBr8  pubsubZ	subscriberw   ZlistenrQ   rR   rk   appr   r  openfcntlZflockZLOCK_EXZLOCK_NBrG   geventspawnjsonrT   
SystemExitKeyboardInterruptrv   rL  rM  )rP  rU  r\  rR  rS  Zhandlersr+   r   rO  r   _spawn_server_event_listener  sV    	




"re  c                   C   s   t t d S r   )r`  ra  re  r   r   r   r   spawn_server_event_listener.  s    rf  c                    s    fdd}|S )Nc                    s   t   |  | S r   )rZ  r   )funcrS  r   r   r1   5  s    z"on_server_event.<locals>.decoratorr   )rS  patternr1   r   rh  r   on_server_event2  s    rj  cache_settingsr%  ry   r8  Z	run_uwsgiu?   При работе через uwsgi обязателен Redisr   F)r]  Zcors_allowed_originsloggerZengineio_loggerdbunix_socket_pathzunix://z?db=zflask-socketio)rS  Z
write_onlyclient_managerredis://passwordrg   @hostport6379r$   message_queue)Payloadd   )rl  z/custom/org_name)r>   r?   )r?   u&   Неизвестный тип кешаc                  C   s   t jd dr0dt jd d  dtd  } nld} dt jd kr\| dt jd d  d	7 } | t jd d
 7 } | dt jd dd 7 } | dtd  7 } td| | d}|jt j G dd d|j}||_|S )Nr%  rn  zredis+socket://z?virtual_host=r_   rp  rq  rg   rr  rs  rt  ru  r$   Zcrm)ZbackendZbrokerc                       s8   e Zd Z fddZd	 fdd	ZddddZ  ZS )
z$make_celery_app.<locals>.ContextTaskc                    s.   t  j|| d| j | _d| j | _dS )uy   Фабрика все опции прописывает в классе, вызов конструктора пустойZcmf_task_only_once_queue__Zcmf_task_only_once_lock__N)r   r   r   only_once_queue_flag_nameonly_once_lock_namer   r   r   r   r     s    z-make_celery_app.<locals>.ContextTask.__init__Nc                    s   t | dd rLtjj| jd| jp dd d dd}|sLtd| j d	 d S |pRi }t | d
d rdd ntj	j
j|d< t j||f|}|j
tj	j
j||| jd}t| td| |S )N	only_oncer_   r   rd   rT  T)exZnxzSkip create task z - already startedsystem_taskcmf_current_person_id)Ztask_idr   r   r   rg  zcmf-background-task-queued)r   r[  r8  r   ry  soft_time_limitr   r  r   current_personr   rn   r   apply_asyncrb  r{   socketiorW   )r   r   r   Z_my_custom_paramr/   Zneed_creater   event_paramsr   r   r   r    s,          
z0make_celery_app.<locals>.ContextTask.apply_async)r~  c          	      _   s  dd l }|d tdd tjj| j| jp2dd d}| jj	rzt
d| jj	  t| dd rz|  tj| j td	| j d
dd zz>|rtjj|tjdt_| j||}td	| j ddd W nx tk
rH } zXt d| jj	  td	| j d| dd | jj	r6t
d| jj	 t!|  W 5 d }~X Y nX W 5 t| dd rz|  W nJ tjjk
r } z&td| d|j d|j dd W 5 d }~X Y nX X | jj	rt
d| jj	 t!| t"j#$  |W  5 Q R  S Q R X d S )Nr   rQ  F)init_views_and_dsrT  timeoutzcmf-background-task-start-r{  zContextTask z startT)flushzlock release error z, lock_name z
, timeout r   z successzcelery task error z error zcmf-background-task-error-zcmf-background-task-result-)%rX  rY  rK  r[  r8  lockrz  r  requestr   r  rW   r   acquirerU   ry  r*   r   release
exceptionsZ	LockErrorr  r   	CmfPersonrR   r2  current_person_fieldsr   _current_personrunrv   rL  rM  ro   rE   stdoutr  )	r   r~  r   r   rX  
redis_lockr   resulterrorr   r   r   __call__  sH    
 


z-make_celery_app.<locals>.ContextTask.__call__)NNN)r(   r&   r3   r   r  r  r4   r   r   r   r   ContextTask  s   r  )	rC   rk  rR   rm  r	   Zconfr   celeryZTask)Z	redis_url
celery_appr  r   r   r   make_celery_appz  s"     Fr  )r{  r}  c               
   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   Ошибка выполнения периодической задачи )r2  HOOK_CRON_MINUTELYr*   rd  rc  rv   rL  rM  )_kwargs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-Headersi  r  zUnknown errorr   r  r  )r   r  r  
format_excrj   r   Zget_responserb  r{   r  r   r  rW  content_typer  headersrR   r;   ro   Zjsonifystatus_code)r   Zresponser   r   r   handle_exception  s4    






r  Zjwt_rsazjwt_rsa.pub)RSAZcmf_deletedrg_member_ofZdefault_projectZemailZphone
user_localZphone_internalZprimary_roleZonline_statusZvacation_startZvacation_endZon_vacationZactivitydoes_not_workZis_admin
is_supportservicedesk_allowc                 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)rC   AUTH_ENABLEDr2  system_personr   r  rR   r  rv   rL  rM  rH   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 для проверки прав доступаjsurlrc   z/share/Tr   r      r$   r   z*^(?P<obj_type>[^:-]*)[:-](?P<obj_code>.*)$docZDOCCmfDocumentZflZFLZIN_WORK	CmfFolderCmfListZEPIr
  rg   r   sharelink_hashr  )r  r   )#r  r+  r`   r  rR   rW  ujsonrT   rv   rL  rM  rj   r;   r   r   sharelink_access_requestr   Zqueryr   r'   rematchgroupsr   r  r  r  r   rk   Z	CmfEntityr   ro   r  sharelink_access_grantedsharelink_access_obj)
r  Zjson_resr-   Z
hash_paramZobj_keyr  r   Zobj_codeZ	obj_modelr   r   r   r   _check_sharelink_access0  s^    
(
r  c                 C   s   | t _t jS )uh   !!! Эта функция не меняет контекст, только инициализирует.)r   r  )personr   r   r   set_current_person  s    r  c                 C   sZ   t | dd dkr| jS tjs d S t| dr@t | dd d k	r@| jS td tjt	j
d d S )Nr  ZFAIL_recursionz#Warning!!! Lazy Calc Current PersonrA   )r   r  rC   r  r   r  r*   r  print_stackrE   r  rH   r   r   r   r    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   rc   c                 3   s   | ]}  V  qd S r   )choice)r   r   Zalphabetsecretsr   r   	<genexpr>  s     zapp_key.<locals>.<genexpr>    zapp.app_key() error)r2  r  r   CmfGlobalSettingsrR   rk   utilcmfutildisable_aclstringr  Zascii_lettersdigitsr   rangesaverv   rL  rM  )r   Zsettingsr  r   r  r   r    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_anonymous_userzanonymous@evateam.ruTr  Zinclude_deletedr   zcreate-anonymous-user-lockrQ  r  zapp._anonymous_user() error)r   r  r   r  rR   r2  r  r[  r8  r  r  r  rk   r  r  r  system_dataZcreate_anonymous_userr  ddcommit_all_dsrv   rL  rM  r   r  r   r   r   anonymous_user  s4      

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_sharelink_anonymous_userzsharelink-anonymous@evateam.ruTr  z$create-sharelink-anonymous-user-lockrQ  r  z%app._sharelink_anonymous_user() error)r   r  r   r  rR   r2  r  r[  r8  r  r  r  rk   r  r  r  r  Zcreate_sharelink_anonymous_userr  r  r  rv   rL  rM  r  r   r   r   sharelink_anonymous_user  s8      

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-lockrQ  r  zapp._test_guest_user() error)r   r  r   r  rR   r2  r  r[  r8  r  r  r  rk   r  r  r  r  Zcreate_test_guest_userr  r  r  rv   rL  rM  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  rR   rk   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CmfGlobalVarrR   rH   r   r   r   
global_var3  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 linesr_   r   z#%s: %s:%s: %.1f KiBi   z    %sc                 s   s   | ]}|j V  qd S r   sizer   statr   r   r   r  V  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  X  s     zTotal allocated size: %.1f KiB)Zfilter_tracestracemallocZFilterZ
statisticsr*   	enumerater  r   sepr   r4  r'   r  r  	linecachegetlinestripformatsumr   )ZsnapshotZkey_typelimitZ	top_statsr#   r  framer4  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   )r`   )r   r   r   r   r   r   
<dictcomp>b  s
   
  z+create_person_from_auth.<locals>.<dictcomp>Tr   Z	cmf_ownerZ
cmf_authorr  ZServiceDeskClient)r  )Z	only_data)rk   r  r  ZCmfLockr   r  rR   r  r2  r  rx   r   system_userr  r  r   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                     s6  t   tjdkrdS t  d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_#dt_$tj%&dt_'dt_(dt_)t*j*+t*j,j-t_.dd t_+tj./ t_0dd t_/dt_1i t_2i t_3g t_4dt_5dt_6dd fdd
}|t_7t8j9:  t;j<st=d dS tj%&drdS t>tdrtj?j@rtj?j@t;jAkrdtj?j@ dt;jA dS d}tj%&drtjBdptjBdptjCd}|r|&dr0|tDdd }t8jEF|}t8jEj|dtGjHd }t7d!|dd  d"| d#|  |stId$d%d&d'S tj%d(krt8jJjKtGjHd)}tj%&d*r&d+}d,tjLkrtjLd, }tM|}|stNd,|i}tOt;jP d-| }tjBd.d/|jBd0< d1|jBd2< d3|jBd4< |S |sLtjQd5}tjQd6}	|r`t8jRS|\t_t_)n|	rtt8jTU|	t_tjrt;jVot8jTjtjjjWd7}
t;jVr|
sdt_tjrLtjjjWt_d8d9d:dgd;d:dggd<d:tjjgg}t8jEj|tGjHd=}|r
|jXrLd}nB|
stjjYr4tZ|
p&tjtjjYd>}ntj?j[rLtZtjdd?}tj%&d@prtj%&dAprtj%&dB}dCdD }|rd}|r|jjWt_tjrtjjYt_tjj\t_tjj\ t_ndt_dt_dt_dt_t=| n`|s| r,tj]}t^  tj$r
tj_}dt_dt_dt_dt_t=| ndt_dt_t=tj` tjpxtj%&dEpxtj%dFkpxtj%&dGpxtj%&dHpxtj%dIkpxtj%&dJpxtj%&drtjLdKdLkrtjadMkpxtj%&dNpxtj%dOkpxtj%&dPpxtj%&dQrtjadMkpxtj%&dRr"tjadMkpx| rDtj%&dSrDt8jbc px| rftj%&dTrft8jbc pxtj%&dUoxtj}tjd}tj`}t8j9e  |s2tjs2tjr|stfdVtj dWS tjrtjrtf S tj%d+kr|r|jgs|jhrtOdS tj'r|jhstfdXS tj)r2tj)i }|r2|S dS )YuJ  
    Должны вернуть 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   rX  )choicesrc   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   r
    r  )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 )NrD   rI   rd   r   Zselect_countZselectr   r   insertmr$   z(+z)mszs zu zi t)r   rC   ro   roundr   debug_start	debug_nowrR   r;   r  r   r*   
request_id)
r  messagesr   r   rG  ZscZscsZscuZscir  r  r   r   r    s,    "	zbefore_request.<locals>.debugz/memZOKr  u>   Версия Eva отличается от версии БД: z != u   . Вероятно была запущен несовместимый образ Eva, либо были проблемы во время обновления и патчи применились частично./api/zX-Eva-TokenZAuthorizationtokenzBearer T)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   )r  )r  z/pub/apiz/docsz/sharec                   S   s   t jdpt jdS )Nr  /socket.io/)r  r+  r`   r   r   r   r   is_allow_publicC  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	/helpdesku   Учётная запись uQ    заблокирована. Обратитесь к администраторуuU   У вас нет доступа. Обратитесь к администратору)jr   r   r  methodr  before_requestr   r   flagsremove_filesr   r   rR   ZtestrX  Zrandomr  r  r  r   r  Zsave_only_data_hackalertdeferred_tasksr  Zpublic_accessr  Zis_local_userZis_guest_userZis_anonymousr  is_system_contextZdisable_notifyZimport_modeZinteractive_shellr  r  r+  r`   request_servicedeskr  sessionri   r   rb   rt   r	  r"  r  Zrelaxed_bz_python_mode	emit_listsocket_eventsserver_eventsr  Zjscache_timelifer  r   CmfAccessListZinit_contextrC   r  r  r   r  Zeva_versionZEVA_VERSIONr  r   r   r  Z
hash_tokenr2  r  r   Z
CmfWebhookZget_token_personr   check_sso_redirectr   redirectAUTH_SERVER_URLZcookiesZ
CmfSessionZ
from_tokenCmfAuthZfrom_jwtZIS_AUTHORIZATORrn   r  Zjwt_is_supportr  Zservicedesk_allow_auth_guestsZjwt_is_match_orgr  r  r  r  Zremote_addrZ	CmfPluginZcheck_secretr  Zsetup_contextreject_responser  r  Ztfa_check_two_factor)r  r  Zauth_personZ	api_tokenr  r  rF  qsr  r   Z	real_authZ_filterZis_force_publicr$  Zanon_personZis_allow_without_authr   r   r  r   r(  z  sz   




  $


$












	 


"
r(  c                 C   s0   t jr
d S tjjddgdd}|r,|| S d S )Nr   zplugin.*F)r   Zdisabled)r   r-  r   ZCmfAuthOpenIdPluginrR   Zlogin_redirect)r  Zopenidr   r   r   r4    s
    r4  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 )Nr#  r  r  znot authorizedr  r  r  r  rR  z/servicedesk/auth/signin?r  r  r   r  r  r  r  r  )r  r+  r`   r   r-   r   r   r.  r5  rC   r6  r4  r  rR   )rR  paramsr9  rF  r   r   r   r8    s(    




r8  c                   C   s   t   t  t  d S r   )r  r  emit_eventsemit_server_eventsr   r   r   r   commit_with_event  s    r=  c               	   C   sN   t dsd S t j D ]*\} }td|d  |d|ddd qi t _d S )Nr0  is_changed-r   r$   r   private)	namespacer   )r   rR   r0  rx   r   )r   r}   r   r   r   emit_list_apply  s
    
$rA  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   r@  r   r?  r   event_current_personr   Zrelation_personsuY   DEV: INFO Кривой евент, в event_person попал объект, а не str: r   )rx   r   copyrb  r{   rv   r*   rj   r'  rW   r`   r   rk   r   r   r   rn   ro   )Z
event_dictmsgZevent_param_listZevent_paramrB  r   Zemit_kwargsr   Zuser_idevent_personevent_persons_strr   r   r   emit_events_dict  sF    


 
""
 
rH  c                  C   s&   t   tdpi } i t_t|  d S )Nr1  )rA  r   rR   r1  rH  )r1  r   r   r   r;    s    r;  c                    s:    fdd}t   tdp i i t_r6t| dS )u   Запускаемся в контексте, но отправляем в отдельном таске вне контекста, после паузы, чтобы не держать запрос.c                      s   t   t d S r   )r`  rY  rH  r   delayr1  r   r   emitter  s    
z'emit_events_with_delay.<locals>.emitterr1  N)rA  r   rR   r1  r`  ra  )rJ  rK  r   rI  r   emit_events_with_delay  s    rL  c                  C   sP   t dpg } g t _| D ]2\}}t d| d|  tj|t| qd S )Nr2  zemit_server_events: r   )	r   rR   r2  r  r[  r8  Zpublishrb  r{   )r2  rS  rW  r   r   r   r<  $  s
    r<  c                   C   s   t   i t_d S r   )r  Zrollback_all_dsr   r1  r   r   r   r   rollback_purge_event,  s    rM  c                  C   s$   t dg D ]} |  }qg t _d S )Nr,  )r   rR   r  r,  )Ztask_signaturer   r   r   r   apply_deferred_run_tasks1  s    
rN  c                  C   s2   t dg D ]} tj| rt|  qg t _d S )Nr*  )r   rR   r   r+  r   r   r*  r4  r   r   r   apply_deferred_remove_files9  s    rP  c                 C   sN   t   td t  t  t  tjdd| jd< d| jd< d| jd< | S )	uk   
    Запускается только если небыло ошибок
    :param r:
    :return:
    rd   r  r   r  r  r  r  r  )	r  r  rL  r<  rN  rP  r  r  rR   )rF  r   r   r   acaoB  s    

rQ  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   )rC   r  ZDISABLE_PERMISSIONSr2  disable_permissionsrK  rk   r  r  r  includer   r3  Zload_acl_datarf  r   r   r   r   app_init_aclU  s    "rT  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   rk   rS  r   rK  r  r  r  rU  Zload_project_permission_datar   r   r   r   app_init_project_permission`  s    rV  c                   C   s0   t   t  t  tjr t  tjr,t  d S r   )	r  before_first_requestrT  rV  rC   WHATSAPP_MESSENGER_URLspawn_messenger_socketio_clientWHATSAPP_WEB_SOCKETspawn_whatsapp_socketio_clientr   r   r   r   rW  h  s    rW  c                 C   s   t j| d d S NrM  )r  r  r]  r   r   r   teardown_requestu  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   r  rC   rD   Z
PRODUCTIONr   r  format_stackr:  r+  r   )rE  r   r   Z
devel_onlyZ	stack_strr   r   r   r   {  s    "

r   r?  )r@  rB  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 )Nr1  r   rM   session_tab_idrc   rC  )r   r   r@  r   rB  F)
zevent-r	  ztask-comment-zaudit-task-comment-znotify-person-r>  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   )r  r   r;   r1  rv   r   r  r   rn   ry   r`  rb  r{   r`   r*   localsr   rj   rk   r   r   r   ro   
setdefault)rE  r@  rB  r   r   r   r   r   r  ZmutedZ
muted_debtrG  rF  Z
event_listr   r   r   r     sL    


r   c                 C   s"   dt krg t _t j| |f d S )Nr2  )r   r2  r   )rS  rW  r   r   r   cmf_emit_server_event  s    rc  c                 C   s   |rd |nd}|rdnd}|r&dnd}	d ||| |	g}
tj|
dtjtjd}|r| \}}|rv| }| }|j}|r|rtd|
 td	| td
| t	d|
 |r|||fS ||p|f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 {0} rc   zsudo z 2>&1z0{0} bash -c "export BOOTUP="noncolor";{1}{2}{3}"T)shellr  rF   u6   Произошла ошибка при вызове %sz
STDOUT: %sz
STDERR: %su4   Произошла ошибка при вызове )NN)
r  
subprocessPopenPIPEZcommunicaterQ   
returncoderL  r  RuntimeError)ZcommandZsudor  waitZseparate_out_and_errZ	do_decodeZdo_raiseZtimeout_cmdZ_sudoZ	_redirectcmdZprocessouterrZerrcoder   r   r   run_bash_command  s8    
rn  c                 C   sL   t tj}t }||   ||}t	|
 }|  d| }|S )ua   
    Подписываем токен сертификатом
    :param jwt:
    :return:
    r!   )r   r  r2  rsa_private_keyr
   r   r   signbase64	b64encoderQ   )jwtZsignerZdigestrp  r   r   r   r   rsa_sign_pack_jwt  s    
rt  c                 C   sH   ddd}t t|  }t t|   } | d|  S )uD   
    Создаем токен
    :param payload:
    :return:
    ZRS256ZJWT)Zalgtypr!   )rq  rr  rb  r{   r   rQ   )payloadheaderr   r   r   
create_jwt	  s    
rx  c                   C   s   t jS )u2   
    Текущая версия
    :return:
    )rC   ZCMF_VERSIONr   r   r   r   cmf_get_version	  s    ry  c                 C   s   | t jkrt j|  dS )ux   
    Удаления файлов после коммита транзакции
    :param filename:
    :return:
    N)r   r*  r   rO  r   r   r   cmf_remove_file!	  s    
rz  c                   @   s,   e Zd Zd
ddddZdd Zdd	 ZdS )rK  FNr7   c                 C   s   t d| _|| _d S )Nz/with-context)r2  Ztest_request_contextctxr  )r   r  r   r   r   r   ,	  s    zcmf_context.__init__c                 C   s*   | j   | jrt  t  t  d S r   )r{  	__enter__r  start_viewsr  Zinit_dsr2  Zpreprocess_requestrH   r   r   r   r|  0	  s
    
zcmf_context.__enter__c                 C   s<   t j|d |s(t  t  t  t  | j||| d S r\  )r  r  r;  r<  rN  rP  r{  __exit__)r   excrn   r  r   r   r   r~  7	  s    zcmf_context.__exit__)F)r(   r&   r3   r   r|  r~  r   r   r   r   rK  +	  s   rK  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   walkrC   r,  )r   Z
search_dirr   r   r   r   C	  s   zstart_views.<locals>.<listcomp>rc   z/viewsz.pyz.pycz__init__.pyr!   c                 s   s   | ]}|r|V  qd S r   r   )r   r   r   r   r   r  K	  s      zstart_views.<locals>.<genexpr>r$   r   )packager&  )r    Z	view_funcz/<path:req_filename>Zdistz/static/<path:req_filename>Zstatic)	itertoolschainru   rC   r,  endswithr`   r   r'   	importlibimport_moduler2  r)   r6  )Zsearch_dirsZsearch_iterdirnamedirnames	filenamesr4  r,   r   r   r   r}  A	  s$    

$  r}  c                 K   s,   t j| ||d}|jf | tj| |S )NrN  )r  	signaturer   r   r,  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--poolr`  )r   r   rR   r`  ra  r  Zworker_mainr   r   r   r   spawn_task_workerb	  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.rA   r_   )	Zcelery.apps.beatr  rK  r  r  r*   rE   rF   exitr  r   r   r   run_beatj	  s
    z&spawn_task_scheduler.<locals>.run_beatr  rQ  )r   r   rR   r`  Zspawn_later)r  r   r   r   spawn_task_scheduleri	  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   rR   rC   ORG_NAMEwhatsapp_sioconnectrX  r  r   r   r   messenger_connectv	  s    
 z:spawn_messenger_socketio_client.<locals>.messenger_connectz	/whatsapp)r  )rC   rX  r`  ra  )r  r   r   r   rY  u	  s    rY  c                   C   s   t tjtj d S r   )r`  ra  whatsapp_go_sior  rC   rZ  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)rt  ZstdoutToServerZstderrToServerZsuspend)pydevd_pycharmr*   rC   ZREMOTE_DEBUG_SERVERZREMOTE_DEBUG_PORTsettrace)r  r   r   r   cmf_pycharm_debug	  s     r  r7   c                  C   sH   t tjtjttt ttt d tjj	dd} t
| }t|S )NrT  Zguid)ZissZorg_nameZiatZexpr  Zjti)r;   rC   ZAPP_FQDNr  ro   rp   rX  r   r  rn   rx  rt  )rv  rs  r   r   r   gen_eva_app_token	  s    r  )urirW  c           
      C   s   ddl m} tjsFt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/  r'  r   r   r  r  r   )zContent-typeZAcceptzContent-EncodingZeva_app_token)rW     u9   Не удалось отправить запрос, url=z, status_code=z, res=r  u(   Сервер вернул ошибку: )Zrequestsr/  rC   ZEVA_ACCOUNT_USEr   r   r7  rR   r  r6  r  Zpostrb  r{   r  rv   Zcontentr   r  )
r  rW  r/  r'  Zmethod_argsZmethod_kwargsr  r   r-   r   r   r   r   call_eva_account	  s.    


r  )rc   )NN)r  r  )FF)N)N)r   )N)FFN)TNTFFF)NN)r   r  rS   rE   r_  rq  Zcalendarri   re  rX  r  r  r   r   pathlibr   Zurllib.parser   r   r   r   r  r	   r~   r`  r  ZCrypto.Hashr
   ZCrypto.Signaturer   r.  r   r   Z
flask.jsonr   Zwerkzeug.exceptionsr   rk   r   Zcmf.includeZcmf.data_providersr   r  r  r   r5   objectr6   r  r   r(   rC   r,  r2  Zjson_encoderr  r  r3  r  ZHOOK_CRON_HOURLYZHOOK_CRON_DAILYZHOOK_CRON_WEEKLYZHOOK_CRON_MONTHLYrR  Zflask_socketior'  r(  r  r)  r*  r8  r6  r7  r[  rw   rZ  re  rf  rj  r   rk  rD  Zcfgr%   rI  r   r   rR   rv   rD   Zsocketio_kwargsrm  r-   ro  rv  Zengineio.payloadrw  Zmax_decode_packetsr  r  r+  r   r^  r+   readr  r  r   r  r  r  r  Zerrorhandlerr  Zregister_error_handlerZprivate_key_pathZpublic_key_pathZCrypto.PublicKeyr  Z
import_keyZ
read_bytesro  Zrsa_public_keyr  r  r  r  r  r  r  propertyry   r   r  Zcurrent_userr  r  r  r  r(  r4  r8  r=  rA  rH  r;  rL  r<  rM  rN  rP  Zafter_requestrQ  rT  rV  rW  r^  r   r   rc  rn  rt  rx  ry  rz  rK  r}  r  r  r  rY  r[  r  ro   r  r;   r  r   r   r   r   <module>   s        #

;F
	 
	 


[

!

             	b


  5

1
	


9  
,

