
    +j/J                         S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SKJ	r	  S SK
Jr  S SKJr  S SKrSSKJr  S SKJr  Sr " S	 S
\5      rS\S\S\4S jr " S S5      rg)    N)web)parse)args   )AppSettings)	TypedDictdefaultc                   >    \ rS rSr% \\S'   \\S'   \\S'   \\S'   Srg)FileInfo   pathsizemodifiedcreated N)__name__
__module____qualname____firstlineno__str__annotations__int__static_attributes__r       0/home/wildlama/comfy/ComfyUI/app/user_manager.pyr   r      s    
I
IMLr   r   r   relative_toreturnc                 d   [         R                  R                  X5      R                  [         R                  S5      [         R                  R                  U 5      [        [         R                  R                  U 5      S-  5      [        [         R                  R                  U 5      S-  5      S.$ )N/i  )r   r   r   r   )	osr   relpathreplacesepgetsizer   getmtimegetctime)r   r   s     r   get_file_infor'      su    2::2663G%((.56rww''-45	 r   c                   <    \ rS rSrS rS rS rS
S jrS rS r	Sr
g	)UserManager#   c                    [         R                  " 5       n[        U 5      U l        [        R
                  R                  U5      (       dV  [        R                  " USS9  [        R                  (       d,  [        R                  " S5        [        R                  " S5        [        R                  (       ax  [        R
                  R                  U R                  5       5      (       a>  [        U R                  5       5       n[        R                   " U5      U l        S S S 5        g 0 U l        g SS0U l        g ! , (       d  f       g = f)NTexist_okzd****** User settings have been changed to be stored on the server instead of browser storage. ******zg****** For multi-user setups add the --multi-user CLI argument to enable multiple user profiles. ******r	   )folder_pathsget_user_directoryr   settingsr    r   existsmakedirsr   
multi_userloggingwarningisfileget_users_fileopenjsonloadusers)selfuser_directoryfs      r   __init__UserManager.__init__$   s    %88:#D)ww~~n--KK6??  !G  H  !J  K??ww~~d11344$--/0A!%1DJ 10  
#Y/DJ 10s    D77
Ec                 h    [         R                  R                  [        R                  " 5       S5      $ )Nz
users.json)r    r   joinr.   r/   )r<   s    r   r7   UserManager.get_users_file7   s     ww||L;;=|LLr   c                    Sn[         R                  (       aQ  SUR                  ;   aA  UR                  S   nUR                  [        R
                  5      (       a  [        SU-   5      eX R                  ;  a  [        SU-   5      eU$ )Nr	   z
comfy-userzUnknown user: )r   r3   headers
startswithr.   SYSTEM_USER_PREFIXKeyErrorr;   )r<   requestusers      r   get_request_user_idUserManager.get_request_user_id:   sm    ??|w>??<0D|>>??/$677zz!+d233r   c                    US:X  a  [         R                  " 5       nO[        SU-   5      eU R                  U5      n[         R                  " U5      nUc  g Un[
        R                  R                  XW45      U:w  a  g Ub}  SU;   a  [        R                  " U5      n[
        R                  R                  [
        R                  R                  Xr5      5      n[
        R                  R                  Xx45      U:w  a  g [
        R                  R                  U5      S   n	U(       a9  [
        R                  R                  U	5      (       d  [
        R                  " U	SS9  U$ )NuserdatazUnknown filepath type:%r   Tr,   )r.   r/   rH   rK   get_public_user_directoryr    r   
commonpathr   unquoteabspathrB   splitr1   r2   )
r<   rI   filetype
create_dirroot_dirrJ   	user_rootr   parents
             r   get_request_user_filepath%UserManager.get_request_user_filepathG   s   :#668H3d:;;''0 ::4@	 77x34@d{}}T* 77??277<<	#@ADww!!9"34	At$Q'bggnnV44KK.r   c                 F   UR                  5       nU(       d  [        S5      eUR                  [        R                  5      (       a  [        S5      e[
        R                  " SSU5      nUR                  [        R                  5      (       a  [        S5      eUS-   [        [        R                  " 5       5      -   nXR                  U'   [        U R                  5       S5       n[        R                  " U R                  U5        S S S 5        U$ ! , (       d  f       U$ = f)Nzusername not providedzSystem User prefix not allowedz[^a-zA-Z0-9-_]+-_w)strip
ValueErrorrF   r.   rG   resubr   uuiduuid4r;   r8   r7   r9   dump)r<   nameuser_idr>   s       r   add_userUserManager.add_userh   s    zz|455??<::;;=>>&&*C6l==>>=>>C-#djjl"33"

7$%%'-IIdjj!$ .  .- s   %"D
D c                   ^ ^
 T R                   R                  U5        UR                  S5      U 4S j5       nUR                  S5      U 4S j5       nUR                  S5      U 4S j5       nUR                  S5      U 4S j5       nSU 4S jjm
UR                  S	5      U
4S
 j5       nUR                  S	5      U
U 4S j5       nUR	                  S	5      U
4S j5       nUR                  S5      U
U 4S j5       n	g )Nz/usersc                 
  >#    [         R                  (       a#  [        R                  " STR                  S.5      $ TR                  U S SS9n[        R                  " S[        R                  R                  U5      S.5      $ 7f)Nserver)storager;   FrW   )ro   migrated)	r   r3   r   json_responser;   r[   r    r   r1   )rI   user_dirr<   s     r   	get_users)UserManager.add_routes.<locals>.get_users}   sj     ((X

)STT99'4TY9Z((' "x 8*  s   B Bc                 r  >#    U R                  5       I S h  vN nUS   nUTR                  R                  5       ;   a  [        R                  " SS0SS9$  TR                  U5      n[        R                  " U5      $  Nf! [         a*  n[        R                  " S[        U5      0SS9s S nA$ S nAff = f7f)NusernameerrorzDuplicate username.  status)r9   r;   valuesr   rr   rj   rb   r   )rI   bodyrw   ri   er<   s        r   
post_users*UserManager.add_routes.<locals>.post_users   s      'DJ'H4::,,..(('3H)IRUVVH--1 $$W-- (  H(('3q6):3GGHs?   B7A>>B7B  (B7 
B4
B/)B4*B7/B44B7z	/userdatac                   >^^^	#    U R                   R                  R                  SS5      nU(       d  [        R                  " SSS9$ T
R                  X5      mT(       d  [        R                  " SSS9$ [        R                  R                  T5      (       d  [        R                  " SS	S9$ U R                   R                  R                  S
S5      R                  5       S:H  nU R                   R                  R                  SS5      R                  5       S:H  mU R                   R                  R                  SS5      R                  5       S:H  m	U(       a6  [        R                  R                  [        R                  " T5      SS5      nO4[        R                  R                  [        R                  " T5      S5      nS[        S[        [        -  [        [           -  4UUU	4S jjn[        R                  " X2S9 Vs/ s H1  n[        R                  R!                  U5      (       d  M)  U" U5      PM3     nn[        R"                  " U5      $ s  snf 7f)a  
List user data files in a specified directory.

This endpoint allows listing files in a user's data directory, with options for recursion,
full file information, and path splitting.

Query Parameters:
- dir (required): The directory to list files from.
- recurse (optional): If "true", recursively list files in subdirectories.
- full_info (optional): If "true", return detailed file information (path, size, modified time).
- split (optional): If "true", split file paths into components (only applies when full_info is false).

Returns:
- 400: If 'dir' parameter is missing.
- 403: If the requested path is not allowed.
- 404: If the requested directory does not exist.
- 200: JSON response with the list of files or file information.

The response format depends on the query parameters:
- Default: List of relative file paths.
- full_info=true: List of dictionaries with file details.
- split=true (and full_info=false): List of lists, each containing path components.
dir ry   zDirectory not providedr{   text  zInvalid directory  zDirectory not foundrecursetrue	full_inforT   z***	full_pathr   c                    > T(       a  [        U T5      $ [        R                  R                  U T5      R	                  [        R
                  S5      nT(       a  U/UR                  S5      -   $ U$ )Nr   )r'   r    r   r!   r"   r#   rT   )r   rel_pathr   r   
split_paths     r   process_full_pathGUserManager.add_routes.<locals>.listuserdata.<locals>.process_full_path   sV    (D9977??9d;CCBFFCP$:s(;;;r   )	recursive)rel_urlquerygetr   Responser[   r    r   r1   lowerrB   globescaper   r   listr6   rr   )rI   	directoryr   patternr   r   resultsr   r   r   r<   s          @@@r   listuserdata,UserManager.add_routes.<locals>.listuserdata   s    2  --11%<I||35MNN11'ED||35HII77>>$''||35JKKoo++//	2>DDF&PG--11+rBHHJfTI ..227B?EEG6QJ '',,t{{4'8$D'',,t{{4'8#> S  X^d3i5O     "&7!F!FI77>>), -!),!F   $$W--s   H I(I2I>Iz/v2/userdatac           	      ,  >#    U R                   R                  R                  SS5      n [        R                  " U5      n TR                  U SS	S
9nU(       a  TR                  XS	S
9nOUn U(       d  [        R                  " SSS9$ [        R                  R                  U5      (       d0  XC:X  a  [        R                  " / 5      $ [        R                  " SSS9$ [        R                  R!                  U5      (       d  [        R                  " SSS9$ / n [        R"                  " USS9 GH2  u  pgnU Ht  n	[        R                  R%                  Xi5      n
[        R                  R'                  X5      R)                  [        R*                  S5      nUR-                  U	USS.5        Mv     U H  n[        R                  R%                  Xl5      n[        R                  R'                  X5      R)                  [        R*                  S5      nUUSS.n [        R.                  " U5      nUR0                  US'   UR2                  US'   UR-                  U5        M     GM5     UR9                  S S 9  [        R                  " U5      $ ! [
         a;  n[        R                  " SU SU 35        [        R                  " SSS9s SnA$ SnAff = f! [         a8  n[        R                  " SU 35        [        R                  " SSS9s SnA$ SnAff = f! [4         a&  n[        R                  " SU SU 35         SnANSnAff = f! [4         a;  n[        R6                  " SU SU 35        [        R                  " SSS9s SnA$ SnAff = f7f)!a  
List files and directories in a user's data directory.

This endpoint provides a structured listing of contents within a specified
subdirectory of the user's data storage.

Query Parameters:
- path (optional): The relative path within the user's data directory
                   to list. Defaults to the root ('').

Returns:
- 400: If the requested path is invalid, outside the user's data directory, or is not a directory.
- 404: If the requested path does not exist.
- 403: If the user is invalid.
- 500: If there is an error reading the directory contents.
- 200: JSON response containing a list of file and directory objects.
       Each object includes:
       - name: The name of the file or directory.
       - type: 'file' or 'directory'.
       - path: The relative path from the user's data root.
       - size (for files): The size in bytes.
       - modified (for files): The last modified timestamp (Unix epoch).
r   r   z!Failed to decode path parameter: z	, Error: ry   z$Invalid characters in path parameterr   NFrp   zAccess denied for user: r   z!Invalid user specified in requestzInvalid path requestedr   zRequested path not foundz!Requested path is not a directoryT)topdownr   r   )rh   r   rV   rU   r   r   zCould not stat file z: zError listing directory i  z Error reading directory contentsc                 8    U S   S:g  U S   R                  5       4$ )NrV   r   rh   )r   )xs    r   <lambda>BUserManager.add_routes.<locals>.list_userdata_v2.<locals>.<lambda>;  s    &	[(@!F)//BS'Tr   )key)r   r   r   r   rR   	Exceptionr4   r5   r   r   r[   rH   r    r   r1   rr   isdirwalkrB   r!   r"   r#   appendstatst_sizest_mtimeOSErrorrx   sort)rI   requested_rel_pathr~   base_user_pathtarget_abs_pathr   rootdirsfilesdir_namedir_pathr   	file_name	file_path
entry_infostats
stat_errorr<   s                    r   list_userdata_v20UserManager.add_routes.<locals>.list_userdata_v2   s    2 ")!6!6!:!:62!F]%*]]3E%F"["&"@"@$[`"@"a&'+'E'Egns'E't_'5_ #C6NOO 77>>/22"4--b11  LL:TUU77==11C6YZZGY)+$)O%D$(#%77<<#?#%77??8#L#T#TUWU[U[]`#a$,$,$/(  %) &+	$&GGLL$A	#%77??9#M#U#UVXV\V\^a#b$-$,$*&

!$&GGI$6E16Jv.5:^^Jz2  z2 &+ *PB LLTLU$$W--U  ]"CDVCWW`ab`c de||35[\\]  [#;A3!?@C6YZZ[b  ' !#OO.B9+RPZ|,\] !  Y 88IA3OP||35WXXYs   'NJ (K *N+K -B,NC=M 4LM &&N
K0KKNKN
L-LLNLN
M	#M?M M		M 
N0NNNNNc                 L  > U R                   R                  US 5      nU(       d  [        R                  " SS9$ TR	                  X5      nU(       d  [        R                  " SS9$ U(       a8  [
        R                  R                  U5      (       d  [        R                  " SS9$ U$ )Nry   rz   r   r   )
match_infor   r   r   r[   r    r   r1   )rI   check_existsparamrU   r   r<   s        r   get_user_data_path2UserManager.add_routes.<locals>.get_user_data_path?  sx    %%))%6D||3//11'@D||3//BGGNN4$8$8||3//Kr   z/userdata/{file}c                 t   >#    T" U SS9n[        U[        5      (       d  U$ [        R                  " U5      $ 7f)NTr   )
isinstancer   r   FileResponserI   r   r   s     r   getuserdata+UserManager.add_routes.<locals>.getuserdataM  s5     %gDADdC((##D))s   58c                 0  >#    T" U 5      n[        U[        5      (       d  U$ U R                  R                  SS5      S:g  nU R                  R                  SS5      R	                  5       S:H  nU(       d9  [
        R                  R                  U5      (       a  [        R                  " SSS9$  U R                  5       I Sh  vN n[
        R                  R                  U5      n[        R                  " US	9u  pg [
        R                  " US
5       nUR                  U5        SSS5        [
        R                   " Xq5        TR+                  U S5      n
U(       a  [-        X5      nO[
        R                  R/                  X5      n[        R0                  " U5      $  N! , (       d  f       N= f!   [
        R"                  " U5        e = f! [$         a;  n	[&        R(                  " SU SU	 35        [        R                  " SSS9s Sn	A	$ Sn	A	ff = f7f)ak  
Upload or update a user data file.

This endpoint handles file uploads to a user's data directory, with options for
controlling overwrite behavior and response format.

Query Parameters:
- overwrite (optional): If "false", prevents overwriting existing files. Defaults to "true".
- full_info (optional): If "true", returns detailed file information (path, size, modified time).
                      If "false", returns only the relative file path.

Path Parameters:
- file: The target file path (URL encoded if necessary).

Returns:
- 400: If 'file' parameter is missing.
- 403: If the requested path is not allowed.
- 409: If overwrite=false and the file already exists.
- 200: JSON response with either:
      - Full file information (if full_info=true)
      - Relative file path (if full_info=false)

The request body should contain the raw file content to be written.
	overwriter   falser     File already existsr   N)r   wbzError saving file 'z': ry   z@Invalid filename. Please avoid special characters like :\/*?"<>|)r{   reason)r   r   r   r   r   r    r   r1   r   r   readdirnametempfilemkstempfdopenwriter"   unlinkr   r4   r5   r[   r'   r!   rr   )rI   r   r   r   r}   r   fdtmp_pathr>   r~   	user_pathrespr   r<   s               r   post_userdata-UserManager.add_routes.<locals>.post_userdataU  s    4 &g.DdC(())+v>'II))+w?EEG6QI!5!5||35JKK$\\^+77??40'//H=2t, -JJx. 66wEI$T5wwt7$$T**1 ,
 -,IIh' "5dV3qc BC||_ ss   B,H0G F9G >F2 F!'F2 AHG !
F/+F2 2GG 
H0HH	HHHc                    >#    T" U SS9n[        U[        5      (       d  U$ [        R                  " U5        [        R
                  " SS9$ 7f)NTr      rz   )r   r   r    remover   r   r   s     r   delete_userdata/UserManager.add_routes.<locals>.delete_userdata  s>     %gDADdC((IIdO<<s++s   A	Az/userdata/{file}/move/{dest}c                   >#    T" U SS9n[        U[        5      (       d  U$ T" U SSS9n[        U[        5      (       d  U$ U R                  R                  SS5      S:g  nU R                  R                  S	S5      R	                  5       S:H  nU(       d9  [
        R                  R                  U5      (       a  [        R                  " S
SS9$ [        R                  " SU SU S35        [        R                  " X5        TR                  U S5      nU(       a  [        X%5      nO[
        R                  R!                  X%5      n[        R"                  " U5      $ 7f)a  
Move or rename a user data file.

This endpoint handles moving or renaming files within a user's data directory, with options for
controlling overwrite behavior and response format.

Path Parameters:
- file: The source file path (URL encoded if necessary)
- dest: The destination file path (URL encoded if necessary)

Query Parameters:
- overwrite (optional): If "false", prevents overwriting existing files. Defaults to "true".
- full_info (optional): If "true", returns detailed file information (path, size, modified time).
                      If "false", returns only the relative file path.

Returns:
- 400: If either 'file' or 'dest' parameter is missing
- 403: If either requested path is not allowed
- 404: If the source file does not exist
- 409: If overwrite=false and the destination file already exists
- 200: JSON response with either:
      - Full file information (if full_info=true)
      - Relative file path (if full_info=false)
Tr   Fdest)r   r   r   r   r   r   r   r   r   zmoving 'z' -> ''N)r   r   r   r   r   r    r   r1   r   r   r4   infoshutilmover[   r'   r!   rr   )	rI   sourcer   r   r   r   r   r   r<   s	          r   move_userdata-UserManager.add_routes.<locals>.move_userdata  s    4 (dCFfc**%gEPDdC(())+v>'II))+w?EEG6QI!5!5||35JKKLL8F86$q9:KK%66wEI$T5wwt7$$T**s   EE)FrU   )r0   
add_routesr   postdelete)r<   routesrt   r   r   r   r   r   r   r   r   s   `         @r   r   UserManager.add_routesz   s	     (	H		 
	 
X	
	. 

	. 
K	 =	. 
!=	.~ 
N	#g	. 
$g	.R	 
&	'	* 
(	* 
'	(<	+ 
)<	+| 
)	*	, 
+	, 
3	40	+ 
50	+r   )r0   r;   N)rN   T)r   r   r   r   r?   r7   rK   r[   rj   r   r   r   r   r   r)   r)   #   s#    0&MB$U+r   r)   )r9   r    rc   re   r   r   r4   r   aiohttpr   urllibr   comfy.cli_argsr   r.   app_settingsr   typingr   default_userr   r   r'   r)   r   r   r   <module>r      sf     	 	          % y  # ( l+ l+r   