From 454b97496f13892bb5acba9035fc91dcc3d05109 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 18 Jun 2025 17:45:54 +0300 Subject: [PATCH 1/9] skipPermissionsUpdate --- src/Database/Adapter.php | 19 ++- src/Database/Adapter/MariaDB.php | 199 +++++++++++++++--------------- src/Database/Adapter/Postgres.php | 179 ++++++++++++++------------- src/Database/Adapter/SQLite.php | 11 +- src/Database/Database.php | 11 +- 5 files changed, 224 insertions(+), 195 deletions(-) diff --git a/src/Database/Adapter.php b/src/Database/Adapter.php index 88fd7d64f..57f67a15c 100644 --- a/src/Database/Adapter.php +++ b/src/Database/Adapter.php @@ -21,6 +21,8 @@ abstract class Adapter protected bool $tenantPerDocument = false; + protected bool $skipPermissions = false; + protected int $timeout = 0; protected int $inTransaction = 0; @@ -229,6 +231,19 @@ public function setTenantPerDocument(bool $tenantPerDocument): bool return true; } + /** + * Set whether to skip permissions logic + * + * @param bool $tenantPerDocument + * + */ + public function setSkipPermissions(bool $skipPermissions): void + { + $this->skipPermissions = $skipPermissions; + } + + + /** * Get Tenant Per Document. * @@ -697,10 +712,10 @@ abstract public function createDocuments(string $collection, array $documents): * @param string $collection * @param string $id * @param Document $document - * + * @param bool $skipPermissions * @return Document */ - abstract public function updateDocument(string $collection, string $id, Document $document): Document; + abstract public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document; /** * Update documents diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index bab2eb267..2593ee05f 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -927,13 +927,14 @@ public function createDocument(string $collection, Document $document): Document * @param string $collection * @param string $id * @param Document $document + * @param bool $skipPermissions * @return Document * @throws Exception * @throws PDOException * @throws DuplicateException * @throws \Throwable */ - public function updateDocument(string $collection, string $id, Document $document): Document + public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document { try { $attributes = $document->getAttributes(); @@ -944,149 +945,151 @@ public function updateDocument(string $collection, string $id, Document $documen $name = $this->filter($collection); $columns = ''; - $sql = " + if (!$skipPermissions){ + $sql = " SELECT _type, _permission FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid {$this->getTenantQuery($collection)} "; +var_dump($sql); + $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); - $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); + /** + * Get current permissions from the database + */ + $sqlPermissions = $this->getPDO()->prepare($sql); + $sqlPermissions->bindValue(':_uid', $document->getId()); - /** - * Get current permissions from the database - */ - $sqlPermissions = $this->getPDO()->prepare($sql); - $sqlPermissions->bindValue(':_uid', $document->getId()); - - if ($this->sharedTables) { - $sqlPermissions->bindValue(':_tenant', $this->tenant); - } + if ($this->sharedTables) { + $sqlPermissions->bindValue(':_tenant', $this->tenant); + } - $sqlPermissions->execute(); - $permissions = $sqlPermissions->fetchAll(); - $sqlPermissions->closeCursor(); + $sqlPermissions->execute(); + $permissions = $sqlPermissions->fetchAll(); + $sqlPermissions->closeCursor(); - $initial = []; - foreach (Database::PERMISSIONS as $type) { - $initial[$type] = []; - } + $initial = []; + foreach (Database::PERMISSIONS as $type) { + $initial[$type] = []; + } - $permissions = array_reduce($permissions, function (array $carry, array $item) { - $carry[$item['_type']][] = $item['_permission']; + $permissions = array_reduce($permissions, function (array $carry, array $item) { + $carry[$item['_type']][] = $item['_permission']; - return $carry; - }, $initial); + return $carry; + }, $initial); - /** - * Get removed Permissions - */ - $removals = []; - foreach (Database::PERMISSIONS as $type) { - $diff = \array_diff($permissions[$type], $document->getPermissionsByType($type)); - if (!empty($diff)) { - $removals[$type] = $diff; + /** + * Get removed Permissions + */ + $removals = []; + foreach (Database::PERMISSIONS as $type) { + $diff = \array_diff($permissions[$type], $document->getPermissionsByType($type)); + if (!empty($diff)) { + $removals[$type] = $diff; + } } - } - /** - * Get added Permissions - */ - $additions = []; - foreach (Database::PERMISSIONS as $type) { - $diff = \array_diff($document->getPermissionsByType($type), $permissions[$type]); - if (!empty($diff)) { - $additions[$type] = $diff; + /** + * Get added Permissions + */ + $additions = []; + foreach (Database::PERMISSIONS as $type) { + $diff = \array_diff($document->getPermissionsByType($type), $permissions[$type]); + if (!empty($diff)) { + $additions[$type] = $diff; + } } - } - /** - * Query to remove permissions - */ - $removeQuery = ''; - if (!empty($removals)) { - $removeQuery = ' AND ('; - foreach ($removals as $type => $permissions) { - $removeQuery .= "( + /** + * Query to remove permissions + */ + $removeQuery = ''; + if (!empty($removals)) { + $removeQuery = ' AND ('; + foreach ($removals as $type => $permissions) { + $removeQuery .= "( _type = '{$type}' AND _permission IN (" . implode(', ', \array_map(fn (string $i) => ":_remove_{$type}_{$i}", \array_keys($permissions))) . ") )"; - if ($type !== \array_key_last($removals)) { - $removeQuery .= ' OR '; + if ($type !== \array_key_last($removals)) { + $removeQuery .= ' OR '; + } } } - } - if (!empty($removeQuery)) { - $removeQuery .= ')'; - $sql = " + if (!empty($removeQuery)) { + $removeQuery .= ')'; + $sql = " DELETE FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid {$this->getTenantQuery($collection)} "; - $removeQuery = $sql . $removeQuery; + $removeQuery = $sql . $removeQuery; - $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); + $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); - $stmtRemovePermissions = $this->getPDO()->prepare($removeQuery); - $stmtRemovePermissions->bindValue(':_uid', $document->getId()); + $stmtRemovePermissions = $this->getPDO()->prepare($removeQuery); + $stmtRemovePermissions->bindValue(':_uid', $document->getId()); - if ($this->sharedTables) { - $stmtRemovePermissions->bindValue(':_tenant', $this->tenant); - } + if ($this->sharedTables) { + $stmtRemovePermissions->bindValue(':_tenant', $this->tenant); + } - foreach ($removals as $type => $permissions) { - foreach ($permissions as $i => $permission) { - $stmtRemovePermissions->bindValue(":_remove_{$type}_{$i}", $permission); + foreach ($removals as $type => $permissions) { + foreach ($permissions as $i => $permission) { + $stmtRemovePermissions->bindValue(":_remove_{$type}_{$i}", $permission); + } } } - } - - /** - * Query to add permissions - */ - if (!empty($additions)) { - $values = []; - foreach ($additions as $type => $permissions) { - foreach ($permissions as $i => $_) { - $value = "( :_uid, '{$type}', :_add_{$type}_{$i}"; - if ($this->sharedTables) { - $value .= ", :_tenant)"; - } else { - $value .= ")"; + /** + * Query to add permissions + */ + if (!empty($additions)) { + $values = []; + foreach ($additions as $type => $permissions) { + foreach ($permissions as $i => $_) { + $value = "( :_uid, '{$type}', :_add_{$type}_{$i}"; + + if ($this->sharedTables) { + $value .= ", :_tenant)"; + } else { + $value .= ")"; + } + + $values[] = $value; } - - $values[] = $value; } - } - $sql = " + $sql = " INSERT INTO {$this->getSQLTable($name . '_perms')} (_document, _type, _permission "; - if ($this->sharedTables) { - $sql .= ', _tenant)'; - } else { - $sql .= ')'; - } + if ($this->sharedTables) { + $sql .= ', _tenant)'; + } else { + $sql .= ')'; + } - $sql .= " VALUES " . \implode(', ', $values); + $sql .= " VALUES " . \implode(', ', $values); - $sql = $this->trigger(Database::EVENT_PERMISSIONS_CREATE, $sql); + $sql = $this->trigger(Database::EVENT_PERMISSIONS_CREATE, $sql); - $stmtAddPermissions = $this->getPDO()->prepare($sql); + $stmtAddPermissions = $this->getPDO()->prepare($sql); - $stmtAddPermissions->bindValue(":_uid", $document->getId()); + $stmtAddPermissions->bindValue(":_uid", $document->getId()); - if ($this->sharedTables) { - $stmtAddPermissions->bindValue(":_tenant", $this->tenant); - } + if ($this->sharedTables) { + $stmtAddPermissions->bindValue(":_tenant", $this->tenant); + } - foreach ($additions as $type => $permissions) { - foreach ($permissions as $i => $permission) { - $stmtAddPermissions->bindValue(":_add_{$type}_{$i}", $permission); + foreach ($additions as $type => $permissions) { + foreach ($permissions as $i => $permission) { + $stmtAddPermissions->bindValue(":_add_{$type}_{$i}", $permission); + } } } } diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index 37d2edeec..e34c134e7 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -1045,15 +1045,16 @@ public function createDocument(string $collection, Document $document): Document /** * Update Document * + * * @param string $collection * @param string $id * @param Document $document - * + * @param bool $skipPermissions * @return Document * @throws DatabaseException * @throws DuplicateException */ - public function updateDocument(string $collection, string $id, Document $document): Document + public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document { $attributes = $document->getAttributes(); $attributes['_createdAt'] = $document->getCreatedAt(); @@ -1063,134 +1064,136 @@ public function updateDocument(string $collection, string $id, Document $documen $name = $this->filter($collection); $columns = ''; - $sql = " + if (!$skipPermissions){ + $sql = " SELECT _type, _permission FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid {$this->getTenantQuery($collection)} - "; + "; - $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); + $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); - /** - * Get current permissions from the database - */ - $permissionsStmt = $this->getPDO()->prepare($sql); - $permissionsStmt->bindValue(':_uid', $document->getId()); + /** + * Get current permissions from the database + */ + $permissionsStmt = $this->getPDO()->prepare($sql); + $permissionsStmt->bindValue(':_uid', $document->getId()); - if ($this->sharedTables) { - $permissionsStmt->bindValue(':_tenant', $this->tenant); - } + if ($this->sharedTables) { + $permissionsStmt->bindValue(':_tenant', $this->tenant); + } - $this->execute($permissionsStmt); - $permissions = $permissionsStmt->fetchAll(); - $permissionsStmt->closeCursor(); + $this->execute($permissionsStmt); + $permissions = $permissionsStmt->fetchAll(); + $permissionsStmt->closeCursor(); - $initial = []; - foreach (Database::PERMISSIONS as $type) { - $initial[$type] = []; - } + $initial = []; + foreach (Database::PERMISSIONS as $type) { + $initial[$type] = []; + } - $permissions = array_reduce($permissions, function (array $carry, array $item) { - $carry[$item['_type']][] = $item['_permission']; + $permissions = array_reduce($permissions, function (array $carry, array $item) { + $carry[$item['_type']][] = $item['_permission']; - return $carry; - }, $initial); + return $carry; + }, $initial); - /** - * Get removed Permissions - */ - $removals = []; - foreach (Database::PERMISSIONS as $type) { - $diff = \array_diff($permissions[$type], $document->getPermissionsByType($type)); - if (!empty($diff)) { - $removals[$type] = $diff; + /** + * Get removed Permissions + */ + $removals = []; + foreach (Database::PERMISSIONS as $type) { + $diff = \array_diff($permissions[$type], $document->getPermissionsByType($type)); + if (!empty($diff)) { + $removals[$type] = $diff; + } } - } - /** - * Get added Permissions - */ - $additions = []; - foreach (Database::PERMISSIONS as $type) { - $diff = \array_diff($document->getPermissionsByType($type), $permissions[$type]); - if (!empty($diff)) { - $additions[$type] = $diff; + /** + * Get added Permissions + */ + $additions = []; + foreach (Database::PERMISSIONS as $type) { + $diff = \array_diff($document->getPermissionsByType($type), $permissions[$type]); + if (!empty($diff)) { + $additions[$type] = $diff; + } } - } - /** - * Query to remove permissions - */ - $removeQuery = ''; - if (!empty($removals)) { - $removeQuery = ' AND ('; - foreach ($removals as $type => $permissions) { - $removeQuery .= "( + /** + * Query to remove permissions + */ + $removeQuery = ''; + if (!empty($removals)) { + $removeQuery = ' AND ('; + foreach ($removals as $type => $permissions) { + $removeQuery .= "( _type = '{$type}' AND _permission IN (" . implode(', ', \array_map(fn (string $i) => ":_remove_{$type}_{$i}", \array_keys($permissions))) . ") )"; - if ($type !== \array_key_last($removals)) { - $removeQuery .= ' OR '; + if ($type !== \array_key_last($removals)) { + $removeQuery .= ' OR '; + } } } - } - if (!empty($removeQuery)) { - $removeQuery .= ')'; + if (!empty($removeQuery)) { + $removeQuery .= ')'; - $sql = " + $sql = " DELETE FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid {$this->getTenantQuery($collection)} "; - $removeQuery = $sql . $removeQuery; + $removeQuery = $sql . $removeQuery; - $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); - $stmtRemovePermissions = $this->getPDO()->prepare($removeQuery); - $stmtRemovePermissions->bindValue(':_uid', $document->getId()); + $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); + $stmtRemovePermissions = $this->getPDO()->prepare($removeQuery); + $stmtRemovePermissions->bindValue(':_uid', $document->getId()); - if ($this->sharedTables) { - $stmtRemovePermissions->bindValue(':_tenant', $this->tenant); - } + if ($this->sharedTables) { + $stmtRemovePermissions->bindValue(':_tenant', $this->tenant); + } - foreach ($removals as $type => $permissions) { - foreach ($permissions as $i => $permission) { - $stmtRemovePermissions->bindValue(":_remove_{$type}_{$i}", $permission); + foreach ($removals as $type => $permissions) { + foreach ($permissions as $i => $permission) { + $stmtRemovePermissions->bindValue(":_remove_{$type}_{$i}", $permission); + } } } - } - /** - * Query to add permissions - */ - if (!empty($additions)) { - $values = []; - foreach ($additions as $type => $permissions) { - foreach ($permissions as $i => $_) { - $sqlTenant = $this->sharedTables ? ', :_tenant' : ''; - $values[] = "( :_uid, '{$type}', :_add_{$type}_{$i} {$sqlTenant})"; + /** + * Query to add permissions + */ + if (!empty($additions)) { + $values = []; + foreach ($additions as $type => $permissions) { + foreach ($permissions as $i => $_) { + $sqlTenant = $this->sharedTables ? ', :_tenant' : ''; + $values[] = "( :_uid, '{$type}', :_add_{$type}_{$i} {$sqlTenant})"; + } } - } - $sqlTenant = $this->sharedTables ? ', _tenant' : ''; + $sqlTenant = $this->sharedTables ? ', _tenant' : ''; - $sql = " + $sql = " INSERT INTO {$this->getSQLTable($name . '_perms')} (_document, _type, _permission {$sqlTenant}) VALUES" . \implode(', ', $values); - $sql = $this->trigger(Database::EVENT_PERMISSIONS_CREATE, $sql); + $sql = $this->trigger(Database::EVENT_PERMISSIONS_CREATE, $sql); - $stmtAddPermissions = $this->getPDO()->prepare($sql); - $stmtAddPermissions->bindValue(":_uid", $document->getId()); - if ($this->sharedTables) { - $stmtAddPermissions->bindValue(':_tenant', $this->tenant); - } + $stmtAddPermissions = $this->getPDO()->prepare($sql); + $stmtAddPermissions->bindValue(":_uid", $document->getId()); + if ($this->sharedTables) { + $stmtAddPermissions->bindValue(':_tenant', $this->tenant); + } - foreach ($additions as $type => $permissions) { - foreach ($permissions as $i => $permission) { - $stmtAddPermissions->bindValue(":_add_{$type}_{$i}", $permission); + foreach ($additions as $type => $permissions) { + foreach ($permissions as $i => $permission) { + $stmtAddPermissions->bindValue(":_add_{$type}_{$i}", $permission); + } } } } diff --git a/src/Database/Adapter/SQLite.php b/src/Database/Adapter/SQLite.php index be2c4b5f7..4ca55c8f5 100644 --- a/src/Database/Adapter/SQLite.php +++ b/src/Database/Adapter/SQLite.php @@ -626,16 +626,15 @@ public function createDocument(string $collection, Document $document): Document } /** - * Update Document - * * @param string $collection + * @param string $id * @param Document $document + * @param bool $skipPermissions * @return Document - * @throws Exception - * @throws PDOException - * @throws Duplicate + * @throws DatabaseException + * @throws DuplicateException */ - public function updateDocument(string $collection, string $id, Document $document): Document + public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document { $attributes = $document->getAttributes(); $attributes['_createdAt'] = $document->getCreatedAt(); diff --git a/src/Database/Database.php b/src/Database/Database.php index 6d55e5f17..04ae6d866 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -4118,6 +4118,15 @@ public function updateDocument(string $collection, string $id, Document $documen fn () => $this->getDocument($collection->getId(), $id, forUpdate: true) )); + $skipPermissionsUpdate = $old->getPermissions() === $document->getPermissions(); + + if(!$skipPermissionsUpdate){ + var_dump('check permissiosnss permissiosnss permissiosnss permissiosnss'); + var_dump($skipPermissionsUpdate); + var_dump($old->getPermissions()); + var_dump($document->getPermissions()); + } + $document = \array_merge($old->getArrayCopy(), $document->getArrayCopy()); $document['$collection'] = $old->getAttribute('$collection'); // Make sure user doesn't switch collection ID $document['$createdAt'] = $old->getCreatedAt(); // Make sure user doesn't switch createdAt @@ -4274,7 +4283,7 @@ public function updateDocument(string $collection, string $id, Document $documen $document = $this->silent(fn () => $this->updateDocumentRelationships($collection, $old, $document)); } - $this->adapter->updateDocument($collection->getId(), $id, $document); + $this->adapter->updateDocument($collection->getId(), $id, $document, $skipPermissionsUpdate); $this->purgeCachedDocument($collection->getId(), $id); return $document; From 9d3d2197b9940c67121f5db4012d2d3ae1cf945b Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 18 Jun 2025 17:47:58 +0300 Subject: [PATCH 2/9] Remove from Adapter --- src/Database/Adapter.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/Database/Adapter.php b/src/Database/Adapter.php index 57f67a15c..474995014 100644 --- a/src/Database/Adapter.php +++ b/src/Database/Adapter.php @@ -21,8 +21,6 @@ abstract class Adapter protected bool $tenantPerDocument = false; - protected bool $skipPermissions = false; - protected int $timeout = 0; protected int $inTransaction = 0; @@ -231,19 +229,6 @@ public function setTenantPerDocument(bool $tenantPerDocument): bool return true; } - /** - * Set whether to skip permissions logic - * - * @param bool $tenantPerDocument - * - */ - public function setSkipPermissions(bool $skipPermissions): void - { - $this->skipPermissions = $skipPermissions; - } - - - /** * Get Tenant Per Document. * @@ -713,6 +698,7 @@ abstract public function createDocuments(string $collection, array $documents): * @param string $id * @param Document $document * @param bool $skipPermissions + * * @return Document */ abstract public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document; From 8a83a2e8aca42f89bef8d19365232bc0e2c691f5 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 18 Jun 2025 17:49:31 +0300 Subject: [PATCH 3/9] Remove dbg --- src/Database/Adapter/MariaDB.php | 2 +- src/Database/Database.php | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index 2593ee05f..566c0df78 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -952,7 +952,7 @@ public function updateDocument(string $collection, string $id, Document $documen WHERE _document = :_uid {$this->getTenantQuery($collection)} "; -var_dump($sql); + $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); /** diff --git a/src/Database/Database.php b/src/Database/Database.php index 04ae6d866..6d73a1087 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -4120,13 +4120,6 @@ public function updateDocument(string $collection, string $id, Document $documen $skipPermissionsUpdate = $old->getPermissions() === $document->getPermissions(); - if(!$skipPermissionsUpdate){ - var_dump('check permissiosnss permissiosnss permissiosnss permissiosnss'); - var_dump($skipPermissionsUpdate); - var_dump($old->getPermissions()); - var_dump($document->getPermissions()); - } - $document = \array_merge($old->getArrayCopy(), $document->getArrayCopy()); $document['$collection'] = $old->getAttribute('$collection'); // Make sure user doesn't switch collection ID $document['$createdAt'] = $old->getCreatedAt(); // Make sure user doesn't switch createdAt From 8800985a916b4df1e6dce937e1209deab6f828c7 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 18 Jun 2025 17:53:04 +0300 Subject: [PATCH 4/9] lint --- src/Database/Adapter/MariaDB.php | 2 +- src/Database/Adapter/Postgres.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index 566c0df78..67846fd17 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -945,7 +945,7 @@ public function updateDocument(string $collection, string $id, Document $documen $name = $this->filter($collection); $columns = ''; - if (!$skipPermissions){ + if (!$skipPermissions) { $sql = " SELECT _type, _permission FROM {$this->getSQLTable($name . '_perms')} diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index e34c134e7..2277cc856 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -1064,7 +1064,7 @@ public function updateDocument(string $collection, string $id, Document $documen $name = $this->filter($collection); $columns = ''; - if (!$skipPermissions){ + if (!$skipPermissions) { $sql = " SELECT _type, _permission FROM {$this->getSQLTable($name . '_perms')} From 7e69e85eee04f50495933cdafb37d158123a7559 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 19 Jun 2025 09:21:47 +0300 Subject: [PATCH 5/9] Add sort --- src/Database/Database.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 6d73a1087..5150e9b51 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -4118,7 +4118,13 @@ public function updateDocument(string $collection, string $id, Document $documen fn () => $this->getDocument($collection->getId(), $id, forUpdate: true) )); - $skipPermissionsUpdate = $old->getPermissions() === $document->getPermissions(); + $originalPermissions = $old->getPermissions(); + $currentPermissions = $document->getPermissions(); + + sort($originalPermissions); + sort($currentPermissions); + + $skipPermissionsUpdate = ($originalPermissions === $currentPermissions); $document = \array_merge($old->getArrayCopy(), $document->getArrayCopy()); $document['$collection'] = $old->getAttribute('$collection'); // Make sure user doesn't switch collection ID From 2c1dc52007664cb776092529fdfc0362d4ec4bf5 Mon Sep 17 00:00:00 2001 From: Shmuel Fogel Date: Thu, 19 Jun 2025 09:26:59 +0300 Subject: [PATCH 6/9] Update src/Database/Adapter/Postgres.php Co-authored-by: Jake Barnby --- src/Database/Adapter/Postgres.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index 2277cc856..4854544b9 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -1045,7 +1045,6 @@ public function createDocument(string $collection, Document $document): Document /** * Update Document * - * * @param string $collection * @param string $id * @param Document $document From 63345f2d8bcb54da93acc22933fe42f30abad652 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 19 Jun 2025 09:32:35 +0300 Subject: [PATCH 7/9] Fix Pool --- src/Database/Adapter/Pool.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Adapter/Pool.php b/src/Database/Adapter/Pool.php index 302338aa9..8502c7da0 100644 --- a/src/Database/Adapter/Pool.php +++ b/src/Database/Adapter/Pool.php @@ -235,7 +235,7 @@ public function createDocuments(string $collection, array $documents): array return $this->delegate(__FUNCTION__, \func_get_args()); } - public function updateDocument(string $collection, string $id, Document $document): Document + public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document { return $this->delegate(__FUNCTION__, \func_get_args()); } From cadce6cfcba9e874b4fdbbd1dc4486776cb7049f Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 19 Jun 2025 14:54:39 +0300 Subject: [PATCH 8/9] Check key exists --- src/Database/Database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 5150e9b51..c089c6322 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -4124,7 +4124,7 @@ public function updateDocument(string $collection, string $id, Document $documen sort($originalPermissions); sort($currentPermissions); - $skipPermissionsUpdate = ($originalPermissions === $currentPermissions); + $skipPermissionsUpdate = ($originalPermissions === $currentPermissions && $document->getAttribute('$permissions') !== null); $document = \array_merge($old->getArrayCopy(), $document->getArrayCopy()); $document['$collection'] = $old->getAttribute('$collection'); // Make sure user doesn't switch collection ID From 130beb0ca1d3d434e49405a8f3fa4b3dcdef4221 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 19 Jun 2025 15:54:08 +0300 Subject: [PATCH 9/9] SQLite --- src/Database/Adapter/SQLite.php | 172 ++++++++++++++++---------------- 1 file changed, 87 insertions(+), 85 deletions(-) diff --git a/src/Database/Adapter/SQLite.php b/src/Database/Adapter/SQLite.php index 4ca55c8f5..e69c87a39 100644 --- a/src/Database/Adapter/SQLite.php +++ b/src/Database/Adapter/SQLite.php @@ -648,134 +648,136 @@ public function updateDocument(string $collection, string $id, Document $documen $name = $this->filter($collection); $columns = ''; - $sql = " + if (!$skipPermissions) { + $sql = " SELECT _type, _permission FROM `{$this->getNamespace()}_{$name}_perms` WHERE _document = :_uid {$this->getTenantQuery($collection)} "; - $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); + $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); - /** - * Get current permissions from the database - */ - $permissionsStmt = $this->getPDO()->prepare($sql); - $permissionsStmt->bindValue(':_uid', $document->getId()); + /** + * Get current permissions from the database + */ + $permissionsStmt = $this->getPDO()->prepare($sql); + $permissionsStmt->bindValue(':_uid', $document->getId()); - if ($this->sharedTables) { - $permissionsStmt->bindValue(':_tenant', $this->tenant); - } + if ($this->sharedTables) { + $permissionsStmt->bindValue(':_tenant', $this->tenant); + } - $permissionsStmt->execute(); - $permissions = $permissionsStmt->fetchAll(); - $permissionsStmt->closeCursor(); + $permissionsStmt->execute(); + $permissions = $permissionsStmt->fetchAll(); + $permissionsStmt->closeCursor(); - $initial = []; - foreach (Database::PERMISSIONS as $type) { - $initial[$type] = []; - } + $initial = []; + foreach (Database::PERMISSIONS as $type) { + $initial[$type] = []; + } - $permissions = array_reduce($permissions, function (array $carry, array $item) { - $carry[$item['_type']][] = $item['_permission']; + $permissions = array_reduce($permissions, function (array $carry, array $item) { + $carry[$item['_type']][] = $item['_permission']; - return $carry; - }, $initial); + return $carry; + }, $initial); - /** - * Get removed Permissions - */ - $removals = []; - foreach (Database::PERMISSIONS as $type) { - $diff = \array_diff($permissions[$type], $document->getPermissionsByType($type)); - if (!empty($diff)) { - $removals[$type] = $diff; + /** + * Get removed Permissions + */ + $removals = []; + foreach (Database::PERMISSIONS as $type) { + $diff = \array_diff($permissions[$type], $document->getPermissionsByType($type)); + if (!empty($diff)) { + $removals[$type] = $diff; + } } - } - /** - * Get added Permissions - */ - $additions = []; - foreach (Database::PERMISSIONS as $type) { - $diff = \array_diff($document->getPermissionsByType($type), $permissions[$type]); - if (!empty($diff)) { - $additions[$type] = $diff; + /** + * Get added Permissions + */ + $additions = []; + foreach (Database::PERMISSIONS as $type) { + $diff = \array_diff($document->getPermissionsByType($type), $permissions[$type]); + if (!empty($diff)) { + $additions[$type] = $diff; + } } - } - /** - * Query to remove permissions - */ - $removeQuery = ''; - if (!empty($removals)) { - $removeQuery = ' AND ('; - foreach ($removals as $type => $permissions) { - $removeQuery .= "( + /** + * Query to remove permissions + */ + $removeQuery = ''; + if (!empty($removals)) { + $removeQuery = ' AND ('; + foreach ($removals as $type => $permissions) { + $removeQuery .= "( _type = '{$type}' AND _permission IN (" . implode(', ', \array_map(fn (string $i) => ":_remove_{$type}_{$i}", \array_keys($permissions))) . ") )"; - if ($type !== \array_key_last($removals)) { - $removeQuery .= ' OR '; + if ($type !== \array_key_last($removals)) { + $removeQuery .= ' OR '; + } } } - } - if (!empty($removeQuery)) { - $removeQuery .= ')'; - $sql = " + if (!empty($removeQuery)) { + $removeQuery .= ')'; + $sql = " DELETE FROM `{$this->getNamespace()}_{$name}_perms` WHERE _document = :_uid {$this->getTenantQuery($collection)} "; - $removeQuery = $sql . $removeQuery; - $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); + $removeQuery = $sql . $removeQuery; + $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); - $stmtRemovePermissions = $this->getPDO()->prepare($removeQuery); - $stmtRemovePermissions->bindValue(':_uid', $document->getId()); + $stmtRemovePermissions = $this->getPDO()->prepare($removeQuery); + $stmtRemovePermissions->bindValue(':_uid', $document->getId()); - if ($this->sharedTables) { - $stmtRemovePermissions->bindValue(':_tenant', $this->tenant); - } + if ($this->sharedTables) { + $stmtRemovePermissions->bindValue(':_tenant', $this->tenant); + } - foreach ($removals as $type => $permissions) { - foreach ($permissions as $i => $permission) { - $stmtRemovePermissions->bindValue(":_remove_{$type}_{$i}", $permission); + foreach ($removals as $type => $permissions) { + foreach ($permissions as $i => $permission) { + $stmtRemovePermissions->bindValue(":_remove_{$type}_{$i}", $permission); + } } } - } - /** - * Query to add permissions - */ - if (!empty($additions)) { - $values = []; - foreach ($additions as $type => $permissions) { - foreach ($permissions as $i => $_) { - $tenantQuery = $this->sharedTables ? ', :_tenant' : ''; - $values[] = "(:_uid, '{$type}', :_add_{$type}_{$i} {$tenantQuery})"; + /** + * Query to add permissions + */ + if (!empty($additions)) { + $values = []; + foreach ($additions as $type => $permissions) { + foreach ($permissions as $i => $_) { + $tenantQuery = $this->sharedTables ? ', :_tenant' : ''; + $values[] = "(:_uid, '{$type}', :_add_{$type}_{$i} {$tenantQuery})"; + } } - } - $tenantQuery = $this->sharedTables ? ', _tenant' : ''; + $tenantQuery = $this->sharedTables ? ', _tenant' : ''; - $sql = " + $sql = " INSERT INTO `{$this->getNamespace()}_{$name}_perms` (_document, _type, _permission {$tenantQuery}) VALUES " . \implode(', ', $values); - $sql = $this->trigger(Database::EVENT_PERMISSIONS_CREATE, $sql); + $sql = $this->trigger(Database::EVENT_PERMISSIONS_CREATE, $sql); - $stmtAddPermissions = $this->getPDO()->prepare($sql); + $stmtAddPermissions = $this->getPDO()->prepare($sql); - $stmtAddPermissions->bindValue(":_uid", $document->getId()); - if ($this->sharedTables) { - $stmtAddPermissions->bindValue(":_tenant", $this->tenant); - } + $stmtAddPermissions->bindValue(":_uid", $document->getId()); + if ($this->sharedTables) { + $stmtAddPermissions->bindValue(":_tenant", $this->tenant); + } - foreach ($additions as $type => $permissions) { - foreach ($permissions as $i => $permission) { - $stmtAddPermissions->bindValue(":_add_{$type}_{$i}", $permission); + foreach ($additions as $type => $permissions) { + foreach ($permissions as $i => $permission) { + $stmtAddPermissions->bindValue(":_add_{$type}_{$i}", $permission); + } } } }