U
    pVc                     @   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mZ d dl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mZ d dlmZmZ d d	lmZmZ d dlZd dlZd d
lmZmZ d dl m!Z! d dl"T d dl#m$Z$ dd Z%e&j'ddddd Z(dd Z)dd Z*dd Z+G dd dZ,G dd dej-j.Z/dS )    N)OrderedDict)deepcopy)is_dataclass)isclass
isfunctionismethod	signature)time)uuid4)Responserequest)dumpsloads)commit_all_dsrollback_all_ds)CmfType)*)	CMF_CACHEc                 C   sh   t | tjrt| S t | tjr(t| S t | tjjrXdd | j	
 D }| j|d< |S t| | jd S )Nc                 S   s,   i | ]$\}}t |tr|jd k	r||jqS ).)
isinstancer   _value).0attrfield r   ./modules/api/views/index.py
<dictcomp>!   s
   
 
 z%cmf_dumps_default.<locals>.<dictcomp>
class_name)r   	ipaddressIPv4AddressstrdecimalDecimalcmfmodels	BaseModel__dict__itemsr   	TypeError	__class__)objresultr   r   r   cmf_dumps_default   s    
r+   zjshash-invalidate-confirm/)	namespacec                 O   s   t |  d S N)r   Zjshash_invalidate_confirm)Zconfirm_dictargskwargsr   r   r   handle_message*   s    r1   c                 C   s:   zt j| tt jdW S  tk
r4   td  Y nX d S )N)defaultoptionzorjson.dumps error)orjsonr   r+   ZOPT_NON_STR_KEYSr'   gdebug)r)   r   r   r   	cmf_dumps.   s
    
r7   c                    s   i  fdd}|S )Nc                     s4   t | t| f}|kr, | ||< | S r.   )pickler   sortedr&   )r/   r0   hashfuncZmemoryr   r   memo9   s    zmemoized.<locals>.memor   )r<   r=   r   r;   r   memoized6   s    r>   c                 C   s   dt krt t _|t j| < d S )Nprofiler_data)r5   r   r?   )keymsr   r   r   set_call_timeA   s    rB   c                   @   s   e Zd Zd$ddZdd Zejjp(ejjdddZ	e
d	d
 Zd%ejjdddZd&ddZdd Zed'ejjdddZdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# ZdS )(CmfResultSplitterNc                 C   sD   || _ i | _t | _d | _d | _d | _d| _t | _d| _	|| _
d S )Nr   )_objmetasetmeta_fields_keepr*   startendnumber_of_objectsm2m_id_cachedepthno_meta)selfr)   rM   r   r   r   __init__I   s    zCmfResultSplitter.__init__c                    s    fdd}|S )Nc                    sL   |  j d7  _ | j dkrd S  | f||}|  j d8  _ | j dksHt|S )N   
   r   )rL   AssertionError)rN   r/   r0   retfnr   r   wrapV   s    
z,CmfResultSplitter._check_depth.<locals>.wrapr   )rU   rV   r   rT   r   _check_depthU   s    zCmfResultSplitter._check_depth)oc                 C   s"   |j | jkrt|j| j|j < d S r.   )r   rE   r   Zui_metarN   rX   r   r   r   _add_class_to_meta`   s    z$CmfResultSplitter._add_class_to_metac                 C   s  |  d}|  d}|  d}|  d}tt|}i }d}tjj|||ddpRt }t|tjjr|j	r|r|
dd	 }	tt|	d}
|
j |j	}|  d
}|  d}|r|jstjj||	||j	d}t|t|@ }d|krd|krdnd}t|  D ]}|j |}|dks|r$|jr$qd}tjj||||ddpDt }d|krbd|kr^dnd}|rp|||< |dkr| |= q|r|| d< |r|| d< | S )u;  
        Чтобы код не дблировать для модели, простой модели и дикта, можно проверять итоговый json
        Правда в таком случае, мы обходим все данные, даже если они не доступны.
        perm_effective_acl_idcmf_owner_idr   perm_inherit_parent_idNF)initial_acl_keyobject_modelobject_owner_idraise_error:r   perm_inherit_acl_idperm_inherit_parent_owner_id)r^   r_   r`   object_fieldwritereadreadonlyZdeny)idr   )r^   r_   re   r`   ra   Z_acl_fieldsZ_acl_obj)getgetattrr#   CmfAccessListcheck_accessrF   
