a116b30df7
[ui] registrace.php – použit společný JS pro kontrolu hesla [ui] nove_heslo.php – použit společný JS pro kontrolu hesla, opraven odkaz na reset [ui] admin.php – použit společný JS pro kontrolu hesla [FÁZE-1][install] Vícekrokový průběh instalace, použit společný JS pro kontrolu hesla
402 lines
14 KiB
PHP
402 lines
14 KiB
PHP
<?php
|
||
// ============================================================
|
||
// INSTALAČNÍ SKRIPT
|
||
// ============================================================
|
||
// Tento skript spusť JEDNOU po nahrání souborů na server.
|
||
// Vytvoří všechny potřebné tabulky v databázi a prvního
|
||
// administrátora.
|
||
//
|
||
// Průběh:
|
||
// Krok 1 – pokus o automatické vytvoření tabulek
|
||
// Krok 2 – pokud selže, zobrazí SQL pro ruční zadání do phpMyAdmin
|
||
// Krok 3 – ověření, že tabulky existují a mají správnou strukturu
|
||
// Krok 4 – formulář pro vytvoření prvního admina + zámek
|
||
// Krok 5 – instalace úspěšně dokončena
|
||
//
|
||
// Po úspěšné instalaci se vytvoří soubor install.lock
|
||
// a tento skript již nepůjde spustit znovu.
|
||
// ============================================================
|
||
|
||
require_once __DIR__ . '/config.php';
|
||
require_once __DIR__ . '/db.php';
|
||
|
||
// ------------------------------------------------------------
|
||
// KONTROLA: Proběhla už instalace?
|
||
// ------------------------------------------------------------
|
||
|
||
$lock_soubor = __DIR__ . '/install.lock';
|
||
|
||
if (file_exists($lock_soubor)) {
|
||
die('<!DOCTYPE html><html lang="cs"><head><meta charset="UTF-8">
|
||
<title>Instalace</title></head><body>
|
||
<p>Instalace již proběhla.</p>
|
||
<p>Pokud chceš instalaci opakovat, smaž soubor
|
||
<code>auth/install.lock</code>. Pozor – tím přijdeš o všechna data!</p>
|
||
</body></html>');
|
||
}
|
||
|
||
// ------------------------------------------------------------
|
||
// SQL PŘÍKAZY PRO VYTVOŘENÍ TABULEK
|
||
// ------------------------------------------------------------
|
||
// Definujeme je jako pole – použijeme je jak pro automatické
|
||
// spuštění, tak pro zobrazení uživateli k ručnímu zadání.
|
||
|
||
$sql_tabulky = [
|
||
|
||
'auth_users' => "CREATE TABLE IF NOT EXISTS `" . DB_TABULKA_UZIVATELE . "` (
|
||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||
`email` VARCHAR(255) NOT NULL,
|
||
`heslo` VARCHAR(255) NOT NULL,
|
||
`admin` TINYINT(1) NOT NULL DEFAULT 0,
|
||
`vytvoreno` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `email` (`email`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||
|
||
'auth_remember_tokens' => "CREATE TABLE IF NOT EXISTS `" . DB_TABULKA_TOKENY . "` (
|
||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||
`uzivatel_id` INT UNSIGNED NOT NULL,
|
||
`selector` VARCHAR(32) NOT NULL,
|
||
`token_hash` VARCHAR(255) NOT NULL,
|
||
`expiruje` DATETIME NOT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `selector` (`selector`),
|
||
FOREIGN KEY (`uzivatel_id`)
|
||
REFERENCES `" . DB_TABULKA_UZIVATELE . "` (`id`)
|
||
ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||
|
||
'auth_brute_force' => "CREATE TABLE IF NOT EXISTS `" . DB_TABULKA_BRUTE . "` (
|
||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||
`ip_adresa` VARCHAR(45) NOT NULL,
|
||
`email` VARCHAR(255) NOT NULL,
|
||
`cas` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`id`),
|
||
KEY `ip_adresa` (`ip_adresa`),
|
||
KEY `email` (`email`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||
|
||
'auth_password_resets' => "CREATE TABLE IF NOT EXISTS `" . DB_TABULKA_RESET . "` (
|
||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||
`uzivatel_id` INT UNSIGNED NOT NULL,
|
||
`token_hash` VARCHAR(255) NOT NULL,
|
||
`expiruje` DATETIME NOT NULL,
|
||
PRIMARY KEY (`id`),
|
||
FOREIGN KEY (`uzivatel_id`)
|
||
REFERENCES `" . DB_TABULKA_UZIVATELE . "` (`id`)
|
||
ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
|
||
|
||
];
|
||
|
||
// Tabulka služby je volitelná
|
||
if (DB_TABULKA_SLUZBA !== '') {
|
||
$sql_tabulky['sluzba'] = "CREATE TABLE IF NOT EXISTS `" . DB_TABULKA_SLUZBA . "` (
|
||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||
`uzivatel_id` INT UNSIGNED NOT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uzivatel_id` (`uzivatel_id`),
|
||
FOREIGN KEY (`uzivatel_id`)
|
||
REFERENCES `" . DB_TABULKA_UZIVATELE . "` (`id`)
|
||
ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
|
||
}
|
||
|
||
// ------------------------------------------------------------
|
||
// POMOCNÁ FUNKCE: Ověření existence tabulek
|
||
// ------------------------------------------------------------
|
||
// Zkontroluje, zda všechny potřebné tabulky existují v DB.
|
||
// Vrací pole chybějících tabulek (prázdné = vše OK).
|
||
|
||
function zkontroluj_tabulky(PDO $pdo): array
|
||
{
|
||
// Zjistíme, které tabulky existují v aktuální databázi
|
||
$stmt = $pdo->query("SHOW TABLES");
|
||
$existuje = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||
|
||
$potrebne = [
|
||
DB_TABULKA_UZIVATELE,
|
||
DB_TABULKA_TOKENY,
|
||
DB_TABULKA_BRUTE,
|
||
DB_TABULKA_RESET,
|
||
];
|
||
|
||
if (DB_TABULKA_SLUZBA !== '') {
|
||
$potrebne[] = DB_TABULKA_SLUZBA;
|
||
}
|
||
|
||
// Vrátíme seznam tabulek, které chybí
|
||
return array_diff($potrebne, $existuje);
|
||
}
|
||
|
||
// ------------------------------------------------------------
|
||
// URČENÍ AKTUÁLNÍHO KROKU
|
||
// ------------------------------------------------------------
|
||
|
||
$krok = 1;
|
||
$chyba = '';
|
||
|
||
// Krok se přenáší přes skryté pole ve formuláři
|
||
$krok_z_post = (int) ($_POST['krok'] ?? 0);
|
||
|
||
// ------------------------------------------------------------
|
||
// ZPRACOVÁNÍ AKCÍ
|
||
// ------------------------------------------------------------
|
||
|
||
// == KROK 1: Pokus o automatické vytvoření tabulek ============
|
||
if ($krok_z_post === 0 || $krok_z_post === 1) {
|
||
|
||
$auto_ok = true;
|
||
|
||
foreach ($sql_tabulky as $nazev => $sql) {
|
||
try {
|
||
$pdo->exec($sql);
|
||
} catch (PDOException $e) {
|
||
// Automatické vytvoření selhalo – uživatel nemá práva
|
||
$auto_ok = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ($auto_ok) {
|
||
// Tabulky byly vytvořeny automaticky – přeskočíme na krok 4
|
||
$krok = 4;
|
||
} else {
|
||
// Nemáme práva – přejdeme na krok 2 (ruční SQL)
|
||
$krok = 2;
|
||
}
|
||
}
|
||
|
||
// == KROK 3: Ověření tabulek po ručním zadání SQL =============
|
||
elseif ($krok_z_post === 3) {
|
||
|
||
$chybejici = zkontroluj_tabulky($pdo);
|
||
|
||
if (empty($chybejici)) {
|
||
// Všechny tabulky existují – přejdeme na krok 4
|
||
$krok = 4;
|
||
} else {
|
||
// Stále chybí tabulky – zůstaneme na kroku 2/3
|
||
$krok = 3;
|
||
$chyba = 'Následující tabulky stále chybí: '
|
||
. implode(', ', $chybejici)
|
||
. '. Zkontroluj, zda jsi SQL správně zadal do phpMyAdmin.';
|
||
}
|
||
}
|
||
|
||
// == KROK 4: Vytvoření prvního admina =========================
|
||
elseif ($krok_z_post === 4) {
|
||
|
||
$email = trim($_POST['email'] ?? '');
|
||
$heslo = $_POST['heslo'] ?? '';
|
||
$heslo2 = $_POST['heslo2'] ?? '';
|
||
|
||
// Validace
|
||
if (empty($email)) {
|
||
$chyba = 'Email nesmí být prázdný.';
|
||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||
$chyba = 'Email není platná emailová adresa.';
|
||
} elseif (empty($heslo)) {
|
||
$chyba = 'Heslo nesmí být prázdné.';
|
||
} elseif (mb_strlen($heslo) < HESLO_MIN_DELKA) {
|
||
$chyba = 'Heslo musí mít alespoň ' . HESLO_MIN_DELKA . ' znaků.';
|
||
} elseif ($heslo !== $heslo2) {
|
||
$chyba = 'Hesla se neshodují.';
|
||
}
|
||
|
||
if (empty($chyba)) {
|
||
|
||
try {
|
||
$heslo_hash = password_hash($heslo, PASSWORD_DEFAULT);
|
||
|
||
$stmt = $pdo->prepare("
|
||
INSERT INTO `" . DB_TABULKA_UZIVATELE . "`
|
||
(`email`, `heslo`, `admin`)
|
||
VALUES
|
||
(:email, :heslo, 1)
|
||
");
|
||
$stmt->execute([
|
||
':email' => $email,
|
||
':heslo' => $heslo_hash,
|
||
]);
|
||
|
||
$novy_id = $pdo->lastInsertId();
|
||
|
||
if (DB_TABULKA_SLUZBA !== '') {
|
||
$stmt2 = $pdo->prepare("
|
||
INSERT INTO `" . DB_TABULKA_SLUZBA . "`
|
||
(`uzivatel_id`)
|
||
VALUES
|
||
(:uzivatel_id)
|
||
");
|
||
$stmt2->execute([':uzivatel_id' => $novy_id]);
|
||
}
|
||
|
||
// Vytvoříme zámek – instalace je hotová
|
||
file_put_contents($lock_soubor, 'Instalace proběhla: ' . date('Y-m-d H:i:s'));
|
||
|
||
$krok = 5; // krok 5 = úspěšné dokončení
|
||
|
||
} catch (PDOException $e) {
|
||
error_log('Chyba při instalaci (admin): ' . $e->getMessage());
|
||
$chyba = 'Při vytváření admina došlo k chybě databáze. Zkontroluj PHP error log.';
|
||
$krok = 4;
|
||
}
|
||
|
||
} else {
|
||
// Validace selhala – zůstaneme na kroku 4
|
||
$krok = 4;
|
||
}
|
||
}
|
||
|
||
// ------------------------------------------------------------
|
||
// SESTAVENÍ SQL TEXTU PRO ZOBRAZENÍ UŽIVATELI (krok 2 a 3)
|
||
// ------------------------------------------------------------
|
||
|
||
$sql_pro_zobrazeni = implode(";\n\n", $sql_tabulky) . ';';
|
||
|
||
// ------------------------------------------------------------
|
||
// HTML VÝSTUP
|
||
// ------------------------------------------------------------
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="cs">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Instalace – <?php echo htmlspecialchars(PROJEKT_NAZEV); ?></title>
|
||
</head>
|
||
<body>
|
||
|
||
<h1>Instalace systému přihlašování</h1>
|
||
<h2><?php echo htmlspecialchars(PROJEKT_NAZEV); ?></h2>
|
||
|
||
<?php if (!empty($chyba)): ?>
|
||
<p><strong>Chyba: <?php echo htmlspecialchars($chyba); ?></strong></p>
|
||
<?php endif; ?>
|
||
|
||
<?php
|
||
// ============================================================
|
||
// KROK 2: Ruční SQL pro phpMyAdmin
|
||
// ============================================================
|
||
if ($krok === 2): ?>
|
||
|
||
<p>Nepodařilo se automaticky vytvořit tabulky v databázi –
|
||
pravděpodobně nemá databázový uživatel dostatečná oprávnění
|
||
(CREATE TABLE).</p>
|
||
|
||
<p><strong>Postup:</strong></p>
|
||
<ol>
|
||
<li>Zkopíruj SQL níže.</li>
|
||
<li>Otevři phpMyAdmin a vyber svou databázi
|
||
(<code><?php echo htmlspecialchars(DB_NAME); ?></code>).</li>
|
||
<li>Klikni na záložku <strong>SQL</strong>, vlož SQL a spusť ho.</li>
|
||
<li>Vrať se sem a klikni na tlačítko níže.</li>
|
||
</ol>
|
||
|
||
<textarea rows="30" cols="100" onclick="this.select();"
|
||
style="font-family: monospace; font-size: 13px;"
|
||
><?php echo htmlspecialchars($sql_pro_zobrazeni); ?></textarea>
|
||
|
||
<p>
|
||
<form method="POST" action="">
|
||
<input type="hidden" name="krok" value="3">
|
||
<button type="submit">Zkontrolovat tabulky a pokračovat</button>
|
||
</form>
|
||
</p>
|
||
|
||
<?php
|
||
// ============================================================
|
||
// KROK 3: Tabulky stále chybí (chyba je zobrazena výše)
|
||
// ============================================================
|
||
elseif ($krok === 3): ?>
|
||
|
||
<p>Tabulky ještě nejsou v pořádku. Zkontroluj phpMyAdmin a zkus to znovu.</p>
|
||
|
||
<textarea rows="30" cols="100" onclick="this.select();"
|
||
style="font-family: monospace; font-size: 13px;"
|
||
><?php echo htmlspecialchars($sql_pro_zobrazeni); ?></textarea>
|
||
|
||
<p>
|
||
<form method="POST" action="">
|
||
<input type="hidden" name="krok" value="3">
|
||
<button type="submit">Zkontrolovat tabulky znovu</button>
|
||
</form>
|
||
</p>
|
||
|
||
<?php
|
||
// ============================================================
|
||
// KROK 4: Formulář pro vytvoření prvního admina
|
||
// ============================================================
|
||
elseif ($krok === 4): ?>
|
||
|
||
<p><strong>Tabulky jsou připraveny.</strong>
|
||
Nyní vytvoř prvního administrátora.</p>
|
||
|
||
<form method="POST" action="">
|
||
<input type="hidden" name="krok" value="4">
|
||
|
||
<p>
|
||
<label for="email">Email administrátora:</label><br>
|
||
<input
|
||
type="email"
|
||
id="email"
|
||
name="email"
|
||
value="<?php echo htmlspecialchars($_POST['email'] ?? ''); ?>"
|
||
required
|
||
>
|
||
</p>
|
||
|
||
<p>
|
||
<label for="heslo">Heslo administrátora:</label><br>
|
||
<input
|
||
type="password"
|
||
id="heslo"
|
||
name="heslo"
|
||
required
|
||
>
|
||
<br>
|
||
<span id="heslo-sila">Síla hesla: zadej heslo</span>
|
||
</p>
|
||
|
||
<p>
|
||
<label for="heslo2">Heslo znovu (pro ověření):</label><br>
|
||
<input
|
||
type="password"
|
||
id="heslo2"
|
||
name="heslo2"
|
||
required
|
||
>
|
||
</p>
|
||
|
||
<p>
|
||
<button type="submit" id="tlacitko-odeslat" disabled>
|
||
Dokončit instalaci
|
||
</button>
|
||
<span id="tlacitko-duvod"> (čekám na dostatečně silné heslo)</span>
|
||
</p>
|
||
|
||
</form>
|
||
|
||
<?php
|
||
// ============================================================
|
||
// KROK 5: Instalace úspěšně dokončena
|
||
// ============================================================
|
||
elseif ($krok === 5): ?>
|
||
|
||
<p><strong>Instalace proběhla úspěšně!</strong></p>
|
||
<p>Tabulky byly vytvořeny a první administrátor byl založen.</p>
|
||
<p>Byl vytvořen soubor <code>auth/install.lock</code> –
|
||
instalaci již nelze spustit znovu.</p>
|
||
<p><a href="<?php echo htmlspecialchars(AUTH_LOGIN_URL); ?>">Přejít na přihlášení</a></p>
|
||
|
||
<?php endif; ?>
|
||
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"></script>
|
||
<script>
|
||
var AUTH_HESLO_MIN_SILA = <?php echo (int) HESLO_MIN_SILA; ?>;
|
||
var AUTH_HESLO_MIN_DELKA = <?php echo (int) HESLO_MIN_DELKA; ?>;
|
||
</script>
|
||
<script src="<?php echo htmlspecialchars(PROJEKT_URL); ?>/auth/js/heslo-sila.js"></script>
|
||
|
||
</body>
|
||
</html>
|