o
    i	L                     @  s   d dl m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	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 deZdddZG dd dZdS )    )annotationsN)web)parse)args   )AppSettings)	TypedDictdefaultc                   @  s.   e Zd ZU ded< ded< ded< ded< dS )FileInfostrpathintsizemodifiedcreatedN)__name__
__module____qualname____annotations__ r   r   ./mnt/c/Users/fbmor/ComfyUI/app/user_manager.pyr
      s
   
 r
   r   r   relative_toreturnc                 C  s:   t j| |t jdt j| t j| t j| dS )N/)r   r   r   r   )osr   relpathreplacesepgetsizegetmtimegetctime)r   r   r   r   r   get_file_info   s
   


r!   c                   @  s>   e Zd Zdd Zdd Zdd Zdd	d
Zdd Zdd ZdS )UserManagerc                 C  s   t  }t| | _tj|s#tj|dd tj	s#t
d t
d tj	rRtj|  rMt|  }t|| _W d    d S 1 sFw   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fr   r   r   __init__%   s   


"
zUserManager.__init__c                 C  s   t jt dS )Nz
users.json)r   r   joinr%   r&   r3   r   r   r   r.   8   s   zUserManager.get_users_filec                 C  sP   d}t jrd|jv r|jd }|tjrtd| || jvr&td| |S )Nr	   z
comfy-userzUnknown user: )r   r*   headers
startswithr%   SYSTEM_USER_PREFIXKeyErrorr2   )r3   requestuserr   r   r   get_request_user_id;   s   

zUserManager.get_request_user_iduserdataTc           
      C  s   |dkr	t  }ntd| | |}t |}|d u rd S |}tj||f|kr-d S |d urQd|v r:t	|}tj
tj||}tj||f|krQd S tj|d }	|rhtj|	shtj|	dd |S )Nr@   zUnknown filepath type:%r   Tr#   )r%   r&   r<   r?   get_public_user_directoryr   r   
commonpathr   unquoteabspathr7   splitr(   r)   )
r3   r=   filetype
create_dirroot_dirr>   	user_rootr   parentr   r   r   get_request_user_filepathH   s(   



z%UserManager.get_request_user_filepathc                 C  s   |  }|s
td|tjrtdtdd|}|tjr%td|d tt	  }|| j
|< t|  d}t| j
| W d    |S 1 sNw   Y  |S )Nzusername not providedzSystem User prefix not allowedz[^a-zA-Z0-9-_]+-_w)strip
ValueErrorr:   r%   r;   resubr   uuiduuid4r2   r/   r.   r0   dump)r3   nameuser_idr5   r   r   r   add_useri   s    

zUserManager.add_userc           
        s   j | |dfdd}|dfdd}|dfdd}|d	fd
d}dfdd	 |d fdd}|d fdd}|d fdd}|d fdd}	d S )Nz/usersc                   sB   t jrtd jdS  j| d dd}tdtj|dS )Nserver)storager2   FrI   )r\   migrated)	r   r*   r   json_responser2   rM   r   r   r(   )r=   user_dirr8   r   r   	get_users~   s   
z)UserManager.add_routes.<locals>.get_usersc              
     s   |   I d H }|d }| j v rtjddiddS z |}W n ty@ } ztjdt|iddW  Y d }~S d }~ww t|S )NusernameerrorzDuplicate username.  status)r0   r2   valuesr   r_   rZ   rR   r   )r=   bodyrb   rY   er8   r   r   
