✏️ 编辑:admin.php
路径:
/home/boguraj1/public_html/lisence/admin.php
大小:15.3 KB · 修改:2026-06-17 00:41:56 · 权限:0644 · 可写
← 返回目录
👁 查看
⬇ 下载
<?php /** * License Admin Panel * URL: https://tmitstore.com/license/admin.php * Protect this URL with .htaccess or basic auth for extra security. */ session_start(); require_once __DIR__ . '/config.php'; $page_error = ''; $page_success = ''; // ---- Login / logout ---- if (isset($_POST['admin_login'])) { $pwd = $_POST['admin_password'] ?? ''; if (password_verify($pwd, LIC_ADMIN_HASH)) { $_SESSION['lic_admin'] = true; } else { $page_error = 'Incorrect password.'; } } if (isset($_GET['logout'])) { unset($_SESSION['lic_admin']); header('Location: admin.php'); exit; } $logged_in = !empty($_SESSION['lic_admin']); // ---- Actions (require login) ---- if ($logged_in) { // Generate random license key helper function genKey(): string { $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; $key = []; for ($g = 0; $g < 4; $g++) { $part = ''; for ($c = 0; $c < 5; $c++) { $part .= $chars[random_int(0, strlen($chars) - 1)]; } $key[] = $part; } return implode('-', $key); } // Add license if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'add') { $domain = strtolower(trim($_POST['domain'] ?? '')); $domain = preg_replace('/^www\./', '', $domain); $customer = trim($_POST['customer'] ?? ''); $notes = trim($_POST['notes'] ?? ''); $expires_at = $_POST['expires_at'] !== '' ? $_POST['expires_at'] : null; $key = trim($_POST['license_key'] ?? ''); if ($key === '') $key = genKey(); // Validate if (!$domain) { $page_error = 'Domain is required.'; } else { try { $lic_pdo->prepare( "INSERT INTO licenses (license_key, domain, product, status, expires_at, customer, notes) VALUES (?, ?, ?, 'active', ?, ?, ?)" )->execute([$key, $domain, LIC_PRODUCT, $expires_at, $customer, $notes]); $page_success = "License added! Key: <strong>{$key}</strong> for domain <strong>{$domain}</strong>"; } catch (PDOException $e) { $page_error = 'Error: ' . htmlspecialchars($e->getMessage()); } } } // Toggle status if (isset($_GET['toggle'])) { $id = (int) $_GET['toggle']; $lic_pdo->prepare( "UPDATE licenses SET status = IF(status='active','suspended','active') WHERE id = ?" )->execute([$id]); header('Location: admin.php'); exit; } // Delete if (isset($_GET['delete'])) { $id = (int) $_GET['delete']; $lic_pdo->prepare("DELETE FROM licenses WHERE id = ?")->execute([$id]); header('Location: admin.php'); exit; } // Update expiry if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_expiry') { $id = (int) ($_POST['lic_id'] ?? 0); $exp = $_POST['new_expiry'] !== '' ? $_POST['new_expiry'] : null; $lic_pdo->prepare("UPDATE licenses SET expires_at = ? WHERE id = ?")->execute([$exp, $id]); $page_success = 'Expiry date updated.'; } // Fetch search $search = trim($_GET['search'] ?? ''); $w_sql = $search ? "WHERE domain LIKE ? OR license_key LIKE ? OR customer LIKE ?" : ''; $w_params = $search ? ["%$search%", "%$search%", "%$search%"] : []; $licenses_stmt = $lic_pdo->prepare( "SELECT * FROM licenses {$w_sql} ORDER BY created_at DESC" ); $licenses_stmt->execute($w_params); $licenses = $licenses_stmt->fetchAll(); // Stats $stats = $lic_pdo->query( "SELECT COUNT(*) AS total, SUM(status='active') AS active, SUM(status='suspended') AS suspended, SUM(status='expired') AS expired FROM licenses WHERE product = '" . LIC_PRODUCT . "'" )->fetch(); } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>License Admin — tmitstore.com</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet"> <style> body { background: #f0f2f5; } .key-badge { font-family: monospace; font-size: 0.85em; letter-spacing: 1px; } .stat-num { font-size: 1.8rem; font-weight: 700; } </style> </head> <body> <nav class="navbar navbar-dark bg-dark px-4"> <span class="navbar-brand fw-bold"><i class="bi bi-shield-lock me-2"></i>License Admin — ISP Stock Manager</span> <?php if ($logged_in): ?> <a href="admin.php?logout=1" class="btn btn-outline-light btn-sm"> <i class="bi bi-box-arrow-right"></i> Logout </a> <?php endif; ?> </nav> <div class="container-fluid px-4 mt-4"> <?php if (!$logged_in): ?> <!-- ===== Login ===== --> <div class="row justify-content-center mt-5"> <div class="col-md-4"> <div class="card shadow-sm"> <div class="card-body p-4"> <h5 class="fw-bold mb-3"><i class="bi bi-lock me-2"></i>Admin Login</h5> <?php if ($page_error): ?> <div class="alert alert-danger py-2"><?= htmlspecialchars($page_error) ?></div> <?php endif; ?> <form method="POST"> <div class="mb-3"> <label class="form-label fw-semibold">Password</label> <input type="password" name="admin_password" class="form-control" autofocus required> </div> <button type="submit" name="admin_login" class="btn btn-dark w-100 fw-semibold">Login</button> </form> </div> </div> </div> </div> <?php else: ?> <!-- ===== Dashboard ===== --> <?php if ($page_success): ?> <div class="alert alert-success alert-dismissible fade show"> <i class="bi bi-check-circle me-2"></i><?= $page_success ?> <button type="button" class="btn-close" data-bs-dismiss="alert"></button> </div> <?php endif; ?> <?php if ($page_error): ?> <div class="alert alert-danger"> <i class="bi bi-exclamation-triangle me-2"></i><?= htmlspecialchars($page_error) ?> </div> <?php endif; ?> <!-- Stats --> <div class="row g-3 mb-4"> <?php foreach ([ ['Total', $stats['total'], 'primary', 'bi-key'], ['Active', $stats['active'], 'success', 'bi-check-circle'], ['Suspended', $stats['suspended'], 'warning', 'bi-pause-circle'], ['Expired', $stats['expired'], 'danger', 'bi-x-circle'], ] as [$label, $val, $cls, $icon]): ?> <div class="col-6 col-md-3"> <div class="card border-<?= $cls ?> h-100"> <div class="card-body d-flex justify-content-between align-items-center"> <div> <div class="text-muted small"><?= $label ?></div> <div class="stat-num text-<?= $cls ?>"><?= $val ?></div> </div> <i class="bi <?= $icon ?> text-<?= $cls ?> opacity-25" style="font-size:2.5rem;"></i> </div> </div> </div> <?php endforeach; ?> </div> <div class="row g-4"> <!-- ===== Add License ===== --> <div class="col-lg-4"> <div class="card"> <div class="card-header bg-primary text-white fw-semibold"> <i class="bi bi-plus-circle me-1"></i> Issue New License </div> <div class="card-body"> <form method="POST"> <input type="hidden" name="action" value="add"> <div class="mb-2"> <label class="form-label fw-semibold small">Customer Domain <span class="text-danger">*</span></label> <input type="text" name="domain" class="form-control form-control-sm" placeholder="e.g., client-isp.com" required> <div class="form-text">www. is stripped automatically.</div> </div> <div class="mb-2"> <label class="form-label fw-semibold small">License Key</label> <input type="text" name="license_key" class="form-control form-control-sm font-monospace" placeholder="Leave blank to auto-generate"> </div> <div class="mb-2"> <label class="form-label fw-semibold small">Customer Name</label> <input type="text" name="customer" class="form-control form-control-sm" placeholder="Optional"> </div> <div class="mb-2"> <label class="form-label fw-semibold small">Expires On</label> <input type="date" name="expires_at" class="form-control form-control-sm"> <div class="form-text">Leave blank = lifetime license.</div> </div> <div class="mb-3"> <label class="form-label fw-semibold small">Notes</label> <textarea name="notes" class="form-control form-control-sm" rows="2" placeholder="Order ID, payment method, etc."></textarea> </div> <div class="d-grid"> <button type="submit" class="btn btn-primary btn-sm fw-semibold"> <i class="bi bi-key me-1"></i> Issue License </button> </div> </form> </div> </div> </div> <!-- ===== License List ===== --> <div class="col-lg-8"> <div class="card"> <div class="card-header bg-dark text-white d-flex justify-content-between align-items-center"> <span><i class="bi bi-list-ul me-1"></i>All Licenses <span class="badge bg-light text-dark ms-1"><?= count($licenses) ?></span> </span> <form class="d-flex gap-2" method="GET"> <input type="text" class="form-control form-control-sm" name="search" value="<?= htmlspecialchars($search) ?>" placeholder="Search domain / key…" style="width:200px;"> <button type="submit" class="btn btn-light btn-sm">Go</button> <?php if ($search): ?> <a href="admin.php" class="btn btn-outline-light btn-sm">Clear</a> <?php endif; ?> </form> </div> <div class="card-body p-0"> <div class="table-responsive"> <table class="table table-hover table-sm mb-0 align-middle"> <thead class="table-light"> <tr> <th>Domain / Customer</th> <th>License Key</th> <th class="text-center">Status</th> <th>Expires</th> <th>Last Check</th> <th class="text-center">Actions</th> </tr> </thead> <tbody> <?php if (empty($licenses)): ?> <tr><td colspan="6" class="text-center text-muted py-4">No licenses found.</td></tr> <?php else: ?> <?php foreach ($licenses as $lic): ?> <tr> <td> <div class="fw-semibold small"><?= htmlspecialchars($lic['domain']) ?></div> <?php if ($lic['customer']): ?> <div class="text-muted" style="font-size:0.78em;"><?= htmlspecialchars($lic['customer']) ?></div> <?php endif; ?> </td> <td> <span class="key-badge badge bg-light text-dark border" title="Click to copy" style="cursor:pointer;" onclick="navigator.clipboard.writeText('<?= htmlspecialchars($lic['license_key']) ?>');this.textContent='Copied!' ;setTimeout(()=>this.textContent='<?= $lic['license_key'] ?>',1500)"> <?= htmlspecialchars($lic['license_key']) ?> </span> </td> <td class="text-center"> <?php $cls_map = ['active'=>'success','suspended'=>'warning','expired'=>'danger']; $cls = $cls_map[$lic['status']] ?? 'secondary'; ?> <span class="badge bg-<?= $cls ?>"> <?= ucfirst($lic['status']) ?> </span> </td> <td class="small text-muted"> <?= $lic['expires_at'] ?? '<span class="badge bg-success">Lifetime</span>' ?> </td> <td class="small text-muted"> <?= $lic['last_check'] ? date('d M Y H:i', strtotime($lic['last_check'])) : '—' ?> </td> <td class="text-center"> <!-- Toggle status --> <a href="admin.php?toggle=<?= $lic['id'] ?>" class="btn btn-sm <?= $lic['status'] === 'active' ? 'btn-warning' : 'btn-success' ?>" title="<?= $lic['status'] === 'active' ? 'Suspend' : 'Activate' ?>" onclick="return confirm('<?= $lic['status'] === 'active' ? 'Suspend' : 'Activate' ?> this license?')"> <i class="bi bi-<?= $lic['status'] === 'active' ? 'pause' : 'play' ?>-fill"></i> </a> <!-- Delete --> <a href="admin.php?delete=<?= $lic['id'] ?>" class="btn btn-sm btn-danger" title="Delete" onclick="return confirm('Permanently delete this license?')"> <i class="bi bi-trash"></i> </a> </td> </tr> <?php endforeach; ?> <?php endif; ?> </tbody> </table> </div> </div> </div> </div> </div> <?php endif; ?> </div><!-- /container --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
💾 保存
取消
保存为 UTF-8,换行统一为 LF