commit 8349706c363664a81a33410febeb91598c60f4a4 Author: Adrian Hinz Date: Mon Jan 19 18:33:03 2026 +0100 First commit CMS diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..63dd6f7 --- /dev/null +++ b/.htaccess @@ -0,0 +1,48 @@ +# Włącz mod_rewrite +RewriteEngine On +RewriteBase /cms/ + +# Przekierowanie do HTTPS (opcjonalne, odkomentuj jeśli używasz SSL) +# RewriteCond %{HTTPS} off +# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + +# Jeśli plik lub katalog istnieje, wyświetl go +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d + +# W przeciwnym razie przekieruj do index.php +RewriteRule ^([a-zA-Z0-9-_]+)/?$ index.php?page=$1 [L,QSA] + +# Zabezpieczenia + + Order Allow,Deny + Deny from all + + +# Ochrona plików konfiguracyjnych + + Order Allow,Deny + Deny from all + + +# Włącz kompresję + + AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript + + +# Cache przeglądarki + + ExpiresActive On + ExpiresByType image/jpg "access plus 1 year" + ExpiresByType image/jpeg "access plus 1 year" + ExpiresByType image/gif "access plus 1 year" + ExpiresByType image/png "access plus 1 year" + ExpiresByType text/css "access plus 1 month" + ExpiresByType application/javascript "access plus 1 month" + + +# Zwiększ limit uploadów (jeśli możliwe) +php_value upload_max_filesize 10M +php_value post_max_size 10M +php_value max_execution_time 300 +php_value max_input_time 300 \ No newline at end of file diff --git a/admin/categories.php b/admin/categories.php new file mode 100644 index 0000000..9d5da1a --- /dev/null +++ b/admin/categories.php @@ -0,0 +1,384 @@ +prepare(" + UPDATE categories + SET name = ?, slug = ?, description = ?, parent_id = ? + WHERE id = ? + "); + $parentId = !empty($_POST['parent_id']) ? $_POST['parent_id'] : null; + + if ($stmt->execute([$_POST['name'], $slug, $_POST['description'], $parentId, $_POST['id']])) { + $message = 'Kategoria została zaktualizowana'; + logActivity('category_updated', 'category', $_POST['id']); + } + } else { + // Nowa kategoria + $stmt = $db->prepare(" + INSERT INTO categories (name, slug, description, parent_id) + VALUES (?, ?, ?, ?) + "); + $parentId = !empty($_POST['parent_id']) ? $_POST['parent_id'] : null; + + if ($stmt->execute([$_POST['name'], $slug, $_POST['description'], $parentId])) { + $message = 'Kategoria została dodana'; + logActivity('category_created', 'category', $db->lastInsertId()); + } + } + break; + + case 'delete': + $stmt = $db->prepare("DELETE FROM categories WHERE id = ?"); + if ($stmt->execute([$_POST['id']])) { + $message = 'Kategoria została usunięta'; + logActivity('category_deleted', 'category', $_POST['id']); + } + break; + } + } +} + +// Pobierz wszystkie kategorie +$stmt = $db->query(" + SELECT c.*, parent.name as parent_name, + (SELECT COUNT(*) FROM page_categories WHERE category_id = c.id) as page_count + FROM categories c + LEFT JOIN categories parent ON c.parent_id = parent.id + ORDER BY c.name +"); +$categories = $stmt->fetchAll(); + +// Tryb edycji +$editCategory = null; +if (isset($_GET['edit'])) { + $stmt = $db->prepare("SELECT * FROM categories WHERE id = ?"); + $stmt->execute([$_GET['edit']]); + $editCategory = $stmt->fetch(); +} +?> + + + + + + Kategorie - Panel CMS + + + +
+

Panel CMS

+ ← Powrót +
+ + + +
+

Zarządzanie kategoriami

+ + +
+ + + +
+
+

+
+
+
+ + + + + +
+ + +
+ +
+ + + Zostaw puste, aby wygenerować automatycznie z nazwy +
+ +
+ + + Opcjonalny opis kategorii +
+ +
+ + + Wybierz kategorię nadrzędną, aby utworzyć podkategorię +
+ + + + Anuluj + +
+
+
+ + +
+
+

Wszystkie kategorie ()

+
+
+ +

+ Brak kategorii. Dodaj pierwszą kategorię powyżej. +

