Refactor and extend configuration classes.

This commit is contained in:
netkas 2024-12-23 19:02:37 -05:00
parent 01253d5115
commit 395e6b95ff
24 changed files with 1158 additions and 682 deletions

7
.idea/php.xml generated
View file

@ -58,7 +58,7 @@
<extension name="enchant" enabled="false" /> <extension name="enchant" enabled="false" />
<extension name="fann" enabled="false" /> <extension name="fann" enabled="false" />
<extension name="ffmpeg" enabled="false" /> <extension name="ffmpeg" enabled="false" />
<extension name="gd" enabled="false" /> <extension name="frankenphp" enabled="false" />
<extension name="gearman" enabled="false" /> <extension name="gearman" enabled="false" />
<extension name="geoip" enabled="false" /> <extension name="geoip" enabled="false" />
<extension name="geos" enabled="false" /> <extension name="geos" enabled="false" />
@ -77,7 +77,7 @@
<extension name="libevent" enabled="false" /> <extension name="libevent" enabled="false" />
<extension name="libsodium" enabled="false" /> <extension name="libsodium" enabled="false" />
<extension name="mailparse" enabled="false" /> <extension name="mailparse" enabled="false" />
<extension name="memcache" enabled="false" /> <extension name="memcached" enabled="false" />
<extension name="ming" enabled="false" /> <extension name="ming" enabled="false" />
<extension name="mongo" enabled="false" /> <extension name="mongo" enabled="false" />
<extension name="mongodb" enabled="false" /> <extension name="mongodb" enabled="false" />
@ -94,9 +94,6 @@
<extension name="odbc" enabled="false" /> <extension name="odbc" enabled="false" />
<extension name="opentelemetry" enabled="false" /> <extension name="opentelemetry" enabled="false" />
<extension name="pdflib" enabled="false" /> <extension name="pdflib" enabled="false" />
<extension name="pdo_ibm" enabled="false" />
<extension name="pdo_pgsql" enabled="false" />
<extension name="pdo_sqlite" enabled="false" />
<extension name="pgsql" enabled="false" /> <extension name="pgsql" enabled="false" />
<extension name="pspell" enabled="false" /> <extension name="pspell" enabled="false" />
<extension name="pthreads" enabled="false" /> <extension name="pthreads" enabled="false" />

View file

@ -2,8 +2,6 @@
<module type="WEB_MODULE" version="4"> <module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.idea/dataSources" /> <excludeFolder url="file://$MODULE_DIR$/.idea/dataSources" />
<excludeFolder url="file://$MODULE_DIR$/build" /> <excludeFolder url="file://$MODULE_DIR$/build" />
</content> </content>

View file

@ -14,6 +14,7 @@
"ext-openssl": "*", "ext-openssl": "*",
"ext-redis": "*", "ext-redis": "*",
"ext-memcached": "*", "ext-memcached": "*",
"ext-curl": "*" "ext-curl": "*",
"ext-gd": "*"
} }
} }

View file

@ -0,0 +1,52 @@
<?php
namespace Socialbox\Classes\ClientCommands;
class StorageConfiguration
{
private string $path;
private string $userDisplayImagesPath;
private int $userDisplayImagesMaxSize;
/**
* Constructor method to initialize the class properties with provided data.
*
* @param array $data An associative array containing configuration values
*/
public function __construct(array $data)
{
$this->path = $data['path'];
$this->userDisplayImagesPath = $data['user_display_images_path'];
$this->userDisplayImagesMaxSize = $data['user_display_images_max_size'];
}
/**
* Retrieves the base path value.
*
* @return string The base path.
*/
public function getPath(): string
{
return $this->path;
}
/**
* Retrieves the path for user display images.
*
* @return string The path where user display images are stored.
*/
public function getUserDisplayImagesPath(): string
{
return $this->userDisplayImagesPath;
}
/**
* Retrieves the maximum size allowed for user display images.
*
* @return int The maximum size in bytes.
*/
public function getUserDisplayImagesMaxSize(): int
{
return $this->userDisplayImagesMaxSize;
}
}

View file

