Skip to content
Snippets Groups Projects
command.php 21.4 KiB
Newer Older
root's avatar
root committed
#!/usr/bin/php
<?php
root's avatar
root committed
require_once './Console/CommandLine.php';
require_once './Console/CommandLine/Option.php';
require_once './Console/CommandLine/Command.php';

require_once __DIR__.'/../Config.php';
use SmartData\Config\Config_V1_1 as Config;
root's avatar
root committed

$parser = new Console_CommandLine(array(
    'description' => 'description description description description.',
    'version'     => '1.0.0',
    'add_version_option' => false,
    'force_options_defaults' => true,
));


/**
 * Create Command
 */
root's avatar
root committed
$create_cmd = $parser->addCommand('create', array('description' => 'create a new domain or user, or..', 'subcommand_required' => true));
root's avatar
root committed
$create_domain_cmd = $create_cmd->addCommand('domain');
$create_domain_cmd->addArgument('domain', array('description' => '', 'help_name' => 'DOMAIN'));
$create_domain_cmd->addOption('type', array('description'     => '(optional) versions to be created [default=both]',
                                            'short_name'      => '-t',
                                            'long_name'       => '--type',
                                            'help_name'       => 'TYPE',
                                            'default'         => 'both',
                                            'choices'         => array('si', 'digital', 'both'),
                                            'add_list_option' => true));
root's avatar
root committed
$create_domain_cmd->addOption('cert', array('description'     => '(optional) certificate name (without extension)',
                                            'short_name'      => '-c',
                                            'long_name'       => '--cert',
                                            'help_name'       => 'CERTIFICATE',
                                            'default'         => ''));

$create_domain_cmd->addOption('descr', array('description'     => '(optional) description of the domain',
                                            'short_name'      => '-d',
                                            'long_name'       => '--descr',
                                            'help_name'       => 'DESCRIPTION',
                                            'default'         => ''));

$create_user_cmd = $create_cmd->addCommand('user');
$create_user_cmd->addArgument('name', array('description' => 'user name for login', 'help_name' => 'DOMAIN'));

$create_user_cmd->addOption('domain', array('description'     => '(optional) domain in which user can manipulate smartdata',
                                            'short_name'      => '-d',
                                            'long_name'       => '--domain',
                                            'help_name'       => 'DOMAIN',
                                            'default'         => ''));
$create_user_cmd->addOption('password', array('description'     => '(required) password for authentication',
                                            'short_name'      => '-p',
                                            'long_name'       => '--password',
                                            'help_name'       => 'PASSWORD',
                                            'default'         => ''));
root's avatar
root committed

/**
 * Delete Command
 */
$delete_cmd = $parser->addCommand('delete', array('description' => 'delete a domain, or..', 'subcommand_required' => true));
$delete_domain_cmd = $delete_cmd->addCommand('domain');
$delete_domain_cmd->addArgument('domain', array('description' => '', 'help_name' => 'DOMAIN'));


/**
 * List Command
 */
$list_cmd = $parser->addCommand('list', array('description' => 'list domains, or..', 'subcommand_required' => true));
$list_domain_cmd = $list_cmd->addCommand('domains');
$list_domain_cmd->addOption('follow', array('short_name' => '-f',
                                            'long_name'  => '--follow',
                                            'action'     => 'StoreTrue'));

/**
 * Delete Command
 */
$clear_cmd = $parser->addCommand('clear', array('description' => 'clear a domain', 'subcommand_required' => true));
$clear_domain_cmd = $clear_cmd->addCommand('domain');
$clear_domain_cmd->addArgument('domain', array('description' => '', 'help_name' => 'DOMAIN'));


/**
 * Set Command
 */
$set_cmd = $parser->addCommand('set', array('description' => 'set configuration', 'subcommand_required' => true));
$set_cmd->addArgument('domain', array('description' => '', 'help_name' => 'DOMAIN'));
$set_cmd->addArgument('level', array('description' => '', 'help_name' => 'LEVEL'));

class Maintenance
{
    public function __construct(){}