+ + + + + + + + + + + + + + + + + + + + + + + + +
NazwaSlugKategoria nadrzędnaLiczba stronData utworzeniaAkcje
+ + + + + + + + + + + + + -- + + + 0): ?> + + + 0 + + + Edytuj +
+ + + +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 0000000..aa25105 --- /dev/null +++ b/admin/index.php @@ -0,0 +1,265 @@ + $db->query("SELECT COUNT(*) as count FROM pages")->fetch()['count'], + 'published' => $db->query("SELECT COUNT(*) as count FROM pages WHERE status = 'published'")->fetch()['count'], + 'users' => $db->query("SELECT COUNT(*) as count FROM users")->fetch()['count'], + 'media' => $db->query("SELECT COUNT(*) as count FROM media")->fetch()['count'] +]; + +// Ostatnie strony +$recentPages = getAllPages('published', 5); +?> + + + + + + Panel administracyjny - CMS + + + +
+

🚀 Panel CMS

+
+ Witaj, + Wyloguj +
+
+ + + +
+

Dashboard

+ +
+
+

Wszystkie strony

+
+
+ +
+

Opublikowane

+
+
+ +
+

Użytkownicy

+
+
+ +
+

Pliki

+
+
+
+ +
+
+

Ostatnie strony

+
+
+ +

Brak opublikowanych stron

+ +
    + +
  • +

    + + Autor: | + Data: + +
  • + +
+ + +
+ Zobacz wszystkie strony +
+
+
+
+ + \ No newline at end of file diff --git a/admin/login.php b/admin/login.php new file mode 100644 index 0000000..d774139 --- /dev/null +++ b/admin/login.php @@ -0,0 +1,157 @@ + + + + + + + Logowanie - Panel CMS + + + +
+

Panel CMS

+

Zaloguj się do systemu

+ + +
+ + +
+
+ + +
+ +
+ + +
+ + +
+ + +
+ + \ No newline at end of file diff --git a/admin/logout.php b/admin/logout.php new file mode 100644 index 0000000..955d642 --- /dev/null +++ b/admin/logout.php @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/admin/media.php b/admin/media.php new file mode 100644 index 0000000..8255d7d --- /dev/null +++ b/admin/media.php @@ -0,0 +1,356 @@ +prepare("SELECT * FROM media WHERE id = ?"); + $stmt->execute([$mediaId]); + $media = $stmt->fetch(); + + if ($media) { + // Usuń plik z dysku + if (file_exists($media['file_path'])) { + unlink($media['file_path']); + } + + // Usuń z bazy + $stmt = $db->prepare("DELETE FROM media WHERE id = ?"); + if ($stmt->execute([$mediaId])) { + $message = 'Plik został usunięty'; + logActivity('media_deleted', 'media', $mediaId); + } + } +} + +// Pobierz wszystkie media +$stmt = $db->query(" + SELECT m.*, u.username as uploaded_by_name + FROM media m + LEFT JOIN users u ON m.uploaded_by = u.id + ORDER BY m.created_at DESC +"); +$mediaFiles = $stmt->fetchAll(); +?> + + + + + + Zarządzanie mediami - Panel CMS + + + +
+

Panel CMS

+ ← Powrót +
+ + + +
+

Zarządzanie mediami

+ + +
+ + + +
+ + + +
+
+

Prześlij nowy plik

+
+
+
+
+
📁
+

+ Kliknij lub przeciągnij pliki tutaj +

+ + Dozwolone typy: JPG, PNG, GIF (max 5MB) + + +
+
+
+
+ + +
+
+

Biblioteka mediów ( plików)

+
+
+ +

+ Brak plików w bibliotece. Prześlij pierwszy plik powyżej. +

+ +
+ +
+ + <?php echo escape($media['alt_text'] ?? $media['original_name']); ?> + +
📄
+ + +
+

+ +

+ + KB + + + + + + przez + + +
+ +
+ + + +
+
+
+
+ +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/admin/menus.php b/admin/menus.php new file mode 100644 index 0000000..aec4779 --- /dev/null +++ b/admin/menus.php @@ -0,0 +1,500 @@ +prepare("INSERT INTO menus (name, location) VALUES (?, ?)"); + if ($stmt->execute([$_POST['name'], $_POST['location']])) { + $message = 'Menu zostało utworzone'; + logActivity('menu_created', 'menu', $db->lastInsertId()); + } + break; + + case 'delete_menu': + $stmt = $db->prepare("DELETE FROM menus WHERE id = ?"); + if ($stmt->execute([$_POST['menu_id']])) { + $message = 'Menu zostało usunięte'; + logActivity('menu_deleted', 'menu', $_POST['menu_id']); + } + break; + + case 'add_menu_item': + $stmt = $db->prepare(" + INSERT INTO menu_items (menu_id, title, url, page_id, parent_id, sort_order, target, css_class) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + "); + + $pageId = !empty($_POST['page_id']) ? $_POST['page_id'] : null; + $parentId = !empty($_POST['parent_id']) ? $_POST['parent_id'] : null; + + if ($stmt->execute([ + $_POST['menu_id'], + $_POST['title'], + $_POST['url'], + $pageId, + $parentId, + $_POST['sort_order'] ?? 0, + $_POST['target'] ?? '_self', + $_POST['css_class'] ?? '' + ])) { + $message = 'Element menu został dodany'; + logActivity('menu_item_created', 'menu_item', $db->lastInsertId()); + } + break; + + case 'delete_menu_item': + $stmt = $db->prepare("DELETE FROM menu_items WHERE id = ?"); + if ($stmt->execute([$_POST['item_id']])) { + $message = 'Element menu został usunięty'; + logActivity('menu_item_deleted', 'menu_item', $_POST['item_id']); + } + break; + } + } +} + +// Pobierz wszystkie menu +$menus = $db->query("SELECT * FROM menus ORDER BY name")->fetchAll(); + +// Pobierz wszystkie strony do wyboru +$pages = $db->query("SELECT id, title FROM pages WHERE status = 'published' ORDER BY title")->fetchAll(); + +// Wybrane menu do edycji +$selectedMenuId = $_GET['menu_id'] ?? ($menus[0]['id'] ?? null); +$menuItems = []; + +if ($selectedMenuId) { + $stmt = $db->prepare(" + SELECT mi.*, p.title as page_title + FROM menu_items mi + LEFT JOIN pages p ON mi.page_id = p.id + WHERE mi.menu_id = ? + ORDER BY mi.sort_order, mi.id + "); + $stmt->execute([$selectedMenuId]); + $menuItems = $stmt->fetchAll(); +} +?> + + + + + + Zarządzanie menu - Panel CMS + + + +
+

