
    |jH0                    b   S r SSKJr  SSKrSSKrSSKJr  SSKJr  SSK	J
r
Jr  SSKJr  SSKJr  S	rS
r\S   rSS jr\" S	S9 " S S5      5       r\rS	S.S S jjrS!S jrS"S jrS#S jrS$S jrS$S jrS	S.           S%S jjrS&S jrS'S jr S(     S)S jjrS*S jr S+S jr!S,S jr"g)-uP   Configuración Google Drive por customer (cada cliente su propia nube OAuth/SA).    )annotationsN)	dataclass)Path)AnyLiteral)Session)settingsTuZ   Google Drive está desactivado temporalmente. Los archivos se guardan solo en el servidor.)service_accountoauthc                 8    [         (       d  [        [        5      eg N)GOOGLE_DRIVE_ENABLED
ValueErrorGOOGLE_DRIVE_DISABLED_MESSAGE     YC:\Users\jesus\Desktop\proyecto_pie360\backend\app\backend\utils\customer_drive_config.pyassert_google_drive_enabledr      s    677  r   )frozenc                  |    \ rS rSr% SrS\S'   S\S'   S\S'   SrS	\S
'   SrS	\S'   \SS j5       r	\SS j5       r
Srg)DriveCustomerConfig   z0Credenciales Drive de un customer (nube propia).intcustomer_idstrroot_folder_idsourceNdict[str, Any] | Noneservice_account_info
oauth_infoc                (    U R                   (       a  gg)Nr   r
   )r    )selfs    r   kindDriveCustomerConfig.kind&   s    ?? r   c                   U R                   U R                  U R                  U R                  (       aI  U R                  =(       d    0 R	                  S5      U R                  =(       d    0 R	                  S5      S.OS S.nSU R                   SU R
                   S[        [        R                  " US[        S95       3$ )	N	client_idrefresh_token)r&   r'   )r#   r   sar   c:T)	sort_keysdefault)
r#   r   r   r    getr   hashjsondumpsr   )r"   payloads     r   	cache_keyDriveCustomerConfig.cache_key,   s     II++++
  #oo388E"&//"7R!<!<_!M
 

 4##$Adkk]!DGW[eh9i4j3kllr   r   )returnCredKind)r4   r   )__name__
__module____qualname____firstlineno____doc____annotations__r   r    propertyr#   r2   __static_attributes__r   r   r   r   r      sU    :K26/6(,J%,! !
 m mr   r   require_tokenc               *   [        U R                  S5      =(       d    S5      R                  5       n[        U R                  S5      =(       d    S5      R                  5       n[        U R                  S5      =(       d    S5      R                  5       n[        U R                  S5      =(       d    U R                  S5      =(       d    S5      R                  5       =(       d    S n[        U R                  S5      =(       d    S5      R                  5       nU(       a  U(       d  S	 H  nU R                  U5      n[        U[        5      (       d  M+  U=(       d1    [        UR                  S5      =(       d    S5      R                  5       nU=(       d1    [        UR                  S5      =(       d    S5      R                  5       n  O   U(       a  U(       d  [        S
5      eU(       a  U(       d  U(       d  [        S5      eSUUU=(       d    S UUS.$ )Nr&    client_secretr'   tokenaccess_token	token_uriz#https://oauth2.googleapis.com/token)	installedwebzpOAuth incompleto: falta client_id o client_secret. Pega el JSON OAuth (client_id, client_secret, refresh_token).zCOAuth incompleto: falta refresh_token (recomendado) o access_token.authorized_user)typer&   rB   r'   rC   rE   )r   r-   strip
isinstancedictr   )	datar?   r&   rB   r'   rC   rE   keyblocks	            r   _parse_oauth_inforP   @   s   DHH[)/R0668I17R8>>@M17R8>>@M!CTXXn%=CDJJLTPTEF!Feg  M'CHHSME%&&%RUYY{-C-Ir)J)P)P)R	 - ^UYY5O5USU1V1\1\1^ ( ML
 	
 ]5Q
 	

 "&&.$ r   c                d   U =(       d    SR                  5       nU(       d  [        S5      e [        R                  " U5      n[        U[        5      (       d  [        S5      e[        USS9n[        US   5      [        US	   5      S
.$ ! [        R                   a  n[        S5      UeSnAff = f)u:   Extrae client_id/secret aunque aún no haya refresh_token.rA   u   Credenciales vacías.&   El JSON de Google Drive no es válido.N*Las credenciales deben ser un objeto JSON.Fr>   r&   rB   )r&   rB   )	rJ   r   r/   loadsJSONDecodeErrorrK   rL   rP   r   )rawtextrM   excinfos        r   parse_oauth_client_pairrZ   e   s    I2D011Lzz$ dD!!EFFT7Dk*+T/23   LABKLs   B
 
B/B**B/c                :   U =(       d    SR                  5       nU(       d  [        S5      e [        R                  " U5      n[        U[        5      (       d  [        S5      e[        UR                  S5      =(       d    S5      R                  5       R                  5       nUS:X  a;  UR                  S5      (       a  UR                  S5      (       d  [        S	5      eSU4$ US
;   dt  UR                  S5      (       d^  UR                  S5      (       dH  [        UR                  S5      [        5      (       d$  [        UR                  S5      [        5      (       a  S[        U5      4$ [        S5      e! [        R                   a  n[        S5      UeS nAff = f)NrA   u%   Credenciales de Google Drive vacías.rR   rS   rI   r
   private_keyclient_emailzFEl JSON de cuenta de servicio debe incluir private_key y client_email.>   userr   rH   r'   rB   rF   rG   r   zaJSON no reconocido. Usa OAuth (client_id, client_secret, refresh_token) o type="service_account".)rJ   r   r/   rT   rU   rK   rL   r   r-   lowerrP   )rV   rW   rM   rX   ctypes        r   parse_drive_credentials_jsonra   w   s_   I2D@AALzz$ dD!!EFF &B'--/557E!!xx&&dhh~.F.FX  !$&& 	5588O$$88O$$dhh{+T22dhhuot,,)$///
	N -  LABKLs   E5 5F	FFc                B    [        U 5      u  pUS:w  a  [        S5      eU$ )Nr
   z&Se espera JSON type="service_account".)ra   r   )rV   r#   rY   s      r   _parse_service_account_jsonrc      s(    -c2JD  ABBKr   c                     [         R                  =(       d    SR                  5       n U (       d  g [        U 5      R	                  5       R                  5       nUR                  5       (       d  g [        UR                  SS95      u  p#US:w  a  g U$ )NrA   utf-8encodingr
   )	r	   google_drive_credentials_pathrJ   r   
expanduserresolveis_filera   	read_text)	cred_pathpathr#   rY   s       r   #_service_account_info_from_env_filero      sr    77=2DDFI	?%%'//1D<<>>-dnngn.NOJD  Kr   c                    [         R                  " S5      =(       d    SR                  5       n [         R                  " S5      =(       d    SR                  5       n[         R                  " S5      =(       d    SR                  5       nU (       a  U(       a  U(       d  [        R                  =(       d    SR                  5       nU(       aa  [        U5      R                  5       R                  5       nUR                  5       (       a%   [        UR                  SS95      u  pVUS:X  a  U$  g g [        U UUS.5      $ ! [         a     g f = f)	NGOOGLE_DRIVE_OAUTH_CLIENT_IDrA    GOOGLE_DRIVE_OAUTH_CLIENT_SECRET GOOGLE_DRIVE_OAUTH_REFRESH_TOKENre   rf   r   )r&   rB   r'   )osgetenvrJ   r	   rh   r   ri   rj   rk   ra   rl   r   rP   )r&   rB   r'   rm   rn   r#   rY   s          r   _oauth_info_from_envrv      s   9:@bGGIIYYABHbOOQMYYABHbOOQM-M;;ArHHJ		?--/779D||~~!=8"JD w# ' "**	
  " s   !D< <
E	E	)allow_env_fallbackc                   U=(       d    SR                  5       nU(       d  g U(       aR  UR                  5       (       a=  [        U5      u  pVUS:X  a  [        [        U 5      UUUS9$ [        [        U 5      UUUS9$ U(       d  g [	        5       nU(       a  [        [        U 5      UUU S3S9$ [        5       nU(       a  [        [        U 5      UUU S3S9$ g )NrA   r   )r   r   r    r   )r   r   r   r   z
+env_oauthz	+env_file)rJ   ra   r   r   rv   ro   )	r   rootraw_jsonr   rw   r#   rY   r   r(   s	            r   _config_from_partsr{      s     JBDHNN$$1(;
7?&,#	  #K(!%	
 	
  "E"K(XZ(	
 	
 
-	.B	"K(!#XY'	
 	
 r   c           	     R   [        5         [        U5      S:  a  [        S5      eSSKJn  U R                  U5      R                  UR                  [        U5      :H  5      R                  5       nU(       a  [        [        USS5      5      (       d  [        SU S35      eUR                  =(       d    S	R                  5       nUR                  =(       d    S	R                  5       =(       d    S
n[        [        U5      UUS[        U5       3SS9nU(       a  U$ [        SU S35      e)z<Carga el Drive del customer (tabla customer_drive_settings).   u   customer_id inválido.r   )CustomerDriveSettingModelenabledTu-   Google Drive no está activo para el cliente u=   . Conéctalo en la ficha del cliente (OAuth + carpeta raíz).rA   Nz	customer:F)r   ry   rz   r   rw   z(Google Drive incompleto para el cliente uN   . Guarda carpeta raíz + JSON OAuth (client_id, client_secret, refresh_token).)r   r   r   -app.backend.db.models.customer_drive_settingsr~   queryfilterr   firstboolgetattrr   rJ   credentials_jsonr{   )dbr   r~   rowry   rV   cfgs          r   load_customer_drive_configr      s"   !
;!122W 	*+	)55[9II	J	 
 d73	4899;K= IJ J
 	

 $"++-D%2
,
,
.
6$C
$3{+,- C 


2;- @W 	W r   c                <     [        X5        g! [         a     gf = fNTF)r   r   r   r   s     r   customer_drive_configuredr     s$    "23     
c                z    [        5         Ub$  [        U5      S:  a  [        U [        U5      5      $ [        S5      e)z>Drive de Agentes: siempre por customer cuando hay customer_id.r   zCIndica customer_id: cada cliente PIE360 usa su propio Google Drive.)r   r   r   r   r   s     r   load_agents_global_drive_configr   '  s>      !3{#3a#7)"c+.>??
M r   c                d   [        5         US:  a  [        S5      eU c  [        S5      eSSKJn  U R	                  U5      R                  UR                  U:H  5      R                  5       nU(       a  [        USS5      (       d  [        SU S	35      e[        U [        UR                  5      5      $ )
u   
Compatibilidad: flujos por school_id resuelven al Drive del customer dueño.
(Ya no se usa una nube por colegio como fuente principal.)
r}   u   school_id inválido.Nz0Se requiere db para resolver Drive del customer.r   )SchoolModelr   z No hay customer para el colegio z; no se puede cargar Drive.)r   r   app.backend.db.models.pie_corer   r   r   idr   r   r   r   r   )r   	school_idr   schools       r   load_drive_configr   3  s    
  !1}/00	zKLL:XXk"))+..I*EFLLNF==.yk9TU
 	
 &b#f.@.@*ABBr   c                <     [        X5        g! [         a     gf = fr   )r   r   )r   r   s     r   drive_configuredr   H  s$    "( r   c                   SSK Jn  UR                  U 5      nUR                  5       R	                  U R
                  SSS9R                  5       nUR                  5       R                  SU R
                   S3SS	S
SSS9R                  5       nUR	                  S5      =(       d    / nSU R                  U R                  UR	                  S5      UR	                  S5      UR	                  S5      S.U Vs/ s H6  nUR	                  S5      UR	                  S5      UR	                  S5      S.PM8     sn[        U5      S.$ s  snf )Nr   )google_drive_storagezid,name,mimeTypeT)fileIdfieldssupportsAllDrives'z ' in parents and trashed = falsedrivezfiles(id,name,mimeType)
   )qspacesr   pageSizer   includeItemsFromAllDrivesfilesr   namemimeType)r   r   r   )okauthr   ry   sample_childrenchildren_count_sample)app.backend.utilsr   _service_for_configr   r-   r   executelistr#   r   len)configgdriveservicemetachildrenr   fs          r   test_drive_connectionr   P  s:   @((0G	((%" 
 


 
 	 		&''((HI,"&* 
 

 
  LL!'RE))((4.HHV$,
 
 55;f155CTU
 "%U 
s   4=E )r4   None)rM   dict[str, Any]r?   r   r4   r   )rV   r   r4   zdict[str, str])rV   r   r4   ztuple[CredKind, dict[str, Any]])rV   r   r4   r   )r4   r   )r   r   ry   r   rz   z
str | Noner   r   rw   r   r4   zDriveCustomerConfig | None)r   r   r   r   r4   r   )r   r   r   r   r4   r   r   )r   r   r   z
int | Noner4   r   )r   Session | Noner   r   r4   r   )r   r   r   r   r4   r   )r   r   r4   r   )#r:   
__future__r   r/   rt   dataclassesr   pathlibr   typingr   r   sqlalchemy.ormr   app.backend.core.configr	   r   r   r5   r   r   DriveSchoolConfigrP   rZ   ra   rc   ro   rv   r{   r   r   r   r   r   r   r   r   r   <module>r      s   V "  	 !   " , `  -.8
 $m m m@ (  FJ "J$D
B  $00 0 	0
 0 0  0f!H ,0		(		C*(r   