post_users   s   "
z*UserManager.add_routes.<locals>.post_usersz	/userdatac                   s  | j jdd}|stjdddS | |s!tjdddS tjs.tjdd	dS | j jd
d	 dk}| j jdd	 dk | j jdd	 dk|r`tj
tdd}n
tj
td}d fddfddtj||dD }t|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 rd   zDirectory not providedrf   text  zInvalid directory  zDirectory not foundrecursetrue	full_inforF   z***	full_pathr   r   FileInfo | str | list[str]c                   s>    rt | S tj| tjd}r|g|d S |S )Nr   )r!   r   r   r   r   r   rF   )ru   rel_path)rs   r   
split_pathr   r   process_full_path   s   
zGUserManager.add_routes.<locals>.listuserdata.<locals>.process_full_pathc                   s    g | ]}t j|r |qS r   )r   r   r-   ).0ru   )ry   r   r   
<listcomp>   s    
z@UserManager.add_routes.<locals>.listuserdata.<locals>.<listcomp>)	recursiveN)ru   r   r   rv   )rel_urlquerygetr   ResponserM   r   r   r(   lowerr7   globescaper_   )r=   	directoryrq   patternresultsr8   )rs   r   ry   rx   r   listuserdata   s(   


z,UserManager.add_routes.<locals>.listuserdataz/v2/userdatac                   s  | j jdd}zt|}W n$ ty4 } ztd| d|  tj	dddW  Y d}~S d}~ww z j
| dd	d
}|rI j
| |d	d
}n|}W n! tym } ztd|  tj	dddW  Y d}~S d}~ww |swtj	dddS tj|s||krtg S tj	dddS tj|stj	dddS g }ztj|ddD ]y\}}}|D ]}	tj||	}
tj|
|tjd}||	|dd q|D ]P}tj||}tj||tjd}||dd}zt|}|j|d< |j|d< W n ty } ztd| d|  W Y d}~nd}~ww || qqW n% tyD } ztd| d|  tj	dddW  Y d}~S d}~ww |jdd  d! t|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   rl   z!Failed to decode path parameter: z	, Error: rd   z$Invalid characters in path parameterrm   NFr]   zAccess denied for user: ro   z!Invalid user specified in requestzInvalid path requestedrp   zRequested path not foundz!Requested path is not a directoryT)topdownr   r   )rX   r   rH   rG   r   r   zCould not stat file z: zError listing directory i  z Error reading directory contentsc                 S  s   | d dk| d   fS )NrH   r   rX   )r   )xr   r   r   <lambda><  s    zBUserManager.add_routes.<locals>.list_userdata_v2.<locals>.<lambda>)key)r}   r~   r   r   rD   	Exceptionr+   r,   r   r   rM   r<   r   r   r(   r_   isdirwalkr7   r   r   r   appendstatst_sizest_mtimeOSErrorrc   sort)r=   requested_rel_pathri   base_user_pathtarget_abs_pathr   rootdirsfilesdir_namedir_pathrw   	file_name	file_path
entry_infostats
stat_errorr8   r   r   list_userdata_v2   s   




z0UserManager.add_routes.<locals>.list_userdata_v2FrG   c                   sZ   | j |d }|stjddS  | |}|stjddS |r+tj|s+tjddS |S )Nrd   re   ro   rp   )
match_infor   r   r   rM   r   r   r(   )r=   check_existsparamrG   r   r8   r   r   get_user_data_path@  s   z2UserManager.add_routes.<locals>.get_user_data_pathz/userdata/{file}c                   s&    | dd}t |ts|S t|S )NTr   )
isinstancer   r   FileResponser=   r   r   r   r   getuserdataN  s
   

z+UserManager.add_routes.<locals>.getuserdatac              
     sd   | }t |ts|S | jdddk}| jdd dk}|s/tj|r/tj	dddS zD| 
 I dH }tj|}tj|d	\}}z#t|d
}|| W d   n1 s\w   Y  t|| W n	   t|  W n$ ty }	 ztd| d|	  tj	dddW  Y d}	~	S d}	~	ww | d}
|rt||
}ntj||
}t|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.
            	overwriterr   falsers     File already existsrm   N)rk   wbzError saving file 'z': rd   z@Invalid filename. Please avoid special characters like :\/*?"<>|)rf   reason)r   r   r~   r   r   r   r   r(   r   r   readdirnametempfilemkstempfdopenwriter   unlinkr   r+   r,   rM   r!   r   r_   )r=   r   r   rs   rh   r   fdtmp_pathr5   ri   	user_pathrespr   r3   r   r   post_userdataV  sD   


z-UserManager.add_routes.<locals>.post_userdatac                   s2    | dd}t |ts|S t| tjddS )NTr      re   )r   r   r   remover   r   r   r   r   r   delete_userdata  s   

z/UserManager.add_routes.<locals>.delete_userdataz/userdata/{file}/move/{dest}c                   s    | dd}t |ts|S  | ddd}t |ts|S | jdddk}| jd	d dk}|s?tj|r?tj	d
ddS t
d| d| d t|| | d}|r_t||}ntj||}t|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   rr   r   rs   r   r   rm   zmoving 'z' -> ''N)r   r   r~   r   r   r   r   r(   r   r   r+   infoshutilmoverM   r!   r   r_   )r=   sourcer   r   rs   r   r   r   r   r   move_userdata  s$   


z-UserManager.add_routes.<locals>.move_userdata)FrG   )r'   
add_routesr   postdelete)
r3   routesra   rj   r   r   r   r   r   r   r   r   r   r   {   s$   
?i>	zUserManager.add_routesN)r@   T)	r   r   r   r6   r.   r?   rM   rZ   r   r   r   r   r   r"   $   s    
!r"   )r   r   r   r   r   r
   )
__future__r   r0   r   rS   rU   r   r   r+   r   aiohttpr   urllibr   comfy.cli_argsr   r%   app_settingsr   typingr   default_userr
   r!   r"   r   r   r   r   <module>   s&    
	