Panel CMS

+ ← Powrót +
+ + + +
+

Zarządzanie menu

+ + +
+ + + +
+
+

Utwórz nowe menu

+
+
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+
+ + + + + + + +
+
+

Dodaj element do menu

+
+
+
+ + + +
+
+ + +
+ +
+ + +
+
+ +
+
+ + + Zostaw puste jeśli wybrano stronę powyżej +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ + +
+
+
+ + +
+
+

Elementy menu

+
+ + + +
+
+
+ +

+ To menu nie ma jeszcze żadnych elementów +

+ + + + + + + + + +
+
+ + +
+
+ Nie masz jeszcze żadnych menu. Utwórz pierwsze menu powyżej. +
+
+ +
+ + \ No newline at end of file diff --git a/admin/pages.php b/admin/pages.php new file mode 100644 index 0000000..acdfbe2 --- /dev/null +++ b/admin/pages.php @@ -0,0 +1,352 @@ + $_POST['id'] ?? null, + 'title' => $_POST['title'], + 'slug' => $_POST['slug'], + 'content' => $_POST['content'], + 'meta_description' => $_POST['meta_description'], + 'status' => $_POST['status'], + 'template' => $_POST['template'], + 'author_id' => $_SESSION['user_id'] + ]; + + if (savePage($data)) { + $action = $data['id'] ? 'page_updated' : 'page_created'; + logActivity($action, 'page', $data['id']); + $message = 'Strona została zapisana'; + } else { + $message = 'Błąd podczas zapisywania strony'; + } + break; + } + } +} + +// Pobierz wszystkie strony +$stmt = $db->query(" + SELECT p.*, u.username as author_name + FROM pages p + LEFT JOIN users u ON p.author_id = u.id + ORDER BY p.created_at DESC +"); +$pages = $stmt->fetchAll(); + +// Tryb edycji +$editPage = null; +if (isset($_GET['edit'])) { + $stmt = $db->prepare("SELECT * FROM pages WHERE id = ?"); + $stmt->execute([$_GET['edit']]); + $editPage = $stmt->fetch(); +} +?> + + + + + + Zarządzanie stronami - Panel CMS + + + +
+

Panel CMS

