Files
webval/enseignant/export_passwords.php

412 lines
12 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Export Mots de Passe - Enseignant
* Génération et téléchargement des listes par classe
*/
define('APP_ROOT', dirname(__DIR__));
require_once APP_ROOT . '/config/config.php';
require_once APP_ROOT . '/config/database.php';
session_start();
// Vérifier authentification enseignant
if (!isLoggedIn() || !isEnseignant()) {
redirect('index.php');
}
// $auth = new Auth(); // MIGRÉ vers SessionManager
$user = currentUser();
$db = Database::getInstance();
$exporter = new PasswordExport();
// Actions
$action = $_GET['action'] ?? '';
$message = '';
$error = '';
if ($action === 'export_classe' && isset($_GET['id_classe'])) {
$result = $exporter->exportClassePasswords((int)$_GET['id_classe']);
if ($result['success']) {
$message = 'Export réussi : ' . $result['filename'];
} else {
$error = $result['message'];
}
}
if ($action === 'export_all') {
$results = $exporter->exportAllClasses();
$success_count = count(array_filter($results, fn($r) => $r['success']));
$message = "Export terminé : $success_count classe(s) exportée(s)";
}
if ($action === 'download' && isset($_GET['file'])) {
$exporter->downloadFile($_GET['file']);
}
if ($action === 'delete' && isset($_GET['file'])) {
if ($exporter->deleteFile($_GET['file'])) {
$message = 'Fichier supprimé';
} else {
$error = 'Erreur suppression';
}
}
// Récupérer classes
$classes = $db->fetchAll("
SELECT
c.id_classe,
c.nom_classe,
c.niveau,
c.type_classe,
COUNT(u.id_utilisateur) as nb_eleves
FROM classes c
LEFT JOIN utilisateurs u ON c.id_classe = u.id_classe AND u.actif = TRUE
WHERE c.actif = TRUE
GROUP BY c.id_classe
ORDER BY c.nom_classe
");
// Fichiers exportés
$files = $exporter->listExportedFiles();
// Déconnexion
if (isset($_GET['logout'])) {
$auth->logout();
redirect('index.php');
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Export Mots de Passe - Enseignant</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--primary: #667eea;
--secondary: #764ba2;
--success: #10b981;
--danger: #ef4444;
--warning: #f59e0b;
--gray-100: #f3f4f6;
--gray-200: #e5e7eb;
--gray-800: #1f2937;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: var(--gray-100);
color: var(--gray-800);
}
.header {
background: linear-gradient(135deg, var(--primary), var(--secondary));
color: white;
padding: 20px 0;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.header .container {
max-width: 1400px;
margin: 0 auto;
padding: 0 30px;
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
font-size: 1.8em;
}
.header .nav {
display: flex;
gap: 15px;
}
.header a {
color: white;
text-decoration: none;
padding: 10px 20px;
border-radius: 8px;
background: rgba(255,255,255,0.2);
transition: all 0.3s;
}
.header a:hover {
background: rgba(255,255,255,0.3);
}
.main-content {
max-width: 1400px;
margin: 40px auto;
padding: 0 30px;
}
.alert {
padding: 15px 20px;
border-radius: 8px;
margin-bottom: 20px;
}
.alert-success {
background: #d1fae5;
color: #065f46;
border-left: 4px solid var(--success);
}
.alert-error {
background: #fee2e2;
color: #991b1b;
border-left: 4px solid var(--danger);
}
.alert-warning {
background: #fef3c7;
color: #92400e;
border-left: 4px solid var(--warning);
}
.section {
background: white;
padding: 30px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
margin-bottom: 30px;
}
.section h2 {
margin-bottom: 20px;
color: var(--primary);
}
.btn {
padding: 10px 20px;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
transition: all 0.3s;
border: none;
cursor: pointer;
display: inline-block;
}
.btn-primary {
background: var(--primary);
color: white;
}
.btn-success {
background: var(--success);
color: white;
}
.btn-danger {
background: var(--danger);
color: white;
}
.btn-warning {
background: var(--warning);
color: white;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th {
background: var(--gray-100);
padding: 15px;
text-align: left;
font-weight: 600;
border-bottom: 2px solid var(--gray-200);
}
td {
padding: 15px;
border-bottom: 1px solid var(--gray-200);
}
tr:hover {
background: var(--gray-100);
}
.badge {
display: inline-block;
padding: 5px 12px;
border-radius: 20px;
font-size: 0.85em;
font-weight: 600;
}
.badge-regular { background: #dbeafe; color: #1e40af; }
.badge-soutien { background: #fef3c7; color: #92400e; }
.actions {
display: flex;
gap: 10px;
}
</style>
</head>
<body>
<header class="header">
<div class="container">
<h1>🔐 Export Mots de Passe</h1>
<div class="nav">
<a href="dashboard.php">← Retour Dashboard</a>
<a href="?logout=1">Déconnexion</a>
</div>
</div>
</header>
<main class="main-content">
<?php if ($message): ?>
<div class="alert alert-success"><?= h($message) ?></div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-error"><?= h($error) ?></div>
<?php endif; ?>
<div class="alert alert-warning">
⚠️ <strong>Sécurité :</strong> Les fichiers contiennent les mots de passe en clair.
Ils sont stockés hors du dossier web dans <code>/var/backups/mathematiques/classes_passwords/</code>
avec permissions 600 (lecture seule propriétaire).
</div>
<!-- Export par classe -->
<section class="section">
<h2>📚 Export par Classe</h2>
<p style="margin-bottom: 20px;">
Générez un fichier JSON contenant tous les logins et mots de passe pour chaque classe.
</p>
<div style="margin-bottom: 20px;">
<a href="?action=export_all" class="btn btn-success"
onclick="return confirm('Exporter toutes les classes ?')">
📤 Exporter Toutes les Classes
</a>
</div>
<table>
<thead>
<tr>
<th>Classe</th>
<th>Niveau</th>
<th>Type</th>
<th>Nb Élèves</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($classes as $classe): ?>
<tr>
<td><strong><?= h($classe['nom_classe']) ?></strong></td>
<td><?= h($classe['niveau']) ?></td>
<td>
<span class="badge badge-<?= $classe['type_classe'] ?>">
<?= $classe['type_classe'] === 'reguliere' ? 'Régulière' : 'Soutien' ?>
</span>
</td>
<td><?= $classe['nb_eleves'] ?></td>
<td class="actions">
<a href="?action=export_classe&id_classe=<?= $classe['id_classe'] ?>"
class="btn btn-primary">
Exporter
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</section>
<!-- Fichiers exportés -->
<section class="section">
<h2>📁 Fichiers Exportés</h2>
<?php if (empty($files)): ?>
<p style="color: #6b7280;">Aucun fichier exporté pour le moment.</p>
<?php else: ?>
<table>
<thead>
<tr>
<th>Fichier</th>
<th>Taille</th>
<th>Date Modification</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($files as $file): ?>
<tr>
<td><code><?= h($file['filename']) ?></code></td>
<td><?= number_format($file['size'] / 1024, 2) ?> KB</td>
<td><?= date('d/m/Y H:i', $file['date_modification']) ?></td>
<td class="actions">
<a href="?action=download&file=<?= urlencode($file['filename']) ?>"
class="btn btn-success">
⬇️ Télécharger
</a>
<a href="?action=delete&file=<?= urlencode($file['filename']) ?>"
class="btn btn-danger"
onclick="return confirm('Supprimer ce fichier ?')">
🗑️ Supprimer
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</section>
<!-- Informations -->
<section class="section">
<h2> Informations</h2>
<h3 style="margin-top: 20px;">Format du fichier JSON :</h3>
<pre style="background: var(--gray-100); padding: 15px; border-radius: 8px; overflow-x: auto;">
{
"classe": "2nde_A",
"niveau": "2nde",
"annee_scolaire": "2024-2025",
"type": "reguliere",
"date_export": "2025-10-23 10:30:00",
"nombre_eleves": 25,
"eleves": [
{
"login": "j.dupont",
"nom": "DUPONT",
"prenom": "Jean",
"date_naissance": "15/03/2009",
"mot_de_passe": "1503"
}
]
}
</pre>
<h3 style="margin-top: 20px;">Règles de génération :</h3>
<ul style="margin-left: 20px; line-height: 1.8;">
<li><strong>Login :</strong> p.nom (première lettre prénom + point + nom, minuscules)</li>
<li><strong>Doublons :</strong> ajout chiffre (j.dupont2, j.dupont3...)</li>
<li><strong>Mot de passe élève :</strong> JJMM (jour+mois naissance en 4 chiffres)</li>
<li><strong>Mot de passe enseignant :</strong> Personnalisé (n.boyer → math2025!)</li>
</ul>
</section>
</main>
</body>
</html>