/** * @param Delete $delete * @return mixed * @throws Exception\RuntimeException * @throws \Directus\Acl\Exception\UnauthorizedTableBigDeleteException * @throws \Directus\Acl\Exception\UnauthorizedTableDeleteException */ protected function executeDelete(Delete $delete) { $cuurrentUserId = null; if (Auth::loggedIn()) { $currentUser = Auth::getUserInfo(); $currentUserId = intval($currentUser['id']); } $deleteState = $delete->getRawState(); $deleteTable = $this->getRawTableNameFromQueryStateTable($deleteState['table']); $cmsOwnerColumn = $this->acl->getCmsOwnerColumnByTable($deleteTable); $canBigHardDelete = $this->acl->hasTablePrivilege($deleteTable, 'bigharddelete'); $canHardDelete = $this->acl->hasTablePrivilege($deleteTable, 'harddelete'); $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); // Is this table a junction table? $deleteTableSchema = TableSchema::getTable($deleteTable); $isDeleteTableAJunction = array_key_exists('is_junction_table', $deleteTableSchema) ? (bool) $deleteTableSchema['is_junction_table'] : false; if ($isDeleteTableAJunction || !TableSchema::hasTableColumn($deleteTable, STATUS_COLUMN_NAME)) { if ($this->acl->hasTablePrivilege($deleteTable, 'bigdelete')) { $canBigHardDelete = true; } else { if ($this->acl->hasTablePrivilege($deleteTable, 'delete')) { $canHardDelete = true; } } } // @todo: clean way if ($deleteTable === 'directus_bookmarks') { $canBigHardDelete = true; } /** * ACL Enforcement */ if (!$canBigHardDelete && !$canHardDelete) { throw new UnauthorizedTableBigDeleteException($aclErrorPrefix . "BigHardDelete/HardDelete access forbidden on table `{$deleteTable}`."); } if (false === $cmsOwnerColumn) { // cannot delete if there's no magic owner column and can't big delete if (!$canBigHardDelete) { // All deletes are "big" deletes if there is no magic owner column. throw new UnauthorizedTableBigDeleteException($aclErrorPrefix . "The table `{$deleteTable}` is missing the `user_create_column` within `directus_tables` (BigHardDelete Permission Forbidden)"); } } else { if (!$canBigHardDelete) { // Who are the owners of these rows? list($predicateResultQty, $predicateOwnerIds) = $this->acl->getCmsOwnerIdsByTableGatewayAndPredicate($this, $deleteState['where']); if (in_array($currentUserId, $predicateOwnerIds)) { $exceptionMessage = "Table harddelete access forbidden on {$predicateResultQty} `{$deleteTable}` table records owned by the authenticated CMS user (#{$currentUserId})."; $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); throw new UnauthorizedTableDeleteException($aclErrorPrefix . $exceptionMessage); } } } try { return parent::executeDelete($delete); } catch (\Zend\Db\Adapter\Exception\InvalidQueryException $e) { if ('production' !== DIRECTUS_ENV) { throw new \RuntimeException("This query failed: " . $this->dumpSql($delete), 0, $e); } // @todo send developer warning throw $e; } }
public function delete() { /** * ACL Enforcement */ $currentUserId = null; if (Auth::loggedIn()) { $currentUser = Auth::getUserInfo(); $currentUserId = intval($currentUser['id']); } $cmsOwnerId = $this->acl->getRecordCmsOwnerId($this, $this->table); if (!TableSchema::hasTableColumn($this->table, STATUS_COLUMN_NAME)) { throw new UnauthorizedTableBigDeleteException($aclErrorPrefix . " forbidden to hard delete on table `{$this->table}` because it has status column."); } /** * Enforce Privilege: "Little" Delete (I am the record CMS owner) */ if ($cmsOwnerId === $currentUserId) { if (!$this->acl->hasTablePrivilege($this->table, 'delete')) { $recordPk = self::stringifyPrimaryKeyForRecordDebugRepresentation($this->primaryKeyData); $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); throw new UnauthorizedTableDeleteException($aclErrorPrefix . "Table harddelete access forbidden on `" . $this->table . "` table record with {$recordPk} owned by the authenticated CMS user (#{$cmsOwnerId})."); } } else { if (!$this->acl->hasTablePrivilege($this->table, 'bigdelete')) { $recordPk = self::stringifyPrimaryKeyForRecordDebugRepresentation($this->primaryKeyData); $recordOwner = false === $cmsOwnerId ? "no magic owner column" : "the CMS owner #{$cmsOwnerId}"; $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); throw new UnauthorizedTableBigDeleteException($aclErrorPrefix . "Table bigharddelete access forbidden on `" . $this->table . "` table record with {$recordPk} and {$recordOwner}."); } } return parent::delete(); }
public function dropColumn($columnName, $tableName = null) { if ($tableName == null) { $tableName = $this->table; } if (!TableSchema::hasTableColumn($tableName, $columnName, true)) { return false; } // Drop table column if is a non-alias column if (!array_key_exists($columnName, array_flip(TableSchema::getAllAliasTableColumns($tableName, true)))) { $sql = new Sql($this->adapter); $alterTable = new Ddl\AlterTable($tableName); $dropColumn = $alterTable->dropColumn($columnName); $query = $sql->getSqlStringForSqlObject($dropColumn); $this->adapter->query($query)->execute(); } // Remove column from directus_columns $columnsTableGateway = new TableGateway('directus_columns', $this->adapter); $columnsTableGateway->delete(['table_name' => $tableName, 'column_name' => $columnName]); // Remove column from directus_ui $uisTableGateway = new TableGateway('directus_ui', $this->adapter); $uisTableGateway->delete(['table_name' => $tableName, 'column_name' => $columnName]); return true; }
/** * @param Delete $delete * @return mixed * @throws Exception\RuntimeException * @throws \Directus\Acl\Exception\UnauthorizedTableBigDeleteException * @throws \Directus\Acl\Exception\UnauthorizedTableDeleteException */ protected function executeDelete(Delete $delete) { $cuurrentUserId = null; if (Auth::loggedIn()) { $currentUser = Auth::getUserInfo(); $currentUserId = intval($currentUser['id']); } $deleteState = $delete->getRawState(); $deleteTable = $this->getRawTableNameFromQueryStateTable($deleteState['table']); $cmsOwnerColumn = $this->acl->getCmsOwnerColumnByTable($deleteTable); $canBigDelete = $this->acl->hasTablePrivilege($deleteTable, 'bigdelete'); $canDelete = $this->acl->hasTablePrivilege($deleteTable, 'delete'); $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); if (!TableSchema::hasTableColumn($deleteTable, STATUS_COLUMN_NAME)) { if ($this->acl->hasTablePrivilege($deleteTable, 'bigdelete')) { $canBigDelete = true; } else { if ($this->acl->hasTablePrivilege($deleteTable, 'delete')) { $canDelete = true; } } } // @todo: clean way if ($deleteTable === 'directus_bookmarks') { $canBigDelete = true; } /** * ACL Enforcement */ if (!$canBigDelete && !$canDelete) { throw new UnauthorizedTableBigDeleteException($aclErrorPrefix . ' forbidden to hard delete on table `' . $deleteTable . '` because it has Status Column.'); } if (false === $cmsOwnerColumn) { // cannot delete if there's no magic owner column and can't big delete if (!$canBigDelete) { // All deletes are "big" deletes if there is no magic owner column. throw new UnauthorizedTableBigDeleteException($aclErrorPrefix . 'The table `' . $deleteTable . '` is missing the `user_create_column` within `directus_tables` (BigHardDelete Permission Forbidden)'); } } else { if (!$canBigDelete) { // Who are the owners of these rows? list($predicateResultQty, $predicateOwnerIds) = $this->acl->getCmsOwnerIdsByTableGatewayAndPredicate($this, $deleteState['where']); if (!in_array($currentUserId, $predicateOwnerIds)) { // $exceptionMessage = "Table harddelete access forbidden on $predicateResultQty `$deleteTable` table records owned by the authenticated CMS user (#$currentUserId)."; $groupsTableGateway = self::makeTableGatewayFromTableName($this->acl, 'directus_groups', $this->adapter); $group = $groupsTableGateway->find($this->acl->getGroupId()); $exceptionMessage = '[' . $group['name'] . '] permissions only allow you to [delete] your own items.'; // $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); throw new UnauthorizedTableDeleteException($exceptionMessage); } } } try { $this->emitter->run('table.delete:before', [$deleteTable]); $this->emitter->run('table.delete.' . $deleteTable . ':before'); $result = parent::executeDelete($delete); $this->emitter->run('table.delete', [$deleteTable]); $this->emitter->run('table.delete:after', [$deleteTable]); $this->emitter->run('table.delete.' . $deleteTable); $this->emitter->run('table.delete.' . $deleteTable . ':after'); return $result; } catch (\Zend\Db\Adapter\Exception\InvalidQueryException $e) { if ('production' !== DIRECTUS_ENV) { throw new \RuntimeException('This query failed: ' . $this->dumpSql($delete), 0, $e); } // @todo send developer warning throw $e; } }
public function delete() { /** * ACL Enforcement */ $currentUserId = $this->acl->getUserId(); $cmsOwnerId = $this->acl->getRecordCmsOwnerId($this, $this->table); $isCurrentUserOwner = $cmsOwnerId === $currentUserId; $canBigDelete = false; $canDelete = false; if (TableSchema::hasTableColumn($this->table, STATUS_COLUMN_NAME)) { if ($this->acl->hasTablePrivilege($this->table, 'bigdelete')) { $canBigDelete = true; } else { if ($this->acl->hasTablePrivilege($this->table, 'delete')) { $canDelete = true; } } } if (!$canDelete && !$canBigDelete) { $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); throw new UnauthorizedTableBigDeleteException($aclErrorPrefix . ' forbidden to hard delete on table `' . $this->table . '` because it has status column.'); } /** * Enforce Privilege: "Little" Delete (I am the record CMS owner) */ if ($isCurrentUserOwner && !$canDelete) { $recordPk = self::stringifyPrimaryKeyForRecordDebugRepresentation($this->primaryKeyData); $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); throw new UnauthorizedTableDeleteException($aclErrorPrefix . 'Table harddelete access forbidden on `' . $this->table . '` table record with ' . $recordPk . ' owned by the authenticated CMS user (#' . $cmsOwnerId . ').'); } elseif (!$isCurrentUserOwner && !$canBigDelete) { /** * Enforce Privilege: "Big" Delete (I am not the record CMS owner) */ $recordPk = self::stringifyPrimaryKeyForRecordDebugRepresentation($this->primaryKeyData); $recordOwner = false === $cmsOwnerId ? 'no magic owner column' : 'the CMS owner #' . $cmsOwnerId; $aclErrorPrefix = $this->acl->getErrorMessagePrefix(); throw new UnauthorizedTableBigDeleteException($aclErrorPrefix . 'Table bigharddelete access forbidden on `' . $this->table . '` table record with $recordPk and ' . $recordOwner . '.'); } return parent::delete(); }
public function constructPreferences($user_id, $table, $preferences = null, $title = null) { if ($preferences) { $newPreferencesData = false; // @todo enforce non-empty set if (empty($preferences['columns_visible'])) { $newPreferencesData = true; $columns_visible = TableSchema::getTableColumns($table, 6); $preferences['columns_visible'] = implode(',', $columns_visible); } $preferencesDefaultsApplied = $this->applyDefaultPreferences($table, $preferences); if (count(array_diff($preferences, $preferencesDefaultsApplied))) { $newPreferencesData = true; } $preferences = $preferencesDefaultsApplied; if ($newPreferencesData) { $id = $this->addOrUpdateRecordByArray($preferences); } return $preferences; } $insert = new Insert($this->table); // User doesn't have any preferences for this table yet. Please create! $columns_visible = TableSchema::getTableColumns($table, 6); $data = array('user' => $user_id, 'columns_visible' => implode(',', $columns_visible), 'table_name' => $table, 'title' => $title); if (TableSchema::hasTableColumn($table, 'sort')) { $data['sort'] = 'sort'; } $data = $this->applyDefaultPreferences($table, $data); $insert->values($data); $this->insertWith($insert); return $data; }