Ë
    >È'jG'  ã            
       ó  — d dl m Z mZmZ d dlmZmZmZmZ d dlm	Z	 d dl
mZ d dlmZmZ d dlmZ d dlmZmZmZ d dlmZmZmZmZmZmZmZmZmZ d d	lm Z m!Z! d d
l"m#Z#m$Z$ d dl%m&Z&m'Z'm(Z( d dl)m*Z*m+Z+  eddg¬«      Z,e,j[                  deej\                  ¬«       ee«      fdedefd„«       Z/e,j[                  de¬«       ee«      fdedefd„«       Z0e,j[                  de¬«       ee«      fdefd„«       Z1dZ2dZ3dZ4 ed¬«      Z5d e6d!d"fd#„Z7ded$ed%e6d&e6d!d"f
d'„Z8d(e d!e fd)„Z9ded$ed!e:fd*„Z;deded!efd+„Z<deded!efd,„Z=e,j[                  d-e¬«       ee«      fdedefd.„«       Z>e,j[                  d/e¬«       ee«      fdedefd0„«       Z?e,j[                  d1e¬«       ee«      fdedefd2„«       Z@e,j[                  d3e¬«       ee«      fdedefd4„«       ZAe,j[                  d5e¬«       ee«      fdedefd6„«       ZBy")7é    )ÚdatetimeÚ	timedeltaÚtimezone)Ú	APIRouterÚDependsÚHTTPExceptionÚstatus)ÚIntegrityError)ÚSession)Úget_dbÚrelease_db_connection)Úrequire_user_token)ÚPasswordResetTokenÚUserÚUserRole)	ÚForgotPasswordRequestÚLoginRequestÚMessageÚResetPasswordRequestÚTokenÚUserRegisterRequestÚUserTokenResponseÚVerifyEmailRequestÚVerifyOTPRequest)Úhash_passwordÚverify_password)ÚauthenticateÚissue_token_for)Úcreate_password_reset_flowÚsend_otp_emailÚverify_email_with_otp)Úfind_user_by_emailÚsend_password_reset_otpz/authz	user-auth)ÚprefixÚtagsz	/register)Úresponse_modelÚstatus_codeÚbodyÚdbc              ƒ   ó<  K  — t        | j                  «      }t        d|› �«       |j                  t        «      j                  t        j                  |k(  «      j                  «       r*t        d|› d�«       t        t        j                  d¬«      ‚t	        || j                  t        | j                  «      t        j                  d¬«      }	 |j                  |«       |j!                  «        |j'                  «        |j)                  |«       t+        |||d¬	«      ƒ d {  –—†  t-        t/        |«      |j                  |j0                  ¬
«      S # t"        $ r; |j%                  «        t        d|› d�«       t        t        j                  d¬«      ‚w xY w7 Œv­w)Nz$register request received for email=zregister failed for email=z: email already registeredzEmail already registered©r'   ÚdetailF)ÚemailÚ	full_nameÚhashed_passwordÚroleÚemail_verifiedÚregister©r-   Úsource©Úaccess_tokenr-   r1   )Ústrr-   Ú_print_user_otp_debugÚqueryr   ÚfilterÚfirstr   r	   ÚHTTP_409_CONFLICTr.   r   Úpasswordr   ÚuserÚaddÚflushr
   ÚrollbackÚcommitÚrefreshÚ_send_user_verification_otpr   r   r1   ©r(   r)   r-   r>   s       ú@/var/www/html/kelly/kelly-backend/app/routers/user_panel/auth.pyÚuser_registerrG      sO  è ø€ ä�—
‘
‹O€EÜÐ@ÀÀÐHÔIà	‡x�x”ƒ~×ÑœTŸZ™Z¨5Ñ0Ó1×7Ñ7Ô9ÜÐ :¸5¸'ÐA[Ð\Ô]Ü¬×(@Ñ(@ÐIcÔdÐdäØØ—.‘.Ü% d§m¡mÓ4Ü�]‰]Øô€DðeØ
�‰ˆtŒØ
�‰Œ
ð ‡I�I„KØ‡J�JˆtÔÜ
% b¨$°eÀJÔ
O×OÐOÜÜ$ TÓ*Ø�j‰jØ×*Ñ*ôð øô ò eØ
�‰ŒÜÐ :¸5¸'ÐA[Ð\Ô]Ü¬×(@Ñ(@ÐIcÔdÐdðeúð Pús+   ‚CFÃ!E Ã03FÄ#FÄ$/FÅAFÆFz/login)r&   c                 ó�  — t        || j                  | j                  «      }|r|j                  t        j
                  k7  rt        t        j                  d¬«      ‚|j                  st        t        j                  d¬«      ‚ddlm}  |||d¬«       t        t        |«      |j                  t        |j                   «      ¬«      S )	NzInvalid user credentialsr+   zInactive accountr   )Útouch_user_last_activeT)rB   r5   )r   r-   r=   r0   r   r>   r   r	   ÚHTTP_401_UNAUTHORIZEDÚ	is_activeÚHTTP_403_FORBIDDENÚ-app.services.member_inactive_followup_servicerI   r   r   Úboolr1   )r(   r)   r>   rI   s       rF   Ú
user_loginrO   ?   s’   € ä˜˜DŸJ™J¨¯©Ó6€DÙ�4—9‘9¤§¡Ò-Ü¬×(DÑ(DÐMgÔhÐhØ�>Š>Ü¬×(AÑ(AÐJ\Ô]Ð]ÝTá˜2˜t¨DÕ1ÜÜ$ TÓ*Ø�j‰jÜ˜D×/Ñ/Ó0ôð ó    z/logoutÚ_c                 ó   — t        d¬«      S )Nz
Logged out©Úmessage)r   )rQ   s    rF   Úuser_logoutrU   P   s   € ä˜<Ô(Ð(rP   zIIf an account exists for this email, a password reset code has been sent.z=Password reset code sent. Check your inbox (and spam folder).z;Verification code sent. Check your inbox (and spam folder).é<   )ÚsecondsrT   ÚreturnNc                 ó$   — t        d| › �d¬«       y )Nz[USER SEND OTP] T)r@   )ÚprintrS   s    rF   r8   r8   [   s   € Ü	Ð˜W˜IÐ
&¨dÖ3rP   r>   r-   r4   c             ƒ   ó*  K  — t        | |«      }|j                  }t        |› d|› d|› �«       t        | «       t	        ||«      ƒ d {  –—† }|s.t        |› d|› d|› �«       t        t        j                  d¬«      ‚t        |› d|› d|› �«       y 7 ŒH­w)Nz: generated otp=z for email=z: failed to send otp=zECould not send verification email. Check SMTP settings on the server.r+   z: sent otp=z successfully for email=)r   r-   r8   r   r    r   r	   ÚHTTP_503_SERVICE_UNAVAILABLE)r)   r>   r-   r4   ÚotpÚ	recipientÚsents          rF   rD   rD   _   s¥   è ø€ ô % R¨Ó
.€CØ—
‘
€IÜ˜V˜HÐ$4°S°E¸ÀUÀGÐLÔMÜ˜"ÔÜ 	¨3Ó/×/€DÙÜ  Ð(=¸c¸UÀ+ÈeÈWÐUÔVÜÜ×;Ñ;ØZô
ð 	
ô ˜V˜H K°¨uÐ4LÈUÈGÐTÕUð 0ús   ‚ABÁBÁ	A	BÚvaluec                 ó˜   — | j                   € | j                  t        j                  ¬«      S | j	                  t        j                  «      S )N©Útzinfo)rc   Úreplacer   ÚutcÚ
astimezone)r`   s    rF   Ú_as_utcrg   t   s6   € Ø‡|�|ÐØ�}‰}¤H§L¡Lˆ}Ó1Ð1Ø×ÑœHŸL™LÓ)Ð)rP   c                 ó  — | j                  t        «      j                  t        j                  |j                  k(  t        j
                  j                  d«      «      j                  t        j                  j                  «       «      j                  «       }|r|j                  syt        j                  t        j                  «      }t        |j                   «      }t        |j                  «      }||kD  xr ||t"        z
  k\  S )NF)r9   r   r:   Úuser_idÚidÚusedÚis_Úorder_byÚ
created_atÚdescr;   r   Únowr   re   rg   Ú
expires_atÚ_OTP_DUPLICATE_WINDOW)r)   r>   Ú	token_rowrp   rq   rn   s         rF   Ú_has_recent_active_otprt   z   sÁ   € à
�‰Ô#Ó$ß	‰Ô"×*Ñ*¨d¯g©gÑ5Ô7I×7NÑ7N×7RÑ7RÐSXÓ7YÓ	Zß	‰Ô$×/Ñ/×4Ñ4Ó6Ó	7ß	‰‹ð	 ñ ˜I×0Ò0Øä
�,‰,”x—|‘|Ó
$€CÜ˜×-Ñ-Ó.€JÜ˜×-Ñ-Ó.€JØ˜ÑÒI 
¨cÔ4IÑ.IÑ IÐIrP   c              ƒ   ó\  K  — t        |t        | j                  «      t        j                  ¬«      }|st        t        j                  d¬«      ‚	 t        ||«      ƒ d {  –—†  t        t        ¬«      S 7 Œ# t        $ r*}t        t        j                  t        |«      ¬«      |‚d }~ww xY w­w)N©r0   úEmail is not registeredr+   rS   )r"   r7   r-   r   r>   r   r	   ÚHTTP_404_NOT_FOUNDr#   ÚRuntimeErrorr\   r   Ú_USER_FORGOT_SENT_MSG)r(   r)   r>   Úexcs       rF   Ú_user_forgot_password_handlerr|   Š   s•   è ø€ Ü˜b¤# d§j¡j£/¼¿¹ÔF€DÙÜÜ×1Ñ1Ø,ô
ð 	
ðÜ% b¨$Ó/×/Ð/ô Ô0Ô1Ð1ð 	0ùÜò ÜÜ×;Ñ;Ü�s“8ô
ð ð	ûðüs<   ‚AB,ÁA6 ÁA4Á A6 Á$B,Á4A6 Á6	B)Á?%B$Â$B)Â)B,c              ƒ   ó  K  — t        | j                  «      }t        d|› �«       t        ||t        j
                  ¬«      }|s*t        d|› d�«       t        t        j                  d¬«      ‚|j                  r#t        d|› d�«       t        | |«      ƒ d {  –—† S t        ||«      r+t        d	|› d
|j                  › �«       t        t        ¬«      S t        |||d¬«      ƒ d {  –—†  t        t        ¬«      S 7 Œb7 Œ­w)Nzrequest received for email=rv   zfailed for email=z: email is not registeredrw   r+   zemail=z8 is already verified; sending password reset OTP insteadz+recent active OTP already exists for email=z; current otp=rS   zsend-otpr3   )r7   r-   r8   r"   r   r>   r   r	   rx   r1   r|   rt   r]   r   Ú_USER_VERIFICATION_MSGrD   rE   s       rF   Ú_user_verification_otp_handlerr   ›   sö   è ø€ Ü�—
‘
‹O€EÜÐ7¸°wÐ?Ô@ä˜b %¬h¯m©mÔ<€DÙÜÐ 1°%°Ð8QÐRÔSÜÜ×1Ñ1Ø,ô
ð 	
ð ×ÒÜØ�U�GÐSÐTô	
ô 3°4¸Ó<×<Ð<Ü˜b $Ô'ÜØ9¸%¸ÀÈtÏxÉxÈjÐYô	
ô Ô5Ô6Ð6ä
% b¨$°eÀJÔ
O×OÐOÜÔ1Ô2Ð2ð =øð Pús%   ‚BC?ÂC;ÂAC?Ã&C=Ã'C?Ã=C?z/forgot-passwordc              ƒ   ó6   K  — t        | |«      ƒ d {  –—† S 7 Œ­w)N)r|   ©r(   r)   s     rF   Úuser_forgot_passwordr‚   µ   s   è ø€ ä.¨t°RÓ8×8Ð8Ð8úó   ‚’“z	/send-otpc              ƒ   ó6   K  — t        | |«      ƒ d{  –—† S 7 Œ­w)zOSend/resend a user OTP without duplicating the registration verification email.N)r   r�   s     rF   Úuser_send_otpr…   º   s   è ø€ ô 0°°bÓ9×9Ð9Ð9úrƒ   z/verify-emailc                 ó$  — 	 t        |t        | j                  «      | j                  j	                  «       ¬«      }t        t        |«      |j                  d¬«      S # t
        $ r*}t        t        j                  t        |«      ¬«      |‚d}~ww xY w)zDVerify email once; sets users.email_verified = true in the database.)r-   r]   r+   NTr5   )r!   r7   r-   r]   ÚstripÚ
ValueErrorr   r	   ÚHTTP_400_BAD_REQUESTr   r   )r(   r)   r>   Úes       rF   Úuser_verify_emailr‹   À   sy   € ð[Ü$ R¬s°4·:±:«ÀDÇHÁHÇNÁNÓDTÔUˆô Ü$ TÓ*Ø�j‰jØôð øô ò [Ü¬×(CÑ(CÌCÐPQËFÔSÐYZÐZûð[ús   ‚9A Á	BÁ%%B
Â
Bz/reset-passwordc                 óÈ  — t        |t        | j                  «      t        j                  ¬«      }|st        t        j                  d¬«      ‚|j                  t        «      j                  t        j                  |j                  k(  t        j                  j                  d«      «      j                  t        j                   j#                  «       «      j%                  «       }|r.t'        | j(                  j+                  «       |j,                  «      st        t        j                  d¬«      ‚|j.                  }|j0                  € |j3                  t4        j6                  ¬«      }|t9        j:                  t4        j6                  «      k  rt        t        j                  d¬«      ‚t=        | j>                  «      |_         d|_        |jC                  «        tE        d	¬
«      S )Nrv   úInvalid requestr+   FzInvalid or expired OTPrb   úOTP expiredTzPassword updatedrS   )#r"   r7   r-   r   r>   r   r	   r‰   r9   r   r:   ri   rj   rk   rl   rm   rn   ro   r;   r   r]   r‡   Úotp_hashrq   rc   rd   r   re   r   rp   r   Únew_passwordr/   rB   r   ©r(   r)   r>   rs   Úexpiress        rF   Úuser_reset_passwordr“   Î   sJ  € ä˜b¤# d§j¡j£/¼¿¹ÔF€DÙÜ¬×(CÑ(CÐL]Ô^Ð^ð 	�‰Ô#Ó$ß	‰Ô"×*Ñ*¨d¯g©gÑ5Ô7I×7NÑ7N×7RÑ7RÐSXÓ7YÓ	Zß	‰Ô$×/Ñ/×4Ñ4Ó6Ó	7ß	‰‹ð	 ñ œO¨D¯H©H¯N©NÓ,<¸i×>PÑ>PÔQÜ¬×(CÑ(CÐLdÔeÐeà×"Ñ"€GØ‡~�~ÐØ—/‘/¬¯©�/Ó6ˆØ”—‘œhŸl™lÓ+Ò+Ü¬×(CÑ(CÈMÔZÐZä(¨×):Ñ):Ó;€DÔØ€I„NØ‡I�I„KÜÐ-Ô.Ð.rP   z/verify-otpc                 ó¦  — t        |t        | j                  «      t        j                  ¬«      }|st        t        j                  d¬«      ‚|j                  r'|j                  | j                  j                  «       k7  rt        t        j                  d¬«      ‚|j                  t        «      j                  t        j                  |j                  k(  t        j                  j!                  d«      «      j#                  t        j$                  j'                  «       «      j)                  «       }|st        t        j                  d¬«      ‚|j*                  }|j,                  € |j/                  t0        j2                  ¬«      }|t5        j6                  t0        j2                  «      k  rt        t        j                  d¬«      ‚t9        d¬	«      S )
Nrv   r�   r+   zinsert the correct otpFrb   rŽ   zOTP verified successfullyrS   )r"   r7   r-   r   r>   r   r	   r‰   r]   r‡   r9   r   r:   ri   rj   rk   rl   rm   rn   ro   r;   rq   rc   rd   r   re   r   rp   r   r‘   s        rF   Úuser_verify_otpr•   é   sA  € ä˜b¤# d§j¡j£/¼¿¹ÔF€DÙÜ¬×(CÑ(CÐL]Ô^Ð^à�8Š8�t—x‘x 4§8¡8§>¡>Ó#3Ò3Ü¬×(CÑ(CÐLdÔeÐeð 	�‰Ô#Ó$ß	‰Ü×&Ñ&¨$¯'©'Ñ1Ü×#Ñ#×'Ñ'¨Ó.ó

÷ 
‰Ô$×/Ñ/×4Ñ4Ó6Ó	7ß	‰‹ð ñ Ü¬×(CÑ(CÐLdÔeÐeà×"Ñ"€GØ‡~�~ÐØ—/‘/¬¯©�/Ó6ˆØ”—‘œhŸl™lÓ+Ò+Ü¬×(CÑ(CÈMÔZÐZäÐ6Ô7Ð7rP   )Cr   r   r   Úfastapir   r   r   r	   Úsqlalchemy.excr
   Úsqlalchemy.ormr   Úapp.databaser   r   Úapp.dependenciesr   Ú
app.modelsr   r   r   Úapp.schemasr   r   r   r   r   r   r   r   r   Úapp.securityr   r   Úapp.services.auth_servicer   r   Úapp.services.email_otpr   r    r!   Ú#app.services.password_reset_servicer"   r#   ÚrouterÚpostÚHTTP_201_CREATEDrG   rO   rU   Ú_USER_FORGOT_MSGrz   r~   rr   r7   r8   rD   rg   rN   rt   r|   r   r‚   r…   r‹   r“   r•   © rP   rF   Ú<module>r¦      sè  ðß 2Ñ 2ç =Ó =Ý )Ý "ç 6Ý /ß 9Ñ 9÷
÷ 
õ 
÷ 8ß Cß dÑ dß [á	˜'¨¨Ô	6€ð ‡�ˆ[Ð):È×H_ÑH_€Ó`ÙAHÈÃñ Ð1ð °wò ó aððB ‡�ˆXÐ&7€Ó8Ù18¸³ñ �\ð  wò ó 9ðð  ‡�ˆY w€Ó/Ù!Ð"4Ó5ñ )�4ò )ó 0ð)ð _Ð ØWÐ ØVÐ Ù!¨"Ô-Ð ð4 3ð 4¨4ó 4ðVØðVà
ðVð ð	Vð
 ðVð 
óVð**�8ð * ó *ðJ˜wð J¨dð J°tó Jð 2Ð.Cð 2Èð 2ÐU\ó 2ð"3Ð/Dð 3È'ð 3ÐV]ó 3ð4 ‡�Ð°€Ó8ÙJQÐRXË/ñ 9Ð%:ð 9Àò 9ó 9ð9ð ‡�ˆ[¨€Ó1ÙCJÈ6Ã?ñ :Ð3ð :¸ò :ó 2ð:ð
 ‡�ˆ_Ð->€Ó?Ù>EÀf»oñ 
Ð.ð 
°Gò 
ó @ð
ð ‡�Ð¨w€Ó7ÙBIÈ&Ã/ñ /Ð2ð /¸ò /ó 8ð/ð4 ‡�ˆ]¨7€Ó3Ù:AÀ&»/ñ 8Ð*ð 8°ò 8ó 4ñ8rP   