Add admin page
This commit is contained in:
parent
0543ba1ff5
commit
f3ac806c4b
@ -28,4 +28,18 @@ class Config {
|
||||
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
|
||||
public function save(): self {
|
||||
$db = get_db();
|
||||
|
||||
$stmt = $db->prepare("UPDATE settings SET site_title=?, site_description=?, base_path=?, items_per_page=? WHERE id=1");
|
||||
$stmt->execute([$this->siteTitle, $this->siteDescription, $this->basePath, $this->itemsPerPage]);
|
||||
|
||||
return self::load();
|
||||
}
|
||||
|
||||
// I'm making this
|
||||
public function setPassword(){
|
||||
|
||||
}
|
||||
}
|
||||
|
50
tkr/lib/user.php
Normal file
50
tkr/lib/user.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../bootstrap.php';
|
||||
|
||||
confirm_setup();
|
||||
|
||||
// Made this a class so it could be more obvious where config settings are coming from.
|
||||
// Felt too much like magic constants in other files before.
|
||||
class User {
|
||||
// properties
|
||||
public string $username;
|
||||
public string $displayName;
|
||||
public string $mood;
|
||||
|
||||
// load user settings from sqlite database
|
||||
public static function load(): self {
|
||||
$db = get_db();
|
||||
|
||||
// There's only ever one user. I'm just leaning into that.
|
||||
$stmt = $db->query("SELECT username, display_name, mood FROM user WHERE id=1");
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$u = new self();
|
||||
|
||||
if ($row) {
|
||||
$u->username = $row['username'];
|
||||
$u->displayName = $row['display_name'];
|
||||
$u->mood = $row['mood'];
|
||||
}
|
||||
|
||||
return $u;
|
||||
}
|
||||
|
||||
public function save(): self {
|
||||
$db = get_db();
|
||||
|
||||
$stmt = $db->prepare("UPDATE user SET username=?, display_name=?, mood=? WHERE id=1");
|
||||
$stmt->execute([$this->username, $this->displayName, $this->mood]);
|
||||
|
||||
return self::load();
|
||||
}
|
||||
|
||||
// Making this a separate function to avoid
|
||||
// loading the password into memory
|
||||
public function set_password(string $password): void {
|
||||
$db = get_db();
|
||||
|
||||
$hash = password_hash($password, PASSWORD_DEFAULT);
|
||||
$stmt = $db->prepare("UPDATE user SET password_hash=? WHERE id=1");
|
||||
$stmt->execute([$hash]);
|
||||
}
|
||||
}
|
121
tkr/public/admin.php
Normal file
121
tkr/public/admin.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../bootstrap.php';
|
||||
|
||||
confirm_setup();
|
||||
|
||||
require_once LIB_ROOT . '/config.php';
|
||||
require LIB_ROOT . '/session.php';
|
||||
|
||||
if (!$isLoggedIn){
|
||||
header('Location: ' . $config->basePath . 'login.php');
|
||||
}
|
||||
|
||||
require LIB_ROOT . '/user.php';
|
||||
|
||||
$config = Config::load();
|
||||
$user = User::load();
|
||||
|
||||
// handle form submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$errors = [];
|
||||
|
||||
// User profile
|
||||
$username = trim($_POST['username'] ?? '');
|
||||
$displayName = trim($_POST['display_name'] ?? '');
|
||||
// Site settings
|
||||
$siteTitle = trim($_POST['site_title']) ?? '';
|
||||
$siteDescription = trim($_POST['site_description']) ?? '';
|
||||
$basePath = trim($_POST['base_path'] ?? '/');
|
||||
$itemsPerPage = (int) ($_POST['items_per_page'] ?? 25);
|
||||
// Password
|
||||
// TODO - Make sure I really shouldn't trim these
|
||||
// (I'm assuming there may be people who end their password with a space character)
|
||||
$password = $_POST['password'] ?? '';
|
||||
$confirmPassword = $_POST['confirm_password'] ?? '';
|
||||
|
||||
// Validate user profile
|
||||
if (!$username) {
|
||||
$errors[] = "Username is required.";
|
||||
}
|
||||
if (!$displayName) {
|
||||
$errors[] = "Display name is required.";
|
||||
}
|
||||
|
||||
// Validate site settings
|
||||
if (!$siteTitle) {
|
||||
$errors[] = "Site title is required.";
|
||||
}
|
||||
if (!preg_match('#^/[^?<>:"|\\*]*$#', $basePath)) {
|
||||
$errors[] = "Base path must look like a valid URL path (e.g. / or /tkr/).";
|
||||
}
|
||||
if ($itemsPerPage < 1 || $itemsPerPage > 50) {
|
||||
$errors[] = "Items per page must be a number between 1 and 50.";
|
||||
}
|
||||
|
||||
// If a password was sent, make sure it matches the confirmation
|
||||
if ($password && !($password = $confirmPassword)){
|
||||
$errors[] = "Passwords do not match";
|
||||
}
|
||||
|
||||
// TODO: Actually handle errors
|
||||
if (empty($errors)) {
|
||||
// Update site settings
|
||||
$config->siteTitle = $siteTitle;
|
||||
$config->siteDescription = $siteDescription;
|
||||
$config->basePath = $basePath;
|
||||
$config->itemsPerPage = $itemsPerPage;
|
||||
|
||||
// Save site settings and reload config from database
|
||||
$config = $config->save();
|
||||
|
||||
// Update user profile
|
||||
$user->username = $username;
|
||||
$user->displayName = $displayName;
|
||||
|
||||
// Save user profile and reload user from database
|
||||
$user = $user->save();
|
||||
|
||||
// Update the password if one was sent
|
||||
if($password){
|
||||
$user->set_password($password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?= $config->siteTitle ?></title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="<?= htmlspecialchars($config->basePath) ?>css/tkr.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Admin</h1>
|
||||
<div><a href="<?= $config->basePath ?>">Back to home</a></div>
|
||||
<div>
|
||||
<form method="post">
|
||||
<fieldset id="user_settings" class="admin-settings-group">
|
||||
<legend>User settings</legend>
|
||||
<label class="admin-option">Username: <input type="text" name="username" value="<?= $user->username ?>" required></label><br>
|
||||
<label class="admin-option">Display name: <input type="text" name="display_name" value="<?= $user->displayName ?>" required></label><br>
|
||||
</fieldset>
|
||||
<fieldset id="site_settings" class="admin-settings-group">
|
||||
<legend>Site settings</legend>
|
||||
<label class="admin-option">Title: <input type="text" name="site_title" value="<?= $config->siteTitle ?>" required></label><br>
|
||||
<label class="admin-option">Description: <input type="text" name="site_description" value="<?= $config->siteDescription ?>"></label><br>
|
||||
<label class="admin-option">Base path: <input type="text" name="base_path" value="<?= $config->basePath ?>" required></label><br>
|
||||
<label class="admin-option">Items per page (max 50): <input type="number" name="items_per_page" value="<?= $config->itemsPerPage ?>" min="1" max="50" required></label><br>
|
||||
</fieldset>
|
||||
<fieldset id="change_password" class="admin-settings-group">
|
||||
<legend>Change password</legend>
|
||||
<label class="admin-option">New password: <input type="password" name="password"></label><br>
|
||||
<label class="admin-option">Confirm new password: <input type="password" name="confirm_password"></label><br>
|
||||
</fieldset>
|
||||
<button type="submit">Save Settings</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -53,7 +53,7 @@ $ticks = iterator_to_array(stream_ticks($limit, $offset));
|
||||
<button type="submit">Tick</button>
|
||||
</form>
|
||||
<p>Current mood: <?= get_mood() ?> | <a href="<?= $config->basePath ?>set_mood.php">Set your mood</a></p>
|
||||
<p><a href="<?= $config->basePath ?>logout.php">Logout</a> <?= htmlspecialchars($_SESSION['username']) ?> </p>
|
||||
<p><a href="<?= $config->basePath . '/admin.php' ?>">Admin</a> | <a href="<?= $config->basePath ?>logout.php">Logout</a> <?= htmlspecialchars($_SESSION['username']) ?> </p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -39,6 +39,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$errors[] = "Items per page must be a number between 1 and 50.";
|
||||
}
|
||||
|
||||
// TODO: Actually handle errors
|
||||
if (empty($errors)) {
|
||||
$hash = password_hash($password, PASSWORD_DEFAULT);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user