
    Xj                        U d dl Z d dlmZmZ d dlmZ d dlZd dlmZmZ d dl	m
Z
 d dlmZ d dlmZ  ee          Zerd dlmZ  e
d	gd
          Zdaej        dz  ed<   dej        fdZdededefdZdedefdZd8dededz  defdZdededz  fdZeZdefdZ dede!eef         fdZ"dede#ddfdZ$dedefdZ%defdZ&defdZ'defd Z(defd!Z)defd"Z*defd#Z+defd$Z,defd%Z-defd&Z.defd'Z/d(e#dz  defd)Z0	 d8d*e#d+e#dz  defd,Z1d8d-edz  defd.Z2d/ Z3d8d9d2Z4de5fd3Z6d4e5defd5Z7d6edefd7Z8dS ):    N)datetime	timedelta)TYPE_CHECKING)JWTErrorjwt)CryptContext)settings)
get_logger)Userbcryptauto)schemes
deprecated_redis_clientreturnc                      t           nt          j        r!t          j        t          j        d          a nAt          j        t          j        t          j        t          j        t          j	        d          a t           S )NT)decode_responses)hostportdbpasswordr   )
r   r	   	REDIS_URLredisfrom_urlRedis
REDIS_HOST
REDIS_PORTREDIS_DBREDIS_PASSWORD     9/lsinfo/ai/hellotax_ai/base_platform/app/core/security.pyget_redis_clientr#      sf     		!N8+=PTUUUMM!K(($!0!%  M r!   plain_passwordhashed_passwordc                    t          | t                    r2|                     d          d d                             dd          } t                              | |          }|st                              d           |S )Nzutf-8H   ignore)errorszPassword verification failed)
isinstancestrencodedecodepwd_contextverifyloggerwarning)r$   r%   results      r"   verify_passwordr3   %   sz    .#&& ^'..w77<CCGT\C]]@@F 75666Mr!   r   c                 n    t                               |           }t                              d           |S )NzPassword hashed successfully)r.   hashr0   info)r   hasheds     r"   get_password_hashr8   .   s-    h''F
KK.///Mr!   dataexpires_deltac                 @   |                                  }|rt          j                    |z   }n.t          j                    t          t          j                  z   }|                    d|i           t          j        |t          j	        t          j
                  }|S )N)minutesexp)	algorithm)copyr   utcnowr   r	   ACCESS_TOKEN_EXPIRE_MINUTESupdater   r,   
SECRET_KEY	ALGORITHM)r9   r:   	to_encodeexpireencoded_jwts        r"   create_access_tokenrH   4   s    		I ]""]2""Yx7[%\%\%\\eV_%%%*Y(;xGYZZZKr!   tokenc                     	 t          j        | t          j        t          j        g          }|S # t
          $ r(}t                              d|            Y d }~d S d }~ww xY w)N)
algorithmszToken decode failed: )r   r-   r	   rC   rD   r   r0   r1   )rI   payloades      r"   decode_access_tokenrN   ?   sr    *UH$7XEWDXYYY   2q22333ttttts   -0 
A"AA"c                  *    t          j        d          S )N    )secretstoken_urlsafer    r!   r"   generate_verification_tokenrS   K   s     $$$r!   c                    t          |           dk     rdS t          d | D                       sdS t          d | D                       sdS t          d | D                       sdS d	t          fd
| D                       sdS dS )N   )Fu   密码至少需要8个字符c              3   >   K   | ]}|                                 V  d S N)isupper.0cs     r"   	<genexpr>z-validate_password_strength.<locals>.<genexpr>R   *      --qqyy{{------r!   )Fu   密码必须包含大写字母c              3   >   K   | ]}|                                 V  d S rW   )islowerrY   s     r"   r\   z-validate_password_strength.<locals>.<genexpr>T   r]   r!   )Fu   密码必须包含小写字母c              3   >   K   | ]}|                                 V  d S rW   )isdigitrY   s     r"   r\   z-validate_password_strength.<locals>.<genexpr>V   r]   r!   )Fu   密码必须包含数字z!@#$%^&*()_+-=[]{}|;:,.<>?c              3       K   | ]}|v V  	d S rW   r    )rZ   r[   special_charss     r"   r\   z-validate_password_strength.<locals>.<genexpr>Y   s(      44aqM!444444r!   )Fu   密码必须包含特殊字符)T )lenany)r   rc   s    @r"   validate_password_strengthrg   O   s    
8}}q66--H----- 988--H----- 988--H----- 3220M4444844444 988:r!   exp_timestampc                     t                      }|t          t          j                                                              z
  }|dk    r|                    d|  |d           d S d S )Nr   revoked_token:1)r#   intr   r@   	timestampsetex)rI   rh   clientttls       r"   revoke_tokenrq   ^   sh    F
