Initial Commit

This commit is contained in:
Netkas 2023-06-04 14:23:51 -04:00
parent 93a0b9be02
commit 6e599b2c0c
No known key found for this signature in database
GPG key ID: 5DAF58535614062B
99 changed files with 10836 additions and 4 deletions

View file

@ -0,0 +1,149 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace FederationCLI;
use FederationLib\FederationLib;
class InteractiveMode
{
/**
* The current menu the user is in
*
* @var string
*/
private static $current_menu = 'Main';
/**
* An array of menu pointers to functions
*
* @var string[]
*/
private static $menu_pointers = [
'ClientManager' => 'FederationCLI\InteractiveMode\ClientManager::processCommand',
'ConfigManager' => 'FederationCLI\InteractiveMode\ConfigurationManager::processCommand'
];
private static $help_pointers =[
'ClientManager' => 'FederationCLI\InteractiveMode\ClientManager::help',
'ConfigManager' => 'FederationCLI\InteractiveMode\ConfigurationManager::help'
];
/**
* @var FederationLib|null
*/
private static $federation_lib = null;
/**
* Main entry point for the interactive mode
*
* @param array $args
* @return void
*/
public static function main(array $args=[]): void
{
while(true)
{
print(sprintf('federation@%s:~$ ', self::$current_menu));
$input = trim(fgets(STDIN));
self::processCommand($input);
}
}
/**
* Processes a command from the user
*
* @param string $input
* @return void
*/
private static function processCommand(string $input): void
{
$parsed_input = Utilities::parseShellInput($input);
switch(strtolower($parsed_input['command']))
{
case 'help':
print('Available commands:' . PHP_EOL);
print(' help - displays the help menu for the current menu and global commands' . PHP_EOL);
print(' client_manager - enter client manager mode' . PHP_EOL);
print(' config_manager - enter config manager mode' . PHP_EOL);
print(' clear - clears the screen' . PHP_EOL);
print(' exit - exits the current menu, if on the main menu, exits the program' . PHP_EOL);
if(isset(self::$help_pointers[self::$current_menu]))
{
call_user_func(self::$help_pointers[self::$current_menu]);
}
break;
case 'client_manager':
self::$current_menu = 'ClientManager';
break;
case 'config_manager':
self::$current_menu = 'ConfigManager';
break;
case 'clear':
print(chr(27) . "[2J" . chr(27) . "[;H");
break;
case 'exit':
if(self::$current_menu != 'Main')
{
self::$current_menu = 'Main';
break;
}
exit(0);
default:
if(!isset(self::$menu_pointers[self::$current_menu]))
{
print(sprintf('Unknown command: %s', $parsed_input['command']) . PHP_EOL);
break;
}
call_user_func(self::$menu_pointers[self::$current_menu], $input);
break;
}
}
/**
* Returns the current menu
*
* @return string
*/
public static function getCurrentMenu(): string
{
return self::$current_menu;
}
/**
* Sets the current menu to the specified value
*
* @param string $current_menu
*/
public static function setCurrentMenu(string $current_menu): void
{
self::$current_menu = $current_menu;
}
/**
* Returns the FederationLib instance
*
* @return FederationLib
*/
public static function getFederationLib(): FederationLib
{
if(self::$federation_lib == null)
{
self::$federation_lib = new FederationLib();
}
return self::$federation_lib;
}
}

View file

