+
    i|                        ^ RI Ht ^ RI HtHtHtHtHtHtH	t	 ^ RI
t
^ RIt^ RIt^ RIHt ^ RIHtHt ^ RIt^ RIt^ RIHtHtHt ^ RIHt ^ RIHtHtHt ^ R	I HtHtHtH	t	Ht ^ R
IHt ^ RIt^ RIHt ^ RI H!t! ^ RI"H#t# ^ R	I HtHtHtH	t	Ht ^ RIt^ RIHt ^ RI$t$R t% ! R R4      t&R t'R t(R t)R t*RR lt+R t,RR lt-R# )    )current_app)Flaskrender_templatesessionjsonifyrequestredirecturl_forN)Message)
save_Tokenconsultar_profile)ConfigHostSCHEME)wraps)datetime	timedeltatimezone)r   r   r	   r
   r   )r   )get_connection)MIMEMultipart)MIMEText)r   c                  B    \        \        P                  R ,          4      # )
SECRET_KEY)strappconfig     _C:\Users\victor.barrera\Documents\proyectos\elepV3\Elep\src\App\Security_Module\UserPassword.py<lambda>r        s    SL12r   c                   4   a  ] tR t^$t o RtR tRR ltRtV tR# )EmailSenderuK   
Clase para el envío de correos electrónicos sin depender de Flask-Mail.
c                B    Wn         W n        W0n        W@n        WPn        R# )u  
Inicializa el objeto EmailSender con configuración.

Args:
    mail_server: Servidor SMTP
    mail_port: Puerto SMTP
    mail_use_tls: Usar TLS para la conexión
    mail_username: Usuario para autenticación SMTP
    mail_password: Contraseña para autenticación SMTP
N)smtp_server	smtp_portuse_tlssender_emailsender_password)selfmail_server	mail_portmail_use_tlsmail_usernamemail_passwords   &&&&&&r   __init__EmailSender.__init__)   s      '"#),r   Nc                <   V'       g   V'       g   \        R4      h\        V\        4      '       d   V.p\        R4      pW%R&   V P                  VR&   RP                  V4      VR&   V'       d   VP                  \        VR4      4       V'       d   VP                  \        VR4      4        \        P                  ! V P                  V P                  4      ;_uu_ 4       pV P                  '       d   VP                  4        VP                  V P                  V P                  4       VP!                  V4       R	R	R	4       R
#   + '       g   i     R
# ; i  \"         d8   p\%        RT 24       \%        \&        P(                  ! 4       4        R	p?R# R	p?ii ; i)uP  
Envía un correo electrónico.

Args:
    recipients: Lista de destinatarios o un solo destinatario
    subject: Asunto del correo
    html_content: Contenido HTML del correo (opcional)
    text_content: Contenido de texto plano del correo (opcional)
    
Returns:
    True si el correo se envió correctamente, False si hubo un error
z:Debe proporcionar contenido HTML o de texto para el correoalternativeSubjectFromz, ToplainhtmlNTError al enviar correo: F)
ValueError
isinstancer   r   r'   joinattachr   smtplibSMTPr$   r%   r&   starttlsloginr(   send_message	Exceptionprint	traceback
format_exc)r)   
recipientssubjecthtml_contenttext_contentmsgserveres   &&&&&   r   
send_emailEmailSender.send_email:   s9    LYZZ j#&&$J M* I''FIIj)D	 JJxg67 JJxf56	d..??6<<<OO%T..0D0DE##C(	 @
  @?
  	,QC01)&&()	s7   .3E !AE;E E	E E F$,FF)r'   r(   r%   r$   r&   )NN)	__name__
__module____qualname____firstlineno____doc__r/   rM   __static_attributes____classdictcell__)__classdict__s   @r   r"   r"   $   s     -"- -r   r"   c                    \        V4      p\        V4      pV'       g   \        RR/4      R3# VR,          pVR,          p\        P                  ! \
        P                  4      \        RR7      ,           pRVR	VRVR
