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:
2024-04-05 22:14:24 -04:00
parent 8db4216ea2
commit 74bc83f266
5 changed files with 127 additions and 25 deletions

View File

@@ -14,6 +14,9 @@ class Data {
return $db;
}
/**
* Make sure the expected tables exist
*/
public static function ensureDb(): void {
$db = self::getConnection();
$tables = array();
@@ -24,8 +27,7 @@ class Data {
CREATE TABLE frc_user (
id INTEGER NOT NULL PRIMARY KEY,
email TEXT NOT NULL,
password TEXT NOT NULL,
salt TEXT NOT NULL)
password TEXT NOT NULL)
SQL;
$db->exec($query);
$db->exec('CREATE INDEX idx_user_email ON frc_user (email)');
@@ -50,15 +52,46 @@ class Data {
published_on TEXT NOT NULL,
updated_on TEXT,
content TEXT NOT NULL,
is_encoded INTEGER NOT NULL,
is_read INTEGER NOT NULL,
is_bookmarked INTEGER NOT NULL,
is_encoded BOOLEAN NOT NULL,
is_read BOOLEAN NOT NULL,
is_bookmarked BOOLEAN NOT NULL,
FOREIGN KEY (feed_id) REFERENCES feed (id))
SQL;
$db->exec($query);
}
$db->close();
}
}
Data::ensureDb();
/**
* 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;
}
/**
* 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
View 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');
}
}