Added external-auth-id option to create-admin command
- Added tests to cover. - Refactored some existing testing. - Requires password or external_auth_id to be provided. Defaults to password. - Randomly sets password to 32 digit random chars if external_auth_id provided instead. For #3222
This commit is contained in:
parent
17215431ca
commit
f83cc83877
|
@ -3,8 +3,10 @@
|
||||||
namespace BookStack\Console\Commands;
|
namespace BookStack\Console\Commands;
|
||||||
|
|
||||||
use BookStack\Auth\UserRepo;
|
use BookStack\Auth\UserRepo;
|
||||||
|
use BookStack\Exceptions\NotFoundException;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Validation\Rules\Password;
|
use Illuminate\Validation\Rules\Password;
|
||||||
use Illuminate\Validation\Rules\Unique;
|
use Illuminate\Validation\Rules\Unique;
|
||||||
use Symfony\Component\Console\Command\Command as SymfonyCommand;
|
use Symfony\Component\Console\Command\Command as SymfonyCommand;
|
||||||
|
@ -19,7 +21,8 @@ class CreateAdmin extends Command
|
||||||
protected $signature = 'bookstack:create-admin
|
protected $signature = 'bookstack:create-admin
|
||||||
{--email= : The email address for the new admin user}
|
{--email= : The email address for the new admin user}
|
||||||
{--name= : The name of the new admin user}
|
{--name= : The name of the new admin user}
|
||||||
{--password= : The password to assign to the new admin user}';
|
{--password= : The password to assign to the new admin user}
|
||||||
|
{--external-auth-id= : The external authentication system id for the new admin user (SAML2/LDAP/OIDC)}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
|
@ -42,28 +45,35 @@ class CreateAdmin extends Command
|
||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
*
|
*
|
||||||
* @throws \BookStack\Exceptions\NotFoundException
|
* @throws NotFoundException
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$details = $this->options();
|
$details = $this->snakeCaseOptions();
|
||||||
|
|
||||||
if (empty($details['email'])) {
|
if (empty($details['email'])) {
|
||||||
$details['email'] = $this->ask('Please specify an email address for the new admin user');
|
$details['email'] = $this->ask('Please specify an email address for the new admin user');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($details['name'])) {
|
if (empty($details['name'])) {
|
||||||
$details['name'] = $this->ask('Please specify a name for the new admin user');
|
$details['name'] = $this->ask('Please specify a name for the new admin user');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($details['password'])) {
|
if (empty($details['password'])) {
|
||||||
|
if (empty($details['external_auth_id'])) {
|
||||||
$details['password'] = $this->ask('Please specify a password for the new admin user (8 characters min)');
|
$details['password'] = $this->ask('Please specify a password for the new admin user (8 characters min)');
|
||||||
|
} else {
|
||||||
|
$details['password'] = Str::random(32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$validator = Validator::make($details, [
|
$validator = Validator::make($details, [
|
||||||
'email' => ['required', 'email', 'min:5', new Unique('users', 'email')],
|
'email' => ['required', 'email', 'min:5', new Unique('users', 'email')],
|
||||||
'name' => ['required', 'min:2'],
|
'name' => ['required', 'min:2'],
|
||||||
'password' => ['required', Password::default()],
|
'password' => ['required_without:external_auth_id', Password::default()],
|
||||||
|
'external_auth_id' => ['required_without:password'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
|
@ -84,4 +94,13 @@ class CreateAdmin extends Command
|
||||||
|
|
||||||
return SymfonyCommand::SUCCESS;
|
return SymfonyCommand::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function snakeCaseOptions(): array
|
||||||
|
{
|
||||||
|
$returnOpts = [];
|
||||||
|
foreach ($this->options() as $key => $value) {
|
||||||
|
$returnOpts[str_replace('-', '_', $key)] = $value;
|
||||||
|
}
|
||||||
|
return $returnOpts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Commands;
|
|
||||||
|
|
||||||
use BookStack\Auth\User;
|
|
||||||
use Tests\TestCase;
|
|
||||||
|
|
||||||
class AddAdminCommandTest extends TestCase
|
|
||||||
{
|
|
||||||
public function test_add_admin_command()
|
|
||||||
{
|
|
||||||
$exitCode = \Artisan::call('bookstack:create-admin', [
|
|
||||||
'--email' => 'admintest@example.com',
|
|
||||||
'--name' => 'Admin Test',
|
|
||||||
'--password' => 'testing-4',
|
|
||||||
]);
|
|
||||||
$this->assertTrue($exitCode === 0, 'Command executed successfully');
|
|
||||||
|
|
||||||
$this->assertDatabaseHas('users', [
|
|
||||||
'email' => 'admintest@example.com',
|
|
||||||
'name' => 'Admin Test',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertTrue(User::query()->where('email', '=', 'admintest@example.com')->first()->hasSystemRole('admin'), 'User has admin role as expected');
|
|
||||||
$this->assertTrue(\Auth::attempt(['email' => 'admintest@example.com', 'password' => 'testing-4']), 'Password stored as expected');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Commands;
|
||||||
|
|
||||||
|
use BookStack\Auth\User;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class CreateAdminCommandTest extends TestCase
|
||||||
|
{
|
||||||
|
public function test_standard_command_usage()
|
||||||
|
{
|
||||||
|
$this->artisan('bookstack:create-admin', [
|
||||||
|
'--email' => 'admintest@example.com',
|
||||||
|
'--name' => 'Admin Test',
|
||||||
|
'--password' => 'testing-4',
|
||||||
|
])->assertExitCode(0);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('users', [
|
||||||
|
'email' => 'admintest@example.com',
|
||||||
|
'name' => 'Admin Test',
|
||||||
|
]);
|
||||||
|
|
||||||
|
/** @var User $user */
|
||||||
|
$user = User::query()->where('email', '=', 'admintest@example.com')->first();
|
||||||
|
$this->assertTrue($user->hasSystemRole('admin'));
|
||||||
|
$this->assertTrue(Auth::attempt(['email' => 'admintest@example.com', 'password' => 'testing-4']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_providing_external_auth_id()
|
||||||
|
{
|
||||||
|
$this->artisan('bookstack:create-admin', [
|
||||||
|
'--email' => 'admintest@example.com',
|
||||||
|
'--name' => 'Admin Test',
|
||||||
|
'--external-auth-id' => 'xX_admin_Xx',
|
||||||
|
])->assertExitCode(0);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('users', [
|
||||||
|
'email' => 'admintest@example.com',
|
||||||
|
'name' => 'Admin Test',
|
||||||
|
'external_auth_id' => 'xX_admin_Xx',
|
||||||
|
]);
|
||||||
|
|
||||||
|
/** @var User $user */
|
||||||
|
$user = User::query()->where('email', '=', 'admintest@example.com')->first();
|
||||||
|
$this->assertNotEmpty($user->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_password_required_if_external_auth_id_not_given()
|
||||||
|
{
|
||||||
|
$this->artisan('bookstack:create-admin', [
|
||||||
|
'--email' => 'admintest@example.com',
|
||||||
|
'--name' => 'Admin Test',
|
||||||
|
])->expectsQuestion('Please specify a password for the new admin user (8 characters min)', 'hunter2000')
|
||||||
|
->assertExitCode(0);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('users', [
|
||||||
|
'email' => 'admintest@example.com',
|
||||||
|
'name' => 'Admin Test',
|
||||||
|
]);
|
||||||
|
$this->assertTrue(Auth::attempt(['email' => 'admintest@example.com', 'password' => 'hunter2000']));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue