
    ng&                        d dl mZmZmZ d dl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 d dlZd dlZd dlZd dlmZmZ d dlZd dlZd dlZd dlmZ d d	lmZ  e         e       Z e       Z ej>                  d
d      Z ddgddgdZ!ejE                  ee!e    ddgdg        ej>                  dd      Z#dZ$dZ% ed      Z& ej>                  dd       ej>                  dd       ej>                  dd       ej>                  d d!      d"dd#d$Z' G d% d&e      Z( G d' d(e      Z)d) Z* ee&      fde+fd*Z,d+e-fd,Z.ej_                  d-      d.e(fd/       Z0ej_                  d0      d.e(fd1       Z1eje                  d2       ee,      fd3e+fd4       Z3ej_                  d5       ee,      fd6e)d3e+fd7       Z4eje                  d8       ee,      fd9e+d3e+fd:       Z5e6d;k(  rd dl7Z7 e7jp                  ed<d=>       yy)?    )FastAPIHTTPExceptionDepends)CORSMiddleware)OAuth2PasswordBearer)DictAnyOptional)	BaseModel	validatorFieldN)datetime	timedelta)load_dotenv)get_game_validatorENVIRONMENTdevelopmentzhttp://localhost:3000zhttp://127.0.0.1:3000zhttps://iammrfrank.netzhttp://iammrfrank.net)r   
productionT*)allow_originsallow_credentialsallow_methodsallow_headersJWT_SECRET_KEYzyour-secret-key-hereHS256i  token)tokenUrlDB_HOST	localhostDB_USERidlegameDB_PASSWORD3w3dCXqhVDl4aB0neAIfO7DDB_NAMEidle_game_dbutf8mb4utf8mb4_unicode_ci)hostuserpassworddatabasecharsetuse_unicode	collationc                       e Zd ZU  eddd      Zeed<    edd      Zeed<    ed      d	        Z	 ed      d
        Z
y)
UserCreate.      )
min_length
max_lengthusername   )r3   r*   c                 H    t        j                  d|      st        d      |S )Nz^[a-zA-Z0-9_-]+$zDUsername can only contain letters, numbers, underscores, and hyphensrematch
ValueErrorclsvs     CC:\Users\fvalley\Desktop\MWHGitProjects\games\idleremake2\server.pyvalidate_usernamezUserCreate.validate_usernameD   s"    xx+Q/cdd    c                 ~    |j                         st        d      t        j                  d|      rt        d      |S )NzPassword cannot be emptyz[;<>&\']z$Password contains invalid characters)stripr;   r9   searchr<   s     r?   validate_passwordzUserCreate.validate_passwordJ   s8     wwy78899[!$CDDrA   N)__name__
__module____qualname__r   r5   str__annotations__r*   r   r@   rE    rA   r?   r0   r0   @   sV    #!;Hc;#!,Hc,z 
 z rA   r0   c                       e Zd ZU eed<   eed<   eed<   eeef   ed<    ed      d        Z	 ed      d        Z
 ed      d        Z ed      d        Zy	)
