§
    ÖÁj   ã                  óø   — d dl mZ 	 d dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dl
mZmZ  ej        d¦  «        Zg d¢Z G d	„ d
e¦  «        Zd dlmZmZ d dlZ G d„ de¦  «        Zd dl
mZ  G d„ de¦  «        ZdS )é    )ÚannotationsN)Úunquote)ÚBaseHTTPMiddleware)ÚRequest)ÚJSONResponseÚResponsezdscons.security.waf))zk(?i)(union\s+select|select\s+.*\s+from\s+pg_|insert\s+into\s+.*values|drop\s+table|delete\s+from\s+.*where)ÚSQL_INJECTION)z.(?i)('\s*or\s*'1'\s*=\s*'1|--\s*$|;\s*drop\s+)ÚSQL_BYPASS_INJECTION)zF(?i)(<script[^>]*>|javascript:|onerror\s*=|onload\s*=|alert\(|<iframe)ÚCROSS_SITE_SCRIPTING)z6(\.\./\.\./|\.\.\\\.\.\\|/etc/passwd|windows/system32)ÚPATH_TRAVERSAL)z:(?i)(\|\|\s*bash|;\s*rm\s+-rf|;\s*powershell|\$\(whoami\))ÚCOMMAND_INJECTIONc                  ó   — e Zd ZdZdd„ZdS )	ÚEnterpriseSecurityMiddlewarezRAdds enterprise-grade HTTP security headers and performs basic request inspection.Úrequestr   Úreturnr   c           	   ƒ  ó¤  K  — t          |j        ¦  «        }t          |¦  «        }t          D ]o\  }}t	          j        ||¦  «        rUt                               d||j        r|j        j	        nd|j        j
        ¦  «         t          dddd|› d�dœ¬	¦  «        c S Œp ||¦  «        ƒ d {V —†}d
|j        d<   d|j        d<   d|j        d<   d|j        d<   d|j        d<   d|j        d<   d|j        d<   d|j        d<   |j        j
                             d¦  «        s|j        j
                             d¦  «        rd|j        d<   d|j        d<   |S ) Nz9[SECURITY WAF BLOCK] Threat: %s | Client IP: %s | URL: %sÚunknowni�  ÚerrorÚSECURITY_THREAT_BLOCKEDuO   YÃªu cáº§u chá»©a máº«u Ä‘á»™c háº¡i bá»‹ cháº·n bá»Ÿi DSCons Security Shield (z).©ÚstatusÚ
