|
29 | 29 | use App\Console\LnmsCommand; |
30 | 30 | use App\Facades\LibrenmsConfig; |
31 | 31 | use App\Models\User; |
| 32 | +use Illuminate\Support\Facades\Validator; |
32 | 33 | use Illuminate\Validation\Rule; |
33 | | -use LibreNMS\Authentication\LegacyAuth; |
| 34 | +use Illuminate\Validation\Rules\Password; |
| 35 | +use Illuminate\Validation\ValidationException; |
34 | 36 | use Spatie\Permission\Models\Role; |
35 | 37 | use Symfony\Component\Console\Input\InputArgument; |
36 | 38 | use Symfony\Component\Console\Input\InputOption; |
37 | 39 |
|
| 40 | +use function Laravel\Prompts\form; |
| 41 | + |
38 | 42 | class AddUserCommand extends LnmsCommand |
39 | 43 | { |
40 | 44 | protected $name = 'user:add'; |
41 | 45 |
|
42 | | - /** |
43 | | - * Create a new command instance. |
44 | | - * |
45 | | - * @return void |
46 | | - */ |
47 | 46 | public function __construct() |
48 | 47 | { |
49 | 48 | parent::__construct(); |
50 | 49 |
|
51 | 50 | $this->setDescription(__('commands.user:add.description')); |
52 | | - |
53 | | - $this->addArgument('username', InputArgument::REQUIRED); |
| 51 | + $this->addArgument('username', InputArgument::OPTIONAL); |
54 | 52 | $this->addOption('password', 'p', InputOption::VALUE_REQUIRED); |
55 | | - $this->addOption('role', 'r', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, __('commands.user:add.options.role', ['roles' => '[user, global-read, admin]']), ['user']); |
| 53 | + $this->addOption('role', 'r', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, |
| 54 | + __('commands.user:add.options.role', ['roles' => '[user, global-read, admin]']), default: ['user']); |
56 | 55 | $this->addOption('email', 'e', InputOption::VALUE_REQUIRED); |
57 | 56 | $this->addOption('full-name', 'l', InputOption::VALUE_REQUIRED); |
58 | 57 | $this->addOption('descr', 's', InputOption::VALUE_REQUIRED); |
59 | 58 | } |
60 | 59 |
|
61 | | - /** |
62 | | - * Execute the console command. |
63 | | - */ |
64 | 60 | public function handle(): int |
65 | 61 | { |
66 | | - if (LibrenmsConfig::get('auth_mechanism') != 'mysql') { |
| 62 | + if (LibrenmsConfig::get('auth_mechanism') !== 'mysql') { |
67 | 63 | $this->warn(__('commands.user:add.wrong-auth')); |
68 | 64 | } |
69 | 65 |
|
70 | | - $roles = Role::query()->pluck('name') |
71 | | - ->whenEmpty(fn () => collect(['admin', 'global-read', 'user'])); |
| 66 | + $availableRoles = Role::pluck('name')->whenEmpty(fn () => collect(['admin', 'global-read', 'user']))->all(); |
72 | 67 |
|
73 | | - $this->validate([ |
74 | | - 'username' => ['required', Rule::unique('users', 'username')->where('auth_type', 'mysql')], |
75 | | - 'email' => 'nullable|email', |
76 | | - 'role.*' => Rule::in($roles), |
77 | | - ]); |
78 | | - |
79 | | - // set get password |
| 68 | + $username = $this->argument('username'); |
80 | 69 | $password = $this->option('password'); |
81 | | - if (! $password) { |
82 | | - $password = $this->secret(__('commands.user:add.password-request')); |
| 70 | + $roles = $this->option('role'); |
| 71 | + $roles = empty($roles) ? ['user'] : $roles; |
| 72 | + $email = $this->option('email'); |
| 73 | + $fullName = $this->option('full-name'); |
| 74 | + $descr = $this->option('descr'); |
| 75 | + |
| 76 | + if ($username && $password) { |
| 77 | + // cli input method |
| 78 | + try { |
| 79 | + Validator::make(['username' => $username], ['username' => $this->usernameRules()])->validate(); |
| 80 | + Validator::make(['password' => $password], ['password' => $this->passwordRules()])->validate(); |
| 81 | + Validator::make(['roles' => $roles], |
| 82 | + ['roles' => ['required', 'array', Rule::in($availableRoles)]])->validate(); |
| 83 | + Validator::make(['email' => $email], ['email' => ['nullable', 'email']])->validate(); |
| 84 | + } catch (ValidationException $e) { |
| 85 | + $this->error($e->getMessage()); |
| 86 | + |
| 87 | + return 1; |
| 88 | + } |
| 89 | + |
| 90 | + $this->makeUser( |
| 91 | + $username, |
| 92 | + $password, |
| 93 | + $roles, |
| 94 | + $email, |
| 95 | + $fullName, |
| 96 | + $descr, |
| 97 | + ); |
| 98 | + |
| 99 | + return 0; |
83 | 100 | } |
84 | 101 |
|
| 102 | + // interactive input |
| 103 | + $data = form() |
| 104 | + ->text( |
| 105 | + label: __('commands.user:add.form.username'), |
| 106 | + default: $username ?? '', |
| 107 | + required: true, |
| 108 | + validate: $this->validatePromptInput('username', $this->usernameRules()) |
| 109 | + ) |
| 110 | + ->password( |
| 111 | + label: __('commands.user:add.form.password'), |
| 112 | + required: true, |
| 113 | + validate: $this->validatePromptInput('password', $this->passwordRules()) |
| 114 | + ) |
| 115 | + ->multiselect( |
| 116 | + label: __('commands.user:add.form.roles'), |
| 117 | + options: $availableRoles, |
| 118 | + default: $roles, |
| 119 | + required: true, |
| 120 | + ) |
| 121 | + ->text( |
| 122 | + label: __('commands.user:add.form.email'), |
| 123 | + default: $email ?? '', |
| 124 | + validate: $this->validatePromptInput('email', ['nullable', 'email']) |
| 125 | + ) |
| 126 | + ->text(__('commands.user:add.form.full-name'), default: $fullName ?? '') |
| 127 | + ->text(__('commands.user:add.form.descr'), default: $descr ?? '') |
| 128 | + ->submit(); |
| 129 | + |
| 130 | + $this->makeUser(...$data); |
| 131 | + |
| 132 | + return 0; |
| 133 | + } |
| 134 | + |
| 135 | + private function usernameRules(): array |
| 136 | + { |
| 137 | + return [ |
| 138 | + 'required', |
| 139 | + 'string', |
| 140 | + 'max:255', |
| 141 | + Rule::unique('users', 'username')->where('auth_type', 'mysql'), |
| 142 | + ]; |
| 143 | + } |
| 144 | + |
| 145 | + private function passwordRules(): array |
| 146 | + { |
| 147 | + return [ |
| 148 | + 'required', |
| 149 | + Password::defaults(), |
| 150 | + ]; |
| 151 | + } |
| 152 | + |
| 153 | + private function makeUser( |
| 154 | + string $username, |
| 155 | + string $password, |
| 156 | + array $roles, |
| 157 | + ?string $email, |
| 158 | + ?string $fullName, |
| 159 | + ?string $descr, |
| 160 | + ): void { |
85 | 161 | $user = new User([ |
86 | | - 'username' => $this->argument('username'), |
87 | | - 'descr' => $this->option('descr'), |
88 | | - 'email' => $this->option('email'), |
89 | | - 'realname' => $this->option('full-name'), |
| 162 | + 'username' => $username, |
| 163 | + 'realname' => $fullName, |
| 164 | + 'email' => $email, |
| 165 | + 'descr' => $descr, |
90 | 166 | 'auth_type' => 'mysql', |
91 | 167 | ]); |
92 | 168 |
|
93 | 169 | $user->setPassword($password); |
94 | | - $user->save(); |
95 | | - $user->assignRole($this->option('role')); |
96 | | - |
97 | | - $user->auth_id = (string) LegacyAuth::get()->getUserid($user->username) ?: $user->user_id; |
| 170 | + $user->save(); // assign roles requires a user_id |
| 171 | + $user->assignRole($roles); |
98 | 172 | $user->save(); |
99 | 173 |
|
100 | 174 | $this->info(__('commands.user:add.success', ['username' => $user->username])); |
101 | | - |
102 | | - return 0; |
103 | 175 | } |
104 | 176 | } |
0 commit comments