👁 查看: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>