    private static function _create_domain(string $name, string $type)
    {
        $ddl = file_get_contents('sql/domain.sql', FILE_TEXT);
        $ret = false;

        $_ddl = str_replace(":type", $type, $ddl);
        $_ddl = str_replace(":name", $name.'_'.$type, $_ddl);
        try {
            $session = self::_cassandraConnect();
            $stmt = $session->prepare($_ddl);
            $session->execute($stmt);
            $ret = true;
        } catch (Cassandra\Exception\AlreadyExistsException $e) {
            echo "The {$name} domain already exists.\n";
        } catch (\Exception $e) {
            die ($e);
        } finally {
            if (isset($session))
                $session->close();
        }
        return $ret;
    }

root's avatar
root committed
    public static function create_domain(string $name, string $type, string $cert, string $descr) {
root's avatar
root committed
        if(!self::is_valid_name($name))
root's avatar
root committed
             die ("Invalid name");
root's avatar
root committed

        self::_create_domain($name, 'v1_1_si');
root's avatar
root committed
        self::_create_domain($name, 'v1_1_si_blob');
root's avatar
root committed
        self::_create_domain($name, 'v1_1_digital');
        self::_create_domain($name, 'v1_2_si');
root's avatar
root committed
        self::_create_domain($name, 'v1_2_si_blob');
root's avatar
root committed
        self::_create_domain($name, 'v1_2_digital');
root's avatar
root committed
        self::create_user($name, $cert, $descr);
root's avatar
root committed
        self::create_counter($name);
    }

root's avatar
root committed
    public static function create_cassandra_user(string $name, string $domain, string $pwd) {
        try {
            $perms = array('SELECT','ALTER','DROP','MODIFY','AUTHORIZE');
            $crt = "CREATE ROLE :name WITH LOGIN = true AND PASSWORD = ':pwd'";
            $crt = str_replace(":name", $name, $crt);
            $crt = str_replace(":pwd", $pwd, $crt);
            $session = self::_cassandraConnect();
            $session->execute($session->prepare($crt));
            $ddl1 = 'GRANT :perm ON smartdata_v1.:domain_v1_1_si to :name;';
root's avatar
root committed
            $ddl2 = 'GRANT :perm ON smartdata_v1.:domain_v1_1_si_blob to :name;';
            $ddl3 = 'GRANT :perm ON smartdata_v1.:domain_v1_1_digital to :name;';
            $ddl4 = 'GRANT :perm ON smartdata_v1.:domain_v1_2_si to :name;';
            $ddl5 = 'GRANT :perm ON smartdata_v1.:domain_v1_2_si_blob to :name;';
            $ddl6 = 'GRANT :perm ON smartdata_v1.:domain_v1_2_digital to :name;';
root's avatar
root committed
            foreach ($perms as $prm) {
                $c1 = str_replace(':perm', $prm, $ddl1);
                $c1 = str_replace(':domain', $domain, $c1);
                $c1 = str_replace(':name', $name, $c1);
root's avatar
root committed

root's avatar
root committed
                $c2 = str_replace(':perm', $prm, $ddl2);
                $c2 = str_replace(':domain', $domain, $c2);
                $c2 = str_replace(':name', $name, $c2);
root's avatar
root committed

root's avatar
root committed
                $c3 = str_replace(':perm', $prm, $ddl3);
                $c3 = str_replace(':domain', $domain, $c3);
                $c3 = str_replace(':name', $name, $c3);
root's avatar
root committed

root's avatar
root committed
                $c4 = str_replace(':perm', $prm, $ddl4);
                $c4 = str_replace(':domain', $domain, $c4);
                $c4 = str_replace(':name', $name, $c4);
root's avatar
root committed

                $c5 = str_replace(':perm', $prm, $ddl5);
                $c5 = str_replace(':domain', $domain, $c5);
                $c5 = str_replace(':name', $name, $c5);

                $c6 = str_replace(':perm', $prm, $ddl6);
                $c6 = str_replace(':domain', $domain, $c6);
                $c6 = str_replace(':name', $name, $c6);

root's avatar
root committed
                $session->execute($session->prepare($c1));
                $session->execute($session->prepare($c2));
                $session->execute($session->prepare($c3));
                $session->execute($session->prepare($c4));
root's avatar
root committed
                $session->execute($session->prepare($c5));
                $session->execute($session->prepare($c6));
           }
           return true;
           
root's avatar
root committed
	} catch (\Exceptions $ex) {
		echo  "Error creating user.";
                var_dump($ex);
                return false;
	}
    }


root's avatar
root committed
    private static function create_counter(string $name) {
        $dml = "INSERT INTO counters VALUES (:name, 0);";
        try {
            $conn = self::_mysqlConnect();
            $stmt = $conn->prepare($dml);
            $stmt->execute(array(':name' => $name));
        } catch (\Exception $e) {
            die ($e);
        } finally {
            $conn = null;
        }
    }

root's avatar
root committed
    private static function create_user(string $name, string $cert, string $descr) {
        $dml = "INSERT INTO clients (certificate, name, domain, level, enable) VALUES (:cert, :name, :domain, 'rw', 1);";
        try {
            $conn = self::_mysqlConnect();
            $stmt = $conn->prepare($dml);
            $stmt->execute(array(':name' => $descr, ':cert' => $cert, ':domain' => $name));
        } catch (\Exception $e) {
            die ($e);
        } finally {
            $conn = null;
        }
    }


root's avatar
root committed
    public static function delete_domain(string $name) {
        if(!self::is_valid_name($name))
            die ("Invalid name");

        $ddl1 = 'DROP TABLE IF EXISTS :name_v1_1_si;';
        $ddl2 = 'DROP TABLE IF EXISTS :name_v1_1_digital;';
        $ddl3 = 'DROP TABLE IF EXISTS :name_v1_2_si;';
        $ddl4 = 'DROP TABLE IF EXISTS :name_v1_2_digital;';
        $ddl1 = str_replace(":name", $name, $ddl1);
        $ddl2 = str_replace(":name", $name, $ddl2);
        $ddl3 = str_replace(":name", $name, $ddl3);
        $ddl4 = str_replace(":name", $name, $ddl4);

        do {
            $r = strtoupper(readline("The [{$name}] domain will be deleted. Are you sure (Y/N)? "));
            if($r === 'N' | $r === 'n')
                return;
            else
                break;
        } while (true);

        try {
            $session = self::_cassandraConnect();
            $session->execute($session->prepare($ddl1));
            $session->execute($session->prepare($ddl2));
            $session->execute($session->prepare($ddl3));
            $session->execute($session->prepare($ddl4));
            self::delete_counter($name);
        } catch (\Exception $e){
            die ($e);
        } finally {
            if (isset($session))
                $session->close();
        }
    }

