diff --git a/src/Database/Adapter.php b/src/Database/Adapter.php index c20593ba1..7ff0770c4 100644 --- a/src/Database/Adapter.php +++ b/src/Database/Adapter.php @@ -697,10 +697,11 @@ 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 988af6bed..234b0cd83 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -925,13 +925,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(); @@ -942,149 +943,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)} "; - $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/Pool.php b/src/Database/Adapter/Pool.php index e64db87ec..d255a1d1e 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()); } diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index 2f26dd3e2..4d77772aa 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -1043,15 +1043,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(); @@ -1061,134 +1062,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..0c8d502c6 100644 --- a/src/Database/Adapter/SQLite.php +++ b/src/Database/Adapter/SQLite.php @@ -629,13 +629,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 */ - 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(); @@ -649,134 +651,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); + } } } } diff --git a/src/Database/Database.php b/src/Database/Database.php index ca1f47389..5aefb0be8 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -4108,6 +4108,18 @@ public function updateDocument(string $collection, string $id, Document $documen fn () => $this->getDocument($collection->getId(), $id, forUpdate: true) )); + $skipPermissionsUpdate = false; + + if ($document->offsetExists('$permissions')) { + $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 $document['$createdAt'] = $old->getCreatedAt(); // Make sure user doesn't switch createdAt @@ -4263,7 +4275,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; @@ -4929,12 +4941,21 @@ public function createOrUpdateDocumentsWithIncrease( ))); } - $updatesPermissions = \in_array('$permissions', \array_keys($document->getArrayCopy())) - && $document->getPermissions() != $old->getPermissions(); + $skipPermissionsUpdate = false; + + if ($document->offsetExists('$permissions')) { + $originalPermissions = $old->getPermissions(); + $currentPermissions = $document->getPermissions(); + + sort($originalPermissions); + sort($currentPermissions); + + $skipPermissionsUpdate = ($originalPermissions === $currentPermissions); + } if ( empty($attribute) - && !$updatesPermissions + && $skipPermissionsUpdate && $old->getAttributes() == $document->getAttributes() ) { // If not updating a single attribute and the @@ -4990,7 +5011,7 @@ public function createOrUpdateDocumentsWithIncrease( } } - if (!$updatesPermissions) { + if ($skipPermissionsUpdate) { $document->setAttribute('$permissions', $old->getPermissions()); }