CIA/e-voting-system/restore_data.py
E-Voting Developer 8baabf528c feat: Implement Historique and Upcoming Votes pages with styling and data fetching
- Added HistoriquePage component to display user's voting history with detailed statistics and vote cards.
- Created UpcomingVotesPage component to show upcoming elections with a similar layout.
- Developed CSS styles for both pages to enhance visual appeal and responsiveness.
- Integrated API calls to fetch user's votes and upcoming elections.
- Added a rebuild script for Docker environment setup and data restoration.
- Created a Python script to populate the database with sample data for testing.
2025-11-06 05:12:03 +01:00

413 lines
15 KiB
Python

#!/usr/bin/env python3
"""
Script pour repeupler la base de données avec :
- 1700 utilisateurs
- 10 élections passées (historique)
- 5 élections actives
- 15 élections futures
- Votes distribués aléatoirement (pas tous les users dans chaque election)
"""
import subprocess
import random
from datetime import datetime, timedelta
import bcrypt
import tempfile
import os
# Configuration
DB_USER = "evoting_user"
DB_PASSWORD = "evoting_pass123"
DB_NAME = "evoting_db"
HASHED_PASSWORD = bcrypt.hashpw(b"epita1234", b"$2b$12$zxCiC3MJpa32FfpX8u7Lx.").decode('utf-8')
def run_sql(sql):
"""Exécuter du SQL via docker exec"""
cmd = f'docker exec -i evoting_db mariadb -u {DB_USER} -p{DB_PASSWORD} {DB_NAME}'
result = subprocess.run(cmd, shell=True, input=sql, capture_output=True, text=True)
return result
def log(msg, emoji="📝"):
"""Afficher un message formaté"""
print(f"{emoji} {msg}")
# ============================================================================
# PHASE 0: NETTOYER LA BASE DE DONNÉES
# ============================================================================
log("PHASE 0: Nettoyage de la base de données...", "🧹")
# Utiliser mysql client directement pour avoir plus de control
cleanup_sql = """
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS votes;
DROP TABLE IF EXISTS candidates;
DROP TABLE IF EXISTS elections;
DROP TABLE IF EXISTS voters;
SET FOREIGN_KEY_CHECKS=1;
"""
# Écrire dans un fichier temporaire et exécuter
import tempfile
import os
with tempfile.NamedTemporaryFile(mode='w', suffix='.sql', delete=False) as f:
f.write(cleanup_sql)
temp_file = f.name
try:
cmd = f'docker exec -i evoting_db mariadb -u {DB_USER} -p{DB_PASSWORD} {DB_NAME} < {temp_file}'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode == 0:
log("✓ Anciennes tables supprimées", "")
else:
log(f"⚠️ Nettoyage échoué: {result.stderr}", "⚠️")
finally:
os.unlink(temp_file)
# Recréer les tables
create_tables_sql = """
CREATE TABLE voters (
id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
first_name VARCHAR(100),
last_name VARCHAR(100),
citizen_id VARCHAR(50) UNIQUE,
public_key LONGBLOB,
has_voted BOOLEAN DEFAULT FALSE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
certificate_hash VARCHAR(255),
INDEX idx_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE elections (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
description TEXT,
start_date DATETIME NOT NULL,
end_date DATETIME NOT NULL,
elgamal_p INT,
elgamal_g INT,
public_key LONGBLOB,
is_active BOOLEAN DEFAULT FALSE,
results_published BOOLEAN DEFAULT FALSE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE candidates (
id INT PRIMARY KEY AUTO_INCREMENT,
election_id INT NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
`order` INT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (election_id) REFERENCES elections(id) ON DELETE CASCADE,
INDEX idx_election (election_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE votes (
id INT PRIMARY KEY AUTO_INCREMENT,
voter_id INT NOT NULL,
election_id INT NOT NULL,
candidate_id INT NOT NULL,
encrypted_vote LONGBLOB NOT NULL,
zero_knowledge_proof LONGBLOB,
ballot_hash VARCHAR(255),
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
ip_address VARCHAR(45),
FOREIGN KEY (voter_id) REFERENCES voters(id) ON DELETE CASCADE,
FOREIGN KEY (election_id) REFERENCES elections(id) ON DELETE CASCADE,
FOREIGN KEY (candidate_id) REFERENCES candidates(id) ON DELETE CASCADE,
INDEX idx_voter (voter_id),
INDEX idx_election (election_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.sql', delete=False) as f:
f.write(create_tables_sql)
temp_file = f.name
try:
cmd = f'docker exec -i evoting_db mariadb -u {DB_USER} -p{DB_PASSWORD} {DB_NAME} < {temp_file}'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode == 0:
log("✓ Tables recréées", "")
else:
log(f"Erreur: {result.stderr}", "")
finally:
os.unlink(temp_file)
# ============================================================================
log("PHASE 1: Création de 1700 utilisateurs...", "👥")
sql_users = "INSERT INTO voters (email, password_hash, first_name, last_name, citizen_id, certificate_hash, public_key, created_at) VALUES\n"
values = []
# 1698 utilisateurs normaux
for i in range(1, 1699):
email = f"voter_{i}@voting.local"
first_name = f"User{i}"
last_name = f"Voter{i}"
citizen_id = f"ID_{i:06d}"
values.append(f"('{email}', '{HASHED_PASSWORD}', '{first_name}', '{last_name}', '{citizen_id}', 'cert_{i}', 'pk_{i}', NOW())")
# 2 utilisateurs spéciaux
special_users = [
("new_user_e13_157@voting.local", "NewUser157", "Election13_157", "ID_SPEC_157"),
("new_user_e13_192@voting.local", "NewUser192", "Election13_192", "ID_SPEC_192"),
]
for email, first_name, last_name, citizen_id in special_users:
values.append(f"('{email}', '{HASHED_PASSWORD}', '{first_name}', '{last_name}', '{citizen_id}', 'cert_special', 'pk_special', NOW())")
sql_users += ",\n".join(values) + ";"
result = run_sql(sql_users)
if result.returncode == 0:
log("✓ 1700 utilisateurs créés", "")
else:
log(f"Erreur: {result.stderr}", "")
# ============================================================================
# PHASE 2: CRÉER LES 30 ÉLECTIONS (10 passées + 5 actives + 15 futures)
# ============================================================================
log("PHASE 2: Création des 30 élections...", "🗳️")
now = datetime.now()
elections = []
# 10 élections passées (historique)
for i in range(1, 11):
start = (now - timedelta(days=365-i*30)).strftime("%Y-%m-%d")
end = (now - timedelta(days=365-(i*30)-7)).strftime("%Y-%m-%d")
elections.append({
"name": f"Historical Election {i}",
"description": f"Past election {i}",
"start": start,
"end": end,
"is_active": 0
})
# 5 élections actives (en cours)
for i in range(1, 6):
start = (now - timedelta(days=7-i)).strftime("%Y-%m-%d")
end = (now + timedelta(days=30+i)).strftime("%Y-%m-%d")
elections.append({
"name": f"Active Election {i}",
"description": f"Current election {i}",
"start": start,
"end": end,
"is_active": 1
})
# 15 élections futures
for i in range(1, 16):
start = (now + timedelta(days=30+i*5)).strftime("%Y-%m-%d")
end = (now + timedelta(days=37+i*5)).strftime("%Y-%m-%d")
elections.append({
"name": f"Upcoming Election {i}",
"description": f"Future election {i}",
"start": start,
"end": end,
"is_active": 0
})
sql_elections = "INSERT INTO elections (name, description, start_date, end_date, elgamal_p, elgamal_g, public_key, is_active, results_published) VALUES\n"
election_values = []
for idx, election in enumerate(elections, 1):
election_values.append(
f"('{election['name']}', '{election['description']}', '{election['start']}', '{election['end']}', '23', '5', 'pk_{idx}', {election['is_active']}, 0)"
)
sql_elections += ",\n".join(election_values) + ";"
result = run_sql(sql_elections)
if result.returncode == 0:
log(f"✓ 30 élections créées (10 passées + 5 actives + 15 futures)", "")
else:
log(f"Erreur: {result.stderr}", "")
# ============================================================================
# PHASE 3: CRÉER LES CANDIDATS
# ============================================================================
log("PHASE 3: Création des candidats...", "🎭")
candidate_names = [
"Alice Johnson", "Bob Smith", "Carol White", "David Brown",
"Emily Davis", "Frank Miller", "Grace Wilson", "Henry Moore"
]
sql_candidates = "INSERT INTO candidates (election_id, name, description, `order`, created_at) VALUES\n"
candidate_values = []
for election_id in range(1, 31):
# 4-8 candidats par élection
num_candidates = random.randint(4, 8)
selected_candidates = random.sample(candidate_names, min(num_candidates, len(candidate_names)))
for order, name in enumerate(selected_candidates, 1):
candidate_values.append(
f"({election_id}, '{name}', 'Candidate {name}', {order}, NOW())"
)
sql_candidates += ",\n".join(candidate_values) + ";"
result = run_sql(sql_candidates)
if result.returncode == 0:
log(f"✓ Candidats créés pour toutes les élections", "")
else:
log(f"Erreur: {result.stderr}", "")
# ============================================================================
# PHASE 4: CRÉER LES VOTES
# ============================================================================
log("PHASE 4: Création des votes...", "🗳️")
sql_votes = "INSERT INTO votes (voter_id, election_id, candidate_id, encrypted_vote, ballot_hash, timestamp) VALUES\n"
vote_values = []
# Pour chaque élection
for election_id in range(1, 31):
# Récupérer les candidats de cette élection
result_candidates = run_sql(f"SELECT id FROM candidates WHERE election_id = {election_id};")
candidate_ids = []
if result_candidates.returncode == 0:
lines = result_candidates.stdout.strip().split('\n')[1:]
for line in lines:
if line.strip():
candidate_ids.append(int(line.split()[0]))
if not candidate_ids:
continue
# Déterminer le nombre de votants pour cette élection
# Entre 20% et 80% des utilisateurs votent pour cette élection
num_voters = random.randint(int(1700 * 0.2), int(1700 * 0.8))
# Sélectionner les votants aléatoirement
voter_ids = random.sample(range(1, 1701), num_voters)
for voter_id in voter_ids:
candidate_id = random.choice(candidate_ids)
ballot_hash = f"hash_{voter_id}_{election_id}"
vote_values.append(
f"({voter_id}, {election_id}, {candidate_id}, 'encrypted_{voter_id}_{election_id}', '{ballot_hash}', NOW())"
)
# Insérer tous les votes en batch
batch_size = 1000
for i in range(0, len(vote_values), batch_size):
batch = vote_values[i:i+batch_size]
sql_batch = "INSERT INTO votes (voter_id, election_id, candidate_id, encrypted_vote, ballot_hash, timestamp) VALUES\n"
sql_batch += ",\n".join(batch) + ";"
result = run_sql(sql_batch)
if result.returncode != 0:
log(f"Erreur batch {i//batch_size}: {result.stderr}", "")
log(f"{len(vote_values)} votes créés", "")
# ============================================================================
# PHASE 5: VOTES SPÉCIAUX POUR new_user_e13_192
# ============================================================================
log("PHASE 5: Configuration des votes pour new_user_e13_192...", "⚙️")
# Récupérer l'ID de new_user_e13_192
result = run_sql("SELECT id FROM voters WHERE email = 'new_user_e13_192@voting.local';")
special_user_id = None
if result.returncode == 0 and result.stdout.strip():
lines = result.stdout.strip().split('\n')
if len(lines) > 1:
special_user_id = int(lines[1].split()[0])
if special_user_id:
# Supprimer tous les votes actuels pour cet utilisateur
run_sql(f"DELETE FROM votes WHERE voter_id = {special_user_id};")
special_votes = []
# 10 votes pour les élections passées (1-10)
for election_id in range(1, 11):
result_cand = run_sql(f"SELECT id FROM candidates WHERE election_id = {election_id} LIMIT 1;")
if result_cand.returncode == 0 and result_cand.stdout.strip():
lines = result_cand.stdout.strip().split('\n')
if len(lines) > 1:
candidate_id = int(lines[1].split()[0])
ballot_hash = f"hash_{special_user_id}_{election_id}"
special_votes.append(
f"({special_user_id}, {election_id}, {candidate_id}, 'encrypted_{special_user_id}_{election_id}', '{ballot_hash}', NOW())"
)
# 4 votes pour les élections actives (11, 12, 14, 15) - PAS 13
for election_id in [11, 12, 14, 15]:
result_cand = run_sql(f"SELECT id FROM candidates WHERE election_id = {election_id} LIMIT 1;")
if result_cand.returncode == 0 and result_cand.stdout.strip():
lines = result_cand.stdout.strip().split('\n')
if len(lines) > 1:
candidate_id = int(lines[1].split()[0])
ballot_hash = f"hash_{special_user_id}_{election_id}"
special_votes.append(
f"({special_user_id}, {election_id}, {candidate_id}, 'encrypted_{special_user_id}_{election_id}', '{ballot_hash}', NOW())"
)
# 4 votes pour les élections futures (21, 24, 27, 30)
for election_id in [21, 24, 27, 30]:
result_cand = run_sql(f"SELECT id FROM candidates WHERE election_id = {election_id} LIMIT 1;")
if result_cand.returncode == 0 and result_cand.stdout.strip():
lines = result_cand.stdout.strip().split('\n')
if len(lines) > 1:
candidate_id = int(lines[1].split()[0])
ballot_hash = f"hash_{special_user_id}_{election_id}"
special_votes.append(
f"({special_user_id}, {election_id}, {candidate_id}, 'encrypted_{special_user_id}_{election_id}', '{ballot_hash}', NOW())"
)
if special_votes:
sql_special = "INSERT INTO votes (voter_id, election_id, candidate_id, encrypted_vote, ballot_hash, timestamp) VALUES\n"
sql_special += ",\n".join(special_votes) + ";"
result = run_sql(sql_special)
if result.returncode == 0:
log(f"✓ 18 votes spéciaux créés pour new_user_e13_192 (10 + 4 + 4)", "")
else:
log(f"Erreur: {result.stderr}", "")
# ============================================================================
# PHASE 6: STATISTIQUES FINALES
# ============================================================================
log("PHASE 6: Vérification des données...", "📊")
result = run_sql("""
SELECT
(SELECT COUNT(*) FROM elections) as total_elections,
(SELECT COUNT(*) FROM voters) as total_voters,
(SELECT COUNT(*) FROM candidates) as total_candidates,
(SELECT COUNT(*) FROM votes) as total_votes;
""")
if result.returncode == 0:
print("\n" + "="*60)
print("✅ BASE DE DONNÉES REPUPLÉE AVEC SUCCÈS!")
print("="*60)
print(result.stdout)
print("="*60)
# Afficher les utilisateurs spéciaux
result = run_sql("SELECT id, email, first_name, last_name FROM voters WHERE email LIKE 'new_user_e13_%' ORDER BY id;")
if result.returncode == 0:
print("\n" + "="*60)
print("👤 UTILISATEURS SPÉCIAUX:")
print("="*60)
print(result.stdout)
print("\n✅ Vous pouvez maintenant vous connecter avec:")
print(" Email: new_user_e13_192@voting.local")
print(" Mot de passe: epita1234")
print(" Votes: 10 historiques + 4 actifs + 4 futurs")
print(" Élection sans vote: Active Election 3 (ID 13)")
print("="*60)