Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Database/Adapter/MariaDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ public function updateDocument(Document $collection, string $id, Document $docum
$stmtRemovePermissions = $this->getPDO()->prepare($sql);
$stmtRemovePermissions->bindValue(':_uid', $id);
if ($this->sharedTables) {
$stmtRemovePermissions->bindValue(':_tenant', $this->tenant);
$stmtRemovePermissions->bindValue(':_tenant', $document->getTenant());
}

$values = [];
Expand All @@ -1026,7 +1026,7 @@ public function updateDocument(Document $collection, string $id, Document $docum
$stmtAddPermissions = $this->getPDO()->prepare($sql);
$stmtAddPermissions->bindValue(":_uid", $newUid);
if ($this->sharedTables) {
$stmtAddPermissions->bindValue(":_tenant", $this->tenant);
$stmtAddPermissions->bindValue(":_tenant", $document->getTenant());
}

foreach ($binds as $key => $permission) {
Expand Down
4 changes: 2 additions & 2 deletions src/Database/Adapter/Postgres.php
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@ public function updateDocument(Document $collection, string $id, Document $docum
$stmtRemovePermissions = $this->getPDO()->prepare($sql);
$stmtRemovePermissions->bindValue(':_uid', $id);
if ($this->sharedTables) {
$stmtRemovePermissions->bindValue(':_tenant', $this->tenant);
$stmtRemovePermissions->bindValue(':_tenant', $document->getTenant());
}

$values = [];
Expand All @@ -1152,7 +1152,7 @@ public function updateDocument(Document $collection, string $id, Document $docum
$stmtAddPermissions = $this->getPDO()->prepare($sql);
$stmtAddPermissions->bindValue(":_uid", $newUid);
if ($this->sharedTables) {
$stmtAddPermissions->bindValue(':_tenant', $this->tenant);
$stmtAddPermissions->bindValue(':_tenant', $document->getTenant());
}

foreach ($binds as $key => $permission) {
Expand Down
6 changes: 3 additions & 3 deletions src/Database/Adapter/SQLite.php
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,7 @@ public function updateDocument(Document $collection, string $id, Document $docum
$attributes['_uid'] = $document->getId();

if ($this->sharedTables) {
$attributes['_tenant'] = $this->tenant;
$attributes['_tenant'] = $document->getTenant();
}

$name = $this->filter($collection);
Expand All @@ -1289,7 +1289,7 @@ public function updateDocument(Document $collection, string $id, Document $docum
$stmtRemovePermissions = $this->getPDO()->prepare($sql);
$stmtRemovePermissions->bindValue(':_uid', $id);
if ($this->sharedTables) {
$stmtRemovePermissions->bindValue(':_tenant', $this->tenant);
$stmtRemovePermissions->bindValue(':_tenant', $document->getTenant());
}

$values = [];
Expand All @@ -1314,7 +1314,7 @@ public function updateDocument(Document $collection, string $id, Document $docum
$stmtAddPermissions = $this->getPDO()->prepare($sql);
$stmtAddPermissions->bindValue(":_uid", $newUid);
if ($this->sharedTables) {
$stmtAddPermissions->bindValue(":_tenant", $this->tenant);
$stmtAddPermissions->bindValue(":_tenant", $document->getTenant());
}

foreach ($binds as $key => $permission) {
Expand Down
47 changes: 47 additions & 0 deletions tests/e2e/Adapter/Scopes/PermissionTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,63 @@
namespace Tests\E2E\Adapter\Scopes;

use Exception;
use Utopia\Database\Adapter\SQL;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Exception\Authorization as AuthorizationException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;

trait PermissionTests
{
public function testUpdatingASharedDefinitionKeepsItsPermissionRowsTenantless(): void
{
/** @var Database $database */
$database = $this->getDatabase();

// Only the SQL adapters keep permissions in a side table that carries
// its own tenant column; Mongo stores them on the document itself.
if (!$database->getSharedTables() || !$database->getAdapter() instanceof SQL) {
$this->expectNotToPerformAssertions();
return;
}

$tenant = $database->getTenant();
$collection = 'sharedDefinitionPerms';

try {
// A shared pool's system collections are created once with no
// tenant, so every tenant on the pool reads the one definition.
$database->setTenant(null);
$database->createCollection($collection, [], [], [Permission::read(Role::any())], false);

// A per-project pass rewrites that definition while it holds one
// project's tenant. The rows it writes belong to the document, not
// to whoever happened to be selected.
$database->setTenant(989);
$database->updateDocument(Database::METADATA, $collection, new Document([
'$id' => $collection,
'$permissions' => [Permission::read(Role::any()), Permission::update(Role::any())],
]));

// Permission filtering reads the permission rows, so tenanting them
// to 989 hides the shared definition from every other tenant.
$database->setTenant(990);
$found = $database->find(Database::METADATA, [Query::equal('$id', [$collection])]);

$this->assertCount(
1,
$found,
'A shared definition updated under one tenant must stay visible to the rest of the pool.',
);
} finally {
$database->setTenant($tenant);
}
}

public function testUnsetPermissions(): void
{
/** @var Database $database */
Expand Down
Loading