VP                  4       /pTp	Tp
Tp\        R\        \        4       4      4       \        R\        4       4       \        P                  ! V\        4       RR7      p\        V\        4      '       d   VP!                  R4      p\#        W<4      pVf   \        RRV R2/4      R3#  \$         R\&         RV RV
 RV	 RV 2pT	pRVRV/pRp\)        RVR7      pRp \+        VV P,                  R,          V.R7      pVVn        VP1                  V4       R pT'       g   \        RR(/4      R)3# \        R*TR+TR,T/4      #   \2         d   p\        R!T 24        \5        T P,                  R",          T P,                  R#,          T P,                  R$,          T P,                  R,          T P,                  R%,          4      pTP7                  TTTR&7      p Rp?L  \2         d3   p\        R'T 24       \        \8        P:                  ! 4       4       h Rp?ii ; iRp?ii ; i  \2         dW   p\        R-T R.24       \        R/\8        P:                  ! 4        R.24       \        RR0\=        T4       2/4      R)3u Rp?# Rp?ii ; i  \2         do   p\        R1T R.24       \        R2\        T4       R.24       \        R/\8        P:                  ! 4        R.24       \        RR3\=        T4       2/4      R)3u Rp?# Rp?ii ; i)4uD   
Genera un token JWT y envía un correo de activación al usuario.

errorz(No se pudo obtener el perfil del usuario  NombreEmail  minutesIDusernameexpzTipo de SECRET_KEY:zValor de SECRET_KEY:HS256	algorithmutf-8NEl usuario con ID  no existe en el sistemaz:///password_confirm?token=&userid=&email=&name=activation_url	user_nameu   Configuración de passwordSecurity/UserPasswordemail.htmldataFMAIL_USERNAMEsenderrF   TzError al usar Flask-Mail: MAIL_SERVER	MAIL_PORTMAIL_USE_TLSMAIL_PASSWORD)rH   zError al usar EmailSender: u*   No se pudo enviar el correo de activación  tokentoken_id
email_sentu-   ===== Error al enviar correo de activación:  ========== Traceback completo: r8   z&===== Error en send_activation_email:    ===== Tipo de excepción: Error: )intr   r   r   nowr   utcr   	timestamprC   typer   jwtencoder:   bytesdecoder   r   r   r   r   r   r7   sendrB   r"   rM   rD   rE   r   )r   mailUserID_UserIDprofile_datarZ   r[   exp_timetoken_payloadrecipient_emailuser_idrm   ry   rz   rl   destinatariorp   asuntorH   r{   rJ   rL   email_sendere2s   &&&                     r   send_activation_emailr   i   s   
|;W(0G%OPQSVVVh'W% <<-	$0GG&f8%%'	
  	#T*,%78$jl3

L
 eU##LL)E f, -fX5MN  F	P &xs4&0HxX_W``ghwgxx~  @I  J  KN*L .YD 2F ++LSWXL J$::o6 ,~ ( 		#!
2 )UVWY\\\ Hj  9  21#67#.

=1

;/

>2

?3

?3$L ".!8!8$%1 "9 "J
 ! 7t<=)..01%D  	PA!FKL.y/C/C/E.FfMNG'?Ax%HIJCOO	P
  ;6qc@A*47)6:;*9+?+?+A*B&IJ73q6(!345s::;s   ,L
 C?L
 04J& %:G J& 'J& 6J& J#J!A8IJ& J)-JJJJ##J& &L1AL<L=L
 LL
 
NA#M>8N>Nc                     \         P                  ! V \        4       R.R7      pV#   \         P                   d     R# \         P                   d     R# i ; i)u   
Verifica que un token JWT sea válido

Args:
    token: Token JWT a verificar
    
Returns:
    Datos del payload si es válido, None si no lo es
rb   )
algorithmsN)r   r   r   ExpiredSignatureErrorInvalidTokenError)ry   payloads   & r   verify_tokenr      sK    **UJLgYG$$    s   #& AAAAc                 D   a  S P                   ! R R.R7      V 3R l4       pV# )z$/Tokensign/<UserID>/<Email>/<Nombre>GETmethodsc                   <  V '       d   V'       d	   V'       g   \        R 4       \        RR/4      R3# \        R4       \        P                  ! \        P
                  4      \        RR7      ,           pRV RVR	VR