@ -1,236 +1,264 @@
<?php <?php
namespace Socialbox\Classes; namespace Socialbox\Classes;
use League\Flysystem\Config; use Socialbox\Classes\ClientCommands\StorageConfiguration;
use Socialbox\Classes\Configuration\CacheConfiguration; use Socialbox\Classes\Configuration\CacheConfiguration;
use Socialbox\Classes\Configuration\DatabaseConfiguration; use Socialbox\Classes\Configuration\DatabaseConfiguration;
use Socialbox\Classes\Configuration\InstanceConfiguration; use Socialbox\Classes\Configuration\InstanceConfiguration;
use Socialbox\Classes\Configuration\LoggingConfiguration; use Socialbox\Classes\Configuration\LoggingConfiguration;
use Socialbox\Classes\Configuration\RegistrationConfiguration; use Socialbox\Classes\Configuration\RegistrationConfiguration;
use Socialbox\Classes\Configuration\SecurityConfiguration; use Socialbox\Classes\Configuration\SecurityConfiguration;
class Configuration class Configuration
{
private static ?\ConfigLib\Configuration $configuration = null;
private static ?InstanceConfiguration $instanceConfiguration = null;
private static ?SecurityConfiguration $securityConfiguration = null;
private static ?DatabaseConfiguration $databaseConfiguration = null;
private static ?LoggingConfiguration $loggingConfiguration = null;
private static ?CacheConfiguration $cacheConfiguration = null;
private static ?RegistrationConfiguration $registrationConfiguration = null;
/**
* Initializes the configuration settings for the application. This includes
* settings for the instance, security, database, cache layer, and registration.
*
* @return void
*/
private static function initializeConfiguration(): void
{ {
$config = new \ConfigLib\Configuration('socialbox'); private static ?\ConfigLib\Configuration $configuration = null;
private static ?InstanceConfiguration $instanceConfiguration = null;
private static ?SecurityConfiguration $securityConfiguration = null;
private static ?DatabaseConfiguration $databaseConfiguration = null;
private static ?LoggingConfiguration $loggingConfiguration = null;
private static ?CacheConfiguration $cacheConfiguration = null;
private static ?RegistrationConfiguration $registrationConfiguration = null;
private static ?StorageConfiguration $storageConfiguration = null;
// Instance configuration /**
$config->setDefault('instance.enabled', false); // False by default, requires the user to enable it. * Initializes the configuration settings for the application. This includes
$config->setDefault('instance.domain', null); * settings for the instance, security, database, cache layer, and registration.
$config->setDefault('instance.rpc_endpoint', null); *
$config->setDefault('instance.encryption_keys_count', 5); * @return void
$config->setDefault('instance.encryption_records_count', 5); */
$config->setDefault('instance.private_key', null); private static function initializeConfiguration(): void
$config->setDefault('instance.public_key', null);
$config->setDefault('instance.encryption_keys', null);
// Security Configuration
$config->setDefault('security.display_internal_exceptions', false);
$config->setDefault('security.resolved_servers_ttl', 600);
$config->setDefault('security.captcha_ttl', 200);
// Database configuration
$config->setDefault('database.host', '127.0.0.1');
$config->setDefault('database.port', 3306);
$config->setDefault('database.username', 'root');
$config->setDefault('database.password', 'root');
$config->setDefault('database.name', 'test');
// Logging configuration
$config->setDefault('logging.console_logging_enabled', true);
$config->setDefault('logging.console_logging_level', 'info');
$config->setDefault('logging.file_logging_enabled', true);
$config->setDefault('logging.file_logging_level', 'error');
// Cache layer configuration
$config->setDefault('cache.enabled', false);
$config->setDefault('cache.engine', 'redis');
$config->setDefault('cache.host', '127.0.0.1');
$config->setDefault('cache.port', 6379);
$config->setDefault('cache.username', null);
$config->setDefault('cache.password', null);
$config->setDefault('cache.database', 0);
$config->setDefault('cache.sessions.enabled', true);
$config->setDefault('cache.sessions.ttl', 3600);
$config->setDefault('cache.sessions.max', 1000);
// Registration configuration
$config->setDefault('registration.enabled', true);
$config->setDefault('registration.privacy_policy_document', null);
$config->setDefault('registration.accept_privacy_policy', true);
$config->setDefault('registration.terms_of_service_document', null);
$config->setDefault('registration.accept_terms_of_service', null);
$config->setDefault('registration.password_required', true);
$config->setDefault('registration.otp_required', false);
$config->setDefault('registration.display_name_required', false);
$config->setDefault('registration.email_verification_required', false);
$config->setDefault('registration.sms_verification_required', false);
$config->setDefault('registration.phone_call_verification_required', false);
$config->setDefault('registration.image_captcha_verification_required', true);
$config->save();
self::$configuration = $config;
self::$instanceConfiguration = new InstanceConfiguration(self::$configuration->getConfiguration()['instance']);
self::$securityConfiguration = new SecurityConfiguration(self::$configuration->getConfiguration()['security']);
self::$databaseConfiguration = new DatabaseConfiguration(self::$configuration->getConfiguration()['database']);
self::$loggingConfiguration = new LoggingConfiguration(self::$configuration->getConfiguration()['logging']);
self::$cacheConfiguration = new CacheConfiguration(self::$configuration->getConfiguration()['cache']);
self::$registrationConfiguration = new RegistrationConfiguration(self::$configuration->getConfiguration()['registration']);
}
/**
* Resets all configuration instances by setting them to null and then
* reinitializes the configurations.
*
* @return void
*/
public static function reload(): void
{
self::$configuration = null;
self::$instanceConfiguration = null;
self::$securityConfiguration = null;
self::$databaseConfiguration = null;
self::$loggingConfiguration = null;
self::$cacheConfiguration = null;
self::$registrationConfiguration = null;
self::initializeConfiguration();
}
/**
* Retrieves the current configuration array. If the configuration is not initialized,
* it triggers the initialization process.
*
* @return array The current configuration array.
*/
public static function getConfiguration(): array
{
if(self::$configuration === null)
{ {
$config = new \ConfigLib\Configuration('socialbox');
// Instance configuration
$config->setDefault('instance.enabled', false); // False by default, requires the user to enable it.
$config->setDefault('instance.domain', null);
$config->setDefault('instance.rpc_endpoint', null);
$config->setDefault('instance.encryption_keys_count', 5);
$config->setDefault('instance.encryption_records_count', 5);
$config->setDefault('instance.private_key', null);
$config->setDefault('instance.public_key', null);
$config->setDefault('instance.encryption_keys', null);
// Security Configuration
$config->setDefault('security.display_internal_exceptions', false);
$config->setDefault('security.resolved_servers_ttl', 600);
$config->setDefault('security.captcha_ttl', 200);
// Database configuration
$config->setDefault('database.host', '127.0.0.1');
$config->setDefault('database.port', 3306);
$config->setDefault('database.username', 'root');
$config->setDefault('database.password', 'root');
$config->setDefault('database.name', 'test');
// Logging configuration
$config->setDefault('logging.console_logging_enabled', true);
$config->setDefault('logging.console_logging_level', 'info');
$config->setDefault('logging.file_logging_enabled', true);
$config->setDefault('logging.file_logging_level', 'error');
// Cache layer configuration
$config->setDefault('cache.enabled', false);
$config->setDefault('cache.engine', 'redis');
$config->setDefault('cache.host', '127.0.0.1');
$config->setDefault('cache.port', 6379);
$config->setDefault('cache.username', null);
$config->setDefault('cache.password', null);
$config->setDefault('cache.database', 0);
$config->setDefault('cache.sessions.enabled', true);
$config->setDefault('cache.sessions.ttl', 3600);
$config->setDefault('cache.sessions.max', 1000);
// Registration configuration
$config->setDefault('registration.enabled', true);
$config->setDefault('registration.privacy_policy_document', null);
$config->setDefault('registration.privacy_policy_date', 1734985525);
$config->setDefault('registration.accept_privacy_policy', true);
$config->setDefault('registration.terms_of_service_document', null);
$config->setDefault('registration.terms_of_service_date', 1734985525);
$config->setDefault('registration.accept_terms_of_service', true);
$config->setDefault('registration.community_guidelines_document', null);
$config->setDefault('registration.community_guidelines_date', 1734985525);
$config->setDefault('registration.accept_community_guidelines', true);
$config->setDefault('registration.password_required', true);
$config->setDefault('registration.otp_required', false);
$config->setDefault('registration.display_name_required', true);
$config->setDefault('registration.display_picture_required', false);
$config->setDefault('registration.image_captcha_verification_required', true);
// Storage configuration
$config->setDefault('storage.path', '/etc/socialbox'); // The main path for file storage
$config->setDefault('storage.user_display_images_path', 'user_profiles'); // eg; `/etc/socialbox/user_profiles`
$config->setDefault('storage.user_display_images_max_size', 3145728); // 3MB
$config->save();
self::$configuration = $config;
self::$instanceConfiguration = new InstanceConfiguration(self::$configuration->getConfiguration()['instance']);
self::$securityConfiguration = new SecurityConfiguration(self::$configuration->getConfiguration()['security']);
self::$databaseConfiguration = new DatabaseConfiguration(self::$configuration->getConfiguration()['database']);
self::$loggingConfiguration = new LoggingConfiguration(self::$configuration->getConfiguration()['logging']);
self::$cacheConfiguration = new CacheConfiguration(self::$configuration->getConfiguration()['cache']);
self::$registrationConfiguration = new RegistrationConfiguration(self::$configuration->getConfiguration()['registration']);
self::$storageConfiguration = new StorageConfiguration(self::$configuration->getConfiguration()['storage']);
}
/**
* Resets all configuration instances by setting them to null and then
* reinitializes the configurations.
*
* @return void
*/
public static function reload(): void
{
self::$configuration = null;
self::$instanceConfiguration = null;
self::$securityConfiguration = null;
self::$databaseConfiguration = null;
self::$loggingConfiguration = null;
self::$cacheConfiguration = null;
self::$registrationConfiguration = null;
self::initializeConfiguration(); self::initializeConfiguration();
} }
return self::$configuration->getConfiguration(); /**
} * Retrieves the current configuration array. If the configuration is not initialized,
* it triggers the initialization process.
public static function getConfigurationLib(): \ConfigLib\Configuration *
{ * @return array The current configuration array.
if(self::$configuration === null) */
public static function getConfiguration(): array
{ {
self::initializeConfiguration(); if(self::$configuration === null)
{
self::initializeConfiguration();
}
return self::$configuration->getConfiguration();
} }
return self::$configuration; public static function getConfigurationLib(): \ConfigLib\Configuration
}
/**
* Retrieves the current instance configuration.
*
* @return InstanceConfiguration The current instance configuration instance.
*/
public static function getInstanceConfiguration(): InstanceConfiguration
{
if(self::$instanceConfiguration === null)
{ {
self::initializeConfiguration(); if(self::$configuration === null)
{
self::initializeConfiguration();
}
return self::$configuration;
} }
return self::$instanceConfiguration; /**
} * Retrieves the current instance configuration.
*
/** * @return InstanceConfiguration The current instance configuration instance.
* Retrieves the current security configuration. */
* public static function getInstanceConfiguration(): InstanceConfiguration
* @return SecurityConfiguration The current security configuration instance.
*/
public static function getSecurityConfiguration(): SecurityConfiguration
{
if(self::$securityConfiguration === null)
{ {
self::initializeConfiguration(); if(self::$instanceConfiguration === null)
{
self::initializeConfiguration();
}
return self::$instanceConfiguration;
} }
return self::$securityConfiguration; /**
} * Retrieves the current security configuration.
*
/** * @return SecurityConfiguration The current security configuration instance.
* Retrieves the current database configuration. */
* public static function getSecurityConfiguration(): SecurityConfiguration
* @return DatabaseConfiguration The configuration settings for the database.
*/
public static function getDatabaseConfiguration(): DatabaseConfiguration
{
if(self::$databaseConfiguration === null)
{ {
self::initializeConfiguration(); if(self::$securityConfiguration === null)
{
self::initializeConfiguration();
}
return self::$securityConfiguration;
} }
return self::$databaseConfiguration; /**
} * Retrieves the current database configuration.
*
/** * @return DatabaseConfiguration The configuration settings for the database.
* Retrieves the current logging configuration. */
* public static function getDatabaseConfiguration(): DatabaseConfiguration
* @return LoggingConfiguration The current logging configuration instance.
*/
public static function getLoggingConfiguration(): LoggingConfiguration
{
if(self::$loggingConfiguration === null)
{ {
self::initializeConfiguration(); if(self::$databaseConfiguration === null)
{
self::initializeConfiguration();
}
return self::$databaseConfiguration;
} }
return self::$loggingConfiguration; /**
} * Retrieves the current logging configuration.
*
/** * @return LoggingConfiguration The current logging configuration instance.
* Retrieves the current cache configuration. If the cache configuration */
* has not been initialized, it will initialize it first. public static function getLoggingConfiguration(): LoggingConfiguration
*
* @return CacheConfiguration The current cache configuration instance.
*/
public static function getCacheConfiguration(): CacheConfiguration
{
if(self::$cacheConfiguration === null)
{ {
self::initializeConfiguration(); if(self::$loggingConfiguration === null)
{
self::initializeConfiguration();
}
return self::$loggingConfiguration;
} }
return self::$cacheConfiguration; /**
} * Retrieves the current cache configuration. If the cache configuration
* has not been initialized, it will initialize it first.
/** *
* Retrieves the registration configuration. * @return CacheConfiguration The current cache configuration instance.
* */
* This method returns the current RegistrationConfiguration instance. public static function getCacheConfiguration(): CacheConfiguration
* If the configuration has not been initialized yet, it initializes it first.
*
* @return RegistrationConfiguration The registration configuration instance.
*/
public static function getRegistrationConfiguration(): RegistrationConfiguration
{
if(self::$registrationConfiguration === null)
{ {
self::initializeConfiguration(); if(self::$cacheConfiguration === null)
{
self::initializeConfiguration();
}
return self::$cacheConfiguration;
} }
return self::$registrationConfiguration; /**
* Retrieves the registration configuration.
*
* This method returns the current RegistrationConfiguration instance.
* If the configuration has not been initialized yet, it initializes it first.
*
* @return RegistrationConfiguration The registration configuration instance.
*/
public static function getRegistrationConfiguration(): RegistrationConfiguration
{
if(self::$registrationConfiguration === null)
{
self::initializeConfiguration();
}
return self::$registrationConfiguration;
}
/**
* Retrieves the storage configuration.
*
* This method returns the current StorageConfiguration instance.
* If the configuration has not been initialized yet, it initializes it first.
*
* @return StorageConfiguration The storage configuration instance.
*/
public static function getStorageConfiguration(): StorageConfiguration
{
if(self::$storageConfiguration === null)
{
self::initializeConfiguration();
}
return self::$storageConfiguration;
}
} }
}

View file

@ -1,83 +1,151 @@
<?php <?php
namespace Socialbox\Classes\Configuration; namespace Socialbox\Classes\Configuration;
class CacheConfiguration class CacheConfiguration
{
private bool $enabled;
private string $engine;
private string $host;
private int $port;
private ?string $username;
private ?string $password;
private ?int $database;
private bool $sessionsEnabled;
private int $sessionsTtl;
private int $sessionsMax;
public function __construct(array $data)
{ {
$this->enabled = (bool)$data['enabled']; private bool $enabled;
$this->engine = (string)$data['engine']; private string $engine;
$this->host = (string)$data['host']; private string $host;
$this->port = (int)$data['port']; private int $port;
$this->username = $data['username'] ? (string)$data['username'] : null; private ?string $username;
$this->password = $data['password'] ? (string)$data['password'] : null; private ?string $password;
$this->database = $data['database'] ? (int)$data['database'] : null; private ?int $database;
$this->sessionsEnabled = (bool)$data['sessions']['enabled']; private bool $sessionsEnabled;
$this->sessionsTtl = (int)$data['sessions']['ttl']; private int $sessionsTtl;
$this->sessionsMax = (int)$data['sessions']['max']; private int $sessionsMax;
}
public function isEnabled(): bool /**
{ * Constructor to initialize configuration values.
return $this->enabled; *
} * @param array $data An associative array containing configuration data.
* Keys include:
* - enabled (bool): Whether the feature is enabled.
* - engine (string): The engine type.
* - host (string): The host address.
* - port (int): The port number.
* - username (string|null): The username for authentication.
* - password (string|null): The password for authentication.
* - database (int|null): The database ID.
* - sessions (array): Session-specific settings. Keys include:
* - enabled (bool): Whether sessions are enabled.
* - ttl (int): Session time-to-live in seconds.
* - max (int): Maximum number of concurrent sessions.
*
* @return void
*/
public function __construct(array $data)
{
$this->enabled = (bool)$data['enabled'];
$this->engine = (string)$data['engine'];
$this->host = (string)$data['host'];
$this->port = (int)$data['port'];
$this->username = $data['username'] ? (string)$data['username'] : null;
$this->password = $data['password'] ? (string)$data['password'] : null;
$this->database = $data['database'] ? (int)$data['database'] : null;
$this->sessionsEnabled = (bool)$data['sessions']['enabled'];
$this->sessionsTtl = (int)$data['sessions']['ttl'];
$this->sessionsMax = (int)$data['sessions']['max'];
}
public function getEngine(): string /**
{ * Checks whether the feature is enabled.
return $this->engine; *
} * @return bool Returns true if the feature is enabled, false otherwise.
*/
public function isEnabled(): bool
{
return $this->enabled;
}
public function getHost(): string /**
{ * Retrieves the engine name.
return $this->host; *
} * @return string Returns the name of the engine.
*/
public function getEngine(): string
{
return $this->engine;
}
public function getPort(): int /**
{ * Retrieves the host value.
return $this->port; *
} * @return string The host as a string.
*/
public function getHost(): string
{
return $this->host;
}
public function getUsername(): ?string /**
{ * Retrieves the port value.
return $this->username; *
} * @return int The port number.
*/
public function getPort(): int
{
return $this->port;
}
public function getPassword(): ?string /**
{ * Retrieves the username value.
return $this->password; *
} * @return string|null The username, or null if not set.
*/
public function getUsername(): ?string
{
return $this->username;
}
public function getDatabase(): ?int /**
{ * Retrieves the password value.
return $this->database; *
} * @return string|null The password as a string or null if not set.
*/
public function getPassword(): ?string
{
return $this->password;
}
public function isSessionsEnabled(): bool /**
{ * Retrieves the database identifier.
return $this->sessionsEnabled; *
} * @return int|null The database identifier or null if not set.
*/
public function getDatabase(): ?int
{
return $this->database;
}
public function getSessionsTtl(): int /**
{ * Checks whether sessions are enabled.
return $this->sessionsTtl; *
} * @return bool Returns true if sessions are enabled, otherwise false.
*/
public function isSessionsEnabled(): bool
{
return $this->sessionsEnabled;
}
public function getSessionsMax(): int /**
{ * Retrieves the time-to-live (TTL) value for sessions.
return $this->sessionsMax; *
* @return int The TTL value for sessions.
*/
public function getSessionsTtl(): int
{
return $this->sessionsTtl;
}
/**
* Retrieves the maximum number of sessions allowed.
*
* @return int Returns the maximum number of sessions.
*/
public function getSessionsMax(): int
{
return $this->sessionsMax;
}
} }
}

View file

@ -1,46 +1,83 @@
<?php <?php
namespace Socialbox\Classes\Configuration; namespace Socialbox\Classes\Configuration;
class DatabaseConfiguration class DatabaseConfiguration
{
private string $host;
private int $port;
private string $username;
private ?string $password;
private string $name;
public function __construct(array $data)
{ {
$this->host = (string)$data['host']; private string $host;
$this->port = (int)$data['port']; private int $port;
$this->username = (string)$data['username']; private string $username;
$this->password = $data['password'] ? (string)$data['password'] : null; private ?string $password;
$this->name = (string)$data['name']; private string $name;
}
public function getHost(): string /**
{ * Constructor method to initialize properties from the provided data array.
return $this->host; *
} * @param array $data Associative array containing the keys 'host', 'port', 'username', 'password', and 'name'.
* - 'host' (string): The host of the server.
* - 'port' (int): The port number.
* - 'username' (string): The username for authentication.
* - 'password' (string|null): The password for authentication, optional.
* - 'name' (string): The name associated with the connection or resource.
*
* @return void
*/
public function __construct(array $data)
{
$this->host = (string)$data['host'];
$this->port = (int)$data['port'];
$this->username = (string)$data['username'];
$this->password = $data['password'] ? (string)$data['password'] : null;
$this->name = (string)$data['name'];
}
public function getPort(): int /**
{ * Retrieves the host value.
return $this->port; *
} * @return string The value of the host.
*/
public function getHost(): string
{
return $this->host;
}
public function getUsername(): string /**
{ * Retrieves the port value.
return $this->username; *
} * @return int The value of the port.
*/
public function getPort(): int
{
return $this->port;
}
public function getPassword(): ?string /**
{ * Retrieves the username value.
return $this->password; *
} * @return string The value of the username.
*/
public function getUsername(): string
{
return $this->username;
}
public function getName(): string /**
{ * Retrieves the password value.
return $this->name; *
* @return string|null The value of the password, or null if not set.
*/
public function getPassword(): ?string
{
return $this->password;
}
/**
* Retrieves the name value.
*
* @return string The value of the name
*/
public function getName(): string
{
return $this->name;
}
} }
}

View file

@ -1,115 +1,121 @@
<?php <?php
namespace Socialbox\Classes\Configuration; namespace Socialbox\Classes\Configuration;
use LogLib\Enums\LogLevel; use LogLib\Enums\LogLevel;
class LoggingConfiguration class LoggingConfiguration
{
private bool $consoleLoggingEnabled;
private string $consoleLoggingLevel;
private bool $fileLoggingEnabled;
private string $fileLoggingLevel;
/**
* Initializes a new instance of the class with the given configuration data.
*
* @param array $data An associative array containing logging configuration settings.
* @return void
*/
public function __construct(array $data)
{ {
$this->consoleLoggingEnabled = (bool) $data['console_logging_enabled']; private bool $consoleLoggingEnabled;
$this->consoleLoggingLevel = $data['console_logging_level']; private string $consoleLoggingLevel;
$this->fileLoggingEnabled = (bool) $data['file_logging_enabled']; private bool $fileLoggingEnabled;
$this->fileLoggingLevel = $data['file_logging_level']; private string $fileLoggingLevel;
}
/** /**
* Checks if console logging is enabled. * Initializes a new instance of the class with the given configuration data.
* *
* @return bool True if console logging is enabled, otherwise false. * @param array $data An associative array containing logging configuration settings.
*/ * @return void
public function isConsoleLoggingEnabled(): bool */
{ public function __construct(array $data)
return $this->consoleLoggingEnabled; {
} $this->consoleLoggingEnabled = (bool) $data['console_logging_enabled'];
$this->consoleLoggingLevel = $data['console_logging_level'];
$this->fileLoggingEnabled = (bool) $data['file_logging_enabled'];
$this->fileLoggingLevel = $data['file_logging_level'];
}
/** /**
* Retrieves the logging level for console output. * Checks if console logging is enabled.
* *
* @return LogLevel The logging level configured for console output. * @return bool True if console logging is enabled, otherwise false.
*/ */
public function getConsoleLoggingLevel(): LogLevel public function isConsoleLoggingEnabled(): bool
{ {
return $this->parseLogLevel($this->consoleLoggingLevel); return $this->consoleLoggingEnabled;
} }
/** /**
* Checks if file logging is enabled. * Retrieves the logging level for console output.
* *
* @return bool True if file logging is enabled, false otherwise. * @return LogLevel The logging level configured for console output.
*/ */
public function isFileLoggingEnabled(): bool public function getConsoleLoggingLevel(): LogLevel
{ {
return $this->fileLoggingEnabled; return $this->parseLogLevel($this->consoleLoggingLevel);
} }
/** /**
* Retrieves the logging level for file logging. * Checks if file logging is enabled.
* *
* @return LogLevel The logging level set for file logging. * @return bool True if file logging is enabled, false otherwise.
*/ */
public function getFileLoggingLevel(): LogLevel public function isFileLoggingEnabled(): bool
{ {
return $this->parseLogLevel($this->fileLoggingLevel); return $this->fileLoggingEnabled;
} }
/** /**
* Parses the given log level from string format to a LogLevel enumeration. * Retrieves the logging level for file logging.
* *
* @param string $logLevel The log level as a string. * @return LogLevel The logging level set for file logging.
* @return LogLevel The corresponding LogLevel enumeration. */
*/ public function getFileLoggingLevel(): LogLevel
private function parseLogLevel(string $logLevel): LogLevel {
{ return $this->parseLogLevel($this->fileLoggingLevel);
switch (strtolower($logLevel)) { }
case LogLevel::DEBUG:
case 'debug': /**
case '6': * Parses the given log level from string format to a LogLevel enumeration.
case 'dbg': *
return LogLevel::DEBUG; * @param string $logLevel The log level as a string.
case LogLevel::VERBOSE: * @return LogLevel The corresponding LogLevel enumeration.
case 'verbose': */
case '5': private function parseLogLevel(string $logLevel): LogLevel
case 'vrb': {
return LogLevel::VERBOSE; switch (strtolower($logLevel))
default: {
case LogLevel::INFO: case LogLevel::DEBUG:
case 'info': case 'debug':
case '4': case '6':
case 'inf': case 'dbg':
return LogLevel::INFO; return LogLevel::DEBUG;
case LogLevel::WARNING:
case 'warning': case LogLevel::VERBOSE:
case '3': case 'verbose':
case 'wrn': case '5':
return LogLevel::WARNING; case 'vrb':
case LogLevel::ERROR: return LogLevel::VERBOSE;
case 'error':
case '2': default:
case 'err': case LogLevel::INFO:
return LogLevel::ERROR; case 'info':
case LogLevel::FATAL: case '4':
case 'fatal': case 'inf':
case '1': return LogLevel::INFO;
case 'crt':
return LogLevel::FATAL; case LogLevel::WARNING:
case LogLevel::SILENT: case 'warning':
case 'silent': case '3':
case '0': case 'wrn':
case 'sil': return LogLevel::WARNING;
return LogLevel::SILENT; case LogLevel::ERROR:
case 'error':
case '2':
case 'err':
return LogLevel::ERROR;
case LogLevel::FATAL:
case 'fatal':
case '1':
case 'crt':
return LogLevel::FATAL;
case LogLevel::SILENT:
case 'silent':
case '0':
case 'sil':
return LogLevel::SILENT;
}
} }
} }
}

View file

@ -1,171 +1,202 @@
<?php <?php
/** namespace Socialbox\Classes\Configuration;
* This class handles the configuration settings for user registration.
*/
namespace Socialbox\Classes\Configuration; class RegistrationConfiguration
class RegistrationConfiguration
{
private bool $registrationEnabled;
private ?string $privacyPolicyDocument;
private bool $acceptPrivacyPolicy;
private ?string $termsOfServiceDocument;
private bool $acceptTermsOfService;
private bool $passwordRequired;
private bool $otpRequired;
private bool $displayNameRequired;
private bool $emailVerificationRequired;
private bool $smsVerificationRequired;
private bool $phoneCallVerificationRequired;
private bool $imageCaptchaVerificationRequired;
/**
* Constructor method for initializing verification requirements.
*
* @param array $data An associative array containing the following keys:
* 'registration_enabled', 'password_required',
* 'otp_required', 'display_name_required',
* 'email_verification_required', 'sms_verification_required',
* 'phone_call_verification_required', 'image_captcha_verification_required'.
*
* @return void
*/
public function __construct(array $data)
{ {
$this->registrationEnabled = (bool)$data['enabled']; private bool $registrationEnabled;
$this->privacyPolicyDocument = $data['privacy_policy_document'] ?? null; private ?string $privacyPolicyDocument;
$this->acceptPrivacyPolicy = $data['accept_privacy_policy'] ?? true; private int $privacyPolicyDate;
$this->termsOfServiceDocument = $data['terms_of_service_document'] ?? null; private bool $acceptPrivacyPolicy;
$this->acceptTermsOfService = $data['accept_terms_of_service'] ?? true; private ?string $termsOfServiceDocument;
$this->passwordRequired = (bool)$data['password_required']; private int $termsOfServiceDate;
$this->otpRequired = (bool)$data['otp_required']; private bool $acceptTermsOfService;
$this->displayNameRequired = (bool)$data['display_name_required']; private ?string $communityGuidelinesDocument;
$this->emailVerificationRequired = (bool)$data['email_verification_required']; private int $communityGuidelinesDate;
$this->smsVerificationRequired = (bool)$data['sms_verification_required']; private bool $acceptCommunityGuidelines;
$this->phoneCallVerificationRequired = (bool)$data['phone_call_verification_required']; private bool $passwordRequired;
$this->imageCaptchaVerificationRequired = (bool)$data['image_captcha_verification_required']; private bool $otpRequired;
} private bool $displayNameRequired;
private bool $displayPictureRequired;
private bool $imageCaptchaVerificationRequired;
/** /**
* Checks if the registration is enabled. * Constructor method for initializing verification requirements.
* *
* @return bool True if registration is enabled, false otherwise. * @param array $data An associative array containing the following keys:
*/ * 'registration_enabled', 'password_required',
public function isRegistrationEnabled(): bool * 'otp_required', 'display_name_required',
{ * 'email_verification_required', 'sms_verification_required',
return $this->registrationEnabled; * 'phone_call_verification_required', 'image_captcha_verification_required'.
} *
* @return void
*/
public function __construct(array $data)
{
$this->registrationEnabled = (bool)$data['enabled'];
$this->privacyPolicyDocument = $data['privacy_policy_document'] ?? null;
$this->privacyPolicyDate = $data['privacy_policy_date'] ?? 0;
$this->acceptPrivacyPolicy = $data['accept_privacy_policy'] ?? true;
$this->termsOfServiceDocument = $data['terms_of_service_document'] ?? null;
$this->termsOfServiceDate = $data['terms_of_service_date'] ?? 0;
$this->acceptTermsOfService = $data['accept_terms_of_service'] ?? true;
$this->communityGuidelinesDocument = $data['community_guidelines_document'] ?? null;
$this->communityGuidelinesDate = $data['community_guidelines_date'] ?? 0;
$this->acceptCommunityGuidelines = $data['accept_community_guidelines'] ?? true;
$this->passwordRequired = (bool)$data['password_required'];
$this->otpRequired = (bool)$data['otp_required'];
$this->displayNameRequired = (bool)$data['display_name_required'];
$this->displayPictureRequired = (bool)$data['display_picture_required'];
$this->imageCaptchaVerificationRequired = (bool)$data['image_captcha_verification_required'];
}
/**
* Checks if the registration is enabled.
*
* @return bool True if registration is enabled, false otherwise.
*/
public function isRegistrationEnabled(): bool
{
return $this->registrationEnabled;
}
/** /**
* Retrieves the privacy policy document. * Retrieves the privacy policy document.
* *
* @return ?string Returns the privacy policy document or null if not set. * @return ?string Returns the privacy policy document or null if not set.
*/ */
public function getPrivacyPolicyDocument(): ?string public function getPrivacyPolicyDocument(): ?string
{ {
return $this->privacyPolicyDocument; return $this->privacyPolicyDocument;
} }
/** /**
* Checks if accepting the privacy policy is required. * Retrieves the date of the privacy policy.
* *
* @return bool Returns true if the privacy policy must be accepted, false otherwise. * @return int Returns the date of the privacy policy.
*/ */
public function isAcceptPrivacyPolicyRequired(): bool public function getPrivacyPolicyDate(): int
{ {
return $this->acceptPrivacyPolicy; return $this->privacyPolicyDate;
} }
/** /**
* Retrieves the terms of service document. * Checks if accepting the privacy policy is required.
* *
* @return ?string Returns the terms of service document or null if not set. * @return bool Returns true if the privacy policy must be accepted, false otherwise.
*/ */
public function getTermsOfServiceDocument(): ?string public function isAcceptPrivacyPolicyRequired(): bool
{ {
return $this->termsOfServiceDocument; return $this->acceptPrivacyPolicy;
} }
/** /**
* Checks if accepting the terms of service is required. * Retrieves the terms of service document.
* *
* @return bool Returns true if the terms of service must be accepted, false otherwise. * @return ?string Returns the terms of service document or null if not set.
*/ */
public function isAcceptTermsOfServiceRequired(): bool public function getTermsOfServiceDocument(): ?string
{ {
return $this->acceptTermsOfService; return $this->termsOfServiceDocument;
} }
/** /**
* Determines if a password is required. * Retrieves the date of the terms of service.
* *
* @return bool True if a password is required, false otherwise. * @return int Returns the date of the terms of service.
*/ */
public function isPasswordRequired(): bool public function getTermsOfServiceDate(): int
{ {
return $this->passwordRequired; return $this->termsOfServiceDate;
} }
/** /**
* Determines if OTP (One-Time Password) is required. * Checks if accepting the terms of service is required.
* *
* @return bool True if OTP is required, false otherwise. * @return bool Returns true if the terms of service must be accepted, false otherwise.
*/ */
public function isOtpRequired(): bool public function isAcceptTermsOfServiceRequired(): bool
{ {
return $this->otpRequired; return $this->acceptTermsOfService;
} }
/** /**
* Checks if a display name is required. * Retrieves the community guidelines document.
* *
* @return bool Returns true if a display name is required, false otherwise. * @return ?string Returns the community guidelines document or null if not set.
*/ */
public function isDisplayNameRequired(): bool public function getCommunityGuidelinesDocument(): ?string
{ {
return $this->displayNameRequired; return $this->communityGuidelinesDocument;
} }
/** /**
* Checks if email verification is required. * Retrieves the date of the community guidelines.
* *
* @return bool Returns true if email verification is required, false otherwise. * @return int Returns the date of the community guidelines.
*/ */
public function isEmailVerificationRequired(): bool public function getCommunityGuidelinesDate(): int
{ {
return $this->emailVerificationRequired; return $this->communityGuidelinesDate;
} }
/** /**
* Checks if SMS verification is required. * Checks if accepting the community guidelines is required.
* *
* @return bool Returns true if SMS verification is required, false otherwise. * @return bool Returns true if the community guidelines must be accepted, false otherwise.
*/ */
public function isSmsVerificationRequired(): bool public function isAcceptCommunityGuidelinesRequired(): bool
{ {
return $this->smsVerificationRequired; return $this->acceptCommunityGuidelines;
} }
/** /**
* Checks if phone call verification is required. * Determines if a password is required.
* *
* @return bool Returns true if phone call verification is required, false otherwise. * @return bool True if a password is required, false otherwise.
*/ */
public function isPhoneCallVerificationRequired(): bool public function isPasswordRequired(): bool
{ {
return $this->phoneCallVerificationRequired; return $this->passwordRequired;
} }
/** /**
* Determines if image CAPTCHA verification is required. * Determines if OTP (One-Time Password) is required.
* *
* @return bool Returns true if image CAPTCHA verification is required, false otherwise. * @return bool True if OTP is required, false otherwise.
*/ */
public function isImageCaptchaVerificationRequired(): bool public function isOtpRequired(): bool
{ {
return $this->imageCaptchaVerificationRequired; return $this->otpRequired;
}
/**
* Checks if a display name is required.
*
* @return bool Returns true if a display name is required, false otherwise.
*/
public function isDisplayNameRequired(): bool
{
return $this->displayNameRequired;
}
/**
* Checks if a display picture is required.
*
* @return bool Returns true if a display picture is required, false otherwise.
*/
public function isDisplayPictureRequired(): bool
{
return $this->displayPictureRequired;
}
/**
* Determines if image CAPTCHA verification is required.
*
* @return bool Returns true if image CAPTCHA verification is required, false otherwise.
*/
public function isImageCaptchaVerificationRequired(): bool
{
return $this->imageCaptchaVerificationRequired;
}
} }
}

View file

@ -1,55 +1,55 @@
<?php <?php
namespace Socialbox\Classes\Configuration; namespace Socialbox\Classes\Configuration;
class SecurityConfiguration class SecurityConfiguration
{
private bool $displayInternalExceptions;
private int $resolvedServersTtl;
private int $captchaTtl;
/**
* Constructor method for initializing class properties.
*
* @param array $data An associative array containing values for initializing the properties.
*
* @return void
*/
public function __construct(array $data)
{ {
$this->displayInternalExceptions = $data['display_internal_exceptions']; private bool $displayInternalExceptions;
$this->resolvedServersTtl = $data['resolved_servers_ttl']; private int $resolvedServersTtl;
$this->captchaTtl = $data['captcha_ttl']; private int $captchaTtl;
}
/** /**
* Determines if the display of internal errors is enabled. * Constructor method for initializing class properties.
* *
* @return bool True if the display of internal errors is enabled, false otherwise. * @param array $data An associative array containing values for initializing the properties.
*/ *
public function isDisplayInternalExceptions(): bool * @return void
{ */
return $this->displayInternalExceptions; public function __construct(array $data)
} {
$this->displayInternalExceptions = $data['display_internal_exceptions'];
$this->resolvedServersTtl = $data['resolved_servers_ttl'];
$this->captchaTtl = $data['captcha_ttl'];
}
/** /**
* Retrieves the time-to-live (TTL) value for resolved servers. * Determines if the display of internal errors is enabled.
* *
* @return int The TTL value for resolved servers. * @return bool True if the display of internal errors is enabled, false otherwise.
*/ */
public function getResolvedServersTtl(): int public function isDisplayInternalExceptions(): bool
{ {
return $this->resolvedServersTtl; return $this->displayInternalExceptions;
} }
/** /**
* Retrieves the time-to-live (TTL) value for captchas. * Retrieves the time-to-live (TTL) value for resolved servers.
* *
* @return int The TTL value for captchas. * @return int The TTL value for resolved servers.
*/ */
public function getCaptchaTtl(): int public function getResolvedServersTtl(): int
{ {
return $this->captchaTtl; return $this->resolvedServersTtl;
} }
} /**
* Retrieves the time-to-live (TTL) value for captchas.
*
* @return int The TTL value for captchas.
*/
public function getCaptchaTtl(): int
{
return $this->captchaTtl;
}
}

View file

@ -64,4 +64,22 @@
return file_get_contents(self::getDocumentResource('tos')); return file_get_contents(self::getDocumentResource('tos'));
} }
/**
* Retrieves the community guidelines document content.
*
* @return string The content of the community guidelines document, either from a configured location
* or a default resource if the configured location is unavailable.
*/
public static function getCommunityGuidelines(): string
{
$configuredLocation = Configuration::getRegistrationConfiguration()->getCommunityGuidelinesDocument();
if($configuredLocation !== null && file_exists($configuredLocation))
{
return file_get_contents($configuredLocation);
}
return file_get_contents(self::getDocumentResource('community'));
}
} }

