
    Cj.              
       Z   d Z ddlZddlmZmZmZ ddlmZmZ ddlm	Z	 ddl
Z
ddlZddlZddlmZmZmZmZmZ ddlmZ ddlmZmZ dd	lmZmZ ej6                  j9                  d
d      ZdZdZdZ ed   Z! G d de      Z" G d de      Z# G d de      Z$ G d de      Z% edd      Z&e&jO                  edgddgdg       e	d        Z(e	d        Z)d e*d!e*fd"Z+d e*d#e*d!e,fd$Z-d%e*d&e*d'e*d(ee*   d!e*f
d)Z.d*e*d!e/fd+Z0 ed      fd,ee*   d!e/fd-Z1 ee1      fd!e/fd.Z2e&j9                  d/      d0        Z3e&j9                  d1      d2        Z4e&jk                  d3      d4e"fd5       Z6e&jk                  d6       ee1      fd7       Z7e&j9                  d8       ee1      fd9       Z8e&jk                  d:       ee1      fd4e#fd;       Z9e&jk                  d<       ee2      fd4e$fd=       Z:e&jk                  d>       ee2      fd4e%fd?       Z;e&j9                  d@       ee2      fdA       Z<y)Bu   
Demandas Auth Service
Autenticação JWT própria para a ferramenta de demandas.
Substitui o Supabase Auth.

Roda em 127.0.0.1:3009
    N)datetime	timedeltatimezone)OptionalLiteral)contextmanager)FastAPIHTTPExceptionDependsstatusHeader)CORSMiddleware)	BaseModelEmailStr)jwtJWTErrorDEMANDAS_JWT_SECRET"demandas_jwt_secret_climb_2026_miaHS256   zdbname=demandas user=mia)super_adminadmingestorcolaboradorc                   "    e Zd ZU eed<   eed<   y)LoginRequestemailpasswordN__name__
