2024-09-25 00:40:46 -04:00
< ? php
2024-12-10 22:14:43 -05:00
namespace Socialbox\Classes\CliCommands ;
use Exception ;
use PDOException ;
use Socialbox\Abstracts\CacheLayer ;
use Socialbox\Classes\Configuration ;
use Socialbox\Classes\Cryptography ;
use Socialbox\Classes\Database ;
use Socialbox\Classes\Logger ;
use Socialbox\Classes\Resources ;
use Socialbox\Enums\DatabaseObjects ;
use Socialbox\Exceptions\CryptographyException ;
use Socialbox\Exceptions\DatabaseOperationException ;
use Socialbox\Interfaces\CliCommandInterface ;
use Socialbox\Managers\EncryptionRecordsManager ;
class InitializeCommand implements CliCommandInterface
2024-09-25 00:40:46 -04:00
{
2024-12-10 22:14:43 -05:00
/**
* @ inheritDoc
*/
public static function execute ( array $args ) : int
2024-09-25 00:40:46 -04:00
{
2024-12-10 22:14:43 -05:00
if ( Configuration :: getInstanceConfiguration () -> isEnabled () === false && ! isset ( $args [ 'force' ]))
2024-10-30 15:12:10 -04:00
{
2024-12-10 22:14:43 -05:00
$required_configurations = [
'database.host' , 'database.port' , 'database.username' , 'database.password' , 'database.name' ,
'instance.enabled' , 'instance.domain' , 'registration.*'
];
Logger :: getLogger () -> error ( 'Socialbox is disabled. Use --force to initialize the instance or set `instance.enabled` to True in the configuration' );
Logger :: getLogger () -> info ( 'The reason you are required to do this is to allow you to configure the instance before enabling it' );
Logger :: getLogger () -> info ( 'The following configurations are required to be set before enabling the instance:' );
foreach ( $required_configurations as $config )
{
Logger :: getLogger () -> info ( sprintf ( ' - %s' , $config ));
}
2024-09-25 00:40:46 -04:00
2024-12-10 22:14:43 -05:00
Logger :: getLogger () -> info ( 'instance.private_key & instance.public_key are automatically generated if not set' );
Logger :: getLogger () -> info ( 'instance.domain is required to be set to the domain name of the instance' );
Logger :: getLogger () -> info ( 'instance.rpc_endpoint is required to be set to the publicly accessible http rpc endpoint of this server' );
Logger :: getLogger () -> info ( 'registration.* are required to be set to allow users to register to the instance' );
Logger :: getLogger () -> info ( 'You will be given a DNS TXT record to set for the public key after the initialization process' );
Logger :: getLogger () -> info ( 'The configuration file can be edited using ConfigLib:' );
Logger :: getLogger () -> info ( ' configlib --conf socialbox -e nano' );
Logger :: getLogger () -> info ( 'Or manually at:' );
Logger :: getLogger () -> info ( sprintf ( ' %s' , Configuration :: getConfigurationLib () -> getPath ()));
return 1 ;
}
2024-09-30 03:00:02 -04:00
2024-12-10 22:14:43 -05:00
if ( Configuration :: getInstanceConfiguration () -> getDomain () === null )
{
Logger :: getLogger () -> error ( 'instance.domain is required but was not set' );
return 1 ;
}
2024-09-30 03:00:02 -04:00
2024-12-10 22:14:43 -05:00
if ( Configuration :: getInstanceConfiguration () -> getRpcEndpoint () === null )
{
Logger :: getLogger () -> error ( 'instance.rpc_endpoint is required but was not set' );
return 1 ;
}
2024-09-25 00:40:46 -04:00
2024-12-10 22:14:43 -05:00
Logger :: getLogger () -> info ( 'Initializing Socialbox...' );
if ( Configuration :: getCacheConfiguration () -> isEnabled ())
2024-09-25 00:40:46 -04:00
{
2024-12-10 22:14:43 -05:00
Logger :: getLogger () -> verbose ( 'Clearing cache layer...' );
CacheLayer :: getInstance () -> clear ();
2024-09-25 00:40:46 -04:00
}
2024-12-10 22:14:43 -05:00
foreach ( DatabaseObjects :: casesOrdered () as $object )
2024-09-25 00:40:46 -04:00
{
2024-12-10 22:14:43 -05:00
Logger :: getLogger () -> verbose ( " Initializing database object { $object -> value } " );
try
2024-09-25 00:40:46 -04:00
{
2024-12-10 22:14:43 -05:00
Database :: getConnection () -> exec ( file_get_contents ( Resources :: getDatabaseResource ( $object )));
2024-09-25 00:40:46 -04:00
}
2024-12-10 22:14:43 -05:00
catch ( PDOException $e )
{
// Check if the error code is for "table already exists"
if ( $e -> getCode () === '42S01' )
{
Logger :: getLogger () -> warning ( " Database object { $object -> value } already exists, skipping... " );
continue ;
}
else
{
Logger :: getLogger () -> error ( " Failed to initialize database object { $object -> value } : { $e -> getMessage () } " , $e );
return 1 ;
}
}
catch ( Exception $e )
2024-09-25 00:40:46 -04:00
{
2024-10-30 15:12:10 -04:00
Logger :: getLogger () -> error ( " Failed to initialize database object { $object -> value } : { $e -> getMessage () } " , $e );
2024-09-25 00:40:46 -04:00
return 1 ;
}
}
2024-12-10 22:14:43 -05:00
if (
! Configuration :: getInstanceConfiguration () -> getPublicKey () ||
! Configuration :: getInstanceConfiguration () -> getPrivateKey () ||
! Configuration :: getInstanceConfiguration () -> getEncryptionKeys ()
)
2024-09-25 00:40:46 -04:00
{
2024-12-10 22:14:43 -05:00
try
{
Logger :: getLogger () -> info ( 'Generating new key pair...' );
$keyPair = Cryptography :: generateKeyPair ();
$encryptionKeys = Cryptography :: randomKeyS ( 230 , 314 , Configuration :: getInstanceConfiguration () -> getEncryptionKeysCount ());
}
catch ( CryptographyException $e )
{
Logger :: getLogger () -> error ( 'Failed to generate cryptography values' , $e );
return 1 ;
}
Logger :: getLogger () -> info ( 'Updating configuration...' );
Configuration :: getConfigurationLib () -> set ( 'instance.private_key' , $keyPair -> getPrivateKey ());
Configuration :: getConfigurationLib () -> set ( 'instance.public_key' , $keyPair -> getPublicKey ());
Configuration :: getConfigurationLib () -> set ( 'instance.encryption_keys' , $encryptionKeys );
Configuration :: getConfigurationLib () -> save (); // Save
Configuration :: reload (); // Reload
Logger :: getLogger () -> info ( sprintf ( 'Set the DNS TXT record for the domain %s to the following value:' , Configuration :: getInstanceConfiguration () -> getDomain ()));
Logger :: getLogger () -> info ( sprintf ( " v=socialbox;sb-rpc=%s;sb-key=%s; " ,
Configuration :: getInstanceConfiguration () -> getRpcEndpoint (), $keyPair -> getPublicKey ()
));
2024-09-25 00:40:46 -04:00
}
2024-10-30 15:12:10 -04:00
try
2024-09-30 03:00:02 -04:00
{
2024-12-10 22:14:43 -05:00
if ( EncryptionRecordsManager :: getRecordCount () < Configuration :: getInstanceConfiguration () -> getEncryptionRecordsCount ())
{
Logger :: getLogger () -> info ( 'Generating encryption records...' );
EncryptionRecordsManager :: generateRecords ( Configuration :: getInstanceConfiguration () -> getEncryptionRecordsCount ());
}
2024-09-30 03:00:02 -04:00
}
2024-10-30 15:12:10 -04:00
catch ( CryptographyException $e )
{
2024-12-10 22:14:43 -05:00
Logger :: getLogger () -> error ( 'Failed to generate encryption records due to a cryptography exception' , $e );
}
catch ( DatabaseOperationException $e )
{
Logger :: getLogger () -> error ( 'Failed to generate encryption records due to a database error' , $e );
2024-10-30 15:12:10 -04:00
}
2024-12-10 22:14:43 -05:00
// TODO: Create a host peer here?
Logger :: getLogger () -> info ( 'Socialbox has been initialized successfully' );
return 0 ;
2024-09-30 03:00:02 -04:00
}
2024-12-10 22:14:43 -05:00
/**
* @ inheritDoc
*/
public static function getHelpMessage () : string
{
return " Initialize Command - Initializes Socialbox for first-runs \n " .
" Usage: socialbox init [arguments] \n \n " .
" Arguments: \n " .
" --force - Forces the initialization process to run even the instance is disabled \n " ;
}
2024-09-25 00:40:46 -04:00
2024-12-10 22:14:43 -05:00
/**
* @ inheritDoc
*/
public static function getShortHelpMessage () : string
{
return " Initializes Socialbox for first-runs " ;
}
}