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")