
    Iin                         S r SSKrSSKrSSKrSSKJrJr  SSKJr  SSK	J
r
  SSKJrJr  SSKJr   " S S	\5      r\(       a  S
SKJrJr   " S S5      rg)z&Authentication and session management.    N)Enumauto)TYPE_CHECKING)PasswordHasher)VerifyMismatchErrorInvalidHashError)
TrustLevelc                   B    \ rS rSrSr\" 5       r\" 5       r\" 5       rSr	g)
AuthResult   z$Result of an authentication attempt. N)
__name__
__module____qualname____firstlineno____doc__r   SUCCESSUSER_NOT_FOUNDWRONG_PASSWORD__static_attributes__r       /c:\Users\dbart\PlayPalace11\server\auth\auth.pyr   r      s    .fGVNVNr   r      )Database
UserRecordc                      \ rS rSrSrS$S jrS\S\4S jrS\S\4S jrS\S\	4S	 jr
S\S\S\	4S
 jrS\S\S\4S jrSSS.S\S\S\	S\S\	4
S jjrS\S\S\	4S jrS\SS4S jrS\S\S\\\4   4S jrS\S\S-  4S jrS\SS4S jrS\SS4S jrS\S\S\\\4   4S jrS\S \S!\S\\\\\\4   S-  4S" jrS#rg)%AuthManager   zHandle user authentication and session management.

Uses Argon2 for password hashing and supports migration from legacy
SHA-256 hashes on successful login.
c                 <    Xl         0 U l        [        5       U l        g)z4Initialize the auth manager with a database backend.N)_db	_sessionsr   _hasher)selfdatabases     r   __init__AuthManager.__init__"   s    57%'r   passwordreturnc                 8    U R                   R                  U5      $ )zHash a password using Argon2.)r"   hashr#   r'   s     r   hash_passwordAuthManager.hash_password(   s    ||  **r   c                 f    [         R                  " UR                  5       5      R                  5       $ )z*Legacy SHA-256 hash for migration support.)hashlibsha256encode	hexdigestr+   s     r   _hash_password_sha256!AuthManager._hash_password_sha256,   s!    ~~hoo/0::<<r   password_hashc                 l    [        U5      S:H  =(       a     [        S UR                  5        5       5      $ )z=Check if a hash is a legacy SHA-256 hash (64 hex characters).@   c              3   *   #    U  H	  oS ;   v   M     g7f)0123456789abcdefNr   ).0cs     r   	<genexpr>.AuthManager._is_legacy_hash.<locals>.<genexpr>2   s      0
-B##-Bs   )lenalllower)r#   r5   s     r   _is_legacy_hashAuthManager._is_legacy_hash0   s6    =!R' 
C 0
-:-@-@-B0
 -
 	
r   c                      U R                   R                  X!5        g! [        [        4 a     Of = fU R	                  U5      (       a  U R                  U5      U:H  $ g)zMVerify a password against its hash (supports both Argon2 and legacy SHA-256).TF)r"   verifyr   r   rA   r3   )r#   r'   r5   s      r   verify_passwordAuthManager.verify_password6   s`    	LL8#%56 		 ..--h7=HHs    11usernamec                 ~   U R                   R                  U5      nU(       d  [        R                  $ U R	                  X#R
                  5      (       d  [        R                  $ U R                  UR
                  5      (       a,  U R                  U5      nU R                   R                  X5        [        R                  $ )zAuthenticate a user.

Args:
    username: Username to authenticate.
    password: Plaintext password to verify.

Returns:
    AuthResult indicating success or failure reason.
)r    get_userr   r   rE   r5   r   rA   r,   update_user_passwordr   )r#   rG   r'   usernew_hashs        r   authenticateAuthManager.authenticateE   s     xx  *,,,##H.@.@AA,,,  2 233))(3HHH))(=!!!r   Fen)approvedlocalerP   rQ   c                    U R                   R                  U5      (       a  g[        R                  nU R	                  U5      nU R                   R                  XXEU5        g)a  Register a new user.

Args:
    username: Username to create.
    password: Plaintext password.
    approved: Whether the account is pre-approved (skips admin approval).
    locale: Preferred locale.

Returns:
    True if registration succeeded, False if username taken.
FT)r    user_existsr	   USERr,   create_user)r#   rG   r'   rP   rQ   trust_levelr5   s          r   registerAuthManager.register]   sN     88)) oo**84Xf8Tr   new_passwordc                     U R                   R                  U5      (       d  gU R                  U5      nU R                   R                  X5        g)zReset a user's password.