V/p\        RV R24       SP                  P                  R4      '       g   \        R4       \        RR/4      R3# \        R4       \        P                  ! V\        4       RR7      p\        V\        4      '       d   VP                  R4      p\        R\        V4       RV R24       \        R4       \!        W4      pVf#   \        RV  R24       \        RRV  R2/4      R3# \        RV R24       \        R4       \#        4       pVP%                  VVV VR 7      p\        R!4       \        R"VR#VR$V/4      #   \&         do   p	\        R%T	 R24       \        R&\        T	4       R24       ^ RIp
\        R'T
P*                  ! 4        R24       \        RR(\-        T	4       2/4      R3u Rp	?	# Rp	?	ii ; i))z%===== Error: Campos incompletos =====rX   z!Todos los campos son obligatorios  u*   ===== Iniciando generación de token =====r\   r]   r_   r`   rZ   ra   z===== Token payload preparado: r|   r   z,===== Error: SECRET_KEY no configurada =====u&   Configuración del servidor incompletarx   z ===== Iniciando jwt.encode =====rb   rc   re   z===== Token generado (tipo: z): z,===== Guardando token en base de datos =====Nz===== Error: El UserID z" no existe en la tabla Users =====rf   rg   rY   z===== Token guardado con ID: u*   ===== Enviando correo de activación =====)r   rm   r   ry   z%===== Preparando respuesta JSON =====ry   rz   r{   z===== Error en generar_token: r~   r}   r   )rC   r   r   r   r   r   r   r   getr   r   r   r:   r   r   r   r   r"   r   rB   rD   rE   r   )r   r[   rZ   r   r   ry   rz   r   r{   rL   rD   r   s   &&&        r   generar_token!Token_sign.<locals>.generar_token   sX   C	?f=>)LMNPSSS >?||HLL1Id4KKHfE&x	M 3M?&IJ ::>>,//DE)QRSUXXX45JJ!E %''W-0eSvNO@A!&0H /x7YZ[1&9QR    1(6BC>?&=L%;; % 	 < J 9:Hj    	?21#V<=.tAwiv>?.y/C/C/E.FfMNGws1vh%7893>>	?sA   G G G G BG 	B)G 3AG IA#H<6I<Iroute)r   r   s   f r   
Token_signr      s/    YY5wGE? HE?L r   c                 <    V P                   ! R R.R7      R 4       pV# )z	/activater   r   c            
         \         P                  P                  R 4      p \         P                  P                  R4      p\         P                  P                  R4      p\         P                  P                  R4      pV '       d	   V'       g   \        RRR7      #  Rp\	        4       ;_uu_ 4       pVP                  4       pVP                  WAV .4       VP                  4       pV'       g   \        RRR7      uuR	R	R	4       # Vw  rrV'       d   \        RR
R7      uuR	R	R	4       # \        P                  ! 4       V
8  d   \        RRR7      uuR	R	R	4       #  \        P                  ! V \        4       R.RR/R7      pRpTP                  Y.4       RpTP                  Y.4       TP                  4        \        RRT;'       g    TP                  RR4      R7      uuR	R	R	4       #   \        P                   d    \        RRR7      u uuR	R	R	4       # \        P                   d    \        RRR7      u uuR	R	R	4       # i ; i  + '       g   i     R	# ; i  \          d&   p\#        RT 24       \        RRR7      u R	p?# R	p?ii ; i)ry   useridemailnameSecurity/UserPassword.htmlu-   Enlace de activación inválido o incompleto.)message
                SELECT ActivationTokenID, Token, ExpiresAt, IsUsed 
                FROM ActivationTokens 
                WHERE UserID = ? AND Token = ?
                Token no encontrado o inválido.Nu0   Este enlace de activación ya ha sido utilizado.u%   El enlace de activación ha expirado.rb   
verify_expTr   optionsEl token ha expirado.   Token inválido.
                    UPDATE ActivationTokens 
                    SET IsUsed = 1 
                    WHERE ActivationTokenID = ?
                z
                    UPDATE Users 
                    SET Status = 'ACTIVO' 
                    WHERE UserID = ?
                exitorZ   Usuario)r   r   u   Error durante la activación: u,   Ha ocurrido un error durante la activación.)r   argsr   r   r   cursorexecutefetchoner   utcnowr   r   r   r   r   commitrB   rC   )ry   r   r   r   check_token_queryconnr   
