125 lines
4.1 KiB
Python
125 lines
4.1 KiB
Python
"""
|
|
Modèles de données SQLAlchemy pour la persistance.
|
|
"""
|
|
|
|
from sqlalchemy import Column, Integer, String, DateTime, Boolean, ForeignKey, Text, LargeBinary
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime
|
|
|
|
Base = declarative_base()
|
|
|
|
|
|
class Voter(Base):
|
|
"""Électeur - Enregistrement et authentification"""
|
|
__tablename__ = "voters"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
email = Column(String(255), unique=True, index=True, nullable=False)
|
|
password_hash = Column(String(255), nullable=False)
|
|
first_name = Column(String(100))
|
|
last_name = Column(String(100))
|
|
citizen_id = Column(String(50), unique=True) # Identifiant unique (CNI)
|
|
|
|
# Sécurité
|
|
public_key = Column(LargeBinary) # Clé publique ElGamal
|
|
has_voted = Column(Boolean, default=False)
|
|
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
# Relations
|
|
votes = relationship("Vote", back_populates="voter")
|
|
|
|
|
|
class Election(Base):
|
|
"""Élection - Configuration et paramètres"""
|
|
__tablename__ = "elections"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
name = Column(String(255), nullable=False)
|
|
description = Column(Text)
|
|
|
|
# Dates
|
|
start_date = Column(DateTime, nullable=False)
|
|
end_date = Column(DateTime, nullable=False)
|
|
|
|
# Paramètres cryptographiques
|
|
elgamal_p = Column(Integer) # Nombre premier
|
|
elgamal_g = Column(Integer) # Générateur
|
|
public_key = Column(LargeBinary) # Clé publique pour chiffrement
|
|
|
|
# État
|
|
is_active = Column(Boolean, default=True)
|
|
results_published = Column(Boolean, default=False)
|
|
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
# Relations
|
|
candidates = relationship("Candidate", back_populates="election")
|
|
votes = relationship("Vote", back_populates="election")
|
|
|
|
|
|
class Candidate(Base):
|
|
"""Candidat - Options de vote"""
|
|
__tablename__ = "candidates"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
election_id = Column(Integer, ForeignKey("elections.id"), nullable=False)
|
|
|
|
name = Column(String(255), nullable=False)
|
|
description = Column(Text)
|
|
order = Column(Integer) # Ordre d'affichage
|
|
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
# Relations
|
|
election = relationship("Election", back_populates="candidates")
|
|
votes = relationship("Vote", back_populates="candidate")
|
|
|
|
|
|
class Vote(Base):
|
|
"""Vote - Bulletin chiffré"""
|
|
__tablename__ = "votes"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
voter_id = Column(Integer, ForeignKey("voters.id"), nullable=False)
|
|
election_id = Column(Integer, ForeignKey("elections.id"), nullable=False)
|
|
candidate_id = Column(Integer, ForeignKey("candidates.id"), nullable=False)
|
|
|
|
# Vote chiffré avec ElGamal
|
|
encrypted_vote = Column(LargeBinary, nullable=False) # Ciphertext ElGamal
|
|
|
|
# Preuves
|
|
zero_knowledge_proof = Column(LargeBinary) # ZK proof que le vote est valide
|
|
ballot_hash = Column(String(64)) # Hash du bulletin pour traçabilité
|
|
|
|
# Métadonnées
|
|
timestamp = Column(DateTime, default=datetime.utcnow)
|
|
ip_address = Column(String(45)) # IPv4 ou IPv6
|
|
|
|
# Relations
|
|
voter = relationship("Voter", back_populates="votes")
|
|
election = relationship("Election", back_populates="votes")
|
|
candidate = relationship("Candidate", back_populates="votes")
|
|
|
|
|
|
class AuditLog(Base):
|
|
"""Journal d'audit pour la sécurité"""
|
|
__tablename__ = "audit_logs"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
action = Column(String(100), nullable=False)
|
|
description = Column(Text)
|
|
|
|
# Qui
|
|
user_id = Column(Integer, ForeignKey("voters.id"))
|
|
|
|
# Quand
|
|
timestamp = Column(DateTime, default=datetime.utcnow)
|
|
|
|
# Métadonnées
|
|
ip_address = Column(String(45))
|
|
user_agent = Column(String(255))
|