issubclassr"   	CmfEntityZacl_parent_field	partitionfieldsZno_acllistkeys)Zobj_dictr^   obj_owner_idr   r]   modelZ
acl_fieldsZacl_objZaccess_levelsZparent_class_nameZparent_modelZparent_fieldrc   rd   Zparent_access_levels
field_namer   Z	acl_fieldZfield_access_levelsr   r   r   _acl_obj_dictd   sp    




  


   
zCmfResultSplitter._acl_obj_dictr   c                 C   sh   |  j d7  _ | js| | d|ji}|jddD ]$}|js@q4| j||d d||j< q4| |}|S )NrP   r   T)
is_definedrL   )rJ   rM   rZ   r   valuesrx   _process_cmf_typerw   )rN   rX   rL   r*   vr   r   r   _process_cmf_model   s    


z$CmfResultSplitter._process_cmf_modelc                 C   sv   |  j d7  _ | js*tt|j}| | i }|j D ].\}}| jsX| j	|j|f | 
|||< q8| |}|S NrP   )rJ   rM   rk   r#   r   rZ   r%   r&   rG   add_processrw   )rN   r)   rL   ru   r*   r   valuer   r   r   _process_simple_model   s    

z'CmfResultSplitter._process_simple_modelc                    s    fdd  |S )Nc                    s   t | tr fdd| D S t | tr| d} fdd|  D }t |trd|kr jd7  _tjj	
|}js| | D ]}j|j|f q|j|d< |}|S | S )	Nc                    s   g | ]} |qS r   r   )r   elproccess_jsonr   r   
<listcomp>   s     zSCmfResultSplitter._process_json_as_model.<locals>.proccess_json.<locals>.<listcomp>ri   c                    s   i | ]\}}| |qS r   r   )r   kr|   r   r   r   r      s      zSCmfResultSplitter._process_json_as_model.<locals>.proccess_json.<locals>.<dictcomp>rb   rP   r   )r   rr   dictrj   r&   r   rJ   r"   rq   ZCmfTUUIDZget_cls_by_tuuid_strrM   rZ   rG   r   r   rw   )r)   obj_iddataru   rv   r   rN   r   r   r      s     





z?CmfResultSplitter._process_json_as_model.<locals>.proccess_jsonr   rY   r   r   r   _process_json_as_model   s    z(CmfResultSplitter._process_json_as_modelc                 C   sb  |  j d7  _ | js*| j|jj|jf t|tjj	rD| 
|jS t|tjjr^| |jS t|tjjrx| |jS t|tjjrt|| jkrd S | jt| |jrd S | j|j|d d}| jt| |S t|tjjrFt|| jkrg S | jt| g }|jD ]}| |}|| q| jt| |S |j}|dkr\|jS |jS )NrP   ry   .)rJ   rM   rG   r   instancer   r   r"   rq   ZCmfObjectJsonr   r   ZCmfObjectList_process_listZ	CmfObjectr}   ZCmfRelationBaseri   rK   Zis_nullremoveZ
CmfRelBaseappendZjsonr2   )rN   rX   rL   resr*   ipr   r   r   r{      s@    


z#CmfResultSplitter._process_cmf_typec                    s$     j d7  _  fdd|D }|S )NrP   c                    s   g | ]}  |qS r   )r   )r   erN   r   r   r      s     z3CmfResultSplitter._process_list.<locals>.<listcomp>)rJ   )rN   rX   r*   r   r   r   r      s    zCmfResultSplitter._process_listc                 C   s   |  j d7  _ t }| D ]v\}}| |||< | js|dkr|rt|trtt|	dd d }|r| 
| | D ]}| j|j|f qzq|dr|dr| |}|S )NrP   ri   rb   r   r   )rJ   r   r&   r   rM   r   r   rk   r#   splitrZ   rs   rG   r   r   rj   rw   )rN   rX   r*   r   r|   mrv   r   r   r   _process_dict  s    