__module____qualname__str__annotations__     (/opt/mia/workspace/demandas-auth/main.pyr   r       s    JMr&   r   c                   "    e Zd ZU eed<   eed<   y)ChangePasswordRequestcurrent_passwordnew_passwordNr   r%   r&   r'   r)   r)   %   s    r&   r)   c                   b    e Zd ZU eed<   eed<   eed<   dZee   ed<   dZeed<   dZ	ee   ed<   y)	AdminCreateUserRequestr   r   nomeNcargor   	permissaoworkspace_id)
r    r!   r"   r#   r$   r/   r   r0   	Permissaor1   r%   r&   r'   r-   r-   *   s7    JM
IE8C=(Iy("&L(3-&r&   r-   c                   "    e Zd ZU eed<   eed<   y)AdminSetPasswordRequestuser_idr+   Nr   r%   r&   r'   r4   r4   3   s    Lr&   r4   zDemandas Auth1.0.0)titleversion*F)allow_originsallow_credentialsallow_methodsallow_headersc               #      K   t        j                  t              } 	 |  | j                          	 | j                          y # t        $ r | j                           w xY w# | j                          w xY ww)N)psycopg2connectDB_DSNcommit	Exceptionrollbackclose)conns    r'   db_connrG   E   s\     F#D

 	

	   	

s'   A6A A6AA! !A33A6c               #      K   t               5 } | j                  t        j                  j                        }	 | |j                          	 d d d        y # |j                          w xY w# 1 sw Y   y xY ww)N)cursor_factory)rG   cursorr?   extrasRealDictCursorrE   )rF   curs     r'   	db_cursorrN   R   s`     	 dkk)G)GkH	IIIK 
 IIK s2   A8+A,AA,	A8A))A,,A51A8r   returnc                     t        j                  | j                  d      t        j                               j	                  d      S )Nutf-8)bcrypthashpwencodegensaltdecode)r   s    r'   hash_passwordrW   ]   s.    ==16>>3CDKKGTTr&   hashedc                     |r|dk(  ry	 t        j                  | j                  d      |j                  d            S # t        $ r Y yw xY w)NMIGRATED_NO_PASSWORDFrQ   )rR   checkpwrT   rC   )r   rX   s     r'   verify_passwordr\   a   sJ    V55~~hoog6g8NOO s   3> 	A
	A
r5   r   r0   r1   c                    t        j                  t        j                        }| |||dt	        |j                               t	        |t        t              z   j                               d}t        j                  |t        t              S )Nweb_anon)hours)subr   r0   r1   roleiatexp)	algorithm)r   nowr   utcint	timestampr   JWT_EXP_HOURSr   rT   
JWT_SECRETJWT_ALGORITHM)r5   r   r0   r1   re   payloads         r'   
make_tokenrm   j   sh    
,,x||
$C$3==?#C)-88CCEFG ::gz]CCr&   tokenc                     	 t        j                  | t        t        g      S # t        $ r}t        dd|       d }~ww xY w)N)
algorithms  u   Token inválido: status_codedetail)r   rV   rj   rk   r   r
   )rn   es     r'   decode_tokenrv   x   sD    Mzz%HH M6Gs4KLLMs    # 	A<Aauthorizationc                     | r| j                         j                  d      st        dd      | j                  dd      d   j	                         }t        |      }|S )Nzbearer rq   zToken ausenterr       )lower
startswithr
   splitstriprv   )rw   rn   rl   s      r'   get_current_userr      sW     3 3 5 @ @ KODDQ'*002E5!GNr&   c                 F    | j                  d      dvrt        dd      | S )Nr0   )r   r     z!Acesso restrito a administradoresrr   )getr
   currents    r'   require_adminr      s'    {{;'??4WXXNr&   /c                      ddddS )Nzdemandas-authokr6   )servicer   r8   r%   r%   r&   r'   rootr      s    &$7KKr&   z/healthc                      	 t               5 } | j                  d       | j                          d d d        dddS # 1 sw Y   xY w# t        $ r}t	        dd|       d }~ww xY w)NzSELECT 1r   )r   dbi  z
db error: rr   )rN   executefetchonerC   r
   )rM   ru   s     r'   healthr      sm    F[ 	CKK
#LLN	 d++	 	  Fj4DEEFs+   
A ";A A A 	A%A  A%z/auth/loginreqc                 *   t               5 }|j                  d| j                  f       |j                         }d d d        st	        dd      t        | j                  |d         st	        dd      |j                  d      du rt	        dd	      t        |d
         }|j                  d      xs d}|j                  d      rt        |d         nd }t        ||d   ||      }|d||d   |j                  d      ||ddS # 1 sw Y   xY w)Nz
            SELECT u.id, u.email, u.password,
                   p.nome, p.permissao, p.workspace_id, p.ativo
            FROM auth_users u
            LEFT JOIN profiles p ON p.id = u.id
            WHERE lower(u.email) = lower(%s)
            rq   u   Email ou senha inválidosrr   r   ativoFr   u   Usuário desativadoidr0   r   r1   r   bearerr.   r   r   r.   r0   r1   )access_token
token_typeuser)
rN   r   r   r   r
   r\   r   r   r#   rm   )r   rM   rowr5   r0   r1   rn   s          r'   loginr      s   	  YYL		
 lln 4OPP3<<Z94OPP
www5 4IJJ#d)nG$5I/2ww~/F3s>*+DLwGiFE \GGFO"(

 
9 s   .D		Dz/auth/logoutc                 
    ddiS )Nr   r   r%   r   s    r'   logoutr      s     dr&   z/auth/mec           
      \   | d   }t               5 }|j                  d|f       |j                         }d d d        st        dd      t	        |d         |d   |d   |d	   |d
   |d   |d   rt	        |d         nd |d   |d   r|d   j                         d	S d d	S # 1 sw Y   oxY w)Nr`   z
            SELECT id, nome, email, cargo, permissao, avatar_url,
                   workspace_id, ativo, criado_em
            FROM profiles WHERE id = %s
              u   Profile não encontradorr   r   r.   r   r/   r0   
avatar_urlr1   r   	criado_em	r   r.   r   r/   r0   r   r1   r   r   )rN   r   r   r
   r#   	isoformat)r   r5   rM   r   s       r'   mer      s    enG	 	
 J	
 lln	 4MNN #d)nFWW%,'474GC/0TW585ES%//1
 
 LP
 
	 	s   $B""B+z/auth/change-passwordc                    t        | j                        dk  rt        dd      |d   }t               5 }|j	                  d|f       |j                         }|st        dd      t        | j                  |d	         st        d
d      t        | j                        }|j	                  d||f       d d d        ddiS # 1 sw Y   ddiS xY w)N     $Senha deve ter ao menos 6 caracteresrr   r`   z-SELECT password FROM auth_users WHERE id = %sr      Usuário não encontrador   rq   zSenha atual incorreta1UPDATE auth_users SET password = %s WHERE id = %sr   r   )	lenr+   r
   rN   r   r   r\   r*   rW   )r   r   r5   rM   r   new_hashs         r'   change_passwordr      s    
