diff --git a/Dockerfile b/Dockerfile index 5d06d6c828..a264ac8795 100755 --- a/Dockerfile +++ b/Dockerfile @@ -98,24 +98,9 @@ RUN chmod +x /usr/local/bin/doctor && \ chmod +x /usr/local/bin/worker-messaging && \ chmod +x /usr/local/bin/worker-webhooks && \ chmod +x /usr/local/bin/worker-migrations && \ - chmod +x /usr/local/bin/worker-hamster && \ chmod +x /usr/local/bin/worker-usage && \ chmod +x /usr/local/bin/worker-usage-dump - -# Cloud Executabless -RUN chmod +x /usr/local/bin/hamster && \ - chmod +x /usr/local/bin/volume-sync && \ - chmod +x /usr/local/bin/patch-delete-schedule-updated-at-attribute && \ - chmod +x /usr/local/bin/patch-recreate-repositories-documents && \ - chmod +x /usr/local/bin/patch-delete-project-collections && \ - chmod +x /usr/local/bin/delete-orphaned-projects && \ - chmod +x /usr/local/bin/clear-card-cache && \ - chmod +x /usr/local/bin/calc-users-stats && \ - chmod +x /usr/local/bin/calc-tier-stats && \ - chmod +x /usr/local/bin/get-migration-stats && \ - chmod +x /usr/local/bin/create-inf-metric - # Letsencrypt Permissions RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/ diff --git a/README.md b/README.md index 62b084d320..88b4173f1d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -> Great news! Appwrite Cloud is now in public beta! Sign up at [cloud.appwrite.io](https://cloud.appwrite.io) for a hassle-free, hosted experience. Join us in the Cloud today! ☁️🎉 +> Our Appwrite Init event has concluded. You can check out all the new and upcoming features [on our Init website](https://appwrite.io/init) 🚀

