| Server IP : 188.114.96.3 / Your IP : 216.73.216.143 Web Server : Apache System : Linux sv058.home.net.pl 6.8.2 husak_dirty_pages_fix #1 SMP PREEMPT_DYNAMIC Tue Apr 2 22:06:51 CEST 2024 x86_64 User : ( 3194769) PHP Version : 8.5.12 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /polana/admin/ |
Upload File : |
<?php
declare(strict_types=1);
require_once dirname(__DIR__) . '/includes/functions.php';
require_admin_role();
ensure_operations_schema();
$id = (int)($_GET['id'] ?? $_POST['id'] ?? 0);
$currentAdmin = admin_user();
$user = [
'id' => 0,
'username' => '',
'name' => '',
'role' => 'editor',
'active' => 1,
];
if ($id > 0) {
$stmt = db()->prepare(
'SELECT id, username, name, role, active, staff_pin_hash
FROM users WHERE id = ? LIMIT 1'
);
$stmt->execute([$id]);
$user = $stmt->fetch();
if (!$user) {
http_response_code(404);
exit('Nie znaleziono użytkownika.');
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$username = trim((string)($_POST['username'] ?? ''));
$name = trim((string)($_POST['name'] ?? ''));
$role = (string)($_POST['role'] ?? 'editor');
$active = (int)($_POST['active'] ?? 1) === 1 ? 1 : 0;
$password = (string)($_POST['password'] ?? '');
$staffPin = preg_replace('/\D+/', '', (string)($_POST['staff_pin'] ?? ''));
try {
if (!preg_match('/^[A-Za-z0-9._-]{3,100}$/', $username)) {
throw new RuntimeException('Login: minimum 3 znaki, tylko litery, cyfry, kropka, _ i -.');
}
if (!in_array($role, ['admin', 'editor', 'manager', 'waiter', 'kitchen'], true)) {
throw new RuntimeException('Nieprawidłowa rola.');
}
if ($id > 0 && $currentAdmin && (int)$currentAdmin['id'] === $id && $active !== 1) {
throw new RuntimeException('Nie możesz wyłączyć własnego konta.');
}
if ($id > 0 && $user['role'] === 'admin' && ($role !== 'admin' || $active !== 1)) {
$stmt = db()->prepare("SELECT COUNT(*) FROM users WHERE role='admin' AND active=1 AND id<>?");
$stmt->execute([$id]);
if ((int)$stmt->fetchColumn() < 1) {
throw new RuntimeException('Musi pozostać co najmniej jeden aktywny administrator.');
}
}
if ($id === 0) {
if (mb_strlen($password, 'UTF-8') < 10) {
throw new RuntimeException('Nowe konto musi mieć hasło min. 10 znaków.');
}
$stmt = db()->prepare(
'INSERT INTO users (username, password_hash, name, role, active)
VALUES (?, ?, ?, ?, ?)'
);
$stmt->execute([
$username,
password_hash($password, PASSWORD_DEFAULT),
$name !== '' ? $name : null,
$role,
$active,
]);
$id = (int)db()->lastInsertId();
if ($staffPin !== '') {
if (!in_array($role, ['waiter','kitchen'], true)) {
throw new RuntimeException('PIN można ustawić tylko dla kelnera lub kuchni.');
}
staff_pin_set($id, $staffPin);
}
admin_log('user_create', 'Dodano użytkownika: ' . $username);
flash('success', 'Użytkownik został dodany.');
} else {
$check = db()->prepare('SELECT id FROM users WHERE username = ? AND id <> ? LIMIT 1');
$check->execute([$username, $id]);
if ($check->fetch()) {
throw new RuntimeException('Taki login już istnieje.');
}
$sql = 'UPDATE users SET username=?, name=?, role=?, active=?';
$params = [$username, $name !== '' ? $name : null, $role, $active];
if ($password !== '') {
if (mb_strlen($password, 'UTF-8') < 10) {
throw new RuntimeException('Nowe hasło musi mieć minimum 10 znaków.');
}
$sql .= ', password_hash=?';
$params[] = password_hash($password, PASSWORD_DEFAULT);
}
$sql .= ' WHERE id=?';
$params[] = $id;
$stmt = db()->prepare($sql);
$stmt->execute($params);
if ($staffPin !== '') {
if (!in_array($role, ['waiter','kitchen'], true)) {
throw new RuntimeException('PIN można ustawić tylko dla kelnera lub kuchni.');
}
staff_pin_set($id, $staffPin);
}
admin_log('user_update', 'Zmieniono użytkownika: ' . $username);
flash('success', 'Użytkownik został zapisany.');
}
redirect('/admin/users.php');
} catch (Throwable $e) {
flash('error', $e->getMessage());
redirect('/admin/user.php' . ($id > 0 ? '?id=' . $id : ''));
}
}
render_admin_header($id > 0 ? 'Edytuj użytkownika' : 'Nowy użytkownik');
?>
<div class="admin-title-row">
<div>
<h1><?= $id > 0 ? 'Edytuj użytkownika' : 'Nowy użytkownik' ?></h1>
<p>Administrator może zarządzać kontami panelu.</p>
</div>
<a class="btn btn-light" href="/admin/users.php">← Użytkownicy</a>
</div>
<form class="form-card form-grid" method="post">
<?= csrf_field() ?>
<input type="hidden" name="id" value="<?= (int)$id ?>">
<label>
Login
<input name="username" value="<?= e($user['username']) ?>" required autocomplete="off">
</label>
<label>
Nazwa / imię
<input name="name" value="<?= e($user['name'] ?? '') ?>">
</label>
<label>
Rola
<select name="role">
<option value="admin" <?= $user['role'] === 'admin' ? 'selected' : '' ?>>Administrator</option>
<option value="editor" <?= $user['role'] === 'editor' ? 'selected' : '' ?>>Redaktor</option>
<option value="manager" <?= $user['role'] === 'manager' ? 'selected' : '' ?>>Manager</option>
<option value="waiter" <?= $user['role'] === 'waiter' ? 'selected' : '' ?>>Kelner</option>
<option value="kitchen" <?= $user['role'] === 'kitchen' ? 'selected' : '' ?>>Kuchnia</option>
</select>
</label>
<label>
Status
<select name="active">
<option value="1" <?= (int)$user['active'] === 1 ? 'selected' : '' ?>>Aktywny</option>
<option value="0" <?= (int)$user['active'] === 0 ? 'selected' : '' ?>>Wyłączony</option>
</select>
</label>
<label class="full">
<?= $id > 0 ? 'Nowe hasło – zostaw puste, żeby nie zmieniać' : 'Hasło' ?>
<input type="password" name="password" autocomplete="new-password" <?= $id === 0 ? 'required' : '' ?>>
</label>
<label class="full">
PIN terminala napiwków
<input
type="password"
name="staff_pin"
inputmode="numeric"
pattern="[0-9]{4}"
maxlength="4"
autocomplete="off"
placeholder="<?= $id > 0 && !empty($user['staff_pin_hash']) ? 'PIN ustawiony – wpisz nowy, aby zmienić' : '4 cyfry' ?>"
>
<small>4 cyfry. PIN musi być unikalny. Na terminalu napiwków identyfikuje kelnera.</small>
</label>
<div class="full">
<button class="btn btn-primary" type="submit">Zapisz użytkownika</button>
</div>
</form>
<?php render_admin_footer(); ?>