zCmfResultSplitter._process_dictc                 C   s   |  j d7  _ t|tr"| |S t|tjjr:| |S t|tjj	rR| 
|S t|rd| |S t|trx| |S t|tjtjfrt|S t|tjtjfr| S |S r~   )rJ   r   rr   r   r"   rq   r   r{   r#   r$   r}   r   r   r   r   r   r   r    r!   r   datetimedateZ	isoformat)rN   r)   r   r   r   r     s     






zCmfResultSplitter._processc                 C   sB   | j  D ]2\}}t|d D ]}||f| jkr|d |= qq
d S )Nrq   )rE   r&   rr   rG   rN   r   Zclass_valuerv   r   r   r   _process_meta$  s    zCmfResultSplitter._process_metac                    s\   d fdd	  j  j D ]2\}}t|d D ]}||fjkr8|d |= q8q$d S )Nr   c           	         s   j d7  _ t| rdtt| j}| | j D ](\}}j	|j|f  ||d  q6n t
| tjjrtt| j}| | j D ]>\}}t
|tr|jdk	rj	|j|f  |j|d  qnt
| tr| D ]} ||d  qnt
| trd }| d}|rJt
|trJtt|dd d  }rJ| |  D ]0\}}|rrj	|j|f  ||d  qRd S )NrP   .ri   rb   r   )rJ   r   rk   r#   r   rZ   r%   r&   rG   r   r   r"   r$   r   r   rr   r   rj   r   rp   )	r)   rL   ru   Zsub_attrZ	sub_valueZ	sub_fieldsubr   Zsub_keyprocess_jsonrN   r   r   r   ,  s6    




z<CmfResultSplitter._process_simple_meta.<locals>.process_jsonrq   )r   )rD   rE   r&   rr   rG   r   r   r   r   _process_simple_meta+  s    
z&CmfResultSplitter._process_simple_metac                 C   s$   | j r| jsd S t| j| j  d S )N  )rH   rI   intr   r   r   r   rA   Q  s    zCmfResultSplitter.msc                 C   s0   t  | _| | j| _| js$|   t  | _d S r.   )r	   rH   r   rD   r*   rE   r   rI   r   r   r   r   r   W  s
    zCmfResultSplitter.splitc                 C   s<   t  | _tjr| jn
| | j| _| js0|   t  | _	d S r.   )
r	   rH   r5   Zdisable_permissionsrD   r   r*   rM   r   rI   r   r   r   r   split_simple^  s
    zCmfResultSplitter.split_simple)N)r   )r   )r   )__name__
__module____qualname__rO   rW   r"   r#   CmfModelZBaseModelMetarZ   staticmethodrw   r$   r}   r   r   rq   r   r{   r   r   r   r   r   rA   r   r   r   r   r   r   rC   G   s$   

