Add support for Privacy Policy, Terms of Service, and CAPTCHA
This commit is contained in:
parent
756297671f
commit
c866e2f696
22 changed files with 795 additions and 138 deletions
|
@ -135,10 +135,10 @@ class CaptchaManager
|
|||
* Retrieves the captcha record for the given peer UUID.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $peer_uuid The UUID of the peer to retrieve the captcha for.
|
||||
* @return CaptchaRecord The captcha record.
|
||||
* @return CaptchaRecord|null The captcha record.
|
||||
* @throws DatabaseOperationException If the operation fails.
|
||||
*/
|
||||
public static function getCaptcha(string|RegisteredPeerRecord $peer_uuid): CaptchaRecord
|
||||
public static function getCaptcha(string|RegisteredPeerRecord $peer_uuid): ?CaptchaRecord
|
||||
{
|
||||
// If the peer_uuid is a RegisteredPeerRecord, get the UUID
|
||||
if($peer_uuid instanceof RegisteredPeerRecord)
|
||||
|
@ -162,7 +162,7 @@ class CaptchaManager
|
|||
|
||||
if($result === false)
|
||||
{
|
||||
throw new DatabaseOperationException('The requested captcha does not exist');
|
||||
return null;
|
||||
}
|
||||
|
||||
return CaptchaRecord::fromArray($result);
|
||||
|
@ -175,7 +175,7 @@ class CaptchaManager
|
|||
* @return bool True if a captcha exists, false otherwise.
|
||||
* @throws DatabaseOperationException If the operation fails.
|
||||
*/
|
||||
private static function captchaExists(string|RegisteredPeerRecord $peer_uuid): bool
|
||||
public static function captchaExists(string|RegisteredPeerRecord $peer_uuid): bool
|
||||
{
|
||||
// If the peer_uuid is a RegisteredPeerRecord, get the UUID
|
||||
if($peer_uuid instanceof RegisteredPeerRecord)
|
||||
|
|
187
src/Socialbox/Managers/PasswordManager.php
Normal file
187
src/Socialbox/Managers/PasswordManager.php
Normal file
|
@ -0,0 +1,187 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Managers;
|
||||
|
||||
use PDO;
|
||||
use Socialbox\Classes\Database;
|
||||
use Socialbox\Classes\SecuredPassword;
|
||||
use Socialbox\Exceptions\CryptographyException;
|
||||
use Socialbox\Exceptions\DatabaseOperationException;
|
||||
use Socialbox\Objects\Database\RegisteredPeerRecord;
|
||||
use Socialbox\Objects\Database\SecurePasswordRecord;
|
||||
|
||||
class PasswordManager
|
||||
{
|
||||
/**
|
||||
* Checks if the given peer UUID is associated with a password in the database.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $peerUuid The UUID of the peer, or an instance of RegisteredPeerRecord from which the UUID will be retrieved.
|
||||
* @return bool Returns true if the peer UUID is associated with a password, otherwise false.
|
||||
* @throws DatabaseOperationException If an error occurs while querying the database.
|
||||
*/
|
||||
public static function usesPassword(string|RegisteredPeerRecord $peerUuid): bool
|
||||
{
|
||||
if($peerUuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$peerUuid = $peerUuid->getUuid();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$stmt = Database::getConnection()->prepare('SELECT COUNT(*) FROM authentication_passwords WHERE peer_uuid=:uuid');
|
||||
$stmt->bindParam(':uuid', $peerUuid);
|
||||
$stmt->execute();
|
||||
|
||||
return $stmt->fetchColumn() > 0;
|
||||
}
|
||||
catch (\PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('An error occurred while checking the password usage in the database', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a password for a given user or peer record by securely encrypting it
|
||||
* and storing it in the authentication_passwords database table.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $peerUuid The UUID of the peer or an instance of RegisteredPeerRecord.
|
||||
* @param string $password The plaintext password to be securely stored.
|
||||
* @throws CryptographyException If an error occurs while securing the password.
|
||||
* @throws DatabaseOperationException If an error occurs while attempting to store the password in the database.
|
||||
* @throws \DateMalformedStringException If the updated timestamp cannot be formatted.
|
||||
* @return void
|
||||
*/
|
||||
public static function setPassword(string|RegisteredPeerRecord $peerUuid, string $password): void
|
||||
{
|
||||
if($peerUuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$peerUuid = $peerUuid->getUuid();
|
||||
}
|
||||
|
||||
$encryptionRecord = EncryptionRecordsManager::getRandomRecord();
|
||||
$securedPassword = SecuredPassword::securePassword($peerUuid, $password, $encryptionRecord);
|
||||
|
||||
try
|
||||
{
|
||||
$stmt = Database::getConnection()->prepare("INSERT INTO authentication_passwords (peer_uuid, iv, encrypted_password, encrypted_tag) VALUES (:peer_uuid, :iv, :encrypted_password, :encrypted_tag)");
|
||||
$stmt->bindParam(":peer_uuid", $peerUuid);
|
||||
|
||||
$iv = $securedPassword->getIv();
|
||||
$stmt->bindParam(':iv', $iv);
|
||||
|
||||
$encryptedPassword = $securedPassword->getEncryptedPassword();
|
||||
$stmt->bindParam(':encrypted_password', $encryptedPassword);
|
||||
|
||||
$encryptedTag = $securedPassword->getEncryptedTag();
|
||||
$stmt->bindParam(':encrypted_tag', $encryptedTag);
|
||||
|
||||
$stmt->execute();
|
||||
}
|
||||
catch(\PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException(sprintf('Failed to set password for user %s', $peerUuid), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the password for a given peer identified by their UUID or a RegisteredPeerRecord.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $peerUuid The UUID of the peer or an instance of RegisteredPeerRecord.
|
||||
* @param string $newPassword The new password to be set for the peer.
|
||||
* @throws CryptographyException If an error occurs while securing the new password.
|
||||
* @throws DatabaseOperationException If the update operation fails due to a database error.
|
||||
* @throws \DateMalformedStringException If the updated timestamp cannot be formatted.
|
||||
* @returns void
|
||||
*/
|
||||
public static function updatePassword(string|RegisteredPeerRecord $peerUuid, string $newPassword): void
|
||||
{
|
||||
if($peerUuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$peerUuid = $peerUuid->getUuid();
|
||||
}
|
||||
|
||||
|
||||
$encryptionRecord = EncryptionRecordsManager::getRandomRecord();
|
||||
$securedPassword = SecuredPassword::securePassword($peerUuid, $newPassword, $encryptionRecord);
|
||||
|
||||
try
|
||||
{
|
||||
$stmt = Database::getConnection()->prepare("UPDATE authentication_passwords SET iv=:iv, encrypted_password=:encrypted_password, encrypted_tag=:encrypted_tag, updated=:updated WHERE peer_uuid=:peer_uuid");
|
||||
$stmt->bindParam(":peer_uuid", $peerUuid);
|
||||
|
||||
$iv = $securedPassword->getIv();
|
||||
$stmt->bindParam(':iv', $iv);
|
||||
|
||||
$encryptedPassword = $securedPassword->getEncryptedPassword();
|
||||
$stmt->bindParam(':encrypted_password', $encryptedPassword);
|
||||
|
||||
$encryptedTag = $securedPassword->getEncryptedTag();
|
||||
$stmt->bindParam(':encrypted_tag', $encryptedTag);
|
||||
|
||||
$updated = $securedPassword->getUpdated()->format('Y-m-d H:i:s');
|
||||
$stmt->bindParam(':updated', $updated);
|
||||
|
||||
$stmt->execute();
|
||||
}
|
||||
catch(\PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException(sprintf('Failed to update password for user %s', $peerUuid), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the password record associated with the given peer UUID.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $peerUuid The UUID of the peer or an instance of RegisteredPeerRecord.
|
||||
* @return SecurePasswordRecord|null Returns a SecurePasswordRecord if found, or null if no record is present.
|
||||
* @throws DatabaseOperationException If a database operation error occurs during the retrieval process.
|
||||
*/
|
||||
private static function getPassword(string|RegisteredPeerRecord $peerUuid): ?SecurePasswordRecord
|
||||
{
|
||||
if($peerUuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$peerUuid = $peerUuid->getUuid();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare("SELECT * FROM authentication_passwords WHERE peer_uuid=:peer_uuid LIMIT 1");
|
||||
$statement->bindParam(':peer_uuid', $peerUuid);
|
||||
|
||||
$statement->execute();
|
||||
$data = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($data === false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return SecurePasswordRecord::fromArray($data);
|
||||
}
|
||||
catch(\PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException(sprintf('Failed to retrieve password record for user %s', $peerUuid), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the provided password matches the secured password associated with the given peer UUID.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $peerUuid The unique identifier or registered peer record of the user.
|
||||
* @param string $password The password to be verified.
|
||||
* @return bool Returns true if the password is verified successfully; otherwise, false.
|
||||
* @throws DatabaseOperationException If an error occurs while retrieving the password record from the database.
|
||||
* @throws CryptographyException If an error occurs while verifying the password.
|
||||
*/
|
||||
public static function verifyPassword(string|RegisteredPeerRecord $peerUuid, string $password): bool
|
||||
{
|
||||
$securedPassword = self::getPassword($peerUuid);
|
||||
if($securedPassword === null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$encryptionRecords = EncryptionRecordsManager::getAllRecords();
|
||||
return SecuredPassword::verifyPassword($password, $securedPassword, $encryptionRecords);
|
||||
}
|
||||
}
|
|
@ -361,7 +361,7 @@
|
|||
throw new StandardException(sprintf("The requested session '%s' does not exist", $uuid), StandardError::SESSION_NOT_FOUND);
|
||||
}
|
||||
|
||||
return Utilities::unserializeList($data['flags']);
|
||||
return SessionFlags::fromString($data['flags']);
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
|
@ -404,7 +404,7 @@
|
|||
* Removes specified flags from the session associated with the given UUID.
|
||||
*
|
||||
* @param string $uuid The UUID of the session from which the flags will be removed.
|
||||
* @param array $flags An array of flags to be removed from the session.
|
||||
* @param SessionFlags[] $flags An array of flags to be removed from the session.
|
||||
* @return void
|
||||
* @throws DatabaseOperationException|StandardException If there is an error while updating the session in the database.
|
||||
*/
|
||||
|
@ -412,16 +412,15 @@
|
|||
{
|
||||
Logger::getLogger()->verbose(sprintf("Removing flags from session %s", $uuid));
|
||||
|
||||
// First get the existing flags
|
||||
$existingFlags = self::getFlags($uuid);
|
||||
|
||||
// Remove the specified flags
|
||||
$flags = array_diff($existingFlags, $flags);
|
||||
$flagsToRemove = array_map(fn($flag) => $flag->value, $flags);
|
||||
$updatedFlags = array_filter($existingFlags, fn($flag) => !in_array($flag->value, $flagsToRemove));
|
||||
$flags = SessionFlags::toString($updatedFlags);
|
||||
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare("UPDATE sessions SET flags=? WHERE uuid=?");
|
||||
$statement->bindValue(1, Utilities::serializeList($flags));
|
||||
$statement->bindValue(1, $flags); // Directly use the toString() result
|
||||
$statement->bindParam(2, $uuid);
|
||||
$statement->execute();
|
||||
}
|
||||
|
@ -430,4 +429,29 @@
|
|||
throw new DatabaseOperationException('Failed to remove flags from session', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the authentication status for the specified session.
|
||||
*
|
||||
* @param string $uuid The unique identifier of the session to be updated.
|
||||
* @param bool $authenticated The authentication status to set for the session.
|
||||
* @return void
|
||||
* @throws DatabaseOperationException If the database operation fails.
|
||||
*/
|
||||
public static function setAuthenticated(string $uuid, bool $authenticated): void
|
||||
{
|
||||
Logger::getLogger()->verbose(sprintf("Setting session %s as authenticated: %s", $uuid, $authenticated ? 'true' : 'false'));
|
||||
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare("UPDATE sessions SET authenticated=? WHERE uuid=?");
|
||||
$statement->bindParam(1, $authenticated);
|
||||
$statement->bindParam(2, $uuid);
|
||||
$statement->execute();
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to update authenticated peer', $e);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue