feat: enhance backend security and configuration
- 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.
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Modelo de solicitud de login OAuth
|
||||
# ---------------------------------------------------------
|
||||
|
||||
class OrcidLoginRequestSchema(BaseModel):
|
||||
# `code` is the authorization code returned by ORCID OAuth after the user signs in.
|
||||
# Exchanging it for tokens must happen server-side.
|
||||
code: str = Field(..., examples=["Q70Y3A"])
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Modelo de respuesta de login OAuth
|
||||
# ---------------------------------------------------------
|
||||
|
||||
class OrcidLoginResponseSchema(BaseModel):
|
||||
access_token: str
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
Schemas de los endpoints de export.
|
||||
|
||||
El backend recibe `pub_ids` como UUIDs en formato string. Pydantic ya los
|
||||
valida y convierte; aquí además aplicamos un tope de tamaño para impedir
|
||||
peticiones gigantes.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import List
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
|
||||
class PublicationIdsRequestSchema(BaseModel):
|
||||
pub_ids: List[UUID] = Field(
|
||||
min_length=1,
|
||||
max_length=settings.MAX_PUB_IDS_BATCH,
|
||||
)
|
||||
@@ -3,6 +3,10 @@ from uuid import UUID
|
||||
from typing import Optional, List, Any
|
||||
from datetime import datetime
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Modelo de publicación
|
||||
# ---------------------------------------------------------
|
||||
|
||||
class PublicationSchema(BaseModel):
|
||||
id: UUID
|
||||
put_code: int | None = None
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from uuid import UUID
|
||||
from typing import Optional, List, Dict
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from app.core.config import settings
|
||||
from app.schema.publication import PublicationSchema
|
||||
from app.utils.orcid_validator import ORCID_PATTERN, is_valid_orcid
|
||||
|
||||
|
||||
class ResearcherSchema(BaseModel):
|
||||
id: UUID
|
||||
orcid_id: str
|
||||
name: Optional[str]
|
||||
orcid_id: str = Field(min_length=19, max_length=19, pattern=ORCID_PATTERN)
|
||||
name: Optional[str] = Field(default=None, max_length=255)
|
||||
authenticated: bool
|
||||
last_sync_at: Optional[datetime]
|
||||
|
||||
@@ -33,7 +38,25 @@ class ResearcherWithPublicationsSchema(BaseModel):
|
||||
|
||||
|
||||
class ResearcherBatchSearchRequestSchema(BaseModel):
|
||||
orcid_ids: List[str] = Field(min_length=1)
|
||||
orcid_ids: List[str] = Field(
|
||||
min_length=1,
|
||||
max_length=settings.MAX_ORCID_BATCH,
|
||||
)
|
||||
|
||||
@field_validator("orcid_ids")
|
||||
@classmethod
|
||||
def _validate_each(cls, value: List[str]) -> List[str]:
|
||||
deduped: List[str] = []
|
||||
seen = set()
|
||||
for v in value:
|
||||
if not isinstance(v, str):
|
||||
raise ValueError("ORCID iD debe ser string")
|
||||
if not is_valid_orcid(v):
|
||||
raise ValueError(f"ORCID iD inválido: {v}")
|
||||
if v not in seen:
|
||||
seen.add(v)
|
||||
deduped.append(v)
|
||||
return deduped
|
||||
|
||||
|
||||
class ResearcherSearchErrorSchema(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user