View file

@ -0,0 +1 @@
<h1>Community Guidelines</h1>

View file

@ -0,0 +1,37 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class AcceptCommunityGuidelines extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
try
{
// Remove the verification flag
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_COMMUNITY_GUIDELINES]);
// Check & update the session flow
SessionManager::updateFlow($request->getSession());
}
catch (DatabaseOperationException $e)
{
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -21,28 +21,17 @@
{ {
try try
{ {
// Remove the verification flag
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_PRIVACY_POLICY]); SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_PRIVACY_POLICY]);
// Check & update the session flow
SessionManager::updateFlow($request->getSession());
} }
catch (DatabaseOperationException $e) catch (DatabaseOperationException $e)
{ {
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e); return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
} }
// Check if all registration flags are removed
if(SessionFlags::isComplete($request->getSession()->getFlags()))
{
// Set the session as authenticated
try
{
SessionManager::setAuthenticated($request->getSessionUuid(), true);
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::REGISTRATION_REQUIRED, SessionFlags::AUTHENTICATION_REQUIRED]);
}
catch (DatabaseOperationException $e)
{
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
}
}
return $rpcRequest->produceResponse(true); return $rpcRequest->produceResponse(true);
} }
} }

View file

@ -20,28 +20,17 @@
{ {
try try
{ {
// Remove the verification flag
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_TERMS_OF_SERVICE]); SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_TERMS_OF_SERVICE]);
// Check & update the session flow
SessionManager::updateFlow($request->getSession());
} }
catch (DatabaseOperationException $e) catch (DatabaseOperationException $e)
{ {
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e); return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
} }
// Check if all registration flags are removed
if(SessionFlags::isComplete($request->getSession()->getFlags()))
{
// Set the session as authenticated
try
{
SessionManager::setAuthenticated($request->getSessionUuid(), true);
SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::REGISTRATION_REQUIRED, SessionFlags::AUTHENTICATION_REQUIRED]);
}
catch (DatabaseOperationException $e)
{
return $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, $e);
}
}
return $rpcRequest->produceResponse(true); return $rpcRequest->produceResponse(true);
} }
} }

