time()) { $error = 'Zu viele Fehlversuche. Bitte später erneut versuchen.'; } else { $statement = $pdo->prepare('SELECT id, username, password_hash FROM admin_users WHERE username = :username AND is_active = 1 LIMIT 1'); $statement->execute([':username' => $username]); $admin = $statement->fetch(); if ($admin && password_verify($password, $admin['password_hash'])) { session_regenerate_id(true); $_SESSION['admin_id'] = (int) $admin['id']; $_SESSION['admin_username'] = $admin['username']; $_SESSION['admin_csrf'] = bin2hex(random_bytes(32)); unset($_SESSION['admin_login_failures'], $_SESSION['admin_locked_until']); redirectAdmin(); } $failures = (int) ($_SESSION['admin_login_failures'] ?? 0) + 1; $_SESSION['admin_login_failures'] = $failures; if ($failures >= 5) $_SESSION['admin_locked_until'] = time() + 300; usleep(500000); $error = 'Benutzername oder Passwort ist ungültig.'; } } $loggedIn = isset($_SESSION['admin_id']); if ($loggedIn) { requireAdmin(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { verifyCsrf(); try { $action = postText('action', 40); if ($action === 'logout') { $_SESSION = []; session_destroy(); redirectAdmin(); } if ($action === 'save_author') { $id = filter_var($_POST['author_id'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]); $name = postText('name', 255); $address = postText('address', 255); $postalCode = postText('postal_code', 20); $city = postText('city', 120); $bankAccount = postText('bank_account', 255); $bic = postText('bic', 20); $bankName = postText('bank_name', 255); $paypalAddress = postText('paypal_address', 255); if ($name === '') throw new InvalidArgumentException('Der Autorenname ist erforderlich.'); if ($id) { $statement = $pdo->prepare('UPDATE authors SET name = :name, address = :address, postal_code = :postal_code, city = :city, bank_account = :bank_account, bic = :bic, bank_name = :bank_name, paypal_address = :paypal_address WHERE id = :id'); $statement->execute([ ':name' => $name, ':address' => $address, ':postal_code' => $postalCode, ':city' => $city, ':bank_account' => $bankAccount, ':bic' => $bic, ':bank_name' => $bankName, ':paypal_address' => $paypalAddress, ':id' => $id, ]); } else { $statement = $pdo->prepare('INSERT INTO authors (name, address, postal_code, city, bank_account, bic, bank_name, paypal_address) VALUES (:name, :address, :postal_code, :city, :bank_account, :bic, :bank_name, :paypal_address)'); $statement->execute([':name' => $name, ':address' => $address, ':postal_code' => $postalCode, ':city' => $city, ':bank_account' => $bankAccount, ':bic' => $bic, ':bank_name' => $bankName, ':paypal_address' => $paypalAddress]); } $message = 'Autor gespeichert.'; } elseif ($action === 'delete_author') { $id = filter_var($_POST['author_id'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]); if (!$id) throw new InvalidArgumentException('Ungültiger Autor.'); $statement = $pdo->prepare('DELETE FROM authors WHERE id = :id'); $statement->execute([':id' => $id]); $message = $statement->rowCount() ? 'Autor gelöscht.' : 'Autor nicht gefunden.'; } elseif ($action === 'save_book') { $id = filter_var($_POST['book_id'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]); $title = postText('title', 255); $printingCosts = filter_var($_POST['printing_costs'] ?? null, FILTER_VALIDATE_FLOAT); if ($printingCosts === false || $printingCosts < 0 || $printingCosts > 99999999.99) throw new InvalidArgumentException('Die Druckkosten müssen zwischen 0 und 99.999.999,99 liegen.'); $printingCosts = round((float) $printingCosts, 2); $sellingPrice = filter_var($_POST['selling_price'] ?? null, FILTER_VALIDATE_FLOAT); if ($sellingPrice === false || $sellingPrice < 0 || $sellingPrice > 99999999.99) throw new InvalidArgumentException('Der Verkaufspreis muss zwischen 0 und 99.999.999,99 liegen.'); $sellingPrice = round((float) $sellingPrice, 2); $ebookPrice = filter_var($_POST['ebook_price'] ?? null, FILTER_VALIDATE_FLOAT); if ($ebookPrice === false || $ebookPrice < 0 || $ebookPrice > 99999999.99) throw new InvalidArgumentException('Der eBook-Preis muss zwischen 0 und 99.999.999,99 liegen.'); $ebookPrice = round((float) $ebookPrice, 2); $amazonGross = filter_var($_POST['amazon_gross'] ?? null, FILTER_VALIDATE_FLOAT); if ($amazonGross === false || $amazonGross < 0 || $amazonGross > 99999999.99) throw new InvalidArgumentException('Die Amazon-Marge muss zwischen 0 und 99.999.999,99 liegen.'); $amazonGross = round((float) $amazonGross, 2); $isbnPrint = validateIsbnField(postText('isbn_print', 20), 'Die Print-ISBN'); $isbnEbook = validateIsbnField(postText('isbn_ebook', 20), 'Die eBook-ISBN'); $authorIds = $_POST['author_id'] ?? []; $margins = $_POST['margin_percent'] ?? []; if ($title === '') throw new InvalidArgumentException('Der Buchtitel ist erforderlich.'); if (!is_array($authorIds) || !is_array($margins) || count($authorIds) !== count($margins) || count($authorIds) < 1 || count($authorIds) > 50) throw new InvalidArgumentException('Bitte mindestens einen und höchstens 50 Autoren zuweisen.'); $authors = []; foreach ($authorIds as $index => $rawAuthorId) { $authorId = filter_var($rawAuthorId, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]); $margin = filter_var($margins[$index], FILTER_VALIDATE_FLOAT); if (!$authorId || $margin === false || $margin < 0 || $margin > 100 || isset($authors[$authorId])) throw new InvalidArgumentException('Autoren und Margen sind ungültig oder doppelt vergeben.'); $authors[$authorId] = round((float) $margin, 2); } $pdo->beginTransaction(); if ($id) { $statement = $pdo->prepare('UPDATE books SET title = :title, printing_costs = :printing_costs, selling_price = :selling_price, ebook_price = :ebook_price, amazon_gross = :amazon_gross, isbn_print = :isbn_print, isbn_ebook = :isbn_ebook WHERE id = :id'); $statement->execute([':title' => $title, ':printing_costs' => $printingCosts, ':selling_price' => $sellingPrice, ':ebook_price' => $ebookPrice, ':amazon_gross' => $amazonGross, ':isbn_print' => $isbnPrint, ':isbn_ebook' => $isbnEbook, ':id' => $id]); $bookId = $id; $pdo->prepare('DELETE FROM book_authors WHERE book_id = :book_id')->execute([':book_id' => $bookId]); } else { $statement = $pdo->prepare('INSERT INTO books (title, printing_costs, selling_price, ebook_price, amazon_gross, isbn_print, isbn_ebook) VALUES (:title, :printing_costs, :selling_price, :ebook_price, :amazon_gross, :isbn_print, :isbn_ebook)'); $statement->execute([':title' => $title, ':printing_costs' => $printingCosts, ':selling_price' => $sellingPrice, ':ebook_price' => $ebookPrice, ':amazon_gross' => $amazonGross, ':isbn_print' => $isbnPrint, ':isbn_ebook' => $isbnEbook]); $bookId = (int) $pdo->lastInsertId(); } $statement = $pdo->prepare('INSERT INTO book_authors (book_id, author_id, margin_percent) VALUES (:book_id, :author_id, :margin_percent)'); foreach ($authors as $authorId => $margin) $statement->execute([':book_id' => $bookId, ':author_id' => $authorId, ':margin_percent' => $margin]); $pdo->commit(); $message = 'Buch gespeichert.'; } elseif ($action === 'delete_book') { $id = filter_var($_POST['book_id'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]); if (!$id) throw new InvalidArgumentException('Ungültiges Buch.'); $statement = $pdo->prepare('DELETE FROM books WHERE id = :id'); $statement->execute([':id' => $id]); $message = $statement->rowCount() ? 'Buch gelöscht.' : 'Buch nicht gefunden.'; } } catch (Throwable $exception) { if ($pdo->inTransaction()) $pdo->rollBack(); $error = $exception instanceof InvalidArgumentException ? $exception->getMessage() : 'Die Aktion konnte nicht ausgeführt werden.'; } } } if (!$loggedIn) { ?> Admin-Anmeldung

Autorenmargen – Admin

['min_range' => 1]]) ?: null; $editBookId = filter_var($_GET['edit_book'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) ?: null; $author = ['id' => '', 'name' => '', 'address' => '', 'postal_code' => '', 'city' => '', 'bank_account' => '', 'bic' => '', 'bank_name' => '', 'paypal_address' => '']; if ($editAuthorId) { $statement = $pdo->prepare('SELECT id, name, address, postal_code, city, bank_account, bic, bank_name, paypal_address FROM authors WHERE id = :id'); $statement->execute([':id' => $editAuthorId]); $author = $statement->fetch() ?: $author; } $book = ['id' => '', 'title' => '', 'printing_costs' => '0.00', 'selling_price' => '0.00', 'ebook_price' => '0.00', 'amazon_gross' => '0.00', 'isbn_print' => '', 'isbn_ebook' => '']; $bookAuthors = []; if ($editBookId) { $statement = $pdo->prepare('SELECT id, title, printing_costs, selling_price, ebook_price, amazon_gross, isbn_print, isbn_ebook FROM books WHERE id = :id'); $statement->execute([':id' => $editBookId]); $book = $statement->fetch() ?: $book; $statement = $pdo->prepare('SELECT ba.author_id, a.name, ba.margin_percent FROM book_authors ba INNER JOIN authors a ON a.id = ba.author_id WHERE ba.book_id = :id ORDER BY a.name'); $statement->execute([':id' => $editBookId]); $bookAuthors = $statement->fetchAll(); } $authors = $pdo->query('SELECT id, name, address, postal_code, city, bank_account, bic, bank_name, paypal_address FROM authors ORDER BY name')->fetchAll(); $books = $pdo->query('SELECT b.id, b.title, b.printing_costs, b.selling_price, b.ebook_price, b.amazon_gross, b.isbn_print, b.isbn_ebook, GROUP_CONCAT(CONCAT(a.name, " (", ba.margin_percent, " %)" ) ORDER BY a.name SEPARATOR ", ") AS author_summary FROM books b LEFT JOIN book_authors ba ON ba.book_id = b.id LEFT JOIN authors a ON a.id = ba.author_id GROUP BY b.id ORDER BY b.title')->fetchAll(); $token = csrf(); ?> Autorenmargen – Admin

Autorenmargen – Admin

Abbrechen

    Abbrechen

    Autoren

    NameAdresseIBANBICBanknamePayPal-AdresseAktionen
    Bearbeiten

    Bücher

    TitelDruckkostenPrint-PreiseBook-PreisAmazon-MargeISBN PrintISBN eBookAutoren / MargenAktionen
    € € € €Bearbeiten