+ ← Powrót +
+ + + +
+

Zarządzanie stronami

+ + +
+ + + +
+
+

+
+
+
+ + + + + +
+ + +
+ +
+ + + Zostaw puste, aby wygenerować automatycznie +
+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+ +
+ + +
+
+ + + + Anuluj + +
+
+
+ + +
+
+

Wszystkie strony

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
TytułSlugAutorStatusData utworzeniaAkcje
+ + + + + Edytuj +
+ + + +
+
+
+
+
+ + \ No newline at end of file diff --git a/admin/settings.php b/admin/settings.php new file mode 100644 index 0000000..1a7dfd4 --- /dev/null +++ b/admin/settings.php @@ -0,0 +1,353 @@ + $value) { + if ($key !== 'save_settings' && $key !== 'csrf_token') { + updateSetting($key, $value); + } + } + + logActivity('settings_updated'); + $message = 'Ustawienia zostały zapisane'; +} + +// Pobierz wszystkie ustawienia +$stmt = $db->query("SELECT setting_key, setting_value FROM settings ORDER BY setting_key"); +$settings = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); +?> + + + + + + Ustawienia - Panel CMS + + + +
+

Panel CMS

+ ← Powrót +
+ + + +
+

Ustawienia systemu

+ + +
+ + +
+ + + +
+
+

Ogólne ustawienia

+
+
+
+

Podstawowe informacje

+ +
+
+ + + Nazwa wyświetlana w nagłówku i tytule strony +
+ +
+ + + Główny adres email strony +
+
+ +
+ + + Krótki opis strony (używany w meta tagach) +
+
+ +
+

Regionalne

+ +
+
+ + +
+ +
+ + +
+
+
+
+
+ + +
+
+

Wyświetlanie treści

+
+
+
+
+ + + Liczba elementów wyświetlanych na jednej stronie w listach +
+
+
+
+ + +
+
+

Użytkownicy i bezpieczeństwo

+
+
+
+ + Gdy wyłączone, tylko administrator może tworzyć konta +
+
+
+ + +
+
+

Informacje systemowe

