
    ig^                         S SK r S SKrS SKJrJr  S SKJr  S SKJrJrJ	r	J
r
JrJr  S SKJrJrJrJr  S SKr " S S5      rS rg)	    N)datetime	timedelta)	lru_cache)requestrender_templateredirecturl_forjsonifysession)get_ModuleID
get_RoleIDget_permiso.get_CompanyID_DivisionID_DepartamentID_Profilec                   |    \ rS rSrSr/ SQrS rS rS rSS jr	\
" S	S
9S 5       rS rS rS rS rS rSS jrSrg)AccessController   z5Controlador de acceso con logging profesional y cache)CLIEEXTERNOSPROVEEDORESc                     [         R                  " SS5      U l        U R                  5       U l        U R                  S:X  a  SU l        g SU l        g )N	FLASK_ENVdevelopment
productioni,  <   )osgetenvenv_setup_loggerloggercache_duration)selfs    ]C:\Users\victor.barrera\Documents\proyectos\elepV3\Elep\src\App\Security_Module\UserAccess.py__init__AccessController.__init__   s>    99[-8((*%)XX%=c2    c                   ^ SSK nSSKnSSKmSSKnUR                  " S5      nUR
                  (       a  U$ U R                  S:X  a  UR                  OUR                  nUR                  U5        UR                  " S5      n UR                  R                  UR                  R                  [        5      SSS5      nUR                  " USS	9  UR                  R                  US
5      nUR                   " USS9n	U	R#                  U5        UR%                  U	5        UR*                  " UR,                  S9nUR#                  U5         " U4S jSUR.                  5      nUR0                  S:X  a&  U R                  S:X  a  UR3                  U" 5       5        UR%                  U5        U$ ! [&         a  n
[)        SU
 35         Sn
A
NSn
A
ff = f)ui   Configura el sistema de logging según el entorno (UTF-8 seguro y compatible con Windows, VSCode y Flask)r   Nuser_accessr   z:%(asctime)s - ACCESS_CONTROL - %(levelname)s - %(message)sz..logsT)exist_okzaccess_control.logzutf-8)encodingz$No se pudo crear el archivo de log: )streamc                   "   > \ rS rSrU 4S jrSrg)5AccessController._setup_logger.<locals>.NoEmojiFilterC   c                 \   > TR                  SS[        UR                  5      5      Ul        g)Nz[^\x00-\x7F]+ T)substrmsg)r!   recordres     r"   filter<AccessController._setup_logger.<locals>.NoEmojiFilter.filterD   s#    VV$4b#fjj/J
r%    N)__name__
__module____qualname____firstlineno__r6   __static_attributes__)r5   s   r"   NoEmojiFilterr-   C   s     r%   r>   ntr   )r   loggingr5   sys	getLoggerhandlersr   INFODEBUGsetLevel	Formatterpathjoindirname__file__makedirsFileHandlersetFormatter
addHandler	ExceptionprintStreamHandlerstdoutFiltername	addFilter)r!   r   r@   rA   r   level	formatterlog_dirlog_filefile_handlereconsole_handlerr>   r5   s                @r"   r   AccessController._setup_logger   sy   ""=1 ??M !%L 8gmm %%H
	
		>ggll277??8#<dD&QGKK$/ww||G-ABH"..x'JL%%i0l+
 "//szzB$$Y/	GNN 	 77d?txx=8%%mo6/*)  	>8<==	>s   BF* *