token_datarz   db_token
expires_atis_useddecoded_tokenupdate_token_queryupdate_user_queryrL   s                   r   activate_account1activate_account_routes.<locals>.activate_accountK  s`      ),,""8,  )||'G"#?*Y[ [E	Z!  !!T0E2BC#__.
!*+G2TV "! ;E7J *+G2df "!" ??$z1*+G2Y[% "!,F$'JJ"$+9!-t 4	%M&"
 1:>%!
 0)< ''C7+/+Y+Y=3D3DXy3Y[o "!: 00 K*+G2IK K= "!@ ,, F*+G2DF FC "!@FA "!!t  	Z21#67"#?*XZ Z	Zs   I /AI7
I I
I &&I
I %G'=AI
I '"I	I

I I(I6I7
I III	I I J
%J?J
J
r   )r   r   s   & r   activate_account_routesr   J  s.    YY{UG,PZ -PZd r   c                2   \        4       pVP                  4       pRpVP                  WP34       VP                  4       pV'       g   R# RpVP                  Wq34       VP	                  4       pV'       g   R# VP
                  p	V F  p
V
P                  pRpVP                  WV	34       VP	                  4       pV'       g   K>  Vw  rppVR8X  d   V'       d    R# VR8X  d   V'       d    R# VR8X  d   V'       d    R# VR	8X  g   K  V'       g   K   R# 	  R# )
u   
Verifica si el usuario (user_id) tiene permiso de 'read', 'create',
'edit' o 'delete' sobre el m¨®dulo (module_name).

Retorna True/False.
z
        SELECT r.RoleID, r.RoleName
        FROM Roles r
        INNER JOIN UserRoles ur ON r.RoleID = ur.RoleID
        WHERE ur.UserID = ?
    FzO
        SELECT ModuleID
        FROM Modules
        WHERE ModuleName = ?
    z
            SELECT CanRead, CanCreate, CanEdit, CanDelete
            FROM RoleModules
            WHERE RoleID = ? AND ModuleID = ?
        readTcreateeditdelete)r   r   r   fetchallr   ModuleIDRoleID)r   module_nameactionr   r   sql_get_rolesrolessql_get_modulemod_row	module_idrowrole_idsql_check_permissionperm_rowcan_read
can_createcan_edit
can_deletes   &&&               r   user_has_accessr     s     D[[]FM NN=*-OOE N
 NN>>2ooG  I ** 
 	+y-AB??$89A6H(Jh!jh!jj# ( r   c                 r    V P                   ! R R.R7      R 4       pV P                   ! RR.R7      R 4       pV# )z/password_confirmr   r   c                    \         P                  P                  R4      p \         P                  P                  R4      p\         P                  P                  R4      p\         P                  P                  R4      pV '       d	   V'       g   \        RRRR7      #  R	p\	        4       ;_uu_ 4       pVP                  4       pVP                  WAV .4       VP                  4       pV'       g   \        R
RRR7      uuRRR4       # Vw  rrV'       d   \        RRRR7      uuRRR4       # \        P                  ! 4       V
8  d   \        RRRR7      uuRRR4       #  \        P                  ! V \        4       R.RR/R7      pV'       g   VP                  RR4      pV'       g   VP                  RR4      p\        RRT TTTR7      uuRRR4       #   \        P                   d    \        RRRR7      u uuRRR4       # \        P                   d    \        RRRR7      u uuRRR4       # i ; i  + '       g   i     R# ; i  \         d'   p\!        RT 24       \        RRRR7      u Rp?# Rp?ii ; i)ub   
Muestra la página para confirmar/establecer la contraseña.
Verifica el token recibido por URL.
ry   r   r   r   r   F1   Enlace incompleto. Faltan parámetros necesarios.token_validerror_messager   zAccessDened.htmlr   N!Este enlace ya ha sido utilizado.El enlace ha expirado.rb   r   Tr   rZ    r`   r   r   )r   ry   r   r   nombrezError al verificar el token: u8   Ha ocurrido un error durante la verificación del token.)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rB   rC   )ry   r   r   r   r   r   r   r   rz   r   r   r   r   rL   s                 r   password_confirm1password_confirm_routes.<locals>.password_confirm  s_      ),,""8,  )!!&)G"#?.30ce eC	l!  !!T0E2BC#__.
!*+=E  aC  D "! ;E7J *+G6;8[] "!$ ??$z1*+G6;8PR' "!0L$'JJ"$+9!-t 4	%M "!.!2!28R!@  - 1 1*b A ''C26,1.5,1-35a "!L 00 Q*+G6;8OQ QO "!T ,, L*+G6;8JL LW "!TLU "!!n  	l1!56"#?.30jl l	ls   I 0A	H19
I H1
I )'H1
I AG#G5H1
I #H.3H14
I ?H.H.!H1"
I -H..H11I	<I I I6I1+I61I6z/set_passwordPOSTc            
         \         P                  ! 4       p V '       g   \        RRRR/4      R3# V P                  R4      pV P                  R4      pV P                  R4      pV P                  R	4      pV'       d   V'       d   V'       d	   V'       g   \        RRRR