View file

@ -0,0 +1,28 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Resources;
use Socialbox\Enums\StandardError;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\ServerDocument;
class GetCommunityGuidelines extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
return $rpcRequest->produceResponse(new ServerDocument([
'last_updated' => Configuration::getRegistrationConfiguration()->getCommunityGuidelinesDate(),
'title' => 'Community Guidelines',
'content' => Resources::getCommunityGuidelines()
]));
}
}

View file

@ -3,11 +3,13 @@
namespace Socialbox\Classes\StandardMethods; namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method; use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Resources; use Socialbox\Classes\Resources;
use Socialbox\Enums\StandardError; use Socialbox\Enums\StandardError;
use Socialbox\Interfaces\SerializableInterface; use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Objects\ClientRequest; use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest; use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\ServerDocument;
class GetPrivacyPolicy extends Method class GetPrivacyPolicy extends Method
{ {
@ -17,6 +19,10 @@
*/ */
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{ {
return $rpcRequest->produceResponse(Resources::getPrivacyPolicy()); return $rpcRequest->produceResponse(new ServerDocument([
'last_updated' => Configuration::getRegistrationConfiguration()->getPrivacyPolicyDate(),
'title' => 'Privacy Policy',
'content' => Resources::getPrivacyPolicy()
]));
} }
} }

