diff --git a/app/Console/Commands/CleanupImages.php b/app/Console/Commands/CleanupImages.php index 722150197..2399e1cbb 100644 --- a/app/Console/Commands/CleanupImages.php +++ b/app/Console/Commands/CleanupImages.php @@ -49,7 +49,8 @@ class CleanupImages extends Command $dryRun = $this->option('force') ? false : true; if (!$dryRun) { - $proceed = $this->confirm("This operation is destructive and is not guaranteed to be fully accurate.\nEnsure you have a backup of your images.\nAre you sure you want to proceed?"); + $this->warn("This operation is destructive and is not guaranteed to be fully accurate.\nEnsure you have a backup of your images.\n"); + $proceed = $this->confirm("Are you sure you want to proceed?"); if (!$proceed) { return; } @@ -59,7 +60,7 @@ class CleanupImages extends Command $deleteCount = count($deleted); if ($dryRun) { - $this->comment('Dry run, No images have been deleted'); + $this->comment('Dry run, no images have been deleted'); $this->comment($deleteCount . ' images found that would have been deleted'); $this->showDeletedImages($deleted); $this->comment('Run with -f or --force to perform deletions'); diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index 1d04582c0..5458779e9 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -462,6 +462,7 @@ class ImageService Image::query()->whereIn('type', $types) ->chunk(1000, function ($images) use ($checkRevisions, &$deletedPaths, $dryRun) { + /** @var Image $image */ foreach ($images as $image) { $searchQuery = '%' . basename($image->path) . '%'; $inPage = DB::table('pages') diff --git a/tests/Commands/CleanupImagesCommandTest.php b/tests/Commands/CleanupImagesCommandTest.php new file mode 100644 index 000000000..a1a5ab985 --- /dev/null +++ b/tests/Commands/CleanupImagesCommandTest.php @@ -0,0 +1,49 @@ +entities->page(); + $image = Image::factory()->create(['uploaded_to' => $page->id]); + + $this->artisan('bookstack:cleanup-images -v') + ->expectsOutput('Dry run, no images have been deleted') + ->expectsOutput('1 images found that would have been deleted') + ->expectsOutputToContain($image->path) + ->assertExitCode(0); + + $this->assertDatabaseHas('images', ['id' => $image->id]); + } + + public function test_command_force_run() + { + $page = $this->entities->page(); + $image = Image::factory()->create(['uploaded_to' => $page->id]); + + $this->artisan('bookstack:cleanup-images --force') + ->expectsOutputToContain('This operation is destructive and is not guaranteed to be fully accurate') + ->expectsConfirmation('Are you sure you want to proceed?', 'yes') + ->expectsOutput('1 images deleted') + ->assertExitCode(0); + + $this->assertDatabaseMissing('images', ['id' => $image->id]); + } + + public function test_command_force_run_negative_confirmation() + { + $page = $this->entities->page(); + $image = Image::factory()->create(['uploaded_to' => $page->id]); + + $this->artisan('bookstack:cleanup-images --force') + ->expectsConfirmation('Are you sure you want to proceed?', 'no') + ->assertExitCode(0); + + $this->assertDatabaseHas('images', ['id' => $image->id]); + } +} diff --git a/tests/Commands/DeleteUsersCommandTest.php b/tests/Commands/DeleteUsersCommandTest.php new file mode 100644 index 000000000..4d8081b6f --- /dev/null +++ b/tests/Commands/DeleteUsersCommandTest.php @@ -0,0 +1,44 @@ +count(); + $normalUsers = $this->getNormalUsers(); + + $normalUserCount = $userCount - count($normalUsers); + $this->artisan('bookstack:delete-users') + ->expectsQuestion('This will delete all users from the system that are not "admin" or system users. Are you sure you want to continue? (Type "yes" to continue)', 'yes') + ->expectsOutputToContain("Deleted $normalUserCount of $userCount total users.") + ->assertExitCode(0); + + $this->assertDatabaseMissing('users', ['id' => $normalUsers->first()->id]); + } + + public function test_command_requires_confirmation() + { + $normalUsers = $this->getNormalUsers(); + + $this->artisan('bookstack:delete-users') + ->expectsQuestion('This will delete all users from the system that are not "admin" or system users. Are you sure you want to continue? (Type "yes" to continue)', 'no') + ->assertExitCode(0); + + $this->assertDatabaseHas('users', ['id' => $normalUsers->first()->id]); + } + + protected function getNormalUsers(): Collection + { + return User::query()->whereNull('system_name') + ->get() + ->filter(function (User $user) { + return !$user->hasSystemRole('admin'); + }); + } +} diff --git a/tests/Commands/RegenerateSearchCommandTest.php b/tests/Commands/RegenerateSearchCommandTest.php new file mode 100644 index 000000000..418327ebe --- /dev/null +++ b/tests/Commands/RegenerateSearchCommandTest.php @@ -0,0 +1,29 @@ +entities->page(); + SearchTerm::truncate(); + + $this->assertDatabaseMissing('search_terms', ['entity_id' => $page->id]); + + $this->artisan('bookstack:regenerate-search') + ->expectsOutput('Search index regenerated!') + ->assertExitCode(0); + + $this->assertDatabaseHas('search_terms', [ + 'entity_type' => 'page', + 'entity_id' => $page->id + ]); + DB::beginTransaction(); + } +} diff --git a/tests/Commands/UpgradeDatabaseEncodingCommandTest.php b/tests/Commands/UpgradeDatabaseEncodingCommandTest.php new file mode 100644 index 000000000..b7fe4eb6c --- /dev/null +++ b/tests/Commands/UpgradeDatabaseEncodingCommandTest.php @@ -0,0 +1,15 @@ +artisan('bookstack:db-utf8mb4') + ->expectsOutputToContain('ALTER DATABASE') + ->expectsOutputToContain('ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'); + } +}