Skip to content

Commit 59012f9

Browse files
committed
fix comments
1 parent a7a363e commit 59012f9

2 files changed

Lines changed: 33 additions & 7 deletions

File tree

‎src/Database/Database.php‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8279,8 +8279,10 @@ public function upsertDocumentsWithIncrease(
82798279
$old = $existingDocs[$this->tenantKey($document)] ?? new Document();
82808280

82818281
// Captured here, before encoding materialises every column of the
8282-
// collection. Keyed by id because the batches are re-indexed later.
8283-
$suppliedColumns[$document->getId()] = self::suppliedColumns($document);
8282+
// collection. Keyed by tenant identity, not id: the batches are re-indexed
8283+
// later, and in tenant-per-document mode one batch can carry the same id for
8284+
// two tenants, whose exemptions must not overwrite each other.
8285+
$suppliedColumns[$this->tenantKey($document)] = self::suppliedColumns($document);
82848286

82858287
$document = $this->removeUnknownAttributes($collection, $document);
82868288

@@ -8546,7 +8548,7 @@ public function upsertDocumentsWithIncrease(
85468548
// not $doc. $doc is the adapter's merged result, so using it would
85478549
// exempt every stored column and mask nothing at all.
85488550
$onNext && $onNext(
8549-
$this->maskWriteResponse($collection, $doc, $suppliedColumns[$doc->getId()] ?? []),
8551+
$this->maskWriteResponse($collection, $doc, $suppliedColumns[$this->tenantKey($doc)] ?? []),
85508552
$old->isEmpty() ? null : $this->maskUnreadableColumns($collection, $old)
85518553
);
85528554
} catch (\Throwable $th) {

‎tests/unit/ColumnPermissionSqlTest.php‎

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,37 @@ private function shape(array $rows): array
110110
return $shape;
111111
}
112112

113-
public function testColumnIsPersistedOnThePermissionsTable(): void
113+
/**
114+
* A column-scoped grant lives in two places: the _permissions JSON on the row, which
115+
* drives masking, and a _perms row, which drives the find/count/sum gate. Re-scoping
116+
* the grant to another column has to move both. If only the JSON is rewritten the
117+
* filter still answers on the old column -- which is what happens when the permission
118+
* diff compares roles and ignores the column.
119+
*/
120+
public function testRescopingAGrantMovesBothTheMaskAndTheFilter(): void
114121
{
115-
$rows = $this->authorization->skip(
116-
fn () => $this->database->find('employees', [Query::equal('$id', ['e1'])])
122+
$this->as(['any', 'user:hr']);
123+
124+
$this->assertSame(
125+
['e1' => ['name', 'salary']],
126+
$this->shape($this->database->find('employees', [Query::greaterThan('salary', 95000)]))
127+
);
128+
129+
$this->authorization->skip(fn () => $this->database->updateDocument('employees', 'e1', new Document([
130+
'$permissions' => [Permission::read(Role::user('hr'), 'name')],
131+
])));
132+
133+
$this->as(['any', 'user:hr']);
134+
135+
// the mask no longer yields salary...
136+
$this->assertSame(
137+
['e1' => ['name'], 'e2' => ['name']],
138+
$this->shape($this->database->find('employees'))
117139
);
118140

119-
$this->assertSame(['read("user:hr", "salary")'], $rows[0]->getPermissions());
141+
// ...and neither does the gate, so the row cannot be found through it
142+
$this->assertSame([], $this->database->find('employees', [Query::greaterThan('salary', 95000)]));
143+
$this->assertSame(0, $this->database->sum('employees', 'salary'));
120144
}
121145

122146
/**

0 commit comments

Comments
 (0)