<?php
if (!defined('HOBBES')) { http_response_code(403); exit; }
// Prevent setup if admin already exists
$users = user_list();
$has_admin = !empty(array_filter($users, fn($u) => $u['role'] === 'admin'));
if ($has_admin) {
flash('error', 'Setup has already been completed. Log in as admin to manage the site.');
redirect('/login');
}
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
csrf_check();
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$pass1 = $_POST['password'] ?? '';
$pass2 = $_POST['password2'] ?? '';
if (!preg_match('/^[a-zA-Z0-9_-]{3,30}$/', $username)) {
$errors[] = 'Username must be 3-30 characters (letters, numbers, -, _).';
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email address.';
}
if (strlen($pass1) < 8) {
$errors[] = 'Password must be at least 8 characters.';
}
if ($pass1 !== $pass2) {
$errors[] = 'Passwords do not match.';
}
if (empty($errors)) {
$user = user_create($username, $pass1, $email, 'admin');
if ($user) {
// Initialize default categories
$default_cats = [
['id' => hobbes_id(), 'name' => 'Applications', 'slug' => 'applications', 'parent' => null],
['id' => hobbes_id(), 'name' => 'Games', 'slug' => 'games', 'parent' => null],
['id' => hobbes_id(), 'name' => 'Utilities', 'slug' => 'utilities', 'parent' => null],
['id' => hobbes_id(), 'name' => 'Drivers', 'slug' => 'drivers', 'parent' => null],
['id' => hobbes_id(), 'name' => 'Development', 'slug' => 'development', 'parent' => null],
['id' => hobbes_id(), 'name' => 'Internet', 'slug' => 'internet', 'parent' => null],
['id' => hobbes_id(), 'name' => 'Multimedia', 'slug' => 'multimedia', 'parent' => null],
['id' => hobbes_id(), 'name' => 'Documents', 'slug' => 'documents', 'parent' => null],
['id' => hobbes_id(), 'name' => 'System', 'slug' => 'system', 'parent' => null],
];
categories_save($default_cats);
// Initialize settings
settings_save(DEFAULT_SETTINGS);
// Initialize empty search index
storage_write(SEARCH_FILE, []);
auth_login($user);
flash('success', 'Setup complete! Welcome, ' . $username . '. The archive is ready.');
redirect('/admin');
} else {
$errors[] = 'Failed to create admin account.';
}
}
}
// Minimal output for setup page (no full template needed yet)
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Setup — Hobbes OS/2 Archive</title>
<style>
body { font-family: 'Courier New', monospace; font-size:13px; background:#c0c0c0; color:#000; margin:0; display:flex; align-items:center; justify-content:center; min-height:100vh; }
#box { background:#fff; border:3px ridge #808080; max-width:480px; width:96%; }
#title { background:#000080; color:#fff; padding:8px 14px; font-size:16px; font-weight:bold; }
#body { padding:20px; }
label { display:block; margin-top:10px; font-weight:bold; font-size:12px; }
input { width:100%; border:2px inset #808080; padding:3px 5px; font-size:12px; background:#fff; box-sizing:border-box; margin-top:2px; }
.err { background:#ffcccc; border:1px solid #cc0000; padding:4px 8px; margin:4px 0; font-size:12px; }
button { margin-top:14px; background:#c0c0c0; border:2px outset #808080; padding:4px 18px; font-size:13px; cursor:pointer; }
button:hover { border-style:inset; }
p { font-size:12px; line-height:1.5; }
</style>
</head>
<body>
<div id="box">
<div id="title">Hobbes OS/2 Archive — Initial Setup</div>
<div id="body">
<p>
Welcome! This wizard creates the initial administrator account.
After setup, you can log in and configure the site from the Admin panel.
</p>
<p><strong>This page will be inaccessible once an admin account exists.</strong></p>
<?php foreach ($errors as $e): ?>
<div class="err"><?php echo h($e); ?></div>
<?php endforeach; ?>
<form method="post">
<input type="hidden" name="csrf_token" value="<?php echo h(csrf_token()); ?>">
<label>Admin Username
<input type="text" name="username" value="<?php echo h($_POST['username'] ?? ''); ?>" required maxlength="30">
</label>
<label>Email Address
<input type="email" name="email" value="<?php echo h($_POST['email'] ?? ''); ?>" required>
</label>
<label>Password (min 8 chars)
<input type="password" name="password" required minlength="8">
</label>
<label>Confirm Password
<input type="password" name="password2" required minlength="8">
</label>
<button type="submit">Create Admin Account & Initialize Archive</button>
</form>
</div>
</div>
</body>
</html>