G4GGc                     / n/ nU(       d  UR                  S5        OUS   c  UR                  S5        U(       d  UR                  S5        OUS   c  UR                  S5        U(       d  UR                  S5        XE4$ )z5Valida la integridad de los datos de la base de datosu    Datos del módulo no encontradosr   z$ModuloID es NULL en la base de datoszPerfil de usuario no encontradozCompanyID del usuario es NULLzUserID no proporcionado)append)r!   user_idmodule_dataprofile_dataerrorswarningss         r"   _validate_database_integrity-AccessController._validate_database_integrityQ   sy     MM<=1~%DE MM;<A& ?@ MM34r%   Nc                    UUUU[         R                  " 5       R                  5       U R                  S.nU(       a  XWS'   U(       a  [	        U5      US'   US:X  ak  SU SU SU 3nSU SU SU 3n	U R
                  R                  U5        U R                  S	:X  a)  U(       a!  S
U 3n
U R
                  R                  U
5        gggUS:X  aZ  SU SU SU 3nSU SU SU 3n	U R
                  R                  U5        U(       a!  SU 3nU R
                  R                  U5        ggUS:X  aZ  SU SU SU 3nSU SU SU 3n	U R
                  R                  U5        U(       a!  SU 3nU R
                  R                  U5        ggg)u6   Registra intentos de acceso con información detallada)ra   rutastepresult	timestampr   dataerrorSUCCESSu   ✅ ACCESO CONCEDIDO | User: 	 | Ruta: u    | Método: zACCESO CONCEDIDO | User: r   z   Datos utilizados: DENIEDu   🚫 ACCESO DENEGADO | User: z | Paso fallido: zACCESO DENEGADO | User: z   Datos del fallo: ERRORu!   ❌ ERROR EN VALIDACIÓN | User: z	 | Paso:    ERROR EN VALIDACIÓN | User: z
   Error: N)
r   now	isoformatr   r2   r   infodebugwarningrn   )r!   ra   ri   rj   rk   rm   rn   log_datafile_msgconsole_msg	debug_msgwarning_msg	error_msgs                r"   _log_access_attempt$AccessController._log_access_attemptj   s    !11388
 #V #E
