Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-react-native-platform

This commit is contained in:
Torsten Dittmann
2024-08-23 21:44:58 +02:00
4308 changed files with 10050 additions and 7253 deletions
+30 -26
View File
@@ -11,11 +11,8 @@ use Utopia\Validator;
*/
class Headers extends Validator
{
protected bool $allowEmpty;
public function __construct(bool $allowEmpty = true)
public function __construct(protected bool $allowEmpty = true, protected int $maxKeys = 100, protected int $maxSize = 16384)
{
$this->allowEmpty = $allowEmpty;
}
/**
@@ -27,7 +24,7 @@ class Headers extends Validator
*/
public function getDescription(): string
{
return 'Invalid header format. Header keys can only contain alphanumeric characters, underscores, and hyphens. Header keys cannot start with "x-appwrite-" prefix.';
return 'Invalid headers: Alphanumeric characters or hyphens only, cannot start with "x-appwrite", maximum ' . $this->maxKeys . ' keys, and total size ' . $this->maxSize . '.';
}
/**
@@ -47,34 +44,41 @@ class Headers extends Validator
return false;
}
if (\is_array($value)) {
foreach ($value as $key => $val) {
$length = \strlen($key);
// Reject non-string keys
if (!\is_string($key) || $length === 0) {
return false;
}
if(\count($value) > $this->maxKeys) {
return false;
}
// Check first and last character
if (!ctype_alnum($key[0]) || !ctype_alnum($key[$length - 1])) {
return false;
}
$size = 0;
foreach ($value as $key => $val) {
$length = \strlen($key);
// Reject non-string keys
if (!\is_string($key) || $length === 0) {
return false;
}
// Check middle characters
for ($i = 1; $i < $length - 1; $i++) {
if (!ctype_alnum($key[$i]) && $key[$i] !== '-') {
return false;
}
}
$size += $length + \strlen($val);
if($size >= $this->maxSize) {
return false;
}
// Check for x-appwrite- prefix
if (str_starts_with($key, 'x-appwrite-')) {
// Check first and last character
if (!ctype_alnum($key[0]) || !ctype_alnum($key[$length - 1])) {
return false;
}
// Check middle characters
for ($i = 1; $i < $length - 1; $i++) {
if (!ctype_alnum($key[$i]) && $key[$i] !== '-') {
return false;
}
}
return true;
// Check for x-appwrite- prefix
if (str_starts_with($key, 'x-appwrite-')) {
return false;
}
}
return false;
return true;
}
/**
+26 -16
View File
@@ -244,13 +244,7 @@ class Builds extends Action
$tmpTemplateDirectory .= '/';
}
$directorySize = $localDevice->getDirectorySize($tmpTemplateDirectory);
$functionsSizeLimit = (int)System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000');
if ($directorySize > $functionsSizeLimit) {
throw new \Exception('Repository directory size should be less than ' . number_format($functionsSizeLimit / 1048576, 2) . ' MBs.');
}
$tarParamDirectory = \escapeshellarg('/tmp/builds/' . $buildId . '-template' . (empty($templateRootDirectory) ? '' : '/' . $templateRootDirectory));
$tarParamDirectory = \escapeshellarg($tmpTemplateDirectory . (empty($templateRootDirectory) ? '' : '/' . $templateRootDirectory));
Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax
$source = $deviceForFunctions->getPath($deployment->getId() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION));
@@ -262,8 +256,9 @@ class Builds extends Action
Console::execute('rm -rf ' . \escapeshellarg($tmpTemplateDirectory), '', $stdout, $stderr);
$directorySize = $deviceForFunctions->getFileSize($source);
$build = $dbForProject->updateDocument('builds', $build->getId(), $build->setAttribute('source', $source));
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttribute('path', $source));
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttribute('path', $source)->setAttribute('size', $directorySize));
}
} elseif ($isNewBuild && $isVcsEnabled) {
// VCS and VCS+Temaplte
@@ -516,6 +511,8 @@ class Builds extends Action
return;
}
$isCanceled = false;
Co::join([
Co\go(function () use ($executor, &$response, $project, $deployment, $source, $function, $runtime, $vars, $command, $cpus, $memory, &$err) {
try {
@@ -540,12 +537,16 @@ class Builds extends Action
$err = $error;
}
}),
Co\go(function () use ($executor, $project, $deployment, &$response, &$build, $dbForProject, $allEvents, &$err) {
Co\go(function () use ($executor, $project, $deployment, &$response, &$build, $dbForProject, $allEvents, &$err, &$isCanceled) {
try {
$executor->getLogs(
deploymentId: $deployment->getId(),
projectId: $project->getId(),
callback: function ($logs) use (&$response, &$err, &$build, $dbForProject, $allEvents, $project) {
callback: function ($logs) use (&$response, &$err, &$build, $dbForProject, $allEvents, $project, &$isCanceled) {
if($isCanceled) {
return;
}
// If we have response or error from concurrent coroutine, we already have latest logs
if ($response === null && $err === null) {
$build = $dbForProject->getDocument('builds', $build->getId());
@@ -554,6 +555,12 @@ class Builds extends Action
throw new \Exception('Build not found', 404);
}
if ($build->getAttribute('status') === 'canceled') {
$isCanceled = true;
Console::info('Ignoring realtime logs because build has been canceled');
return;
}
$logs = \mb_substr($logs, 0, null, 'UTF-8'); // Get only valid UTF8 part - removes leftover half-multibytes causing SQL errors
$build = $build->setAttribute('logs', $build->getAttribute('logs', '') . $logs);
@@ -586,11 +593,12 @@ class Builds extends Action
}),
]);
if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') {
Console::info('Build has been canceled');
return;
}
if ($err) {
if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') {
Console::info('Build has been canceled');
return;
}
throw $err;
}
@@ -611,6 +619,8 @@ class Builds extends Action
$build->setAttribute('size', $response['size']);
$build->setAttribute('logs', $response['output']);
$build = $dbForProject->updateDocument('builds', $buildId, $build);
if ($isVcsEnabled) {
$this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole);
}
@@ -652,12 +662,12 @@ class Builds extends Action
$build->setAttribute('status', 'failed');
$build->setAttribute('logs', $th->getMessage());
$build = $dbForProject->updateDocument('builds', $buildId, $build);
if ($isVcsEnabled) {
$this->runGitAction('failed', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole);
}
} finally {
$build = $dbForProject->updateDocument('builds', $buildId, $build);
/**
* Send realtime Event
*/
+3 -3
View File
@@ -7,7 +7,7 @@ use Appwrite\Extend\Exception;
use Executor\Executor;
use Throwable;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
use Utopia\Abuse\Adapters\Database\TimeLimit;
use Utopia\Audit\Audit;
use Utopia\Cache\Adapter\Filesystem;
use Utopia\Cache\Cache;
@@ -493,7 +493,7 @@ class Deletes extends Action
$projectCollectionIds = [
...\array_keys(Config::getParam('collections', [])['projects']),
Audit::COLLECTION,
AbuseDatabase::COLLECTION,
TimeLimit::COLLECTION,
];
$limit = \count($projectCollectionIds) + 25;
@@ -686,7 +686,7 @@ class Deletes extends Action
{
$projectId = $project->getId();
$dbForProject = $getProjectDB($project);
$timeLimit = new AbuseDatabase("", 0, 1, $dbForProject);
$timeLimit = new TimeLimit("", 0, 1, $dbForProject);
$abuse = new Abuse($timeLimit);
try {
+11 -3
View File
@@ -33,9 +33,17 @@ class V16 extends Filter
protected function parseDeployment(array $content)
{
$content['buildStderr'] = '';
$content['buildStdout'] = $content['buildLogs'];
unset($content['buildLogs']);
if(isset($content['buildLogs'])) {
$content['buildStderr'] = '';
$content['buildStdout'] = $content['buildLogs'];
unset($content['buildLogs']);
}
if(isset($content['buildSize'])) {
$content['size'] += + $content['buildSize'] ?? 0;
unset($content['buildSize']);
}
return $content;
}
@@ -58,6 +58,12 @@ class Deployment extends Model
'default' => 0,
'example' => 128,
])
->addRule('buildSize', [
'type' => self::TYPE_INTEGER,
'description' => 'The build output size in bytes.',
'default' => 0,
'example' => 128,
])
->addRule('buildId', [
'type' => self::TYPE_STRING,
'description' => 'The current build ID.',