55import glob
66import shutil
77from aiohttp import web
8+ from urllib import parse
89from comfy .cli_args import args
9- from folder_paths import user_directory
10+ import folder_paths
1011from .app_settings import AppSettings
1112
1213default_user = "default"
13- users_file = os .path .join (user_directory , "users.json" )
1414
1515
1616class UserManager ():
1717 def __init__ (self ):
18- global user_directory
18+ user_directory = folder_paths . get_user_directory ()
1919
2020 self .settings = AppSettings (self )
2121 if not os .path .exists (user_directory ):
@@ -25,14 +25,17 @@ def __init__(self):
2525 print ("****** For multi-user setups add the --multi-user CLI argument to enable multiple user profiles. ******" )
2626
2727 if args .multi_user :
28- if os .path .isfile (users_file ):
29- with open (users_file ) as f :
28+ if os .path .isfile (self . get_users_file () ):
29+ with open (self . get_users_file () ) as f :
3030 self .users = json .load (f )
3131 else :
3232 self .users = {}
3333 else :
3434 self .users = {"default" : "default" }
3535
36+ def get_users_file (self ):
37+ return os .path .join (folder_paths .get_user_directory (), "users.json" )
38+
3639 def get_request_user_id (self , request ):
3740 user = "default"
3841 if args .multi_user and "comfy-user" in request .headers :
@@ -44,7 +47,7 @@ def get_request_user_id(self, request):
4447 return user
4548
4649 def get_request_user_filepath (self , request , file , type = "userdata" , create_dir = True ):
47- global user_directory
50+ user_directory = folder_paths . get_user_directory ()
4851
4952 if type == "userdata" :
5053 root_dir = user_directory
@@ -59,6 +62,10 @@ def get_request_user_filepath(self, request, file, type="userdata", create_dir=T
5962 return None
6063
6164 if file is not None :
65+ # Check if filename is url encoded
66+ if "%" in file :
67+ file = parse .unquote (file )
68+
6269 # prevent leaving /{type}/{user}
6370 path = os .path .abspath (os .path .join (user_root , file ))
6471 if os .path .commonpath ((user_root , path )) != user_root :
@@ -80,8 +87,7 @@ def add_user(self, name):
8087
8188 self .users [user_id ] = name
8289
83- global users_file
84- with open (users_file , "w" ) as f :
90+ with open (self .get_users_file (), "w" ) as f :
8591 json .dump (self .users , f )
8692
8793 return user_id
@@ -114,54 +120,75 @@ async def post_users(request):
114120 async def listuserdata (request ):
115121 directory = request .rel_url .query .get ('dir' , '' )
116122 if not directory :
117- return web .Response (status = 400 )
118-
123+ return web .Response (status = 400 , text = "Directory not provided" )
124+
119125 path = self .get_request_user_filepath (request , directory )
120126 if not path :
121- return web .Response (status = 403 )
122-
127+ return web .Response (status = 403 , text = "Invalid directory" )
128+
123129 if not os .path .exists (path ):
124- return web .Response (status = 404 )
125-
130+ return web .Response (status = 404 , text = "Directory not found" )
131+
126132 recurse = request .rel_url .query .get ('recurse' , '' ).lower () == "true"
127- results = glob .glob (os .path .join (
128- glob .escape (path ), '**/*' ), recursive = recurse )
129- results = [os .path .relpath (x , path ) for x in results if os .path .isfile (x )]
130-
133+ full_info = request .rel_url .query .get ('full_info' , '' ).lower () == "true"
134+
135+ # Use different patterns based on whether we're recursing or not
136+ if recurse :
137+ pattern = os .path .join (glob .escape (path ), '**' , '*' )
138+ else :
139+ pattern = os .path .join (glob .escape (path ), '*' )
140+
141+ results = glob .glob (pattern , recursive = recurse )
142+
143+ if full_info :
144+ results = [
145+ {
146+ 'path' : os .path .relpath (x , path ).replace (os .sep , '/' ),
147+ 'size' : os .path .getsize (x ),
148+ 'modified' : os .path .getmtime (x )
149+ } for x in results if os .path .isfile (x )
150+ ]
151+ else :
152+ results = [
153+ os .path .relpath (x , path ).replace (os .sep , '/' )
154+ for x in results
155+ if os .path .isfile (x )
156+ ]
157+
131158 split_path = request .rel_url .query .get ('split' , '' ).lower () == "true"
132- if split_path :
133- results = [[x ] + x .split (os . sep ) for x in results ]
159+ if split_path and not full_info :
160+ results = [[x ] + x .split ('/' ) for x in results ]
134161
135162 return web .json_response (results )
136163
137164 def get_user_data_path (request , check_exists = False , param = "file" ):
138165 file = request .match_info .get (param , None )
139166 if not file :
140167 return web .Response (status = 400 )
141-
168+
142169 path = self .get_request_user_filepath (request , file )
143170 if not path :
144171 return web .Response (status = 403 )
145-
172+
146173 if check_exists and not os .path .exists (path ):
147174 return web .Response (status = 404 )
148-
175+
149176 return path
150177
151178 @routes .get ("/userdata/{file}" )
152179 async def getuserdata (request ):
153180 path = get_user_data_path (request , check_exists = True )
154181 if not isinstance (path , str ):
155182 return path
156-
183+
157184 return web .FileResponse (path )
158185
159186 @routes .post ("/userdata/{file}" )
160187 async def post_userdata (request ):
161188 path = get_user_data_path (request )
162189 if not isinstance (path , str ):
163190 return path
164-
191+
165192 overwrite = request .query ["overwrite" ] != "false"
166193 if not overwrite and os .path .exists (path ):
167194 return web .Response (status = 409 )
@@ -170,7 +197,7 @@ async def post_userdata(request):
170197
171198 with open (path , "wb" ) as f :
172199 f .write (body )
173-
200+
174201 resp = os .path .relpath (path , self .get_request_user_filepath (request , None ))
175202 return web .json_response (resp )
176203
@@ -181,25 +208,25 @@ async def delete_userdata(request):
181208 return path
182209
183210 os .remove (path )
184-
211+
185212 return web .Response (status = 204 )
186213
187214 @routes .post ("/userdata/{file}/move/{dest}" )
188215 async def move_userdata (request ):
189216 source = get_user_data_path (request , check_exists = True )
190217 if not isinstance (source , str ):
191218 return source
192-
219+
193220 dest = get_user_data_path (request , check_exists = False , param = "dest" )
194221 if not isinstance (source , str ):
195222 return dest
196-
223+
197224 overwrite = request .query ["overwrite" ] != "false"
198225 if not overwrite and os .path .exists (dest ):
199226 return web .Response (status = 409 )
200227
201228 print (f"moving '{ source } ' -> '{ dest } '" )
202229 shutil .move (source , dest )
203-
230+
204231 resp = os .path .relpath (dest , self .get_request_user_filepath (request , None ))
205232 return web .json_response (resp )
0 commit comments