diff --git a/app/cli.php b/app/cli.php index d7cc5fe414..4e1df30f9a 100644 --- a/app/cli.php +++ b/app/cli.php @@ -131,9 +131,6 @@ CLI::setResource('queue', function (Group $pools) { CLI::setResource('queueForFunctions', function (Connection $queue) { return new Func($queue); }, ['queue']); -CLI::setResource('queueForHamster', function (Connection $queue) { - return new Hamster($queue); -}, ['queue']); CLI::setResource('queueForDeletes', function (Connection $queue) { return new Delete($queue); }, ['queue']); diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 345486b657..3df4d47355 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -555,7 +555,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userId', $userId), + Query::notEqual('userInternalId', $user->getInternalId()), ]); if (!empty($identityWithMatchingEmail)) { throw new Exception(Exception::USER_ALREADY_EXISTS); @@ -1985,7 +1985,7 @@ App::patch('/v1/account/email') // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userId', $user->getId()), + Query::notEqual('userInternalId', $user->getInternalId()), ]); if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index e0d967eb00..d0f8072f2c 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -23,6 +23,7 @@ use Utopia\Validator\URL; use Utopia\Validator\WhiteList; use chillerlan\QRCode\QRCode; use chillerlan\QRCode\QROptions; +use Utopia\Fetch\Client; $avatarCallback = function (string $type, string $code, int $width, int $height, int $quality, Response $response) { @@ -283,14 +284,21 @@ App::get('/v1/avatars/image') throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); } - $fetch = @\file_get_contents($url); + $client = new Client(); + try { + $res = $client + ->setAllowRedirects(false) + ->fetch($url); + } catch (\Throwable) { + throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); + } - if (!$fetch) { + if ($res->getStatusCode() !== 200) { throw new Exception(Exception::AVATAR_IMAGE_NOT_FOUND); } try { - $image = new Image($fetch); + $image = new Image($res->getBody()); } catch (\Exception $exception) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unable to parse image'); } @@ -339,31 +347,27 @@ App::get('/v1/avatars/favicon') throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); } - $curl = \curl_init(); + $client = new Client(); + try { + $res = $client + ->setAllowRedirects(false) + ->setUserAgent(\sprintf( + APP_USERAGENT, + App::getEnv('_APP_VERSION', 'UNKNOWN'), + App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY) + )) + ->fetch($url); + } catch (\Throwable) { + throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); + } - \curl_setopt_array($curl, [ - CURLOPT_RETURNTRANSFER => 1, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_MAXREDIRS => 3, - CURLOPT_URL => $url, - CURLOPT_USERAGENT => \sprintf( - APP_USERAGENT, - App::getEnv('_APP_VERSION', 'UNKNOWN'), - App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY) - ), - ]); - - $html = \curl_exec($curl); - - \curl_close($curl); - - if (!$html) { + if ($res->getStatusCode() !== 200) { throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); } $doc = new DOMDocument(); $doc->strictErrorChecking = false; - @$doc->loadHTML($html); + @$doc->loadHTML($res->getBody()); $links = $doc->getElementsByTagName('link'); $outputHref = ''; @@ -418,9 +422,22 @@ App::get('/v1/avatars/favicon') throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); } - if ('ico' == $outputExt) { // Skip crop, Imagick isn\'t supporting icon files - $data = @\file_get_contents($outputHref, false); + $client = new Client(); + try { + $res = $client + ->setAllowRedirects(false) + ->fetch($outputHref); + } catch (\Throwable) { + throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED); + } + if ($res->getStatusCode() !== 200) { + throw new Exception(Exception::AVATAR_ICON_NOT_FOUND); + } + + $data = $res->getBody(); + + if ('ico' == $outputExt) { // Skip crop, Imagick isn\'t supporting icon files if (empty($data) || (\mb_substr($data, 0, 5) === 'file($data); } - $fetch = @\file_get_contents($outputHref, false); - - if (!$fetch) { - throw new Exception(Exception::AVATAR_ICON_NOT_FOUND); - } - - $image = new Image($fetch); + $image = new Image($data); $image->crop((int) $width, (int) $height); $output = (empty($output)) ? $type : $output; $data = $image->output($output, $quality); diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index d9faf998e6..6a2c1b0bed 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -796,12 +796,12 @@ App::get('/v1/health/queue/failed/:name') Event::MAILS_QUEUE_NAME, Event::FUNCTIONS_QUEUE_NAME, Event::USAGE_QUEUE_NAME, + Event::USAGE_DUMP_QUEUE_NAME, Event::WEBHOOK_CLASS_NAME, Event::CERTIFICATES_QUEUE_NAME, Event::BUILDS_QUEUE_NAME, Event::MESSAGING_QUEUE_NAME, - Event::MIGRATIONS_QUEUE_NAME, - Event::HAMSTER_CLASS_NAME + Event::MIGRATIONS_QUEUE_NAME ]), 'The name of the queue') ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) ->label('sdk.description', '/docs/references/health/get-failed-queue-jobs.md') diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 978429e51c..03f158c131 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -916,7 +916,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $user->setAttributes($dbForProject->getDocument('users', $userId)->getArrayCopy()); // Get user } - if ($membership->getAttribute('userId') !== $user->getId()) { + if ($membership->getAttribute('userInternalId') !== $user->getInternalId()) { throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); } diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 5ce2263f47..6a0d6f3d7a 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -941,7 +941,7 @@ App::patch('/v1/users/:userId/email') // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userId', $user->getId()), + Query::notEqual('userInternalId', $user->getInternalId()), ]); if ($identityWithMatchingEmail !== false && !$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 1b0c993e11..0d87c101ad 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -95,7 +95,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; - if (!empty($providerPullRequestId)) { + if (!empty($providerPullRequestId) && $function->getAttribute('providerSilentMode', false) === false) { $latestComment = Authorization::skip(fn () => $dbForConsole->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), diff --git a/app/controllers/general.php b/app/controllers/general.php index 11fabe7550..13a86ac36b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -167,7 +167,7 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $permissions = $function->getAttribute('execute'); - if (!(\in_array('any', $permissions)) && (\in_array('guests', $permissions))) { + if (!(\in_array('any', $permissions)) && !(\in_array('guests', $permissions))) { throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"'); } diff --git a/app/views/general/error.phtml b/app/views/general/error.phtml index 450dcf8973..a3715e0156 100644 --- a/app/views/general/error.phtml +++ b/app/views/general/error.phtml @@ -59,7 +59,7 @@ $title = $this->getParam('title', '') - <?php echo $this->print($title, self::FILTER_ESCAPE); ?> + <?php echo $this->print($title); ?>