af1b8e9956
- Updated Dockerfile to improve security with a non-root user and added health checks. - Modified docker-compose.yml to set containers as read-only, restrict ports to localhost, and implement health checks. - Enhanced .env.example with additional environment variables for security and configuration. - Improved FastAPI application with middleware for security headers, CORS, and body size limits. - Refactored authentication flow in auth.py to include state validation and improved error handling. - Added rate limiting to various endpoints to prevent abuse. - Updated researcher and publication handling to ensure better validation and error management.
93 lines
3.4 KiB
Python
93 lines
3.4 KiB
Python
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, UniqueConstraint
|
|
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
|
from sqlalchemy.orm import relationship
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
from app.db.session import Base
|
|
|
|
# ---------------------------------------------------------
|
|
# Modelo de investigador
|
|
# ---------------------------------------------------------
|
|
|
|
class Researcher(Base):
|
|
__tablename__ = "researchers"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
orcid_id = Column(String, unique=True, index=True, nullable=False)
|
|
name = Column(String, nullable=True)
|
|
authenticated = Column(Boolean, default=False)
|
|
last_sync_at = Column(DateTime, nullable=True)
|
|
|
|
publications = relationship("Publication", back_populates="researcher", cascade="all, delete-orphan")
|
|
|
|
# ---------------------------------------------------------
|
|
# Modelo de publicación
|
|
# ---------------------------------------------------------
|
|
|
|
class Publication(Base):
|
|
__tablename__ = "publications"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
|
|
researcher_id = Column(UUID(as_uuid=True), ForeignKey("researchers.id"), nullable=False)
|
|
researcher = relationship("Researcher", back_populates="publications")
|
|
|
|
# ORCID core
|
|
put_code = Column(Integer, index=True, nullable=False)
|
|
title = Column(String, nullable=True)
|
|
subtitle = Column(String, nullable=True)
|
|
type = Column(String, nullable=True)
|
|
|
|
# Journal / container
|
|
journal = Column(String, nullable=True)
|
|
|
|
# Dates
|
|
pub_year = Column(Integer, nullable=True)
|
|
pub_month = Column(Integer, nullable=True)
|
|
pub_day = Column(Integer, nullable=True)
|
|
|
|
# Identifiers / links
|
|
doi = Column(String, nullable=True)
|
|
url = Column(String, nullable=True)
|
|
|
|
# Description / citation
|
|
short_description = Column(String, nullable=True)
|
|
citation_type = Column(String, nullable=True)
|
|
citation_value = Column(String, nullable=True)
|
|
|
|
# Language / country
|
|
language_code = Column(String, nullable=True)
|
|
country = Column(String, nullable=True)
|
|
|
|
# Extra structured data
|
|
external_ids = Column(JSONB, nullable=True) # lista de external-id normalizados
|
|
contributors = Column(JSONB, nullable=True) # lista de autores/roles
|
|
|
|
# Tu campo existente
|
|
hash_fingerprint = Column(String, nullable=True)
|
|
last_modified = Column(DateTime, nullable=True, default=None)
|
|
|
|
# Legacy: descargado global (deprecado). Mantener por compatibilidad de DB.
|
|
downloaded = Column(Boolean, nullable=False, default=False)
|
|
|
|
# ---------------------------------------------------------
|
|
# Modelo de descarga de publicación
|
|
# ---------------------------------------------------------
|
|
|
|
class PublicationDownload(Base):
|
|
"""
|
|
Marca de descarga por usuario (researcher) sobre cualquier publicación.
|
|
Una fila por (researcher_id, publication_id).
|
|
"""
|
|
|
|
__tablename__ = "publication_downloads"
|
|
__table_args__ = (
|
|
UniqueConstraint("researcher_id", "publication_id", name="uq_publication_download"),
|
|
)
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
researcher_id = Column(UUID(as_uuid=True), ForeignKey("researchers.id"), nullable=False, index=True)
|
|
publication_id = Column(UUID(as_uuid=True), ForeignKey("publications.id"), nullable=False, index=True)
|
|
downloaded_at = Column(DateTime, nullable=False, default=datetime.utcnow)
|