Initial Commit
This commit is contained in:
parent
93a0b9be02
commit
6e599b2c0c
99 changed files with 10836 additions and 4 deletions
149
src/FederationCLI/InteractiveMode.php
Normal file
149
src/FederationCLI/InteractiveMode.php
Normal 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;
|
||||
}
|
||||
}
|
190
src/FederationCLI/InteractiveMode/ClientManager.php
Normal file
190
src/FederationCLI/InteractiveMode/ClientManager.php
Normal 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);
|
||||
}
|
||||
}
|
113
src/FederationCLI/InteractiveMode/ConfigurationManager.php
Normal file
113
src/FederationCLI/InteractiveMode/ConfigurationManager.php
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
41
src/FederationCLI/Program.php
Normal file
41
src/FederationCLI/Program.php
Normal 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);
|
||||
}
|
||||
}
|
101
src/FederationCLI/Utilities.php
Normal file
101
src/FederationCLI/Utilities.php
Normal 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue