Ë
    yÌj6  ã                   ó²  — d Z ddlZddlZddlmZ ddlmZmZ ddlm	Z	  ej                  d«      Zdd„Zdddddd	dd
œdedee   dee   dee   dee   dee   dedee   ddfd„Zdefd„Zdeeef   fd„Zdddddddddœdee   dee   dee   dee   dee   dee   dededee   fd„Zdddddddœdee   dee   dee   dee   dee   dee   defd„Zy) uÏ  
audit_service.py â€” Registro de auditorÃ­a de seguridad (MySQL, best-effort).

Fire-and-forget: nunca bloquea ni propaga excepciones â€” un fallo de auditorÃ­a
no debe romper la operaciÃ³n auditada.

ConvenciÃ³n de `action` : "<categorÃ­a>.<evento>", ej. "auth.login",
"photo.rgpd_delete", "consent.given", "family.import", "sale.create".

Niveles de `severity`:
  info     â€” operaciones normales (login correcto, venta, importaciÃ³n)
  warning  â€” intentos fallidos, ediciones, bloqueos temporales
  critical â€” borrado permanente de fotos, fuerza bruta bloqueada

Multi-colegio: cada evento puede llevar `school_id`; el director solo ve los
de su colegio, el operador ve los del colegio seleccionado (o todos).
é    N)ÚOptional)Úget_dbÚTABLE_OPTIONS)Ú
utcnow_isozmeeconic.auditÚreturnc                  ó¾   — t        «       5 } | j                  dt        › d�«       | j                  «        d d d «       t        j                  d«       y # 1 sw Y   ŒxY w)Na  
            CREATE TABLE IF NOT EXISTS audit_logs (
                id            BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
                created_at    VARCHAR(40)  NOT NULL,
                user_id       VARCHAR(100),
                ip_address    VARCHAR(64),
                action        VARCHAR(80)  NOT NULL,
                resource_type VARCHAR(40),
                resource_id   VARCHAR(100),
                details_json  MEDIUMTEXT,
                severity      VARCHAR(20)  NOT NULL DEFAULT 'info',
                school_id     VARCHAR(64),
                KEY idx_audit_created (created_at),
                KEY idx_audit_action (action),
                KEY idx_audit_severity (severity),
                KEY idx_audit_school (school_id)
            ) z	
        zaudit_logs table ready)r   Úexecuter   ÚcommitÚlogÚinfo)Úconns    ú1/var/www/photos/backend/services/audit_service.pyÚinit_audit_dbr      sZ   € Ü	‹ð �TØ�‰ð ô  ˆoð 	ð!ô 	ð$ 	�‰Œ÷'ô( ‡H�HÐ%Õ&÷)ð ús   ‹*AÁAr   )Úuser_idÚ
ip_addressÚresource_typeÚresource_idÚdetailsÚseverityÚ	school_idÚactionr   r   r   r   r   r   r   c                ó6  — 	 t        «       5 }|j                  dt        «       ||| |||rt        j                  |d¬«      nd||f	«       |j                  «        ddd«       y# 1 sw Y   yxY w# t        $ r!}	t        j                  d| |	«       Y d}	~	yd}	~	ww xY w)u=   Persiste un Ã©vÃ©nement d'audit. Ne lÃ¨ve jamais d'exception.zÀINSERT INTO audit_logs
                   (created_at, user_id, ip_address, action, resource_type, resource_id, details_json, severity, school_id)
                   VALUES (?,?,?,?,?,?,?,?,?)F)Úensure_asciiNzAudit logging failed [%s]: %s)	r   r	   r   ÚjsonÚdumpsr
   Ú	Exceptionr   Úwarning)
r   r   r   r   r   r   r   r   r   Úes
             r   Ú	log_eventr   4   s”   € ð@Ü‹Xð 	˜Ø�L‰Lð1ô “L '¨:°v¸}ÈkÙ?F”D—J‘J˜w°UÕ;ÈDØ˜iðô		ð �K‰KŒM÷	÷ 	ñ 	ûô ò @Ü�‰Ð3°V¸Q×?Ñ?ûð@ús5   ‚
