2024-09-25 00:40:46 -04:00
< ? php
namespace Socialbox\Classes\CliCommands ;
2024-09-30 03:00:02 -04:00
use Exception ;
2024-09-25 00:40:46 -04:00
use PDOException ;
2024-09-30 03:00:02 -04:00
use Socialbox\Abstracts\CacheLayer ;
2024-09-25 00:40:46 -04:00
use Socialbox\Classes\Configuration ;
2024-09-30 03:00:02 -04:00
use Socialbox\Classes\Cryptography ;
2024-09-25 00:40:46 -04:00
use Socialbox\Classes\Database ;
2024-10-30 15:12:10 -04:00
use Socialbox\Classes\Logger ;
2024-09-25 00:40:46 -04:00
use Socialbox\Classes\Resources ;
use Socialbox\Enums\DatabaseObjects ;
2024-10-30 15:12:10 -04:00
use Socialbox\Exceptions\CryptographyException ;
2024-09-25 00:40:46 -04:00
use Socialbox\Interfaces\CliCommandInterface ;
class InitializeCommand implements CliCommandInterface
{
/**
2024-09-25 00:41:57 -04:00
* @ inheritDoc
2024-09-25 00:40:46 -04:00
*/
public static function execute ( array $args ) : int
{
2024-10-30 15:12:10 -04:00
if ( Configuration :: getInstanceConfiguration () -> isEnabled () === false && ! isset ( $args [ 'force' ]))
2024-09-25 00:40:46 -04:00
{
2024-10-30 15:12:10 -04: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 ));
}
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 ;
}
if ( Configuration :: getInstanceConfiguration () -> getDomain () === null )
{
Logger :: getLogger () -> error ( 'instance.domain is required but was not set' );
2024-09-25 00:40:46 -04:00
return 1 ;
}
2024-10-30 15:12:10 -04:00
if ( Configuration :: getInstanceConfiguration () -> getRpcEndpoint () === null )
{
Logger :: getLogger () -> error ( 'instance.rpc_endpoint is required but was not set' );
return 1 ;
}
2024-09-30 03:00:02 -04:00
2024-10-30 15:12:10 -04:00
Logger :: getLogger () -> info ( 'Initializing Socialbox...' );
2024-10-24 15:15:14 -04:00
if ( Configuration :: getCacheConfiguration () -> isEnabled ())
2024-09-30 03:00:02 -04:00
{
2024-10-30 15:12:10 -04:00
Logger :: getLogger () -> verbose ( 'Clearing cache layer...' );
2024-09-30 03:00:02 -04:00
CacheLayer :: getInstance () -> clear ();
}
2024-09-25 00:40:46 -04:00
foreach ( DatabaseObjects :: casesOrdered () as $object )
{
2024-10-30 15:12:10 -04:00
Logger :: getLogger () -> verbose ( " Initializing database object { $object -> value } " );
2024-09-25 00:40:46 -04:00
try
{
Database :: getConnection () -> exec ( file_get_contents ( Resources :: getDatabaseResource ( $object )));
}
catch ( PDOException $e )
{
// Check if the error code is for "table already exists"
if ( $e -> getCode () === '42S01' )
{
2024-10-30 15:12:10 -04:00
Logger :: getLogger () -> warning ( " Database object { $object -> value } already exists, skipping... " );
2024-09-25 00:40:46 -04:00
continue ;
}
else
{
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-09-30 03:00:02 -04:00
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 13:30:08 -05:00
if (
! Configuration :: getInstanceConfiguration () -> getPublicKey () ||
! Configuration :: getInstanceConfiguration () -> getPrivateKey () ||
! Configuration :: getInstanceConfiguration () -> getEncryptionKey ()
)
2024-09-30 03:00:02 -04:00
{
2024-10-30 15:12:10 -04:00
try
2024-09-30 03:00:02 -04:00
{
2024-10-30 15:12:10 -04:00
Logger :: getLogger () -> info ( 'Generating new key pair...' );
2024-09-30 03:00:02 -04:00
$keyPair = Cryptography :: generateKeyPair ();
2024-12-10 13:30:08 -05:00
$encryptionKey = Cryptography :: randomBytes ( 230 , 314 );
2024-09-30 03:00:02 -04:00
}
2024-10-30 15:12:10 -04:00
catch ( CryptographyException $e )
{
2024-12-10 13:30:08 -05:00
Logger :: getLogger () -> error ( 'Failed to generate cryptography values' , $e );
2024-10-30 15:12:10 -04:00
return 1 ;
}
Logger :: getLogger () -> info ( 'Updating configuration...' );
Configuration :: getConfigurationLib () -> set ( 'instance.private_key' , $keyPair -> getPrivateKey ());
Configuration :: getConfigurationLib () -> set ( 'instance.public_key' , $keyPair -> getPublicKey ());
2024-12-10 13:30:08 -05:00
Configuration :: getConfigurationLib () -> set ( 'instance.encryption_key' , $encryptionKey );
2024-10-30 15:12:10 -04:00
Configuration :: getConfigurationLib () -> save ();
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-30 03:00:02 -04:00
}
2024-10-30 15:12:10 -04:00
// TODO: Create a host peer here?
Logger :: getLogger () -> info ( 'Socialbox has been initialized successfully' );
2024-09-25 00:40:46 -04:00
return 0 ;
}
/**
2024-09-25 00:41:57 -04:00
* @ inheritDoc
2024-09-25 00:40:46 -04:00
*/
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:41:57 -04:00
* @ inheritDoc
2024-09-25 00:40:46 -04:00
*/
public static function getShortHelpMessage () : string
{
return " Initializes Socialbox for first-runs " ;
}
}