/4      R3# W48w  d   \        RRRR/4      R3# Rp\	        4       ;_uu_ 4       pVP                  4       pVP                  WRV.4       VP                  4       pV'       g   \        RRRR/4      R3uuRRR4       # Vw  rpV'       d   \        RRRR/4      R3uuRRR4       # \        P                  ! 4       V
8  d   \        RRRR/4      R3uuRRR4       # \        P                  ! ^R7      p\        P                  ! VP                  R4      V4      P                  R4      p\        RV 24       \        R\!        V4       R24       \!        V4      R8  d   \        RRRR/4      R3uuRRR4       # RpVP                  WV.4       RpVP                  W.4       VP#                  4        \        RRRRRR/4      uuRRR4       #   + '       g   i     R# ; i  \$         d6   p\        RT 24       \        RRRR\'        T4       2/4      R3u Rp?# Rp?ii ; i)u=   
Recibe y procesa la contraseña establecida por el usuario.
successFr   zNo se recibieron datos.r   ry   userIdpasswordconfirmPasswordzFaltan datos requeridos.u   Las contraseñas no coinciden.z
                SELECT ActivationTokenID, ExpiresAt, IsUsed 
                FROM ActivationTokens 
                WHERE UserID = ? AND Token = ?
            u   Token no válido.Nr   r   )roundsre   u   Contraseña cifrada generada: zLongitud del hash: z caracteresrx   uE   Error interno: El hash de la contraseña excede el tamaño permitido.z
                    UPDATE Users 
                    SET PasswordHash = ?, Status = 'ACTIVO', LastLogin = GETDATE()
                    WHERE UserID = ?
                r   TuN   Contraseña establecida correctamente. Serás redirigido al inicio de sesión.r	   z/loginu$   Error al establecer la contraseña: )r   get_jsonr   r   r   r   r   r   r   r   bcryptgensalthashpwr   r   rC   lenr   rB   r   )rp   ry   r   r   confirm_passwordr   r   r   r   rz   r   r   salthashed_passwordr   r   rL   s                    r   set_password-password_confirm_routes.<locals>.set_password9  s   
S	p##%D	5)=VWXZ]]]HHW%Ehhx(Gxx
+H#xx(9:x?O	5)=WXY[^^^ +	5)=]^_addd!  !!T0E2BC#__.
!"IuiAT#UVX[[ "! 1;-g "IuiAd#efhkk "! ??$z1"IuiAY#Z[]``! "!& ~~R0"(--0H$"O"V"VW^"_66GHI+C,@+AMN '#-"!5!#j$  7 "!B%!
 0G2LM&"
 1:>to  e "!!!p  	p8<=Iui;_`cde`f_g9hijlooo	ps   J	 J	 AJ	 <J	 J	 J	 J	 %J	 <J	 AI5
J	 'I5
J	 *I59
J	 BI5
J	 !A	I5*
J	 5J	 J	 J	 	K	*K>K	K	r   )r   r   r   s   &  r   password_confirm_routesr    sU    YY"UG4Sl 5Slj 	YY1Wp 2Wpr r   c                    a a S P                   ! R R.R7      V V3R l4       pS P                   ! RR.R7      R 4       p\        # )z/auth/forgot-passwordr   r   c            
       <  \         P                  ! 4       p V '       d   V P                  R4      '       g   \        RRRR/4      R3# V P                  R4      p\	        4       ;_uu_ 4       pVP                  4       pRpVP                  WA.4       VP                  4       pV'       g   \        RRRR	/4      uuR
R
R
4       # Vw  rgpRp	VP                  W.4       VP                  4       p
RpVP                  W.4       VP                  4       pV'       d\   RP                  V Uu. uF&  q'       g   K  VP                  4       '       g   K$  VNK(  	  up4      pVP                  4       '       g   RpMRp\        P                  ! 4       \        ^R7      ,           pRVRVRVRR/p\        P                  ! V\        4       RR7      pRp	VP                  W.4       VP                  4       p
V
'       d"   V
^ ,          pRpVP                  VVVV.4       M:RpVP                  VVVV.4       VP                  4       pV'       d
   V^ ,          MR
