/**
  * @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;
     }
 }
Example #2
0
 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();
 }
Example #3
0
 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;
 }