Add single user security mode (#3)
- Tweaks to SQL column definitions - Implement class autoloading - Split user config into its own file
This commit is contained in:
parent
8db4216ea2
commit
74bc83f266
|
@ -14,6 +14,9 @@ class Data {
|
||||||
return $db;
|
return $db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure the expected tables exist
|
||||||
|
*/
|
||||||
public static function ensureDb(): void {
|
public static function ensureDb(): void {
|
||||||
$db = self::getConnection();
|
$db = self::getConnection();
|
||||||
$tables = array();
|
$tables = array();
|
||||||
|
@ -24,8 +27,7 @@ class Data {
|
||||||
CREATE TABLE frc_user (
|
CREATE TABLE frc_user (
|
||||||
id INTEGER NOT NULL PRIMARY KEY,
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
email TEXT NOT NULL,
|
email TEXT NOT NULL,
|
||||||
password TEXT NOT NULL,
|
password TEXT NOT NULL)
|
||||||
salt TEXT NOT NULL)
|
|
||||||
SQL;
|
SQL;
|
||||||
$db->exec($query);
|
$db->exec($query);
|
||||||
$db->exec('CREATE INDEX idx_user_email ON frc_user (email)');
|
$db->exec('CREATE INDEX idx_user_email ON frc_user (email)');
|
||||||
|
@ -50,15 +52,46 @@ class Data {
|
||||||
published_on TEXT NOT NULL,
|
published_on TEXT NOT NULL,
|
||||||
updated_on TEXT,
|
updated_on TEXT,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
is_encoded INTEGER NOT NULL,
|
is_encoded BOOLEAN NOT NULL,
|
||||||
is_read INTEGER NOT NULL,
|
is_read BOOLEAN NOT NULL,
|
||||||
is_bookmarked INTEGER NOT NULL,
|
is_bookmarked BOOLEAN NOT NULL,
|
||||||
FOREIGN KEY (feed_id) REFERENCES feed (id))
|
FOREIGN KEY (feed_id) REFERENCES feed (id))
|
||||||
SQL;
|
SQL;
|
||||||
$db->exec($query);
|
$db->exec($query);
|
||||||
}
|
}
|
||||||
$db->close();
|
$db->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a user by their ID
|
||||||
|
*
|
||||||
|
* @param string $email The e-mail address of the user to retrieve
|
||||||
|
* @return array|null The user information, or null if the user is not found
|
||||||
|
*/
|
||||||
|
public static function findUserByEmail(string $email): ?array {
|
||||||
|
$db = self::getConnection();
|
||||||
|
$query = $db->prepare('SELECT * FROM frc_user WHERE email = :email');
|
||||||
|
$query->bindValue(':email', $email);
|
||||||
|
$result = $query->execute();
|
||||||
|
if ($result) {
|
||||||
|
$user = $result->fetchArray(SQLITE3_ASSOC);
|
||||||
|
if ($user) return $user;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Data::ensureDb();
|
/**
|
||||||
|
* Add a user
|
||||||
|
*
|
||||||
|
* @param string $email The e-mail address for the user
|
||||||
|
* @param string $password The user's password
|
||||||
|
*/
|
||||||
|
public static function addUser(string $email, string $password): void {
|
||||||
|
$db = self::getConnection();
|
||||||
|
$query = $db->prepare('INSERT INTO frc_user (email, password) VALUES (:email, :password)');
|
||||||
|
$query->bindValue(':email', $email);
|
||||||
|
$query->bindValue(':password', password_hash($password, PASSWORD_DEFAULT));
|
||||||
|
$query->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
51
src/lib/Security.php
Normal file
51
src/lib/Security.php
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Security functions
|
||||||
|
*/
|
||||||
|
class Security {
|
||||||
|
|
||||||
|
/** @var int Run as a single user requiring no password */
|
||||||
|
public const int SINGLE_USER = 0;
|
||||||
|
|
||||||
|
/** @var int Run as a single user requiring a password */
|
||||||
|
public const int SINGLE_USER_WITH_PASSWORD = 1;
|
||||||
|
|
||||||
|
/** @var int Require users to provide e-mail address and password */
|
||||||
|
public const int MULTI_USER = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that user is logged on
|
||||||
|
* @param bool $redirectIfAnonymous Whether to redirect the request if there is no user logged on
|
||||||
|
*/
|
||||||
|
public static function verifyUser(bool $redirectIfAnonymous = true): void {
|
||||||
|
switch (SECURITY_MODEL) {
|
||||||
|
case self::SINGLE_USER:
|
||||||
|
$user = self::retrieveSingleUser();
|
||||||
|
break;
|
||||||
|
case self::SINGLE_USER_WITH_PASSWORD:
|
||||||
|
die('Single User w/ Password has not yet been implemented');
|
||||||
|
case self::MULTI_USER:
|
||||||
|
die('Multi-User Mode has not yet been implemented');
|
||||||
|
default:
|
||||||
|
die('Unrecognized security model (' . SECURITY_MODEL . ')');
|
||||||
|
}
|
||||||
|
if (!$user && $redirectIfAnonymous) {
|
||||||
|
header('/logon?returnTo=' . $_SERVER["REQUEST_URI"], true, HTTP_REDIRECT_TEMP);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
$_REQUEST['FRC_USER_ID'] = $user['id'];
|
||||||
|
$_REQUEST['FRC_USER_EMAIL'] = $user['email'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the single user
|
||||||
|
* @return array The user information for the single user
|
||||||
|
*/
|
||||||
|
private static function retrieveSingleUser(): array {
|
||||||
|
$user = Data::findUserByEmail('solouser@example.com');
|
||||||
|
if ($user) return $user;
|
||||||
|
Data::addUser('solouser@example.com', 'no-password-required');
|
||||||
|
return Data::findUserByEmail('solouser@example.com');
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
include '../start.php';
|
include '../start.php';
|
||||||
|
|
||||||
|
Security::verifyUser();
|
||||||
|
|
||||||
page_head('Welcome');
|
page_head('Welcome');
|
||||||
?>
|
?>
|
||||||
<p>Startup worked</p>
|
<p>User ID <?=$_REQUEST['FRC_USER_ID']?> - e-mail <?=$_REQUEST['FRC_USER_EMAIL']?></p>
|
||||||
<?php
|
<?php
|
||||||
page_foot();
|
page_foot();
|
||||||
|
|
|
@ -1,23 +1,16 @@
|
||||||
<?php
|
<?php
|
||||||
// USER CONFIGURATION ITEMS
|
spl_autoload_register(function ($class) {
|
||||||
|
$file = implode(DIRECTORY_SEPARATOR, [ __DIR__, 'lib', "$class.php" ]);
|
||||||
|
if (file_exists($file)) {
|
||||||
|
require $file;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
require 'user-config.php';
|
||||||
* Which security model should the application use?
|
|
||||||
* - 0 = single-user, no password
|
|
||||||
* - 1 = single-user with password
|
|
||||||
* - 2 = multi-user (all users require passwords)
|
|
||||||
*
|
|
||||||
* (NOTE THAT 1 AND 2 HAVE NOT YET BEEN IMPLEMENTED)
|
|
||||||
*/
|
|
||||||
const SECURITY_MODEL = 0;
|
|
||||||
|
|
||||||
/** The name of the database file where users and feeds should be kept */
|
Data::ensureDb();
|
||||||
const DATABASE_NAME = 'frc.db';
|
|
||||||
|
|
||||||
// END USER CONFIGURATION ITEMS
|
|
||||||
// (editing below this line is not advised)
|
|
||||||
|
|
||||||
include 'lib/Data.php';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the page title
|
* Render the page title
|
||||||
|
|
23
src/user-config.php
Normal file
23
src/user-config.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* USER CONFIGURATION ITEMS
|
||||||
|
*
|
||||||
|
* Editing the values here customizes the behavior of Feed Reader Central
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which security model should the application use? Options are:
|
||||||
|
* - Security::SINGLE_USER (no e-mail required, does not require a password)
|
||||||
|
* - Security::SINGLE_USER_WITH_PASSWORD (no e-mail required, does require a password)
|
||||||
|
* - Security::MULTI_USER (e-mail and password required for all users)
|
||||||
|
*
|
||||||
|
* (NOTE THAT ONLY SINGLE_USER IS CURRENTLY IMPLEMENTED)
|
||||||
|
*/
|
||||||
|
const SECURITY_MODEL = Security::SINGLE_USER;
|
||||||
|
|
||||||
|
/** The name of the database file where users and feeds should be kept */
|
||||||
|
const DATABASE_NAME = 'frc.db';
|
||||||
|
|
||||||
|
// END USER CONFIGURATION ITEMS
|
||||||
|
// (editing below this line is not advised)
|
Loading…
Reference in New Issue
Block a user