9
0&rC   c                       s   e Zd ZdZdZdd fddZd+ddZd,dd	Zd-d
dZdd Z	d.ddZ
dd Zdd Zdd Zd/ddZedd Zdd Zejjdd Zd0dd Zd!d" Zd#d$ Zd%d& Zd'd( Zejjd)d* Z  ZS )1ApiViewr,   N)returnc                    s   t    |  | _d S r.   )superrO   get_rpcrpcr   r(   r   r   rO   k  s    
zApiView.__init__c                 C   s   |rdd |j jD |d< |S )Nc                 S   s   g | ]
}|j qS r   )r   )r   Ze_clsr   r   r   r   q  s     z/ApiView._add_exception_info.<locals>.<listcomp>Zexception_types)r(   __mro__)rN   r*   	exceptionr   r   r   _add_exception_infoo  s    zApiView._add_exception_infoc                 C   s.   d||dt d|p| jd}| j||dS )N2.0)codemessagealert)jsonrpcerrorr   callidr   )r5   rj   r   r   )rN   r   r   r   r   r*   r   r   r   _erroru  s    zApiView._errorc	           	      C   s@   |sg }d|||||t dt d|t |d}| j||dS )Nr   r?   r   )r   r*   rE   jsverr   jsurlr?   r   abortversion
invalidater   )r5   rj   Zcmf_get_versionr   )	rN   r*   rE   r   r   r   r   r   r   r   r   r   _ok~  s    zApiView._okc                 C   s   |  ddS )NiDzParse errorr   r   r   r   r   parse_error  s    zApiView.parse_errorc                 C   s&   d}|  d|d kr|n| d| S )NzInvalid Requestiz: r   )rN   r   titler   r   r   invalid_request  s    zApiView.invalid_requestc                 C   s   |  dd|S )NizMethod not foundr   rN   r   r   r   r   method_not_found  s    zApiView.method_not_foundc                 C   s   |  dd|S )NizInvalid paramsr   r   r   r   r   invalid_params  s    zApiView.invalid_paramsc                 C   s   |  dd|S )NizInternal errorr   r   r   r   r   internal_error  s    zApiView.internal_errorc                 C   s$   |t dddkst| j|||dS )Ni ir   )rangerR   r   )rN   r   r   r   r   r   r   server_error  s    zApiView.server_errorc                 C   s  i }dt tD ]}tt|d p.ttj|d }t|s:qt|tjjsJq|jr^|tjjk	r^qi }t |D ]}t||}t	||}|
drqjt|st|st|tjsqj|tjjkr|dkrqjt|t}t|t}	t|tj}
t|}|| |d|jk|	|
dd}|||d < qj|j D ]\}}g }t|tjjtjjfrTdd	d
dg}nt|tjjrldd	g}|D ]D}| d| }t||}||t|ddddd|| d| < qpq"|||d}|||d < q|S )Nr$   _)Zall_models_metarN   F)_methodnamer   is_class_methodis_static_methodis_taskZis_field_methodr   r   r   extendZ
all_nested.T)_classr   methods)r$   )dirr#   rk   r"   r   rn   r$   ZabstractinspectZgetattr_static
startswithr   r   r   Z
celery_appZTaskclassmethodr   r   lowerZ
parametersrq   r&   ZCmfM2MZCmfGenericM2MZCmfJson)rN   Z
rpc_modelsZ
model_nameclsZrpc_methodsZmethod_namemethodZmethod_attrZ_is_class_methodr   r   ZsigZ
rpc_methodrv   Z	field_clsZ
submethodsZ	submethodr   Z	rpc_modelr   r   r   r     sn    



	
zApiView.get_rpcc                 C   s   |dkS )NZ	qweqweqwer   )rN   tokenr   r   r   check_token  s    zApiView.check_tokenc                 C   s   | j d| jtdS )Nz
index.html)r   r
   )Zrender_with_paramsr   r
   r   r   r   r   rj     s    zApiView.getFc           
      C   s:   |  ||||||}|r t|nt|ddd}	t|	ddS )Nr   F)indentZensure_asciizapplication/json)Zmimetype)r   r7   r   r   )
rN   result_dictrE   r   r   r   orjson_r   ZresponseZ	json_datar   r   r   response_ok  s    zApiView.response_okc                 C   sx   t jdrd S |ds(td d S tj dd d tj	j
jd}t||rjtd |d S td	 d S )
NNO_CACHEjshash:z$api_cache_add failed, invalid jshash%Y%m%d%H%M%S%f)r   Zcurrent_person_idzapi_cache_add endr   zapi_cache_add failed)osenvironrj   r   r5   r6   r   utcnowstrftimecurrent_personri   r   r   Z_obj_dict_set)rN   r:   Z	res_cacher   r   r   api_cache_add  s    