SaveDatauserId	timestampversionstatec                 &    |dk  rt        d      |S )Nr   zUser ID must be positive)r;   r<   s     r?   validate_user_idzSaveData.validate_user_idY   s    6788rA   c                     t        t        j                         j                         dz        }||dz   kD  rt	        d      |S )N  i z!Timestamp cannot be in the future)intr   utcnowrO   r;   )r=   r>   current_times      r?   validate_timestampzSaveData.validate_timestamp_   s?    8??,6684?@|f$$@AArA   c                 H    t        j                  d|      st        d      |S )Nz^\d+\.\d+\.\d+$z/Invalid version format. Must be in format X.Y.Zr8   r<   s     r?   validate_versionzSaveData.validate_versionf   s"    xx*A.NOOrA   c                     	 t         j                  d|i       |S # t        $ r}t        dt	        |             d }~ww xY w)NrQ   zInvalid game state: )game_validatorvalidate_save_data	Exceptionr;   rI   )r=   r>   es      r?   validate_game_statezSaveData.validate_game_statel   sE    	>--wl;H 	>3CF8<==	>s    	A ;A N)rF   rG   rH   rV   rJ   rI   r   r	   r   rS   rY   r[   ra   rK   rA   r?   rM   rM   S   s    KNLS>x 
 {  y 
 w> >rA   rM   c                      	 t        j                  j                  di t        } | S # t        $ r)}t        dt        |              t        dd      d }~ww xY w)NzDatabase connection error:   zDatabase connection failedstatus_codedetailrK   )mysql	connectorconnect	DB_CONFIGr_   printrI   r   )connr`   s     r?   get_dbrm   u   sX    R&&33 R+CF8454PQQRs   $' 	A$AAc                    K   	 t        j                  | t        t        g      }|j	                  d      }|t        dd      |S # t         j                  $ r}t        dd      d }~ww xY ww)N)
algorithmssub  zInvalid authentication tokenrd   )jwtdecode
SECRET_KEY	ALGORITHMgetr   JWTError)r   payloaduser_idr`   s       r?   get_current_userrz   }   si     T**UJI;G{{5)?C8VWW<< T4RSSTs)   A/AA A/A,A''A,,A/datac                     | j                         }t        j                         t        t              z   }|j                  d|i       t        j                  |t        t              S )N)minutesexp)	algorithm)
copyr   rW   r   ACCESS_TOKEN_EXPIRE_MINUTESupdaterr   encodert   ru   )r{   	to_encodeexpires      r?   create_access_tokenr      sI    		I__3N!OOFeV_%::iyAArA   z/api/auth/registerr)   c                 H  K   t               }|j                  d      }	 t        d | j                  D              rt	        dd      |j                  d| j                  f       |j                         rt	        dd      t        j                         }t        j                  | j                  j                  d	      |      }|j                  d
| j                  |f       |j                          |j                  }t        dt        |      i      }|| j                  |d|j!                          |j!                          S # t"        $ r+}|j%                          t	        dt        |            d }~ww xY w# |j!                          |j!                          w xY ww)NT
dictionaryc              3   <   K   | ]  }|j                           y w)N)isspace).0chars     r?   	<genexpr>zregister.<locals>.<genexpr>   s     8-$t||~-s   i  z"Username cannot contain whitespacerd   z(SELECT id FROM users WHERE username = %szUsername already registeredutf-8z;INSERT INTO users (username, password_hash) VALUES (%s, %s)rp   rN   r5   r   rc   )rm   cursoranyr5   r   executefetchonebcryptgensalthashpwr*   r   commit	lastrowidr   rI   closer_   rollback)r)   rl   r   salthashed_passwordry   access_tokenr`   s           r?   registerr      sG    8D[[D[)F 8$--88C8\]]ADMMCST??C8UVV~~ --(<(<W(EtLI]]O,	
 	""*E3w<+@A !
 	

  <CF;;< 	

s5   F"DE %!F"	E:&E55E::E= ="FF"z/api/auth/loginc                 ,  K   t               }|j                  d      }	 |j                  d| j                  f       |j	                         }|st        dd      t        j                  | j                  j                  d      |d   j                  d            st        dd      t        d	t        |d
         i      }|d
   |d   |d|j                          |j                          S # |j                          |j                          w xY ww)NTr   zASELECT id, username, password_hash FROM users WHERE username = %srq   zInvalid username or passwordrd   r   password_hashrp   idr5   r   )rm   r   r   r5   r   r   r   checkpwr*   r   r   rI   r   )r)   rl   r   db_userr   s        r?   loginr      s     8D[[D[)FO]]	
 //#C8VWW~~dmm227;W_=U=\=\]d=efC8VWW*E3wt}3E+FG dm
+!
 	

 	

