Beispiel #1
0
 /**
  * @covers Zend\Db\Sql\Update::getRawState
  */
 public function testGetRawState()
 {
     $this->update->table('foo')->set(array('bar' => 'baz'))->where('x = y');
     $this->assertEquals('foo', $this->update->getRawState('table'));
     $this->assertEquals(true, $this->update->getRawState('emptyWhereProtection'));
     $this->assertEquals(array('bar' => 'baz'), $this->update->getRawState('set'));
     $this->assertInstanceOf('Zend\\Db\\Sql\\Where', $this->update->getRawState('where'));
 }
 /**
  * @param Update $update
  */
 public function preUpdate(Update $update)
 {
     $metaColumns = $this->tableGateway->getColumns();
     if (count($metaColumns)) {
         $metaColumns = array_flip($metaColumns);
         $set = $update->getRawState('set');
         $set = array_intersect_key($set, $metaColumns);
         $update->set($set);
     }
 }
 /**
  * @param Update $update
  * @return mixed
  * @throws Exception\RuntimeException
  * @throws \Directus\Acl\Exception\UnauthorizedFieldWriteException
  * @throws \Directus\Acl\Exception\UnauthorizedTableBigEditException
  * @throws \Directus\Acl\Exception\UnauthorizedTableEditException
  */
 protected function executeUpdate(Update $update)
 {
     $currentUserId = null;
     if (Auth::loggedIn()) {
         $currentUser = Auth::getUserInfo();
         $currentUserId = intval($currentUser['id']);
     }
     $updateState = $update->getRawState();
     $updateTable = $this->getRawTableNameFromQueryStateTable($updateState['table']);
     $cmsOwnerColumn = $this->acl->getCmsOwnerColumnByTable($updateTable);
     /**
      * ACL Enforcement
      */
     // check if it's NOT soft delete
     $updateFields = $updateState['set'];
     if (!(count($updateFields) == 2 && array_key_exists(STATUS_COLUMN_NAME, $updateFields) && $updateFields[STATUS_COLUMN_NAME] == STATUS_DELETED_NUM)) {
         if (!$this->acl->hasTablePrivilege($updateTable, 'bigedit')) {
             // Parsing for the column name is unnecessary. Zend enforces raw column names.
             /**
              * Enforce Privilege: "Big" Edit
              */
             if (false === $cmsOwnerColumn) {
                 // All edits are "big" edits if there is no magic owner column.
                 $aclErrorPrefix = $this->acl->getErrorMessagePrefix();
                 throw new UnauthorizedTableBigEditException($aclErrorPrefix . "The table `{$updateTable}` is missing the `user_create_column` within `directus_tables` (BigEdit Permission Forbidden)");
             } else {
                 // Who are the owners of these rows?
                 list($resultQty, $ownerIds) = $this->acl->getCmsOwnerIdsByTableGatewayAndPredicate($this, $updateState['where']);
                 // Enforce
                 if (is_null($currentUserId) || count(array_diff($ownerIds, array($currentUserId)))) {
                     $aclErrorPrefix = $this->acl->getErrorMessagePrefix();
                     throw new UnauthorizedTableBigEditException($aclErrorPrefix . "Table bigedit access forbidden on {$resultQty} `{$updateTable}` table record(s) and " . count($ownerIds) . " CMS owner(s) (with ids " . implode(", ", $ownerIds) . ").");
                 }
             }
             /**
              * Enforce write field blacklist (if user lacks bigedit privileges on this table)
              */
             $attemptOffsets = array_keys($updateState['set']);
             $this->acl->enforceBlacklist($updateTable, $attemptOffsets, Acl::FIELD_WRITE_BLACKLIST);
         }
         if (!$this->acl->hasTablePrivilege($updateTable, 'edit')) {
             /**
              * Enforce Privilege: "Little" Edit (I am the record CMS owner)
              */
             if (false !== $cmsOwnerColumn) {
                 if (!isset($predicateResultQty)) {
                     // Who are the owners of these rows?
                     list($predicateResultQty, $predicateOwnerIds) = $this->acl->getCmsOwnerIdsByTableGatewayAndPredicate($this, $updateState['where']);
                 }
                 if (in_array($currentUserId, $predicateOwnerIds)) {
                     $aclErrorPrefix = $this->acl->getErrorMessagePrefix();
                     throw new UnauthorizedTableEditException($aclErrorPrefix . "Table edit access forbidden on {$predicateResultQty} `{$updateTable}` table records owned by the authenticated CMS user (#{$currentUserId}).");
                 }
             }
         }
     }
     try {
         return parent::executeUpdate($update);
     } catch (\Zend\Db\Adapter\Exception\InvalidQueryException $e) {
         if ('production' !== DIRECTUS_ENV) {
             // @TODO: these lines are the same as the executeInsert,
             // let's put it together
             if (strpos(strtolower($e->getMessage()), 'duplicate entry') !== FALSE) {
                 throw new DuplicateEntryException($e->getMessage());
             }
             throw new \RuntimeException("This query failed: " . $this->dumpSql($update), 0, $e);
         }
         // @todo send developer warning
         throw $e;
     }
 }
 /**
  * @todo add $columns support
  *
  * @param Update $update
  * @return mixed
  * @throws Exception\RuntimeException
  */
 protected function executeUpdate(Update $update)
 {
     $updateState = $update->getRawState();
     if ($updateState['table'] != $this->table) {
         throw new Exception\RuntimeException('The table name of the provided Update object must match that of the table');
     }
     // apply preUpdate features
     $this->featureSet->apply('preUpdate', array($update));
     $statement = $this->sql->prepareStatementForSqlObject($update);
     $result = $statement->execute();
     // apply postUpdate features
     $this->featureSet->apply('postUpdate', array($statement, $result));
     return $result->getAffectedRows();
 }
 /**
  * @todo add $columns support
  *
  * @param Update $update
  * @return int
  * @throws Exception\RuntimeException
  */
 protected function executeUpdate(Update $update)
 {
     $updateState = $update->getRawState();
     if ($updateState['table'] != $this->table) {
         throw new Exception\RuntimeException('The table name of the provided Update object must match that of the table');
     }
     // apply preUpdate features
     $this->featureSet->apply(EventFeatureEventsInterface::EVENT_PRE_UPDATE, [$update]);
     $unaliasedTable = false;
     if (is_array($updateState['table'])) {
         $tableData = array_values($updateState['table']);
         $unaliasedTable = array_shift($tableData);
         $update->table($unaliasedTable);
     }
     $statement = $this->sql->prepareStatementForSqlObject($update);
     $result = $statement->execute();
     // apply postUpdate features
     $this->featureSet->apply(EventFeatureEventsInterface::EVENT_POST_UPDATE, [$statement, $result]);
     // Reset original table information in Update instance, if necessary
     if ($unaliasedTable) {
         $update->table($updateState['table']);
     }
     return $result->getAffectedRows();
 }
 /**
  * @todo add $columns support
  *
  * @param Update $update
  * @return mixed
  * @throws Exception\RuntimeException
  */
 protected function executeUpdate(Update $update)
 {
     $updateState = $update->getRawState();
     if ($updateState['table'] != $this->table) {
         throw new Exception\RuntimeException('The table name of the provided Update object must match that of the table');
     }
     // apply preUpdate features
     $this->featureSet->apply(EventFeatureEventsInterface::EVENT_PRE_UPDATE, [$update]);
     $statement = $this->sql->prepareStatementForSqlObject($update);
     $result = $statement->execute();
     // apply postUpdate features
     $this->featureSet->apply(EventFeatureEventsInterface::EVENT_POST_UPDATE, [$statement, $result]);
     return $result->getAffectedRows();
 }
