Skip to content

Commit cb12ad7

Browse files
authored
Add full_info flag in /userdata endpoint to list out file size and last modified timestamp (#4905)
* Add full_info flag in /userdata endpoint to list out file size and last modified timestamp * nit
1 parent f6b7194 commit cb12ad7

File tree

2 files changed

+115
-8
lines changed

2 files changed

+115
-8
lines changed

app/user_manager.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,21 +121,38 @@ async def listuserdata(request):
121121
directory = request.rel_url.query.get('dir', '')
122122
if not directory:
123123
return web.Response(status=400)
124-
124+
125125
path = self.get_request_user_filepath(request, directory)
126126
if not path:
127127
return web.Response(status=403)
128-
128+
129129
if not os.path.exists(path):
130130
return web.Response(status=404)
131-
131+
132132
recurse = request.rel_url.query.get('recurse', '').lower() == "true"
133-
results = glob.glob(os.path.join(
134-
glob.escape(path), '**/*'), recursive=recurse)
135-
results = [os.path.relpath(x, path) for x in results if os.path.isfile(x)]
136-
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),
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 = [os.path.relpath(x, path) for x in results if os.path.isfile(x)]
153+
137154
split_path = request.rel_url.query.get('split', '').lower() == "true"
138-
if split_path:
155+
if split_path and not full_info:
139156
results = [[x] + x.split(os.sep) for x in results]
140157

141158
return web.json_response(results)
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import pytest
2+
import os
3+
from aiohttp import web
4+
from app.user_manager import UserManager
5+
6+
pytestmark = (
7+
pytest.mark.asyncio
8+
) # This applies the asyncio mark to all test functions in the module
9+
10+
11+
@pytest.fixture
12+
def user_manager(tmp_path):
13+
um = UserManager()
14+
um.get_request_user_filepath = lambda req, file, **kwargs: os.path.join(
15+
tmp_path, file
16+
)
17+
return um
18+
19+
20+
@pytest.fixture
21+
def app(user_manager):
22+
app = web.Application()
23+
routes = web.RouteTableDef()
24+
user_manager.add_routes(routes)
25+
app.add_routes(routes)
26+
return app
27+
28+
29+
async def test_listuserdata_empty_directory(aiohttp_client, app, tmp_path):
30+
client = await aiohttp_client(app)
31+
resp = await client.get("/userdata?dir=test_dir")
32+
assert resp.status == 404
33+
34+
35+
async def test_listuserdata_with_files(aiohttp_client, app, tmp_path):
36+
os.makedirs(tmp_path / "test_dir")
37+
with open(tmp_path / "test_dir" / "file1.txt", "w") as f:
38+
f.write("test content")
39+
40+
client = await aiohttp_client(app)
41+
resp = await client.get("/userdata?dir=test_dir")
42+
assert resp.status == 200
43+
assert await resp.json() == ["file1.txt"]
44+
45+
46+
async def test_listuserdata_recursive(aiohttp_client, app, tmp_path):
47+
os.makedirs(tmp_path / "test_dir" / "subdir")
48+
with open(tmp_path / "test_dir" / "file1.txt", "w") as f:
49+
f.write("test content")
50+
with open(tmp_path / "test_dir" / "subdir" / "file2.txt", "w") as f:
51+
f.write("test content")
52+
53+
client = await aiohttp_client(app)
54+
resp = await client.get("/userdata?dir=test_dir&recurse=true")
55+
assert resp.status == 200
56+
assert set(await resp.json()) == {"file1.txt", os.path.join("subdir", "file2.txt")}
57+
58+
59+
async def test_listuserdata_full_info(aiohttp_client, app, tmp_path):
60+
os.makedirs(tmp_path / "test_dir")
61+
with open(tmp_path / "test_dir" / "file1.txt", "w") as f:
62+
f.write("test content")
63+
64+
client = await aiohttp_client(app)
65+
resp = await client.get("/userdata?dir=test_dir&full_info=true")
66+
assert resp.status == 200
67+
result = await resp.json()
68+
assert len(result) == 1
69+
assert result[0]["path"] == "file1.txt"
70+
assert "size" in result[0]
71+
assert "modified" in result[0]
72+
73+
74+
async def test_listuserdata_split_path(aiohttp_client, app, tmp_path):
75+
os.makedirs(tmp_path / "test_dir" / "subdir")
76+
with open(tmp_path / "test_dir" / "subdir" / "file1.txt", "w") as f:
77+
f.write("test content")
78+
79+
client = await aiohttp_client(app)
80+
resp = await client.get("/userdata?dir=test_dir&recurse=true&split=true")
81+
assert resp.status == 200
82+
assert await resp.json() == [
83+
[os.path.join("subdir", "file1.txt"), "subdir", "file1.txt"]
84+
]
85+
86+
87+
async def test_listuserdata_invalid_directory(aiohttp_client, app):
88+
client = await aiohttp_client(app)
89+
resp = await client.get("/userdata?dir=")
90+
assert resp.status == 400

0 commit comments

Comments
 (0)