Args:
    username: Username to update.
    new_password: New plaintext password.

Returns:
    True if successful, False if user doesn't exist.
FT)r    rS   r,   rJ   )r#   rG   rY   r5   s       r   reset_passwordAuthManager.reset_passwords   sA     xx##H--**<8%%h>r   zUserRecord | Nonec                 8    U R                   R                  U5      $ )zGet a user record.)r    rI   )r#   rG   s     r   rI   AuthManager.get_user   s    xx  **r   ttl_secondsc                     [         R                  " S5      n[        [        R                  " 5       5      U-   nX4U R                  U'   X44$ )z[Create an access session token for a user.

Returns:
    (token, expires_at_epoch_seconds)
    )secrets	token_hexinttimer!   )r#   rG   r_   token
expires_ats        r   create_sessionAuthManager.create_session   sC     !!"%%3
!) 6u  r   rf   Nc                     U R                   R                  U5      nU(       d  gUu  p4U[        [        R                  " 5       5      ::  a  U R                   R	                  US5        gU$ )z!Validate an access session token.N)r!   getrd   re   pop)r#   rf   entryrG   rg   s        r   validate_sessionAuthManager.validate_session   sS    ""5)$TYY[))NNud+r   c                 <    U R                   R                  US5        g)zDInvalidate a session token.

Args:
    token: Session token string.
N)r!   rl   )r#   rf   s     r   invalidate_sessionAuthManager.invalidate_session   s     	5$'r   c                     U R                   R                  5        VVVs/ s H  u  nu  p4X1:X  d  M  UPM     nnnnU H  nU R                   U	 M     gs  snnnf )zhInvalidate all sessions for a user.

Args:
    username: Username whose sessions should be invalidated.
N)r!   items)r#   rG   tu_expires_at	to_removerf   s          r   invalidate_user_sessions$AuthManager.invalidate_user_sessions   sO     37..2F2F2HZ2H.1.qAMQ2H	ZEu%  [s
   AAc                     [         R                  " S5      n[        [        R                  " 5       5      nXB-   nU R                  R                  XXT5        X54$ )z#Create and persist a refresh token.ra   )rb   rc   rd   re   r    store_refresh_token)r#   rG   r_   rf   nowrg   s         r   create_refresh_token AuthManager.create_refresh_token   sG    !!"%$))+&
$$XjF  r   refresh_tokenaccess_ttl_secondsrefresh_ttl_secondsc                    U R                   R                  U5      nU(       d  gUS   nU R                   R                  U5      (       d  g[        [        R                  " 5       5      nUS   c
  US   (       a  gUS   U::  a  U R                   R                  X5        g[        R                  " S5      nXc-   nU R                   R                  XWX5        U R                   R                  XUS9  U R                  XR5      u  pXYXU4$ )zRotate refresh token and issue a new access token.

Returns:
    (username, access_token, access_expires_at, refresh_token, refresh_expires_at)
NrG   
revoked_atreplaced_byrg   ra   )r   )
r    get_refresh_tokenrS   rd   re   revoke_refresh_tokenrb   rc   r|   rh   )r#   r   r   r   recordrG   r}   new_refresh_tokennew_refresh_expiresaccess_tokenaccess_expiress              r   refresh_sessionAuthManager.refresh_session   s     ++M:*%xx##H--$))+,+vm/D,3&HH))-=#--b1!7$$XBU[%%mFW%X'+':':8'X$~J]]]r   )r    r"   r!   )r$   r   )r   r   r   r   r   r%   strr,   r3   boolrA   rE   r   rM   rW   r[   rI   rd   tuplerh   rn   rq   ry   r~   r   r   r   r   r   r   r      s   (+c +c +=c =c =
S 
T 
 C D "S "C "J "0 JO^b   $ X[ gk ,s # $ "+ +)< +	!s 	! 	!sCx 	!	c 	cDj 	( ( (& & &!S !s !uSRUX !^ ^69^PS^	sCc3&	'$	.^r   r   )r   r/   rb   re   enumr   r   typingr   argon2r   argon2.exceptionsr   r   server.core.users.baser	   r   persistence.databaser   r   r   r   r   r   <module>r      sB    ,       ! C -  ;z^ z^r   