]> BookStack Code Mirror - system-cli/blobdiff - tests/Commands/RestoreCommandTest.php
Added path check/validation for provided restore file path
[system-cli] / tests / Commands / RestoreCommandTest.php
index a8ff2b45a78e142f2d3843b30b859189bd8fc710..17b9dd50a27dbce34eaefecad875c96456c2ea92 100644 (file)
@@ -4,6 +4,7 @@ namespace Tests\Commands;
 
 use mysqli;
 use Tests\TestCase;
+use ZipArchive;
 
 class RestoreCommandTest extends TestCase
 {
@@ -16,8 +17,8 @@ class RestoreCommandTest extends TestCase
         $result = $mysql->query('SHOW TABLES LIKE \'zz_testing\';');
         $this->assertEquals(0, mysqli_num_rows($result));
 
-        $zipFile = $this->buildZip(function (\ZipArchive $zip) {
-            $zip->addFromString('.env', "APP_KEY=abc123\nAPP_URL=https://example.com");
+        $zipFile = $this->buildZip(function (ZipArchive $zip) {
+            $zip->addFromString('.env', "APP_KEY=abc123\nAPP_URL=https://restore.example.com");
             $zip->addFromString('public/uploads/test.txt', 'hello-public-uploads');
             $zip->addFromString('storage/uploads/test.txt', 'hello-storage-uploads');
             $zip->addFromString('themes/test.txt', 'hello-themes');
@@ -29,9 +30,7 @@ class RestoreCommandTest extends TestCase
 
         $result = $this->runCommand('restore', [
             'backup-zip' => $zipFile,
-        ], [
-            'yes', '1'
-        ]);
+        ], ['yes', '1']); // This restore uses the existing (Non-backup) APP_URL
 
         $result->dumpError();
         $result->assertSuccessfulExit();
@@ -41,6 +40,7 @@ class RestoreCommandTest extends TestCase
         $result->assertStdoutContains('✔ Private File Uploads');
         $result->assertStdoutContains('✔ Database Dump');
         $result->assertStdoutContains('Restore operation complete!');
+        $result->assertStdoutContains('App URL change made, updating database with URL change');
 
         $result = $mysql->query('SELECT * FROM zz_testing where names = \'barry\';');
         $this->assertEquals(1, mysqli_num_rows($result));
@@ -51,13 +51,42 @@ class RestoreCommandTest extends TestCase
         $this->assertStringEqualsFile('/var/www/bookstack-restore/storage/uploads/test.txt', 'hello-storage-uploads');
         $this->assertStringEqualsFile('/var/www/bookstack-restore/themes/test.txt', 'hello-themes');
 
+        $env = file_get_contents('/var/www/bookstack-restore/.env');
+        $this->assertStringContainsString('APP_KEY=abc123', $env);
+        $this->assertStringNotContainsString('APP_URL=https://restore.example.com', $env);
+        $this->assertStringContainsString('APP_URL="https://example.com"', $env);
+
         $mysql->query("DROP TABLE zz_testing;");
         exec('rm -rf /var/www/bookstack-restore');
     }
 
+    public function test_restore_using_backup_env_url()
+    {
+        $zipFile = $this->buildZip(function (ZipArchive $zip) {
+            $zip->addFromString('.env', "APP_KEY=abc123\nAPP_URL=https://restore.example.com");
+        });
+
+        exec('cp -r /var/www/bookstack /var/www/bookstack-restore-backup-env');
+        chdir('/var/www/bookstack-restore-backup-env');
+
+        $result = $this->runCommand('restore', [
+            'backup-zip' => $zipFile,
+        ], ['yes', '0']); // This restore uses the old (Backup) APP_URL
+
+        $result->assertSuccessfulExit();
+        $result->assertStdoutContains('✔ .env Config File');
+        $result->assertStdoutContains('Restore operation complete!');
+
+        $env = file_get_contents('/var/www/bookstack-restore-backup-env/.env');
+        $this->assertStringContainsString('APP_KEY=abc123', $env);
+        $this->assertStringContainsString('APP_URL="https://restore.example.com"', $env);
+
+        exec('rm -rf /var/www/bookstack-restore-backup-env');
+    }
+
     public function test_command_fails_on_zip_with_no_expected_contents()
     {
-        $zipFile = $this->buildZip(function (\ZipArchive $zip) {
+        $zipFile = $this->buildZip(function (ZipArchive $zip) {
             $zip->addFromString('spaghetti', "Hello world!");
         });
 
@@ -73,7 +102,7 @@ class RestoreCommandTest extends TestCase
 
     public function test_limited_restore_using_app_directory_option()
     {
-        $zipFile = $this->buildZip(function (\ZipArchive $zip) {
+        $zipFile = $this->buildZip(function (ZipArchive $zip) {
             $zip->addFromString('db.sql', "CREATE TABLE zz_testing (names varchar(255));");
             $zip->addFromString('themes/hello.txt', "limited restore test!");
         });
@@ -98,11 +127,65 @@ class RestoreCommandTest extends TestCase
         $mysql->query("DROP TABLE zz_testing;");
     }
 
+    public function test_restore_with_symlinked_content_folders()
+    {
+        $zipFile = $this->buildZip(function (ZipArchive $zip) {
+            $zip->addFromString('.env', "APP_KEY=abc123\nAPP_URL=https://example.com");
+            $zip->addFromString('public/uploads/test.txt', 'hello-public-uploads');
+            $zip->addFromString('storage/uploads/test.txt', 'hello-storage-uploads');
+            $zip->addFromString('themes/test.txt', 'hello-themes');
+        });
+
+        exec('cp -r /var/www/bookstack /var/www/bookstack-symlink-restore');
+        chdir('/var/www/bookstack-symlink-restore');
+        mkdir('/symlinks');
+
+        $symlinkPaths = ['public/uploads', 'storage/uploads', '.env', 'themes'];
+        foreach ($symlinkPaths as $path) {
+            $targetFile = str_replace('/', '-', $path);
+            $code = 0;
+            $output = null;
+            exec("mv /var/www/bookstack-symlink-restore/{$path} /symlinks/{$targetFile}", $output, $code);
+            exec("ln -s /symlinks/{$targetFile} /var/www/bookstack-symlink-restore/{$path}", $output, $code);
+            if ($code !== 0) {
+                $this->fail("Error when setting up symlinks");
+            }
+        }
+
+        $result = $this->runCommand('restore', [
+            'backup-zip' => $zipFile,
+        ], ['yes', '1']);
+
+        $result->assertSuccessfulExit();
+
+        $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/public/uploads/test.txt', 'hello-public-uploads');
+        $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/storage/uploads/test.txt', 'hello-storage-uploads');
+        $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/themes/test.txt', 'hello-themes');
+
+        $this->resetCurrentDirectory();
+        exec('rm -rf /var/www/bookstack-symlink-restore');
+        exec('rm -rf /symlinks');
+    }
+
+    public function test_restore_with_invalid_zip_path_shows_warning()
+    {
+        chdir('/var/www/bookstack');
+
+        $result = $this->runCommand('restore', [
+            'backup-zip' => '/cats/dogs.zip',
+            '--app-directory' => '/var/www/bookstack',
+        ]);
+
+        $result->assertStderrContains("Could not find ZIP file for restoration at provided path [/cats/dogs.zip].");
+    }
+
     protected function buildZip(callable $builder): string
     {
         $zipFile = tempnam(sys_get_temp_dir(), 'cli-test');
-        $testZip = new \ZipArchive('');
-        $testZip->open($zipFile);
+        unlink($zipFile);
+
+        $testZip = new ZipArchive();
+        $testZip->open($zipFile, ZipArchive::CREATE);
         $builder($testZip);
         $testZip->close();