pVP!                  4        R
R
R
4       XpRpR\"         RX RX RV RX 2
pRVR VR!V/p \%        R"V R#7      p\'        VSP(                  R$,          V.R%7      pVVn        SP-                  V4       \        RRRR&/4      # u upi   + '       g   i     L; i  \.         dH   p\1        R'T 24       ^ R
Ip\1        TP4                  ! 4       4       \        RRRR(/4      R)3u R
p?# R
p?ii ; i)*us   
Procesa la solicitud de recuperación de contraseña.
Genera un token y envía un correo electrónico al usuario.
r   r   Fr   u   Correo electrónico requeridor   z
                    SELECT UserID, Email, Status
                    FROM Users
                    WHERE Email = ?
                TuT   Si tu correo está registrado, recibirás un enlace para restablecer tu contraseña.Nz
                    SELECT ActivationTokenID 
                    FROM ActivationTokens 
                    WHERE UserID = ? AND IsUsed = 0
                z
                    SELECT FirstName, MiddleName, LastName, SecondLastName
                    FROM Profiles
                    WHERE UserID = ?
                 r   )hoursr_   r`   ra   r   password_resetrb   rc   z
                        UPDATE ActivationTokens
                        SET Token = ?, ExpiresAt = ?, CreatedAt = GETDATE(), IsUsed = 0
                        WHERE ActivationTokenID = ?
                    z
                        INSERT INTO ActivationTokens (UserID, Token, CreatedAt, ExpiresAt, IsUsed)
                        OUTPUT INSERTED.ActivationTokenID
                        VALUES (?, ?, GETDATE(), ?, 0)
                    u   Restaure su contraseñazhttp://rh   ri   rj   rk   rl   rm   ry   rn   ro   rq   rr   ub   Se ha enviado un enlace para restablecer tu contraseña. Por favor, revisa tu correo electrónico.z(Error en solicitud de restablecimiento: uA   Error al procesar la solicitud. Por favor, inténtalo más tarde.rx   )r   r   r   r   r   r   r   r   r;   stripr   r   r   r   r   r   r   r   r   r   r   r7   r   rB   rC   rD   rE   )rp   r   r   r   check_query	user_datar   
user_emailstatusr   existing_tokentraer_nombre
user_data2partNombre_Completoexpiry_timer   	jwt_tokenrz   r   insert_token_queryr   r   r   rl   cuerpo_htmlrJ   rL   rD   r   r   s                                r   request_password_reset8password_recovery_routes.<locals>.request_password_reset  sm   R	##%Dtxx00	5)=\]^`cccHHW%E  !!T
 {G4"OO-	 "!4!#y$  "!& /8+V%!
 0)<!'!2 
 |Y7#__.
&)hh/etX\XbXbXd/e&fO +0022*3&/O 'oo/)!2DD '
;,	!  JJ!L%	%!
 0)<!'!2!  .a0H*&
 NN#5	;PX7YZ*&
 NN#5K7XY //+C),s1v$HA "F &L.F&tf,DYKxX_W``ghrgssy  {J  zK  LN !._D **KRVWK zz/2(>C #CH IIcN4  i 0fS "!D  	<QC@A)&&()5^   		s   K0 K0 K0 #K0 +AK6
