diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index bc9f28d0cc..4e16f8ad5f 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -650,11 +650,13 @@ App::post('/v1/functions/:functionId/deployments') $end = $request->getContentRangeEnd(); $fileSize = $request->getContentRangeSize(); $deploymentId = $request->getHeader('x-appwrite-id', $deploymentId); - if (is_null($start) || is_null($end) || is_null($fileSize)) { + // TODO make `end >= $fileSize` in next breaking version + if (is_null($start) || is_null($end) || is_null($fileSize) || $end > $fileSize) { throw new Exception(Exception::STORAGE_INVALID_CONTENT_RANGE); } - if ($end === $fileSize) { + // TODO remove the condition that checks `$end === $fileSize` in next breaking version + if ($end === $fileSize - 1 || $end === $fileSize) { //if it's a last chunks the chunk size might differ, so we set the $chunks and $chunk to notify it's last chunk $chunks = $chunk = -1; } else { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index d59d950d93..8a88e3c766 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -445,11 +445,13 @@ App::post('/v1/storage/buckets/:bucketId/files') $end = $request->getContentRangeEnd(); $fileSize = $request->getContentRangeSize(); $fileId = $request->getHeader('x-appwrite-id', $fileId); - if (is_null($start) || is_null($end) || is_null($fileSize)) { + // TODO make `end >= $fileSize` in next breaking version + if (is_null($start) || is_null($end) || is_null($fileSize) || $end > $fileSize) { throw new Exception(Exception::STORAGE_INVALID_CONTENT_RANGE); } - if ($end === $fileSize) { + // TODO remove the condition that checks `$end === $fileSize` in next breaking version + if ($end === $fileSize - 1 || $end === $fileSize) { //if it's a last chunks the chunk size might differ, so we set the $chunks and $chunk to -1 notify it's last chunk $chunks = $chunk = -1; } else { diff --git a/app/controllers/general.php b/app/controllers/general.php index 1982ea0d7f..741b9f4111 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -41,6 +41,7 @@ Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); App::init() + ->groups(['api']) ->inject('utopia') ->inject('request') ->inject('response') diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 33e92f289a..1f251a6d35 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -286,7 +286,7 @@ App::post('/v1/mock/tests/general/upload') $id = $request->getHeader('x-appwrite-id', ''); $file['size'] = (\is_array($file['size'])) ? $file['size'][0] : $file['size']; - if (is_null($start) || is_null($end) || is_null($size)) { + if (is_null($start) || is_null($end) || is_null($size) || $end >= $size) { throw new Exception(Exception::GENERAL_MOCK, 'Invalid content-range header'); } @@ -302,11 +302,11 @@ App::post('/v1/mock/tests/general/upload') throw new Exception(Exception::GENERAL_MOCK, 'All chunked request must have id header (except first)'); } - if ($end !== $size && $end - $start + 1 !== $chunkSize) { + if ($end !== $size - 1 && $end - $start + 1 !== $chunkSize) { throw new Exception(Exception::GENERAL_MOCK, 'Chunk size must be 5MB (except last chunk)'); } - if ($end !== $size && $file['size'] !== $chunkSize) { + if ($end !== $size - 1 && $file['size'] !== $chunkSize) { throw new Exception(Exception::GENERAL_MOCK, 'Wrong chunk size'); } @@ -314,11 +314,11 @@ App::post('/v1/mock/tests/general/upload') throw new Exception(Exception::GENERAL_MOCK, 'Chunk size must be 5MB or less'); } - if ($end !== $size) { + if ($end !== $size - 1) { $response->json([ '$id' => ID::custom('newfileid'), - 'chunksTotal' => $file['size'] / $chunkSize, - 'chunksUploaded' => $start / $chunkSize + 'chunksTotal' => (int) ceil($size / ($end + 1 - $start)), + 'chunksUploaded' => ceil($start / $chunkSize) + 1 ]); } } else { diff --git a/app/init.php b/app/init.php index 0b6efe52c0..fc7541513d 100644 --- a/app/init.php +++ b/app/init.php @@ -903,7 +903,7 @@ App::setResource('project', function ($dbForConsole, $request, $console) { /** @var Utopia\Database\Database $dbForConsole */ /** @var Utopia\Database\Document $console */ - $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', 'console')); + $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', '')); if ($projectId === 'console') { return $console; diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index b9b8dc3a47..110ee3eb4a 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -46,6 +46,8 @@ For **Linux** add your app name and package name, Your package nam ### Mac OS For **Mac OS** add your app name and Bundle ID, You can find your Bundle Identifier in the General tab for your app's primary target in Xcode. +The Appwrite SDK uses ASWebAuthenticationSession on macOS 10.15+ to allow OAuth authentication. You have to change your macOS Deployment Target in Xcode to be macOS >= 10.15 to be able to build your app for macOS. + ### Web Appwrite 0.7, and the Appwrite Flutter SDK 0.3.0 have added support for Flutter Web. To build web apps that integrate with Appwrite successfully, all you have to do is add a web platform on your Appwrite project's dashboard and list the domain your website will use to allow communication to the Appwrite API. diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 2b66277952..37ba2ede7b 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -405,7 +405,7 @@ class FunctionsCustomServerTest extends Scope $id = ''; while (!feof($handle)) { $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'php-large-fx.tar.gz'); - $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size) . '/' . $size; + $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; if (!empty($id)) { $headers['x-appwrite-id'] = $id; } diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 3169077f99..3b14d1961a 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -100,7 +100,7 @@ trait StorageBase $id = ''; while (!feof($handle)) { $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); - $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size) . '/' . $size; + $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; if (!empty($id)) { $headers['x-appwrite-id'] = $id; } @@ -144,7 +144,7 @@ trait StorageBase ]; $id = ''; $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); - $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size) . '/' . $size; + $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size - 1) . '/' . $size; $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket2['body']['$id'] . '/files', $this->getHeaders(), [ 'fileId' => $fileId, 'file' => $curlFile,