View file

@ -3,11 +3,13 @@
namespace Socialbox\Classes\StandardMethods; namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method; use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Resources; use Socialbox\Classes\Resources;
use Socialbox\Enums\StandardError; use Socialbox\Enums\StandardError;
use Socialbox\Interfaces\SerializableInterface; use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Objects\ClientRequest; use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest; use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\ServerDocument;
class GetTermsOfService extends Method class GetTermsOfService extends Method
{ {
@ -17,6 +19,10 @@
*/ */
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{ {
return $rpcRequest->produceResponse(Resources::getTermsOfService()); return $rpcRequest->produceResponse(new ServerDocument([
'last_updated' => Configuration::getRegistrationConfiguration()->getTermsOfServiceDate(),
'title' => 'Terms of Service',
'content' => Resources::getTermsOfService()
]));
} }
} }

View file

@ -60,6 +60,7 @@
// Build the captcha // Build the captcha
// Returns HTML base64 encoded image of the captcha // Returns HTML base64 encoded image of the captcha
// Important note: Must always be HTML-BASE64 which means it must be prefixed with `data:image/jpeg;base64,`
return $rpcRequest->produceResponse(new ImageCaptcha([ return $rpcRequest->produceResponse(new ImageCaptcha([
'expires' => $captchaRecord->getExpires(), 'expires' => $captchaRecord->getExpires(),
'content' => (new CaptchaBuilder($answer))->build()->inline() 'content' => (new CaptchaBuilder($answer))->build()->inline()

View file

@ -194,6 +194,66 @@ class Utilities
return preg_replace('/[^a-zA-Z0-9-_]/', '', $name); return preg_replace('/[^a-zA-Z0-9-_]/', '', $name);
} }
/**
* Sanitizes a Base64-encoded JPEG image by validating its data, decoding it,
* and re-encoding it to ensure it conforms to the JPEG format.
*
* @param string $data The Base64-encoded string potentially containing a JPEG image,
* optionally prefixed with "data:image/...;base64,".
* @return string A sanitized and re-encoded JPEG image as a binary string.
* @throws InvalidArgumentException If the input data is not valid Base64,
* does not represent an image, or is not in the JPEG format.
*/
public static function sanitizeBase64Jpeg(string $data): string
{
// Detect and strip the potential "data:image/...;base64," prefix, if present
if (str_contains($data, ','))
{
[, $data] = explode(',', $data, 2);
}
// Decode the Base64 string
$decodedData = base64_decode($data, true);
// Check if decoding succeeded
if ($decodedData === false)
{
throw new InvalidArgumentException("Invalid Base64 data.");
}
// Temporarily load the decoded data as an image
$tempResource = imagecreatefromstring($decodedData);
// Validate that the decoded data is indeed an image
if ($tempResource === false)
{
throw new InvalidArgumentException("The Base64 data does not represent a valid image.");
}
// Validate MIME type using getimagesizefromstring
$imageInfo = getimagesizefromstring($decodedData);
if ($imageInfo === false || $imageInfo['mime'] !== 'image/jpeg')
{
imagedestroy($tempResource); // Cleanup resources
throw new InvalidArgumentException("The image is not a valid JPEG format.");
}
// Capture the re-encoded image in memory and return it as a string
ob_start(); // Start output buffering
$saveResult = imagejpeg($tempResource, null, 100); // Max quality, save to output buffer
imagedestroy($tempResource); // Free up memory resources
if (!$saveResult)
{
ob_end_clean(); // Clean the output buffer if encoding failed
throw new InvalidArgumentException("Failed to encode the sanitized image.");
}
// Return the sanitized jpeg image as the result
return ob_get_clean();
}
/** /**
* Converts an array into a serialized string by joining the elements with a comma. * Converts an array into a serialized string by joining the elements with a comma.
* *

View file

@ -2,8 +2,10 @@
namespace Socialbox\Enums; namespace Socialbox\Enums;
use Socialbox\Classes\StandardMethods\AcceptCommunityGuidelines;
use Socialbox\Classes\StandardMethods\AcceptPrivacyPolicy; use Socialbox\Classes\StandardMethods\AcceptPrivacyPolicy;
use Socialbox\Classes\StandardMethods\AcceptTermsOfService; use Socialbox\Classes\StandardMethods\AcceptTermsOfService;
use Socialbox\Classes\StandardMethods\GetCommunityGuidelines;
use Socialbox\Classes\StandardMethods\GetPrivacyPolicy; use Socialbox\Classes\StandardMethods\GetPrivacyPolicy;
use Socialbox\Classes\StandardMethods\GetSessionState; use Socialbox\Classes\StandardMethods\GetSessionState;
use Socialbox\Classes\StandardMethods\GetTermsOfService; use Socialbox\Classes\StandardMethods\GetTermsOfService;
@ -74,11 +76,15 @@
self::ACCEPT_PRIVACY_POLICY => AcceptPrivacyPolicy::execute($request, $rpcRequest), self::ACCEPT_PRIVACY_POLICY => AcceptPrivacyPolicy::execute($request, $rpcRequest),
self::GET_TERMS_OF_SERVICE => GetTermsOfService::execute($request, $rpcRequest), self::GET_TERMS_OF_SERVICE => GetTermsOfService::execute($request, $rpcRequest),
self::ACCEPT_TERMS_OF_SERVICE => AcceptTermsOfService::execute($request, $rpcRequest), self::ACCEPT_TERMS_OF_SERVICE => AcceptTermsOfService::execute($request, $rpcRequest),
self::GET_COMMUNITY_GUIDELINES => GetCommunityGuidelines::execute($request, $rpcRequest),
self::ACCEPT_COMMUNITY_GUIDELINES => AcceptCommunityGuidelines::execute($request, $rpcRequest),
self::VERIFICATION_GET_IMAGE_CAPTCHA => VerificationGetImageCaptcha::execute($request, $rpcRequest), self::VERIFICATION_GET_IMAGE_CAPTCHA => VerificationGetImageCaptcha::execute($request, $rpcRequest),
self::VERIFICATION_ANSWER_IMAGE_CAPTCHA => VerificationAnswerImageCaptcha::execute($request, $rpcRequest), self::VERIFICATION_ANSWER_IMAGE_CAPTCHA => VerificationAnswerImageCaptcha::execute($request, $rpcRequest),
self::SETTINGS_SET_PASSWORD => SettingsSetPassword::execute($request, $rpcRequest), self::SETTINGS_SET_PASSWORD => SettingsSetPassword::execute($request, $rpcRequest),
default => $rpcRequest->produceError(StandardError::METHOD_NOT_ALLOWED, sprintf("The method %s is not supported by the server", $rpcRequest->getMethod()))
}; };
} }
@ -107,36 +113,59 @@
*/ */
public static function getAllowedMethods(ClientRequest $clientRequest): array public static function getAllowedMethods(ClientRequest $clientRequest): array
{ {
// These methods should always accessible
$methods = [ $methods = [
self::PING, // Important methods
self::GET_SESSION_STATE, self::PING, // Always allow the ping method
self::GET_PRIVACY_POLICY, self::GET_SESSION_STATE, // The session state should always be accessible
self::GET_TERMS_OF_SERVICE, self::GET_PRIVACY_POLICY, // The user should always be able to get the privacy policy
self::GET_TERMS_OF_SERVICE, // The user should always be able to get the terms of service
self::GET_COMMUNITY_GUIDELINES, // The user should always be able to get the community guidelines
]; ];
$session = $clientRequest->getSession(); $session = $clientRequest->getSession();
if(in_array(SessionFlags::VER_PRIVACY_POLICY, $session->getFlags())) // If the flag `VER_PRIVACY_POLICY` is set, then the user can accept the privacy policy
if($session->flagExists(SessionFlags::VER_PRIVACY_POLICY))
{ {
$methods[] = self::ACCEPT_PRIVACY_POLICY; $methods[] = self::ACCEPT_PRIVACY_POLICY;
} }
if(in_array(SessionFlags::VER_TERMS_OF_SERVICE, $session->getFlags())) // If the flag `VER_TERMS_OF_SERVICE` is set, then the user can accept the terms of service
if($session->flagExists(SessionFlags::VER_TERMS_OF_SERVICE))
{ {
$methods[] = self::ACCEPT_TERMS_OF_SERVICE; $methods[] = self::ACCEPT_TERMS_OF_SERVICE;
} }
if(in_array(SessionFlags::VER_IMAGE_CAPTCHA, $session->getFlags())) // If the flag `VER_COMMUNITY_GUIDELINES` is set, then the user can accept the community guidelines
if($session->flagExists(SessionFlags::VER_COMMUNITY_GUIDELINES))
{
$methods[] = self::ACCEPT_COMMUNITY_GUIDELINES;
}
// If the flag `VER_IMAGE_CAPTCHA` is set, then the user has to get and answer an image captcha
if($session->flagExists(SessionFlags::VER_IMAGE_CAPTCHA))
{ {
$methods[] = self::VERIFICATION_GET_IMAGE_CAPTCHA; $methods[] = self::VERIFICATION_GET_IMAGE_CAPTCHA;
$methods[] = self::VERIFICATION_ANSWER_IMAGE_CAPTCHA; $methods[] = self::VERIFICATION_ANSWER_IMAGE_CAPTCHA;
} }
// If the flag `SET_PASSWORD` is set, then the user has to set a password
if(in_array(SessionFlags::SET_PASSWORD, $session->getFlags())) if(in_array(SessionFlags::SET_PASSWORD, $session->getFlags()))
{ {
$methods[] = self::SETTINGS_SET_PASSWORD; $methods[] = self::SETTINGS_SET_PASSWORD;
} }
// If the user is authenticated, then preform additional method calls
if($session->isAuthenticated())
{
// Always allow the authenticated user to change their password
if(!in_array(SessionFlags::SET_PASSWORD, $session->getFlags()))
{
$methods[] = self::SETTINGS_SET_PASSWORD;
}
}
return $methods; return $methods;
} }
} }

View file

@ -454,4 +454,21 @@
throw new DatabaseOperationException('Failed to update authenticated peer', $e); throw new DatabaseOperationException('Failed to update authenticated peer', $e);
} }
} }
/**
* Marks the session as complete if all necessary conditions are met.
*
* @param SessionRecord $session The session record to evaluate and potentially mark as complete.
* @throws DatabaseOperationException If there is an error while updating the session in the database.
* @throws StandardException If the session record cannot be found or if there is an error during retrieval.
* @return void
*/
public static function updateFlow(SessionRecord $session): void
{
if(SessionFlags::isComplete($session->getFlags()))
{
SessionManager::setAuthenticated($session->getUuid(), true);
SessionManager::removeFlags($session->getUuid(), [SessionFlags::REGISTRATION_REQUIRED, SessionFlags::AUTHENTICATION_REQUIRED]);
}
}
} }

