1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-08-07 23:03:00 +03:00

ZIP Exports: Added ID checks and testing to validator

This commit is contained in:
Dan Brown
2024-11-18 15:53:21 +00:00
parent c2c64e207f
commit e2f6e50df4
10 changed files with 130 additions and 6 deletions

View File

@@ -43,7 +43,7 @@ class ZipExportAttachment extends ZipExportModel
public static function validate(ZipValidationHelper $context, array $data): array
{
$rules = [
'id' => ['nullable', 'int'],
'id' => ['nullable', 'int', $context->uniqueIdRule('attachment')],
'name' => ['required', 'string', 'min:1'],
'link' => ['required_without:file', 'nullable', 'string'],
'file' => ['required_without:link', 'nullable', 'string', $context->fileReferenceRule()],

View File

@@ -70,7 +70,7 @@ class ZipExportBook extends ZipExportModel
public static function validate(ZipValidationHelper $context, array $data): array
{
$rules = [
'id' => ['nullable', 'int'],
'id' => ['nullable', 'int', $context->uniqueIdRule('book')],
'name' => ['required', 'string', 'min:1'],
'description_html' => ['nullable', 'string'],
'cover' => ['nullable', 'string', $context->fileReferenceRule()],

View File

@@ -59,7 +59,7 @@ class ZipExportChapter extends ZipExportModel
public static function validate(ZipValidationHelper $context, array $data): array
{
$rules = [
'id' => ['nullable', 'int'],
'id' => ['nullable', 'int', $context->uniqueIdRule('chapter')],
'name' => ['required', 'string', 'min:1'],
'description_html' => ['nullable', 'string'],
'priority' => ['nullable', 'int'],

View File

@@ -33,7 +33,7 @@ class ZipExportImage extends ZipExportModel
public static function validate(ZipValidationHelper $context, array $data): array
{
$rules = [
'id' => ['nullable', 'int'],
'id' => ['nullable', 'int', $context->uniqueIdRule('image')],
'name' => ['required', 'string', 'min:1'],
'file' => ['required', 'string', $context->fileReferenceRule()],
'type' => ['required', 'string', Rule::in(['gallery', 'drawio'])],

View File

@@ -68,7 +68,7 @@ class ZipExportPage extends ZipExportModel
public static function validate(ZipValidationHelper $context, array $data): array
{
$rules = [
'id' => ['nullable', 'int'],
'id' => ['nullable', 'int', $context->uniqueIdRule('page')],
'name' => ['required', 'string', 'min:1'],
'html' => ['nullable', 'string'],
'markdown' => ['nullable', 'string'],

View File

@@ -4,7 +4,6 @@ namespace BookStack\Exports\ZipExports;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use ZipArchive;
class ZipFileReferenceRule implements ValidationRule
{

View File

@@ -0,0 +1,26 @@
<?php
namespace BookStack\Exports\ZipExports;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class ZipUniqueIdRule implements ValidationRule
{
public function __construct(
protected ZipValidationHelper $context,
protected string $modelType,
) {
}
/**
* @inheritDoc
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if ($this->context->hasIdBeenUsed($this->modelType, $value)) {
$fail('validation.zip_unique')->translate(['attribute' => $attribute]);
}
}
}

View File

@@ -9,6 +9,13 @@ class ZipValidationHelper
{
protected Factory $validationFactory;
/**
* Local store of validated IDs (in format "<type>:<id>". Example: "book:2")
* which we can use to check uniqueness.
* @var array<string, bool>
*/
protected array $validatedIds = [];
public function __construct(
public ZipExportReader $zipReader,
) {
@@ -31,6 +38,23 @@ class ZipValidationHelper
return new ZipFileReferenceRule($this);
}
public function uniqueIdRule(string $type): ZipUniqueIdRule
{
return new ZipUniqueIdRule($this, $type);
}
public function hasIdBeenUsed(string $type, int $id): bool
{
$key = $type . ':' . $id;
if (isset($this->validatedIds[$key])) {
return true;
}
$this->validatedIds[$key] = true;
return false;
}
/**
* Validate an array of relation data arrays that are expected
* to be for the given ZipExportModel.