feat(download-tracking): implementar seguimiento de descargas por usuario en el dashboard

Se añaden funciones para marcar publicaciones y resultados de grupo como descargados en los componentes DashboardPage y GroupResultsPage. Se optimiza la lógica de carga de publicaciones para incluir un control de estado que evita la descarga innecesaria. Además, se actualizan los mocks de publicaciones para reflejar el estado de descarga. Se mejora la presentación del texto en el componente PublicationsTable.
This commit is contained in:
Alexis
2026-06-03 12:27:57 +02:00
parent 2f48dab109
commit 58f164b036
7 changed files with 94 additions and 14 deletions
+9 -1
View File
@@ -64,10 +64,18 @@ def init_db():
def _ensure_columns():
insp = inspect(engine)
if "publications" in insp.get_table_names():
table_names = set(insp.get_table_names())
if "publications" in table_names:
cols = {c["name"] for c in insp.get_columns("publications")}
if "downloaded" not in cols:
with engine.begin() as conn:
conn.execute(
text("ALTER TABLE publications ADD COLUMN downloaded BOOLEAN NOT NULL DEFAULT FALSE")
)
# Per-user download tracking (PublicationDownload model).
if "publication_downloads" not in table_names:
from app.db.models import PublicationDownload # noqa: F401
PublicationDownload.__table__.create(bind=engine, checkfirst=True)
+13 -7
View File
@@ -18,17 +18,23 @@ def require_export_access(
api_key: str | None = Depends(api_key_header),
current: Researcher | None = Depends(get_optional_current_researcher),
) -> Researcher | None:
if api_key is not None:
if not is_valid_api_key(api_key):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid API key",
)
return current
"""
Allow export when the proxy supplies a valid API key and/or the user
sends a valid Bearer token. Prefer returning `current` when both are
present so per-user download tracking is recorded on export.
"""
if api_key is not None and not is_valid_api_key(api_key):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid API key",
)
if current is not None:
return current
if api_key is not None:
return None
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or missing API key",