feat: publish CodexPi contest snapshot
Some checks are pending
Qualité / tests (push) Waiting to run
Some checks are pending
Qualité / tests (push) Waiting to run
This commit is contained in:
70
tests/test_project_permissions.py
Normal file
70
tests/test_project_permissions.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from codexpi.project_paths import ProjectPathError, browse_directories, create_directory, resolve_project_file, validate_project_path
|
||||
|
||||
|
||||
def test_registered_project_must_be_under_allowed_root(app_env):
|
||||
_, _, projects, forbidden = app_env
|
||||
valid = projects / "valid"
|
||||
valid.mkdir()
|
||||
assert validate_project_path(str(valid), (projects,), (forbidden,)) == valid.resolve()
|
||||
with pytest.raises(ProjectPathError):
|
||||
validate_project_path(str(forbidden), (projects,), (forbidden,))
|
||||
|
||||
|
||||
def test_directory_browser_starts_above_allowed_root_and_hides_forbidden(tmp_path: Path):
|
||||
home = tmp_path / "home"
|
||||
allowed = home / "config"
|
||||
project = allowed / "NASFLIX"
|
||||
forbidden = allowed / "private"
|
||||
project.mkdir(parents=True)
|
||||
forbidden.mkdir()
|
||||
(home / "other-user").mkdir()
|
||||
|
||||
root = browse_directories(str(home), (allowed,), (forbidden,), home)
|
||||
assert root["selectable"] is False
|
||||
assert root["directories"] == [{"name": "config", "path": str(allowed), "selectable": True}]
|
||||
|
||||
listing = browse_directories(str(allowed), (allowed,), (forbidden,), home)
|
||||
assert [item["name"] for item in listing["directories"]] == ["NASFLIX"]
|
||||
assert listing["parent"] == str(home)
|
||||
|
||||
|
||||
def test_directory_browser_creates_and_selects_empty_project_folder(tmp_path: Path):
|
||||
home = tmp_path / "home"
|
||||
allowed = home / "config"
|
||||
allowed.mkdir(parents=True)
|
||||
|
||||
result = create_directory(str(allowed), "Nouveau projet", (allowed,), (), home)
|
||||
|
||||
assert result["path"] == str(allowed / "Nouveau projet")
|
||||
assert result["selectable"] is True
|
||||
assert result["directories"] == []
|
||||
with pytest.raises(ProjectPathError):
|
||||
create_directory(str(allowed), "../escape", (allowed,), (), home)
|
||||
|
||||
|
||||
def test_api_rejects_forbidden_project(logged_in):
|
||||
client, _, _, forbidden, headers = logged_in
|
||||
response = client.post("/api/projects", headers=headers, json={"name": "bad", "path": str(forbidden)})
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_path_traversal_is_rejected(tmp_path: Path):
|
||||
root = tmp_path / "project"
|
||||
root.mkdir()
|
||||
outside = tmp_path / "secret.txt"
|
||||
outside.write_text("secret")
|
||||
with pytest.raises(ProjectPathError):
|
||||
resolve_project_file(root, "../secret.txt")
|
||||
|
||||
|
||||
def test_project_operations_use_ids(logged_in):
|
||||
client, _, projects, _, headers = logged_in
|
||||
repo = projects / "repo"
|
||||
repo.mkdir()
|
||||
created = client.post("/api/projects", headers=headers, json={"name": "repo", "path": str(repo)})
|
||||
assert created.status_code == 201
|
||||
assert client.get("/api/projects/not-a-uuid/git").status_code == 404
|
||||
Reference in New Issue
Block a user