View file

@ -0,0 +1,76 @@
<?php
namespace Socialbox\Objects\Standard;
use Socialbox\Interfaces\SerializableInterface;
class ServerDocument implements SerializableInterface
{
private int $lastUpdated;
private string $title;
private string $content;
/**
* Constructor method to initialize the object with provided data.
*
* @param array $data An associative array containing 'last_updated', 'content_type', 'title', and 'content' keys.
* @return void
*/
public function __construct(array $data)
{
$this->lastUpdated = $data['last_updated'];
$this->title = $data['title'];
$this->content = $data['content'];
}
/**
* Retrieves the timestamp of the last update.
*
* @return int The last updated timestamp.
*/
public function getLastUpdated(): int
{
return $this->lastUpdated;
}
/**
* Retrieves the title property.
*
* @return string The title value.
*/
public function getTitle(): string
{
return $this->title;
}
/**
* Retrieves the content stored in the instance.
*
* @return string The content as a string.
*/
public function getContent(): string
{
return $this->content;
}
/**
* @inheritDoc
*/
public static function fromArray(array $data): object
{
return new self($data);
}
/**
* @inheritDoc
*/
public function toArray(): array
{
return [
'last_updated' => $this->lastUpdated,
'content_type' => $this->contentType,
'title' => $this->title,
'content' => $this->content
];
}
}

