From 395e6b95ff9ff7259de440605552e72af71c8b95 Mon Sep 17 00:00:00 2001 From: netkas Date: Mon, 23 Dec 2024 19:02:37 -0500 Subject: [PATCH] Refactor and extend configuration classes. --- .idea/php.xml | 7 +- .idea/socialbox-php.iml | 2 - composer.json | 3 +- .../ClientCommands/StorageConfiguration.php | 52 +++ src/Socialbox/Classes/Configuration.php | 438 ++++++++++-------- .../Configuration/CacheConfiguration.php | 204 +++++--- .../Configuration/DatabaseConfiguration.php | 111 +++-- .../Configuration/LoggingConfiguration.php | 222 ++++----- .../RegistrationConfiguration.php | 339 ++++++++------ .../Configuration/SecurityConfiguration.php | 94 ++-- src/Socialbox/Classes/Resources.php | 18 + .../documents/community_guidelines.html | 1 + .../AcceptCommunityGuidelines.php | 37 ++ .../StandardMethods/AcceptPrivacyPolicy.php | 19 +- .../StandardMethods/AcceptTermsOfService.php | 19 +- .../GetCommunityGuidelines.php | 28 ++ .../StandardMethods/GetPrivacyPolicy.php | 8 +- .../StandardMethods/GetTermsOfService.php | 8 +- .../VerificationGetImageCaptcha.php | 1 + src/Socialbox/Classes/Utilities.php | 60 +++ src/Socialbox/Enums/StandardMethods.php | 43 +- src/Socialbox/Managers/SessionManager.php | 17 + .../Objects/Standard/ServerDocument.php | 76 +++ src/Socialbox/SocialClient.php | 33 +- 24 files changed, 1158 insertions(+), 682 deletions(-) create mode 100644 src/Socialbox/Classes/ClientCommands/StorageConfiguration.php create mode 100644 src/Socialbox/Classes/Resources/documents/community_guidelines.html create mode 100644 src/Socialbox/Classes/StandardMethods/AcceptCommunityGuidelines.php create mode 100644 src/Socialbox/Classes/StandardMethods/GetCommunityGuidelines.php create mode 100644 src/Socialbox/Objects/Standard/ServerDocument.php diff --git a/.idea/php.xml b/.idea/php.xml index 26fbabf..acc3054 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -58,7 +58,7 @@ - + @@ -77,7 +77,7 @@ - + @@ -94,9 +94,6 @@ - - - diff --git a/.idea/socialbox-php.iml b/.idea/socialbox-php.iml index 47ac8d8..9ac0b9d 100644 --- a/.idea/socialbox-php.iml +++ b/.idea/socialbox-php.iml @@ -2,8 +2,6 @@ - - diff --git a/composer.json b/composer.json index 05de501..2386ce4 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ "ext-openssl": "*", "ext-redis": "*", "ext-memcached": "*", - "ext-curl": "*" + "ext-curl": "*", + "ext-gd": "*" } } \ No newline at end of file diff --git a/src/Socialbox/Classes/ClientCommands/StorageConfiguration.php b/src/Socialbox/Classes/ClientCommands/StorageConfiguration.php new file mode 100644 index 0000000..913c3d4 --- /dev/null +++ b/src/Socialbox/Classes/ClientCommands/StorageConfiguration.php @@ -0,0 +1,52 @@ +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; + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/Configuration.php b/src/Socialbox/Classes/Configuration.php index 07fc492..b1aa90b 100644 --- a/src/Socialbox/Classes/Configuration.php +++ b/src/Socialbox/Classes/Configuration.php @@ -1,236 +1,264 @@ 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.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) + /** + * 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'); + + // 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(); } - return self::$configuration->getConfiguration(); - } - - public static function getConfigurationLib(): \ConfigLib\Configuration - { - if(self::$configuration === null) + /** + * 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 { - self::initializeConfiguration(); + if(self::$configuration === null) + { + self::initializeConfiguration(); + } + + return self::$configuration->getConfiguration(); } - return self::$configuration; - } - - /** - * Retrieves the current instance configuration. - * - * @return InstanceConfiguration The current instance configuration instance. - */ - public static function getInstanceConfiguration(): InstanceConfiguration - { - if(self::$instanceConfiguration === null) + public static function getConfigurationLib(): \ConfigLib\Configuration { - self::initializeConfiguration(); + if(self::$configuration === null) + { + self::initializeConfiguration(); + } + + return self::$configuration; } - return self::$instanceConfiguration; - } - - /** - * Retrieves the current security configuration. - * - * @return SecurityConfiguration The current security configuration instance. - */ - public static function getSecurityConfiguration(): SecurityConfiguration - { - if(self::$securityConfiguration === null) + /** + * Retrieves the current instance configuration. + * + * @return InstanceConfiguration The current instance configuration instance. + */ + public static function getInstanceConfiguration(): InstanceConfiguration { - self::initializeConfiguration(); + if(self::$instanceConfiguration === null) + { + self::initializeConfiguration(); + } + + return self::$instanceConfiguration; } - return self::$securityConfiguration; - } - - /** - * Retrieves the current database configuration. - * - * @return DatabaseConfiguration The configuration settings for the database. - */ - public static function getDatabaseConfiguration(): DatabaseConfiguration - { - if(self::$databaseConfiguration === null) + /** + * Retrieves the current security configuration. + * + * @return SecurityConfiguration The current security configuration instance. + */ + public static function getSecurityConfiguration(): SecurityConfiguration { - self::initializeConfiguration(); + if(self::$securityConfiguration === null) + { + self::initializeConfiguration(); + } + + return self::$securityConfiguration; } - return self::$databaseConfiguration; - } - - /** - * Retrieves the current logging configuration. - * - * @return LoggingConfiguration The current logging configuration instance. - */ - public static function getLoggingConfiguration(): LoggingConfiguration - { - if(self::$loggingConfiguration === null) + /** + * Retrieves the current database configuration. + * + * @return DatabaseConfiguration The configuration settings for the database. + */ + public static function getDatabaseConfiguration(): DatabaseConfiguration { - self::initializeConfiguration(); + if(self::$databaseConfiguration === null) + { + self::initializeConfiguration(); + } + + return self::$databaseConfiguration; } - return self::$loggingConfiguration; - } - - /** - * Retrieves the current cache configuration. If the cache configuration - * has not been initialized, it will initialize it first. - * - * @return CacheConfiguration The current cache configuration instance. - */ - public static function getCacheConfiguration(): CacheConfiguration - { - if(self::$cacheConfiguration === null) + /** + * Retrieves the current logging configuration. + * + * @return LoggingConfiguration The current logging configuration instance. + */ + public static function getLoggingConfiguration(): LoggingConfiguration { - self::initializeConfiguration(); + if(self::$loggingConfiguration === null) + { + self::initializeConfiguration(); + } + + return self::$loggingConfiguration; } - return self::$cacheConfiguration; - } - - /** - * 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) + /** + * Retrieves the current cache configuration. If the cache configuration + * has not been initialized, it will initialize it first. + * + * @return CacheConfiguration The current cache configuration instance. + */ + public static function getCacheConfiguration(): CacheConfiguration { - self::initializeConfiguration(); + if(self::$cacheConfiguration === null) + { + self::initializeConfiguration(); + } + + return self::$cacheConfiguration; } - return self::$registrationConfiguration; - } -} \ No newline at end of file + /** + * 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; + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/Configuration/CacheConfiguration.php b/src/Socialbox/Classes/Configuration/CacheConfiguration.php index 5f5d8f4..05ba6bb 100644 --- a/src/Socialbox/Classes/Configuration/CacheConfiguration.php +++ b/src/Socialbox/Classes/Configuration/CacheConfiguration.php @@ -1,83 +1,151 @@ 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; + private bool $enabled; + private string $engine; + private string $host; + private int $port; + private ?string $username; + private ?string $password; + private ?int $database; - $this->sessionsEnabled = (bool)$data['sessions']['enabled']; - $this->sessionsTtl = (int)$data['sessions']['ttl']; - $this->sessionsMax = (int)$data['sessions']['max']; - } + private bool $sessionsEnabled; + private int $sessionsTtl; + private int $sessionsMax; - public function isEnabled(): bool - { - return $this->enabled; - } + /** + * Constructor to initialize configuration values. + * + * @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 - { - return $this->engine; - } + /** + * Checks whether the feature is enabled. + * + * @return bool Returns true if the feature is enabled, false otherwise. + */ + public function isEnabled(): bool + { + return $this->enabled; + } - public function getHost(): string - { - return $this->host; - } + /** + * Retrieves the engine name. + * + * @return string Returns the name of the engine. + */ + public function getEngine(): string + { + return $this->engine; + } - public function getPort(): int - { - return $this->port; - } + /** + * Retrieves the host value. + * + * @return string The host as a string. + */ + public function getHost(): string + { + return $this->host; + } - public function getUsername(): ?string - { - return $this->username; - } + /** + * Retrieves the port value. + * + * @return int The port number. + */ + public function getPort(): int + { + return $this->port; + } - public function getPassword(): ?string - { - return $this->password; - } + /** + * Retrieves the username value. + * + * @return string|null The username, or null if not set. + */ + public function getUsername(): ?string + { + return $this->username; + } - public function getDatabase(): ?int - { - return $this->database; - } + /** + * Retrieves the password value. + * + * @return string|null The password as a string or null if not set. + */ + public function getPassword(): ?string + { + return $this->password; + } - public function isSessionsEnabled(): bool - { - return $this->sessionsEnabled; - } + /** + * Retrieves the database identifier. + * + * @return int|null The database identifier or null if not set. + */ + public function getDatabase(): ?int + { + return $this->database; + } - public function getSessionsTtl(): int - { - return $this->sessionsTtl; - } + /** + * Checks whether sessions are enabled. + * + * @return bool Returns true if sessions are enabled, otherwise false. + */ + public function isSessionsEnabled(): bool + { + return $this->sessionsEnabled; + } - public function getSessionsMax(): int - { - return $this->sessionsMax; - } -} \ No newline at end of file + /** + * Retrieves the time-to-live (TTL) value for sessions. + * + * @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; + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/Configuration/DatabaseConfiguration.php b/src/Socialbox/Classes/Configuration/DatabaseConfiguration.php index 2eb427c..1093f68 100644 --- a/src/Socialbox/Classes/Configuration/DatabaseConfiguration.php +++ b/src/Socialbox/Classes/Configuration/DatabaseConfiguration.php @@ -1,46 +1,83 @@ 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']; - } + private string $host; + private int $port; + private string $username; + private ?string $password; + private string $name; - public function getHost(): string - { - return $this->host; - } + /** + * Constructor method to initialize properties from the provided data array. + * + * @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 - { - return $this->port; - } + /** + * Retrieves the host value. + * + * @return string The value of the host. + */ + public function getHost(): string + { + return $this->host; + } - public function getUsername(): string - { - return $this->username; - } + /** + * Retrieves the port value. + * + * @return int The value of the port. + */ + public function getPort(): int + { + return $this->port; + } - public function getPassword(): ?string - { - return $this->password; - } + /** + * Retrieves the username value. + * + * @return string The value of the username. + */ + public function getUsername(): string + { + return $this->username; + } - public function getName(): string - { - return $this->name; - } -} \ No newline at end of file + /** + * Retrieves the password value. + * + * @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; + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/Configuration/LoggingConfiguration.php b/src/Socialbox/Classes/Configuration/LoggingConfiguration.php index a499d53..2830648 100644 --- a/src/Socialbox/Classes/Configuration/LoggingConfiguration.php +++ b/src/Socialbox/Classes/Configuration/LoggingConfiguration.php @@ -1,115 +1,121 @@ 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']; - } + private bool $consoleLoggingEnabled; + private string $consoleLoggingLevel; + private bool $fileLoggingEnabled; + private string $fileLoggingLevel; - /** - * Checks if console logging is enabled. - * - * @return bool True if console logging is enabled, otherwise false. - */ - public function isConsoleLoggingEnabled(): bool - { - return $this->consoleLoggingEnabled; - } - - /** - * Retrieves the logging level for console output. - * - * @return LogLevel The logging level configured for console output. - */ - public function getConsoleLoggingLevel(): LogLevel - { - return $this->parseLogLevel($this->consoleLoggingLevel); - } - - /** - * Checks if file logging is enabled. - * - * @return bool True if file logging is enabled, false otherwise. - */ - public function isFileLoggingEnabled(): bool - { - return $this->fileLoggingEnabled; - } - - /** - * Retrieves the logging level for file logging. - * - * @return LogLevel The logging level set for file logging. - */ - public function getFileLoggingLevel(): LogLevel - { - return $this->parseLogLevel($this->fileLoggingLevel); - } - - /** - * Parses the given log level from string format to a LogLevel enumeration. - * - * @param string $logLevel The log level as a string. - * @return LogLevel The corresponding LogLevel enumeration. - */ - private function parseLogLevel(string $logLevel): LogLevel - { - switch (strtolower($logLevel)) { - case LogLevel::DEBUG: - case 'debug': - case '6': - case 'dbg': - return LogLevel::DEBUG; - case LogLevel::VERBOSE: - case 'verbose': - case '5': - case 'vrb': - return LogLevel::VERBOSE; - default: - case LogLevel::INFO: - case 'info': - case '4': - case 'inf': - return LogLevel::INFO; - case LogLevel::WARNING: - case 'warning': - case '3': - case 'wrn': - return LogLevel::WARNING; - 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; + /** + * 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']; + $this->consoleLoggingLevel = $data['console_logging_level']; + $this->fileLoggingEnabled = (bool) $data['file_logging_enabled']; + $this->fileLoggingLevel = $data['file_logging_level']; } - } -} \ No newline at end of file + + /** + * Checks if console logging is enabled. + * + * @return bool True if console logging is enabled, otherwise false. + */ + public function isConsoleLoggingEnabled(): bool + { + return $this->consoleLoggingEnabled; + } + + /** + * Retrieves the logging level for console output. + * + * @return LogLevel The logging level configured for console output. + */ + public function getConsoleLoggingLevel(): LogLevel + { + return $this->parseLogLevel($this->consoleLoggingLevel); + } + + /** + * Checks if file logging is enabled. + * + * @return bool True if file logging is enabled, false otherwise. + */ + public function isFileLoggingEnabled(): bool + { + return $this->fileLoggingEnabled; + } + + /** + * Retrieves the logging level for file logging. + * + * @return LogLevel The logging level set for file logging. + */ + public function getFileLoggingLevel(): LogLevel + { + return $this->parseLogLevel($this->fileLoggingLevel); + } + + /** + * Parses the given log level from string format to a LogLevel enumeration. + * + * @param string $logLevel The log level as a string. + * @return LogLevel The corresponding LogLevel enumeration. + */ + private function parseLogLevel(string $logLevel): LogLevel + { + switch (strtolower($logLevel)) + { + case LogLevel::DEBUG: + case 'debug': + case '6': + case 'dbg': + return LogLevel::DEBUG; + + case LogLevel::VERBOSE: + case 'verbose': + case '5': + case 'vrb': + return LogLevel::VERBOSE; + + default: + case LogLevel::INFO: + case 'info': + case '4': + case 'inf': + return LogLevel::INFO; + + case LogLevel::WARNING: + case 'warning': + case '3': + case 'wrn': + return LogLevel::WARNING; + 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; + } + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/Configuration/RegistrationConfiguration.php b/src/Socialbox/Classes/Configuration/RegistrationConfiguration.php index 29ebcea..b909c9f 100644 --- a/src/Socialbox/Classes/Configuration/RegistrationConfiguration.php +++ b/src/Socialbox/Classes/Configuration/RegistrationConfiguration.php @@ -1,171 +1,202 @@ registrationEnabled = (bool)$data['enabled']; - $this->privacyPolicyDocument = $data['privacy_policy_document'] ?? null; - $this->acceptPrivacyPolicy = $data['accept_privacy_policy'] ?? true; - $this->termsOfServiceDocument = $data['terms_of_service_document'] ?? null; - $this->acceptTermsOfService = $data['accept_terms_of_service'] ?? true; - $this->passwordRequired = (bool)$data['password_required']; - $this->otpRequired = (bool)$data['otp_required']; - $this->displayNameRequired = (bool)$data['display_name_required']; - $this->emailVerificationRequired = (bool)$data['email_verification_required']; - $this->smsVerificationRequired = (bool)$data['sms_verification_required']; - $this->phoneCallVerificationRequired = (bool)$data['phone_call_verification_required']; - $this->imageCaptchaVerificationRequired = (bool)$data['image_captcha_verification_required']; - } + private bool $registrationEnabled; + private ?string $privacyPolicyDocument; + private int $privacyPolicyDate; + private bool $acceptPrivacyPolicy; + private ?string $termsOfServiceDocument; + private int $termsOfServiceDate; + private bool $acceptTermsOfService; + private ?string $communityGuidelinesDocument; + private int $communityGuidelinesDate; + private bool $acceptCommunityGuidelines; + private bool $passwordRequired; + private bool $otpRequired; + private bool $displayNameRequired; + private bool $displayPictureRequired; + private bool $imageCaptchaVerificationRequired; - /** - * Checks if the registration is enabled. - * - * @return bool True if registration is enabled, false otherwise. - */ - public function isRegistrationEnabled(): bool - { - return $this->registrationEnabled; - } + /** + * 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']; + $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. - * - * @return ?string Returns the privacy policy document or null if not set. - */ - public function getPrivacyPolicyDocument(): ?string - { - return $this->privacyPolicyDocument; - } + /** + * Retrieves the privacy policy document. + * + * @return ?string Returns the privacy policy document or null if not set. + */ + public function getPrivacyPolicyDocument(): ?string + { + return $this->privacyPolicyDocument; + } - /** - * Checks if accepting the privacy policy is required. - * - * @return bool Returns true if the privacy policy must be accepted, false otherwise. - */ - public function isAcceptPrivacyPolicyRequired(): bool - { - return $this->acceptPrivacyPolicy; - } + /** + * Retrieves the date of the privacy policy. + * + * @return int Returns the date of the privacy policy. + */ + public function getPrivacyPolicyDate(): int + { + return $this->privacyPolicyDate; + } - /** - * Retrieves the terms of service document. - * - * @return ?string Returns the terms of service document or null if not set. - */ - public function getTermsOfServiceDocument(): ?string - { - return $this->termsOfServiceDocument; - } + /** + * Checks if accepting the privacy policy is required. + * + * @return bool Returns true if the privacy policy must be accepted, false otherwise. + */ + public function isAcceptPrivacyPolicyRequired(): bool + { + return $this->acceptPrivacyPolicy; + } - /** - * Checks if accepting the terms of service is required. - * - * @return bool Returns true if the terms of service must be accepted, false otherwise. - */ - public function isAcceptTermsOfServiceRequired(): bool - { - return $this->acceptTermsOfService; - } + /** + * Retrieves the terms of service document. + * + * @return ?string Returns the terms of service document or null if not set. + */ + public function getTermsOfServiceDocument(): ?string + { + return $this->termsOfServiceDocument; + } - /** - * Determines if a password is required. - * - * @return bool True if a password is required, false otherwise. - */ - public function isPasswordRequired(): bool - { - return $this->passwordRequired; - } + /** + * Retrieves the date of the terms of service. + * + * @return int Returns the date of the terms of service. + */ + public function getTermsOfServiceDate(): int + { + return $this->termsOfServiceDate; + } - /** - * Determines if OTP (One-Time Password) is required. - * - * @return bool True if OTP is required, false otherwise. - */ - public function isOtpRequired(): bool - { - return $this->otpRequired; - } + /** + * Checks if accepting the terms of service is required. + * + * @return bool Returns true if the terms of service must be accepted, false otherwise. + */ + public function isAcceptTermsOfServiceRequired(): bool + { + return $this->acceptTermsOfService; + } - /** - * 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; - } + /** + * Retrieves the community guidelines document. + * + * @return ?string Returns the community guidelines document or null if not set. + */ + public function getCommunityGuidelinesDocument(): ?string + { + return $this->communityGuidelinesDocument; + } - /** - * Checks if email verification is required. - * - * @return bool Returns true if email verification is required, false otherwise. - */ - public function isEmailVerificationRequired(): bool - { - return $this->emailVerificationRequired; - } + /** + * Retrieves the date of the community guidelines. + * + * @return int Returns the date of the community guidelines. + */ + public function getCommunityGuidelinesDate(): int + { + return $this->communityGuidelinesDate; + } - /** - * Checks if SMS verification is required. - * - * @return bool Returns true if SMS verification is required, false otherwise. - */ - public function isSmsVerificationRequired(): bool - { - return $this->smsVerificationRequired; - } + /** + * Checks if accepting the community guidelines is required. + * + * @return bool Returns true if the community guidelines must be accepted, false otherwise. + */ + public function isAcceptCommunityGuidelinesRequired(): bool + { + return $this->acceptCommunityGuidelines; + } - /** - * Checks if phone call verification is required. - * - * @return bool Returns true if phone call verification is required, false otherwise. - */ - public function isPhoneCallVerificationRequired(): bool - { - return $this->phoneCallVerificationRequired; - } + /** + * Determines if a password is required. + * + * @return bool True if a password is required, false otherwise. + */ + public function isPasswordRequired(): bool + { + return $this->passwordRequired; + } - /** - * 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; - } -} \ No newline at end of file + /** + * Determines if OTP (One-Time Password) is required. + * + * @return bool True if OTP is required, false otherwise. + */ + public function isOtpRequired(): bool + { + 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; + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/Configuration/SecurityConfiguration.php b/src/Socialbox/Classes/Configuration/SecurityConfiguration.php index 805437c..72854c2 100644 --- a/src/Socialbox/Classes/Configuration/SecurityConfiguration.php +++ b/src/Socialbox/Classes/Configuration/SecurityConfiguration.php @@ -1,55 +1,55 @@ displayInternalExceptions = $data['display_internal_exceptions']; - $this->resolvedServersTtl = $data['resolved_servers_ttl']; - $this->captchaTtl = $data['captcha_ttl']; - } + private bool $displayInternalExceptions; + private int $resolvedServersTtl; + private int $captchaTtl; - /** - * Determines if the display of internal errors is enabled. - * - * @return bool True if the display of internal errors is enabled, false otherwise. - */ - public function isDisplayInternalExceptions(): bool - { - return $this->displayInternalExceptions; - } + /** + * 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']; + $this->resolvedServersTtl = $data['resolved_servers_ttl']; + $this->captchaTtl = $data['captcha_ttl']; + } - /** - * Retrieves the time-to-live (TTL) value for resolved servers. - * - * @return int The TTL value for resolved servers. - */ - public function getResolvedServersTtl(): int - { - return $this->resolvedServersTtl; - } + /** + * Determines if the display of internal errors is enabled. + * + * @return bool True if the display of internal errors is enabled, false otherwise. + */ + public function isDisplayInternalExceptions(): bool + { + return $this->displayInternalExceptions; + } - /** - * Retrieves the time-to-live (TTL) value for captchas. - * - * @return int The TTL value for captchas. - */ - public function getCaptchaTtl(): int - { - return $this->captchaTtl; - } + /** + * Retrieves the time-to-live (TTL) value for resolved servers. + * + * @return int The TTL value for resolved servers. + */ + public function getResolvedServersTtl(): int + { + return $this->resolvedServersTtl; + } -} \ No newline at end of file + /** + * Retrieves the time-to-live (TTL) value for captchas. + * + * @return int The TTL value for captchas. + */ + public function getCaptchaTtl(): int + { + return $this->captchaTtl; + } + + } \ No newline at end of file diff --git a/src/Socialbox/Classes/Resources.php b/src/Socialbox/Classes/Resources.php index a7c32cb..ca23c34 100644 --- a/src/Socialbox/Classes/Resources.php +++ b/src/Socialbox/Classes/Resources.php @@ -64,4 +64,22 @@ 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')); + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/Resources/documents/community_guidelines.html b/src/Socialbox/Classes/Resources/documents/community_guidelines.html new file mode 100644 index 0000000..2e08c36 --- /dev/null +++ b/src/Socialbox/Classes/Resources/documents/community_guidelines.html @@ -0,0 +1 @@ +

