
    +j/J                         d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZ d dlmZ d dlZddlmZ d dlmZ dZ G d	 d
e          ZdededefdZ G d d          ZdS )    N)web)parse)args   )AppSettings)	TypedDictdefaultc                   8    e Zd ZU eed<   eed<   eed<   eed<   dS )FileInfopathsizemodifiedcreatedN)__name__
__module____qualname__str__annotations__int     0/home/wildlama/comfy/ComfyUI/app/user_manager.pyr   r      s4         
III
IIIMMMLLLLLr   r   r   relative_toreturnc                 v   t           j                            | |                              t           j        d          t           j                            |           t          t           j                            |           dz            t          t           j                            |           dz            dS )N/i  )r   r   r   r   )	osr   relpathreplacesepgetsizer   getmtimegetctime)r   r   s     r   get_file_infor$      s    k22::263GG%%((..566rw''--455	  r   c                   4    e Zd Zd Zd Zd Zd
dZd Zd Zd	S )UserManagerc                 n   t          j                    }t          |           | _        t          j                            |          sJt	          j        |d           t          j	        s(t          j        d           t          j        d           t          j	        rt          j                            |                                           rUt          |                                           5 }t          j        |          | _        d d d            d S # 1 swxY w Y   d S i | _        d S ddi| _        d S )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__zUserManager.__init__$   sc   %8::#D))w~~n-- 	KK6666? K  !G  H  H  H  !J  K  K  K? 	0w~~d113344  $--//00 .A!%1DJ. . . . . . . . . . . . . . . . . .  


#Y/DJJJs   /DDDc                 d    t           j                            t          j                    d          S )Nz
users.json)r   r   joinr*   r+   )r8   s    r   r3   zUserManager.get_users_file7   s!    w||L;==|LLLr   c                     d}t           j        rGd|j        v r>|j        d         }|                    t          j                  rt          d|z             || j        vrt          d|z             |S )Nr	   z
comfy-userzUnknown user: )r   r/   headers
startswithr*   SYSTEM_USER_PREFIXKeyErrorr7   )r8   requestusers      r   get_request_user_idzUserManager.get_request_user_id:   sz    ? 	8|w>>?<0D|>?? 8/$6777tz!!+d2333r   userdataTc                    |dk    rt          j                    }nt          d|z             |                     |          }t          j        |          }|d S |}t
          j                            ||f          |k    rd S ||d|v rt          j	        |          }t
          j        
                    t
          j                            ||                    }t
          j                            ||f          |k    rd S t
          j                            |          d         }	|r5t
          j                            |	          st          j        |	d           |S )NrF   zUnknown filepath type:%r   Tr(   )r*   r+   rB   rE   get_public_user_directoryr   r   
commonpathr   unquoteabspathr=   splitr-   r.   )
r8   rC   filetype
create_dirroot_dirrD   	user_rootr   parents
             r   get_request_user_filepathz%UserManager.get_request_user_filepathG   sB   :#688HH3d:;;;''00 :4@@	4 7x344@@4d{{}T** 7??27<<	4#@#@AADw!!9d"344	AAtt$$Q' 	/bgnnV44 	/K....r   c                 <   |                                 }|st          d          |                    t          j                  rt          d          t          j        dd|          }|                    t          j                  rt          d          |dz   t          t          j	                              z   }|| j
        |<   t          |                                 d          5 }t          j        | j
        |           d d d            n# 1 swxY w Y   |S )Nzusername not providedzSystem User prefix not allowedz[^a-zA-Z0-9-_]+-_w)strip
ValueErrorr@   r*   rA   resubr   uuiduuid4r7   r4   r3   r5   dump)r8   nameuser_idr:   s       r   add_userzUserManager.add_userh   s9   zz|| 	64555??<:;; 	?=>>>&*C66l=>> 	?=>>>C-#djll"3"33"
7$%%''-- 	%Idj!$$$	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% s   *DDDc                 N   
  j                             |           |                    d           fd            }|                    d           fd            }|                    d           fd            }|                    d           fd            }d fd
	
|                    d          
fd            }|                    d          
 fd            }|                    d          
