diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..f94c71d
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,7 @@
+.git
+.gitignore
+node_modules
+vendor
+docker-compose.override.yml
+source/uploads
+mysql_data
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..0a773c3
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,15 @@
+APP_NAME=Zeszyt 2.0
+DB_PREFIX=xyz_
+
+MYSQL_DATABASE=zeszyt
+MYSQL_USER=zeszyt
+MYSQL_PASSWORD=zeszyt
+MYSQL_ROOT_PASSWORD=root
+
+MICROSOFT_OAUTH_ENABLED=false
+MICROSOFT_OAUTH_TENANT=common
+MICROSOFT_OAUTH_CLIENT_ID=
+MICROSOFT_OAUTH_CLIENT_SECRET=
+MICROSOFT_OAUTH_REDIRECT_URI=http://localhost:8080/oauth_callback.php
+MICROSOFT_OAUTH_ALLOWED_TENANT=
+MICROSOFT_OAUTH_AUTO_PROVISION=false
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..2b612e2
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,24 @@
+FROM php:8.2-apache
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ libzip-dev \
+ libpng-dev \
+ libjpeg62-turbo-dev \
+ libfreetype6-dev \
+ libonig-dev \
+ unzip \
+ curl \
+ && docker-php-ext-configure gd --with-freetype --with-jpeg \
+ && docker-php-ext-install -j"$(nproc)" pdo_mysql mysqli mbstring gd zip \
+ && a2enmod rewrite headers \
+ && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /var/www/html
+
+COPY source/ /var/www/html/
+
+RUN mkdir -p /var/www/html/uploads \
+ && chown -R www-data:www-data /var/www/html
+
+EXPOSE 80
diff --git a/db/zeszyt.sql b/db/zeszyt.sql
index fb392a2..8b759ff 100644
--- a/db/zeszyt.sql
+++ b/db/zeszyt.sql
@@ -79,8 +79,14 @@ CREATE TABLE `xyz_settings` (
CREATE TABLE `xyz_users` (
`id` int NOT NULL,
`username` varchar(50) NOT NULL,
+ `email` varchar(255) DEFAULT NULL,
+ `display_name` varchar(255) DEFAULT NULL,
`password` varchar(255) NOT NULL,
- `role` enum('admin','user') DEFAULT 'user'
+ `role` enum('admin','user') DEFAULT 'user',
+ `oauth_provider` varchar(50) DEFAULT NULL,
+ `oauth_subject` varchar(191) DEFAULT NULL,
+ `oauth_tenant_id` varchar(64) DEFAULT NULL,
+ `last_login_at` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- --------------------------------------------------------
@@ -106,7 +112,9 @@ ALTER TABLE `xyz_settings`
ALTER TABLE `xyz_users`
ADD PRIMARY KEY (`id`),
- ADD UNIQUE KEY `username` (`username`);
+ ADD UNIQUE KEY `username` (`username`),
+ ADD UNIQUE KEY `uniq_users_email` (`email`),
+ ADD KEY `idx_users_oauth_identity` (`oauth_provider`,`oauth_subject`,`oauth_tenant_id`);
--
-- AUTO_INCREMENT dla zrzuconych tabel
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..6fce2f1
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,55 @@
+services:
+ app:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ container_name: zeszyt_app
+ depends_on:
+ db:
+ condition: service_healthy
+ ports:
+ - "8080:80"
+ environment:
+ APP_NAME: "${APP_NAME:-Zeszyt 2.0}"
+ DB_HOST: db
+ DB_NAME: "${MYSQL_DATABASE:-zeszyt}"
+ DB_USER: "${MYSQL_USER:-zeszyt}"
+ DB_PASS: "${MYSQL_PASSWORD:-zeszyt}"
+ DB_PREFIX: "${DB_PREFIX:-xyz_}"
+ MICROSOFT_OAUTH_ENABLED: "${MICROSOFT_OAUTH_ENABLED:-false}"
+ MICROSOFT_OAUTH_TENANT: "${MICROSOFT_OAUTH_TENANT:-common}"
+ MICROSOFT_OAUTH_CLIENT_ID: "${MICROSOFT_OAUTH_CLIENT_ID:-}"
+ MICROSOFT_OAUTH_CLIENT_SECRET: "${MICROSOFT_OAUTH_CLIENT_SECRET:-}"
+ MICROSOFT_OAUTH_REDIRECT_URI: "${MICROSOFT_OAUTH_REDIRECT_URI:-http://localhost:8080/oauth_callback.php}"
+ MICROSOFT_OAUTH_ALLOWED_TENANT: "${MICROSOFT_OAUTH_ALLOWED_TENANT:-}"
+ MICROSOFT_OAUTH_AUTO_PROVISION: "${MICROSOFT_OAUTH_AUTO_PROVISION:-false}"
+ volumes:
+ - ./source:/var/www/html
+ - uploads_data:/var/www/html/uploads
+ restart: unless-stopped
+
+ db:
+ image: mysql:8.0
+ container_name: zeszyt_db
+ command: --default-authentication-plugin=mysql_native_password
+ environment:
+ MYSQL_DATABASE: "${MYSQL_DATABASE:-zeszyt}"
+ MYSQL_USER: "${MYSQL_USER:-zeszyt}"
+ MYSQL_PASSWORD: "${MYSQL_PASSWORD:-zeszyt}"
+ MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:-root}"
+ ports:
+ - "3307:3306"
+ volumes:
+ - mysql_data:/var/lib/mysql
+ - ./db/zeszyt.sql:/docker-entrypoint-initdb.d/01-init.sql:ro
+ healthcheck:
+ test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u${MYSQL_USER:-zeszyt}", "-p${MYSQL_PASSWORD:-zeszyt}"]
+ interval: 10s
+ timeout: 5s
+ retries: 10
+ start_period: 20s
+ restart: unless-stopped
+
+volumes:
+ mysql_data:
+ uploads_data:
diff --git a/source/add_order.php b/source/add_order.php
index 2cab010..cc64a49 100644
--- a/source/add_order.php
+++ b/source/add_order.php
@@ -5,18 +5,20 @@ checkAuth();
$message = '';
-if ($_SERVER["REQUEST_METHOD"] == "POST") {
- $product_name = trim($_POST['product_name']);
- $quantity = (int)$_POST['quantity'];
- $purchase_place = trim($_POST['purchase_place']);
- $price = (float)str_replace(',', '.', $_POST['price_per_unit']);
- $delivery_date = $_POST['delivery_date'];
- $notes = trim($_POST['notes']);
- $recipient = trim($_POST['recipient']);
- $delivery_address = trim($_POST['delivery_address']);
- $company = trim($_POST['company'] ?? ''); // NOWE POLE
+if ($_SERVER["REQUEST_METHOD"] === "POST") {
+ requireCsrfToken();
- if (!empty($product_name) && $quantity > 0) {
+ $product_name = trim($_POST['product_name'] ?? '');
+ $quantity = (int)($_POST['quantity'] ?? 0);
+ $purchase_place = trim($_POST['purchase_place'] ?? '');
+ $price = (float)str_replace(',', '.', $_POST['price_per_unit'] ?? '0');
+ $delivery_date = $_POST['delivery_date'] ?? '';
+ $notes = trim($_POST['notes'] ?? '');
+ $recipient = trim($_POST['recipient'] ?? '');
+ $delivery_address = trim($_POST['delivery_address'] ?? '');
+ $company = trim($_POST['company'] ?? '');
+
+ if ($product_name !== '' && $quantity > 0) {
try {
$pdo->beginTransaction();
@@ -30,17 +32,17 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
$hist_sql = "INSERT INTO " . DB_PREFIX . "order_history (order_id, user_id, action) VALUES (?, ?, ?)";
$hist_stmt = $pdo->prepare($hist_sql);
- $hist_stmt->execute([$order_id, $_SESSION['user_id'], 'Utworzono nowe zamówienie.']);
+ $hist_stmt->execute([$order_id, $_SESSION['user_id'], 'Utworzono nowe zamowienie.']);
$pdo->commit();
-
- $message = "
Zamówienie dodane pomyślnie!
";
+ $message = "Zamowienie dodane pomyslnie.
";
} catch (PDOException $e) {
$pdo->rollBack();
- $message = "Błąd: " . $e->getMessage() . "
";
+ error_log($e->getMessage());
+ $message = "Nie udalo sie zapisac zamowienia.
";
}
} else {
- $message = "Wypełnij nazwę produktu i ilość.
";
+ $message = "Wypelnij nazwe produktu i ilosc.
";
}
}
?>
@@ -49,7 +51,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
- Dodaj zamówienie -
+ Dodaj zamowienie -
@@ -57,18 +59,19 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
diff --git a/source/admin.php b/source/admin.php
index d64f3f0..481ff06 100644
--- a/source/admin.php
+++ b/source/admin.php
@@ -3,134 +3,120 @@ require_once 'includes/db.php';
require_once 'includes/auth.php';
checkAuth();
-checkAdmin(); // Tylko admin tu wejdzie
+checkAdmin();
$message = '';
-// ---------------------------------------------------------
-// 0. INICJALIZACJA DOMYŚLNYCH USTAWIEŃ FIRM (jeśli nie istnieją)
-// ---------------------------------------------------------
$default_settings = [
- 'company_1_name' => 'Moje Przedsiębiorstwo IT',
- 'company_1_details' => 'ul. Główna 1, 00-000 Warszawa | NIP: 0987654321',
- 'company_2_name' => 'Spółka Celowa Sp. z o.o.',
- 'company_2_details' => 'ul. Przykładowa 10, 00-000 Warszawa | NIP: 1234567890 | KRS: 0000123456'
+ '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) {
- // INSERT IGNORE dodaje wpis tylko wtedy, gdy taki klucz jeszcze nie istnieje w tabeli
$stmt = $pdo->prepare("INSERT IGNORE INTO " . DB_PREFIX . "settings (setting_key, setting_value) VALUES (?, ?)");
$stmt->execute([$key, $val]);
}
-// ---------------------------------------------------------
-// 1. WGRYWANIE LOGO
-// ---------------------------------------------------------
-if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_FILES['logo'])) {
- if ($_FILES['logo']['error'] === 0) {
- $upload_dir = 'uploads/';
- if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
-
- $file_ext = strtolower(pathinfo($_FILES['logo']['name'], PATHINFO_EXTENSION));
- if(in_array($file_ext, ['jpg', 'jpeg', 'png', 'gif', 'svg'])) {
- $new_name = 'logo_' . time() . '.' . $file_ext;
- $dest_path = $upload_dir . $new_name;
-
- if (move_uploaded_file($_FILES['logo']['tmp_name'], $dest_path)) {
- $stmt = $pdo->prepare("REPLACE INTO " . DB_PREFIX . "settings (setting_key, setting_value) VALUES ('logo_path', ?)");
- $stmt->execute([$dest_path]);
- $message = "Pomyślnie zaktualizowano logo!
";
+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 = "Pomyslnie zaktualizowano logo.
";
+ } else {
+ $message = "Nie udalo sie zapisac pliku.
";
+ }
} else {
- $message = "Błąd: Nie udało się zapisać pliku. Sprawdź uprawnienia folderu 'uploads'.
";
+ $message = "Dozwolone sa tylko prawidlowe pliki JPG, PNG i GIF.
";
}
- } else {
- $message = "Błąd: Dozwolone są tylko pliki graficzne (JPG, PNG, GIF, SVG).
";
}
- }
-}
+ } elseif (isset($_POST['action']) && $_POST['action'] === 'update_company_settings') {
+ $settings_to_update = ['company_1_name', 'company_1_details', 'company_2_name', 'company_2_details'];
-// ---------------------------------------------------------
-// 1B. ZAPISYWANIE DANYCH FIRM
-// ---------------------------------------------------------
-if ($_SERVER['REQUEST_METHOD'] === 'POST' && 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 = ?");
+ 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]);
+ foreach ($settings_to_update as $key) {
+ if (isset($_POST[$key])) {
+ $update_stmt->execute([trim($_POST[$key]), $key]);
+ }
}
+ $pdo->commit();
+ $message = "Ustawienia firmowe zostaly zapisane.
";
+ } catch (PDOException $e) {
+ $pdo->rollBack();
+ error_log($e->getMessage());
+ $message = "Nie udalo sie zapisac ustawien.
";
}
- $pdo->commit();
- $message = "Ustawienia firmowe zostały zapisane!
";
- } catch (PDOException $e) {
- $pdo->rollBack();
- $message = "Błąd zapisu: " . $e->getMessage() . "
";
- }
-}
-
-// ---------------------------------------------------------
-// 2. DODAWANIE UŻYTKOWNIKA
-// ---------------------------------------------------------
-if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['add_user'])) {
- $new_user = trim($_POST['new_username']);
- $new_pass = $_POST['new_password'];
- $new_role = $_POST['new_role'];
+ } 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 = "Dodano nowego uzytkownika: " . e($new_user) . "
";
+ } catch (PDOException $e) {
+ error_log($e->getMessage());
+ $message = "Nie udalo sie dodac uzytkownika.
";
+ }
+ }
+ } elseif (isset($_POST['reset_password'])) {
+ $user_id = (int)($_POST['user_id'] ?? 0);
+ $new_pass = $_POST['new_password'] ?? '';
- if (!empty($new_user) && !empty($new_pass)) {
- try {
+ if ($user_id > 0 && $new_pass !== '') {
$hashed_pass = password_hash($new_pass, PASSWORD_BCRYPT);
- $stmt = $pdo->prepare("INSERT INTO " . DB_PREFIX . "users (username, password, role) VALUES (?, ?, ?)");
- $stmt->execute([$new_user, $hashed_pass, $new_role]);
- $message = "Dodano nowego użytkownika: $new_user
";
- } catch (PDOException $e) {
- $message = "Błąd: Użytkownik o takiej nazwie prawdopodobnie już istnieje.
";
+ $stmt = $pdo->prepare("UPDATE " . DB_PREFIX . "users SET password = ? WHERE id = ?");
+ $stmt->execute([$hashed_pass, $user_id]);
+ $message = "Zmieniono haslo dla wybranego uzytkownika.
";
+ }
+ } 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 = "Uzytkownik zostal pomyslnie usuniety.
";
+ } else {
+ $message = "Nie mozesz usunac wlasnego konta administratora.
";
}
}
}
-// ---------------------------------------------------------
-// 3. RESET HASŁA UŻYTKOWNIKA
-// ---------------------------------------------------------
-if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['reset_password'])) {
- $user_id = (int)$_POST['user_id'];
- $new_pass = $_POST['new_password'];
-
- if (!empty($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 = "Zmieniono hasło dla wybranego użytkownika.
";
- }
-}
-
-// ---------------------------------------------------------
-// 4. USUWANIE UŻYTKOWNIKA
-// ---------------------------------------------------------
-if (isset($_GET['delete'])) {
- $id_to_delete = (int)$_GET['delete'];
- if ($id_to_delete != $_SESSION['user_id']) {
- $stmt = $pdo->prepare("DELETE FROM " . DB_PREFIX . "users WHERE id = ?");
- $stmt->execute([$id_to_delete]);
- $message = "Użytkownik został pomyślnie usunięty.
";
- } else {
- $message = "Odmowa: Nie możesz usunąć własnego konta administratora!
";
- }
-}
-
-// ---------------------------------------------------------
-// POBIERANIE DANYCH DO WIDOKU
-// ---------------------------------------------------------
-$users = $pdo->query("SELECT id, username, role FROM " . DB_PREFIX . "users")->fetchAll();
+$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) {
- // Zabezpieczenie na wypadek awarii tabeli settings
+} catch (PDOException $e) {
+ error_log($e->getMessage());
}
$current_logo = $settings['logo_path'] ?? '';
@@ -141,7 +127,7 @@ $current_logo = $settings['logo_path'] ?? '';
- Panel Administratora -
+ Panel administratora -