s   DB.C/ !D/"DDz/api/auth/verifycurrent_userc                 B  K   t               }|j                  d      }	 |j                  d| f       |j                         }|st	        dd      | |d   d|j                          |j                          S # |j                          |j                          w xY ww)	NTr   z(SELECT username FROM users WHERE id = %srq   zUser not foundrd   r5   )rN   r5   )rm   r   r   r   r   r   )r   rl   r   r)   s       r?   verify_tokenr      s     8D[[D[)FAL?S C8HII #Z(
 	

 	

s   B9A: !B:"BBz	/api/save	save_datac                   K   t        | j                        |k7  rt        dd      t               }|j	                         }	 t        j                  | j                        }|j                  d|f       |j                         }|r+|j                  d| j                  | j                  ||f       n*|j                  d|| j                  | j                  |f       |j                          ddd	|j                          |j                          S # t        $ r+}|j                          t        d
t        |            d }~ww xY w# |j                          |j                          w xY ww)N  z$Not authorized to save for this userrd   zA
            SELECT id FROM save_data WHERE user_id = %s
        z
                UPDATE save_data 
                SET save_timestamp = %s, version = %s, state_json = %s
                WHERE user_id = %s
            z
                INSERT INTO save_data (user_id, save_timestamp, version, state_json)
                VALUES (%s, %s, %s, %s)
            successzSave successful)statusmessagerc   )rI   rN   r   rm   r   jsondumpsrQ   r   r   rO   rP   r   r   r_   r   )r   r   rl   r   
state_jsonexisting_saver`   s          r?   	save_gamer      s9    
9,4Z[[8D[[]FZZ	0
 _	 )NN  %%y'8'8*lS	U NN  	 3 3Y5F5F
SU
 	#0AB 	

  <CF;;< 	

s7   A E-B-D 0!E-	E&E  EE "E**E-z/api/save/{user_id}ry   c                   K   | |k7  rt        dd      t               }|j                  d      }	 |j                  d| f       |j	                         }|sRt        t        j                         j                         dz        dd d	|j                          |j                          S |d
   |d   t        j                  |d         d	|j                          |j                          S # t        $ r2}t        dt        |              t        dt        |            d }~ww xY w# |j                          |j                          w xY ww)Nr   z"Not authorized to access this saverd   Tr   z
            SELECT save_timestamp as timestamp, version, state_json 
            FROM save_data 
            WHERE user_id = %s
        rU   z1.0.0)rO   rP   rQ   rO   rP   r   zLoad error: rc   )r   rm   r   r   r   rV   r   rW   rO   r   r   loadsr_   rk   rI   )ry   r   rl   r   saver`   s         r?   get_saver     s"    ,4XYY8D[[D[)F  Z		   !2!<!<!>!EF"  	

 k*IZZ\ 23
 	

  <SVH%&CF;;< 	

sA   /EAC+ !E)!C+ 
!E+	D&4-D!!D&&D) )"EE__main__z0.0.0.0i@  )r(   port)9fastapir   r   r   fastapi.middleware.corsr   fastapi.securityr   typingr   r	   r
   pydanticr   r   r   rr   r   mysql.connectorrg   r   r   r9   r   osdotenvr   game_settings_validatorr   appr]   getenvr   CORS_ORIGINSadd_middlewarert   ru   r   oauth2_schemerj   r0   rM   rm   rI   rz   dictr   postr   r   rv   r   r   r   rF   uvicornrunrK   rA   r?   <module>r      sy   3 3 2 1 & & 0 0 
   ( 	  	  6  i#%bii}5 	 
 	!	   {+%%   RYY')?@
	" $g6 BIIi-BIIi,		-)BC		)^4%	 &>y >DR )0(> T# TBd B 
$ $  $L 
j  : 	+23C+D S  ( +=DEU=V $x $s $ $L 	5<=M5N !C !s !  !F zGKK)$/ rA   