View file

@ -13,6 +13,7 @@
use Socialbox\Objects\ExportedSession; use Socialbox\Objects\ExportedSession;
use Socialbox\Objects\PeerAddress; use Socialbox\Objects\PeerAddress;
use Socialbox\Objects\RpcRequest; use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\ServerDocument;
use Socialbox\Objects\Standard\SessionState; use Socialbox\Objects\Standard\SessionState;
class SocialClient extends RpcClient class SocialClient extends RpcClient
@ -58,16 +59,16 @@
} }
/** /**
* Retrieves the privacy policy from the server. * Fetches the privacy policy document by sending a remote procedure call request.
* *
* @return string Returns the privacy policy as a string. * @return ServerDocument The privacy policy document retrieved from the server.
* @throws RpcException Thrown if the RPC request fails. * @throws RpcException Thrown if the RPC request fails.
*/ */
public function getPrivacyPolicy(): string public function getPrivacyPolicy(): ServerDocument
{ {
return $this->sendRequest( return ServerDocument::fromArray($this->sendRequest(
new RpcRequest(StandardMethods::GET_PRIVACY_POLICY->value, Utilities::randomCrc32()) new RpcRequest(StandardMethods::GET_PRIVACY_POLICY->value, Utilities::randomCrc32())
)->getResponse()->getResult(); )->getResponse()->getResult());
} }
/** /**
@ -84,16 +85,16 @@
} }
/** /**
* Retrieves the terms of service from the server. * Retrieves the terms of service document by sending a remote procedure call request.
* *
* @return string Returns the terms of service as a string. * @return ServerDocument The terms of service document retrieved from the server.
* @throws RpcException Thrown if the RPC request fails. * @throws RpcException Thrown if the RPC request fails.
*/ */
public function getTermsOfService(): string public function getTermsOfService(): ServerDocument
{ {
return $this->sendRequest( return ServerDocument::fromArray($this->sendRequest(
new RpcRequest(StandardMethods::GET_TERMS_OF_SERVICE->value, Utilities::randomCrc32()) new RpcRequest(StandardMethods::GET_TERMS_OF_SERVICE->value, Utilities::randomCrc32())
)->getResponse()->getResult(); )->getResponse()->getResult());
} }
/** /**
@ -110,16 +111,16 @@
} }
/** /**
* Fetches the community guidelines by performing a remote procedure call request. * Fetches the community guidelines document from the server by sending a remote procedure call request.
* *
* @return string The content of the community guidelines. * @return ServerDocument The community guidelines document retrieved from the server.
* @throws RpcException Thrown if the RPC request encounters an error. * @throws RpcException Thrown if the RPC request fails.
*/ */
public function getCommunityGuidelines(): string public function getCommunityGuidelines(): ServerDocument
{ {
return $this->sendRequest( return ServerDocument::fromArray($this->sendRequest(
new RpcRequest(StandardMethods::GET_COMMUNITY_GUIDELINES->value, Utilities::randomCrc32()) new RpcRequest(StandardMethods::GET_COMMUNITY_GUIDELINES->value, Utilities::randomCrc32())
)->getResponse()->getResult(); )->getResponse()->getResult());
} }
/** /**