K0 A$K%	K3KKK.CK KA<K0 KK-	(K0 0M;<L=7M=Mz/reset-passwordr   c                 6   \         P                  P                  R4      p \         P                  P                  R4      p\        RV  RV R24       V '       d	   V'       g   \        R4       \	        RRR	R
7      #  Rp\        4       ;_uu_ 4       pVP                  4       pVP                  W!V .4       VP                  4       pV'       g]   \        RV R24       VP                  RV.4       VP                  4       p\        RV RV R24       \	        RRRR
7      uuRRR4       # Vw  rxr\        RV RV	 RV
 R24       V
'       d(   \        RV R24       \	        RRRR
7      uuRRR4       # \        P                  ! 4       pW8  d.   \        RV RV RV	 R24       \	        RRRR
7      uuRRR4       #  \        P                  ! V \        4       R.RR/R7      p\        R V R24       VP                  R!4      pV'       d/   VR"8w  d(   \        R#V R24       \	        RRR$R
7      uuRRR4       # VP                  R%R&4      pR'pVP                  W.4       VP                  4       pV'       d   Vw  ppV'       g   TpMR&p\        R(V R)V R24       \        R04       \	        RRT TTTRR17      uuRRR4       #   \        P                   d2   p\        R*T R24       \	        R+RR,R
7      u Rp?uuRRR4       # Rp?i\        P                    d2   p\        R-T R24       \	        R+RR.R
7      u Rp?uuRRR4       # Rp?i\"         dV   p\        R/T R24       R'pTP                  Y.4       TP                  4       pT'       d   Tw  pp Rp?EL R&R&pp Rp?EL
Rp?ii ; i  + '       g   i     R# ; i  \"         dR   p\        R2T R24       ^ RIp\        TP&                  ! 4       4       \	        R+RR3\)        T4       2R
7      u Rp?# Rp?ii ; i)4u^   
Muestra la página para establecer una nueva contraseña.
Verifica que el token sea válido.
ry   r   z!===== reset_password_page: token=z
, user_id=r|   z2===== Error: Falta token o user_id en la URL =====r   Fr   r   r   zB===== Error: Token no encontrado en la base de datos para user_id=zYSELECT ActivationTokenID, Token, ExpiresAt, IsUsed FROM ActivationTokens WHERE UserID = ?z&===== Tokens encontrados para user_id=z: r   Nz===== Token encontrado: ID=z	, expira=z, usado=z$===== Error: Token ya utilizado (ID=z) =====r   z ===== Error: Token expirado (ID=z). Actual: z
, Expira: r   rb   r   Tr   z'===== Token decodificado exitosamente: r   r  z'===== Error: Tipo de token incorrecto: u   Tipo de token inválido.r`   r   z^
                        SELECT Email, Nombre FROM Users WHERE UserID = ?
                    z ===== Usuario encontrado: email=z	, nombre=z!===== Error: Token JWT expirado: zSecurity/AccessDened.htmlr   u"   ===== Error: Token JWT inválido: r   z!===== Error decodificando token: u/   ===== Token válido, mostrando formulario =====)r   ry   r   r   r   is_password_resetz/===== Error inesperado en reset_password_page: u/   Ha ocurrido un error durante la verificación: )r   r   r   rC   r   r   r   r   r   r   r   r   r   r   r   r   r   rB   rD   rE   r   )ry   r   r   r   r   r   
all_tokensrz   r   r   r   r   r   
token_typer   get_user_queryuser_rowdb_emailr   rL   rD   s                        r   reset_password_page5password_recovery_routes.<locals>.reset_password_page1  sU      ),,""8,1%
7)6RSGFG"#?,1.ac cy	j!  !!T0E2BC#__.
!^_f^ggmnoNN#~  BI  AJ  K!'!2JB7)2j\Y_`a*+G496XZ "!  ;E7J3H:YzlRZ[bZccijk @
'RS*+G496Y[- "!6 oo'#<XJkRUQVV`ak`llrst*+G496NP= "!F</$'JJ"$+9!-t 4	%M CM?RXYZ "/!2!26!:J!j4D&D G
|SYZ[./K8=:T Vc "!l *--j"=E&N NN>9=%0H+3(&$$,E!#<UG9VHTZ[\6 GH&'C04*/,3*/+16:<G "!R 00 O=aSGH*+F496MO OW "!\ ,, J>qcHI*+F496HJ Ja "!f ! /=aSGH&N NN>9=%0H(0v(*Bvv/g "!!V  	jCA3fMN)&&()"#>,10_`cde`f_g.hj j		js   ;N< BN(
N< '>N(%
N< 0=N(-
N< 9A0J=)
N< 4A
J=?J=N(2
N< =N%K>.N%/N(3
N< >N%N%M2N%3N(7
N< N%N%A N N(N N( N%%N((N9	3N< 9N< <PAPPP)r   password_recovery_routes)r   r   r  r  s   ff  r   r   r     sU    YY&9W :Wr 	YY 5'2Ij 3IjV $#r   )r   )N).flaskr   r   r   r   r   r   r   r	   r
   osr=   pytz
flask_mailr   &Consultas_SQL.Security.UserPasswordSQLr   r   r   rD   r   r   r   r   	functoolsr   r   r   r   r   Consultas_SQL.conexionr   email.mime.multipartr   email.mime.textr   secretsr   r"   r   r   r   r   r   r  r   r   r   r   <module>r+     s   
 % T T T 	    R 
  ' '  2 2 F F   1 . $ F F 
 = 
 3
C CJA;H$HVTl@Dqfh$r   