HW Y6wiyl[_Z`aH5gYiv\Z^Y_`KKKX&xx=(T3D6:	!!), .2( x6wiyN_`d_efH4WIYtfL]^b]cdKKK) 4TF;##K0  w:7)9TFR[\`[abH9')D6QZ[_Z`aKKKh'(0	!!),  r%   d   )maxsizec                      [        X5      $ ! [         a(  nU R                  R                  SU 35         SnAgSnAff = f)zCache de permisos con TTLz"Error obteniendo permisos cached: N)r   rP   r   rn   )r!   role_id	module_idr\   s       r"   _get_cached_permissions(AccessController._get_cached_permissions   s?    	w22 	KK B1#FG	s   
 
?:?c                    U R                   R                  S5         [        U5      nU R                   R                  SU S35        US:X  a  U R                   R                  S5        SU4$ U R                   R                  S5        SU4$ ! [         a(  nU R                   R	                  S	U 35         S
nAgS
nAff = f)u   Validación 1: Superusuarioz(>>> METODO 1: VALIDACION DE SUPERUSUARIOz    Datos obtenidos: RoleID = ''SUz1    RESULTADO: ACCESO CONCEDIDO - Es SUPERUSUARIOTz1    RESULTADO: No es superusuario, continuando...Fu!       ✗ ERROR obteniendo RoleID: N)FN)r   rv   r   rP   rn   )r!   ra   ri   r   r\   s        r"   _validate_superuser$AccessController._validate_superuser   s    CE	 )GKK>wiqIJ$  #TVW}$  #TV'>! 	KK A!EF	s   AB ,B 
B=B88B=c                     U R                   R                  S5        U R                   R                  S5        US:X  a  U R                   R                  S5        gU R                   R                  SU S35        g)	u+   Validación 2: Acceso especial a index.htmlz,>>> METODO 2: VALIDACION ESPECIAL INDEX.HTMLz'    Verificando si ruta = '/index.html'/index.htmlzC    RESULTADO: ACCESO CONCEDIDO - Ruta es index.html (acceso libre)Tz    RESULTADO: Ruta 'z"' no es index.html, continuando...F)r   rv   )r!   ra   ri   s      r"   _validate_index_access'AccessController._validate_index_access   sf    GIBD= KKbdKK4TF:\]^r%   c           	      	   U R                   R                  S5        US:X  a7  U R                   R                  S5        U R                   R                  S5        gUS   b  US   OSnUS   b  US   OSnUS	   b  US	   OSnUS
   b  US
   OSn	US   b  US   OSn
US   b  US   OSnUS	   b  US	   OSnU R                   R                  S5        U R                   R                  SU SU SU	 S35        U R                   R                  S5        U R                   R                  SU
 SU SU S35        XR                  ;   Gax  U R                   R                  SU S35        U R                   R                  SU R                   35        U R                   R                  S5        Xz:X  a@  X:X  a;  X:X  a6  U(       a/  US:w  a)  U	(       a"  U	S:w  a  U R                   R                  S5        gU R                   R                  S5        U R                   R                  SXz:H   35        U R                   R                  SX:H   35        U R                   R                  SX:H   35        U R                   R                  SU=(       a    US:g   35        U R                   R                  SU	=(       a    U	S:g   35        GOU R                   R                  SU S35        U(       a  US:X  ay  U R                   R                  S5        Xz:X  a  U R                   R                  S5        gU R                   R                  S 5        U R                   R                  SXz:H   35        GOkU	(       a  U	S:X  a  U R                   R                  S!5        Xz:X  a!  X:X  a  U R                   R                  S"5        gU R                   R                  S#5        U R                   R                  SXz:H   35        U R                   R                  SX:H   35        OU R                   R                  S$5        Xz:X  a&  X:X  a!  X:X  a  U R                   R                  S%5        gU R                   R                  S&5        U R                   R                  SXz:H   35        U R                   R                  SX:H   35        U R                   R                  SX:H   35        U R                   R                  S'5        g)(u;   Validación 3: Acceso por departamento/división/compañíaz)>>> METODO 3: VALIDACION POR DEPARTAMENTOTz@    Restricted_Access = True - SALTANDO validacion departamentalzE    RESULTADO: Validacion departamental deshabilitada, continuando...Fr   N         z    DATOS DEL MODULO:z      Company: 'z' | Division: 'z' | Department: 'r   z    DATOS DE TU PERFIL:z%    DIVISION RESTRINGIDA detectada: 'z    Divisiones restringidas: zN    RESULTADO: Solo se permite acceso especifico (Company+Division+Department)r0   zV    RESULTADO: ACCESO CONCEDIDO - Acceso especifico completo para division restringidazY    RESULTADO: ACCESO DENEGADO - Division restringida requiere acceso especifico completoz      Company coincide: z      Division coincide: z      Department coincide: z(      Modulo tiene Division especifica: z*      Modulo tiene Department especifico: z    Division normal: 'z&' - Aplicando logica jerarquica normalzH    Modulo sin division especifica (vacio/None) - Validando solo Companyz2    RESULTADO: ACCESO CONCEDIDO - Company coincidez"    RESULTADO: Company no coincidezR    Modulo sin departamento especifico (vacio/None) - Validando Company + Divisionz>    RESULTADO: ACCESO CONCEDIDO - Company y Division coincidenz.    RESULTADO: Company o Division no coincidenzR    Modulo con departamento especifico - Validando Company + Division + DepartmentzJ    RESULTADO: ACCESO CONCEDIDO - Company, Division y Department coincidenz-    RESULTADO: No todos los valores coincidenz&    Continuando al siguiente metodo...)r   rv   RESTRICTED_DIVISIONS)r!   ra   ri   rb   rc   Restricted_AccessModuloIDM_CompanyIDM_DivisionIDM_DepartamentIDP_CompanyIDP_DivisionIDP_DepartamentIDs                r"   _validate_department_access,AccessController._validate_department_access   s    	DF$KK_aKKdf &1^%?;q>T(3A(Bk!n)4Q)C{1~,7N,F+a.D *6a)Dl1o$*6q/*E|A4-9!_-H,q/d02+K=~Ufgvfwwxyz24+K=~Ufgvfwwxyz 444KKD\NRSTUKK<T=V=V<WXYKKmo *,2!3Or$9  #y{  #|~  #;K<V;W!XY  #<\=Y<Z![\  #>?a>b!cd  #KLLo]imo]oKp!qr  #MoNwbquwbwMx!yz KK5l^Cijk  <2#5  #km-KK$$'Y[KK$$'IKKK$$'?@Z?[%\]$2(=  #uw-,2NKK$$'egKK$$'UWKK$$'?@Z?[%\]KK$$'@A]@^%_`   #uw. 0#6KK$$'qsKK$$'TVKK$$'?@Z?[%\]KK$$'@A]@^%_`KK$$'B?CeBf%ghACr%   c                    U R                   R                  S5        U(       d   U R                   R                  SU S35        g U R                  X45      nU R                   R                  S5        U R                   R                  SU SU S35        U R                   R                  S	U S35        Ubh  [	        U5      nU R                   R                  SU 35        US:  a  U R                   R                  S5        gU R                   R                  S5         gU R                   R                  S5        g! [
         a(  nU R                   R                  SU 35         S
nAgS
nAff = f)u$   Validación 4: Permisos específicosz1>>> METODO 4: VALIDACION POR PERMISOS ESPECIFICOSzRoleID no definido para UserID=u-   , no se pueden validar permisos específicos.Fz    DATOS DE PERMISOS:z      Tu RoleID: 'z' | ModuloID: 'r   z"      Valor de permiso obtenido: 'Nz#      Permiso convertido a entero: r   z-    RESULTADO: ACCESO CONCEDIDO - Permiso > 0Tz9    RESULTADO: ACCESO DENEGADO - Permiso = 0 (sin acceso)z>    RESULTADO: ACCESO DENEGADO - No se encontro permiso (NULL)u#       ✗ ERROR obteniendo permisos: )r   rv   rx   r   intrP   rn   )r!   ra   ri   r   r   
permissionpermission_levelr\   s           r"   _validate_permission_access,AccessController._validate_permission_access  sF   LNKK"A'Jw xy	55gIJKK57KK1'/)TUVWKKA*QOP%#&z?   #FGWFX!YZ#a'KK$$'TVKK$$'`b    #ac 	KK CA3GH	s%   B:D8 ?D8 D8 8
E*E%%E*c                     U R                  X5      u  pxU(       a  SSU4$ U R                  X5      (       a  SSU4$ U R                  XX4U5      (       a  SSU4$ U(       a  U R                  XX5      (       a  SSU4$ SSU4$ )ut   
Ejecuta los 4 métodos de validación en cascada.
Retorna:
    (resultado: bool, metodo: str, role_id: str | None)
TzMETODO 1 - SUPERUSUARIOzMETODO 2 - INDEX.HTMLzMETODO 3 - DEPARTAMENTOzMETODO 4 - PERMISOS ESPECIFICOSFNINGUNO)r   r   r   r   )	r!   UserIDri   rb   rc   r   r   is_superuserr   s	            r"   _validate_access_cascade)AccessController._validate_access_cascade>  s     !% 8 8 F2G;; &&v440'99 ++F+Ufgg2G;; t77gXX:GCC i((r%   c           	         U(       a&  [         R                  " 5       U-
  R                  5       OSnU R                  R	                  SU SU SUS S35        US:X  a   [
        R                  " SS	5      n[        XS
9$ [        U5      $ )zFRenderiza el template exitosamente con manejo especial para index.htmlr   zRENDERIZANDO TEMPLATE | User: rp   z | Tiempo ejecucion: .3fsr   emailUsuario)
user_email)r   rt   total_secondsr   rv   r   getr   )r!   ri   ra   
start_timeexecution_timer   s         r"   _render_success_template)AccessController._render_success_templateY  s    JT(,,.:5DDFZ[,WIYtf E!!/ 4A7	

 =  Wi8J"4??t$$r%   )r    r   r   )NN)N)r9   r:   r;   r<   __doc__r   r#   r   rf   r   r   r   r   r   r   r   r   r   r=   r8   r%   r"   r   r      s^    ? ?F
3j 2+-Z s *
ZxB)6%r%   r   c                    SSK JnJn  SSKJnJnJnJn  SSKJn	  SSK	n
U	R                  " 5       n[        5       n U (       d:  UR                  R                  S5        UR                  " 5         U" U" S5      5      $ U(       d  SnUR                  XS	S
US9  U" SUS9$ UR                  R!                  S5        UR                  R!                  SU  SU SU 35        UR                  R!                  S5         U" U5      nU" U 5      nUR)                  XU5      u  nnU H!  nUR                  R                  SU 35        M#     U(       aw  U	R                  " 5       U-
  R%                  5       nSSR+                  U5       3nUR                  XSS
US9  UR                  R'                  SU  SU SUS SU 35        U" SSS9$ U(       a  US   b  US   OSnUR-                  XUUUU5      u  nnnU	R                  " 5       U-
  R%                  5       nU(       aS  UR                  R!                  SU SU  S U=(       d    S! S"U=(       d    S! SU S#US S$35        UR/                  XU5      $ U(       a!  S%US    S&US'    S(US)    S U=(       d    S! 3nOS*nU(       a  S+US    S,US'    S&US)    S(US-    3nOS.nUR                  R                  S/U  S U=(       d    S! SU S#US S$3	5        UR                  R                  S0U S1U 35        UR                  XS2S
S3U S4U S53S9  U" SS6S9$ ! ["         ak    U	R                  " 5       U-
  R%                  5       nSU 3nUR                  XSS
US9  UR                  R'                  SU  SU SUS SU 35        U" SSS9s $ f = f! [0         a  nU	R                  " 5       U-
  R%                  5       nUR                  R'                  S7U  SU SUS S8[3        U5       35        UR4                  S9:X  a-  UR                  R'                  S:U
R6                  " 5        35        UR                  XS;S
[3        U5      S9  U" SS<[3        U5       3S9s SnA$ SnAff = f)=zs
Valida el acceso del usuario a la ruta solicitada.
Aplica validaciones en cascada y maneja errores de integridad.
r   )r   r   )r   r   r   r	   )r   Nu?   Intento de acceso sin UserID en sesión - Redirigiendo al loginloginzRuta no proporcionadaINPUT_VALIDATIONrr   )rn   zSecurity/AccessDened.html)messagez&=== INICIANDO VALIDACION DE ACCESO ===zUser: rp   z | Restricted: z&=== VALIDANDO 4 METODOS EN CASCADA ===u%   No se encontró el módulo en la BD: DB_INTEGRITYrs   u    | Tiempo ejecución: r   zs | u3   El módulo no está registrado en la base de datos.z	WARNING: zErrores de integridad en BD: z; z"Error al validar datos de usuario.zACCESO FINAL CONCEDIDO POR: z	 | User: z
 | RoleID=zN/Az | ModuloID=z | Tiempo: r   z
