259 lines
13 KiB
PHP
259 lines
13 KiB
PHP
<?php
|
|
session_start();
|
|
|
|
$lockFile = __DIR__ . '/../installed.lock';
|
|
if (file_exists($lockFile)) {
|
|
die("Installation already completed. Please remove 'installed.lock' if you want to re-install.");
|
|
}
|
|
|
|
$step = isset($_GET['step']) ? (int)$_GET['step'] : 1;
|
|
$error = '';
|
|
$success = '';
|
|
|
|
// Step 1: Requirements
|
|
if ($step === 1) {
|
|
$requirements = [
|
|
'php_version' => [
|
|
'name' => 'PHP Version (>= 8.0)',
|
|
'status' => version_compare(PHP_VERSION, '8.0.0', '>='),
|
|
'current' => PHP_VERSION
|
|
],
|
|
'pdo_mysql' => [
|
|
'name' => 'PDO MySQL Extension',
|
|
'status' => extension_loaded('pdo_mysql'),
|
|
'current' => extension_loaded('pdo_mysql') ? 'Loaded' : 'Missing'
|
|
],
|
|
'config_writable' => [
|
|
'name' => 'db/config.php Writable',
|
|
'status' => is_writable(__DIR__ . '/../db/config.php'),
|
|
'current' => is_writable(__DIR__ . '/../db/config.php') ? 'Yes' : 'No'
|
|
],
|
|
'root_writable' => [
|
|
'name' => 'Root Directory Writable',
|
|
'status' => is_writable(__DIR__ . '/..'),
|
|
'current' => is_writable(__DIR__ . '/..') ? 'Yes' : 'No'
|
|
]
|
|
];
|
|
$allOk = true;
|
|
foreach ($requirements as $req) {
|
|
if (!$req['status']) $allOk = false;
|
|
}
|
|
}
|
|
|
|
// Step 2: Database
|
|
if ($step === 2 && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$host = $_POST['db_host'] ?? '';
|
|
$name = $_POST['db_name'] ?? '';
|
|
$user = $_POST['db_user'] ?? '';
|
|
$pass = $_POST['db_pass'] ?? '';
|
|
|
|
try {
|
|
$pdo = new PDO("mysql:host=$host;dbname=$name", $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
|
|
|
// Save to config.php
|
|
$configContent = "<?php\ndefine('DB_HOST', '$host');\ndefine('DB_NAME', '$name');\ndefine('DB_USER', '$user');\ndefine('DB_PASS', '$pass');\n\nfunction db() {\n static \$pdo;\n if (!\$pdo) {\n \$pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4', DB_USER, DB_PASS, [\n PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,\n PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,\n ]);\n }\n return \$pdo;\n}\n";
|
|
file_put_contents(__DIR__ . '/../db/config.php', $configContent);
|
|
|
|
header("Location: index.php?step=3");
|
|
exit;
|
|
} catch (PDOException $e) {
|
|
$error = "Database Connection Failed: " . $e->getMessage();
|
|
}
|
|
}
|
|
|
|
// Step 3: Super Admin
|
|
if ($step === 3 && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
require_once __DIR__ . '/../db/config.php';
|
|
$adminUser = $_POST['admin_user'] ?? '';
|
|
$adminPass = $_POST['admin_pass'] ?? '';
|
|
$adminEmail = $_POST['admin_email'] ?? '';
|
|
|
|
try {
|
|
$pdo = db();
|
|
|
|
// Create tables if they don't exist
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS role_groups (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(50) NOT NULL,
|
|
permissions TEXT
|
|
)");
|
|
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS users (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
username VARCHAR(50) NOT NULL UNIQUE,
|
|
password VARCHAR(255) NOT NULL,
|
|
email VARCHAR(100),
|
|
phone VARCHAR(20),
|
|
group_id INT,
|
|
status ENUM('active', 'inactive') DEFAULT 'active',
|
|
profile_pic VARCHAR(255),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)");
|
|
|
|
// Insert Default Admin Role if missing
|
|
$stmt = $pdo->prepare("SELECT id FROM role_groups WHERE name = 'Administrator'");
|
|
$stmt->execute();
|
|
$role = $stmt->fetch();
|
|
if (!$role) {
|
|
$pdo->exec("INSERT INTO role_groups (name, permissions) VALUES ('Administrator', 'all')");
|
|
$roleId = $pdo->lastInsertId();
|
|
} else {
|
|
$roleId = $role['id'];
|
|
}
|
|
|
|
// Insert Admin User
|
|
$hashedPass = password_hash($adminPass, PASSWORD_DEFAULT);
|
|
$stmt = $pdo->prepare("INSERT INTO users (username, password, email, group_id, status) VALUES (?, ?, ?, ?, 'active')");
|
|
$stmt->execute([$adminUser, $hashedPass, $adminEmail, $roleId]);
|
|
|
|
header("Location: index.php?step=4");
|
|
exit;
|
|
} catch (Exception $e) {
|
|
$error = "Setup Failed: " . $e->getMessage();
|
|
}
|
|
}
|
|
|
|
// Step 4: Finish
|
|
if ($step === 4) {
|
|
file_put_contents($lockFile, date('Y-m-d H:i:s'));
|
|
}
|
|
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Installation - Step <?= $step ?></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.0/font/bootstrap-icons.css" rel="stylesheet">
|
|
<style>
|
|
body { background: #f0f2f5; font-family: 'Inter', sans-serif; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; }
|
|
.install-container { width: 100%; max-width: 600px; padding: 20px; }
|
|
.card { border: none; border-radius: 20px; box-shadow: 0 10px 40px rgba(0,0,0,0.08); overflow: hidden; }
|
|
.card-header { background: linear-gradient(135deg, #6e8efb, #a777e3); color: white; border: none; padding: 30px; text-align: center; }
|
|
.step-indicator { display: flex; justify-content: space-between; margin-bottom: 30px; position: relative; }
|
|
.step-indicator::before { content: ''; position: absolute; top: 15px; left: 0; right: 0; height: 2px; background: #e0e0e0; z-index: 1; }
|
|
.step-dot { width: 32px; height: 32px; background: #fff; border: 2px solid #e0e0e0; border-radius: 50%; display: flex; align-items: center; justify-content: center; z-index: 2; font-weight: bold; font-size: 14px; color: #999; }
|
|
.step-dot.active { border-color: #6e8efb; color: #6e8efb; background: #fff; box-shadow: 0 0 10px rgba(110, 142, 251, 0.3); }
|
|
.step-dot.completed { background: #6e8efb; border-color: #6e8efb; color: #fff; }
|
|
.btn-primary { background: linear-gradient(135deg, #6e8efb, #a777e3); border: none; border-radius: 12px; padding: 12px 24px; font-weight: 600; }
|
|
.form-control { border-radius: 12px; padding: 12px; border: 1px solid #dee2e6; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="install-container">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="fw-bold mb-0">System Installation</h3>
|
|
<p class="mb-0 opacity-75">Configure your application in minutes</p>
|
|
</div>
|
|
<div class="card-body p-4 p-md-5">
|
|
<div class="step-indicator">
|
|
<div class="step-dot <?= $step >= 1 ? ($step > 1 ? 'completed' : 'active') : '' ?>"><?= $step > 1 ? '<i class="bi bi-check"></i>' : '1' ?></div>
|
|
<div class="step-dot <?= $step >= 2 ? ($step > 2 ? 'completed' : 'active') : '' ?>"><?= $step > 2 ? '<i class="bi bi-check"></i>' : '2' ?></div>
|
|
<div class="step-dot <?= $step >= 3 ? ($step > 3 ? 'completed' : 'active') : '' ?>"><?= $step > 3 ? '<i class="bi bi-check"></i>' : '3' ?></div>
|
|
<div class="step-dot <?= $step >= 4 ? 'completed' : '' ?>">4</div>
|
|
</div>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="alert alert-danger d-flex align-items-center mb-4">
|
|
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
|
<div><?= $error ?></div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($step === 1): ?>
|
|
<h5 class="fw-bold mb-4">Step 1: Check Requirements</h5>
|
|
<div class="list-group list-group-flush mb-4">
|
|
<?php foreach ($requirements as $req): ?>
|
|
<div class="list-group-item d-flex justify-content-between align-items-center py-3">
|
|
<div>
|
|
<h6 class="mb-0 fw-semibold"><?= $req['name'] ?></h6>
|
|
<small class="text-muted">Current: <?= $req['current'] ?></small>
|
|
</div>
|
|
<?php if ($req['status']): ?>
|
|
<span class="badge bg-success-subtle text-success rounded-pill px-3">Passed</span>
|
|
<?php else: ?>
|
|
<span class="badge bg-danger-subtle text-danger rounded-pill px-3">Failed</span>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php if ($allOk): ?>
|
|
<div class="d-grid">
|
|
<a href="index.php?step=2" class="btn btn-primary">Next: Database Setup</a>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="alert alert-warning small">Please fix the issues above to continue.</div>
|
|
<div class="d-grid">
|
|
<button onclick="window.location.reload()" class="btn btn-secondary">Retry Check</button>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php elseif ($step === 2): ?>
|
|
<h5 class="fw-bold mb-4">Step 2: Database Configuration</h5>
|
|
<form method="POST">
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold">Database Host</label>
|
|
<input type="text" name="db_host" class="form-control" value="127.0.0.1" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold">Database Name</label>
|
|
<input type="text" name="db_name" class="form-control" placeholder="e.g. admin_db" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold">Database User</label>
|
|
<input type="text" name="db_user" class="form-control" placeholder="e.g. root" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold">Database Password</label>
|
|
<input type="password" name="db_pass" class="form-control" placeholder="Enter password">
|
|
</div>
|
|
<div class="d-grid mt-4">
|
|
<button type="submit" class="btn btn-primary">Verify & Save Config</button>
|
|
</div>
|
|
</form>
|
|
|
|
<?php elseif ($step === 3): ?>
|
|
<h5 class="fw-bold mb-4">Step 3: Super Admin Setup</h5>
|
|
<form method="POST">
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold">Admin Username</label>
|
|
<input type="text" name="admin_user" class="form-control" placeholder="e.g. admin" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold">Admin Email</label>
|
|
<input type="email" name="admin_email" class="form-control" placeholder="admin@example.com" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold">Admin Password</label>
|
|
<input type="password" name="admin_pass" class="form-control" placeholder="Minimum 6 characters" required minlength="6">
|
|
</div>
|
|
<div class="d-grid mt-4">
|
|
<button type="submit" class="btn btn-primary">Finish Installation</button>
|
|
</div>
|
|
</form>
|
|
|
|
<?php elseif ($step === 4): ?>
|
|
<div class="text-center py-4">
|
|
<div class="display-1 text-success mb-4">
|
|
<i class="bi bi-check-circle-fill"></i>
|
|
</div>
|
|
<h4 class="fw-bold">Ready to Launch!</h4>
|
|
<p class="text-muted">Installation completed successfully. Your system is now secure and ready to use.</p>
|
|
<div class="alert alert-info small mt-4">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
For security, the <code>installed.lock</code> file has been created.
|
|
</div>
|
|
<div class="d-grid mt-5">
|
|
<a href="../index.php" class="btn btn-primary">Go to Dashboard</a>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|