
    Sivl              	          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
 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mZ d dlmZ d dlmZ d dlmZmZmZm Z m!Z!m"Z" d dl#m#Z#m$Z$ d dl%m&Z& d dl'Z'd dl(Z(d dl)m*Z* d dl+m,Z,m-Z-  e'j\                  e/      Z0d8dede1fdZ2de3fdZ4de5de5e6   fdZ7dede5e6   fdZ8	 d8dede1de1de1fdZ9 G d d e,      Z: G d! d"e,      Z; ed#d$g%      Z<e<j{                  d&       ee
      fd'e:defd(       Z>e<j{                  d)       ee
      fd'e;defd*       Z?e<j{                  d+       e        ee
      fd,edefd-       Z@e<j{                  d.       ee       ee
      fde1d/e&defd0       ZAe<j{                  d1       ee       ee
      fd2e1d/e&defd3       ZBe<j                  d4       ee       ee
      fd/e&defd5       ZDe<j{                  d6       e        ee
      fd,edefd7       ZEy)9    )	APIRouterDependsstatusHTTPException)JSONResponse)OAuth2PasswordRequestForm)get_db)Session)funcor_)AuthenticationClass)RolClass)
AuditClass)EmailServiceClass)get_current_active_user)users_rol_period_clause)RolModelProfessionalModelProfessionalTeachingCourseModelSchoolModel	UserModelUsersRolModel)datetime	timedelta)	UserLoginN)quote)	BaseModelFielddbuser_idc           
         | j                  t        j                  t        j                  t        j                  t        j
                        j                  t        t        j                  t        j                  k(        j                  t        j                  |k(  t        t        j                  dk(  t        j                  j                  d       t        j                  dk(        t        t        j                  dk(  t        j                  j                  d       t        j                  dk(        t        |d            j                  t        j                  j!                               j#                         }t%        |      S )Nr      r"   bypass_global_rol_ids)queryr   idrolcustomer_id	school_idjoinr   rol_idfilterr    r   deleted_status_idis_r   order_byascall!_dedupe_roles_for_login_selection)r   r    period_yearrowss       K/var/www/pie360backend.cl/public_html/app/backend/routes/authentications.py_active_user_rolesr7       s   
KKLL  		
 
m]11X[[@	A	!!W,//14//33D9$$)
 **a/**..t4q 
 $KtL

 
(++//#	$	/ 	2 -T22    returnc                 X    t        | xs d      j                         j                         S )N )strstriplower)rol_texts    r6   _normalize_rol_display_keyr@   =   s#    x~2$$&,,..r8   	role_rowsc                    i }| D ]!  }t        |j                        }||vs|||<   # t        |j                         d       }i }|D ]!  }t	        |j
                        }||vs|||<   # t        |j                         d       }|D cg c]1  }|j                  |j
                  |j                  |j                  d3 c}S c c}w )ui  
    Asignaciones en users_rols pueden apuntar a varios registros en rols con el mismo nombre
    (clones por colegio). Para /select-role debe haber una sola opción por rol lógico.
    Representante estable: menor RolModel.id entre los que el usuario tiene activos en users_rols.
    La lista siguiente de colegios ya filtra por RolModel.rol coincidente.
    c                 ,    t        | j                        S Nintr'   xs    r6   <lambda>z3_dedupe_roles_for_login_selection.<locals>.<lambda>M   s    QTT r8   keyc                 ,    t        | j                        S rD   rE   rG   s    r6   rI   z3_dedupe_roles_for_login_selection.<locals>.<lambda>S   s    SY r8   r,   r(   r)   r*   )rF   r'   sortedvaluesr@   r(   r)   r*   )rA   by_rol_table_idrridunique_rowsby_namerK   ordereds           r6   r3   r3   A   s     O %!$$io%#$OC % //17JKKG (/gGCL W^^%+>?G   dd55==		
  s   6Crolesc           	      (   |D ch c]  }t        |j                  dd             }}d|v rd|vr| j                  t              j	                  t        j
                  dk(  t        t        j                  dk(  t        j                  j                  d                   j                         }|r^|j                  t        |j
                        |j                  xs d|j                  |j                  d       |j                  d        |S c c}w )	Nr,   r      r"   zSuper AdministradorrM   c                 8    t        | j                  dd            S )Nr,   r   )rF   getrG   s    r6   rI   z8_ensure_superadmin_if_admin_equivalent.<locals>.<lambda>s   s    Sx);%< r8   rJ   )rF   rZ   r&   r   r-   r'   r   r.   r/   firstappendr(   r)   r*   sort)r   rV   rQ   role_idssuperadmin_rows        r6   &_ensure_superadmin_if_admin_equivalentr`   _   s    167AAEE(A&'7H7H}(*HHXVq H..!3X5O5O5S5STX5YZ UW 	 LL!."3"34)--F1F#1#=#=!/!9!9	 JJ<J=L) 8s   "Dr)   r,   c                 T   | j                  t              j                  t        j                  |k(  t        j                  dk(        }|dv rg S | j                  t
              j                  t
        j                  |k(  t        t
        j                  dk(  t
        j                  j                  d                   j                         }|sg S t        |      dk(  r|j                         }n| j                  t
        j                        j                  t        t        j                  t
        j                  k(        j                  t        j                   |k(  t        t        j                  dk(  t        j                  j                  d             t
        j                  |k(  t
        j"                  |j"                  k(  t        t
        j                  dk(  t
        j                  j                  d             t
        j                  j%                  d       t'        |d            j)                         j                         }|D 	cg c]  }	|	s|	d   t        |	d          }
}	|
r=|j                  t        j                  j+                  |
            j                         }nI|j                  r;|j                  t        j                  |j                  k(        j                         }ng }|D cg c]  }|j                  |j                  |j                  |j,                  |j.                  |j0                  |j2                  |j4                  r|j4                  j7                  d      nd |j8                  r|j8                  j7                  d      nd d	 c}S c c}	w c c}w )Nr   )r   NrX   r#   r$   %Y-%m-%d %H:%M:%S)	r'   r)   r.   school_nameschool_addressdirector_namecommunity_school_password
added_dateupdated_date)r&   r   r-   r)   r.   r   r'   r   r/   r[   rF   r2   r*   r+   r   r,   r    r(   isnotr   distinctin_rc   rd   re   rf   rg   strftimerh   )r   r)   r,   r    r4   
base_queryrol_rowr5   same_role_school_idsrH   allowed_idsss               r6   #_available_schools_for_current_rolerr   w   s    +&--;.%%*J 	 		KK6!**a/1K1K1O1OPT1UV

 
  	 6{a~~
 HHX''(T-!5!5!DEV%%0M33q8-:Y:Y:]:]^b:cd$$3+H..!3X5O5O5S5STX5YZ""((.'4P XZSU 	 +?YQ!!HXs1Q4yYY$$[^^%7%7%DEIIKD$$[^^w7H7H%HIMMODD   $$==!"!4!4==..__)*)D)DHI!,,//0CDZ^LMNNANN334GH`d
	
  Zs   
N N N 6B'N%c                   .    e Zd ZU  eddd      Zeed<   y)ForgotPasswordBody.      
min_length
max_lengthemailN)__name__
__module____qualname__r   rz   r<   __annotations__ r8   r6   rt   rt      s    sqS9E39r8   rt   c                   L    e Zd ZU  edd      Zeed<    eddd      Zeed<   y	)
ResetPasswordBody.
   )rx   token      rw   new_passwordN)r{   r|   r}   r   r   r<   r~   r   r   r8   r6   r   r      s&    sr*E3*caC@L#@r8   r   z/authenticationsAuthentications)prefixtagsz/forgot-passwordbodyc                    | j                   j                         j                         }ddd}	 |j                  t              j                  t        j                  t        j                         |k(  t        j                  dk(        j                         }|r|j                   xs dj                         rt        |      }|j                  |j                        \  }}t        j                  d      xs dj                  d      }| d	t        |d
       }	t!               }
|
j#                  |	|j$                  xs dj                         xs d|      }|
j'                  |j                   j                         d|d|	       }|st(        j+                  d       t1        t2        j4                  |      S # t,        $ r t(        j/                  d       Y ;w xY w)u   
    Recuperación de contraseña: siempre responde igual (no revela si el correo existe).
    Si el usuario existe y SMTP está configurado, envía correo HTML con enlace JWT.
       ub   Si el correo está registrado en Pie360, recibirás instrucciones para restablecer tu contraseña.)r   messager   r;   FRONTEND_PUBLIC_URLzhttp://localhost:5173/z/reset-password?token=)safeN)	reset_url	user_nameexpires_minutesu"   Pie360 — Restablecer contraseñau@   Restablece tu contraseña abriendo este enlace en el navegador:
)
text_plainzLforgot-password: usuario encontrado pero no se pudo enviar el correo (SMTP).z7forgot-password: error interno (no expuesto al cliente)status_codecontent)rz   r=   r>   r&   r   r-   r   r.   r[   r   create_password_reset_tokenr'   osgetenvrstripr   r   password_reset_email_html	full_name	send_htmlloggerwarning	Exception	exceptionr   r   HTTP_200_OK)r   r   
email_normgenericuserauthr   minutes_usedbaser   mailerhtmlsents                r6   forgot_passwordr      s    !!#))+JwG
 THHYV

9??+z9++q0 UW 	 TZZ%2,,.&r*D"&"B"B477"KE<II34O8OWWX[\D& 6uU7L6MNI&(F33#>>/R668@D , 4 D
 ##

  "4^_h^ij	 $ D b F$6$6HH  TRSTs   E1F; ;GGz/reset-passwordc           	      *   	 t        |      }|j                  | j                  j                               }|j	                  t
              j                  t
        j                  |k(  t
        j                  dk(        j                         }|st        t        j                  dddd      S |j                  | j                        |_        t!        j"                         |_        |j'                          t        t        j(                  dddd      S # t*        $ r9}t        |j,                  |j,                  |j.                  dd      cY d}~S d}~wt0        $ r5}t        t        j2                  d	d
t5        |       dd      cY d}~S d}~ww xY w)uU   Restablece contraseña con el token recibido por correo (JWT purpose=password_reset).r     u@   No se pudo restablecer la contraseña. Solicita un nuevo enlace.Nr   r   datar   r   u&   Contraseña actualizada correctamente.  u%   Error al restablecer la contraseña: )r   decode_password_reset_tokenr   r=   r&   r   r-   r'   r.   r[   r   r   HTTP_400_BAD_REQUESTgenerate_bcrypt_hashr   hashed_passwordr   utcnowrh   commitr   r   r   detailr   HTTP_500_INTERNAL_SERVER_ERRORr<   )r   r   r   r    r   es         r6   reset_passwordr      sX   )
"2&224::3C3C3EFHHYVILLG+Y-H-HA-MNUW 	
 "77!a    $889J9JK$OO-
		**C
 	
  
 }}4P
 	
  
==B3q6(K
 	

s7   B)D ,A'D 	F.EFF*FFFz/login	form_datac                    	 t        |      j                  | j                  | j                        }|d   }t	        |t        |d               }t        ||      }|st        dd      t        |      dkD  rt        d      }t        |      j                  t        |d	         d
|j                  d      d t        j                         j                  d|      }i d|d|d   d|d   dd
d|j                  d      dd dd dddg dd d|d   d	|d	   ddd|j!                         ddd|}n9t        |d
   d         }|rt#        |      j                  |      nd }	d}
t%        |	t&              rd|	v r|	d   j                  dd      }
t%        |	t&              r3|	j                  d      r"|	j                  di       j                  dg       ng }|j                  d      }d }d }t        d      }t        |d	         |||d d t        j                         j                  d}t        |      j                  ||      }||d   |d   |||||
|d |d   |d	   d|j!                         d d!}	 t)        |      j+                  |d   |j                  d      "       t1        t2        j4                  d$d%|d&'      S # t,        $ r!}t/        d#t        |              Y d }~Dd }~ww xY w# t        $ r9}t1        |j6                  |j6                  |j8                  d d&'      cY d }~S d }~wt,        $ r5}t1        t2        j:                  d(d)t        |       d d&'      cY d }~S d }~ww xY w)*N	user_datar'   i  z#El usuario no tiene roles asignadosr   r   r"    minutesrz   r   r)   )subr,   r)   r*   r4   access_tokenr    rutr,   r*   schoolr(   r;   permissionsprofessional_teaching_courser   
token_typebearer
expires_inrequires_role_selectionTavailable_rolesrol_datar   r,   r)   r*   teaching_id	course_idr4   Fr   r    r   r,   r)   r*   r   r(   r   r   r   rz   r   r   r   )r    r,   u(   Error guardando registro de auditoría: r   zLogin successfulr   r   r   Internal server error: )r   authenticate_userusernamepasswordr7   rF   r`   r   lenr   create_tokenr<   rZ   r   nowyeartotal_secondsr   
isinstancedictr   storer   printr   r   r   r   r   r   )r   r   r   r   
user_rolestoken_expiresr   r   chosen_rol_id
rol_resultrol_namer   r)   r*   school_data
token_dataaudit_errorr   s                     r6   loginr   )  s   r
"2&889K9KYM_M_`%	'C	$,@A
;B
K
C8]^^ z?Q%g6M'+88y12#,==#?!%#+<<>#6#6 	E9T? y' !	
 y}}]; T $ r r / Y{3 7+ h m99; *4  ":!D&  
1h 78M<I"))-8tJH*d+
j0H%j155eR@S]^hjnSot~  uC  uC  DN  uO*..R8<<]BO  UWK#--6KIK%g6M9W-.'*&#!'||~22J (+88]SE %$T? ''*&%*04&{3"7+&+99;+0D$	QrN  !$xx) !  **-
 	
  	Q<S=M<NOPP	Q  
--88
 	
  
==4SVH=
 	

sZ   I/K, 2.J?  K, ?	K)K$K, $K))K, ,	M*5.L)#M*)M*5*M%M*%M*z/select-role/{rol_id}session_userc                 d   	 |j                  t              j                  t        j                  |j                  k(        j                  t	        t        j
                  dk(  t        j
                  j                  d                   j                         }|st        dd      |j                  t        j                        j                  t        j                  |j                  k(  t        j                  | k(  t	        t        j
                  dk(  t        j
                  j                  d       t        j                  dk(        t        t        |dd       d            j                         }|st        |       dk(  r|j                  t        j                        j                  t        j                  |j                  k(  t        j                  d	k(  t	        t        j
                  dk(  t        j
                  j                  d             t        t        |dd       d            j                         }|st        d
d      t        d
d      t        |      j!                  |       }d}g }t#        |t$              r.d|v r*|d   j!                  dd      }|d   j!                  dg       }d }	d }
t'        d      }t        |dd       }|t)        j*                         j,                  }t/        |      j1                  t3        |j4                        t        |       |j6                  |	d d |d|      }||j                  |j8                  t        |       |j6                  |	|
||d |j:                  |j4                  d|j=                         dd}t?        t@        jB                  dd|d      S # t        $ r9}t?        |jD                  |jD                  |jF                  d d      cY d }~S d }~wtH        $ r5}t?        t@        jJ                  ddt3        |       d d      cY d }~S d }~ww xY w)Nr     User not foundr   r"   r4   r#   r$   rX     zRol no asignado a este usuarior;   r   r(   r   r   r   r   r   Fr   r   zRole selected successfullyr   r   r   r   )&r&   r   r-   r'   r   r.   r/   r[   r   r   r    r,   r   getattrrF   r   rZ   r   r   r   r   r   r   r   r   r<   rz   r)   r   r   r   r   r   r   r   r   r   r   )r,   r   r   user_rowrel	admin_relr   r   r   r*   r   r   py_tokr   r   r   s                   r6   select_roler     s   h
HHYVILLLOO34VC	33q8):U:U:Y:YZ^:_`aUW	 	 C8HII HH]%%&V%%4$$.!33q8!3377=!((A-
 (L->VZ UW 	  6{aHH]--.V%--<%,,1M;;q@-BaBaBeBefjBkl/#L-F^b	 UW  !'C@`aa#<\]]b\%%f-
j$'J*,D!*-11%<H$Z044]BGK 	!'2}d;>\\^((F#B'448>>*f+'33&#!% 
 "{{<<&k#//"!&,0!++^^"'557',
$ **"/KUYZ
 	
  
 }}4P
 	
  
=="1HQ/Q[_`
 	

s0   N.N1 1	P/:.O.(P/.P/:*P*$P/*P/z/select-school/{school_id}r*   c                 *	    	 |j                  t              j                  t        j                  |j                  k(        j                  t	        t        j
                  dk(  t        j
                  j                  d                   j                         }|st        dd      t        t        |dd      xs d      }|j                  }|rt        |      j                  |      nd }d}g }t        |t              r.d|v r*|d   j                  dd      }|d   j                  d	g       }t!        |||t        |j                        t        |d
d             }	t#         fd|	D        d       }
|
st%        t&        j(                  ddd d      S |
}d }d }d }d }|dvr|j+                         dk7  r|j                  t,        j                        j                  t,        j.                  |j                  k(        j1                  t,        j                  j3                               j                         }|rt        |d         nd }||j                  t4              j                  t4        j6                  |k(  t4        j
                  dk(        j                         }|r|j8                  }|j:                  }|j                  |j6                  |j8                  |j:                  |j<                  r|j<                  j?                  d      nd |j@                  r|j@                  j?                  d      nd d}tC        d      }t        |d
d       }|tE        jF                         jH                  }tK        |jL                        || |||d}tO        |      jQ                  ||      }|jS                         }||j                  |jT                  ||nd| ||||||jV                  |jL                  d|d}t%        t&        jX                  dd|d      S # t        $ r9}t%        |jZ                  |jZ                  |j\                  d d      cY d }~S d }~wt^        $ r5}t%        t&        j`                  ddtK        |       d d      cY d }~S d }~ww xY w)Nr   r   r   r   r,   r;   r   r(   r   r4   c              3   X   K   | ]!  }t        |d          t              k(  s| # yw)r'   N)rF   ).0rq   r*   s     r6   	<genexpr>z select_school.<locals>.<genexpr>'  s$     Y!#ag,#i.:XAYs   **r   z4School not found or does not belong to your customerr   r   )r"   rX   coordinadorrb   )r'   professional_idr   r   rg   rh   r   r   r   r   )r   r    r   r,   r)   r*   r   r(   r   r   r   r   rz   r   r   r   zSchool selected successfullyr   r   )1r&   r   r-   r'   r   r.   r/   r[   r   rF   r   r)   r   rZ   r   r   rr   nextr   r   HTTP_404_NOT_FOUNDr>   r   r    r0   descr   r   r   r   rg   rl   rh   r   r   r   r   r<   rz   r   r   r   r   r   r   r   r   r   r   )r*   r   r   r   user_rol_idr)   r   r   r   allowed_schoolsr   school_dictr   ptc_teaching_idptc_course_idprofessional_id_valprof_pkptcr   r   r   r   expires_in_secondsr   r   s   `                        r6   select_schoolr    s/   F
HHYVILLLOO34VC	33q8):U:U:Y:YZ^:_`aUW	 	 C8HII',!<AB** 7BXb\%%k2t
j$'J*,D!*-11%<H$Z044]BGK=[#hkk*:GLR_ae<f
 YY[_`"55!U   " (,$"f$)9])J *--.)11X[[@A+..3356	  6=#gaj/$".hh>?FF3CCGZZ3EEJ %' 
 &)ooO$'MMM!ff+.+>+>'*%(]]VYVdVdcnn&=&=>Q&RjnZ]ZjZj(8(8(A(ABU(Vpt40 "'2}d;>\\^((Fx~~&!&"*&!

 $B'44ZO*88: "{{<<%0%<k!&"!&2,H!++^^",
$ **9
 	
  
--88
 	
  
==4SVH=
 	

s7   FP JP 	R.QRR*RRRz/available-schoolsc                    	 t        t        | dd      xs d      }t        t        | dd      xs d      }|dk  s|dk  rt        t        j                  ddg d      S t        |||t        | j                        t        | dd             }t        t        j                  d	d
|d      S # t        $ r5}t        t        j                  ddt        |       g d      cY d }~S d }~ww xY w)Nr)   r   r,   r   u0   Rol o cliente inválido para seleccionar colegior   r   r4   r   OKr   r   )rF   r   r   r   r   rr   r'   r   r   r   r<   )r   r   r)   r   r   r   s         r6   available_schoolsr
    s    
',qAFQG',!<AB!{a/"77#&3eoqr 
 3[#loo*>Vcei@j
 **"tTB
 	
  
=="1HQ/Q[]^
 	

s%   AB+ AB+ +	C)4*C$C)$C)z/logoutc           	      `   	 t        |      j                  | j                  | j                        }t	        d      }|d   }t        |      j                  dt        |d         i|      }||j                  d      |j                  d      dd	}t        t        j                  d
d|d      S # t        $ r9}t        |j                  |j                  |j                  d d      cY d }~S d }~wt        $ r5}t        t        j                  ddt        |       d d      cY d }~S d }~ww xY w)Nr   r   r   r   rz   r   r,   r   )r   r   r,   r   r   zLogout successfulr   r   r   r   )r   r   r   r   r   r   r<   rZ   r   r   r   r   r   r   r   r   )r   r   r   access_token_expiresudaccess_token_jwtr   r   s           r6   logoutr    s(   &
"2&889K9KYM_M_`(9+.r2??BwKHX@Y[op -66%=ffX&"	
 **.
 	
  
--88
 	
  
==4SVH=
 	

s0   B,B/ /	D-8.C,&D-,D-8*D("D-(D-rD   )Ffastapir   r   r   r   fastapi.responsesr   fastapi.securityr   app.backend.db.databaser	   sqlalchemy.ormr
   
sqlalchemyr   r   (app.backend.classes.authentication_classr   app.backend.classes.rol_classr   app.backend.classes.audit_classr   app.backend.classes.email_classr   app.backend.auth.auth_userr   "app.backend.utils.users_rol_periodr   app.backend.db.modelsr   r   r   r   r   r   r   r   app.backend.schemasr   loggingr   urllib.parser   pydanticr   r   	getLoggerr{   r   rF   r7   r<   r@   listr   r3   r`   rr   rt   r   authenticationspostr   r   r   r   r  rZ   r
  r  r   r8   r6   <module>r%     s   = = * 6 * "   H 2 6 = > F  ) )  	  % 
		8	$37 3S 3:/C / $t* <w tDz 2 KO@@!@+.@9<@F: :A	 A
 
	 ()<CFO -I, -I' -I *-I` '(:A&/ +
* +
 +
 )+
\ h18'RX/ s
. s
 s
  s
l -.7>?V7Wgnougv i
 i
9 i
]d i
 /i
V 23<CD[<\lstzl{ G
S G
	 G
bi G
 4G
T )*078O0P`ghn`o 
I 
V] 
 +
. i 29)7SY? '
/ '
 '
 !'
r8   