    public static function set_public(string $name) {
        if(!self::is_valid_name($name))
            die ("Invalid name");

        $ddl1 = 'GRANT SELECT ON :name_v1_1_si TO public;';
        $ddl2 = 'GRANT SELECT ON :name_v1_1_digital TO public;';
        $ddl3 = 'GRANT SELECT ON :name_v1_2_si TO public;';
        $ddl4 = 'GRANT SELECT ON :name_v1_2_digital TO public;';
        $ddl1 = str_replace(":name", $name, $ddl1);
        $ddl2 = str_replace(":name", $name, $ddl2);
        $ddl3 = str_replace(":name", $name, $ddl3);
        $ddl4 = str_replace(":name", $name, $ddl4);

        do {
            $r = strtoupper(readline("The [{$name}] domain will became public. Are you sure (Y/N)? "));
            if($r === 'N' | $r === 'n')
                return;
            else
                break;
        } while (true);

        try {
            $session = self::_cassandraConnect();
            $session->execute($session->prepare($ddl1));
            $session->execute($session->prepare($ddl2));
            $session->execute($session->prepare($ddl3));
            $session->execute($session->prepare($ddl4));
            self::delete_counter($name);
        } catch (\Exception $e){
            die ($e);
        } finally {
            if (isset($session))
                $session->close();
        }
    }

