public function fetchFeed($params = null) { $sql = new Sql($this->adapter); $select = $sql->select()->from($this->table); $params['orderColumn'] = 'id'; $params['orderDirection'] = 'DESC'; $tableSchemaArray = TableSchema::getSchemaArray($this->table); $hasActiveColumn = $this->schemaHasActiveColumn($tableSchemaArray); $params = $this->applyDefaultEntriesSelectParams($params); $columns = array('id', 'identifier', 'action', 'table_name', 'row_id', 'user', 'datetime', 'type', 'data'); $select->columns($columns); // ->order('id DESC'); $select->where->nest->isNull('parent_id')->OR->equalTo('type', 'FILES')->unnest; $select = $this->applyParamsToTableEntriesSelect($params, $select, $tableSchemaArray, $hasActiveColumn); //die($this->dumpSql($select)); $rowset = $this->selectWith($select); $rowset = $rowset->toArray(); foreach ($rowset as &$row) { $row['datetime'] .= ' UTC'; } $countTotalWhere = new Where(); $countTotalWhere->isNull('parent_id')->OR->equalTo('type', 'FILES'); $activityTotal = $this->countTotal($countTotalWhere); return array('total' => $activityTotal, 'rows' => $rowset); }
public function fetchFeed($params = null) { $sql = new Sql($this->adapter); $select = $sql->select()->from($this->table); $params['orderColumn'] = 'id'; $params['orderDirection'] = 'DESC'; $tableSchemaArray = TableSchema::getSchemaArray($this->table); $hasActiveColumn = $this->schemaHasActiveColumn($tableSchemaArray); $params = $this->applyDefaultEntriesSelectParams($params); $columns = ['id', 'identifier', 'action', 'table_name', 'row_id', 'user', 'datetime', 'type', 'data']; $select->columns($columns); // ->order('id DESC'); $select->where->nest->isNull('parent_id')->OR->equalTo('type', 'FILES')->unnest; $select = $this->applyParamsToTableEntriesSelect($params, $select, $tableSchemaArray, $hasActiveColumn); //die($this->dumpSql($select)); $rowset = $this->selectWith($select); $rowset = $rowset->toArray(); $rowset = $this->convertDates($rowset, $tableSchemaArray); // @TODO: Returns date in ISO 8601 Ex: 2016-06-06T17:18:20Z // see: https://en.wikipedia.org/wiki/ISO_8601 // foreach ($rowset as &$row) { // $row['datetime'] .= ' UTC'; // } $countTotalWhere = new Where(); $countTotalWhere->isNull('parent_id')->OR->equalTo('type', 'FILES'); $activityTotal = $this->countTotal($countTotalWhere); return ['total' => $activityTotal, 'rows' => $rowset]; }
public function toArrayWithImmediateRelationships(RelationalTableGateway $TableGateway) { if ($this->table !== $TableGateway->getTable()) { throw new \InvalidArgumentException('The table of the gateway parameter must match this row\'s table.'); } $entry = $this->toArray(); $schemaArray = TableSchema::getSchemaArray($this->table); $aliasColumns = $TableGateway->filterSchemaAliasFields($schemaArray); // Many-to-One list($entry) = $TableGateway->loadManyToOneRelationships($schemaArray, [$entry]); // One-to-Many, Many-to-Many $entry = $TableGateway->loadToManyRelationships($entry, $aliasColumns); return $entry; }
/** * @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; } }
/** * Fetch related, foreign rows for one record's ManyToMany relationships. * @param string $table_name * @param string $foreign_table * @param string $junction_table * @param string $junction_key_left * @param string $junction_key_right * @param string $column_equals * @return array Foreign rowset */ public function loadManyToManyRelationships($table_name, $foreign_table, $junction_table, $junction_key_left, $junction_key_right, $column_equals) { $foreign_table_pk = TableSchema::getTablePrimaryKey($foreign_table); $foreign_join_column = "{$foreign_table}.{$foreign_table_pk}"; $junction_join_column = "{$junction_table}.{$junction_key_right}"; $junction_comparison_column = "{$junction_table}.{$junction_key_left}"; $junction_table_pk = TableSchema::getTablePrimaryKey($junction_table); $junction_id_column = "{$junction_table}." . $junction_table_pk; // Less likely name collision: $junction_id_column_alias = "directus_junction_id_column_518d31856e131"; $junction_sort_column_alias = "directus_junction_sort_column_518d318e3f0f5"; $junctionSelectColumns = array($junction_id_column_alias => $junction_table_pk); $sql = new Sql($this->adapter); $select = $sql->select(); // If the Junction Table has a Sort column, do eet. // @todo is this the most efficient way? // @hint TableSchema#getUniqueColumnName $junctionColumns = TableSchema::getAllNonAliasTableColumnNames($junction_table); if (in_array('sort', $junctionColumns)) { $junctionSelectColumns[$junction_sort_column_alias] = "sort"; $select->order($junction_sort_column_alias); } $select->from($foreign_table)->join($junction_table, "{$foreign_join_column} = {$junction_join_column}", $junctionSelectColumns)->where(array($junction_comparison_column => $column_equals))->order("{$junction_id_column} ASC"); // Only select the fields not on the currently authenticated user group's read field blacklist $columns = TableSchema::getAllNonAliasTableColumnNames($foreign_table); $select->columns($columns); $ForeignTable = new RelationalTableGateway($this->acl, $foreign_table, $this->adapter); $results = $ForeignTable->selectWith($select); $results = $results->toArray(); $foreign_data = array(); $columns = TableSchema::getAllNonAliasTableColumns($foreign_table); foreach ($results as $row) { $row = $this->parseRecordValuesByMysqlType($row, $columns); $junction_table_id = (int) $row[$junction_id_column_alias]; unset($row[$junction_id_column_alias]); $entry = array($junction_table_pk => $junction_table_id); if (in_array('sort', $junctionColumns)) { // @TODO: check why is this a string instead of an integer. $entry['sort'] = (int) $row[$junction_sort_column_alias]; unset($row[$junction_sort_column_alias]); } $entry['data'] = $row; $foreign_data[] = $entry; } return array('rows' => $foreign_data); }
$TableGateway->update($table_settings, array('table_name' => $table)); } else { $TableGateway->insert($table_settings); } $column_settings = array(); foreach ($data['columns'] as $col) { $columnData = array('table_name' => $table, 'column_name' => $col['column_name'], 'ui' => $col['ui'], 'hidden_input' => $col['hidden_input'], 'required' => $col['required'], 'master' => $col['master'], 'sort' => array_key_exists('sort', $col) ? $col['sort'] : 99999, 'comment' => array_key_exists('comment', $col) ? $col['comment'] : ''); $existing = $ColumnsTableGateway->select(array('table_name' => $table, 'column_name' => $col['column_name']))->toArray(); if (count($existing) > 0) { $columnData['id'] = $existing[0]['id']; } array_push($column_settings, $columnData); } $ColumnsTableGateway->updateCollection($column_settings); } $response = TableSchema::getTable($table); JsonView::render($response); })->via('GET', 'PUT')->name('table_meta'); /** * UPLOAD COLLECTION */ $app->post("/{$v}/upload/?", function () use($params, $requestPayload, $app, $acl, $ZendDb) { // $Transfer = new Files\Transfer(); // $Storage = new Files\Storage\Storage(); $Files = new Directus\Files\Files(); $result = []; foreach ($_FILES as $file) { $result[] = $Files->upload($file); } JsonView::render($result); });
/** * Remove Directus-managed virtual/alias fields from the table schema array * and return them as a separate array. * @param array $schema Table schema array. * @return array Alias fields */ public function filterSchemaAliasFields(&$schema) { $alias_fields = []; foreach ($schema as $i => $col) { // Is it a "virtual"/alias column? if (TableSchema::isColumnAnAlias($col)) { // Remove them from the standard schema unset($schema[$i]); $alias_fields[] = $col; } } return $alias_fields; }
public static function getAllSchemas($userGroupId, $versionHash) { $cacheKey = MemcacheProvider::getKeyDirectusGroupSchema($userGroupId, $versionHash); $acl = Bootstrap::get('acl'); $ZendDb = Bootstrap::get('ZendDb'); $directusPreferencesTableGateway = new DirectusPreferencesTableGateway($acl, $ZendDb); $getPreferencesFn = function () use($directusPreferencesTableGateway) { $currentUser = Auth::getUserInfo(); $preferences = $directusPreferencesTableGateway->fetchAllByUser($currentUser['id']); return $preferences; }; $getSchemasFn = function () { $tableSchemas = TableSchema::getTableSchemas(); $columnSchemas = TableSchema::getColumnSchemas(); // Nest column schemas in table schemas foreach ($tableSchemas as &$table) { $tableName = $table['id']; $table['columns'] = array_values($columnSchemas[$tableName]); foreach ($columnSchemas[$tableName] as $column) { if ($column['column_key'] == 'PRI') { $table['primary_column'] = $column['column_name']; break; } } $table = array('schema' => $table); } return $tableSchemas; }; // 3 hr cache $schemas = $directusPreferencesTableGateway->memcache->getOrCache($cacheKey, $getSchemasFn, 10800); // Append preferences post cache $preferences = $getPreferencesFn(); foreach ($schemas as &$table) { $table['preferences'] = $preferences[$table['schema']['id']]; } return $schemas; }
public function applyParamsToTableEntriesSelect(array $params, Select $select, array $schema, $hasActiveColumn = false) { $tableName = $this->getTable(); if (isset($params['group_by'])) { $select->group($tableName . '.' . $params['group_by']); } else { $select->group($tableName . '.' . $this->primaryKeyFieldName); } //If this is a relational order, than it is an array. if (is_array($params['orderBy'])) { $select->join(array('jsort' => $params['orderBy']['junction_table']), 'jsort.' . $params['orderBy']['jkeyRight'] . ' = ' . $tableName . '.' . $this->primaryKeyFieldName, array(), $select::JOIN_LEFT); $select->join(array('rsort' => $params['orderBy']['related_table']), 'rsort.id = jsort.' . $params['orderBy']['jkeyLeft'], array(), $select::JOIN_LEFT); $select->order('rsort.title', $params['orderDirection']); } else { $select->order(implode(' ', array($params['orderBy'], $params['orderDirection']))); } if (isset($params['perPage']) && isset($params['currentPage'])) { $select->limit($params['perPage'])->offset($params['currentPage'] * $params['perPage']); } // Are we sorting on a relationship? foreach ($schema as $column) { if ($column['column_name'] != $params['orderBy']) { continue; } // Must have defined table_related if (!isset($column['relationship']) || !is_array($column['relationship']) || !isset($column['relationship']['table_related'])) { break; } // Must have defined visible_column if (!isset($column['options']) || !is_array($column['options']) || !isset($column['options']['visible_column'])) { break; } $relatedTable = $column['relationship']['table_related']; $visibleColumn = $column['options']['visible_column']; $keyLeft = $params['table_name'] . "." . $params['orderBy']; // @todo it's wrong to assume PKs are "id" but this is currently endemic to directus6 $keyRight = $relatedTable . ".id"; $joinedSortColumn = $relatedTable . "." . $visibleColumn; $select->reset(Select::ORDER)->join($relatedTable, "{$keyLeft} = {$keyRight}", array(), Select::JOIN_LEFT)->order("{$joinedSortColumn} " . $params['orderDirection']); break; } // Note: be sure to explicitly check for null, because the value may be // '0' or 0, which is meaningful. if (null !== $params[STATUS_COLUMN_NAME] && $hasActiveColumn) { $haystack = is_array($params[STATUS_COLUMN_NAME]) ? $params[STATUS_COLUMN_NAME] : explode(",", $params[STATUS_COLUMN_NAME]); if (!isset($params['table_name']) || empty($params['table_name'])) { $tableName = $this->getTable(); } else { $tableName = $params['table_name']; } $select->where->in($tableName . '.' . STATUS_COLUMN_NAME, $haystack); } // Select only ids from the ids if provided if (array_key_exists('ids', $params)) { $entriesIds = array_filter(explode(',', $params['ids']), 'is_numeric'); if (count($entriesIds) > 0) { $select->where->in($this->getTable() . '.' . $this->primaryKeyFieldName, $entriesIds); } } // Where $select->where->nest->expression('-1 = ?', $params[$this->primaryKeyFieldName])->or->equalTo($tableName . '.' . $this->primaryKeyFieldName, $params[$this->primaryKeyFieldName])->unnest; // very very rudimentary ability to supply where conditions to fetch... // at the moment, only 'equalTo' and 'between' are supported... also, the 'total' key returned // in the json does not reflect these filters... // -MG if (array_key_exists('where', $params)) { $outer = $select->where->nest; foreach ($params['where'] as $whereCond) { $type = $whereCond['type']; $column = $whereCond['column']; if ($type == 'equalTo') { $val = $whereCond['val']; if (is_array($val)) { $where = $select->where->nest; foreach ($val as $currentval) { $where->equalTo($column, $currentval); if ($currentval != end($val)) { $where->or; } } $where->unnest; } else { $outer->equalTo($column, $val); } } else { if ($type == 'between') { $val1 = $whereCond['val1']; $val2 = $whereCond['val2']; $outer->between($column, $val1, $val2); } } } $outer->unnest; } //@TODO: Make this better if (isset($params['adv_where'])) { $select->where($params['adv_where']); } if (isset($params['adv_search']) && !empty($params['adv_search'])) { $i = 0; foreach ($params['adv_search'] as $search_col) { $target = array(); foreach ($schema as $col) { if ($col['id'] == $search_col['id']) { $target = $col; break; } } if (empty($target)) { continue; } // TODO: fix this, it must be refactored if (isset($target['relationship']) && $target['relationship']['type'] == "MANYTOMANY") { $relatedTable = $target['relationship']['table_related']; $relatedAliasName = $relatedTable . "_" . $i; if ($target['relationship']['type'] == "MANYTOMANY") { $junctionTable = $target['relationship']['junction_table']; $jkl = $target['relationship']['junction_key_left']; $jkr = $target['relationship']['junction_key_right']; $keyleft = $params['table_name'] . ".id"; $keyRight = $junctionTable . '.' . $jkl; $jkeyleft = $junctionTable . '.' . $jkr; $jkeyright = $relatedAliasName . ".id"; $select->join($junctionTable, "{$keyleft} = {$keyRight}", array(), Select::JOIN_INNER); } else { $select->join(array($relatedAliasName => $relatedTable), $tableName . '.' . $target['column_name'] . " = " . $relatedAliasName . ".id", array(), Select::JOIN_INNER); } $relatedTableMetadata = TableSchema::getSchemaArray($relatedTable); if ($search_col['type'] == "like") { $select->join(array($relatedAliasName => $relatedTable), "{$jkeyleft} = {$jkeyright}", array(), Select::JOIN_INNER); $search_col['value'] = "%" . $search_col['value'] . "%"; if (isset($target['options']['filter_column'])) { $targetCol = $target['options']['filter_column']; } else { $targetCol = $target['options']['visible_column']; } foreach ($relatedTableMetadata as $col) { if ($col['id'] == $targetCol) { if ($col['type'] == 'VARCHAR' || $col['type'] == 'INT') { $where = $select->where->nest; $columnName = $this->adapter->platform->quoteIdentifier($col['column_name']); $columnName = $relatedAliasName . "." . $columnName; $like = new Predicate\Expression("LOWER({$columnName}) LIKE ?", $search_col['value']); $where->addPredicate($like, Predicate\Predicate::OP_OR); $where->unnest; } } } } else { $select->where($jkeyleft . ' = ' . $this->adapter->platform->quoteValue($search_col['value'])); } } elseif (isset($target['relationship']) && $target['relationship']['type'] == "MANYTOONE") { $relatedTable = $target['relationship']['table_related']; $keyLeft = $this->getTable() . "." . $target['relationship']['junction_key_left']; $keyRight = $relatedTable . ".id"; $filterColumn = $target['options']['filter_column']; $joinedFilterColumn = $relatedTable . "." . $filterColumn; // do not let join this table twice // TODO: do a extra checking in case it's being used twice // and none for sorting if ($target['column_name'] != $params['orderBy']) { $select->join($relatedTable, "{$keyLeft} = {$keyRight}", array(), Select::JOIN_LEFT); } if ($search_col['type'] == 'like') { $searchLike = '%' . $search_col['value'] . '%'; $spec = function (Where $where) use($joinedFilterColumn, $searchLike) { $where->like($joinedFilterColumn, $searchLike); }; $select->where($spec); } else { $select->where($search_col['id'] . " " . $search_col['type'] . " " . $this->adapter->platform->quoteValue($search_col['value'])); } } else { if ($target['type'] == "DATETIME" && strpos($search_col['value'], " ") == false) { $select->where('date(' . $tableName . '.' . $search_col['id'] . ") = " . $this->adapter->platform->quoteValue($search_col['value'])); } else { if ($search_col['type'] == "like") { $select->where($tableName . '.' . $search_col['id'] . " " . $search_col['type'] . " " . $this->adapter->platform->quoteValue("%" . $search_col['value'] . "%")); } else { $select->where($tableName . '.' . $search_col['id'] . " " . $search_col['type'] . " " . $this->adapter->platform->quoteValue($search_col['value'])); } } } $i++; } } else { if (isset($params['search']) && !empty($params['search'])) { $params['search'] = "%" . $params['search'] . "%"; $where = $select->where->nest; foreach ($schema as $col) { if ($col['type'] == 'VARCHAR' || $col['type'] == 'INT') { $columnName = $this->adapter->platform->quoteIdentifier($col['column_name']); $like = new Predicate\Expression("LOWER({$columnName}) LIKE ?", strtolower($params['search'])); $where->addPredicate($like, Predicate\Predicate::OP_OR); } } $where->unnest; } } return $select; }
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(); }
if (!$isHttpsFn()) { $host = 'https://' . $_SERVER['SERVER_NAME']; if ('80' != $_SERVER['SERVER_PORT']) { $host .= ":" . $_SERVER['SERVER_PORT']; } $httpsUrl = $host . $_SERVER['REQUEST_URI']; header('Location: ' . $httpsUrl); exit; } } $users = getUsers(); $currentUserInfo = getCurrentUserInfo($users); // Cache buster $git = __DIR__ . '/.git'; $cacheBuster = Directus\Util\Git::getCloneHash($git); $tableSchema = TableSchema::getAllSchemas($currentUserInfo['group']['id'], $cacheBuster); // $tabPrivileges = getTabPrivileges(($currentUserInfo['group']['id'])); $groupId = $currentUserInfo['group']['id']; $groups = getGroups(); $currentUserGroup = array(); if (isset($groups['rows']) && count($groups['rows'] > 0)) { foreach ($groups['rows'] as $group) { if ($group['id'] === $groupId) { $currentUserGroup = $group; break; } } } $statusMapping = array('active_num' => STATUS_ACTIVE_NUM, 'deleted_num' => STATUS_DELETED_NUM, 'status_name' => STATUS_COLUMN_NAME); $statusMapping['mapping'] = $config['statusMapping']; $data = array('cacheBuster' => $cacheBuster, 'nonces' => getNonces(), 'storage_adapters' => getStorageAdapters(), 'path' => DIRECTUS_PATH, 'page' => '#tables', 'tables' => parseTables($tableSchema), 'preferences' => parsePreferences($tableSchema), 'users' => $users, 'groups' => $groups, 'settings' => getSettings(), 'active_files' => getActiveFiles(), 'authenticatedUser' => $authenticatedUser, 'extensions' => getExtensions($currentUserGroup), 'privileges' => getPrivileges($groupId), 'ui' => getUI(), 'listViews' => getListViews(), 'messages' => getInbox(), 'bookmarks' => getBookmarks(), 'extendedUserColumns' => getExtendedUserColumns($tableSchema), 'statusMapping' => $statusMapping);
public function fetchAllByUser($user_id, $assoc = false) { $select = new Select($this->table); $select->columns(array('id', 'user', 'table_name', 'columns_visible', 'sort', 'sort_order', STATUS_COLUMN_NAME, 'title', 'search_string')); $select->where->equalTo('user', $user_id)->isNull('title'); $select->where('table_name NOT IN( "directus_columns", "directus_ip_whitelist", "directus_preferences", "directus_privileges", "directus_settings", "directus_storage_adapters", "directus_tables", "directus_tab_privileges", "directus_ui" )'); $metadata = new \Zend\Db\Metadata\Metadata($this->getAdapter()); $tables = $metadata->getTableNames(DB_NAME); $tables = array_diff($tables, array("directus_columns", "directus_ip_whitelist", "directus_preferences", "directus_privileges", "directus_settings", "directus_storage_adapters", "directus_tables", "directus_tab_privileges", "directus_ui")); $rows = $this->selectWith($select)->toArray(); $preferences = array(); $tablePrefs = array(); foreach ($rows as $row) { $tablePrefs[$row['table_name']] = $row; } //Get Default Preferences foreach ($tables as $key => $table) { // Honor ACL. Skip the tables that the user doesn't have access too if (!TableSchema::canGroupViewTable($table)) { continue; } $tableName = $table; if (!isset($tablePrefs[$table])) { $table = null; } else { $table = $tablePrefs[$table]; } if (!isset($table['user'])) { $table = null; } $table = $this->constructPreferences($user_id, $tableName, $table); $preferences[$tableName] = $table; } return $preferences; }
public function fetchPerTable($groupId) { // Don't include tables that can't have privileges changed /*$blacklist = array( 'directus_columns', 'directus_ip_whitelist', 'directus_messages_recipients', 'directus_preferences', 'directus_privileges', 'directus_settings', 'directus_social_feeds', 'directus_social_posts', 'directus_storage_adapters', 'directus_tab_privileges', 'directus_tables', 'directus_ui', 'directus_users_copy' );*/ $blacklist = array(); $select = new Select($this->table); $select->where->equalTo('group_id', $groupId); $select->group(array('group_id', 'table_name', 'status_id')); $rowset = $this->selectWith($select); $rowset = $rowset->toArray(); $tableSchema = new TableSchema(); $tables = $tableSchema->getTablenames(); $privileges = array(); $privilegesHash = array(); foreach ($rowset as $item) { if (in_array($item['table_name'], $blacklist)) { continue; } $privilegesHash[$item['table_name']] = $item; $privileges[] = $item; } foreach ($tables as $table) { if (in_array($table, $blacklist)) { continue; } if (array_key_exists($table, $privilegesHash)) { continue; } $item = array('table_name' => $table, 'group_id' => $groupId, 'status_id' => null); $privileges[] = $item; } // sort ascending usort($privileges, function ($a, $b) { return strcmp($a['table_name'], $b['table_name']); }); return $privileges; }
protected function parseRecord($records, $tableName = null) { if (is_array($records)) { $tableName = $tableName === null ? $this->table : $tableName; $records = $this->parseRecordValuesByType($records, $tableName); $columns = TableSchema::getAllNonAliasTableColumns($tableName); $records = $this->convertDates($records, $columns, $tableName); } return $records; }
public function fetchAllByUser($user_id, $assoc = false) { $select = new Select($this->table); $select->columns(['id', 'user', 'table_name', 'columns_visible', 'sort', 'sort_order', 'status', 'title', 'search_string']); $select->where->equalTo('user', $user_id)->isNull('title'); $coreTables = SchemaManager::getDirectusTables(static::$IGNORED_TABLES); $select->where->addPredicate(new NotIn('table_name', $coreTables)); $metadata = new \Zend\Db\Metadata\Metadata($this->getAdapter()); $tables = $metadata->getTableNames(); $tables = array_diff($tables, $coreTables); $rows = $this->selectWith($select)->toArray(); $preferences = []; $tablePrefs = []; foreach ($rows as $row) { $tablePrefs[$row['table_name']] = $row; } //Get Default Preferences foreach ($tables as $key => $table) { // Honor ACL. Skip the tables that the user doesn't have access too if (!TableSchema::canGroupViewTable($table)) { continue; } $tableName = $table; if (!isset($tablePrefs[$table])) { $table = null; } else { $table = $tablePrefs[$table]; } if (!isset($table['user'])) { $table = null; } $table = $this->constructPreferences($user_id, $tableName, $table); $preferences[$tableName] = $table; } return $preferences; }
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(); }