+
+
+
+
+ Wersja PHP: +
+
+ Wersja MySQL: + query('SELECT VERSION()')->fetchColumn(); + echo $version; + ?> +
+
+ Zainstalowane strony: + query('SELECT COUNT(*) FROM pages')->fetchColumn(); ?> +
+
+ Zarejestrowani użytkownicy: + query('SELECT COUNT(*) FROM users')->fetchColumn(); ?> +
+
+ +
+ +
+
+ Ścieżka do uploadu:
+ +
+
+ Max rozmiar pliku: + MB +
+
+
+
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/admin/users.php b/admin/users.php new file mode 100644 index 0000000..15304c4 --- /dev/null +++ b/admin/users.php @@ -0,0 +1,468 @@ +prepare("SELECT id FROM users WHERE username = ? OR email = ?"); + $stmt->execute([$_POST['username'], $_POST['email']]); + + if ($stmt->fetch()) { + $error = 'Użytkownik o tej nazwie lub emailu już istnieje'; + } else { + // Utwórz użytkownika + $hashedPassword = password_hash($_POST['password'], PASSWORD_DEFAULT); + $stmt = $db->prepare(" + INSERT INTO users (username, email, password, role, status) + VALUES (?, ?, ?, ?, ?) + "); + + if ($stmt->execute([ + $_POST['username'], + $_POST['email'], + $hashedPassword, + $_POST['role'], + $_POST['status'] + ])) { + $message = 'Użytkownik został utworzony'; + logActivity('user_created', 'user', $db->lastInsertId()); + } else { + $error = 'Błąd podczas tworzenia użytkownika'; + } + } + } + break; + + case 'update': + $stmt = $db->prepare(" + UPDATE users + SET username = ?, email = ?, role = ?, status = ? + WHERE id = ? + "); + + if ($stmt->execute([ + $_POST['username'], + $_POST['email'], + $_POST['role'], + $_POST['status'], + $_POST['id'] + ])) { + // Jeśli podano nowe hasło + if (!empty($_POST['password'])) { + $hashedPassword = password_hash($_POST['password'], PASSWORD_DEFAULT); + $stmt = $db->prepare("UPDATE users SET password = ? WHERE id = ?"); + $stmt->execute([$hashedPassword, $_POST['id']]); + } + + $message = 'Użytkownik został zaktualizowany'; + logActivity('user_updated', 'user', $_POST['id']); + } else { + $error = 'Błąd podczas aktualizacji użytkownika'; + } + break; + + case 'delete': + // Nie pozwól usunąć własnego konta + if ($_POST['id'] == $_SESSION['user_id']) { + $error = 'Nie możesz usunąć własnego konta'; + } else { + $stmt = $db->prepare("DELETE FROM users WHERE id = ?"); + if ($stmt->execute([$_POST['id']])) { + $message = 'Użytkownik został usunięty'; + logActivity('user_deleted', 'user', $_POST['id']); + } + } + break; + } + } +} + +// Pobierz wszystkich użytkowników +$stmt = $db->query(" + SELECT u.*, + (SELECT COUNT(*) FROM pages WHERE author_id = u.id) as page_count + FROM users u + ORDER BY u.created_at DESC +"); +$users = $stmt->fetchAll(); + +// Tryb edycji +$editUser = null; +if (isset($_GET['edit'])) { + $stmt = $db->prepare("SELECT * FROM users WHERE id = ?"); + $stmt->execute([$_GET['edit']]); + $editUser = $stmt->fetch(); +} +?> + + + + + + Użytkownicy - Panel CMS + + + +
+

Panel CMS

+ ← Powrót +
+ + + +
+

Zarządzanie użytkownikami

+ + +
+ + + +
+ + + +
+
+

+
+
+
+ + + + + +
+
+ + +
+ +
+ + +
+
+ +
+
+ + > + Minimum 6 znaków +
+ +
+ + + + Użytkownik: może przeglądać
+ Edytor: może edytować strony
+ Administrator: pełny dostęp +
+
+
+ +
+ + +
+ + + + Anuluj + +
+
+
+ + +
+
+

Wszyscy użytkownicy ()

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Nazwa użytkownikaEmailRolaStatusLiczba stronOstatnie logowanieData rejestracjiAkcje
+ + + (Ty) + + + + 'Użytkownik', 'editor' => 'Edytor', 'admin' => 'Administrator']; + echo $roles[$user['role']]; + ?> + + + + + + + 0): ?> + + + + + 0 + + + + + + Nigdy + + + Edytuj + +
+ + + +
+ +
+
+
+
+ + \ No newline at end of file diff --git a/assets/uploads/69694ec8ceca1.png b/assets/uploads/69694ec8ceca1.png new file mode 100644 index 0000000..2958c3d Binary files /dev/null and b/assets/uploads/69694ec8ceca1.png differ diff --git a/cms_install.php b/cms_install.php new file mode 100644 index 0000000..0cda813 --- /dev/null +++ b/cms_install.php @@ -0,0 +1,41 @@ +query("SELECT COUNT(*) as count FROM users WHERE username = 'admin'"); +$result = $stmt->fetch(); + +if ($result['count'] > 0) { + die('Administrator już istnieje! Jeśli zapomniałeś hasła, usuń użytkownika z bazy i uruchom ten skrypt ponownie.'); +} + +// Utwórz użytkownika admin z hasłem admin123 +$password = password_hash('admin123', PASSWORD_DEFAULT); + +$stmt = $db->prepare(" + INSERT INTO users (username, email, password, role, status) + VALUES ('admin', 'admin@example.com', ?, 'admin', 'active') +"); + +if ($stmt->execute([$password])) { + echo "

✅ Instalacja zakończona pomyślnie!

"; + echo "

Użytkownik administratora został utworzony:

"; + echo ""; + echo "

WAŻNE: Zmień hasło po pierwszym zalogowaniu!

"; + echo "

Przejdź do panelu logowania →

"; + echo "
"; + echo "

USUŃ TEN PLIK (install.php) PO INSTALACJI!

"; +} else { + echo "

❌ Błąd instalacji

"; + echo "

Nie udało się utworzyć użytkownika administratora.

