Skip to content

Commit 7290a34

Browse files
added validation enable check for every db methods
1 parent 89647af commit 7290a34

2 files changed

Lines changed: 181 additions & 39 deletions

File tree

src/Database/Database.php

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4432,15 +4432,17 @@ public function createDocument(string $collection, Document $document): Document
44324432
}
44334433
}
44344434

4435-
$structure = new Structure(
4436-
$collection,
4437-
$this->adapter->getIdAttributeType(),
4438-
$this->adapter->getMinDateTime(),
4439-
$this->adapter->getMaxDateTime(),
4440-
$this->adapter->getSupportForAttributes()
4441-
);
4442-
if (!$structure->isValid($document)) {
4443-
throw new StructureException($structure->getDescription());
4435+
if ($this->validate) {
4436+
$structure = new Structure(
4437+
$collection,
4438+
$this->adapter->getIdAttributeType(),
4439+
$this->adapter->getMinDateTime(),
4440+
$this->adapter->getMaxDateTime(),
4441+
$this->adapter->getSupportForAttributes()
4442+
);
4443+
if (!$structure->isValid($document)) {
4444+
throw new StructureException($structure->getDescription());
4445+
}
44444446
}
44454447

44464448
$document = $this->adapter->castingBefore($collection, $document);
@@ -5096,16 +5098,18 @@ public function updateDocument(string $collection, string $id, Document $documen
50965098

50975099
$document = $this->encode($collection, $document);
50985100

5099-
$structureValidator = new Structure(
5100-
$collection,
5101-
$this->adapter->getIdAttributeType(),
5102-
$this->adapter->getMinDateTime(),
5103-
$this->adapter->getMaxDateTime(),
5104-
$this->adapter->getSupportForAttributes(),
5105-
$old
5106-
);
5107-
if (!$structureValidator->isValid($document)) { // Make sure updated structure still apply collection rules (if any)
5108-
throw new StructureException($structureValidator->getDescription());
5101+
if ($this->validate) {
5102+
$structureValidator = new Structure(
5103+
$collection,
5104+
$this->adapter->getIdAttributeType(),
5105+
$this->adapter->getMinDateTime(),
5106+
$this->adapter->getMaxDateTime(),
5107+
$this->adapter->getSupportForAttributes(),
5108+
$old
5109+
);
5110+
if (!$structureValidator->isValid($document)) { // Make sure updated structure still apply collection rules (if any)
5111+
throw new StructureException($structureValidator->getDescription());
5112+
}
51095113
}
51105114

51115115
if ($this->resolveRelationships) {
@@ -5252,17 +5256,19 @@ public function updateDocuments(
52525256
applyDefaults: false
52535257
);
52545258

5255-
$validator = new PartialStructure(
5256-
$collection,
5257-
$this->adapter->getIdAttributeType(),
5258-
$this->adapter->getMinDateTime(),
5259-
$this->adapter->getMaxDateTime(),
5260-
$this->adapter->getSupportForAttributes(),
5261-
null // No old document available in bulk updates
5262-
);
5259+
if ($this->validate) {
5260+
$validator = new PartialStructure(
5261+
$collection,
5262+
$this->adapter->getIdAttributeType(),
5263+
$this->adapter->getMinDateTime(),
5264+
$this->adapter->getMaxDateTime(),
5265+
$this->adapter->getSupportForAttributes(),
5266+
null // No old document available in bulk updates
5267+
);
52635268

5264-
if (!$validator->isValid($updates)) {
5265-
throw new StructureException($validator->getDescription());
5269+
if (!$validator->isValid($updates)) {
5270+
throw new StructureException($validator->getDescription());
5271+
}
52665272
}
52675273

52685274
$originalLimit = $limit;
@@ -6021,17 +6027,19 @@ public function upsertDocumentsWithIncrease(
60216027
}
60226028
}
60236029

6024-
$validator = new Structure(
6025-
$collection,
6026-
$this->adapter->getIdAttributeType(),
6027-
$this->adapter->getMinDateTime(),
6028-
$this->adapter->getMaxDateTime(),
6029-
$this->adapter->getSupportForAttributes(),
6030-
$old->isEmpty() ? null : $old
6031-
);
6030+
if ($this->validate) {
6031+
$validator = new Structure(
6032+
$collection,
6033+
$this->adapter->getIdAttributeType(),
6034+
$this->adapter->getMinDateTime(),
6035+
$this->adapter->getMaxDateTime(),
6036+
$this->adapter->getSupportForAttributes(),
6037+
$old->isEmpty() ? null : $old
6038+
);
60326039

6033-
if (!$validator->isValid($document)) {
6034-
throw new StructureException($validator->getDescription());
6040+
if (!$validator->isValid($document)) {
6041+
throw new StructureException($validator->getDescription());
6042+
}
60356043
}
60366044

60376045
$document = $this->encode($collection, $document);

tests/e2e/Adapter/Scopes/DocumentTests.php

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6229,4 +6229,138 @@ public function testBypassStructureWithSupportForAttributes(): void
62296229

62306230
$database->deleteCollection($collectionId);
62316231
}
6232+
6233+
public function testValidationGuardsWithNullRequired(): void
6234+
{
6235+
/** @var Database $database */
6236+
$database = static::getDatabase();
6237+
6238+
if (!$database->getAdapter()->getSupportForAttributes()) {
6239+
$this->expectNotToPerformAssertions();
6240+
return;
6241+
}
6242+
6243+
// Base collection and attributes
6244+
$collection = 'validation_guard_all';
6245+
$database->createCollection($collection, permissions: [
6246+
Permission::read(Role::any()),
6247+
Permission::create(Role::any()),
6248+
Permission::update(Role::any()),
6249+
Permission::delete(Role::any()),
6250+
], documentSecurity: true);
6251+
$database->createAttribute($collection, 'name', Database::VAR_STRING, 32, true);
6252+
$database->createAttribute($collection, 'age', Database::VAR_INTEGER, 0, true);
6253+
$database->createAttribute($collection, 'value', Database::VAR_INTEGER, 0, false);
6254+
6255+
// 1) createDocument with null required should fail when validation enabled, pass when disabled
6256+
try {
6257+
$database->createDocument($collection, new Document([
6258+
'$permissions' => [Permission::read(Role::any()), Permission::create(Role::any())],
6259+
'name' => null,
6260+
'age' => null,
6261+
]));
6262+
$this->fail('Failed to throw exception');
6263+
} catch (Throwable $e) {
6264+
$this->assertInstanceOf(StructureException::class, $e);
6265+
}
6266+
6267+
$database->disableValidation();
6268+
$doc = $database->createDocument($collection, new Document([
6269+
'$id' => 'created-null',
6270+
'$permissions' => [Permission::read(Role::any()), Permission::create(Role::any()), Permission::update(Role::any())],
6271+
'name' => null,
6272+
'age' => null,
6273+
]));
6274+
$this->assertEquals('created-null', $doc->getId());
6275+
$database->enableValidation();
6276+
6277+
// Seed a valid document for updates
6278+
$valid = $database->createDocument($collection, new Document([
6279+
'$id' => 'valid',
6280+
'$permissions' => [Permission::read(Role::any()), Permission::update(Role::any())],
6281+
'name' => 'ok',
6282+
'age' => 10,
6283+
]));
6284+
$this->assertEquals('valid', $valid->getId());
6285+
6286+
// 2) updateDocument set required to null should fail when validation enabled, pass when disabled
6287+
try {
6288+
$database->updateDocument($collection, 'valid', new Document([
6289+
'age' => null,
6290+
]));
6291+
$this->fail('Failed to throw exception');
6292+
} catch (Throwable $e) {
6293+
$this->assertInstanceOf(StructureException::class, $e);
6294+
}
6295+
6296+
$database->disableValidation();
6297+
$updated = $database->updateDocument($collection, 'valid', new Document([
6298+
'age' => null,
6299+
]));
6300+
$this->assertNull($updated->getAttribute('age'));
6301+
$database->enableValidation();
6302+
6303+
// Seed a few valid docs for bulk update
6304+
for ($i = 0; $i < 2; $i++) {
6305+
$database->createDocument($collection, new Document([
6306+
'$id' => 'b' . $i,
6307+
'$permissions' => [Permission::read(Role::any()), Permission::update(Role::any())],
6308+
'name' => 'ok',
6309+
'age' => 1,
6310+
]));
6311+
}
6312+
6313+
// 3) updateDocuments setting required to null should fail when validation enabled, pass when disabled
6314+
if ($database->getAdapter()->getSupportForBatchOperations()) {
6315+
try {
6316+
$database->updateDocuments($collection, new Document([
6317+
'name' => null,
6318+
]));
6319+
$this->fail('Failed to throw exception');
6320+
} catch (Throwable $e) {
6321+
$this->assertInstanceOf(StructureException::class, $e);
6322+
}
6323+
6324+
$database->disableValidation();
6325+
$count = $database->updateDocuments($collection, new Document([
6326+
'name' => null,
6327+
]));
6328+
$this->assertGreaterThanOrEqual(3, $count); // at least the seeded docs are updated
6329+
$database->enableValidation();
6330+
}
6331+
6332+
// 4) upsertDocumentsWithIncrease with null required should fail when validation enabled, pass when disabled
6333+
if ($database->getAdapter()->getSupportForUpserts()) {
6334+
try {
6335+
$database->upsertDocumentsWithIncrease(
6336+
collection: $collection,
6337+
attribute: 'value',
6338+
documents: [new Document([
6339+
'$id' => 'u1',
6340+
'name' => null, // required null
6341+
'value' => 1,
6342+
])]
6343+
);
6344+
$this->fail('Failed to throw exception');
6345+
} catch (Throwable $e) {
6346+
$this->assertInstanceOf(StructureException::class, $e);
6347+
}
6348+
6349+
$database->disableValidation();
6350+
$ucount = $database->upsertDocumentsWithIncrease(
6351+
collection: $collection,
6352+
attribute: 'value',
6353+
documents: [new Document([
6354+
'$id' => 'u1',
6355+
'name' => null,
6356+
'value' => 1,
6357+
])]
6358+
);
6359+
$this->assertEquals(1, $ucount);
6360+
$database->enableValidation();
6361+
}
6362+
6363+
// Cleanup
6364+
$database->deleteCollection($collection);
6365+
}
62326366
}

0 commit comments

Comments
 (0)