90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
"""File manager: ls parsing and chmod schema validation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from server.api.schemas import FileChmod
|
|
from server.utils.unix_ls import modified_from_ls_parts, parse_ls_la_line
|
|
|
|
|
|
def test_parse_ls_la_line_file_classic():
|
|
line = "-rw-r--r-- 1 www www 1234 Jun 1 12:00 index.php"
|
|
row = parse_ls_la_line(line)
|
|
assert row is not None
|
|
assert row["name"] == "index.php"
|
|
assert row["owner"] == "www"
|
|
assert row["group"] == "www"
|
|
assert row["modified"] == "Jun 1 12:00"
|
|
|
|
|
|
def test_parse_ls_la_line_long_iso():
|
|
line = "-rw-r--r-- 1 www www 99 2026-06-01 12:00:00.123456789 +0800 app.log"
|
|
row = parse_ls_la_line(line)
|
|
assert row is not None
|
|
assert row["name"] == "app.log"
|
|
assert row["modified"] == "2026-06-01 12:00:00"
|
|
|
|
|
|
def test_parse_ls_la_line_symlink():
|
|
line = "lrwxrwxrwx 1 root root 8 2026-06-01 10:00:00 +0800 current -> release"
|
|
row = parse_ls_la_line(line)
|
|
assert row is not None
|
|
assert row["is_link"] is True
|
|
assert row["name"] == "current"
|
|
assert row["link_target"] == "release"
|
|
|
|
|
|
def test_parse_ls_la_line_name_with_spaces():
|
|
line = '-rw-r--r-- 1 www www 1 2026-06-01 09:00:00 +0800 my file.txt'
|
|
row = parse_ls_la_line(line)
|
|
assert row is not None
|
|
assert row["name"] == "my file.txt"
|
|
|
|
|
|
def test_parse_ls_la_line_skips_dot_dirs():
|
|
assert parse_ls_la_line("drwxr-xr-x 2 www www 4096 Jun 1 12:00 .") is None
|
|
assert parse_ls_la_line("total 12") is None
|
|
|
|
|
|
def test_modified_from_ls_parts_iso():
|
|
parts = "-rw-r--r-- 1 www www 1 2026-06-01 15:30:45.999 +0800".split(None, 8)[:8]
|
|
assert modified_from_ls_parts(parts) == "2026-06-01 15:30:45"
|
|
|
|
|
|
def test_file_chmod_group_requires_owner():
|
|
with pytest.raises(ValidationError):
|
|
FileChmod(server_id=1, path="/tmp/x", mode="644", group="www")
|
|
|
|
|
|
def test_file_chmod_valid_chown():
|
|
m = FileChmod(server_id=1, path="/tmp/x", mode="755", owner="www", group="www")
|
|
assert m.owner == "www"
|
|
|
|
|
|
def test_file_chmod_recursive_flag():
|
|
m = FileChmod(server_id=1, path="/var/www/html", mode="755", recursive=True)
|
|
assert m.recursive is True
|
|
|
|
|
|
def test_assert_recursive_chmod_forbidden_root():
|
|
from server.utils.files_chmod_policy import assert_recursive_chmod_allowed
|
|
|
|
with pytest.raises(ValueError, match="禁止"):
|
|
assert_recursive_chmod_allowed("/")
|
|
|
|
|
|
def test_assert_recursive_chmod_forbidden_system_subtree():
|
|
from server.utils.files_chmod_policy import assert_recursive_chmod_allowed
|
|
|
|
with pytest.raises(ValueError, match="禁止"):
|
|
assert_recursive_chmod_allowed("/etc/nginx")
|
|
|
|
|
|
def test_assert_recursive_chmod_allows_common_web_roots():
|
|
from server.utils.files_chmod_policy import assert_recursive_chmod_allowed
|
|
|
|
assert_recursive_chmod_allowed("/www/wwwroot/site")
|
|
assert_recursive_chmod_allowed("/var/www/html")
|