Resolve merge conflicts

This commit is contained in:
Khushboo Verma
2024-01-10 13:13:09 +05:30
17 changed files with 535 additions and 301 deletions
+11 -7
View File
@@ -8,6 +8,7 @@ use Appwrite\Docker\Env;
use Appwrite\Utopia\View;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
use Utopia\Platform\Action;
@@ -24,15 +25,16 @@ class Install extends Action
{
$this
->desc('Install Appwrite')
->param('httpPort', '', new Text(4), 'Server HTTP port', true)
->param('httpsPort', '', new Text(4), 'Server HTTPS port', true)
->param('http-port', '', new Text(4), 'Server HTTP port', true)
->param('https-port', '', new Text(4), 'Server HTTPS port', true)
->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true)
->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true)
->param('interactive', 'Y', new Text(1), 'Run an interactive session', true)
->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive));
->param('no-start', false, new Boolean(true), 'Run an interactive session', true)
->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive, $noStart) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive, $noStart));
}
public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive): void
public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive, bool $noStart): void
{
$config = Config::getParam('variables');
$defaultHTTPPort = '80';
@@ -220,9 +222,11 @@ class Install extends Action
}
}
Console::log("Running \"docker compose up -d --remove-orphans --renew-anon-volumes\"");
$exit = Console::execute("$env docker compose --project-directory $this->path up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr);
$exit = 0;
if (!$noStart) {
Console::log("Running \"docker compose up -d --remove-orphans --renew-anon-volumes\"");
$exit = Console::execute("$env docker compose --project-directory $this->path up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr);
}
if ($exit !== 0) {
$message = 'Failed to install Appwrite dockers';
+7 -5
View File
@@ -3,6 +3,7 @@
namespace Appwrite\Platform\Tasks;
use Utopia\CLI\Console;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
class Upgrade extends Install
@@ -16,15 +17,16 @@ class Upgrade extends Install
{
$this
->desc('Upgrade Appwrite')
->param('httpPort', '', new Text(4), 'Server HTTP port', true)
->param('httpsPort', '', new Text(4), 'Server HTTPS port', true)
->param('http-port', '', new Text(4), 'Server HTTP port', true)
->param('https-port', '', new Text(4), 'Server HTTPS port', true)
->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true)
->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true)
->param('interactive', 'Y', new Text(1), 'Run an interactive session', true)
->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive));
->param('no-start', false, new Boolean(true), 'Run an interactive session', true)
->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive, $noStart) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive, $noStart));
}
public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive): void
public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive, bool $noStart): void
{
// Check for previous installation
$data = @file_get_contents($this->path . '/docker-compose.yml');
@@ -37,6 +39,6 @@ class Upgrade extends Install
Console::log(' └── docker-compose.yml');
Console::exit(1);
}
parent::action($httpPort, $httpsPort, $organization, $image, $interactive);
parent::action($httpPort, $httpsPort, $organization, $image, $interactive, $noStart);
}
}
+95 -48
View File
@@ -13,22 +13,23 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Messaging\Adapters\SMS as SMSAdapter;
use Utopia\Messaging\Adapters\SMS\Mock;
use Utopia\Messaging\Adapters\SMS\Msg91;
use Utopia\Messaging\Adapters\SMS\Telesign;
use Utopia\Messaging\Adapters\SMS\Textmagic;
use Utopia\Messaging\Adapters\SMS\Twilio;
use Utopia\Messaging\Adapters\SMS\Vonage;
use Utopia\Messaging\Adapters\Push as PushAdapter;
use Utopia\Messaging\Adapters\Push\APNS;
use Utopia\Messaging\Adapters\Push\FCM;
use Utopia\Messaging\Adapters\Email as EmailAdapter;
use Utopia\Messaging\Adapters\Email\Mailgun;
use Utopia\Messaging\Adapters\Email\SendGrid;
use Utopia\Messaging\Adapter\Email as EmailAdapter;
use Utopia\Messaging\Adapter\Email\Mailgun;
use Utopia\Messaging\Adapter\Email\Sendgrid;
use Utopia\Messaging\Adapter\Push as PushAdapter;
use Utopia\Messaging\Adapter\Push\APNS;
use Utopia\Messaging\Adapter\Push\FCM;
use Utopia\Messaging\Adapter\SMS as SMSAdapter;
use Utopia\Messaging\Adapter\SMS\Mock;
use Utopia\Messaging\Adapter\SMS\Msg91;
use Utopia\Messaging\Adapter\SMS\Telesign;
use Utopia\Messaging\Adapter\SMS\Textmagic;
use Utopia\Messaging\Adapter\SMS\Twilio;
use Utopia\Messaging\Adapter\SMS\Vonage;
use Utopia\Messaging\Messages\Email;
use Utopia\Messaging\Messages\Push;
use Utopia\Messaging\Messages\SMS;
use Utopia\Messaging\Response;
use function Swoole\Coroutine\batch;
@@ -62,7 +63,7 @@ class Messaging extends Action
$payload = $message->getPayload() ?? [];
if (empty($payload)) {
Console::error('Payload arg not found');
Console::error('Payload not found.');
return;
}
@@ -84,14 +85,14 @@ class Messaging extends Action
$usersId = $message->getAttribute('users', []);
/**
* @var Document[] $recipients
*/
* @var Document[] $recipients
*/
$recipients = [];
if (\count($topicsId) > 0) {
$topics = $dbForProject->find('topics', [Query::equal('$id', $topicsId)]);
foreach ($topics as $topic) {
$targets = \array_filter($topic->getAttribute('targets'), fn (Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
$targets = \array_filter($topic->getAttribute('targets'), fn(Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
$recipients = \array_merge($recipients, $targets);
}
}
@@ -99,7 +100,7 @@ class Messaging extends Action
if (\count($usersId) > 0) {
$users = $dbForProject->find('users', [Query::equal('$id', $usersId)]);
foreach ($users as $user) {
$targets = \array_filter($user->getAttribute('targets'), fn (Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
$targets = \array_filter($user->getAttribute('targets'), fn(Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
$recipients = \array_merge($recipients, $targets);
}
}
@@ -115,14 +116,16 @@ class Messaging extends Action
]);
/**
* @var array<string, array<string>> $identifiersByProviderId
*/
* @var array<string, array<string>> $identifiersByProviderId
*/
$identifiersByProviderId = [];
/**
* @var Document[] $providers
*/
$providers = [];
* @var Document[] $providers
*/
$providers = [
$primaryProvider->getId() => $primaryProvider
];
foreach ($recipients as $recipient) {
$providerId = $recipient->getAttribute('providerId');
@@ -139,29 +142,28 @@ class Messaging extends Action
}
/**
* @var array[] $results
*/
* @var array[] $results
*/
$results = batch(\array_map(function ($providerId) use ($identifiersByProviderId, $providers, $primaryProvider, $message, $dbForProject) {
return function () use ($providerId, $identifiersByProviderId, $providers, $primaryProvider, $message, $dbForProject) {
$provider = new Document();
if ($primaryProvider->getId() === $providerId) {
$provider = $primaryProvider;
if (\array_key_exists($providerId, $providers)) {
$provider = $providers[$providerId];
} else {
$provider = $dbForProject->getDocument('providers', $providerId, [Query::equal('enabled', [true])]);
if ($provider->isEmpty()) {
$provider = $primaryProvider;
} else {
$providers[$providerId] = $provider;
}
}
$providers[] = $provider;
$identifiers = $identifiersByProviderId[$providerId];
$adapter = match ($provider->getAttribute('type')) {
MESSAGE_TYPE_SMS => $this->sms($provider),
MESSAGE_TYPE_PUSH => $this->push($provider),
MESSAGE_TYPE_EMAIL => $this->email($provider),
MESSAGE_TYPE_EMAIL => $this->email($provider),
default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE)
};
@@ -169,8 +171,8 @@ class Messaging extends Action
$batches = \array_chunk($identifiers, $maxBatchSize);
$batchIndex = 0;
$results = batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex) {
return function () use ($batch, $message, $provider, $adapter, $batchIndex) {
return batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex, $dbForProject) {
return function () use ($batch, $message, $provider, $adapter, $batchIndex, $dbForProject) {
$deliveredTotal = 0;
$deliveryErrors = [];
$messageData = clone $message;
@@ -179,13 +181,29 @@ class Messaging extends Action
$data = match ($provider->getAttribute('type')) {
MESSAGE_TYPE_SMS => $this->buildSMSMessage($messageData, $provider),
MESSAGE_TYPE_PUSH => $this->buildPushMessage($messageData),
MESSAGE_TYPE_EMAIL => $this->buildEmailMessage($messageData, $provider),
MESSAGE_TYPE_EMAIL => $this->buildEmailMessage($dbForProject, $messageData, $provider),
default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE)
};
try {
$adapter->send($data);
$deliveredTotal += \count($batch);
$response = new Response($provider->getAttribute('type'));
$response->fromArray($adapter->send($data));
$deliveredTotal += $response->getDeliveredTo();
$details[] = $response->getDetails();
foreach ($details as $detail) {
if ($detail['status'] === 'failure') {
$deliveryErrors[] = "Failed sending to target {$detail['recipient']} with error: {$detail['error']}";
}
// Deleting push targets when token has expired.
if ($detail['error'] === 'Expired device token.') {
$target = $dbForProject->findOne('targets', [Query::equal('identifier', [$detail['recipient']])]);
if ($target instanceof Document && !$target->isEmpty()) {
$dbForProject->deleteDocument('targets', $target->getId());
}
}
}
} catch (\Exception $e) {
$deliveryErrors[] = 'Failed sending to targets ' . $batchIndex + 1 . '-' . \count($batch) . ' with error: ' . $e->getMessage();
} finally {
@@ -197,8 +215,6 @@ class Messaging extends Action
}
};
}, $batches));
return $results;
};
}, \array_keys($identifiersByProviderId)));
@@ -313,7 +329,7 @@ class Messaging extends Action
'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']),
'textmagic' => new Textmagic($credentials['username'], $credentials['apiKey']),
'telesign' => new Telesign($credentials['username'], $credentials['password']),
'msg91' => new Msg91($credentials['senderId'], $credentials['authKey']),
'msg91' => new Msg91($credentials['senderId'], $credentials['authKey'], $credentials['templateId']),
'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']),
default => null
};
@@ -323,6 +339,7 @@ class Messaging extends Action
{
$credentials = $provider->getAttribute('credentials');
return match ($provider->getAttribute('provider')) {
'mock' => new Mock('username', 'password'),
'apns' => new APNS(
$credentials['authKey'],
$credentials['authKeyId'],
@@ -330,7 +347,7 @@ class Messaging extends Action
$credentials['bundleId'],
$credentials['endpoint']
),
'fcm' => new FCM($credentials['serverKey']),
'fcm' => new FCM($credentials['serviceAccountJSON']),
default => null
};
}
@@ -339,21 +356,51 @@ class Messaging extends Action
{
$credentials = $provider->getAttribute('credentials');
return match ($provider->getAttribute('provider')) {
'mock' => new Mock('username', 'password'),
'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain'], $credentials['isEuRegion']),
'sendgrid' => new SendGrid($credentials['apiKey']),
'sendgrid' => new Sendgrid($credentials['apiKey']),
default => null
};
}
private function buildEmailMessage(Document $message, Document $provider): Email
private function buildEmailMessage(Database $dbForProject, Document $message, Document $provider): Email
{
$from = $provider['options']['from'];
$to = $message['to'];
$subject = $message['data']['subject'];
$content = $message['data']['content'];
$html = $message['data']['html'];
$fromName = $provider['options']['fromName'];
$fromEmail = $provider['options']['fromEmail'];
$replyToEmail = null;
$replyToName = null;
return new Email($to, $subject, $content, $from, null, $html);
if (isset($provider['options']['replyToName']) && isset($provider['options']['replyToEmail'])) {
$replyToName = $provider['options']['replyToName'];
$replyToEmail = $provider['options']['replyToEmail'];
}
$data = $message['data'] ?? [];
$ccTargets = $data['cc'] ?? [];
$bccTargets = $data['bcc'] ?? [];
$cc = [];
$bcc = [];
if (\count($ccTargets) > 0) {
$ccTargets = $dbForProject->find('targets', [Query::equal('identifier', $ccTargets)]);
foreach ($ccTargets as $ccTarget) {
$cc[] = ['email' => $ccTarget['identifier']];
}
}
if (\count($bccTargets) > 0) {
$bccTargets = $dbForProject->find('targets', [Query::equal('identifier', $bccTargets)]);
foreach ($bccTargets as $bccTarget) {
$bcc[] = ['email' => $bccTarget['identifier']];
}
}
$to = $message['to'];
$subject = $data['subject'];
$content = $data['content'];
$html = $data['html'];
return new Email($to, $subject, $content, $fromName, $fromEmail, $replyToName, $replyToEmail, $cc, $bcc, null, $html);
}
private function buildSMSMessage(Document $message, Document $provider): SMS
@@ -7,6 +7,7 @@ class Topics extends Base
public const ALLOWED_ATTRIBUTES = [
'name',
'description',
'total'
];
/**
+3 -3
View File
@@ -72,6 +72,7 @@ class Executor
) {
$runtimeId = "$projectId-$deploymentId-build";
$route = "/runtimes";
$timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900);
$params = [
'runtimeId' => $runtimeId,
'source' => $source,
@@ -84,10 +85,9 @@ class Executor
'cpus' => $this->cpus,
'memory' => $this->memory,
'version' => $version,
'timeout' => $timeout,
];
$timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900);
$response = $this->call(self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout);
$status = $response['headers']['status-code'];
@@ -111,7 +111,7 @@ class Executor
string $projectId,
callable $callback
) {
$timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900);
$timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900);
$runtimeId = "$projectId-$deploymentId-build";
$route = "/runtimes/{$runtimeId}/logs";