error_codeÚmessage©Ústatus_codeÚcontentÚ
SAMEORIGINzX-Frame-OptionsÚnosniffzX-Content-Type-Optionsz1; mode=blockzX-XSS-Protectionzstrict-origin-when-cross-originzReferrer-Policyz,geolocation=(self), microphone=(), camera=()zPermissions-PolicyÚnonez!X-Permitted-Cross-Domain-Policiesz,max-age=31536000; includeSubDomains; preloadzStrict-Transport-Securityaü  default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.tailwindcss.com https://cdn.jsdelivr.net blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.tailwindcss.com https://cdn.jsdelivr.net; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data: https: blob: https://fastapi.tiangolo.com https://cdn.jsdelivr.net; media-src 'self' blob: data:; connect-src 'self' https: ws: wss:; frame-ancestors 'self'; base-uri 'self'; form-action 'self';zContent-Security-Policyz/v1/z/dashboard/z.no-store, no-cache, must-revalidate, max-age=0zCache-Controlzno-cacheÚPragma)ÚstrÚurlr   ÚMALICIOUS_PATTERNSÚreÚsearchÚloggerÚwarningÚclientÚhostÚpathr   ÚheadersÚ
startswith)Úselfr   Ú	call_nextÚraw_urlÚdecoded_urlÚpatternÚthreat_typeÚresponses           ú<C:\Projects\DSCons\app\api\middleware\security_middleware.pyÚdispatchz%EnterpriseSecurityMiddleware.dispatch%   sã  è è € å�g”kÑ"Ô"ˆÝ˜gÑ&Ô&ˆå$6ð 	ð 	Ñ ˆG�[ÝŒy˜ +Ñ.Ô.ð Ý—’ØOØØ+2¬>ÐH�G”NÔ'Ð'¸yØ”KÔ$ñ	ô ð õ $Ø #à")Ø&?ð $Eð  vAð  $Eð  $Eð  $Eðð ðñ ô ð ð ð ðð" $- 9¨WÑ#5Ô#5Ð5Ð5Ð5Ð5Ð5Ð5ˆð /;ˆÔÐ*Ñ+Ø5>ˆÔÐ1Ñ2Ø/>ˆÔÐ+Ñ,Ø.OˆÔÐ*Ñ+à:ð 	ÔÐ-Ñ.ð AGˆÔÐ<Ñ=à:ð 	ÔÐ4Ñ5ð	"ð 	ÔÐ2Ñ3ð Œ;Ô×&Ò& vÑ.Ô.ð 	4°'´+Ô2B×2MÒ2MØñ3
ô 3
ð 	4ð Að Ô˜_Ñ-ð *4ˆHÔ˜XÑ&àˆó    N)r   r   r   r   ©Ú__name__Ú
__module__Ú__qualname__Ú__doc__r5   © r6   r4   r   r   "   s.   € € € € € Ø\Ð\ð;ð ;ð ;ð ;ð ;ð ;r6   r   )ÚdefaultdictÚdequec                  ó.   ‡ — e Zd ZdZd
dˆ fd„Zdd	„Zˆ xZS )ÚSimpleGlobalRateLimitMiddlewarezGGlobal Rate Limiter (Sliding Window Memory) to prevent DDoS/Bruteforce.é<   Úmax_requestsÚintÚwindow_secondsc                ó˜   •— t          ¦   «                              |¦  «         || _        || _        t	          t
          ¦  «        | _        d S )N)ÚsuperÚ__init__rB   rD   r=   r>   Ú
ip_records)r-   ÚapprB   rD   Ú	__class__s       €r4   rG   z(SimpleGlobalRateLimitMiddleware.__init__g   s>   ø€ Ý‰Œ×Ò˜ÑÔÐØ(ˆÔØ,ˆÔÝ%¥eÑ,Ô,ˆŒˆˆr6   r   r   c           	   ƒ  ó¢  K  — |j         j                             d¦  «        s|j         j                             d¦  «        r ||¦  «        ƒ d {V —†S |j        r|j        j        nd}t          j        ¦   «         }| j        |         }|r>|d         || j        z
  k     r*|                     ¦   «          |r|d         || j        z
  k     °*t          |¦  «        | j
        k    rLt                               d|› d| j
        › d| j        › d�¦  «         t          d	d