Community Guidelines

\ No newline at end of file diff --git a/src/Socialbox/Classes/StandardMethods/AcceptCommunityGuidelines.php b/src/Socialbox/Classes/StandardMethods/AcceptCommunityGuidelines.php new file mode 100644 index 0000000..16ff746 --- /dev/null +++ b/src/Socialbox/Classes/StandardMethods/AcceptCommunityGuidelines.php @@ -0,0 +1,37 @@ +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); + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/StandardMethods/AcceptPrivacyPolicy.php b/src/Socialbox/Classes/StandardMethods/AcceptPrivacyPolicy.php index d87ada5..a09c5cd 100644 --- a/src/Socialbox/Classes/StandardMethods/AcceptPrivacyPolicy.php +++ b/src/Socialbox/Classes/StandardMethods/AcceptPrivacyPolicy.php @@ -21,28 +21,17 @@ { try { + // Remove the verification flag SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_PRIVACY_POLICY]); + + // Check & update the session flow + SessionManager::updateFlow($request->getSession()); } catch (DatabaseOperationException $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); } } \ No newline at end of file diff --git a/src/Socialbox/Classes/StandardMethods/AcceptTermsOfService.php b/src/Socialbox/Classes/StandardMethods/AcceptTermsOfService.php index bd5fb8c..2732c2e 100644 --- a/src/Socialbox/Classes/StandardMethods/AcceptTermsOfService.php +++ b/src/Socialbox/Classes/StandardMethods/AcceptTermsOfService.php @@ -20,28 +20,17 @@ { try { + // Remove the verification flag SessionManager::removeFlags($request->getSessionUuid(), [SessionFlags::VER_TERMS_OF_SERVICE]); + + // Check & update the session flow + SessionManager::updateFlow($request->getSession()); } catch (DatabaseOperationException $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); } } \ No newline at end of file diff --git a/src/Socialbox/Classes/StandardMethods/GetCommunityGuidelines.php b/src/Socialbox/Classes/StandardMethods/GetCommunityGuidelines.php new file mode 100644 index 0000000..4021f57 --- /dev/null +++ b/src/Socialbox/Classes/StandardMethods/GetCommunityGuidelines.php @@ -0,0 +1,28 @@ +produceResponse(new ServerDocument([ + 'last_updated' => Configuration::getRegistrationConfiguration()->getCommunityGuidelinesDate(), + 'title' => 'Community Guidelines', + 'content' => Resources::getCommunityGuidelines() + ])); + } + } \ No newline at end of file diff --git a/src/Socialbox/Classes/StandardMethods/GetPrivacyPolicy.php b/src/Socialbox/Classes/StandardMethods/GetPrivacyPolicy.php index 20ab6c5..db83fd0 100644 --- a/src/Socialbox/Classes/StandardMethods/GetPrivacyPolicy.php +++ b/src/Socialbox/Classes/StandardMethods/GetPrivacyPolicy.php @@ -3,11 +3,13 @@ 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 GetPrivacyPolicy extends Method { @@ -17,6 +19,10 @@ */ 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() + ])); } } \ No newline at end of file diff --git a/src/Socialbox/Classes/StandardMethods/GetTermsOfService.php b/src/Socialbox/Classes/StandardMethods/GetTermsOfService.php index c92a38f..96c1d51 100644 --- a/src/Socialbox/Classes/StandardMethods/GetTermsOfService.php +++ b/src/Socialbox/Classes/StandardMethods/GetTermsOfService.php @@ -3,11 +3,13 @@ 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 GetTermsOfService extends Method { @@ -17,6 +19,10 @@ */ 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() + ])); } } \ No newline at end of file diff --git a/src/Socialbox/Classes/StandardMethods/VerificationGetImageCaptcha.php b/src/Socialbox/Classes/StandardMethods/VerificationGetImageCaptcha.php index f935346..515938b 100644 --- a/src/Socialbox/Classes/StandardMethods/VerificationGetImageCaptcha.php +++ b/src/Socialbox/Classes/StandardMethods/VerificationGetImageCaptcha.php @@ -60,6 +60,7 @@ // Build 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([ 'expires' => $captchaRecord->getExpires(), 'content' => (new CaptchaBuilder($answer))->build()->inline() diff --git a/src/Socialbox/Classes/Utilities.php b/src/Socialbox/Classes/Utilities.php index d12ad20..ff38b98 100644 --- a/src/Socialbox/Classes/Utilities.php +++ b/src/Socialbox/Classes/Utilities.php @@ -194,6 +194,66 @@ class Utilities 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. * diff --git a/src/Socialbox/Enums/StandardMethods.php b/src/Socialbox/Enums/StandardMethods.php index e921744..0afad9c 100644 --- a/src/Socialbox/Enums/StandardMethods.php +++ b/src/Socialbox/Enums/StandardMethods.php @@ -2,8 +2,10 @@ namespace Socialbox\Enums; + use Socialbox\Classes\StandardMethods\AcceptCommunityGuidelines; use Socialbox\Classes\StandardMethods\AcceptPrivacyPolicy; use Socialbox\Classes\StandardMethods\AcceptTermsOfService; + use Socialbox\Classes\StandardMethods\GetCommunityGuidelines; use Socialbox\Classes\StandardMethods\GetPrivacyPolicy; use Socialbox\Classes\StandardMethods\GetSessionState; use Socialbox\Classes\StandardMethods\GetTermsOfService; @@ -74,11 +76,15 @@ self::ACCEPT_PRIVACY_POLICY => AcceptPrivacyPolicy::execute($request, $rpcRequest), self::GET_TERMS_OF_SERVICE => GetTermsOfService::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_ANSWER_IMAGE_CAPTCHA => VerificationAnswerImageCaptcha::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 { + // These methods should always accessible $methods = [ - self::PING, - self::GET_SESSION_STATE, - self::GET_PRIVACY_POLICY, - self::GET_TERMS_OF_SERVICE, + // Important methods + self::PING, // Always allow the ping method + self::GET_SESSION_STATE, // The session state should always be accessible + 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(); - 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; } - 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; } - 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_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())) { $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; } } \ No newline at end of file diff --git a/src/Socialbox/Managers/SessionManager.php b/src/Socialbox/Managers/SessionManager.php index 0b50151..982a66b 100644 --- a/src/Socialbox/Managers/SessionManager.php +++ b/src/Socialbox/Managers/SessionManager.php @@ -454,4 +454,21 @@ 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]); + } + } } \ No newline at end of file diff --git a/src/Socialbox/Objects/Standard/ServerDocument.php b/src/Socialbox/Objects/Standard/ServerDocument.php new file mode 100644 index 0000000..2143eb2 --- /dev/null +++ b/src/Socialbox/Objects/Standard/ServerDocument.php @@ -0,0 +1,76 @@ +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 + ]; + } + } \ No newline at end of file diff --git a/src/Socialbox/SocialClient.php b/src/Socialbox/SocialClient.php index 669508d..f23e79f 100644 --- a/src/Socialbox/SocialClient.php +++ b/src/Socialbox/SocialClient.php @@ -13,6 +13,7 @@ use Socialbox\Objects\ExportedSession; use Socialbox\Objects\PeerAddress; use Socialbox\Objects\RpcRequest; + use Socialbox\Objects\Standard\ServerDocument; use Socialbox\Objects\Standard\SessionState; 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. */ - 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()) - )->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. */ - 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()) - )->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. - * @throws RpcException Thrown if the RPC request encounters an error. + * @return ServerDocument The community guidelines document retrieved from the server. + * @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()) - )->getResponse()->getResult(); + )->getResponse()->getResult()); } /**