Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Commit

Permalink
v2.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
rijkvanzanten committed May 21, 2019
1 parent d2b417e commit cb8ab58
Show file tree
Hide file tree
Showing 91 changed files with 2,498 additions and 280 deletions.
2 changes: 1 addition & 1 deletion src/core/Directus/Application/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Application extends App
*
* @var string
*/
const DIRECTUS_VERSION = '2.0.23';
const DIRECTUS_VERSION = '2.1.0';

/**
* NOT USED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class CorsMiddleware extends AbstractMiddleware
'Authorization',
],
'exposed_headers' => [],
'max_age' => null,
'max_age' => 500,
'credentials' => false,
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ class InvalidFieldException extends UnprocessableEntityException
{
const ERROR_CODE = 202;

public function __construct($field)
public function __construct($field, $collection)
{
$message = sprintf('Invalid field "%s"', $field);
$message = sprintf('Invalid field "%s" in "%s"', $field, $collection);

parent::__construct($message);
}
Expand Down
9 changes: 6 additions & 3 deletions src/core/Directus/Database/Schema/SchemaFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,17 @@ public function createColumn($name, array $data)
*
* @return \Zend\Db\Adapter\Driver\StatementInterface|\Zend\Db\ResultSet\ResultSet
*/
public function buildTable(AbstractSql $table)
public function buildTable(AbstractSql $table,$charset="")
{
$connection = $this->schemaManager->getSource()->getConnection();
$sql = new Sql($connection);


$tableQuery = $sql->buildSqlString($table);
$tableQuery = !empty($charset) ? $tableQuery."charset = ".$charset: $tableQuery;

// TODO: Allow charset and comment
return $connection->query(
$sql->buildSqlString($table),
$tableQuery,
$connection::QUERY_MODE_EXECUTE
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/core/Directus/Database/Schema/Sources/MySQLSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,8 @@ public function getTypesRequireLength()
'varbinary',
'enum',
'set',
'decimal'
'decimal',
'char'
];
}

Expand Down
6 changes: 4 additions & 2 deletions src/core/Directus/Database/SchemaService.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,10 @@ public static function getRelatedCollectionName($tableName, $columnName)

$tableObject = static::getCollection($tableName);
$columnObject = $tableObject->getField($columnName);

return $columnObject->getRelationship()->getCollectionOne();
if($columnObject->getRelationship()->getType() == FieldRelationship::ONE_TO_MANY)
return $columnObject->getRelationship()->getCollectionMany();
else
return $columnObject->getRelationship()->getCollectionOne();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public function addRecordByArray(array $recordData)
if (
array_key_exists('filename', $recordData) &&
array_key_exists('data', $recordData) &&
strlen($recordData) > 25000000
strlen($recordData['data']) > 25000000
) {
$recordData = ['filename' => $recordData['filename']];
}
Expand Down
88 changes: 71 additions & 17 deletions src/core/Directus/Database/TableGateway/RelationalTableGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,6 @@ public function fetchItems(array $params = [], \Closure $queryCallback = null)
if (ArrayUtils::get($params, 'single')) {
$results = reset($results);
}

return $results ? $results : [];
}

Expand Down Expand Up @@ -1198,19 +1197,21 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
continue;
}

$columnList = $columns = explode('.', $column);
$columnList = $filterColumns = explode('.', $column);
$columnsTable = [
$this->getTable()
];

$nextColumn = array_shift($columnList);
$nextTable = $this->getTable();
$relational = SchemaService::hasRelationship($nextTable, $nextColumn);

$relationalTables = [];
while ($relational) {
$relationalTables[$nextColumn] = $nextTable;
$nextTable = SchemaService::getRelatedCollectionName($nextTable, $nextColumn);
$nextColumn = array_shift($columnList);

if(empty($nextColumn))
break;
// Confirm the user has permission to all chained (dot) fields
if ($this->acl && !$this->acl->canRead($nextTable)) {
throw new Exception\ForbiddenFieldAccessException($nextColumn);
Expand All @@ -1219,7 +1220,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
$relational = SchemaService::hasRelationship($nextTable, $nextColumn);
$columnsTable[] = $nextTable;
}

// if one of the column in the list has not relationship
// it will break the loop before going over all the columns
// which we will call this as column not found
Expand All @@ -1230,7 +1231,23 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)

// Remove the original filter column with dot-notation
unset($filters[$column]);


//Prepare relational data for all the fields
$columnRelationalData = [];
foreach($filterColumns as $filterColumn){
if(isset($relationalTables[$filterColumn])){
$collection = $this->getTableSchema($relationalTables[$filterColumn]);
$fieldRelation = $collection->getField($filterColumn)->getRelationship();
$columnRelationalData[$filterColumn] = [
"type" => $fieldRelation->getType(),
"collection_many" => $fieldRelation->getCollectionMany(),
"field_many" => $fieldRelation->getFieldMany(),
"collection_one" => $fieldRelation->getCollectionOne(),
"field_one" => $fieldRelation->getFieldOne()
];
}
}

// Reverse all the columns from comments.author.id to id.author.comments
// To filter from the most deep relationship to their parents
$columns = explode('.', \Directus\column_identifier_reverse($column));
Expand All @@ -1246,11 +1263,23 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)

$query = new Builder($this->getAdapter());
$mainTableObject = $this->getTableSchema($table);
$query->columns([$mainTableObject->getPrimaryField()->getName()]);
$selectColumn = $mainTableObject->getPrimaryField()->getName();

//check if column type is alias and relationship is O2M
$previousRelation = isset($filterColumns[array_search($column, $filterColumns)-1])?$filterColumns[array_search($column, $filterColumns)-1]:'';
if ($previousRelation && $columnRelationalData[$previousRelation]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) {
$selectColumn = $columnRelationalData[$previousRelation]['field_many'];
}

//get last relationship
if ($mainColumn && !empty($mainColumn) && $columnRelationalData[$mainColumn]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) {
$mainColumn = $mainTableObject->getPrimaryField()->getName();
}
$query->columns([$selectColumn]);

$query->from($table);

$this->doFilter($query, $column, $condition, $table);

$index = 0;
foreach ($columns as $key => $column) {
++$index;
Expand All @@ -1261,6 +1290,11 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
$field = $collection->getField($column);

$selectColumn = $collection->getPrimaryField()->getName();
//check if column type is alias and relationship is O2M
$previousRelation = isset($filterColumns[array_search($column, $filterColumns)-1])?$filterColumns[array_search($column, $filterColumns)-1]:'';
if ($previousRelation && $columnRelationalData[$previousRelation]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) {
$selectColumn = $columnRelationalData[$previousRelation]['field_many'];
}
$table = $columnsTable[$key];

if ($field->isAlias()) {
Expand All @@ -1279,7 +1313,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
// TODO: Make all this whereIn duplication into a function
// TODO: Can we make the O2M simpler getting the parent id from itself
// right now is creating one unnecessary select
if ($field->isOneToMany()) {
/*if ($field->isOneToMany()) {
$mainColumn = $collection->getPrimaryField()->getName();
$oldQuery = $query;
$query = new Builder($this->getAdapter());
Expand All @@ -1292,7 +1326,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
$column,
$oldQuery
);
}
}*/

$this->doFilter(
$mainQuery,
Expand All @@ -1318,7 +1352,7 @@ protected function doFilter(Builder $query, $column, $condition, $table)
);

if (!$field) {
throw new Exception\InvalidFieldException($fieldName);
throw new Exception\InvalidFieldException($fieldName, $table);
}

$condition = $this->parseCondition($condition);
Expand Down Expand Up @@ -1469,9 +1503,21 @@ protected function shouldIgnoreQueryFilter($operator, $value)
*/
protected function processFilter(Builder $query, array $filters = [])
{
$filters = $this->parseDotFilters($query, $filters);

foreach ($filters as $column => $conditions) {
//Logic for blacklisted fields
$blackListStatuses = [];
foreach($filters as $column => $conditions){
$column = explode('.', $column);
$column = array_shift($column);
$fieldReadBlackListDetails = $this->acl->getStatusesOnReadFieldBlacklist($this->getTable(),$column);
if (isset($fieldReadBlackListDetails['isReadBlackList']) && $fieldReadBlackListDetails['isReadBlackList']) {
throw new Exception\ForbiddenFieldAccessException($column);
}else if(isset($fieldReadBlackListDetails['statuses']) && !empty ($fieldReadBlackListDetails['statuses'])){
$blackListStatuses = array_merge($blackListStatuses,array_values($fieldReadBlackListDetails['statuses']));
}
}
$filters = $this->parseDotFilters($query, $filters);

foreach ($filters as $column => $conditions) {
if ($conditions instanceof Filter) {
$column = $conditions->getIdentifier();
$conditions = $conditions->getValue();
Expand All @@ -1485,6 +1531,14 @@ protected function processFilter(Builder $query, array $filters = [])
$this->doFilter($query, $column, $condition, $this->getTable());
}
}
//Condition for blacklisted statuses
if(!empty($blackListStatuses)){
$statusCondition = [
'nin' => array_unique($blackListStatuses)
];
$statusFieldName = SchemaService::getStatusFieldName($this->getTable());
$this->doFilter($query, $statusFieldName, $statusCondition, $this->getTable());
}
}

/**
Expand Down Expand Up @@ -1587,7 +1641,7 @@ protected function processSort(Builder $query, array $columns)

$field = SchemaService::getField($this->table, $orderBy, false, $this->acl === null);
if ($orderBy !== '?' && !$field) {
throw new Exception\InvalidFieldException($column);
throw new Exception\InvalidFieldException($column, $this->table);
}

if ($field && $field->isAlias()) {
Expand Down Expand Up @@ -1655,7 +1709,7 @@ protected function applyLegacyParams(Builder $query, array $params = [])
}

//$query->whereIn($this->primaryKeyFieldName, $entriesIds);
$query->whereIn(new Expression('CAST('.$this->primaryKeyFieldName.' as CHAR)'), $entriesIds);
$query->whereIn(new Expression('CAST(`'.$this->getTable().'`.`'.$this->primaryKeyFieldName.'` as CHAR)'), $entriesIds);
}

if (!ArrayUtils::has($params, 'q')) {
Expand Down Expand Up @@ -2048,7 +2102,7 @@ public function validateFields(array $fields)

foreach ($selectedFields as $field) {
if (!$collection->hasField($field)) {
throw new Exception\InvalidFieldException($field);
throw new Exception\InvalidFieldException($field, $collection->getName());
}
}
}
Expand Down
50 changes: 42 additions & 8 deletions src/core/Directus/Permissions/Acl.php
Original file line number Diff line number Diff line change
Expand Up @@ -1252,15 +1252,16 @@ public function allowTo($action, $level, $collection, $status = null)
$statuses = $this->getCollectionStatuses($collection);

$allowed = false;
foreach ($statuses as $status) {
$permission = $this->getPermission($collection, $status);
$permissionLevel = ArrayUtils::get($permission, $action);
if ($this->can($permissionLevel, $level)) {
$allowed = true;
break;
if($statuses){
foreach ($statuses as $status) {
$permission = $this->getPermission($collection, $status);
$permissionLevel = ArrayUtils::get($permission, $action);
if ($this->can($permissionLevel, $level)) {
$allowed = true;
break;
}
}
}

return $allowed;
} else {
$permissionLevel = ArrayUtils::get($permission, $action);
Expand Down Expand Up @@ -1293,7 +1294,40 @@ public function allowToOnce($action, $collection)

return $allowed;
}


/**
* Gets the statuses on which field has been blacklisted
*
* @param string $collection
* @param mixed $status
*
* @return array
*/
public function getStatusesOnReadFieldBlacklist($collection, $field)
{
$blackListStatuses = [];
$collectionPermission = $this->getCollectionPermissions($collection);
$statuses = $this->getCollectionStatuses($collection);
if($statuses){
foreach($statuses as $status){
$readFieldBlackList = isset($collectionPermission[$status]['read_field_blacklist']) ? $collectionPermission[$status]['read_field_blacklist'] : [];
if($readFieldBlackList && in_array($field, $readFieldBlackList)){
$blackListStatuses['statuses'][] = $status;
}
}
//Set flag for field which is blacklist for all statuses
if(isset($blackListStatuses['statuses']) && count($blackListStatuses['statuses']) == count($statuses)){
$blackListStatuses['isReadBlackList'] = true;
}
}else{
$readFieldBlackList = isset($collectionPermission['read_field_blacklist']) ? $collectionPermission['read_field_blacklist'] : [];
if($readFieldBlackList && in_array($field, $readFieldBlackList)){
$blackListStatuses['isReadBlackList'] = true;
}
}
return $blackListStatuses;
}

/**
* Returns a list of status the given collection has permission to read
*
Expand Down
2 changes: 1 addition & 1 deletion src/core/Directus/Services/MailService.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function send(array $data)

$useDefaultEmail = isset($data['use_default_email']) && $acl->isAdmin() ? $data['use_default_email'] : false;
send_mail_with_layout(
'base.twig',
$data['type'] == 'plain' ? 'plain.twig' : 'base.twig',
$data['body'],
(array) ArrayUtils::get($data, 'data'),
$data['type'] == 'plain' ? 'text/plain' : 'text/html',
Expand Down
4 changes: 2 additions & 2 deletions src/core/Directus/Services/SettingsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ public function findAll(array $params = [])

public function findFile($id,array $params = [])
{
return (new ItemsService($this->container))->findByIds(SchemaManager::COLLECTION_FILES, $id,$params);
return $this->itemsService->findByIds(SchemaManager::COLLECTION_FILES, $id,$params);
}

public function findAllFields(array $params = [])
{
return (new ItemsService($this->container))->findAll(SchemaManager::COLLECTION_FIELDS, array_merge($params, [
return $this->itemsService->findAll(SchemaManager::COLLECTION_FIELDS, array_merge($params, [
'filter' => [
'collection' => $this->collection
]
Expand Down
Loading

0 comments on commit cb8ab58

Please sign in to comment.