1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2023 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Cli\Commands; 21 22use Composer\Console\Input\InputOption; 23use Fisharebest\Webtrees\Contracts\UserInterface; 24use Fisharebest\Webtrees\DB; 25use Fisharebest\Webtrees\Services\UserService; 26use Symfony\Component\Console\Command\Command; 27use Symfony\Component\Console\Input\InputArgument; 28use Symfony\Component\Console\Input\InputInterface; 29use Symfony\Component\Console\Output\OutputInterface; 30use Symfony\Component\Console\Style\SymfonyStyle; 31 32use function bin2hex; 33use function random_bytes; 34 35class UserCreate extends Command 36{ 37 public function __construct(private readonly UserService $user_service) 38 { 39 parent::__construct(); 40 } 41 42 protected function configure(): void 43 { 44 $this 45 ->setName(name: 'user-create') 46 ->setDescription(description: 'Create a new user account') 47 ->addOption(name: 'admin', shortcut: 'a', mode: InputOption::VALUE_NONE, description: 'Make the new user an administrator') 48 ->addOption(name: 'username', shortcut: 'u', mode: InputOption::VALUE_REQUIRED, description: 'The username of the new user') 49 ->addOption(name: 'realname', shortcut: 'r', mode: InputOption::VALUE_REQUIRED, description: 'The real name of the new user') 50 ->addOption(name: 'email', shortcut: 'e', mode: InputOption::VALUE_REQUIRED, description: 'The email of the new user') 51 ->addOption(name: 'password', shortcut: 'p', mode: InputOption::VALUE_OPTIONAL, description: 'The password of the new user'); 52 } 53 54 protected function execute(InputInterface $input, OutputInterface $output): int 55 { 56 $io = new SymfonyStyle(input: $input, output: $output); 57 58 $username = $input->getOption(name: 'username'); 59 $realname = $input->getOption(name: 'realname'); 60 $email = $input->getOption(name: 'email'); 61 $password = $input->getOption(name: 'password'); 62 $admin = (bool) $input->getOption(name: 'admin'); 63 64 $missing = false; 65 66 if ($username === null) { 67 $io->error(message: 'Missing required option: --username'); 68 $missing = true; 69 } 70 71 if ($realname === null) { 72 $io->error(message: 'Missing required option: --realname'); 73 $missing = true; 74 } 75 76 if ($email === null) { 77 $io->error(message: 'Missing required option: --email'); 78 $missing = true; 79 } 80 81 if ($missing) { 82 return Command::FAILURE; 83 } 84 85 $user = $this->user_service->findByUserName(user_name: $username); 86 87 if ($user !== null) { 88 $io->error(message: 'A user with the username "' . $username . '" already exists.'); 89 90 return Command::FAILURE; 91 } 92 93 $user = $this->user_service->findByEmail(email: $email); 94 95 if ($user !== null) { 96 $io->error(message: 'A user with the email "' . $email . '" already exists'); 97 98 return Command::FAILURE; 99 } 100 101 if ($password === null) { 102 $password = bin2hex(string: random_bytes(length: 8)); 103 $io->info(message: 'Generated password: ' . $password); 104 } 105 106 $user = $this->user_service->create(user_name: $username, real_name:$realname, email: $email, password: $password); 107 $user->setPreference(setting_name: UserInterface::PREF_IS_ACCOUNT_APPROVED, setting_value: '1'); 108 $user->setPreference(setting_name: UserInterface::PREF_IS_EMAIL_VERIFIED, setting_value: '1'); 109 $io->success('User ' . $user->id() . ' created.'); 110 111 if ($admin) { 112 $user->setPreference(setting_name: UserInterface::PREF_IS_ADMINISTRATOR, setting_value: '1'); 113 $io->success(message: 'User granted administrator role.'); 114 } 115 116 DB::exec(sql: 'COMMIT'); 117 118 return Command::SUCCESS; 119 } 120} 121