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 return active
@router.get("/completed") @router.get("/blockchain")
def get_completed_elections(db: Session = Depends(get_db)): def get_elections_blockchain():
"""Récupérer tous les votes passés/terminés""" """
Retrieve the complete elections blockchain.
from datetime import datetime Returns all election records stored immutably with cryptographic verification.
elections = db.query(services.models.Election).filter( Useful for auditing election creation and verifying no tampering occurred.
services.models.Election.end_date < datetime.utcnow(), """
services.models.Election.results_published == True return get_elections_blockchain_data()
).all()
return elections
@router.get("/upcoming") @router.get("/{election_id}/blockchain-verify")
def get_upcoming_elections(db: Session = Depends(get_db)): def verify_election_blockchain(election_id: int, db: Session = Depends(get_db)):
"""Récupérer tous les votes à venir""" """
Verify an election's blockchain integrity.
from datetime import datetime Returns verification report:
elections = db.query(services.models.Election).filter( - hash_valid: Block hash matches computed hash
services.models.Election.start_date > datetime.utcnow() - chain_valid: Entire chain integrity is valid
).all() - 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") @router.get("/active/results")
def get_active_election_results(db: Session = Depends(get_db)): def get_active_election_results(db: Session = Depends(get_db)):
"""Récupérer les résultats de l'élection active""" """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 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) @router.get("/{election_id}/results", response_model=schemas.ElectionResultResponse)
def get_election_results( def get_election_results(
election_id: int, election_id: int,
@ -206,71 +210,16 @@ def publish_results(
} }
@router.get("/completed", response_model=list[schemas.ElectionResponse]) @router.get("/{election_id}", response_model=schemas.ElectionResponse)
def get_completed_elections(db: Session = Depends(get_db)): def get_election(election_id: int, db: Session = Depends(get_db)):
"""Récupérer toutes les élections terminées (archives)""" """Récupérer une élection par son ID"""
from datetime import datetime
from .. import models
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) election = services.ElectionService.get_election(db, election_id)
if not election: if not election:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail="Election not found in database" detail="Election not found"
) )
# Then verify it's in blockchain return election
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