@ -0,0 +1,190 @@
<?php
namespace FederationCLI\InteractiveMode;
use AsciiTable\Builder;
use Exception;
use FederationCLI\InteractiveMode;
use FederationCLI\Utilities;
use FederationLib\Enums\FilterOrder;
use FederationLib\Enums\Filters\ListClientsFilter;
use FederationLib\Exceptions\DatabaseException;
use FederationLib\Objects\Client;
class ClientManager
{
/**
* @param string $input
* @return void
*/
public static function processCommand(string $input): void
{
$parsed_input = Utilities::parseShellInput($input);
try
{
switch(strtolower($parsed_input['command']))
{
case 'register':
self::registerClient();
break;
case 'list':
// list [optional: page] [optional: filter] [optional: order] [optional: max_items]
self::listClients($parsed_input['args']);
break;
case 'total':
self::totalClients();
break;
case 'total_pages':
self::totalPages($parsed_input['args']);
break;
case 'get':
self::getClient($parsed_input['args']);
break;
default:
print(sprintf('Unknown command: %s', $parsed_input['command']) . PHP_EOL);
break;
}
}
catch(Exception $e)
{
Utilities::printExceptionStack($e);
}
}
/**
* Displays the help message for the client manager
*
* @return void
*/
public static function help(): void
{
print('Client manager commands:' . PHP_EOL);
print(' register - registers a new client with the federation' . PHP_EOL);
print(' list [optional: page (default 1)] [optional: filter (default created_timestamp)] [optional: order (default asc)] [optional: max_items (default 100)] - lists clients' . PHP_EOL);
print(' total - gets the total number of clients' . PHP_EOL);
print(' total_pages [optional: max_items (default 100)] - gets the total number of pages of clients' . PHP_EOL);
print(' get [client uuid] - gets a client by UUID' . PHP_EOL);
}
/**
* Registers a new client with the federation. prints the UUID of the client if successful.
*
* @return void
*/
private static function registerClient(): void
{
$client = new Client();
$client->setName(Utilities::promptInput('Client name (default: Random): '));
$client->setDescription(Utilities::promptInput('Client description (default: N/A): '));
$client->setQueryPermission((int)Utilities::parseBoolean(Utilities::promptInput('Query permission (default: 1): ')));
$client->setUpdatePermission((int)Utilities::parseBoolean(Utilities::promptInput('Update permission (default: 0): ')));
try
{
$client_uuid = InteractiveMode::getFederationLib()->getClientManager()->registerClient($client);
}
catch(Exception $e)
{
print('Failed to register client: ' . $e->getMessage() . PHP_EOL);
Utilities::printExceptionStack($e);
return;
}
print(sprintf('Client registered successfully, UUID: %s', $client_uuid) . PHP_EOL);
}
/**
* @param array $args
* @return void
* @throws DatabaseException
* @throws \Doctrine\DBAL\Exception
* @throws \RedisException
*/
private static function listClients(array $args): void
{
$page = $args[0] ?? 1;
$filter = $args[1] ?? ListClientsFilter::CREATED_TIMESTAMP;
$order = $args[2] ?? FilterOrder::ASCENDING;
$max_items = $args[3] ?? 100;
$clients = InteractiveMode::getFederationLib()->getClientManager()->listClients($page, $filter, $order, $max_items);
if(count($clients) === 0)
{
print('No clients found' . PHP_EOL);
}
else
{
$builder = new Builder();
foreach($clients as $client)
{
$builder->addRow($client->toArray());
}
$builder->setTitle(sprintf('Clients (page %d, filter %s, order %s, max items %d)', $page, $filter, $order, $max_items));
print($builder->renderTable() . PHP_EOL);
}
}
private static function getClient(mixed $args)
{
$client_uuid = $args[0] ?? null;
if(is_null($client_uuid))
{
print('Client UUID required' . PHP_EOL);
return;
}
try
{
$client = InteractiveMode::getFederationLib()->getClientManager()->getClient($client_uuid);
}
catch(Exception $e)
{
print('Failed to get client: ' . $e->getMessage() . PHP_EOL);
Utilities::printExceptionStack($e);
return;
}
foreach($client->toArray() as $key => $value)
{
print match ($key)
{
'id' => (sprintf(' UUID: %s', $value) . PHP_EOL),
'enabled' => (sprintf(' Enabled: %s', (Utilities::parseBoolean($value) ? 'Yes' : 'No')) . PHP_EOL),
'name' => (sprintf(' Name: %s', $value ?? 'N/A') . PHP_EOL),
'description' => (sprintf(' Description: %s', $value ?? 'N/A') . PHP_EOL),
'secret_totp' => (sprintf(' Secret TOTP: %s', $value ?? 'N/A') . PHP_EOL),
'query_permission' => (sprintf(' Query permission Level: %s', $value) . PHP_EOL),
'update_permission' => (sprintf(' Update permission Level: %s', $value) . PHP_EOL),
'flags' => (sprintf(' Flags: %s', $value) . PHP_EOL),
'created_timestamp' => (sprintf(' Created: %s', date('Y-m-d H:i:s', $value)) . PHP_EOL),
'updated_timestamp' => (sprintf(' Updated: %s', date('Y-m-d H:i:s', $value)) . PHP_EOL),
'seen_timestamp' => (sprintf(' Last seen: %s', date('Y-m-d H:i:s', $value)) . PHP_EOL),
default => (sprintf(' %s: %s', $key, $value) . PHP_EOL),
};
}
}
private static function totalClients()
{
print(sprintf('Total clients: %d', InteractiveMode::getFederationLib()->getClientManager()->getTotalClients()) . PHP_EOL);
}
private static function totalPages(mixed $args)
{
$max_items = $args[0] ?? 100;
print(sprintf('Total pages: %d', InteractiveMode::getFederationLib()->getClientManager()->getTotalPages($max_items)) . PHP_EOL);
}
}