zApiView.api_cache_addc                 C   sL   t jdrd S |dsd S t|}|s0d S t|}td|  |S )Nr   r   zAPI CACHE HIT )	r   r   rj   r   r   _obj_dict_getr8   r   print)rN   r:   Z_resr   r   r   r   api_cache_get  s    


zApiView.api_cache_getc                 O   sr   dt j  dd d i}|D ]6}|ds0q t|}|r t|}|d||< q | j	|d d | j
tjddS )Notherr   r   r   r   T)rE   r   r   r   r   )r   r   r   r   r   r   r8   r   rj   r   r   r5   r   )rN   Zjshash_list_args_kwargsr*   jshashZ
redis_data
cache_datar   r   r   full_cache_validation  s    


zApiView.full_cache_validationc                 C   s   t jrt jt jkrdS dS )u;   
        Проверяем доступ к апи
        FT)r5   r   Zanonymous_userr   r   r   r   _check_access  s    zApiView._check_accessc           +      C   s 	  |   s| ddS tdtjjj d tj }t	t
j}td|  |d kr`|  S d|krr| dS d|kr| d	S |d | _|d
d}|t_|dpi }|dpi }|r||d< |dpg }|dd }|r||d< |dd }|r||d< |dd }	|	r"|	|d< |dd }
|
r<|
|d< |di t_tjdrbtj  |dd }|r||d< td|d}|dd }|d}|d }g }|dkr| j||S d }z|jddd\}}W n" tk
r   | | j Y S X || jkr| | jS | j| }|d }d}|d kr`|js`|d!d s`d"| }d#}||d$ krz| | jS |d$ | }|d% }d}d&D ]}||d krd#} qqd'|d krd}|r|d(rd}|jrd}|d)}|d*}|t_|r&|d kr&td+|  d}|r|r>td, n|rtj }td- | |}t d.tj | j!d/  td0 |r||d)kr|rt"#|}td1 | j$d d |d) | j|||d2S td3 |d4 s|d5 s|d6 r n|d7| }td8 |d9sJ|rJtd: |j|d9g|	|d;}nN|r|% }g |d< d9g|d< ||d7< |jf |}|&d9d n| d<d=S |std> t'  | j(d i d | j|d?d@S t)|t*jj+o|j,j}t)|t*jj-o|j.j}tjj/||j0|dAddBs<tdC t'  | j(d i d | j|dDt1 dES tdF d|dG kr|dG jddd\} }!tjj/||j0| |dAddHstdI t'  | j(d i d | j|dJt1 dES t2|| }"t2|"|!}nt2||dG }t dKtj | j!d/  tj }tdL|d   z4|d6 r6|j3||dM}#|#o2|#j4}$n
|||}$W n t5k
r }% z8t6|% t78dN | j(d i d | j|t9|%|%dE W Y S d }%~%X Y nh tk
r  }% zHt:j;8dO t6|% dP|d  dQ}&|&t<= 7 }&| j>dR|&|%dS W Y S d }%~%X Y nX tdT t dUtj | j!d/  tj }|r|j?rtdV z|@  W nX t5k
r }% z8t6|% t78dN | j(d i d | j|t9|%|%dE W Y S d }%~%X Y nX tdW t dXtj | j!d/  tj }t6  t dYtj | j!d/  tj }|dG dZkr$|$o |$j4j}$n|dG d[kr:|$j4j}$tA|$|d\}'td] |r`|'B  n|'  t d^tj | j!d/  |'jC|'jD }(})t d_|'jE td` tj }|rt2tdad s| F|}|rt"#|}| j$|)|(|| j|||db}*t dctj | j!d/  tdd |*S )eNi  u   Нет правzAPI request start ()z	json_res=r   zNo method specifiedr   zNo callid specifiedr    r0   filterr/   rq   sliceorder_bygroup_byflagsZ
admin_modeno_cacheu)   no_cache запрещен go to spec0 osv
no_jscacherM   cache_idzCache.full_cache_validationr   rP   )maxsplitr   F)rj   rr   disable_simplesTr   r   )z.getZ_getz.listZ_listz.selectZ_selectz.sumZ_sumz.count_countz.maxZ_maxz.minZ_minZget_current_userZsearch_stringr   r   ur   ошибка на frontend методы list get и тп должны быть с jshash, кроме тестов z$api_cache_get skip due to no_jscachezapi_cache_get startr   r   zapi_cache_get endzapi_cache_get hit!)r   rE   r   r   r   r   r   zapi_cache_get jsver mismatch!r   r   r   
for_updatezAPI object get startri   u~   deprecated id объекта нужно передавать в kwargs или может вообще параметром RPC)r   rq   r   r  i  u   Необходимо указать filter или kwargs для получения объекта перед вызовом его методаzAPI object get Noneu>   Объект не найден, возможно удалён.)r*   rE   r   r   r   r   rg   )r^   r_   r`   access_levelra   zAPI object access prohibiteduG   Объект не доступен: не достаточно прав.)r*   rE   r   r   r   r   r   zAPI object get endr   )r^   r_   re   r`   r  ra   z"API object field access prohibiteduR   Поле объекта не доступно: не достаточно прав.ZpreparezAPI method start )r/   r0   zUserError Trace:	Exceptionu/   Ошибка выполнения метода z

ir   zAPI method endZcall_method_mszAPI save startzAPI save endsaveZcommit)ZcreateZupsertZcreate_from_templateupdate)rM   zAPI json dump startZresult_to_dict_msrJ   zAPI json dump endZcache_store_error)r   r   Zresult_to_response_mszAPI request end)Gr   r   r5   r6   r   r   r   r   Znowr   r   r   r   r   r   rj   r   r   r#   rl   Zactivate_admin_moder  r   r   
ValueErrorr   r   r  r   r   Z	cmf_alertr   rB   Zmicrosecondsr   Zjshash_invalidate_confirm_listr   copypopr   r   r   r"   ro   r[   r   r\   rm   r   ZCmfPermissionErrorrk   Zapply_asyncri   ZCmfUserErrorr   Zloggingr   r   ZAPPlogger	traceback
format_excr   Z
is_changedr  rC   r   rE   r*   rJ   r   )+rN   Z
start_dateZjson_resr   r0   Z_filterr/   rq   r   r   r   r   r   rM   r   r   Zinvalidate_listr)   Zproc_cls_nameZproc_methodZproc_clsr   Z
use_simpleZapi_use_cacher  r   r   r   r  Z
tmp_kwargsr^   rt   rv   Zfield_methodZ	obj_fieldZtaskr*   r   msgZsplitterrE   r   Zrespr   r   r   post#  s    









 









 




       
     
   
     



      	&



      








      
zApiView.post)N)NN)NNN)N)N)FN)r   r   r   Z__url__r   rO   r   r   r   r   r   r   r   r   r   r>   r   r   r"   viewsactionrj   r   r   r   r   r   r  __classcell__r   r   r   r   r   g  s0   

	



B

	r   )0r    r   sysr   r8   r  collectionsr   r  r   Zdataclassesr   r   r   r   r   r   r	   Zuuidr
   Zflaskr   r   Zujsonr   r   r4   Z
cmf.modelsr"   Zcmf.data_providers.baser   r   Z
cmf.fieldsr   Zcmf.includeZcmf.appr   r+   ZsocketioZonr1   r7   r>   rB   rC   r  ZBaseViewr   r   r   r   r   <module>   s:   
  "