You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

364 lines
19 KiB
PHP

<?php
require_once 'includes/db.php';
require_once 'includes/auth.php';
checkAuth();
checkAdmin();
$message = '';
$default_settings = [
'company_1_name' => 'Moje Przedsiebiorstwo IT',
'company_1_details' => 'ul. Glowna 1, 00-000 Warszawa | NIP: 0987654321',
'company_2_name' => 'Spolka Celowa Sp. z o.o.',
'company_2_details' => 'ul. Przykladowa 10, 00-000 Warszawa | NIP: 1234567890 | KRS: 0000123456'
];
foreach ($default_settings as $key => $val) {
$stmt = $pdo->prepare("INSERT IGNORE INTO " . DB_PREFIX . "settings (setting_key, setting_value) VALUES (?, ?)");
$stmt->execute([$key, $val]);
}
if ($_SERVER["REQUEST_METHOD"] === "POST") {
requireCsrfToken();
if (isset($_FILES['logo'])) {
if ($_FILES['logo']['error'] === 0) {
$upload_dir = 'uploads/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0755, true);
}
$tmpPath = $_FILES['logo']['tmp_name'];
$mime = mime_content_type($tmpPath);
$allowedMimes = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
];
if (isset($allowedMimes[$mime]) && @getimagesize($tmpPath) !== false) {
$new_name = 'logo_' . bin2hex(random_bytes(8)) . '.' . $allowedMimes[$mime];
$dest_path = $upload_dir . $new_name;
if (move_uploaded_file($tmpPath, $dest_path)) {
$stmt = $pdo->prepare("REPLACE INTO " . DB_PREFIX . "settings (setting_key, setting_value) VALUES ('logo_path', ?)");
$stmt->execute([$dest_path]);
$message = "<div class='alert alert-success'>Pomyslnie zaktualizowano logo.</div>";
} else {
$message = "<div class='alert alert-danger'>Nie udalo sie zapisac pliku.</div>";
}
} else {
$message = "<div class='alert alert-warning'>Dozwolone sa tylko prawidlowe pliki JPG, PNG i GIF.</div>";
}
}
} elseif (isset($_POST['action']) && $_POST['action'] === 'update_company_settings') {
$settings_to_update = ['company_1_name', 'company_1_details', 'company_2_name', 'company_2_details'];
try {
$pdo->beginTransaction();
$update_stmt = $pdo->prepare("UPDATE " . DB_PREFIX . "settings SET setting_value = ? WHERE setting_key = ?");
foreach ($settings_to_update as $key) {
if (isset($_POST[$key])) {
$update_stmt->execute([trim($_POST[$key]), $key]);
}
}
$pdo->commit();
$message = "<div class='alert alert-success'>Ustawienia firmowe zostaly zapisane.</div>";
} catch (PDOException $e) {
$pdo->rollBack();
error_log($e->getMessage());
$message = "<div class='alert alert-danger'>Nie udalo sie zapisac ustawien.</div>";
}
} elseif (isset($_POST['add_user'])) {
$new_user = trim($_POST['new_username'] ?? '');
$new_pass = $_POST['new_password'] ?? '';
$new_role = $_POST['new_role'] ?? 'user';
if ($new_user !== '' && $new_pass !== '') {
try {
$new_email = trim($_POST['new_email'] ?? '');
$hashed_pass = password_hash($new_pass, PASSWORD_BCRYPT);
$stmt = $pdo->prepare("INSERT INTO " . DB_PREFIX . "users (username, email, password, role) VALUES (?, ?, ?, ?)");
$stmt->execute([$new_user, $new_email !== '' ? $new_email : null, $hashed_pass, $new_role === 'admin' ? 'admin' : 'user']);
$message = "<div class='alert alert-success'>Dodano nowego uzytkownika: <strong>" . e($new_user) . "</strong></div>";
} catch (PDOException $e) {
error_log($e->getMessage());
$message = "<div class='alert alert-danger'>Nie udalo sie dodac uzytkownika.</div>";
}
}
} elseif (isset($_POST['reset_password'])) {
$user_id = (int)($_POST['user_id'] ?? 0);
$new_pass = $_POST['new_password'] ?? '';
if ($user_id > 0 && $new_pass !== '') {
$hashed_pass = password_hash($new_pass, PASSWORD_BCRYPT);
$stmt = $pdo->prepare("UPDATE " . DB_PREFIX . "users SET password = ? WHERE id = ?");
$stmt->execute([$hashed_pass, $user_id]);
$message = "<div class='alert alert-info'>Zmieniono haslo dla wybranego uzytkownika.</div>";
}
} elseif (isset($_POST['delete_user'])) {
$id_to_delete = (int)($_POST['user_id'] ?? 0);
if ($id_to_delete !== (int)$_SESSION['user_id']) {
$stmt = $pdo->prepare("DELETE FROM " . DB_PREFIX . "users WHERE id = ?");
$stmt->execute([$id_to_delete]);
$message = "<div class='alert alert-success'>Uzytkownik zostal pomyslnie usuniety.</div>";
} else {
$message = "<div class='alert alert-warning'>Nie mozesz usunac wlasnego konta administratora.</div>";
}
}
}
$users = $pdo->query("SELECT id, username, email, role, oauth_provider, last_login_at FROM " . DB_PREFIX . "users ORDER BY username ASC")->fetchAll();
$settings = [];
try {
$settings = $pdo->query("SELECT setting_key, setting_value FROM " . DB_PREFIX . "settings")->fetchAll(PDO::FETCH_KEY_PAIR);
} catch (PDOException $e) {
error_log($e->getMessage());
}
$current_logo = $settings['logo_path'] ?? '';
?>
<!DOCTYPE html>
<html lang="pl" data-bs-theme="light" id="mainHtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Panel administratora - <?php echo e(defined('APP_NAME') ? APP_NAME : 'System'); ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<style>
.logo-img { max-height: 40px; width: auto; }
.transition-colors { transition: background-color 0.3s ease, color 0.3s ease; }
</style>
</head>
<body class="bg-body-tertiary transition-colors">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4 shadow-sm">
<div class="container">
<a class="navbar-brand d-flex align-items-center" href="index.php">
<?php if ($current_logo && file_exists($current_logo)): ?>
<img src="<?php echo e($current_logo); ?>" alt="Logo" class="logo-img me-2">
<?php else: ?>
<span class="me-2">IT</span>
<?php endif; ?>
<strong><?php echo e(defined('APP_NAME') ? APP_NAME : 'System IT'); ?></strong>
</a>
<div class="navbar-nav ms-auto align-items-center">
<button class="btn btn-sm btn-outline-secondary me-3" onclick="toggleDarkMode()">
<i class="bi bi-moon-stars" id="themeIcon"></i>
</button>
<span class="nav-link text-light me-3 small">Admin: <strong><?php echo e($_SESSION['username']); ?></strong></span>
<a class="btn btn-outline-light btn-sm me-2" href="index.php"><i class="bi bi-arrow-left"></i> Powrot do zamowien</a>
<a class="btn btn-outline-danger btn-sm" href="logout.php">Wyloguj</a>
</div>
</div>
</nav>
<div class="container pb-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>Panel zarzadzania systemem</h2>
</div>
<?php echo $message; ?>
<div class="row">
<div class="col-md-5 mb-4">
<div class="card shadow-sm mb-4 border-0">
<div class="card-header bg-secondary text-white">
<i class="bi bi-image"></i> Ustawienia wizualne
</div>
<div class="card-body">
<form method="POST" enctype="multipart/form-data">
<?php echo csrfInput(); ?>
<div class="text-center mb-3">
<?php if ($current_logo && file_exists($current_logo)): ?>
<img src="<?php echo e($current_logo); ?>" class="img-thumbnail" style="max-height: 80px;" alt="Logo">
<?php else: ?>
<div class="text-muted small">Brak wgranego logo</div>
<?php endif; ?>
</div>
<div class="mb-3">
<label class="form-label small">Zmien logotyp (PNG/JPG/GIF)</label>
<input type="file" name="logo" class="form-control form-control-sm" accept=".png,.jpg,.jpeg,.gif" required>
</div>
<button type="submit" class="btn btn-dark w-100 btn-sm">Wgraj plik na serwer</button>
</form>
</div>
</div>
<div class="card shadow-sm border-0 mb-4">
<div class="card-header bg-info text-dark fw-bold">
<i class="bi bi-buildings"></i> Dane firm
</div>
<div class="card-body">
<form method="POST">
<?php echo csrfInput(); ?>
<input type="hidden" name="action" value="update_company_settings">
<div class="mb-3">
<label class="form-label small fw-bold text-primary">1. Przedsiebiorstwo (Nazwa)</label>
<input type="text" name="company_1_name" class="form-control form-control-sm border-primary" value="<?php echo e($settings['company_1_name'] ?? ''); ?>" required>
</div>
<div class="mb-4">
<label class="form-label small fw-bold text-primary">Przedsiebiorstwo (Adres/NIP)</label>
<input type="text" name="company_1_details" class="form-control form-control-sm" value="<?php echo e($settings['company_1_details'] ?? ''); ?>">
</div>
<div class="mb-3 border-top pt-3">
<label class="form-label small fw-bold text-success">2. Spolka (Nazwa)</label>
<input type="text" name="company_2_name" class="form-control form-control-sm border-success" value="<?php echo e($settings['company_2_name'] ?? ''); ?>" required>
</div>
<div class="mb-4">
<label class="form-label small fw-bold text-success">Spolka (Adres/NIP/KRS)</label>
<input type="text" name="company_2_details" class="form-control form-control-sm" value="<?php echo e($settings['company_2_details'] ?? ''); ?>">
</div>
<button type="submit" class="btn btn-info w-100 btn-sm fw-bold text-dark"><i class="bi bi-save"></i> Zapisz stopki firm</button>
</form>
</div>
</div>
<div class="card shadow-sm border-0">
<div class="card-header bg-primary text-white">
<i class="bi bi-person-plus"></i> Dodaj pracownika
</div>
<div class="card-body">
<form method="POST">
<?php echo csrfInput(); ?>
<div class="mb-3">
<label class="form-label small">Login uzytkownika</label>
<input type="text" name="new_username" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label small">Haslo poczatkowe</label>
<input type="password" name="new_password" class="form-control" required minlength="8">
</div>
<div class="mb-3">
<label class="form-label small">Email do powiazania z Microsoft 365</label>
<input type="email" name="new_email" class="form-control" placeholder="np. user@firma.pl">
</div>
<div class="mb-3">
<label class="form-label small">Rola w systemie</label>
<select name="new_role" class="form-select">
<option value="user">Zwykly pracownik</option>
<option value="admin">Administrator</option>
</select>
</div>
<button type="submit" name="add_user" class="btn btn-primary w-100"><i class="bi bi-check2-circle"></i> Utworz konto</button>
</form>
</div>
</div>
</div>
<div class="col-md-7">
<div class="card shadow-sm text-nowrap border-0">
<div class="card-header bg-dark text-white">
<i class="bi bi-people"></i> Zarejestrowani pracownicy
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0 align-middle">
<thead class="table-light">
<tr>
<th class="px-3">ID</th>
<th>Login</th>
<th>Email</th>
<th>Uprawnienia</th>
<th>Zrodlo</th>
<th class="text-end px-4">Zarzadzaj</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $u): ?>
<tr>
<td class="px-3 text-muted"><?php echo (int)$u['id']; ?></td>
<td><strong><?php echo e($u['username']); ?></strong></td>
<td class="small text-muted"><?php echo e($u['email'] ?? ''); ?></td>
<td>
<span class="badge <?php echo $u['role'] === 'admin' ? 'bg-danger' : 'bg-primary'; ?>">
<?php echo $u['role'] === 'admin' ? 'Administrator' : 'Uzytkownik'; ?>
</span>
</td>
<td>
<span class="badge <?php echo $u['oauth_provider'] === 'microsoft' ? 'bg-success' : 'bg-secondary'; ?>">
<?php echo $u['oauth_provider'] === 'microsoft' ? 'Microsoft 365' : 'Lokalne'; ?>
</span>
</td>
<td class="text-end px-3">
<button class="btn btn-sm btn-outline-info me-1" data-bs-toggle="modal" data-bs-target="#resetModal<?php echo (int)$u['id']; ?>">
<i class="bi bi-shield-lock"></i> Reset hasla
</button>
<?php if ((int)$u['id'] !== (int)$_SESSION['user_id']): ?>
<form method="POST" class="d-inline" onsubmit="return confirm('Czy na pewno chcesz bezpowrotnie usunac to konto?')">
<?php echo csrfInput(); ?>
<input type="hidden" name="user_id" value="<?php echo (int)$u['id']; ?>">
<button type="submit" name="delete_user" class="btn btn-sm btn-outline-danger">
<i class="bi bi-trash"></i> Usun
</button>
</form>
<?php else: ?>
<button class="btn btn-sm btn-outline-secondary disabled"><i class="bi bi-person-check"></i> To ty</button>
<?php endif; ?>
<div class="modal fade" id="resetModal<?php echo (int)$u['id']; ?>" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-sm modal-dialog-centered">
<div class="modal-content text-start">
<form method="POST">
<?php echo csrfInput(); ?>
<div class="modal-header bg-light">
<h6 class="modal-title"><i class="bi bi-key"></i> Nowe haslo: <?php echo e($u['username']); ?></h6>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" name="user_id" value="<?php echo (int)$u['id']; ?>">
<label class="form-label small">Wpisz nowe haslo:</label>
<input type="password" name="new_password" class="form-control" required minlength="8">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Anuluj</button>
<button type="submit" name="reset_password" class="btn btn-info btn-sm text-white">Zapisz haslo</button>
</div>
</form>
</div>
</div>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function toggleDarkMode() {
const html = document.getElementById('mainHtml');
const icon = document.getElementById('themeIcon');
const currentTheme = html.getAttribute('data-bs-theme');
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
html.setAttribute('data-bs-theme', newTheme);
icon.classList.toggle('bi-moon-stars', newTheme === 'light');
icon.classList.toggle('bi-sun', newTheme === 'dark');
localStorage.setItem('theme', newTheme);
}
if (localStorage.getItem('theme') === 'dark') {
document.getElementById('mainHtml').setAttribute('data-bs-theme', 'dark');
document.getElementById('themeIcon').classList.replace('bi-moon-stars', 'bi-sun');
}
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>