View file

@ -0,0 +1,113 @@
<?php
namespace FederationCLI\InteractiveMode;
use Exception;
use FederationCLI\Utilities;
use FederationLib\Classes\Configuration;
class ConfigurationManager
{
/**
* @param string $input
* @return void
*/
public static function processCommand(string $input): void
{
$parsed_input = Utilities::parseShellInput($input);
switch(strtolower($parsed_input['command']))
{
case 'read':
self::read($parsed_input['args'][0] ?? null);
break;
case 'write':
self::write($parsed_input['args'][0] ?? null, $parsed_input['args'][1] ?? null);
break;
case 'save':
self::save();
break;
default:
print(sprintf('Unknown command: %s', $parsed_input['command']) . PHP_EOL);
break;
}
}
/**
* Displays the help message for the client manager
*
* @return void
*/
public static function help(): void
{
print('Configuration manager commands:' . PHP_EOL);
print(' read - reads the current configuration' . PHP_EOL);
print(' read <key> - reads the value of the specified configuration key' . PHP_EOL);
print(' write <key> <value> - writes the value of the specified configuration key' . PHP_EOL);
print(' save - saves the current configuration to disk' . PHP_EOL);
}
/**
* Reads the current configuration or the value of a specific key
*
* @param string|null $key
* @return void
*/
private static function read(?string $key=null): void
{
if($key === null)
{
$value = Configuration::getConfiguration();
}
else
{
$value = Configuration::getConfigurationObject()->get($key);
}
if(is_null($value))
{
print('No value found for key: ' . $key . PHP_EOL);
}
elseif(is_array($value))
{
print(json_encode($value, JSON_PRETTY_PRINT) . PHP_EOL);
}
else
{
print($value . PHP_EOL);
}
}
/**
* Writes the value of a specific configuration key
*
* @param string $key
* @param string $value
* @return void
*/
private static function write(string $key, string $value): void
{
Configuration::getConfigurationObject()->set($key, $value);
}
/**
* Writes the current configuration to disk
*
* @return void
*/
private static function save(): void
{
try
{
Configuration::getConfigurationObject()->save();
}
catch(Exception $e)
{
print('Failed to save configuration: ' . $e->getMessage() . PHP_EOL);
Utilities::printExceptionStack($e);
}
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace FederationCLI;
use ncc\Runtime;
class Program
{
/**
* Main entry point for the CLI
*
* @param array $args
* @return void
*/
public static function main(array $args=[]): void
{
if (isset($args['shell']))
{
InteractiveMode::main($args);
}
self::help();
}
/**
* Displays the help message
*
* @return void
*/
public static function help(): void
{
print('FederationLib v' . Runtime::getConstant('net.nosial.federationlib', 'version') . PHP_EOL . PHP_EOL);
print('Usage: federationlib [command] [options]' . PHP_EOL);
print('Commands:' . PHP_EOL);
print(' help - show this help' . PHP_EOL);
print(' shell - enter interactive mode' . PHP_EOL);
exit(0);
}
}

View file

@ -0,0 +1,101 @@
<?php
namespace FederationCLI;
class Utilities
{
/**
* Parses the shell input into a command and arguments array
*
* @param string $input
* @return array
*/
public static function parseShellInput(string $input): array
{
$parsed = explode(' ', $input);
$command = array_shift($parsed);
$args = $parsed;
return [
'command' => $command,
'args' => $args
];
}
/**
* Parses a boolean value from a string
*
* @param $input
* @return bool
*/
public static function parseBoolean($input): bool
{
if(is_null($input))
return false;
if(is_bool($input))
return $input;
if(is_numeric($input))
return (bool) $input;
if(is_string($input))
$input = trim($input);
switch(strtolower($input))
{
case 'true':
case 'yes':
case 'y':
case '1':
return true;
default:
case 'false':
case 'no':
case 'n':
case '0':
return false;
}
}
/**
* Prompts the user for an input value
*
* @param string|null $prompt
* @param string|null $default_value
* @return string|null
*/
public static function promptInput(?string $prompt=null, ?string $default_value=null): ?string
{
if($prompt)
print($prompt . ' ');
$input = trim(fgets(STDIN));
if(!$input && $default_value)
$input = $default_value;
return $input;
}
/**
* Prompts the user for a boolean value
*
* @param string|null $prompt
* @param bool $default_value
* @return bool
*/
public static function promptYesNo(?string $prompt=null, bool $default_value=false): bool
{
if($prompt)
print($prompt . ' ');
$input = trim(fgets(STDIN));
if(!$input && $default_value)
$input = $default_value;
return self::parseBoolean($input);
}
}