fix: Reorder election routes to fix blockchain endpoint routing

Moved specific routes (/blockchain, /debug/all, /active, /completed, /upcoming)
BEFORE generic routes (/{election_id}, /{election_id}/results, etc) so that
specific paths are matched first and don't get caught by the {election_id}
path parameter matcher.

Also removed duplicate /completed and /upcoming route definitions.

Routes now in correct order:
1. Specific paths: /debug/all, /active, /blockchain
2. Specific subpaths: /{id}/blockchain-verify, /{id}/candidates, /{id}/results
3. Generic: /{id}
This commit is contained in:
Alexis Bruneteau 2025-11-07 03:09:49 +01:00
parent 1fd71e71e1
commit 9f5aee8b93

View File

@ -71,31 +71,50 @@ def get_active_elections(db: Session = Depends(get_db)):
return active
@router.get("/completed")
def get_completed_elections(db: Session = Depends(get_db)):
"""Récupérer tous les votes passés/terminés"""
@router.get("/blockchain")
def get_elections_blockchain():
"""
Retrieve the complete elections blockchain.
from datetime import datetime
elections = db.query(services.models.Election).filter(
services.models.Election.end_date < datetime.utcnow(),
services.models.Election.results_published == True
).all()
return elections
Returns all election records stored immutably with cryptographic verification.
Useful for auditing election creation and verifying no tampering occurred.
"""
return get_elections_blockchain_data()
@router.get("/upcoming")
def get_upcoming_elections(db: Session = Depends(get_db)):
"""Récupérer tous les votes à venir"""
@router.get("/{election_id}/blockchain-verify")
def verify_election_blockchain(election_id: int, db: Session = Depends(get_db)):
"""
Verify an election's blockchain integrity.
from datetime import datetime
elections = db.query(services.models.Election).filter(
services.models.Election.start_date > datetime.utcnow()
).all()
Returns verification report:
- hash_valid: Block hash matches computed hash
- chain_valid: Entire chain integrity is valid
- signature_valid: Block is properly signed
- verified: All checks passed
"""
# First verify it exists in database
election = services.ElectionService.get_election(db, election_id)
if not election:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Election not found in database"
)
return elections
# Then verify it's in blockchain
verification = verify_election_in_blockchain(election_id)
if not verification.get("verified"):
# Still return data but mark as unverified
return {
**verification,
"warning": "Election blockchain verification failed - possible tampering"
}
return verification
# Routes with path parameters must come AFTER specific routes
@router.get("/active/results")
def get_active_election_results(db: Session = Depends(get_db)):
"""Récupérer les résultats de l'élection active"""
@ -128,21 +147,6 @@ def get_election_candidates(election_id: int, db: Session = Depends(get_db)):
return election.candidates
@router.get("/{election_id}", response_model=schemas.ElectionResponse)
def get_election(election_id: int, db: Session = Depends(get_db)):
"""Récupérer une élection par son ID"""
election = services.ElectionService.get_election(db, election_id)
if not election:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Election not found"
)
return election
@router.get("/{election_id}/results", response_model=schemas.ElectionResultResponse)
def get_election_results(
election_id: int,
@ -206,71 +210,16 @@ def publish_results(
}
@router.get("/completed", response_model=list[schemas.ElectionResponse])
def get_completed_elections(db: Session = Depends(get_db)):
"""Récupérer toutes les élections terminées (archives)"""
from datetime import datetime
from .. import models
@router.get("/{election_id}", response_model=schemas.ElectionResponse)
def get_election(election_id: int, db: Session = Depends(get_db)):
"""Récupérer une élection par son ID"""
completed = db.query(models.Election).filter(
models.Election.end_date < datetime.utcnow(),
models.Election.results_published == True
).all()
return completed
@router.get("/upcoming", response_model=list[schemas.ElectionResponse])
def get_upcoming_elections(db: Session = Depends(get_db)):
"""Récupérer toutes les élections futures"""
from datetime import datetime
from .. import models
upcoming = db.query(models.Election).filter(
models.Election.start_date > datetime.utcnow()
).all()
return upcoming
@router.get("/blockchain")
def get_elections_blockchain():
"""
Retrieve the complete elections blockchain.
Returns all election records stored immutably with cryptographic verification.
Useful for auditing election creation and verifying no tampering occurred.
"""
return get_elections_blockchain_data()
@router.get("/{election_id}/blockchain-verify")
def verify_election_blockchain(election_id: int, db: Session = Depends(get_db)):
"""
Verify an election's blockchain integrity.
Returns verification report:
- hash_valid: Block hash matches computed hash
- chain_valid: Entire chain integrity is valid
- signature_valid: Block is properly signed
- verified: All checks passed
"""
# First verify it exists in database
election = services.ElectionService.get_election(db, election_id)
if not election:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Election not found in database"
detail="Election not found"
)
# Then verify it's in blockchain
verification = verify_election_in_blockchain(election_id)
if not verification.get("verified"):
# Still return data but mark as unverified
return {
**verification,
"warning": "Election blockchain verification failed - possible tampering"
}
return verification
return election