diff --git a/backend/app/models/db_models.py b/backend/app/models/db_models.py index 9a98605a..a2bce361 100644 --- a/backend/app/models/db_models.py +++ b/backend/app/models/db_models.py @@ -1,11 +1,11 @@ # backend/app/models/db_models.py """Models SQLAlchemy per a tota la persistència de MiroFish.""" import uuid -from datetime import datetime +from datetime import datetime, timezone from typing import Optional from sqlalchemy import ( String, Integer, Text, Boolean, DateTime, JSON, - ForeignKey, UniqueConstraint + ForeignKey ) from sqlalchemy.orm import Mapped, mapped_column, relationship from ..db import Base @@ -16,7 +16,7 @@ def _uuid() -> str: def _now() -> datetime: - return datetime.utcnow() + return datetime.now(timezone.utc) class UserModel(Base): diff --git a/backend/app/storage/factory.py b/backend/app/storage/factory.py index 2b3b30f7..642a49b3 100644 --- a/backend/app/storage/factory.py +++ b/backend/app/storage/factory.py @@ -1,20 +1,18 @@ """Selecciona la implementació de StorageService per STORAGE_TYPE.""" -import os from .protocol import StorageService def create_storage_service() -> StorageService: - storage_type = os.environ.get("STORAGE_TYPE", "local") + from app.config import Config + storage_type = Config.STORAGE_TYPE match storage_type: case "azure": from .azure_blob import AzureBlobStorage - conn_str = os.environ.get("AZURE_STORAGE_CONNECTION_STRING", "") - container = os.environ.get("AZURE_STORAGE_CONTAINER", "mirofish") + conn_str = Config.AZURE_STORAGE_CONNECTION_STRING + container = Config.AZURE_STORAGE_CONTAINER if not conn_str: raise RuntimeError("AZURE_STORAGE_CONNECTION_STRING no configurada per STORAGE_TYPE=azure") return AzureBlobStorage(conn_str, container) case _: from .local import LocalFSStorage - base = os.environ.get("STORAGE_LOCAL_PATH", - os.path.join(os.path.dirname(__file__), "../../../uploads")) - return LocalFSStorage(base) + return LocalFSStorage(Config.STORAGE_LOCAL_PATH) diff --git a/backend/app/storage/local.py b/backend/app/storage/local.py index 52b765b9..ccd7ccfe 100644 --- a/backend/app/storage/local.py +++ b/backend/app/storage/local.py @@ -1,6 +1,5 @@ """Adapter de storage per a filesystem local.""" import io -import os import shutil from pathlib import Path from .protocol import StorageService @@ -16,7 +15,9 @@ class LocalFSStorage: def _safe_path(self, relative: str) -> Path: """Resol el path i valida que estigui dins del base per evitar path traversal.""" resolved = (self._base / relative).resolve() - if not str(resolved).startswith(str(self._base)): + try: + resolved.relative_to(self._base) + except ValueError: raise ValueError(f"Path traversal detectat: {relative!r}") return resolved @@ -41,6 +42,8 @@ class LocalFSStorage: p.unlink() def delete_prefix(self, prefix: str) -> None: + if not prefix or prefix in (".", "/"): + raise ValueError("prefix no pot ser buit ni arrel") p = self._safe_path(prefix) if p.is_dir(): shutil.rmtree(p)