3q 4Z[[enG	 	^CgZPllnC8RSSs33S_EC8OPP !1!12G(T[I\]	^ d	^ ds   BCCz/auth/admin/create-userc           
         t        | j                        dk  rt        dd      | j                  dk(  r!|j	                  d      dk7  rt        dd      | j
                  xs |j	                  d	      }|j	                  d      d
k(  r!||j	                  d	      k7  rt        dd      t        | j                        }t               5 }|j                  d| j                  f       |j                         rt        dd      |j                  d| j                  |f       |j                         d   }|j                  d|| j                  | j                  | j                  | j                  |f       d d d        t              | j                  | j                  | j                  |rt        |      dS d dS # 1 sw Y   GxY w)Nr   r   r   rr   r   r0   r   z)Apenas super_admin pode criar super_adminr1   r   u4   Admin só pode criar usuários no próprio workspacez8SELECT id FROM auth_users WHERE lower(email) = lower(%s)i  u   Email já cadastradozEINSERT INTO auth_users (email, password) VALUES (%s, %s) RETURNING idr   a  
            INSERT INTO profiles (id, nome, email, cargo, permissao, workspace_id, ativo)
            VALUES (%s, %s, %s, %s, %s, %s, true)
            ON CONFLICT (id) DO UPDATE SET
                nome = EXCLUDED.nome,
                email = EXCLUDED.email,
                cargo = EXCLUDED.cargo,
                permissao = EXCLUDED.permissao,
                workspace_id = EXCLUDED.workspace_id
            r   )r   r   r
   r0   r   r1   rW   rN   r   r   r   r.   r/   r#   )r   r   r1   pwd_hashrM   new_ids         r'   admin_create_userr     s   
3<<14Z[[ }}%'++k*Bm*S4_`` ##Bw{{>'BL {{;7*|w{{>?Z/Z4jkkS\\*H	 
NQTQZQZP\]<<>C8NOO 	SYY!	
 % 		 SXXsyy#))S]]LQ	

: &k]]-9L) 
 @D 9
 
s   	B,F;;Gz/auth/admin/set-passwordc                 D   t        | j                        dk  rt        dd      t               5 }|j	                  d      dk(  rr|j                  d| j                  f       |j                         }|st        dd	      |d
   rt        |d
         nd }||j	                  d
      k7  rt        dd      t        | j                        }|j                  d|| j                  f       |j                  dk(  rt        dd	      	 d d d        ddiS # 1 sw Y   ddiS xY w)Nr   r   r   rr   r0   r   z/SELECT workspace_id FROM profiles WHERE id = %sr   r   r1   r   u4   Admin só pode redefinir senha do próprio workspacer   r   r   r   )r   r+   r
   rN   r   r   r5   r   r#   rW   rowcount)r   r   rM   r   	target_wsr   s         r'   admin_set_passwordr   9  s   
3q 4Z[[	 T;;{#w.KKICKK>Z,,.C#<VWW474GC/0TIGKK77#<rss !1!12G(TWT_T_I`a<<1C8RSS T  d!T  ds   CDDz/auth/admin/usersc                    | j                  d      dk(  }t               5 }|r|j                  d       n"|j                  d| j                  d      f       |j                         }d d d        D cg c]W  }t	        |d         |d   |d   |d	   |d   |d
   |d   rt	        |d         nd |d   |d   r|d   j                         nd d	Y c}S # 1 sw Y   lxY wc c}w )Nr0   r   z
                SELECT id, nome, email, cargo, permissao, avatar_url,
                       workspace_id, ativo, criado_em
                FROM profiles
                ORDER BY criado_em DESC
                z
                SELECT id, nome, email, cargo, permissao, avatar_url,
                       workspace_id, ativo, criado_em
                FROM profiles
                WHERE workspace_id = %s
                ORDER BY criado_em DESC
                r1   r   r.   r   r/   r   r   r   r   )r   rN   r   fetchallr#   r   )r   is_superrM   rowsrs        r'   admin_list_usersr   Q  s    {{;'=8H	 KK KK ^,.	 ||~+F   ag,fIwZwZ;L/676GC. 12TwZ78~;1134
	
 / .s   AC2ACC)=__doc__osr   r   r   typingr   r   
contextlibr   rR   r?   psycopg2.extrasfastapir	   r
   r   r   r   fastapi.middleware.corsr   pydanticr   r   joser   r   environr   rj   rk   ri   rA   r2   r   r)   r-   r4   appadd_middlewarerG   rN   r#   rW   boolr\   rm   dictrv   r   r   r   r   postr   r   r   r   r   r   r   r%   r&   r'   <module>r      s   
 2 2 $ %    C C 2 (  ZZ^^13WX
	#CD	9 
I 
'Y 'i  OW5   %%%   	 	  UC UC Uc 3 4 D DC DC DxPS} DY\ DM M M 5;4L HSM T  ""23   L L F F -'| ' 'T .+,  
 '(  : 
!"8?@P8Q .  #& 
#$;B=;Q 31 3 %3l 
$%=D]=S 3  &. 	$]3 & &r&   