"; +} +?> \ No newline at end of file diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..72f0d15 --- /dev/null +++ b/config/database.php @@ -0,0 +1,63 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, + ]; + + $this->connection = new PDO($dsn, DB_USER, DB_PASS, $options); + } catch (PDOException $e) { + die("Błąd połączenia z bazą danych: " . $e->getMessage()); + } + } + + public static function getInstance() { + if (self::$instance === null) { + self::$instance = new self(); + } + return self::$instance; + } + + public function getConnection() { + return $this->connection; + } + + // Zapobieganie klonowaniu + private function __clone() {} + + // Zapobieganie deserializacji + public function __wakeup() { + throw new Exception("Nie można deserializować singletona"); + } +} + +// Inicjalizacja połączenia +function getDB() { + return Database::getInstance()->getConnection(); +} +?> \ No newline at end of file diff --git a/includes/auth.php b/includes/auth.php new file mode 100644 index 0000000..691c837 --- /dev/null +++ b/includes/auth.php @@ -0,0 +1,190 @@ +prepare("SELECT * FROM users WHERE username = ? AND status = 'active'"); + $stmt->execute([$username]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + // Regeneruj ID sesji dla bezpieczeństwa + session_regenerate_id(true); + + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['role'] = $user['role']; + $_SESSION['logged_in'] = true; + $_SESSION['last_activity'] = time(); + + // Aktualizuj ostatnie logowanie + $updateStmt = $db->prepare("UPDATE users SET last_login = NOW() WHERE id = ?"); + $updateStmt->execute([$user['id']]); + + logActivity('login'); + + return ['success' => true, 'user' => $user]; + } + + return ['success' => false, 'message' => 'Nieprawidłowa nazwa użytkownika lub hasło']; +} + +// Wylogowanie użytkownika +function logout() { + logActivity('logout'); + + $_SESSION = []; + + if (isset($_COOKIE[session_name()])) { + setcookie(session_name(), '', time() - 3600, '/'); + } + + session_destroy(); +} + +// Sprawdzenie czy użytkownik jest zalogowany +function isLoggedIn() { + if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) { + return false; + } + + // Sprawdź timeout sesji + if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > SESSION_LIFETIME)) { + logout(); + return false; + } + + $_SESSION['last_activity'] = time(); + return true; +} + +// Sprawdzenie roli użytkownika +function hasRole($role) { + if (!isLoggedIn()) { + return false; + } + + $roles = ['user' => 1, 'editor' => 2, 'admin' => 3]; + $userRole = $_SESSION['role'] ?? 'user'; + + return $roles[$userRole] >= $roles[$role]; +} + +// Wymuszenie logowania +function requireLogin() { + if (!isLoggedIn()) { + header('Location: ' . ADMIN_URL . '/login.php'); + exit; + } +} + +// Wymuszenie roli +function requireRole($role) { + requireLogin(); + + if (!hasRole($role)) { + http_response_code(403); + die('Brak uprawnień do tej strony'); + } +} + +// Rejestracja nowego użytkownika +function register($username, $email, $password) { + $db = getDB(); + + // Sprawdź czy rejestracja jest włączona + if (!getSetting('allow_registration', '0')) { + return ['success' => false, 'message' => 'Rejestracja jest wyłączona']; + } + + // Walidacja + if (strlen($username) < 3) { + return ['success' => false, 'message' => 'Nazwa użytkownika musi mieć co najmniej 3 znaki']; + } + + if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + return ['success' => false, 'message' => 'Nieprawidłowy adres email']; + } + + if (strlen($password) < 6) { + return ['success' => false, 'message' => 'Hasło musi mieć co najmniej 6 znaków']; + } + + // Sprawdź czy użytkownik już istnieje + $stmt = $db->prepare("SELECT id FROM users WHERE username = ? OR email = ?"); + $stmt->execute([$username, $email]); + + if ($stmt->fetch()) { + return ['success' => false, 'message' => 'Użytkownik o tej nazwie lub emailu już istnieje']; + } + + // Hashuj hasło + $hashedPassword = password_hash($password, HASH_ALGO); + + // Dodaj użytkownika + $stmt = $db->prepare(" + INSERT INTO users (username, email, password, role) + VALUES (?, ?, ?, 'user') + "); + + if ($stmt->execute([$username, $email, $hashedPassword])) { + logActivity('user_registered', 'user', $db->lastInsertId()); + return ['success' => true, 'message' => 'Rejestracja zakończona pomyślnie']; + } + + return ['success' => false, 'message' => 'Wystąpił błąd podczas rejestracji']; +} + +// Zmiana hasła +function changePassword($userId, $oldPassword, $newPassword) { + $db = getDB(); + + $stmt = $db->prepare("SELECT password FROM users WHERE id = ?"); + $stmt->execute([$userId]); + $user = $stmt->fetch(); + + if (!$user || !password_verify($oldPassword, $user['password'])) { + return ['success' => false, 'message' => 'Nieprawidłowe aktualne hasło']; + } + + if (strlen($newPassword) < 6) { + return ['success' => false, 'message' => 'Nowe hasło musi mieć co najmniej 6 znaków']; + } + + $hashedPassword = password_hash($newPassword, HASH_ALGO); + $stmt = $db->prepare("UPDATE users SET password = ? WHERE id = ?"); + + if ($stmt->execute([$hashedPassword, $userId])) { + logActivity('password_changed'); + return ['success' => true, 'message' => 'Hasło zostało zmienione']; + } + + return ['success' => false, 'message' => 'Nie udało się zmienić hasła']; +} + +// Pobierz aktualnego użytkownika +function getCurrentUser() { + if (!isLoggedIn()) { + return null; + } + + $db = getDB(); + $stmt = $db->prepare("SELECT * FROM users WHERE id = ?"); + $stmt->execute([$_SESSION['user_id']]); + return $stmt->fetch(); +} + +// CSRF Token +function generateCSRFToken() { + if (!isset($_SESSION['csrf_token'])) { + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); + } + return $_SESSION['csrf_token']; +} + +function validateCSRFToken($token) { + return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token); +} +?> \ No newline at end of file diff --git a/includes/functions.php b/includes/functions.php new file mode 100644 index 0000000..e786e2b --- /dev/null +++ b/includes/functions.php @@ -0,0 +1,244 @@ + 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', + 'ń' => 'n', 'ó' => 'o', 'ś' => 's', 'ź' => 'z', + 'ż' => 'z', 'Ą' => 'a', 'Ć' => 'c', 'Ę' => 'e', + 'Ł' => 'l', 'Ń' => 'n', 'Ó' => 'o', 'Ś' => 's', + 'Ź' => 'z', 'Ż' => 'z' + ]; + + $text = strtr($text, $replacements); + $text = preg_replace('/[^a-z0-9-]/', '-', $text); + $text = preg_replace('/-+/', '-', $text); + $text = trim($text, '-'); + + return $text; +} + +// Pobranie strony po slug +function getPageBySlug($slug) { + $db = getDB(); + $stmt = $db->prepare(" + SELECT p.*, u.username as author_name + FROM pages p + LEFT JOIN users u ON p.author_id = u.id + WHERE p.slug = ? AND p.status = 'published' + "); + $stmt->execute([$slug]); + return $stmt->fetch(); +} + +// Pobranie wszystkich stron +function getAllPages($status = 'published', $limit = null) { + $db = getDB(); + $sql = "SELECT p.*, u.username as author_name + FROM pages p + LEFT JOIN users u ON p.author_id = u.id + WHERE p.status = ? + ORDER BY p.created_at DESC"; + + if ($limit) { + $sql .= " LIMIT " . intval($limit); + } + + $stmt = $db->prepare($sql); + $stmt->execute([$status]); + return $stmt->fetchAll(); +} + +// Pobranie ustawień +function getSetting($key, $default = '') { + $db = getDB(); + $stmt = $db->prepare("SELECT setting_value FROM settings WHERE setting_key = ?"); + $stmt->execute([$key]); + $result = $stmt->fetch(); + return $result ? $result['setting_value'] : $default; +} + +// Aktualizacja ustawienia +function updateSetting($key, $value) { + $db = getDB(); + $stmt = $db->prepare(" + INSERT INTO settings (setting_key, setting_value) + VALUES (?, ?) + ON DUPLICATE KEY UPDATE setting_value = ? + "); + return $stmt->execute([$key, $value, $value]); +} + +// Zapisywanie strony +function savePage($data) { + $db = getDB(); + + // Jeśli nie ma slug, generuj z tytułu + if (empty($data['slug'])) { + $data['slug'] = createSlug($data['title']); + } + + if (isset($data['id']) && $data['id']) { + // Aktualizacja + $stmt = $db->prepare(" + UPDATE pages SET + title = ?, + slug = ?, + content = ?, + meta_description = ?, + meta_keywords = ?, + template = ?, + status = ?, + featured_image = ? + WHERE id = ? + "); + + return $stmt->execute([ + $data['title'], + $data['slug'], + $data['content'], + $data['meta_description'] ?? '', + $data['meta_keywords'] ?? '', + $data['template'] ?? 'default', + $data['status'] ?? 'draft', + $data['featured_image'] ?? null, + $data['id'] + ]); + } else { + // Nowa strona + $stmt = $db->prepare(" + INSERT INTO pages (title, slug, content, meta_description, meta_keywords, template, author_id, status, featured_image) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + "); + + return $stmt->execute([ + $data['title'], + $data['slug'], + $data['content'], + $data['meta_description'] ?? '', + $data['meta_keywords'] ?? '', + $data['template'] ?? 'default', + $data['author_id'], + $data['status'] ?? 'draft', + $data['featured_image'] ?? null + ]); + } +} + +// Usuwanie strony +function deletePage($id) { + $db = getDB(); + $stmt = $db->prepare("DELETE FROM pages WHERE id = ?"); + return $stmt->execute([$id]); +} + +// Pobranie menu +function getMenu($location) { + $db = getDB(); + $stmt = $db->prepare(" + SELECT mi.* + FROM menu_items mi + JOIN menus m ON mi.menu_id = m.id + WHERE m.location = ? + ORDER BY mi.sort_order ASC + "); + $stmt->execute([$location]); + return $stmt->fetchAll(); +} + +// Upload pliku +function uploadFile($file, $allowedTypes = ['image/jpeg', 'image/png', 'image/gif']) { + if (!isset($file['error']) || $file['error'] !== UPLOAD_ERR_OK) { + return ['success' => false, 'message' => 'Błąd podczas przesyłania pliku']; + } + + if (!in_array($file['type'], $allowedTypes)) { + return ['success' => false, 'message' => 'Niedozwolony typ pliku']; + } + + if ($file['size'] > MAX_UPLOAD_SIZE) { + return ['success' => false, 'message' => 'Plik jest za duży']; + } + + $extension = pathinfo($file['name'], PATHINFO_EXTENSION); + $filename = uniqid() . '.' . $extension; + $filepath = UPLOAD_DIR . $filename; + + if (!is_dir(UPLOAD_DIR)) { + mkdir(UPLOAD_DIR, 0755, true); + } + + if (move_uploaded_file($file['tmp_name'], $filepath)) { + // Zapisz do bazy + $db = getDB(); + $stmt = $db->prepare(" + INSERT INTO media (filename, original_name, file_path, file_type, file_size, mime_type, uploaded_by) + VALUES (?, ?, ?, ?, ?, ?, ?) + "); + + $stmt->execute([ + $filename, + $file['name'], + $filepath, + $extension, + $file['size'], + $file['type'], + $_SESSION['user_id'] ?? 1 + ]); + + return [ + 'success' => true, + 'filename' => $filename, + 'url' => UPLOAD_URL . $filename, + 'id' => $db->lastInsertId() + ]; + } + + return ['success' => false, 'message' => 'Nie udało się zapisać pliku']; +} + +// Logowanie aktywności +function logActivity($action, $entityType = null, $entityId = null) { + $db = getDB(); + $stmt = $db->prepare(" + INSERT INTO activity_logs (user_id, action, entity_type, entity_id, ip_address, user_agent) + VALUES (?, ?, ?, ?, ?, ?) + "); + + return $stmt->execute([ + $_SESSION['user_id'] ?? null, + $action, + $entityType, + $entityId, + $_SERVER['REMOTE_ADDR'] ?? null, + $_SERVER['HTTP_USER_AGENT'] ?? null + ]); +} + +// Formatowanie daty +function formatDate($date, $format = 'd.m.Y H:i') { + return date($format, strtotime($date)); +} + +// Pobieranie kategorii strony +function getPageCategories($pageId) { + $db = getDB(); + $stmt = $db->prepare(" + SELECT c.* + FROM categories c + JOIN page_categories pc ON c.id = pc.category_id + WHERE pc.page_id = ? + "); + $stmt->execute([$pageId]); + return $stmt->fetchAll(); +} +?> \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..a3bb1c8 --- /dev/null +++ b/index.php @@ -0,0 +1,244 @@ +404 - Strona nie znaleziona

Przepraszamy, ale szukana strona nie istnieje.

'; +} else { + $pageTitle = $page['title']; + $pageContent = $page['content']; + $metaDescription = $page['meta_description'] ?? ''; +} + +// Pobierz ustawienia +$siteName = getSetting('site_name', 'Moja Strona'); +$menu = getMenu('header'); +?> + + + + + + <?php echo escape($pageTitle . ' - ' . $siteName); ?> + + + + + + +
+ + + + + +
+ +
+
+ +
+
+ + + + \ No newline at end of file