]> BookStack Code Mirror - bookstack/commitdiff
Slugs: Added test to cover history lookup permission usage 5913/head
authorDan Brown <redacted>
Mon, 24 Nov 2025 20:04:55 +0000 (20:04 +0000)
committerDan Brown <redacted>
Mon, 24 Nov 2025 20:04:55 +0000 (20:04 +0000)
app/Entities/Models/SlugHistory.php
database/factories/Entities/Models/SlugHistoryFactory.php [new file with mode: 0644]
tests/Entity/SlugTest.php

index 2731fe7495b04ca4a22dc2090ba4d99e31cfdd62..4041cedd9594ef53219840072e9936c870dbb14e 100644 (file)
@@ -4,6 +4,7 @@ namespace BookStack\Entities\Models;
 
 use BookStack\App\Model;
 use BookStack\Permissions\Models\JointPermission;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 
 /**
@@ -15,6 +16,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
  */
 class SlugHistory extends Model
 {
+    use HasFactory;
+
     protected $table = 'slug_history';
 
     public function jointPermissions(): HasMany
diff --git a/database/factories/Entities/Models/SlugHistoryFactory.php b/database/factories/Entities/Models/SlugHistoryFactory.php
new file mode 100644 (file)
index 0000000..c8c57e0
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+
+namespace Database\Factories\Entities\Models;
+
+use BookStack\Entities\Models\Book;
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+/**
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\BookStack\Entities\Models\SlugHistory>
+ */
+class SlugHistoryFactory extends Factory
+{
+    protected $model = \BookStack\Entities\Models\SlugHistory::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array<string, mixed>
+     */
+    public function definition(): array
+    {
+        return [
+            'sluggable_id' => Book::factory(),
+            'sluggable_type' => 'book',
+            'slug' => $this->faker->slug(),
+            'parent_slug' => null,
+        ];
+    }
+}
index e8565d00f13980216e1e4d6da86529b02e629558..51cf34e5dfec6ffb895479bdbc61ca60750348ab 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace Tests\Entity;
 
+use BookStack\Entities\Models\SlugHistory;
 use Tests\TestCase;
 
 class SlugTest extends TestCase
@@ -111,6 +112,27 @@ class SlugTest extends TestCase
             ->assertRedirect("/books/super-test-book/chapter/{$chapter->slug}");
     }
 
+    public function test_slug_lookup_controlled_by_permissions()
+    {
+        $editor = $this->users->editor();
+        $pageA = $this->entities->page();
+        $pageB = $this->entities->page();
+
+        SlugHistory::factory()->create(['sluggable_id' => $pageA->id, 'sluggable_type' => 'page', 'slug' => 'monkey', 'parent_slug' => 'animals', 'created_at' => now()]);
+        SlugHistory::factory()->create(['sluggable_id' => $pageB->id, 'sluggable_type' => 'page', 'slug' => 'monkey', 'parent_slug' => 'animals', 'created_at' => now()->subDay()]);
+
+        // Defaults to latest where visible
+        $this->actingAs($editor)->get("/books/animals/page/monkey")->assertRedirect($pageA->getUrl());
+
+        $this->permissions->disableEntityInheritedPermissions($pageA);
+
+        // Falls back to other entry where the latest is not visible
+        $this->actingAs($editor)->get("/books/animals/page/monkey")->assertRedirect($pageB->getUrl());
+
+        // Original still accessible where permissions allow
+        $this->asAdmin()->get("/books/animals/page/monkey")->assertRedirect($pageA->getUrl());
+    }
+
     public function test_slugs_recorded_in_history_on_page_update()
     {
         $page = $this->entities->page();