fd            }|                    d          
 fd            }	d S )Nz/usersc                    K   t           j        rt          j        dj        d          S                     | d d          }t          j        dt          j                            |          d          S )Nserver)storager7   FrP   )rf   migrated)	r   r/   r   json_responser7   rT   r   r   r-   )rC   user_dirr8   s     r   	get_usersz)UserManager.add_routes.<locals>.get_users}   sz       (X
)S)STTT99'4TY9ZZ(' "x 8 8* *   r   c                   K   |                                   d {V }|d         }|j                                        v rt          j        ddid          S 	                     |          }n<# t          $ r/}t          j        dt          |          id          cY d }~S d }~ww xY wt          j        |          S )NusernameerrorzDuplicate username.  status)r5   r7   valuesr   ri   rb   rZ   r   )rC   bodyrm   ra   er8   s        r   
post_usersz*UserManager.add_routes.<locals>.post_users   s       ''''''DJ'H4:,,....('3H)IRUVVVVH--11 H H H('3q66):3GGGGGGGGGH$W---s   A0 0
B):$B$B)$B)z	/userdatac                 (  K   | j         j                            dd          }|st          j        dd          S 	                    | |          st          j        dd          S t          j                                      st          j        dd	          S | j         j                            d
d          	                                dk    }| j         j                            dd          	                                dk    | j         j                            dd          	                                dk    |r4t          j        
                    t          j                  dd          }n2t          j        
                    t          j                  d          }dt          dt          t          z  t          t                   z  ffdfdt          j        ||          D             }t          j        |          S )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 ro   zDirectory not providedrq   text  zInvalid directory  zDirectory not foundrecursetrue	full_inforM   z***	full_pathr   c                     rt          |           S t          j                            |                               t          j        d          }r|g|                    d          z   S |S )Nr   )r$   r   r   r   r   r    rM   )r   rel_pathr   r   
split_paths     r   process_full_pathzGUserManager.add_routes.<locals>.listuserdata.<locals>.process_full_path   sh     :(D9997??9d;;CCBFCPP <$:s(;(;;;r   c                 d    g | ],}t           j                            |          ! |          -S r   )r   r   r2   ).0r   r   s     r   
<listcomp>z@UserManager.add_routes.<locals>.listuserdata.<locals>.<listcomp>   sH       7>>),,!!),,  r   )	recursive)rel_urlquerygetr   ResponserT   r   r   r-   lowerr=   globescaper   r   listri   )
rC   	directoryr}   patternresultsr   r   r   r   r8   s
        @@@@r   listuserdataz,UserManager.add_routes.<locals>.listuserdata   s     2  -11%<<I O|35MNNNN11'9EED J|35HIIII7>>$'' L|35JKKKKo+//	2>>DDFF&PG-11+rBBHHJJfTI .227B??EEGG6QJ  ?',,t{4'8'8$DD',,t{4'8'8#>> S  X^d3i5O                   !%7g!F!F!F  G $W---r   z/v2/userdatac           	        K   | j         j                            dd          }	 t          j        |          }nG# t
          $ r:}t          j        d| d|            t          j	        dd          cY d}~S d}~ww xY w	 
                    | dd	
          }|r
                    | |d	
          }n|}nD# t          $ r7}t          j        d|            t          j	        dd          cY d}~S d}~ww xY w|st          j	        dd          S t          j                            |          s0||k    rt          j        g           S t          j	        dd          S t          j                            |          st          j	        dd          S g }	 t          j        |d          D ]\\  }}}|D ]y}	t          j                            ||	          }
t          j                            |
|                              t          j        d          }|                    |	|dd           z|D ]}t          j                            ||          }t          j                            ||                              t          j        d          }||dd}	 t          j        |          }|j        |d<   |j        |d<   n1# t4          $ r$}t          j        d| d|            Y d}~nd}~ww xY w|                    |           א^nG# t4          $ r:}t          j        d| d|            t          j	        dd          cY d}~S d}~ww xY w|                    d             t          j        |          S )!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   rx   z!Failed to decode path parameter: z	, Error: ro   z$Invalid characters in path parameterry   NFrg   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   )r`   r   rO   rN   r   r   zCould not stat file z: zError listing directory i  z Error reading directory contentsc                 N    | d         dk    | d                                          fS )NrO   r   r`   )r   )xs    r   <lambda>zBUserManager.add_routes.<locals>.list_userdata_v2.<locals>.<lambda>;  s"    &	[(@!F)//BSBS'T r   )key)r   r   r   r   rK   	Exceptionr0   r1   r   r   rT   rB   r   r   r-   ri   isdirwalkr=   r   r   r    appendstatst_sizest_mtimeOSErrorrn   sort)rC   requested_rel_pathrt   base_user_pathtarget_abs_pathr   rootdirsfilesdir_namedir_pathr   	file_name	file_path
entry_infostats
stat_errorr8   s                    r   list_userdata_v2z0UserManager.add_routes.<locals>.list_userdata_v2   s5     2 ")!6!:!:62!F!F]%*]3E%F%F"" ] ] ] dDV d dab d deee|35[\\\\\\\\\]["&"@"@$[`"@"a"a& 6'+'E'EgOans'E't't__'5_ [ [ [!?A!?!?@@@C6YZZZZZZZZZ[ # PC6NOOOO 7>>/22 V"n44-b111  L:TUUUU7==11 [C6YZZZZGY)+$)O)O)O 3 3%D$$(  #%7<<h#?#?#%7??8^#L#L#T#TUWU[]`#a#a$,$,$/( (     &+ 3 3	$&GLLy$A$A	#%7??9n#M#M#U#UVXV\^a#b#b$-$,$*& &

!$&GI$6$6E16Jv.5:^Jz22& ! ! !#O,\9,\,\PZ,\,\]]] DDDD!  z2222338  Y Y YOOOAOOPPP|35WXXXXXXXXXY
 LLTTLUUU$W---s   : 
A>/A93A>9A>5B8 8
C9,C4.C94C9DL (KL 
K4K/*L /K44L 
M/M	MMFrN   c                 2   | j                             |d           }|st          j        d          S                     | |          }|st          j        d          S |r4t
          j                            |          st          j        d          S |S )Nro   rp   r{   r|   )
match_infor   r   r   rT   r   r   r-   )rC   check_existsparamrN   r   r8   s        r   get_user_data_pathz2UserManager.add_routes.<locals>.get_user_data_path?  s    %))%66D 0|3////11'4@@D 0|3//// 0BGNN4$8$8 0|3////Kr   z/userdata/{file}c                 x   K    | d          }t          |t                    s|S t          j        |          S )NTr   )
isinstancer   r   FileResponserC   r   r   s     r   getuserdataz+UserManager.add_routes.<locals>.getuserdataM  sD      %%gDAAADdC(( #D)))r   c                 .  K    |           }t          |t                    s|S | j                            dd          dk    }| j                            dd                                          dk    }|s5t
          j                            |          rt          j	        dd          S 	 | 
                                 d{V }t
          j                            |          }t          j        |	          \  }}	 t          j        |d
          5 }|                    |           ddd           n# 1 swxY w Y   t          j        ||           n#  t          j        |            xY wnG# t$          $ r:}	t'          j        d| d|	            t          j	        dd          cY d}	~	S d}	~	ww xY w                    | d          }
|rt-          ||
          }n t
          j                            ||
          }t          j        |          S )aC  
            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 existsry   N)rw   wbzError saving file 'z': ro   z@Invalid filename. Please avoid special characters like :\/*?"<>|)rq   reason)r   r   r   r   r   r   r   r-   r   r   readdirnametempfilemkstempfdopenwriter   unlinkr   r0   r1   rT   r$   r   ri   )rC   r   r   r   rs   r   fdtmp_pathr:   rt   	user_pathrespr   r8   s               r   post_userdataz-UserManager.add_routes.<locals>.post_userdataU  su     4 &%g..DdC(( ))+v>>'II))+w??EEGG6QI L!5!5 L|35JKKKK$\\^^++++++7??400'/H===H2t,, && & & & & & & & & & & & & & &Jx....Ih''' /     Bd B Bq B BCCC|_         66wEEI 8$T955wtY77$T***s[   .AE3  E D7+E 7D;;E >D;?E E3 E//E3 3
F7=/F2,F72F7c                    K    | d          }t          |t                    s|S t          j        |           t	          j        d          S )NTr      rp   )r   r   r   remover   r   r   s     r   delete_userdataz/UserManager.add_routes.<locals>.delete_userdata  sS      %%gDAAADdC(( IdOOO<s++++r   z/userdata/{file}/move/{dest}c                   K    | d          }t          |t                    s|S  | dd          }t          |t                    s|S | j                            dd          dk    }| j                            d	d                                          dk    }|s5t
          j                            |          rt          j	        d
d          S t          j        d| d| d           t          j        ||                               | d          }|rt          ||          }n t
          j                            ||          }t          j        |          S )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   ry   zmoving 'z' -> ''N)r   r   r   r   r   r   r   r-   r   r   r0   infoshutilmoverT   r$   r   ri   )	rC   sourcer   r   r   r   r   r   r8   s	          r   move_userdataz-UserManager.add_routes.<locals>.move_userdata  sf     4 ('dCCCFfc** %%gEPPPDdC(( ))+v>>'II))+w??EEGG6QI L!5!5 L|35JKKKKL9F99$999:::K%%%66wEEI 8$T955wtY77$T***r   )FrN   )r,   
add_routesr   postdelete)r8   routesrk   ru   r   r   r   r   r   r   r   s   `         @r   r   zUserManager.add_routesz   s     (((	H			 	 	 	 
		 
X		
	. 
	. 
	. 
	. 
	
	. 
K	 	 =	. =	. =	. =	. 
!	 =	.~ 
N	#	#g	. g	. g	. g	. 
$	#g	.R	 	 	 	 	 	 
&	'	'	* 	* 	* 	* 
(	'	* 
'	(	(<	+ <	+ <	+ <	+ <	+ 
)	(<	+| 
)	*	*	, 	, 	, 	, 
+	*	, 
3	4	40	+ 0	+ 0	+ 0	+ 0	+ 
5	40	+ 0	+ 0	+r   N)rF   T)	r   r   r   r;   r3   rE   rT   rb   r   r   r   r   r&   r&   #   s|        0 0 0&M M M     B  $U+ U+ U+ U+ U+r   r&   )r5   r   r[   r]   r   r   r0   r   aiohttpr   urllibr   comfy.cli_argsr   r*   app_settingsr   typingr   default_userr   r   r$   r&   r   r   r   <module>r      sG    				 				                            % % % % % %          y    # (    l+ l+ l+ l+ l+ l+ l+ l+ l+ l+r   