use BookStack\App\Model;
use BookStack\Permissions\Models\JointPermission;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
*/
class SlugHistory extends Model
{
+ use HasFactory;
+
protected $table = 'slug_history';
public function jointPermissions(): HasMany
--- /dev/null
+<?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,
+ ];
+ }
+}
namespace Tests\Entity;
+use BookStack\Entities\Models\SlugHistory;
use Tests\TestCase;
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();