dd| j        › d�dœ¬¦  «        S |                     |¦  «          ||¦  «        ƒ d {V —†S )Nz/staticz/storager   r   z[RATE LIMIT] Blocked IP z - Exceeded z req / Úsi­  r   ÚTOO_MANY_REQUESTSu?   Há»‡ thá»‘ng Ä‘ang chá»‹u táº£i cao. Vui lÃ²ng thá»­ láº¡i sau u    giÃ¢y.r   r   )r"   r*   r,   r(   r)   ÚtimerH   rD   ÚpopleftÚlenrB   r&   r'   r   Úappend)r-   r   r.   ÚipÚnowÚhistorys         r4   r5   z(SimpleGlobalRateLimitMiddleware.dispatchm   s–  è è € àŒ;Ô×&Ò& yÑ1Ô1ð 	,°W´[Ô5E×5PÒ5PÐQ[Ñ5\Ô5\ð 	,Ø"˜ 7Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+Ð+à$+¤NÐAˆWŒ^Ô Ð ¸	ˆÝŒi‰kŒkˆà”/ "Ô%ˆØð 	˜' !œ* s¨TÔ-@Ñ'@Ò@Ð@Ø�OŠOÑÔÐð ð 	˜' !œ* s¨TÔ-@Ñ'@Ò@Ð@õ ˆw‰<Œ<˜4Ô,Ò,Ð,Ý�NŠNÐv°bÐvÐvÀdÔFWÐvÐvÐ`dÔ`sÐvÐvÐvÑwÔwÐwÝØà%Ø"5Ø}ÐaeÔatÐ}Ð}Ð}ðð ðñ ô ð ð 	�Š�sÑÔÐØ�Y˜wÑ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'Ð'r6   )rA   rA   )rB   rC   rD   rC   ©r   r   )r8   r9   r:   r;   rG   r5   Ú__classcell__)rJ   s   @r4   r@   r@   e   s\   ø€ € € € € ØQÐQð-ð -ð -ð -ð -ð -ð -ð(ð (ð (ð (ð (ð (ð (ð (r6   r@   )ÚRedirectResponsec                  ó   — e Zd ZdZdd„ZdS )ÚLegacyRedirectMiddlewarezLRedirects old URLs to the new /v1/erp/... standard and routes erp subdomain.r   r   c              ƒ  ó‚  K  — |j         j        }|j                             dd¦  «                             ¦   «         }|                     d¦  «        r|dv rt          dd¬¦  «        S d}|                     |¦  «        r3|j         j        rd	|j         j        › �nd}t          d
|› |› �d¬¦  «        S  ||¦  «        ƒ d {V —†S )Nr)   Ú zerp.)ú/z/landingz/landing.htmlz/v1/erp/dashboardi.  )r"   r   )z
/dashboardz/loginz/takeoffz/drawing-takeoffz/material-pricesz/material-price-comparisonz/state-pricesz	/zalo-crmz/documents-dashboardz
/documentsz	/projectsz/wbsz/financez	/war-roomz
/employeesz/usersz
/equipmentz	/invoicesz/bankingz	/partnersz/vendorsz
/customersz/dhsz/agent-modelsz/site-diaryz	/site-pwaz	/settingsÚ?z/v1/erpi-  )r"   r*   r+   ÚgetÚlowerr,   rW   Úquery)r-   r   r.   r*   r)   Úlegacy_prefixesr`   s          r4   r5   z!LegacyRedirectMiddleware.dispatch‹   sì   è è € ØŒ{ÔˆØŒ×"Ò" 6¨2Ñ.Ô.×4Ò4Ñ6Ô6ˆð �?Š?˜6Ñ"Ô"ð 	N tÐ/QÐ'QÐ'QÝ#Ð(;ÈÐMÑMÔMÐMð
ˆð �?Š?˜?Ñ+Ô+ð 	RØ/6¬{Ô/@ÐHÐ+˜œÔ)Ð+Ð+Ð+ÀbˆEÝ#Ð(?°$Ð(?¸Ð(?Ð(?ÈSÐQÑQÔQÐQà�Y˜wÑ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'Ð'r6   NrU   r7   r<   r6   r4   rY   rY   ‰   s.   € € € € € ØVÐVð(ð (ð (ð (ð (ð (r6   rY   )Ú
__future__r   Úloggingr$   Úurllib.parser   Ústarlette.middleware.baser   Ústarlette.requestsr   Ústarlette.responsesr   r   Ú	getLoggerr&   r#   r   Úcollectionsr=   r>   rN   r@   rW   rY   r<   r6   r4   ú<module>rj      sc  ðØ "Ð "Ð "Ð "Ð "Ð "à aà €€€Ø 	€	€	€	Ø  Ð  Ð  Ð  Ð  Ð  à 8Ð 8Ð 8Ð 8Ð 8Ð 8Ø &Ð &Ð &Ð &Ð &Ð &Ø 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6à	ˆÔ	Ð0Ñ	1Ô	1€ðð ð Ð ð$>ð >ð >ð >ð >Ð#5ñ >ô >ð >ð@ +Ð *Ð *Ð *Ð *Ð *Ð *Ð *Ø €€€ð (ð  (ð  (ð  (ð  (Ð&8ñ  (ô  (ð  (ðD 1Ð 0Ð 0Ð 0Ð 0Ð 0ð(ð (ð (ð (ð (Ð1ñ (ô (ð (ð (ð (r6   