CompanyID=z | DivisionID=r   z | DepartamentID=r   zPerfil de usuario no disponiblez	ModuloID=z | CompanyID=r   u    Datos del módulo no disponiblesu>   ACCESO FINAL DENEGADO - TODOS LOS 4 MÉTODOS FALLARON | User: u      Comparación → Usuario: u    | Módulo: ACCESS_DENIEDu8   Diferencias detectadas entre perfil y módulo (Usuario: u    vs Módulo: )u/   No tienes permisos para acceder a este módulo.u   ERROR CRÍTICO | User: zs | Error: r   zTraceback completo:
GENERALzError al verificar acceso: )&Consultas_SQL.Security.UserPasswordSQLr   r   flaskr   r   r   r	   r   	tracebackrt   r   r   rx   clearr   rv   LookupErrorr   rn   rf   rI   r   r   rP   r2   r   
format_exc)r   ri   r   r   r   r   r   r   r	   r   r   r   access_controllerr~   rb   r   rc   rd   re   rx   r   	resultadometodor   user_cmp
module_cmpr\   s                              r"   check_user_accessr   h  sx   
 BA!J(*FO $$,,-noMMOGG,--/I11&@RT[cl1m"#>	RR  %%&NO  %%vhiv_UfTg&hi  %%&NO	b&t,K FfM -II&_kl  G$$,,y	-BC   &llnz9HHJN7		&8I7JKI11&PW_h1i$$**/xy G&&4S%9i[J ##>+OQ Q &1[^5O;q>UY
 &7%O%O+|5F&
"	67 #,,.:5DDF$$))*6( 3HJw'7%&8XEVQVDW XF+nS%9<

 %==dJWW  a 1Q?P Q%%1!_$5Z@P5?QS 
 =A/}[^<L M""-a.!11B;q>BRT 
 @
$$,,
7+;e*<IdV;WefiVjjkm $$,,/LXJVbcmbn-op11ow!!)
-
|1F 2  #+I q  		b&llnz9HHJN?vFI11&PW_h1i$$**/xy G&&4S%9i[J ##>+`b b		bz  O #,,.:5DDF  &&%fXYtf =""0!5[QJ	

   M1$$**-B9CWCWCYBZ+[\--fIwVYZ[V\-]:)DSVH'MO 	OOs`   A N% <!N% AN% 9L- CN% B(N% ,C N% -A2N"N% !N""N% %
Q7/B=Q2,Q72Q7)r@   r   r   r   	functoolsr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r8   r%   r"   <module>r      s<      (  O O  
U% U%n
VOr%   