diff --git a/app/user_manager.py b/app/user_manager.py index e7381e62..8cf8b36e 100644 --- a/app/user_manager.py +++ b/app/user_manager.py @@ -197,21 +197,22 @@ class UserManager(): return web.json_response(results) - def get_user_data_path(request, check_exists = False, param = "file"): - file = request.match_info.get(param, None) + def get_user_data_path(request, check_exists=False, param="file"): + """Reads a file-like parameter from the query string.""" + file = request.query.get(param) if not file: - return web.Response(status=400) + return web.Response(status=400, text=f"Missing query param '{param}'.") path = self.get_request_user_filepath(request, file) if not path: - return web.Response(status=403) + return web.Response(status=403, text="Forbidden path.") if check_exists and not os.path.exists(path): - return web.Response(status=404) + return web.Response(status=404, text="File not found.") return path - @routes.get("/userdata/{file}") + @routes.get("/userdata/file") async def getuserdata(request): path = get_user_data_path(request, check_exists=True) if not isinstance(path, str): @@ -219,7 +220,7 @@ class UserManager(): return web.FileResponse(path) - @routes.post("/userdata/{file}") + @routes.post("/userdata/file") async def post_userdata(request): """ Upload or update a user data file. @@ -228,13 +229,11 @@ class UserManager(): controlling overwrite behavior and response format. Query Parameters: + - file: The target file path (URL encoded if necessary). - 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. @@ -250,7 +249,7 @@ class UserManager(): return path overwrite = request.query.get("overwrite", 'true') != "false" - full_info = request.query.get('full_info', 'false').lower() == "true" + full_info = request.query.get("full_info", 'false').lower() == "true" if not overwrite and os.path.exists(path): return web.Response(status=409, text="File already exists") @@ -268,7 +267,7 @@ class UserManager(): return web.json_response(resp) - @routes.delete("/userdata/{file}") + @routes.delete("/userdata/file") async def delete_userdata(request): path = get_user_data_path(request, check_exists=True) if not isinstance(path, str): @@ -278,7 +277,7 @@ class UserManager(): return web.Response(status=204) - @routes.post("/userdata/{file}/move/{dest}") + @routes.post("/userdata/file/move") async def move_userdata(request): """ Move or rename a user data file. @@ -286,11 +285,9 @@ class UserManager(): 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: + - source: The source file path (URL encoded if necessary) + - dest: The destination file path (URL encoded if necessary) - 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. @@ -304,12 +301,12 @@ class UserManager(): - Full file information (if full_info=true) - Relative file path (if full_info=false) """ - source = get_user_data_path(request, check_exists=True) + source = get_user_data_path(request, check_exists=True, param="source") if not isinstance(source, str): return source dest = get_user_data_path(request, check_exists=False, param="dest") - if not isinstance(source, str): + if not isinstance(dest, str): return dest overwrite = request.query.get("overwrite", 'true') != "false" diff --git a/tests-unit/prompt_server_test/user_manager_test.py b/tests-unit/prompt_server_test/user_manager_test.py index 7e523cbf..0ae50619 100644 --- a/tests-unit/prompt_server_test/user_manager_test.py +++ b/tests-unit/prompt_server_test/user_manager_test.py @@ -121,7 +121,7 @@ async def test_listuserdata_normalized_separator(aiohttp_client, app, tmp_path): async def test_post_userdata_new_file(aiohttp_client, app, tmp_path): client = await aiohttp_client(app) content = b"test content" - resp = await client.post("/userdata/test.txt", data=content) + resp = await client.post("/userdata/file?file=test.txt", data=content) assert resp.status == 200 assert await resp.text() == '"test.txt"' @@ -138,7 +138,7 @@ async def test_post_userdata_overwrite_existing(aiohttp_client, app, tmp_path): client = await aiohttp_client(app) new_content = b"updated content" - resp = await client.post("/userdata/test.txt", data=new_content) + resp = await client.post("/userdata/file?file=test.txt", data=new_content) assert resp.status == 200 assert await resp.text() == '"test.txt"' @@ -154,7 +154,7 @@ async def test_post_userdata_no_overwrite(aiohttp_client, app, tmp_path): f.write("initial content") client = await aiohttp_client(app) - resp = await client.post("/userdata/test.txt?overwrite=false", data=b"new content") + resp = await client.post("/userdata/file?file=test.txt&overwrite=false", data=b"new content") assert resp.status == 409 @@ -166,7 +166,7 @@ async def test_post_userdata_no_overwrite(aiohttp_client, app, tmp_path): async def test_post_userdata_full_info(aiohttp_client, app, tmp_path): client = await aiohttp_client(app) content = b"test content" - resp = await client.post("/userdata/test.txt?full_info=true", data=content) + resp = await client.post("/userdata/file?file=test.txt&full_info=true", data=content) assert resp.status == 200 result = await resp.json() @@ -181,7 +181,7 @@ async def test_move_userdata(aiohttp_client, app, tmp_path): f.write("test content") client = await aiohttp_client(app) - resp = await client.post("/userdata/source.txt/move/dest.txt") + resp = await client.post("/userdata/file/move?source=source.txt&dest=dest.txt") assert resp.status == 200 assert await resp.text() == '"dest.txt"' @@ -200,7 +200,7 @@ async def test_move_userdata_no_overwrite(aiohttp_client, app, tmp_path): f.write("destination content") client = await aiohttp_client(app) - resp = await client.post("/userdata/source.txt/move/dest.txt?overwrite=false") + resp = await client.post("/userdata/file/move?source=source.txt&dest=dest.txt&overwrite=false") assert resp.status == 409 @@ -217,7 +217,7 @@ async def test_move_userdata_full_info(aiohttp_client, app, tmp_path): f.write("test content") client = await aiohttp_client(app) - resp = await client.post("/userdata/source.txt/move/dest.txt?full_info=true") + resp = await client.post("/userdata/file/move?source=source.txt&dest=dest.txt&full_info=true") assert resp.status == 200 result = await resp.json()