feat: enhance authentication and publication download tracking
- Added JWT authentication support with configurable secret and expiration. - Introduced optional API key validation for endpoints. - Implemented tracking of publication downloads by researchers, storing records in a new PublicationDownload model. - Updated export endpoints to conditionally register downloads based on user authentication. - Enhanced researcher search response to indicate if publications were downloaded by the current user. - Updated environment configuration to include new JWT settings.
This commit is contained in:
@@ -4,8 +4,9 @@ from sqlalchemy.orm import Session
|
||||
from uuid import UUID
|
||||
|
||||
from app.db.session import get_db
|
||||
from app.db.models import Publication, Researcher
|
||||
from app.security.api_key import get_api_key
|
||||
from app.db.models import Publication, Researcher, PublicationDownload
|
||||
from app.security.api_key import get_api_key_optional
|
||||
from app.security.jwt import get_optional_current_researcher
|
||||
from app.services.sword_generator import SWORDGenerator
|
||||
from app.services.zip_generator import ZIPGenerator
|
||||
|
||||
@@ -29,8 +30,11 @@ def validate_uuid_list(pub_ids: list[str]) -> list[UUID]:
|
||||
async def export_multiple_sword(
|
||||
pub_ids: list[str],
|
||||
db: Session = Depends(get_db),
|
||||
api_key: str = Depends(get_api_key)
|
||||
api_key: str | None = Depends(get_api_key_optional),
|
||||
current: Researcher | None = Depends(get_optional_current_researcher),
|
||||
):
|
||||
if not api_key and not current:
|
||||
raise HTTPException(status_code=401, detail="Missing credentials")
|
||||
validate_uuid_list(pub_ids)
|
||||
|
||||
pubs = db.query(Publication).filter(Publication.id.in_(pub_ids)).all()
|
||||
@@ -41,6 +45,20 @@ async def export_multiple_sword(
|
||||
researcher = db.query(Researcher).filter_by(id=pubs[0].researcher_id).first()
|
||||
|
||||
xml_bytes = SWORDGenerator.generate_feed_xml(researcher, pubs)
|
||||
# Registrar descarga solo si hay usuario logueado
|
||||
if current:
|
||||
for p in pubs:
|
||||
exists = (
|
||||
db.query(PublicationDownload)
|
||||
.filter(
|
||||
PublicationDownload.researcher_id == current.id,
|
||||
PublicationDownload.publication_id == p.id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not exists:
|
||||
db.add(PublicationDownload(researcher_id=current.id, publication_id=p.id))
|
||||
db.commit()
|
||||
return Response(content=xml_bytes, media_type="application/xml")
|
||||
|
||||
|
||||
@@ -48,8 +66,11 @@ async def export_multiple_sword(
|
||||
async def export_researcher_sword(
|
||||
orcid_id: str,
|
||||
db: Session = Depends(get_db),
|
||||
api_key: str = Depends(get_api_key)
|
||||
api_key: str | None = Depends(get_api_key_optional),
|
||||
current: Researcher | None = Depends(get_optional_current_researcher),
|
||||
):
|
||||
if not api_key and not current:
|
||||
raise HTTPException(status_code=401, detail="Missing credentials")
|
||||
researcher = db.query(Researcher).filter_by(orcid_id=orcid_id).first()
|
||||
if not researcher:
|
||||
raise HTTPException(status_code=404, detail="Researcher not found")
|
||||
@@ -60,6 +81,19 @@ async def export_researcher_sword(
|
||||
raise HTTPException(status_code=404, detail="No publications found for this researcher")
|
||||
|
||||
xml_bytes = SWORDGenerator.generate_feed_xml(researcher, pubs)
|
||||
if current:
|
||||
for p in pubs:
|
||||
exists = (
|
||||
db.query(PublicationDownload)
|
||||
.filter(
|
||||
PublicationDownload.researcher_id == current.id,
|
||||
PublicationDownload.publication_id == p.id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not exists:
|
||||
db.add(PublicationDownload(researcher_id=current.id, publication_id=p.id))
|
||||
db.commit()
|
||||
return Response(content=xml_bytes, media_type="application/xml")
|
||||
|
||||
|
||||
@@ -67,8 +101,11 @@ async def export_researcher_sword(
|
||||
async def export_multiple_zip(
|
||||
pub_ids: list[str],
|
||||
db: Session = Depends(get_db),
|
||||
api_key: str = Depends(get_api_key)
|
||||
api_key: str | None = Depends(get_api_key_optional),
|
||||
current: Researcher | None = Depends(get_optional_current_researcher),
|
||||
):
|
||||
if not api_key and not current:
|
||||
raise HTTPException(status_code=401, detail="Missing credentials")
|
||||
validate_uuid_list(pub_ids)
|
||||
|
||||
pubs = db.query(Publication).filter(Publication.id.in_(pub_ids)).all()
|
||||
@@ -79,6 +116,19 @@ async def export_multiple_zip(
|
||||
researcher = db.query(Researcher).filter_by(id=pubs[0].researcher_id).first()
|
||||
|
||||
zip_bytes = ZIPGenerator.generate_zip(researcher, pubs)
|
||||
if current:
|
||||
for p in pubs:
|
||||
exists = (
|
||||
db.query(PublicationDownload)
|
||||
.filter(
|
||||
PublicationDownload.researcher_id == current.id,
|
||||
PublicationDownload.publication_id == p.id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not exists:
|
||||
db.add(PublicationDownload(researcher_id=current.id, publication_id=p.id))
|
||||
db.commit()
|
||||
return Response(content=zip_bytes, media_type="application/zip")
|
||||
|
||||
|
||||
@@ -86,8 +136,11 @@ async def export_multiple_zip(
|
||||
async def export_researcher_zip(
|
||||
orcid_id: str,
|
||||
db: Session = Depends(get_db),
|
||||
api_key: str = Depends(get_api_key)
|
||||
api_key: str | None = Depends(get_api_key_optional),
|
||||
current: Researcher | None = Depends(get_optional_current_researcher),
|
||||
):
|
||||
if not api_key and not current:
|
||||
raise HTTPException(status_code=401, detail="Missing credentials")
|
||||
researcher = db.query(Researcher).filter_by(orcid_id=orcid_id).first()
|
||||
if not researcher:
|
||||
raise HTTPException(status_code=404, detail="Researcher not found")
|
||||
@@ -98,4 +151,17 @@ async def export_researcher_zip(
|
||||
raise HTTPException(status_code=404, detail="No publications found for this researcher")
|
||||
|
||||
zip_bytes = ZIPGenerator.generate_zip(researcher, pubs)
|
||||
if current:
|
||||
for p in pubs:
|
||||
exists = (
|
||||
db.query(PublicationDownload)
|
||||
.filter(
|
||||
PublicationDownload.researcher_id == current.id,
|
||||
PublicationDownload.publication_id == p.id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not exists:
|
||||
db.add(PublicationDownload(researcher_id=current.id, publication_id=p.id))
|
||||
db.commit()
|
||||
return Response(content=zip_bytes, media_type="application/zip")
|
||||
|
||||
Reference in New Issue
Block a user