    public static function set_private(string $name) {
        if(!self::is_valid_name($name))
            die ("Invalid name");

        $ddl1 = 'REVOKE SELECT ON :name_v1_1_si FROM public;';
        $ddl2 = 'REVOKE SELECT ON :name_v1_1_digital FROM public;';
        $ddl3 = 'REVOKE SELECT ON :name_v1_2_si FROM public;';
        $ddl4 = 'REVOKE SELECT ON :name_v1_2_digital FROM public;';
        $ddl1 = str_replace(":name", $name, $ddl1);
        $ddl2 = str_replace(":name", $name, $ddl2);
        $ddl3 = str_replace(":name", $name, $ddl3);
        $ddl4 = str_replace(":name", $name, $ddl4);

        do {
            $r = strtoupper(readline("The [{$name}] domain will became private. Are you sure (Y/N)? "));
            if($r === 'N' | $r === 'n')
                return;
            else
                break;
        } while (true);

        try {
            $session = self::_cassandraConnect();
            $session->execute($session->prepare($ddl1));
            $session->execute($session->prepare($ddl2));
            $session->execute($session->prepare($ddl3));
            $session->execute($session->prepare($ddl4));
            self::delete_counter($name);
        } catch (\Exception $e){
            die ($e);
        } finally {
            if (isset($session))
                $session->close();
        }
    }

    private static function delete_counter(string $name) {
        $dml = "DELETE FROM counters WHERE domain = :name;";
        try {
            $conn = self::_mysqlConnect();
            $stmt = $conn->prepare($dml);
            $stmt->execute(array(':name' => $name));
        } catch (\Exception $e) {
            die ($e);
        } finally {
            $conn = null;
        }
    }

    private static function reset_counter(string $name) {
        $dml = "UPDATE counters SET count = 0 WHERE domain = :name;";
        try {
            $conn = self::_mysqlConnect();
            $stmt = $conn->prepare($dml);
            $stmt->execute(array(':name' => $name));
        } catch (\Exception $e) {
            die ($e);
        } finally {
            $conn = null;
        }
    }

    public static function list_domains($follow = false) {
        try {
            $conn = self::_mysqlConnect();
            $sth = $conn->prepare('SELECT domain as "Domain", max(updated_at) as "Last Update" FROM series GROUP BY domain;');
            do {
                $sth->execute();
                $result = $sth->fetchAll(PDO::FETCH_ASSOC);

                $table = self::table($result);

                if($follow) system('clear');
                echo $table;
                if($follow) sleep(1);

            } while($follow);
        } catch (\Exception $e) {
            die ($e);
        } finally {
            $conn = null;
        }
    }

    public static function clear_domain(string $name) {
        if(!self::is_valid_name($name))
            die ("Invalid name");

        $ddl1 = 'TRUNCATE TABLE :name;';
        $ddl2 = 'TRUNCATE TABLE :name_dig;';
        $ddl1 = str_replace(":name", $name, $ddl1);
        $ddl2 = str_replace(":name", $name, $ddl2);

        do {
            $r = strtoupper(readline("The [{$name}] domain will be cleaned. Are you sure (Y/N)? "));
            if($r === 'N' | $r === 'n')
                return;
            else
                break;
        } while (true);

        try {
            $session = self::_cassandraConnect();
            $stmt1 = $session->prepare($ddl1);
            $stmt2 = $session->prepare($ddl2);
            $session->execute($stmt1);
            $session->execute($stmt2);
            self::reset_counter($name);
        } catch (\Exception $e){
            die ($e);
        } finally {
            if (isset($session))
                $session->close();
        }
    }

    private static function is_valid_name($name) : bool {
        return preg_match('/^[a-zA-Z_][a-zA-Z0-9_]{3,39}$/', $name) ? true : false;
    }

