refactor logout. cleanup
This commit is contained in:
parent
fea0e9eb53
commit
f635dd8724
@ -1,11 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// Start a session and create a csrf token if necessary
|
||||||
session_start();
|
// TODO - move these to an AuthController?
|
||||||
|
function start_session(){
|
||||||
if (!isset($_SESSION['csrf_token'])) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
session_start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generate_csrf_token(bool $regenerate = false){
|
||||||
|
if (!isset($_SESSION['csrf_token']) || $regenerate) {
|
||||||
|
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
start_session();
|
||||||
|
generate_csrf_token();
|
||||||
|
|
||||||
define('APP_ROOT', dirname(dirname(__FILE__)));
|
define('APP_ROOT', dirname(dirname(__FILE__)));
|
||||||
|
|
||||||
define('SRC_DIR', APP_ROOT . '/src');
|
define('SRC_DIR', APP_ROOT . '/src');
|
||||||
@ -94,11 +105,14 @@ header('Content-Type: text/html; charset=utf-8');
|
|||||||
// routes
|
// routes
|
||||||
$routes = [
|
$routes = [
|
||||||
['', 'HomeController'],
|
['', 'HomeController'],
|
||||||
['', 'HomeController@tick', ['POST']],
|
['', 'HomeController@handleTick', ['POST']],
|
||||||
['login', 'LoginController'],
|
['admin', 'AdminController'],
|
||||||
['login', 'LoginController@login', ['POST']],
|
['admin', 'AdminController@save', ['POST']],
|
||||||
|
['login', 'AuthController@showLogin'],
|
||||||
|
['login', 'AuthController@handleLogin', ['POST']],
|
||||||
|
['logout', 'AuthController@handleLogout', ['GET', 'POST']],
|
||||||
['mood', 'MoodController'],
|
['mood', 'MoodController'],
|
||||||
['mood', 'MoodController@set_mood', ['POST']],
|
['mood', 'MoodController@handleMood', ['POST']],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
114
src/Controller/Admin/Admin.php
Normal file
114
src/Controller/Admin/Admin.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
class AdminController {
|
||||||
|
// GET handler
|
||||||
|
// render the admin page
|
||||||
|
public function index(){
|
||||||
|
$config = Config::load();
|
||||||
|
$user = USER::load();
|
||||||
|
|
||||||
|
$vars = [
|
||||||
|
'user' => $user,
|
||||||
|
'config' => $config,
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
echo render_template(TEMPLATES_DIR . "/admin.php", $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST handler
|
||||||
|
// save updated settings
|
||||||
|
public function save(){
|
||||||
|
$isLoggedIn = isset($_SESSION['user_id']);
|
||||||
|
if (!$isLoggedIn){
|
||||||
|
header('Location: ' . $config->basePath . 'login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$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'] ?? '');
|
||||||
|
$about = trim($_POST['about'] ?? '');
|
||||||
|
$website = trim($_POST['website'] ?? '');
|
||||||
|
|
||||||
|
// 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.";
|
||||||
|
}
|
||||||
|
// Make sure the website looks like a URL and starts with a protocol
|
||||||
|
if ($website) {
|
||||||
|
if (!filter_var($website, FILTER_VALIDATE_URL)) {
|
||||||
|
$errors[] = "Please enter a valid URL (including http:// or https://).";
|
||||||
|
} elseif (!preg_match('/^https?:\/\//i', $website)) {
|
||||||
|
$errors[] = "URL must start with http:// or https://.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
$user->about = $about;
|
||||||
|
$user->website = $website;
|
||||||
|
|
||||||
|
// Save user profile and reload user from database
|
||||||
|
$user = $user->save();
|
||||||
|
|
||||||
|
// Update the password if one was sent
|
||||||
|
if($password){
|
||||||
|
$user->set_password($password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ' . $config->basePath . '/admin');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
class LoginController {
|
class AuthController {
|
||||||
function index(?string $error = null){
|
function showLogin(?string $error = null){
|
||||||
$config = Config::load();
|
$config = Config::load();
|
||||||
$csrf_token = $_SESSION['csrf_token'];
|
$csrf_token = $_SESSION['csrf_token'];
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ class LoginController {
|
|||||||
echo render_template(TEMPLATES_DIR . '/login.php', $vars);
|
echo render_template(TEMPLATES_DIR . '/login.php', $vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
function login(){
|
function handleLogin(){
|
||||||
$config = Config::load();
|
$config = Config::load();
|
||||||
|
|
||||||
$error = '';
|
$error = '';
|
||||||
@ -36,13 +36,21 @@ class LoginController {
|
|||||||
session_regenerate_id(true);
|
session_regenerate_id(true);
|
||||||
$_SESSION['user_id'] = $user['id'];
|
$_SESSION['user_id'] = $user['id'];
|
||||||
$_SESSION['username'] = $user['username'];
|
$_SESSION['username'] = $user['username'];
|
||||||
|
$_SESSION['csrf_token'] = generate_csrf_token(true);
|
||||||
header('Location: ' . $config->basePath);
|
header('Location: ' . $config->basePath);
|
||||||
exit;
|
exit;
|
||||||
} else {
|
} else {
|
||||||
$error = 'Invalid username or password';
|
$error = 'Invalid username or password';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$csrf_token = generateCsrfToken();
|
function handleLogout(){
|
||||||
|
$_SESSION = [];
|
||||||
|
session_destroy();
|
||||||
|
|
||||||
|
$config = Config::load();
|
||||||
|
header('Location: ' . $config->basePath);
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,7 +27,7 @@ class HomeController{
|
|||||||
|
|
||||||
// POST handler
|
// POST handler
|
||||||
// Saves the tick and reloads the homepage
|
// Saves the tick and reloads the homepage
|
||||||
public function tick(){
|
public function handleTick(){
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' and isset($_POST['tick'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' and isset($_POST['tick'])) {
|
||||||
// ensure that the session is valid before proceeding
|
// ensure that the session is valid before proceeding
|
||||||
if (!validateCsrfToken($_POST['csrf_token'])) {
|
if (!validateCsrfToken($_POST['csrf_token'])) {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
echo render_template(TEMPLATES_DIR . "/mood.php", $vars);
|
echo render_template(TEMPLATES_DIR . "/mood.php", $vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set_mood(){
|
public function handleMood(){
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' and isset($_POST['mood'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' and isset($_POST['mood'])) {
|
||||||
// ensure that the session is valid before proceeding
|
// ensure that the session is valid before proceeding
|
||||||
if (!validateCsrfToken($_POST['csrf_token'])) {
|
if (!validateCsrfToken($_POST['csrf_token'])) {
|
||||||
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
// go back to the index and show the updated mood
|
// go back to the index and show the updated mood
|
||||||
header('Location: ' . $config->basePath);
|
header('Location: ' . $config->basePath);
|
||||||
//exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
/*
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
@ -9,7 +10,7 @@ function generateCsrfToken() {
|
|||||||
}
|
}
|
||||||
return $_SESSION['csrf_token'];
|
return $_SESSION['csrf_token'];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
function validateCsrfToken($token) {
|
function validateCsrfToken($token) {
|
||||||
return hash_equals($_SESSION['csrf_token'], $token);
|
return hash_equals($_SESSION['csrf_token'], $token);
|
||||||
}
|
}
|
||||||
|
@ -1,102 +1,5 @@
|
|||||||
<?php
|
<?php /** @var Config $config */ ?>
|
||||||
#require_once __DIR__ . '/../bootstrap.php';
|
<?php /** @var User $user */ ?>
|
||||||
|
|
||||||
#confirm_setup();
|
|
||||||
|
|
||||||
#require_once CLASSES_DIR . '/Config.php';
|
|
||||||
#require LIB_DIR . '/session.php';
|
|
||||||
|
|
||||||
if (!$isLoggedIn){
|
|
||||||
header('Location: ' . $config->basePath . 'login.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
require CLASSES_DIR . '/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'] ?? '');
|
|
||||||
$about = trim($_POST['about'] ?? '');
|
|
||||||
$website = trim($_POST['website'] ?? '');
|
|
||||||
|
|
||||||
// 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.";
|
|
||||||
}
|
|
||||||
// Make sure the website looks like a URL and starts with a protocol
|
|
||||||
if ($website) {
|
|
||||||
if (!filter_var($website, FILTER_VALIDATE_URL)) {
|
|
||||||
$errors[] = "Please enter a valid URL (including http:// or https://).";
|
|
||||||
} elseif (!preg_match('/^https?:\/\//i', $website)) {
|
|
||||||
$errors[] = "URL must start with http:// or https://.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
$user->about = $about;
|
|
||||||
$user->website = $website;
|
|
||||||
|
|
||||||
// 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>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@ -111,6 +14,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
<div><a href="<?= $config->basePath ?>">Back to home</a></div>
|
<div><a href="<?= $config->basePath ?>">Back to home</a></div>
|
||||||
<div>
|
<div>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||||
<fieldset id="user_settings" class="admin-settings-group">
|
<fieldset id="user_settings" class="admin-settings-group">
|
||||||
<legend>User settings</legend>
|
<legend>User settings</legend>
|
||||||
<label class="admin-option">Username: <input type="text" name="username" value="<?= $user->username ?>" required></label><br>
|
<label class="admin-option">Username: <input type="text" name="username" value="<?= $user->username ?>" required></label><br>
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
#require_once __DIR__ . '/../bootstrap.php';
|
|
||||||
|
|
||||||
#confirm_setup();
|
|
||||||
|
|
||||||
#require_once CLASSES_DIR . '/Config.php';
|
|
||||||
#require LIB_DIR . '/session.php';
|
|
||||||
|
|
||||||
$config = Config::load();
|
|
||||||
$_SESSION = [];
|
$_SESSION = [];
|
||||||
session_destroy();
|
session_destroy();
|
||||||
|
|
||||||
|
$config = Config::load();
|
||||||
header('Location: ' . $config->basePath);
|
header('Location: ' . $config->basePath);
|
||||||
exit;
|
exit;
|
Loading…
x
Reference in New Issue
Block a user