diff --git a/src/Console/CreatePermissionCommand.php b/src/Console/CreatePermissionCommand.php index a5cb2d1..3b4d467 100644 --- a/src/Console/CreatePermissionCommand.php +++ b/src/Console/CreatePermissionCommand.php @@ -4,16 +4,19 @@ namespace App\Console; use App\Service\DatabaseService; use App\Service\Traits\SelectDatabaseQuestion; +use App\Service\Traits\SelectUserQuestion; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; -#[AsCommand('app:permissions:list')] +#[AsCommand('app:permission:create')] class CreatePermissionCommand extends Command { use SelectDatabaseQuestion; + use SelectUserQuestion; public function __construct( private readonly DatabaseService $db, @@ -24,18 +27,31 @@ class CreatePermissionCommand extends Command public function configure(): void { - $this->addArgument('name', InputArgument::OPTIONAL, 'User name'); - $this->addArgument('host', InputArgument::OPTIONAL, 'User host'); + $this->addArgument('user', InputArgument::OPTIONAL, 'User name'); $this->addArgument('database', InputArgument::OPTIONAL, 'Database'); + $this->addArgument('host', InputArgument::OPTIONAL, 'User host'); } protected function execute(InputInterface $input, OutputInterface $output): int { - $dbs = $this->db->listDatabases(); + $question = $this->getHelper('question'); - $output->writeln('List of permissions for user:'); - foreach ($dbs as $db) { - $output->writeln(sprintf(' -%s', $db)); + $user = $this->getUserName($input, $output); + $host = $input->getArgument('host'); + + $permissionTypeQuestion = new ChoiceQuestion('Permission type: ', [ + 'admin' => 'Admin', + 'db_admin' => 'Database admin', + ]); + + $permissionType = $question->ask($input, $output, $permissionTypeQuestion); + if ($permissionType === 'admin') { + throw new \Exception('Not implemented'); + } else { + $db = $this->getDatabaseName($input, $output); + $this->db->grantDatabaseAdminPermission($user, $db, $host); + + $output->writeln(sprintf('Database admin permission granted to "%s" on "%s"', $user, $db)); } return Command::SUCCESS; diff --git a/src/Console/CreateUserCommand.php b/src/Console/CreateUserCommand.php index dc0da4b..b715d04 100644 --- a/src/Console/CreateUserCommand.php +++ b/src/Console/CreateUserCommand.php @@ -22,7 +22,7 @@ class CreateUserCommand extends Command public function configure(): void { - $this->addArgument('name', InputArgument::OPTIONAL, 'User name'); + $this->addArgument('user', InputArgument::OPTIONAL, 'User name'); $this->addArgument('password', InputArgument::OPTIONAL, 'User password'); $this->addArgument('host', InputArgument::OPTIONAL, 'User host'); } @@ -31,12 +31,12 @@ class CreateUserCommand extends Command { $question = $this->getHelper('question'); - $name = $input->getArgument('name'); + $user = $input->getArgument('user'); $password = $input->getArgument('password'); $host = $input->getArgument('host'); - if (!$name) { - $name = $question->ask($input, $output, new Question('User name: ')); + if (!$user) { + $user = $question->ask($input, $output, new Question('User name: ')); } if (!$password) { $passwordQuestion = new Question('User password: '); @@ -44,9 +44,9 @@ class CreateUserCommand extends Command $password = $question->ask($input, $output, $passwordQuestion); } - $this->db->createUser($name, $password, $host); + $this->db->createUser($user, $password, $host); - $output->writeln(sprintf('User "%s" successfully created', $name)); + $output->writeln(sprintf('User "%s" successfully created', $user)); return Command::SUCCESS; } diff --git a/src/Console/DeleteUserCommand.php b/src/Console/DeleteUserCommand.php index 8f2bc33..6fca6e8 100644 --- a/src/Console/DeleteUserCommand.php +++ b/src/Console/DeleteUserCommand.php @@ -3,6 +3,7 @@ namespace App\Console; use App\Service\DatabaseService; +use App\Service\Traits\SelectUserQuestion; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -14,6 +15,8 @@ use Symfony\Component\Console\Question\Question; #[AsCommand('app:user:delete')] class DeleteUserCommand extends Command { + use SelectUserQuestion; + public function __construct( private readonly DatabaseService $db, ) @@ -23,27 +26,18 @@ class DeleteUserCommand extends Command public function configure(): void { - $this->addArgument('name', InputArgument::OPTIONAL, 'User name'); + $this->addArgument('user', InputArgument::OPTIONAL, 'User name'); $this->addArgument('host', InputArgument::OPTIONAL, 'User host'); } protected function execute(InputInterface $input, OutputInterface $output): int { $host = $input->getArgument('host'); - $name = $input->getArgument('name'); + $user = $this->getUserName($input, $output); - if (!$name) { - $question = $this->getHelper('question'); - $selectQuestion = new ChoiceQuestion('User name: ', array_map( - fn($user) => $user['name'], - $this->db->listUsers()) - ); - $name = $question->ask($input, $output, $selectQuestion); - } + $this->db->deleteUser($user, $host); - $this->db->deleteUser($name, $host); - - $output->writeln(sprintf('User "%s" successfully deleted', $name)); + $output->writeln(sprintf('User "%s" successfully deleted', $user)); return Command::SUCCESS; } diff --git a/src/Console/ListPermissionsCommand.php b/src/Console/ListPermissionsCommand.php index 9b5f706..f2921d5 100644 --- a/src/Console/ListPermissionsCommand.php +++ b/src/Console/ListPermissionsCommand.php @@ -3,17 +3,19 @@ namespace App\Console; use App\Service\DatabaseService; +use App\Service\Traits\SelectUserQuestion; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Style\SymfonyStyle; #[AsCommand('app:permission:list')] class ListPermissionsCommand extends Command { + use SelectUserQuestion; + public function __construct( private readonly DatabaseService $db, ) @@ -23,7 +25,7 @@ class ListPermissionsCommand extends Command public function configure(): void { - $this->addArgument('name', InputArgument::OPTIONAL, 'User name'); + $this->addArgument('user', InputArgument::OPTIONAL, 'User name'); $this->addArgument('host', InputArgument::OPTIONAL, 'User host'); } @@ -31,24 +33,15 @@ class ListPermissionsCommand extends Command { $style = new SymfonyStyle($input, $output); - $name = $input->getArgument('name'); $host = $input->getArgument('host'); + $user = $this->getUserName($input, $output); - if (!$name) { - $question = $this->getHelper('question'); - $selectQuestion = new ChoiceQuestion('User name: ', array_map( - fn($user) => $user['name'], - $this->db->listUsers()) - ); - $name = $question->ask($input, $output, $selectQuestion); - } - - $permissions = $this->db->listPermissions($name, $host); + $permissions = $this->db->listPermissions($user, $host); $table = $style ->createTable() ->setHeaders(['Permission']) - ->setHeaderTitle(sprintf('List of users for %s@%s', $name, $host)) + ->setHeaderTitle(sprintf('List of users for %s@%s', $user, $host)) ; foreach ($permissions as $permission) { $table->addRow([$permission]); diff --git a/src/Service/DatabaseService.php b/src/Service/DatabaseService.php index 5da4a2a..7dfebbd 100644 --- a/src/Service/DatabaseService.php +++ b/src/Service/DatabaseService.php @@ -114,7 +114,7 @@ class DatabaseService public function listPermissions(string $user, ?string $host = null): array { $host ??= 'localhost'; - $results = $this->conn->query(sprintf("SHOW GRANTS FOR '%s'@'%s'", $user, $host), ); + $results = $this->conn->query(sprintf("SHOW GRANTS FOR '%s'@'%s'", $user, $host)); $permissions = []; while ($result = $results->fetch_array()) { @@ -123,4 +123,13 @@ class DatabaseService return $permissions; } + + public function grantDatabaseAdminPermission(string $user, string $db, ?string $host = null): void + { + $host ??= 'localhost'; + $result = $this->conn->query(sprintf("GRANT ALL PRIVILEGES ON `%s`.* TO '%s'@'%s'", $db, $user, $host)); + if (!$result) { + throw new Exception(sprintf('Permission grant error: %s', $this->conn->error)); + } + } } \ No newline at end of file diff --git a/src/Service/Traits/SelectDatabaseQuestion.php b/src/Service/Traits/SelectDatabaseQuestion.php index ea11421..404b1c3 100644 --- a/src/Service/Traits/SelectDatabaseQuestion.php +++ b/src/Service/Traits/SelectDatabaseQuestion.php @@ -10,13 +10,13 @@ trait SelectDatabaseQuestion { private function getDatabaseName(InputInterface $input, OutputInterface $output): string { - $question = $this->getHelper('question'); - - if (!$name = $input->getArgument('database')) { - $selectQuestion = new ChoiceQuestion('Database name: ', $this->db->listDatabases()); - $name = $question->ask($input, $output, $selectQuestion); + if (!$database = $input->getArgument('database')) { + $question = $this->getHelper('question'); + $databases = $this->db->listDatabases(); + $selectQuestion = new ChoiceQuestion('Database name: ', array_combine($databases, $databases)); + $database = $question->ask($input, $output, $selectQuestion); } - return $name; + return $database; } } \ No newline at end of file diff --git a/src/Service/Traits/SelectUserQuestion.php b/src/Service/Traits/SelectUserQuestion.php index f6e45db..287809b 100644 --- a/src/Service/Traits/SelectUserQuestion.php +++ b/src/Service/Traits/SelectUserQuestion.php @@ -10,13 +10,16 @@ trait SelectUserQuestion { private function getUserName(InputInterface $input, OutputInterface $output): string { - $question = $this->getHelper('question'); - - if (!$name = $input->getArgument('name')) { - $selectQuestion = new ChoiceQuestion('Database name: ', $this->db->listDatabases()); - $name = $question->ask($input, $output, $selectQuestion); + $user = $input->getArgument('user'); + if (!$user) { + $question = $this->getHelper('question'); + $users = array_map( + fn($user) => $user['name'], + $this->db->listUsers()); + $selectQuestion = new ChoiceQuestion('User name: ', array_combine($users, $users)); + $user = $question->ask($input, $output, $selectQuestion); } - return $name; + return $user; } } \ No newline at end of file