    private static function table($data) {
        // Find longest string in each column
        $columns = [];
        foreach ($data as $row_key => $row) {
            foreach ($row as $cell_key => $cell) {
                $length = strlen($cell);
                if (empty($columns[$cell_key]) || $columns[$cell_key] < $length) {
                    $columns[$cell_key] = $length;
                }
            }
        }

        // Output table, padding columns
        $line = '+';
        foreach ($data[0] as $cell_key => $cell)
            $line .= str_pad('', $columns[$cell_key]+2, '-').'+';
        $line .= PHP_EOL;

        $table = $line;

        foreach ($data[0] as $cell_key => $cell)
            $table .= '| '.str_pad($cell_key, $columns[$cell_key]+1);
        $table .= '|'.PHP_EOL.$line;

        foreach ($data as $row_key => $row) {
            foreach ($row as $cell_key => $cell)
                $table .= '| '.str_pad($cell, $columns[$cell_key]+1);
            $table .= '|'.PHP_EOL;
        }
        $table .= $line;
        return $table;
    }

    private static function _mysqlConnect(string $servername=Config::MYSQL_SEVERNAME, int $port=Config::MYSQL_PORT, string $dbname=Config::MYSQL_DBNAME, string $username=Config::MYSQL_SUPERUSER, string $password=Config::MYSQL_SUPERPASS) : \PDO {
        $conn = new \PDO("mysql:host=$servername;port=$port;dbname=$dbname", $username, $password);
        // set the PDO error mode to exception
        $conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

        return $conn;
    }

    // Open a connection with Cassandra database
    private static function _cassandraConnect(string $servername=Config::CASSANDRA_SERVERNAME, int $port=Config::CASSANDRA_PORT,
                                                string $username=Config::CASSANDRA_SUPERUSER,    string $password=Config::CASSANDRA_SUPERPASS,
                                                string $keyspace=Config::CASSANDRA_KEYSPACE) : \Cassandra\DefaultSession {

        $cluster = \Cassandra::cluster()->withContactPoints($servername)
                                        ->withPort($port)
                                        ->withCredentials($username, $password)
                                        //->withDefaultPageSize(200)
                                        ->build();
        $session = $cluster->connect($keyspace);
        return $session;
    }

}

try {
    $result = $parser->parse();

    if($result->command_name){
        switch ($result->command_name) {
            case 'create':
		if($result->command->command_name){
                    switch ($result->command->command_name) {
                        case 'domain':
                            $domain = $result->command->command->args['domain'];
                            $type = $result->command->command->options['type'];
root's avatar
root committed
                            $cert_file = $result->command->command->options['cert'];
                            $domain_descr = $result->command->command->options['descr'];
                            Maintenance::create_domain($domain, $type, $cert_file, $domain_descr);
                        break;

                        case 'user':
                            $name = $result->command->command->args['name'];
                            $domain = $result->command->command->options['domain'];
                            $pwd = $result->command->command->options['password'];
                            if (Maintenance::create_cassandra_user($name, $domain, $pwd)) {
                                echo "\nUser ".$name." created on domain ".$domain.".\n\n";
                            } else {
                                echo "\nAn error occured while creating user.\n\n";
                            }
root's avatar
root committed
                        break;

                        default:
                        break;
                    }
                }
            break;
            case 'delete':
                if($result->command->command_name){
                    switch ($result->command->command_name) {
                        case 'domain': Maintenance::delete_domain($result->command->command->args['domain']);
                            break;
                        default:
                            break;
                    }
                }
            break;

            case 'list':
                if($result->command->command_name){
                    switch ($result->command->command_name) {
                        case 'domains':
                            Maintenance::list_domains((bool)$result->command->command->options['follow']);
                        break;

                        default:
                            break;
                    }
                }
            break;

            case 'clear':
                if($result->command->command_name){
                    switch ($result->command->command_name) {
                        case 'domain': Maintenance::clear_domain($result->command->command->args['domain']);
                            break;
                        default:
                            break;
                    }
                }
            break;

            case 'set':
                $domain = $result->command->args['domain'] ?? null;
                $level = $result->command->args['level'] ?? null;

                if($domain != null){
                    switch ($level) {
                        case 'public': Maintenance::set_public($domain);
                            break;
                        case 'private': Maintenance::set_private($domain);
                            break;
                        default:
                            break;
                    }
                }
            break;

            default:
            break;
        }
    } else {
        echo $parser->displayUsage(1);
    }
} catch (Exception $exc) {
    $parser->displayError($exc->getMessage());
root's avatar
root committed
}