lfss 0.3.2__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lfss/src/database.py +5 -4
- lfss/src/server.py +5 -2
- lfss/src/stat.py +6 -5
- lfss/src/utils.py +18 -2
- {lfss-0.3.2.dist-info → lfss-0.4.0.dist-info}/METADATA +1 -1
- {lfss-0.3.2.dist-info → lfss-0.4.0.dist-info}/RECORD +8 -8
- {lfss-0.3.2.dist-info → lfss-0.4.0.dist-info}/WHEEL +0 -0
- {lfss-0.3.2.dist-info → lfss-0.4.0.dist-info}/entry_points.txt +0 -0
lfss/src/database.py
CHANGED
@@ -69,7 +69,7 @@ class UserRecord:
|
|
69
69
|
permission: 'FileReadPermission'
|
70
70
|
|
71
71
|
def __str__(self):
|
72
|
-
return f"User {self.username} (id={self.id}, admin={self.is_admin}, created at {self.create_time}, last active at {self.last_active}
|
72
|
+
return f"User {self.username} (id={self.id}, admin={self.is_admin}, created at {self.create_time}, last active at {self.last_active}, storage={self.max_storage}, permission={self.permission})"
|
73
73
|
|
74
74
|
DECOY_USER = UserRecord(0, 'decoy', 'decoy', False, '2021-01-01 00:00:00', '2021-01-01 00:00:00', 0, FileReadPermission.PRIVATE)
|
75
75
|
class UserConn(DBConnBase):
|
@@ -421,7 +421,7 @@ class FileConn(DBConnBase):
|
|
421
421
|
new_exists = await self.get_file_record(new_url)
|
422
422
|
if new_exists is not None:
|
423
423
|
raise FileExistsError(f"File {new_url} already exists")
|
424
|
-
async with self.conn.execute("UPDATE fmeta SET url =
|
424
|
+
async with self.conn.execute("UPDATE fmeta SET url = ?, create_time = CURRENT_TIMESTAMP WHERE url = ?", (new_url, old_url)):
|
425
425
|
self.logger.info(f"Moved file {old_url} to {new_url}")
|
426
426
|
|
427
427
|
async def log_access(self, url: str):
|
@@ -481,8 +481,9 @@ class FileConn(DBConnBase):
|
|
481
481
|
await self.conn.execute("DELETE FROM fdata WHERE file_id IN ({})".format(','.join(['?'] * len(file_ids))), file_ids)
|
482
482
|
|
483
483
|
def validate_url(url: str, is_file = True):
|
484
|
-
|
485
|
-
|
484
|
+
prohibited_chars = ['..', ';', "'", '"', '\\', '\0', '\n', '\r', '\t', '\x0b', '\x0c']
|
485
|
+
ret = not url.startswith('/') and not url.startswith('_') and not url.startswith('.')
|
486
|
+
ret = ret and not any([c in url for c in prohibited_chars])
|
486
487
|
|
487
488
|
if not ret:
|
488
489
|
raise InvalidPathError(f"Invalid URL: {url}")
|
lfss/src/server.py
CHANGED
@@ -15,7 +15,7 @@ from .error import *
|
|
15
15
|
from .log import get_logger
|
16
16
|
from .stat import RequestDB
|
17
17
|
from .config import MAX_BUNDLE_BYTES, MAX_FILE_BYTES
|
18
|
-
from .utils import ensure_uri_compnents
|
18
|
+
from .utils import ensure_uri_compnents, format_last_modified, now_stamp
|
19
19
|
from .database import Database, UserRecord, DECOY_USER, FileRecord, check_user_permission, FileReadPermission
|
20
20
|
|
21
21
|
logger = get_logger("server", term_level="DEBUG")
|
@@ -81,6 +81,7 @@ app.add_middleware(
|
|
81
81
|
@app.middleware("http")
|
82
82
|
async def log_requests(request: Request, call_next):
|
83
83
|
|
84
|
+
request_time_stamp = now_stamp()
|
84
85
|
start_time = time.perf_counter()
|
85
86
|
response: Response = await call_next(request)
|
86
87
|
end_time = time.perf_counter()
|
@@ -91,6 +92,7 @@ async def log_requests(request: Request, call_next):
|
|
91
92
|
logger_failed_request.error(f"{request.method} {request.url.path} {response.status_code}")
|
92
93
|
|
93
94
|
await req_conn.log_request(
|
95
|
+
request_time_stamp,
|
94
96
|
request.method, request.url.path, response.status_code, response_time,
|
95
97
|
headers = dict(request.headers),
|
96
98
|
query = dict(request.query_params),
|
@@ -148,7 +150,8 @@ async def get_file(path: str, download = False, user: UserRecord = Depends(get_c
|
|
148
150
|
return Response(
|
149
151
|
content=fblob, media_type=media_type, headers={
|
150
152
|
"Content-Disposition": f"{disposition}; filename={fname}",
|
151
|
-
"Content-Length": str(len(fblob))
|
153
|
+
"Content-Length": str(len(fblob)),
|
154
|
+
"Last-Modified": format_last_modified(file_record.create_time)
|
152
155
|
}
|
153
156
|
)
|
154
157
|
|
lfss/src/stat.py
CHANGED
@@ -13,7 +13,7 @@ class RequestDB:
|
|
13
13
|
await self.conn.execute('''
|
14
14
|
CREATE TABLE IF NOT EXISTS requests (
|
15
15
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
16
|
-
time
|
16
|
+
time FLOAT DEFAULT (strftime('%s', 'now')),
|
17
17
|
method TEXT,
|
18
18
|
path TEXT,
|
19
19
|
headers TEXT,
|
@@ -43,7 +43,8 @@ class RequestDB:
|
|
43
43
|
await self.commit()
|
44
44
|
|
45
45
|
async def log_request(
|
46
|
-
self,
|
46
|
+
self, time: float,
|
47
|
+
method: str, path: str,
|
47
48
|
status: int, duration: float,
|
48
49
|
headers: Optional[Any] = None,
|
49
50
|
query: Optional[Any] = None,
|
@@ -57,9 +58,9 @@ class RequestDB:
|
|
57
58
|
client = str(client)
|
58
59
|
async with self.conn.execute('''
|
59
60
|
INSERT INTO requests (
|
60
|
-
method, path, headers, query, client, duration, request_size, response_size, status
|
61
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
62
|
-
''', (method, path, headers, query, client, duration, request_size, response_size, status)) as cursor:
|
61
|
+
time, method, path, headers, query, client, duration, request_size, response_size, status
|
62
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
63
|
+
''', (time, method, path, headers, query, client, duration, request_size, response_size, status)) as cursor:
|
63
64
|
assert cursor.lastrowid is not None
|
64
65
|
return cursor.lastrowid
|
65
66
|
|
lfss/src/utils.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import datetime
|
2
2
|
import urllib.parse
|
3
3
|
import asyncio
|
4
4
|
import functools
|
@@ -49,4 +49,20 @@ def debounce_async(delay: float = 0):
|
|
49
49
|
except asyncio.CancelledError:
|
50
50
|
pass
|
51
51
|
return wrapper
|
52
|
-
return debounce_wrap
|
52
|
+
return debounce_wrap
|
53
|
+
|
54
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified
|
55
|
+
def format_last_modified(last_modified_gmt: str):
|
56
|
+
"""
|
57
|
+
Format the last modified time to the HTTP standard format
|
58
|
+
- last_modified_gmt: The last modified time in SQLite ISO 8601 GMT format: e.g. '2021-09-01 12:00:00'
|
59
|
+
"""
|
60
|
+
assert len(last_modified_gmt) == 19
|
61
|
+
dt = datetime.datetime.strptime(last_modified_gmt, '%Y-%m-%d %H:%M:%S')
|
62
|
+
return dt.strftime('%a, %d %b %Y %H:%M:%S GMT')
|
63
|
+
|
64
|
+
def now_stamp() -> float:
|
65
|
+
return datetime.datetime.now().timestamp()
|
66
|
+
|
67
|
+
def stamp_to_str(stamp: float) -> str:
|
68
|
+
return datetime.datetime.fromtimestamp(stamp).strftime('%Y-%m-%d %H:%M:%S')
|
@@ -15,13 +15,13 @@ lfss/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
lfss/client/api.py,sha256=VBiU-JxGaN6S-fXYD_KvzG7FsGBIUzZ5IisJJSMooDk,3443
|
16
16
|
lfss/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
lfss/src/config.py,sha256=mc8QoiWoPgiZ5JnSvKBH8jWbp5uLSyG3l5boDiQPXS0,325
|
18
|
-
lfss/src/database.py,sha256=
|
18
|
+
lfss/src/database.py,sha256=wNDsvjvr7Jq1gDeUd_26tETcfeiplAmywIwXLK1TD80,27923
|
19
19
|
lfss/src/error.py,sha256=S5ui3tJ0uKX4EZnt2Db-KbDmJXlECI_OY95cNMkuegc,218
|
20
20
|
lfss/src/log.py,sha256=qNE04sHoZ2rMbQ5dR2zT7Xaz1KVAfYp5hKpWJX42S9g,5244
|
21
|
-
lfss/src/server.py,sha256=
|
22
|
-
lfss/src/stat.py,sha256=
|
23
|
-
lfss/src/utils.py,sha256=
|
24
|
-
lfss-0.
|
25
|
-
lfss-0.
|
26
|
-
lfss-0.
|
27
|
-
lfss-0.
|
21
|
+
lfss/src/server.py,sha256=P4GpsIJ869fi6lzHk2IVMyJooGWIvqh0cykkDerJ74k,13190
|
22
|
+
lfss/src/stat.py,sha256=_4OaSvBm7D6mPgifwxnhGIEk1_q3SxfJr3lizaEoV_w,2081
|
23
|
+
lfss/src/utils.py,sha256=8VkrtpSmurbMiX7GyK-n7Grvzy3uwSJXHdONEsuLCDI,2272
|
24
|
+
lfss-0.4.0.dist-info/METADATA,sha256=X0qXQ4gkl_sJ5VNEGLJ0XG0JSqmNnOPixHVn6ZQ7pj0,1787
|
25
|
+
lfss-0.4.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
26
|
+
lfss-0.4.0.dist-info/entry_points.txt,sha256=nUIJhenyZbcymvPVhrzV7SAtRhd7O52DflbRrpQUC04,110
|
27
|
+
lfss-0.4.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|