#ho//99;;<<
<C
Qww-e--sC88888 wr!   c                     	 t                      }|                    d|            dk    S # t          $ r(}t                              d|            Y d }~dS d }~ww xY w)Nrj   r   z.Redis unavailable for token revocation check: T)r#   exists	Exceptionr0   error)rI   ro   rM   s      r"   is_token_revokedrv   e   sy    !##}}5e5566::   IaIIJJJttttts   ), 
AAAc                     t          | d          r2| j        r+| j        D ]#}|j        s|j        j        s|j        j        c S $| j        r| j        ndS )N
user_rolescustomer_user)hasattrrx   
is_deletedrolecode)userurs     r"   get_primary_roler   n   sh    t\"" $t $/ 	$ 	$B= $"'*< $w|###	64996r!   c                 (    t          |           dk    S )Nplatform_adminr   r~   s    r"   is_platform_adminr   v       D!!%555r!   c                 (    t          |           dk    S )Nplatform_userr   r   s    r"   is_platform_userr   z       D!!_44r!   c                 (    t          |           dk    S )Ncustomer_adminr   r   s    r"   is_customer_adminr   ~   r   r!   c                 (    t          |           dk    S )Nry   r   r   s    r"   is_customer_userr      r   r!   c                 $    t          |           dv S N)r   r   r   r   s    r"   has_platform_accessr          D!!%HHHr!   c                 $    t          |           dv S N)r   r   r   r   s    r"   has_admin_accessr          D!!%IIIr!   c                 $    t          |           dv S r   r   r   s    r"   can_manage_usersr      r   r!   c                 $    t          |           dv S r   r   r   s    r"   can_delete_resourcer      r   r!   c                 $    t          |           dv S r   r   r   s    r"   can_view_all_resourcesr      r   r!   target_tenant_idc                 L    t          |           rdS | j        dS | j        |k    S NTF)r   	tenant_id)r~   r   s     r"   can_access_companyr      s2    4   t~u>---r!   resource_owner_idresource_tenant_idc                 z    t          |           rdS || j        k    rdS t          |           r|r| j        |k    S dS r   )r   idr   r   )r~   r   r   s      r"   can_manage_resourcer      sV      tDG##t 4#5 4~!3335r!   company_namec                 x    ddddd}|                     | j        | j                  }|r| j        dv r| d| S |S )Nu   平台管理员u   平台用户u   企业管理员u   企业用户)r   r   r   ry   )r   ry   /)getr|   )r~   r   
role_namesrole_displays       r"   get_role_displayr      sb    +'+'	 J >>$)TY77L 0	%HHH/////r!   c                 X    ddl m}m} t          |           s ||j        d          d S )Nr   )HTTPExceptionstatuszAdmin access requiredstatus_codedetail)fastapir   r   r   HTTP_403_FORBIDDENr~   r   r   s      r"   require_adminr      sP    --------D!! cm(AJabbbbc cr!   current_userr   c                     ddl m}mm ddlm} |  ||          fd	fd}|S t          |           s j        d          | S )
Nr   )Dependsr   r   )get_current_userr~   r   c                 J    t          |           s j        d          | S )NPlatform admin access requiredr   )r   r   r   s    r"   _require_platform_adminz7require_platform_admin.<locals>._require_platform_admin   s<    $T** #m & 9Bb    Kr!   r   r   )r~   r   )r   r   r   r   app.api.depsr   r   r   )r   r   r   r   r   r   s       @@r"   require_platform_adminr      s    6666666666------3:7;K3L3L 	 	 	 	 	 	 	 	 '& .. 	-"5>^    r!   c                 H    t          | d          rd | j        D             S g S )Nrx   c                 L    g | ]!}|j         	|j        j         |j        j        "S r    )r{   r|   r}   )rZ   r   s     r"   
<listcomp>z"get_user_roles.<locals>.<listcomp>   sA     
 
 
"-
QSQXQc
GL
 
 
r!   )rz   rx   r   s    r"   get_user_rolesr      s>    t\"" 

 
#'?
 
 
 	
 Ir!   
role_codesc                 n    t          |           }|s	| j        v S t          fd|D                       S )Nc              3       K   | ]}|v V  	d S rW   r    )rZ   r}   r   s     r"   r\   zhas_any_role.<locals>.<genexpr>   s(      >>dtz!>>>>>>r!   )r   r|   rf   )r~   r   user_role_codess    ` r"   has_any_roler      sH    $T**O 'yJ&&>>>>o>>>>>>r!   	role_codec                 $    t          | |g          S rW   )r   )r~   r   s     r"   has_roler      s    yk***r!   rW   )r   r   )9rQ   r   r   typingr   r   joser   r   passlib.contextr   
app.configr	   common_loggingr
   __name__r0   
app.modelsr   r.   r   r   __annotations__r#   r+   boolr3   r8   dictrH   rN   verify_tokenrS   tuplerg   rl   rq   rv   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   listr   r   r   r    r!   r"   <module>r      s    ( ( ( ( ( ( ( (                      ( ( ( ( ( (       % % % % % %	H		  lH:&AAA$(u{T! ( ( (%+     C # $          d 9t3C s    s td{     #%S % % % % tSy1A    9 9C 9D 9 9 9 9C D    7c 7 7 7 76t 6 6 6 65d 5 5 5 56t 6 6 6 65d 5 5 5 5I I I I IJd J J J JJd J J J JJ J J J JID I I I I.sTz .d . . . . DH	 	 	69Dj			 	 	 	
 
t 
s 
 
 
 
c c c    .D    ?4 ?D ? ? ? ?+c +d + + + + + +r!   