A. ŒAA"ÁA. Á"A+Á'A. Á+A. Á.	BÁ7BÂBc                 óx   — t        | «      }|j                  dd «      }|rt        j                  |«      nd |d<   |S )NÚdetails_jsonr   )ÚdictÚpopr   Úloads)ÚrÚdr!   s      r   Ú_row_to_dictr'   Q   s6   € ÜˆQ‹€AØ—5‘5˜¨Ó.€LÙ/;”4—:‘:˜lÔ+À€A€i�LØ€Hó    c                 ó>  — d}g }| r|dz  }|j                  | › d�«       |r|dz  }|j                  |«       |r|dz  }|j                  |«       |r|dz  }|j                  |«       |r|dz  }|j                  |dz   «       |r|d	z  }|j                  |«       ||fS )
Nz
 WHERE 1=1z AND action LIKE ?ú%z AND severity = ?z AND user_id = ?z AND created_at >= ?z AND created_at <= ?z	T23:59:59z AND school_id = ?)Úappend)r   r   r   Ú	date_fromÚdate_tor   ÚqÚparamss           r   Ú_wherer0   X   s·   € Ø€AØ€FÙØ	Ð!Ñ!ˆ 6§=¡=°F°8¸1°Ô#>ÙØ	Ð Ñ ˆ &§-¡-°Ô"9ÙØ	ÐÑˆ §¡¨wÔ!7ÙØ	Ð#Ñ#ˆ V§]¡]°9Ô%=ÙØ	Ð#Ñ#ˆ V§]¡]°7¸[Ñ3HÔ%IÙØ	Ð!Ñ!ˆ 6§=¡=°Ô#;Øˆfˆ9Ðr(   éÈ   )r   r   r   r,   r-   r   ÚlimitÚoffsetr,   r-   r2   r3   c                 óü   — t        | |||||«      \  }}	d|z   dz   }
t        «       5 }|j                  |
|	||gz   «      j                  «       }d d d «       D �cg c]  }t	        |«      ‘Œ c}S # 1 sw Y   Œ"xY wc c}w )NzSELECT * FROM audit_logsz3 ORDER BY created_at DESC, id DESC LIMIT ? OFFSET ?)r0   r   r	   Úfetchallr'   )r   r   r   r,   r-   r   r2   r3   Úwherer/   r.   r   Úrowsr%   s                 r   Úlist_eventsr8   j   s…   € ô ˜6 8¨W°iÀÈ)ÓT�M€Eˆ6Ø" UÑ*Ð-bÑb€AÜ	‹ð D�TØ�|‰|˜A˜v¨°¨Ñ7Ó8×AÑAÓCˆ÷Dà%)Ö* ŒL˜�OÒ*Ð*÷Dð Düâ*s   ¦&A-ÁA9Á-A6)r   r   r   r,   r-   r   c                 ó´   — t        | |||||«      \  }}t        «       5 }|j                  d|z   |«      j                  «       d   cd d d «       S # 1 sw Y   y xY w)Nz$SELECT COUNT(*) AS n FROM audit_logsÚn)r0   r   r	   Úfetchone)	r   r   r   r,   r-   r   r6   r/   r   s	            r   Úcount_eventsr<   |   s_   € ô ˜6 8¨W°iÀÈ)ÓT�M€Eˆ6Ü	‹ð d�TØ�|‰|ÐBÀUÑJÈFÓS×\Ñ\Ó^Ð_bÑc÷d÷ dò dús   ž&AÁA)r   N)Ú__doc__r   ÚloggingÚtypingr   Úcore.dbr   r   Úcore.timeutilr   Ú	getLoggerr   r   Ústrr"   r   r'   ÚtupleÚlistr0   Úintr8   r<   © r(   r   ú<module>rH      sû  ðñó" Û Ý ç )Ý $à€g×ÑÐ(Ó)€ó'ð6 "Ø $Ø#'Ø!%Ø"ØØ#ò@Øð@ð �c‰]ð@ð ˜‘ð	@ð
 ˜C‘=ð@ð ˜#‘ð@ð �d‰^ð@ð ð@ð ˜‰}ð@ð 
ó@ð:�tó ðÈÈcÐSWÈiÑHXó ð( !Ø"Ø!Ø#Ø!Ø#ØØò+à�S‰Mð+ð �s‰mð+ð �c‰]ð	+ð
 ˜‰}ð+ð �c‰]ð+ð ˜‰}ð+ð ð+ð ð+ð 
ˆ$�Zó+ð( !Ø"Ø!Ø#Ø!Ø#òdà�S‰Mðdð �s‰mðdð �c‰]ð	dð
 ˜‰}ðdð �c‰]ðdð ˜‰}ðdð 	ôdr(   