Beispiel #7
0
 public function getRawState($key = null)
 {
     $rawState = parent::getRawState();
     $rawState['option'] = $this->option;
     return isset($key) && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState;
 }
 /**
  * @param Update $update
  * @return mixed
  * @throws Exception\RuntimeException
  * @throws \Directus\Acl\Exception\UnauthorizedFieldWriteException
  * @throws \Directus\Acl\Exception\UnauthorizedTableBigEditException
  * @throws \Directus\Acl\Exception\UnauthorizedTableEditException
  */
 protected function executeUpdate(Update $update)
 {
     $currentUserId = null;
     if (Auth::loggedIn()) {
         $currentUser = Auth::getUserInfo();
         $currentUserId = intval($currentUser['id']);
     }
     $updateState = $update->getRawState();
     $updateTable = $this->getRawTableNameFromQueryStateTable($updateState['table']);
     $cmsOwnerColumn = $this->acl->getCmsOwnerColumnByTable($updateTable);
     $updateData = $updateState['set'];
     /**
      * ACL Enforcement
      */
     // check if it's NOT soft delete
     $updateFields = $updateState['set'];
     $permissionName = 'edit';
     $hasStatusColumn = array_key_exists(STATUS_COLUMN_NAME, $updateFields) ? true : false;
     if ($hasStatusColumn && $updateFields[STATUS_COLUMN_NAME] == STATUS_DELETED_NUM) {
         $permissionName = 'delete';
     }
     if (!$this->acl->hasTablePrivilege($updateTable, 'big' . $permissionName)) {
         // Parsing for the column name is unnecessary. Zend enforces raw column names.
         /**
          * Enforce Privilege: "Big" Edit
          */
         if (false === $cmsOwnerColumn) {
             // All edits are "big" edits if there is no magic owner column.
             $aclErrorPrefix = $this->acl->getErrorMessagePrefix();
             throw new UnauthorizedTableBigEditException($aclErrorPrefix . 'The table `' . $updateTable . '` is missing the `user_create_column` within `directus_tables` (BigEdit Permission Forbidden)');
         } else {
             // Who are the owners of these rows?
             list($resultQty, $ownerIds) = $this->acl->getCmsOwnerIdsByTableGatewayAndPredicate($this, $updateState['where']);
             // Enforce
             if (is_null($currentUserId) || count(array_diff($ownerIds, [$currentUserId]))) {
                 // $aclErrorPrefix = $this->acl->getErrorMessagePrefix();
                 // throw new UnauthorizedTableBigEditException($aclErrorPrefix . "Table bigedit access forbidden on $resultQty `$updateTable` table record(s) and " . count($ownerIds) . " CMS owner(s) (with ids " . implode(", ", $ownerIds) . ").");
                 $groupsTableGateway = self::makeTableGatewayFromTableName($this->acl, 'directus_groups', $this->adapter);
                 $group = $groupsTableGateway->find($this->acl->getGroupId());
                 throw new UnauthorizedTableBigEditException('[' . $group['name'] . '] permissions only allow you to [' . $permissionName . '] your own items.');
             }
         }
     }
     if (!$this->acl->hasTablePrivilege($updateTable, $permissionName)) {
         /**
          * Enforce Privilege: "Little" Edit (I am the record CMS owner)
          */
         if (false !== $cmsOwnerColumn) {
             if (!isset($predicateResultQty)) {
                 // Who are the owners of these rows?
                 list($predicateResultQty, $predicateOwnerIds) = $this->acl->getCmsOwnerIdsByTableGatewayAndPredicate($this, $updateState['where']);
             }
             if (in_array($currentUserId, $predicateOwnerIds)) {
                 $aclErrorPrefix = $this->acl->getErrorMessagePrefix();
                 throw new UnauthorizedTableEditException($aclErrorPrefix . 'Table edit access forbidden on ' . $predicateResultQty . '`' . $updateTable . '` table records owned by the authenticated CMS user (#' . $currentUserId . '.');
             }
         }
     }
     // Enforce write field blacklist
     $attemptOffsets = array_keys($updateState['set']);
     $this->acl->enforceBlacklist($updateTable, $attemptOffsets, Acl::FIELD_WRITE_BLACKLIST);
     try {
         $this->emitter->run('table.update:before', [$updateTable, $updateData]);
         $this->emitter->run('table.update.' . $updateTable . ':before', [$updateData]);
         $result = parent::executeUpdate($update);
         $this->emitter->run('table.update', [$updateTable, $updateData]);
         $this->emitter->run('table.update:after', [$updateTable, $updateData]);
         $this->emitter->run('table.update.' . $updateTable, [$updateData]);
         $this->emitter->run('table.update.' . $updateTable . ':after', [$updateData]);
         return $result;
     } catch (\Zend\Db\Adapter\Exception\InvalidQueryException $e) {
         // @TODO: these lines are the same as the executeInsert,
         // let's put it together
         if (strpos(strtolower($e->getMessage()), 'duplicate entry') !== FALSE) {
             throw new DuplicateEntryException($e->getMessage());
         }
         if ('production' !== DIRECTUS_ENV) {
             throw new \RuntimeException('This query failed: ' . $this->dumpSql($update), 0, $e);
         }
         // @todo send developer warning
         throw $e;
     }
 }