File size: 2,113 Bytes
daaa6ed 36ce73b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | """
Shared storage layer — zone metadata and path utilities.
Single Responsibility: only handles metadata persistence and path resolution.
Dependency Inversion: routers depend on these abstractions instead of importing each other.
"""
import json
import os
from pathlib import Path
from config import DATA_DIR, ZONES_META, ZONE_NAME_PATTERN
def load_meta() -> dict:
"""Load zones metadata from JSON file."""
if ZONES_META.exists():
return json.loads(ZONES_META.read_text(encoding="utf-8"))
return {}
def save_meta(meta: dict):
"""Save zones metadata to JSON file."""
ZONES_META.write_text(json.dumps(meta, indent=2, default=str), encoding="utf-8")
def validate_zone_name(name: str):
"""Validate zone name format. Raises ValueError if invalid."""
if not ZONE_NAME_PATTERN.match(name):
raise ValueError("Tên zone chỉ chứa a-z, A-Z, 0-9, _, - (tối đa 50 ký tự)")
def get_zone_path(name: str) -> Path:
"""Get the filesystem path for a zone, validating it exists."""
validate_zone_name(name)
zone_path = DATA_DIR / name
if not zone_path.is_dir():
raise ValueError(f"Zone '{name}' không tồn tại")
return zone_path
def safe_path(zone_path: Path, rel_path: str) -> Path:
"""Resolve a relative path within a zone, preventing path traversal."""
target = (zone_path / rel_path).resolve()
zone_resolved = zone_path.resolve()
if target != zone_resolved and not str(target).startswith(str(zone_resolved) + os.sep):
raise ValueError("Truy cập ngoài zone không được phép")
return target
def check_zone_owner(zone_name: str, user_sub: str, user_role: str):
"""Check that the user owns the zone. Admins can access all zones."""
if user_role == "admin":
return
meta = load_meta()
info = meta.get(zone_name)
if not info:
raise ValueError(f"Zone '{zone_name}' không tồn tại")
if info.get("owner_id") != user_sub:
raise ValueError("Bạn không có quyền truy cập zone này")
|