Made message signing in Cryptography use SHA512 as the message content for... #1
4 changed files with 591 additions and 0 deletions
|
@ -14,6 +14,10 @@ enum PeerFlags : string
|
|||
// Verification Flags
|
||||
case VER_SET_PASSWORD = 'VER_SET_PASSWORD';
|
||||
case VER_SET_OTP = 'VER_SET_OTP';
|
||||
case VER_SET_DISPLAY_NAME = 'VER_SET_DISPLAY_NAME';
|
||||
case VER_EMAIL = 'VER_EMAIL';
|
||||
case VER_SMS = 'VER_SMS';
|
||||
case VER_PHONE_CALL = 'VER_PHONE_CALL';
|
||||
case VER_SOLVE_IMAGE_CAPTCHA = 'VER_SOLVE_IMAGE_CAPTCHA';
|
||||
|
||||
/**
|
||||
|
|
365
src/Socialbox/Managers/RegisteredPeerManager.php
Normal file
365
src/Socialbox/Managers/RegisteredPeerManager.php
Normal file
|
@ -0,0 +1,365 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Managers;
|
||||
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use Socialbox\Classes\Configuration;
|
||||
use Socialbox\Classes\Database;
|
||||
use Socialbox\Enums\Flags\PeerFlags;
|
||||
use Socialbox\Enums\StandardError;
|
||||
use Socialbox\Exceptions\DatabaseOperationException;
|
||||
use Socialbox\Exceptions\StandardException;
|
||||
use Socialbox\Objects\Database\RegisteredPeerRecord;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
class RegisteredPeerManager
|
||||
{
|
||||
/**
|
||||
* Checks if a username already exists in the database.
|
||||
*
|
||||
* @param string $username The username to check.
|
||||
* @return bool True if the username exists, false otherwise.
|
||||
* @throws DatabaseOperationException If the operation fails.
|
||||
*/
|
||||
public static function usernameExists(string $username): bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare('SELECT COUNT(*) FROM `registered_peers` WHERE username=?');
|
||||
$statement->bindParam(1, $username);
|
||||
$statement->execute();
|
||||
|
||||
$result = $statement->fetchColumn();
|
||||
return $result > 0;
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to check if the username exists', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new peer with the given username.
|
||||
*
|
||||
* @param string $username The username to associate with the new peer.
|
||||
* @param bool $enabled True if the peer should be enabled, false otherwise.
|
||||
* @return string The UUID of the newly created peer.
|
||||
* @throws DatabaseOperationException If the operation fails.
|
||||
*/
|
||||
public static function createPeer(string $username, bool $enabled=false): string
|
||||
{
|
||||
if(self::usernameExists($username))
|
||||
{
|
||||
throw new DatabaseOperationException('The username already exists');
|
||||
}
|
||||
|
||||
$uuid = Uuid::v4()->toRfc4122();
|
||||
|
||||
// If `enabled` is True, we insert the peer into the database as an activated account.
|
||||
if($enabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare('INSERT INTO `registered_peers` (uuid, username, enabled) VALUES (?, ?, ?)');
|
||||
$statement->bindParam(1, $uuid);
|
||||
$statement->bindParam(2, $username);
|
||||
$statement->bindParam(3, $enabled, PDO::PARAM_BOOL);
|
||||
$statement->execute();
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to create the peer in the database', $e);
|
||||
}
|
||||
|
||||
return $uuid;
|
||||
}
|
||||
|
||||
// Otherwise, we insert the peer into the database as a disabled account & the required verification flags.
|
||||
$flags = [];
|
||||
|
||||
if(Configuration::getRegistrationConfiguration()->isRegistrationEnabled())
|
||||
{
|
||||
$flags[] = PeerFlags::VER_EMAIL;
|
||||
}
|
||||
|
||||
if(Configuration::getRegistrationConfiguration()->isPasswordRequired())
|
||||
{
|
||||
$flags[] = PeerFlags::VER_SET_PASSWORD;
|
||||
}
|
||||
|
||||
if(Configuration::getRegistrationConfiguration()->isOtpRequired())
|
||||
{
|
||||
$flags[] = PeerFlags::VER_SET_OTP;
|
||||
}
|
||||
|
||||
if(Configuration::getRegistrationConfiguration()->isDisplayNameRequired())
|
||||
{
|
||||
$flags[] = PeerFlags::VER_SET_DISPLAY_NAME;
|
||||
}
|
||||
|
||||
if(Configuration::getRegistrationConfiguration()->isEmailVerificationRequired())
|
||||
{
|
||||
$flags[] = PeerFlags::VER_EMAIL;
|
||||
}
|
||||
|
||||
if(Configuration::getRegistrationConfiguration()->isSmsVerificationRequired())
|
||||
{
|
||||
$flags[] = PeerFlags::VER_SMS;
|
||||
}
|
||||
|
||||
if(Configuration::getRegistrationConfiguration()->isPhoneCallVerificationRequired())
|
||||
{
|
||||
$flags[] = PeerFlags::VER_PHONE_CALL;
|
||||
}
|
||||
|
||||
if(Configuration::getRegistrationConfiguration()->isImageCaptchaVerificationRequired())
|
||||
{
|
||||
$flags[] = PeerFlags::VER_SOLVE_IMAGE_CAPTCHA;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$implodedFlags = implode(',', $flags);
|
||||
$statement = Database::getConnection()->prepare('INSERT INTO `registered_peers` (uuid, username, enabled, flags) VALUES (?, ?, ?, ?)');
|
||||
$statement->bindParam(1, $uuid);
|
||||
$statement->bindParam(2, $username);
|
||||
$statement->bindParam(3, $enabled, PDO::PARAM_BOOL);
|
||||
$statement->bindParam(4, $implodedFlags);
|
||||
$statement->execute();
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to create the peer in the database', $e);
|
||||
}
|
||||
|
||||
return $uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a peer from the database based on the given UUID or RegisteredPeerRecord.
|
||||
* WARNING: This operation is cascading and will delete all associated data.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer to be deleted.
|
||||
* @return void
|
||||
* @throws DatabaseOperationException If the operation fails.
|
||||
*/
|
||||
public static function deletePeer(string|RegisteredPeerRecord $uuid): void
|
||||
{
|
||||
if($uuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$uuid = $uuid->getUuid();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare('DELETE FROM `registered_peers` WHERE uuid=?');
|
||||
$statement->bindParam(1, $uuid);
|
||||
$statement->execute();
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to delete the peer from the database', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a registered peer record based on the given unique identifier or RegisteredPeerRecord object.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $uuid The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
|
||||
* @return RegisteredPeerRecord Returns a RegisteredPeerRecord object containing the peer's information.
|
||||
* @throws StandardException If the requested peer does not exist.
|
||||
* @throws DatabaseOperationException If there is an error during the database operation.
|
||||
*/
|
||||
public static function getPeer(string|RegisteredPeerRecord $uuid): RegisteredPeerRecord
|
||||
{
|
||||
if($uuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$uuid = $uuid->getUuid();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare('SELECT * FROM `registered_peers` WHERE uuid=?');
|
||||
$statement->bindParam(1, $uuid);
|
||||
$statement->execute();
|
||||
|
||||
$result = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if($result === false)
|
||||
{
|
||||
throw new StandardException(sprintf("The requested peer '%s' does not exist", $uuid), StandardError::PEER_NOT_FOUND);
|
||||
}
|
||||
|
||||
return new RegisteredPeerRecord($result);
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to get the peer from the database', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a peer record by the given username.
|
||||
*
|
||||
* @param string $username The username of the peer to be retrieved.
|
||||
* @return RegisteredPeerRecord The record of the peer associated with the given username.
|
||||
* @throws DatabaseOperationException If there is an error while querying the database.
|
||||
* @throws StandardException If the peer does not exist.
|
||||
*/
|
||||
public static function getPeerByUsername(string $username): RegisteredPeerRecord
|
||||
{
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare('SELECT * FROM `registered_peers` WHERE username=?');
|
||||
$statement->bindParam(1, $username);
|
||||
$statement->execute();
|
||||
|
||||
$result = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if($result === false)
|
||||
{
|
||||
throw new StandardException(sprintf("The requested peer '%s' does not exist", $username), StandardError::PEER_NOT_FOUND);
|
||||
}
|
||||
|
||||
return new RegisteredPeerRecord($result);
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to get the peer from the database', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a peer identified by the given UUID or RegisteredPeerRecord.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer to be enabled.
|
||||
* @return void
|
||||
* @throws DatabaseOperationException If there is an error while updating the database.
|
||||
*/
|
||||
public static function enablePeer(string|RegisteredPeerRecord $uuid): void
|
||||
{
|
||||
if($uuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$uuid = $uuid->getUuid();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET enabled=1 WHERE uuid=?');
|
||||
$statement->bindParam(1, $uuid);
|
||||
$statement->execute();
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to enable the peer in the database', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the peer identified by the given UUID or RegisteredPeerRecord.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer.
|
||||
* @return void
|
||||
* @throws DatabaseOperationException If there is an error while updating the peer's status in the database.
|
||||
*/
|
||||
public static function disablePeer(string|RegisteredPeerRecord $uuid): void
|
||||
{
|
||||
if($uuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$uuid = $uuid->getUuid();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET enabled=0 WHERE uuid=?');
|
||||
$statement->bindParam(1, $uuid);
|
||||
$statement->execute();
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to disable the peer in the database', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a specific flag to the peer identified by the given UUID or RegisteredPeerRecord.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer.
|
||||
* @param PeerFlags|array $flags The flag or array of flags to be added to the peer.
|
||||
* @return void
|
||||
* @throws DatabaseOperationException If there is an error while updating the database.
|
||||
* @throws StandardException If the peer does not exist.
|
||||
*/
|
||||
public static function addFlag(string|RegisteredPeerRecord $uuid, PeerFlags|array $flags): void
|
||||
{
|
||||
if($uuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$uuid = $uuid->getUuid();
|
||||
}
|
||||
|
||||
$peer = self::getPeer($uuid);
|
||||
$existingFlags = $peer->getFlags();
|
||||
$flags = is_array($flags) ? $flags : [$flags];
|
||||
|
||||
foreach($flags as $flag)
|
||||
{
|
||||
if(!in_array($flag, $existingFlags))
|
||||
{
|
||||
$existingFlags[] = $flag;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$implodedFlags = implode(',', array_map(fn($flag) => $flag->name, $existingFlags));
|
||||
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET flags=? WHERE uuid=?');
|
||||
$statement->bindParam(1, $implodedFlags);
|
||||
$statement->bindParam(2, $uuid);
|
||||
$statement->execute();
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to add the flag to the peer in the database', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a specific flag from the peer identified by the given UUID or RegisteredPeerRecord.
|
||||
*
|
||||
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer.
|
||||
* @param PeerFlags $flag The flag to be removed from the peer.
|
||||
* @return void
|
||||
* @throws DatabaseOperationException If there is an error while updating the database.
|
||||
* @throws StandardException If the peer does not exist.
|
||||
*/
|
||||
public static function removeFlag(string|RegisteredPeerRecord $uuid, PeerFlags $flag): void
|
||||
{
|
||||
if($uuid instanceof RegisteredPeerRecord)
|
||||
{
|
||||
$uuid = $uuid->getUuid();
|
||||
}
|
||||
|
||||
$peer = self::getPeer($uuid);
|
||||
if(!$peer->flagExists($flag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$flags = $peer->getFlags();
|
||||
unset($flags[array_search($flag, $flags)]);
|
||||
|
||||
try
|
||||
{
|
||||
$implodedFlags = implode(',', $flags);
|
||||
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET flags=? WHERE uuid=?');
|
||||
$statement->bindParam(1, $implodedFlags);
|
||||
$statement->bindParam(2, $uuid);
|
||||
$statement->execute();
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new DatabaseOperationException('Failed to remove the flag from the peer in the database', $e);
|
||||
}
|
||||
}
|
||||
}
|
144
src/Socialbox/Objects/Database/RegisteredPeerRecord.php
Normal file
144
src/Socialbox/Objects/Database/RegisteredPeerRecord.php
Normal file
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Objects\Database;
|
||||
|
||||
use DateTime;
|
||||
use Socialbox\Enums\Flags\PeerFlags;
|
||||
use Socialbox\Interfaces\SerializableInterface;
|
||||
|
||||
class RegisteredPeerRecord implements SerializableInterface
|
||||
{
|
||||
private string $uuid;
|
||||
private string $username;
|
||||
private ?string $displayName;
|
||||
/**
|
||||
* @var PeerFlags[]
|
||||
*/
|
||||
private ?array $flags;
|
||||
private bool $enabled;
|
||||
private DateTime $created;
|
||||
|
||||
/**
|
||||
* Constructor for initializing class properties from provided data.
|
||||
*
|
||||
* @param array $data Array containing initialization data.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $data)
|
||||
{
|
||||
$this->uuid = $data['uuid'];
|
||||
$this->username = $data['username'];
|
||||
$this->displayName = $data['display_name'] ?? null;
|
||||
|
||||
if($data['flags'])
|
||||
{
|
||||
if(is_array($data['flags']))
|
||||
{
|
||||
$this->flags = array_map(fn($flag) => PeerFlags::from($flag), $data['flags']);
|
||||
}
|
||||
elseif(is_string($data['flags']))
|
||||
{
|
||||
$flags = explode(',', $data['flags']);
|
||||
$this->flags = array_map(fn($flag) => PeerFlags::from($flag), $flags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->flags = [];
|
||||
}
|
||||
|
||||
$this->enabled = $data['enabled'];
|
||||
|
||||
if (is_string($data['created']))
|
||||
{
|
||||
$this->created = new DateTime($data['created']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->created = $data['created'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the UUID of the current instance.
|
||||
*
|
||||
* @return string The UUID.
|
||||
*/
|
||||
public function getUuid(): string
|
||||
{
|
||||
return $this->uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the username.
|
||||
*
|
||||
* @return string The username.
|
||||
*/
|
||||
public function getUsername(): string
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the display name.
|
||||
*
|
||||
* @return string|null The display name if set, or null otherwise.
|
||||
*/
|
||||
public function getDisplayName(): ?string
|
||||
{
|
||||
return $this->displayName;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function flagExists(PeerFlags $flag): bool
|
||||
{
|
||||
return in_array($flag, $this->flags, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current instance is enabled.
|
||||
*
|
||||
* @return bool True if enabled, false otherwise.
|
||||
*/
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the creation date and time.
|
||||
*
|
||||
* @return DateTime The creation date and time.
|
||||
*/
|
||||
public function getCreated(): DateTime
|
||||
{
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function fromArray(array $data): object
|
||||
{
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'uuid' => $this->uuid,
|
||||
'username' => $this->username,
|
||||
'display_name' => $this->displayName,
|
||||
'flags' => implode(',', array_map(fn($flag) => $flag->name, $this->flags)),
|
||||
'enabled' => $this->enabled,
|
||||
'created' => $this->created
|
||||
];
|
||||
}
|
||||
}
|
78
tests/Socialbox/Managers/RegisteredPeerManagerTest.php
Normal file
78
tests/Socialbox/Managers/RegisteredPeerManagerTest.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Managers;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Socialbox\Enums\Flags\PeerFlags;
|
||||
|
||||
class RegisteredPeerManagerTest extends TestCase
|
||||
{
|
||||
private static $peerUuid;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
if(RegisteredPeerManager::usernameExists('test_peer'))
|
||||
{
|
||||
RegisteredPeerManager::deletePeer(RegisteredPeerManager::getPeerByUsername('test_peer')->getUuid());
|
||||
}
|
||||
|
||||
self::$peerUuid = RegisteredPeerManager::createPeer('test_peer', true);
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass(): void
|
||||
{
|
||||
if(RegisteredPeerManager::usernameExists('test_peer'))
|
||||
{
|
||||
RegisteredPeerManager::deletePeer(RegisteredPeerManager::getPeerByUsername('test_peer')->getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
public function testEnablePeer()
|
||||
{
|
||||
RegisteredPeerManager::enablePeer(self::$peerUuid);
|
||||
$peer = RegisteredPeerManager::getPeer(self::$peerUuid);
|
||||
|
||||
$this->assertTrue($peer->isEnabled());
|
||||
}
|
||||
|
||||
|
||||
public function testGetPeer()
|
||||
{
|
||||
$peer = RegisteredPeerManager::getPeer(self::$peerUuid);
|
||||
|
||||
$this->assertEquals('test_peer', $peer->getUsername());
|
||||
}
|
||||
|
||||
public function testGetPeerByUsername()
|
||||
{
|
||||
$peer = RegisteredPeerManager::getPeerByUsername('test_peer');
|
||||
|
||||
$this->assertEquals(self::$peerUuid, $peer->getUuid());
|
||||
}
|
||||
|
||||
public function testUsernameExists()
|
||||
{
|
||||
$this->assertTrue(RegisteredPeerManager::usernameExists('test_peer'));
|
||||
}
|
||||
|
||||
public function testDisablePeer()
|
||||
{
|
||||
RegisteredPeerManager::disablePeer(self::$peerUuid);
|
||||
$peer = RegisteredPeerManager::getPeer(self::$peerUuid);
|
||||
|
||||
$this->assertFalse($peer->isEnabled());
|
||||
}
|
||||
|
||||
public function testRemoveFlag()
|
||||
{
|
||||
RegisteredPeerManager::addFlag(self::$peerUuid, PeerFlags::ADMIN);
|
||||
$peer = RegisteredPeerManager::getPeer(self::$peerUuid);
|
||||
|
||||
$this->assertTrue($peer->flagExists(PeerFlags::ADMIN));
|
||||
|
||||
RegisteredPeerManager::removeFlag(self::$peerUuid, PeerFlags::ADMIN);
|
||||
$peer = RegisteredPeerManager::getPeer(self::$peerUuid);
|
||||
|
||||
$this->assertFalse($peer->flagExists(PeerFlags::ADMIN));
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue