mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '1.8.x' into allow-head-requests
This commit is contained in:
@@ -11,9 +11,11 @@ use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Domains\Domain as Domain;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Domain;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Domain as DomainValidator;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
@@ -67,10 +69,59 @@ class Get extends Action
|
||||
Database $dbForPlatform
|
||||
) {
|
||||
if ($type === 'rules') {
|
||||
$validator = new Domain($value);
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$restrictions = [];
|
||||
if (!empty($sitesDomain)) {
|
||||
// Ensure site domains are exactly 1 subdomain, and dont start with reserved prefix
|
||||
$domainLevel = \count(\explode('.', $sitesDomain));
|
||||
$restrictions[] = DomainValidator::createRestriction($sitesDomain, $domainLevel + 1, ['commit-', 'branch-']);
|
||||
}
|
||||
if (!empty($functionsDomain)) {
|
||||
// Ensure function domains are exactly 1 subdomain
|
||||
$domainLevel = \count(\explode('.', $functionsDomain));
|
||||
$restrictions[] = DomainValidator::createRestriction($functionsDomain, $domainLevel + 1);
|
||||
}
|
||||
$validator = new DomainValidator($restrictions);
|
||||
|
||||
if (!$validator->isValid($value)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $validator->getDescription());
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
$deniedDomains = [
|
||||
'localhost',
|
||||
APP_HOSTNAME_INTERNAL
|
||||
];
|
||||
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
$deniedDomains[] = $mainDomain;
|
||||
|
||||
if (!empty($sitesDomain)) {
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
}
|
||||
|
||||
if (!empty($functionsDomain)) {
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
}
|
||||
|
||||
$denyListDomains = System::getEnv('_APP_CUSTOM_DOMAIN_DENY_LIST', '');
|
||||
$denyListDomains = \array_map('trim', explode(',', $denyListDomains));
|
||||
foreach ($denyListDomains as $denyListDomain) {
|
||||
if (empty($denyListDomain)) {
|
||||
continue;
|
||||
}
|
||||
$deniedDomains[] = $denyListDomain;
|
||||
}
|
||||
|
||||
if (\in_array($value, $deniedDomains)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
try {
|
||||
$domain = new Domain($value);
|
||||
} catch (\Throwable) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.');
|
||||
}
|
||||
|
||||
$document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ abstract class Action extends AppwriteAction
|
||||
|
||||
// Use the same helper method to ensure consistency
|
||||
$contextId = '$' . $this->getCollectionsEventsContext() . 'Id';
|
||||
$this->removableAttributes = ['$databaseId', $contextId];
|
||||
$this->removableAttributes = ['$databaseId', $contextId, '$sequence'];
|
||||
|
||||
return parent::setHttpPath($path);
|
||||
}
|
||||
|
||||
+3
@@ -127,6 +127,9 @@ class Update extends Action
|
||||
}
|
||||
}
|
||||
|
||||
// Remove sequence if set
|
||||
unset($document['$sequence']);
|
||||
|
||||
$documents = [];
|
||||
|
||||
try {
|
||||
|
||||
+3
@@ -351,6 +351,9 @@ class Create extends Action
|
||||
}
|
||||
}
|
||||
|
||||
// Remove sequence if set
|
||||
unset($document['$sequence']);
|
||||
|
||||
// Assign a unique ID if needed, otherwise use the provided ID.
|
||||
$document['$id'] = $sourceId === 'unique()' ? ID::unique() : $sourceId;
|
||||
|
||||
|
||||
+3
@@ -159,6 +159,9 @@ class Update extends Action
|
||||
$permissions = $document->getPermissions() ?? [];
|
||||
}
|
||||
|
||||
// Remove sequence if set
|
||||
unset($document['$sequence']);
|
||||
|
||||
$data['$id'] = $documentId;
|
||||
$data['$permissions'] = $permissions;
|
||||
$newDocument = new Document($data);
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class Create extends BooleanCreate
|
||||
->desc('Create boolean column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'column.create')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class Update extends BooleanUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/boolean/:key')
|
||||
->desc('Update boolean column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class Create extends DatetimeCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/datetime')
|
||||
->desc('Create datetime column')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ class Update extends DatetimeUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/datetime/:key')
|
||||
->desc('Update dateTime column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
@@ -32,7 +32,7 @@ class Delete extends AttributesDelete
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/:key')
|
||||
->desc('Delete column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.delete')
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class Create extends EmailCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/email')
|
||||
->desc('Create email column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class Update extends EmailUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/email/:key')
|
||||
->desc('Update email column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class Create extends EnumCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/enum')
|
||||
->desc('Create enum column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ class Update extends EnumUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/enum/:key')
|
||||
->desc('Update enum column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class Create extends FloatCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/float')
|
||||
->desc('Create float column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class Update extends FloatUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/float/:key')
|
||||
->desc('Update float column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
@@ -41,7 +41,7 @@ class Get extends AttributesGet
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/:key')
|
||||
->desc('Get column')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -32,7 +32,7 @@ class Create extends IPCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/ip')
|
||||
->desc('Create IP address column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
@@ -34,7 +34,7 @@ class Update extends IPUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/ip/:key')
|
||||
->desc('Update IP address column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class Create extends IntegerCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/integer')
|
||||
->desc('Create integer column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class Update extends IntegerUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/integer/:key')
|
||||
->desc('Update integer column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class Create extends RelationshipCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/relationship')
|
||||
->desc('Create relationship column')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class Update extends RelationshipUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/:key/relationship')
|
||||
->desc('Update relationship column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class Create extends StringCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/string')
|
||||
->desc('Create string column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ class Update extends StringUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/string/:key')
|
||||
->desc('Update string column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
@@ -32,7 +32,7 @@ class Create extends URLCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/url')
|
||||
->desc('Create URL column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create')
|
||||
->label('audits.event', 'column.create')
|
||||
|
||||
@@ -34,7 +34,7 @@ class Update extends URLUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/url/:key')
|
||||
->desc('Update URL column')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].update')
|
||||
->label('audits.event', 'column.update')
|
||||
|
||||
@@ -30,7 +30,7 @@ class XList extends AttributesXList
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns')
|
||||
->desc('List columns')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -35,7 +35,7 @@ class Create extends CollectionCreate
|
||||
->desc('Create table')
|
||||
->groups(['api', 'database'])
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].create')
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'table.create')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}')
|
||||
|
||||
@@ -30,7 +30,7 @@ class Delete extends CollectionDelete
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId')
|
||||
->desc('Delete table')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].delete')
|
||||
->label('audits.event', 'table.delete')
|
||||
|
||||
@@ -30,7 +30,7 @@ class Get extends CollectionGet
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId')
|
||||
->desc('Get table')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -37,7 +37,7 @@ class Create extends IndexCreate
|
||||
->desc('Create index')
|
||||
->groups(['api', 'database'])
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].create')
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'index.create')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
|
||||
|
||||
@@ -35,7 +35,7 @@ class Delete extends IndexDelete
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/indexes/:key')
|
||||
->desc('Delete index')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].indexes.[indexId].update')
|
||||
->label('audits.event', 'index.delete')
|
||||
|
||||
@@ -31,7 +31,7 @@ class Get extends IndexGet
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/indexes/:key')
|
||||
->desc('Get index')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -31,7 +31,7 @@ class XList extends IndexXList
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/indexes')
|
||||
->desc('List indexes')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -27,7 +27,7 @@ class XList extends CollectionLogXList
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/logs')
|
||||
->desc('List table logs')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -32,7 +32,7 @@ class Delete extends DocumentsDelete
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows')
|
||||
->desc('Delete rows')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'rows.delete')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
|
||||
|
||||
@@ -33,7 +33,7 @@ class Update extends DocumentsUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows')
|
||||
->desc('Update rows')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'rows.update')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
|
||||
|
||||
@@ -32,7 +32,7 @@ class Upsert extends DocumentsUpsert
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows')
|
||||
->desc('Create or update rows')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'row.create')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class Decrement extends DecrementDocumentAttribute
|
||||
->desc('Decrement row column')
|
||||
->groups(['api', 'database'])
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update')
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'rows.update')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class Increment extends IncrementDocumentAttribute
|
||||
->desc('Increment row column')
|
||||
->groups(['api', 'database'])
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update')
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'rows.update')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
|
||||
|
||||
@@ -41,7 +41,7 @@ class Create extends DocumentCreate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows')
|
||||
->desc('Create row')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'row.create')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
|
||||
|
||||
@@ -36,7 +36,7 @@ class Delete extends DocumentDelete
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows/:rowId')
|
||||
->desc('Delete row')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].delete')
|
||||
->label('audits.event', 'row.delete')
|
||||
|
||||
@@ -32,7 +32,7 @@ class Get extends DocumentGet
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows/:rowId')
|
||||
->desc('Get row')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'rows.read')
|
||||
->label('scope', ['rows.read', 'documents.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -27,7 +27,7 @@ class XList extends DocumentLogXList
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows/:rowId/logs')
|
||||
->desc('List row logs')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'rows.read')
|
||||
->label('scope', ['rows.read', 'documents.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -34,7 +34,7 @@ class Update extends DocumentUpdate
|
||||
->desc('Update row')
|
||||
->groups(['api', 'database'])
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].update')
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'row.update')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}')
|
||||
|
||||
@@ -34,7 +34,7 @@ class Upsert extends DocumentUpsert
|
||||
->desc('Create or update a row')
|
||||
->groups(['api', 'database'])
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].upsert')
|
||||
->label('scope', 'rows.write')
|
||||
->label('scope', ['rows.write', 'documents.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('audits.event', 'row.upsert')
|
||||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}/row/{response.$id}')
|
||||
|
||||
@@ -32,7 +32,7 @@ class XList extends DocumentXList
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows')
|
||||
->desc('List rows')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'rows.read')
|
||||
->label('scope', ['rows.read', 'documents.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -33,7 +33,7 @@ class Update extends CollectionUpdate
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId')
|
||||
->desc('Update table')
|
||||
->groups(['api', 'database', 'schema'])
|
||||
->label('scope', 'tables.write')
|
||||
->label('scope', ['tables.write', 'collections.write'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('event', 'databases.[databaseId].tables.[tableId].update')
|
||||
->label('audits.event', 'table.update')
|
||||
|
||||
@@ -31,7 +31,7 @@ class Get extends CollectionUsageGet
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/usage')
|
||||
->desc('Get table usage stats')
|
||||
->groups(['api', 'database', 'usage'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -32,7 +32,7 @@ class XList extends CollectionXList
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/tables')
|
||||
->desc('List tables')
|
||||
->groups(['api', 'database'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', new Method(
|
||||
namespace: $this->getSdkNamespace(),
|
||||
|
||||
@@ -26,7 +26,7 @@ class Get extends DatabaseUsageGet
|
||||
->setHttpPath('/v1/tablesdb/:databaseId/usage')
|
||||
->desc('Get TablesDB usage stats')
|
||||
->groups(['api', 'database', 'usage'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', [
|
||||
new Method(
|
||||
|
||||
@@ -25,7 +25,7 @@ class XList extends DatabaseUsageXList
|
||||
->setHttpPath('/v1/tablesdb/usage')
|
||||
->desc('Get TablesDB usage stats')
|
||||
->groups(['api', 'database', 'usage'])
|
||||
->label('scope', 'tables.read')
|
||||
->label('scope', ['tables.read', 'collections.read'])
|
||||
->label('resourceType', RESOURCE_TYPE_DATABASES)
|
||||
->label('sdk', [
|
||||
new Method(
|
||||
|
||||
@@ -80,7 +80,7 @@ class Create extends Base
|
||||
->param('body', '', new Text(10485760, 0), 'HTTP body of execution. Default value is empty string.', true)
|
||||
->param('async', false, new Boolean(true), 'Execute code in the background. Default value is false.', true)
|
||||
->param('path', '/', new Text(2048), 'HTTP path of execution. Path can include query params. Default value is /', true)
|
||||
->param('method', 'POST', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'], true), 'HTTP method of execution. Default value is GET.', true)
|
||||
->param('method', 'POST', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'], true), 'HTTP method of execution. Default value is POST.', true)
|
||||
->param('headers', [], new AnyOf([new Assoc(), new Text(65535)], AnyOf::TYPE_MIXED), 'HTTP headers of execution. Defaults to empty.', true)
|
||||
->param('scheduledAt', null, new Text(100), 'Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.', true)
|
||||
->inject('response')
|
||||
@@ -221,6 +221,8 @@ class Create extends Base
|
||||
'scopes' => $function->getAttribute('scopes', [])
|
||||
]);
|
||||
|
||||
$executionId = ID::unique();
|
||||
$headers['x-appwrite-execution-id'] = $executionId ?? '';
|
||||
$headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey;
|
||||
$headers['x-appwrite-trigger'] = 'http';
|
||||
$headers['x-appwrite-user-id'] = $user->getId() ?? '';
|
||||
@@ -228,8 +230,9 @@ class Create extends Base
|
||||
$headers['x-appwrite-country-code'] = '';
|
||||
$headers['x-appwrite-continent-code'] = '';
|
||||
$headers['x-appwrite-continent-eu'] = 'false';
|
||||
$ip = $request->getIP();
|
||||
$headers['x-appwrite-client-ip'] = $ip;
|
||||
|
||||
$ip = $headers['x-real-ip'] ?? '';
|
||||
if (!empty($ip)) {
|
||||
$record = $geodb->get($ip);
|
||||
|
||||
@@ -249,7 +252,7 @@ class Create extends Base
|
||||
}
|
||||
}
|
||||
|
||||
$executionId = ID::unique();
|
||||
|
||||
|
||||
$status = $async ? 'waiting' : 'processing';
|
||||
|
||||
@@ -481,6 +484,8 @@ class Create extends Base
|
||||
$execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution));
|
||||
}
|
||||
|
||||
$executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId();
|
||||
|
||||
$headers = [];
|
||||
foreach (($executionResponse['headers'] ?? []) as $key => $value) {
|
||||
$headers[] = ['name' => $key, 'value' => $value];
|
||||
|
||||
@@ -71,6 +71,24 @@ class Create extends Action
|
||||
|
||||
public function action(string $domain, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform)
|
||||
{
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$restrictions = [];
|
||||
if (!empty($sitesDomain)) {
|
||||
$domainLevel = \count(\explode('.', $sitesDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($sitesDomain, $domainLevel + 1, ['commit-', 'branch-']);
|
||||
}
|
||||
if (!empty($functionsDomain)) {
|
||||
$domainLevel = \count(\explode('.', $functionsDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($functionsDomain, $domainLevel + 1);
|
||||
}
|
||||
$validator = new ValidatorDomain($restrictions);
|
||||
|
||||
if (!$validator->isValid($domain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
$deniedDomains = [
|
||||
'localhost',
|
||||
APP_HOSTNAME_INTERNAL
|
||||
@@ -79,12 +97,10 @@ class Create extends Action
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
$deniedDomains[] = $mainDomain;
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
if (!empty($sitesDomain)) {
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
}
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
if (!empty($functionsDomain)) {
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
}
|
||||
@@ -102,10 +118,6 @@ class Create extends Action
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
if (\str_starts_with($domain, 'commit-') || \str_starts_with($domain, 'branch-')) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
try {
|
||||
$domain = new Domain($domain);
|
||||
} catch (\Throwable) {
|
||||
|
||||
@@ -76,6 +76,24 @@ class Create extends Action
|
||||
|
||||
public function action(string $domain, string $functionId, string $branch, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject)
|
||||
{
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$restrictions = [];
|
||||
if (!empty($sitesDomain)) {
|
||||
$domainLevel = \count(\explode('.', $sitesDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($sitesDomain, $domainLevel + 1, ['commit-', 'branch-']);
|
||||
}
|
||||
if (!empty($functionsDomain)) {
|
||||
$domainLevel = \count(\explode('.', $functionsDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($functionsDomain, $domainLevel + 1);
|
||||
}
|
||||
$validator = new ValidatorDomain($restrictions);
|
||||
|
||||
if (!$validator->isValid($domain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
$deniedDomains = [
|
||||
'localhost',
|
||||
APP_HOSTNAME_INTERNAL
|
||||
@@ -84,12 +102,10 @@ class Create extends Action
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
$deniedDomains[] = $mainDomain;
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
if (!empty($sitesDomain)) {
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
}
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
if (!empty($functionsDomain)) {
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
}
|
||||
@@ -107,10 +123,6 @@ class Create extends Action
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
if (\str_starts_with($domain, 'commit-') || \str_starts_with($domain, 'branch-')) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
try {
|
||||
$domain = new Domain($domain);
|
||||
} catch (\Throwable) {
|
||||
|
||||
@@ -79,6 +79,24 @@ class Create extends Action
|
||||
|
||||
public function action(string $domain, string $url, int $statusCode, string $resourceId, string $resourceType, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject)
|
||||
{
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$restrictions = [];
|
||||
if (!empty($sitesDomain)) {
|
||||
$domainLevel = \count(\explode('.', $sitesDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($sitesDomain, $domainLevel + 1, ['commit-', 'branch-']);
|
||||
}
|
||||
if (!empty($functionsDomain)) {
|
||||
$domainLevel = \count(\explode('.', $functionsDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($functionsDomain, $domainLevel + 1);
|
||||
}
|
||||
$validator = new ValidatorDomain($restrictions);
|
||||
|
||||
if (!$validator->isValid($domain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
$deniedDomains = [
|
||||
'localhost',
|
||||
APP_HOSTNAME_INTERNAL
|
||||
@@ -87,12 +105,10 @@ class Create extends Action
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
$deniedDomains[] = $mainDomain;
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
if (!empty($sitesDomain)) {
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
}
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
if (!empty($functionsDomain)) {
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
}
|
||||
@@ -110,10 +126,6 @@ class Create extends Action
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
if (\str_starts_with($domain, 'commit-') || \str_starts_with($domain, 'branch-')) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
try {
|
||||
$domain = new Domain($domain);
|
||||
} catch (\Throwable) {
|
||||
|
||||
@@ -76,6 +76,24 @@ class Create extends Action
|
||||
|
||||
public function action(string $domain, string $siteId, string $branch, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject)
|
||||
{
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
|
||||
$restrictions = [];
|
||||
if (!empty($sitesDomain)) {
|
||||
$domainLevel = \count(\explode('.', $sitesDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($sitesDomain, $domainLevel + 1, ['commit-', 'branch-']);
|
||||
}
|
||||
if (!empty($functionsDomain)) {
|
||||
$domainLevel = \count(\explode('.', $functionsDomain));
|
||||
$restrictions[] = ValidatorDomain::createRestriction($functionsDomain, $domainLevel + 1);
|
||||
}
|
||||
$validator = new ValidatorDomain($restrictions);
|
||||
|
||||
if (!$validator->isValid($domain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
$deniedDomains = [
|
||||
'localhost',
|
||||
APP_HOSTNAME_INTERNAL
|
||||
@@ -84,12 +102,10 @@ class Create extends Action
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
$deniedDomains[] = $mainDomain;
|
||||
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
if (!empty($sitesDomain)) {
|
||||
$deniedDomains[] = $sitesDomain;
|
||||
}
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
if (!empty($functionsDomain)) {
|
||||
$deniedDomains[] = $functionsDomain;
|
||||
}
|
||||
@@ -107,10 +123,6 @@ class Create extends Action
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
if (\str_starts_with($domain, 'commit-') || \str_starts_with($domain, 'branch-')) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please use a different domain.');
|
||||
}
|
||||
|
||||
try {
|
||||
$domain = new Domain($domain);
|
||||
} catch (\Throwable) {
|
||||
|
||||
@@ -264,6 +264,8 @@ class Functions extends Action
|
||||
string $jwt = null,
|
||||
string $event = null,
|
||||
): void {
|
||||
$executionId = ID::unique();
|
||||
$headers['x-appwrite-execution-id'] = $executionId ?? '';
|
||||
$headers['x-appwrite-trigger'] = $trigger;
|
||||
$headers['x-appwrite-event'] = $event ?? '';
|
||||
$headers['x-appwrite-user-id'] = $user->getId() ?? '';
|
||||
@@ -276,7 +278,6 @@ class Functions extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$executionId = ID::unique();
|
||||
$execution = new Document([
|
||||
'$id' => $executionId,
|
||||
'$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))],
|
||||
@@ -397,6 +398,7 @@ class Functions extends Action
|
||||
'scopes' => $function->getAttribute('scopes', [])
|
||||
]);
|
||||
|
||||
$headers['x-appwrite-execution-id'] = $executionId ?? '';
|
||||
$headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey;
|
||||
$headers['x-appwrite-trigger'] = $trigger;
|
||||
$headers['x-appwrite-event'] = $event ?? '';
|
||||
@@ -409,6 +411,8 @@ class Functions extends Action
|
||||
/** Create execution or update execution status */
|
||||
$execution = $dbForProject->getDocument('executions', $executionId ?? '');
|
||||
if ($execution->isEmpty()) {
|
||||
$executionId = ID::unique();
|
||||
$headers['x-appwrite-execution-id'] = $executionId;
|
||||
$headersFiltered = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_REQUEST)) {
|
||||
@@ -416,7 +420,6 @@ class Functions extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$executionId = ID::unique();
|
||||
$execution = new Document([
|
||||
'$id' => $executionId,
|
||||
'$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))],
|
||||
@@ -543,6 +546,8 @@ class Functions extends Action
|
||||
|
||||
$status = $executionResponse['statusCode'] >= 500 ? 'failed' : 'completed';
|
||||
|
||||
$executionResponse['headers']['x-appwrite-execution-id'] = $execution->getId();
|
||||
|
||||
$headersFiltered = [];
|
||||
foreach ($executionResponse['headers'] as $key => $value) {
|
||||
if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) {
|
||||
|
||||
@@ -349,11 +349,10 @@ class Swagger2 extends Format
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($scope)) { // && 'public' != $scope
|
||||
if (!empty($scope)) {
|
||||
$securities = ['Project' => []];
|
||||
|
||||
foreach ($sdk->getAuth() as $security) {
|
||||
/** @var AuthType $security */
|
||||
if (\array_key_exists($security->value, $this->keys)) {
|
||||
$securities[$security->value] = [];
|
||||
}
|
||||
|
||||
@@ -96,36 +96,74 @@ class V20 extends Filter
|
||||
/**
|
||||
* Returns all relationship attribute keys in `key.*` format for use with `Query::select`.
|
||||
*/
|
||||
private function getRelatedCollectionKeys(): array
|
||||
{
|
||||
$dbForProject = $this->getDbForProject();
|
||||
private function getRelatedCollectionKeys(
|
||||
?string $databaseId = null,
|
||||
?string $collectionId = null,
|
||||
?string $prefix = null,
|
||||
int $depth = 1,
|
||||
): array {
|
||||
$databaseId ??= $this->getParamValue('databaseId');
|
||||
$collectionId ??= $this->getParamValue('collectionId');
|
||||
|
||||
if (
|
||||
empty($databaseId) ||
|
||||
empty($collectionId) ||
|
||||
$depth > Database::RELATION_MAX_DEPTH
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$dbForProject = $this->getDbForProject();
|
||||
if ($dbForProject === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$databaseId = $this->getParamValue('databaseId');
|
||||
$collectionId = $this->getParamValue('collectionId');
|
||||
|
||||
if (empty($databaseId) || empty($collectionId)) {
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
$collection = $dbForProject->getDocument(
|
||||
$collection = Authorization::skip(fn () => $dbForProject->getDocument(
|
||||
'database_' . $database->getSequence(),
|
||||
$collectionId
|
||||
);
|
||||
));
|
||||
if ($collection->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$attributes = $collection->getAttribute('attributes', []);
|
||||
$relationshipKeys = [];
|
||||
|
||||
return \array_values(\array_map(
|
||||
fn ($attr) => $attr['key'] . '.*',
|
||||
\array_filter(
|
||||
$attributes,
|
||||
fn ($attr) => ($attr['type'] ?? null) === Database::VAR_RELATIONSHIP
|
||||
)
|
||||
));
|
||||
foreach ($attributes as $attr) {
|
||||
if (
|
||||
($attr['type'] ?? null) !== Database::VAR_RELATIONSHIP ||
|
||||
$attr['status'] !== 'available'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = $attr['key'];
|
||||
$fullKey = $prefix ? $prefix . '.' . $key : $key;
|
||||
|
||||
// Add the wildcard select for this relationship
|
||||
$relationshipKeys[] = $fullKey . '.*';
|
||||
|
||||
// Get the related collection for nested relationships
|
||||
$relatedCollectionId = $attr['relatedCollection'] ?? null;
|
||||
|
||||
if ($relatedCollectionId) {
|
||||
// Recursively get nested relationship keys
|
||||
$nestedKeys = $this->getRelatedCollectionKeys(
|
||||
$databaseId,
|
||||
$relatedCollectionId,
|
||||
$fullKey,
|
||||
$depth + 1,
|
||||
);
|
||||
|
||||
$relationshipKeys = \array_merge($relationshipKeys, $nestedKeys);
|
||||
}
|
||||
}
|
||||
|
||||
return \array_values(\array_unique($relationshipKeys));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,15 @@ class V20 extends Filter
|
||||
{
|
||||
$parsedResponse = $content;
|
||||
|
||||
$parsedResponse = match($model) {
|
||||
return match($model) {
|
||||
Response::MODEL_DOCUMENT => $this->parseDocument($content),
|
||||
Response::MODEL_DOCUMENT_LIST => $this->handleList($content, 'documents', fn ($item) => $this->parseDocument($item)),
|
||||
default => $parsedResponse,
|
||||
};
|
||||
|
||||
return $parsedResponse;
|
||||
}
|
||||
|
||||
protected function parseDocument(array $content): array
|
||||
{
|
||||
unset($content['$sequence']);
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ class Row extends Any
|
||||
{
|
||||
$document->removeAttribute('$collection');
|
||||
$document->removeAttribute('$tenant');
|
||||
$document->setAttribute('$sequence', (int)$document->getAttribute('$sequence', 0));
|
||||
|
||||
foreach ($document->getAttributes() as $column) {
|
||||
if (\is_array($column)) {
|
||||
|
||||
Reference in New Issue
Block a user