mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '1.5.x' of https://github.com/appwrite/appwrite into feat-rc-sdks
This commit is contained in:
@@ -279,7 +279,7 @@ class Firebase extends OAuth2
|
||||
$role = \json_decode($role, true);
|
||||
|
||||
return $role;
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
if ($e->getCode() !== 404) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
@@ -244,7 +244,9 @@ class Exception extends \Exception
|
||||
public const REALTIME_POLICY_VIOLATION = 'realtime_policy_violation';
|
||||
|
||||
/** Health */
|
||||
public const QUEUE_SIZE_EXCEEDED = 'queue_size_exceeded';
|
||||
public const HEALTH_QUEUE_SIZE_EXCEEDED = 'health_queue_size_exceeded';
|
||||
public const HEALTH_CERTIFICATE_EXPIRED = 'health_certificate_expired';
|
||||
public const HEALTH_INVALID_HOST = 'health_invalid_host';
|
||||
|
||||
/** Provider */
|
||||
public const PROVIDER_NOT_FOUND = 'provider_not_found';
|
||||
@@ -264,6 +266,8 @@ class Exception extends \Exception
|
||||
public const MESSAGE_NOT_FOUND = 'message_not_found';
|
||||
public const MESSAGE_MISSING_TARGET = 'message_missing_target';
|
||||
public const MESSAGE_ALREADY_SENT = 'message_already_sent';
|
||||
public const MESSAGE_ALREADY_PROCESSING = 'message_already_processing';
|
||||
public const MESSAGE_ALREADY_FAILED = 'message_already_failed';
|
||||
public const MESSAGE_ALREADY_SCHEDULED = 'message_already_scheduled';
|
||||
public const MESSAGE_TARGET_NOT_EMAIL = 'message_target_not_email';
|
||||
public const MESSAGE_TARGET_NOT_SMS = 'message_target_not_sms';
|
||||
@@ -276,21 +280,16 @@ class Exception extends \Exception
|
||||
|
||||
protected string $type = '';
|
||||
protected array $errors = [];
|
||||
protected bool $publish = true;
|
||||
protected bool $publish;
|
||||
|
||||
public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int $code = null, \Throwable $previous = null)
|
||||
{
|
||||
$this->errors = Config::getParam('errors');
|
||||
$this->type = $type;
|
||||
$this->code = $code ?? $this->errors[$type]['code'];
|
||||
$this->message = $message ?? $this->errors[$type]['description'];
|
||||
|
||||
if (isset($this->errors[$type])) {
|
||||
$this->code = $this->errors[$type]['code'];
|
||||
$this->message = $this->errors[$type]['description'];
|
||||
$this->publish = $this->errors[$type]['publish'] ?? true;
|
||||
}
|
||||
|
||||
$this->message = $message ?? $this->message;
|
||||
$this->code = $code ?? $this->code;
|
||||
$this->publish = $this->errors[$type]['publish'] ?? ($this->code >= 500);
|
||||
|
||||
parent::__construct($this->message, $this->code, $previous);
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ abstract class Migration
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::warning($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ use Utopia\Validator;
|
||||
|
||||
class CNAME extends Validator
|
||||
{
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected mixed $logs;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -27,6 +32,14 @@ class CNAME extends Validator
|
||||
return 'Invalid CNAME record';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLogs(): mixed
|
||||
{
|
||||
return $this->logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if CNAME record target value matches selected target
|
||||
*
|
||||
@@ -42,6 +55,7 @@ class CNAME extends Validator
|
||||
|
||||
try {
|
||||
$records = \dns_get_record($domain, DNS_CNAME);
|
||||
$this->logs = $records;
|
||||
} catch (\Throwable $th) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Appwrite\Platform\Services;
|
||||
|
||||
use Appwrite\Platform\Tasks\CalcTierStats;
|
||||
use Appwrite\Platform\Tasks\CreateInfMetric;
|
||||
use Appwrite\Platform\Tasks\DeleteOrphanedProjects;
|
||||
use Appwrite\Platform\Tasks\DevGenerateTranslations;
|
||||
use Appwrite\Platform\Tasks\Doctor;
|
||||
@@ -12,6 +13,8 @@ use Appwrite\Platform\Tasks\Install;
|
||||
use Appwrite\Platform\Tasks\Maintenance;
|
||||
use Appwrite\Platform\Tasks\Migrate;
|
||||
use Appwrite\Platform\Tasks\PatchRecreateRepositoriesDocuments;
|
||||
use Appwrite\Platform\Tasks\QueueCount;
|
||||
use Appwrite\Platform\Tasks\QueueRetry;
|
||||
use Appwrite\Platform\Tasks\SDKs;
|
||||
use Appwrite\Platform\Tasks\SSL;
|
||||
use Appwrite\Platform\Tasks\ScheduleFunctions;
|
||||
@@ -21,7 +24,6 @@ use Appwrite\Platform\Tasks\Upgrade;
|
||||
use Appwrite\Platform\Tasks\Vars;
|
||||
use Appwrite\Platform\Tasks\Version;
|
||||
use Appwrite\Platform\Tasks\VolumeSync;
|
||||
use Appwrite\Platform\Tasks\CreateInfMetric;
|
||||
use Utopia\Platform\Service;
|
||||
|
||||
class Tasks extends Service
|
||||
@@ -30,19 +32,8 @@ class Tasks extends Service
|
||||
{
|
||||
$this->type = self::TYPE_CLI;
|
||||
$this
|
||||
->addAction(Version::getName(), new Version())
|
||||
->addAction(Vars::getName(), new Vars())
|
||||
->addAction(SSL::getName(), new SSL())
|
||||
->addAction(Hamster::getName(), new Hamster())
|
||||
->addAction(Doctor::getName(), new Doctor())
|
||||
->addAction(Install::getName(), new Install())
|
||||
->addAction(Upgrade::getName(), new Upgrade())
|
||||
->addAction(Maintenance::getName(), new Maintenance())
|
||||
->addAction(Migrate::getName(), new Migrate())
|
||||
->addAction(SDKs::getName(), new SDKs())
|
||||
->addAction(VolumeSync::getName(), new VolumeSync())
|
||||
->addAction(Specs::getName(), new Specs())
|
||||
->addAction(CalcTierStats::getName(), new CalcTierStats())
|
||||
->addAction(CreateInfMetric::getName(), new CreateInfMetric())
|
||||
->addAction(DeleteOrphanedProjects::getName(), new DeleteOrphanedProjects())
|
||||
->addAction(DevGenerateTranslations::getName(), new DevGenerateTranslations())
|
||||
->addAction(Doctor::getName(), new Doctor())
|
||||
@@ -51,7 +42,10 @@ class Tasks extends Service
|
||||
->addAction(Install::getName(), new Install())
|
||||
->addAction(Maintenance::getName(), new Maintenance())
|
||||
->addAction(Migrate::getName(), new Migrate())
|
||||
->addAction(Migrate::getName(), new Migrate())
|
||||
->addAction(PatchRecreateRepositoriesDocuments::getName(), new PatchRecreateRepositoriesDocuments())
|
||||
->addAction(QueueCount::getName(), new QueueCount())
|
||||
->addAction(QueueRetry::getName(), new QueueRetry())
|
||||
->addAction(SDKs::getName(), new SDKs())
|
||||
->addAction(SSL::getName(), new SSL())
|
||||
->addAction(ScheduleFunctions::getName(), new ScheduleFunctions())
|
||||
@@ -61,7 +55,6 @@ class Tasks extends Service
|
||||
->addAction(Vars::getName(), new Vars())
|
||||
->addAction(Version::getName(), new Version())
|
||||
->addAction(VolumeSync::getName(), new VolumeSync())
|
||||
->addAction(CreateInfMetric::getName(), new CreateInfMetric())
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Appwrite\Platform\Tasks;
|
||||
|
||||
use Exception;
|
||||
use League\Csv\CannotInsertRecord;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\Document;
|
||||
@@ -200,7 +199,7 @@ class CalcTierStats extends Action
|
||||
$mail->Body = "Please find the daily cloud report atttached";
|
||||
$mail->send();
|
||||
Console::success('Email has been sent!');
|
||||
} catch (Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::error("Message could not be sent. Mailer Error: {$mail->ErrorInfo}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Appwrite\Platform\Tasks;
|
||||
|
||||
use Exception;
|
||||
use League\Csv\CannotInsertRecord;
|
||||
use Utopia\App;
|
||||
use Utopia\Platform\Action;
|
||||
@@ -180,7 +179,7 @@ class GetMigrationStats extends Action
|
||||
$mail->Body = "Please find the migration report atttached";
|
||||
$mail->send();
|
||||
Console::success('Email has been sent!');
|
||||
} catch (Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::error("Message could not be sent. Mailer Error: {$mail->ErrorInfo}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Appwrite\Platform\Tasks;
|
||||
|
||||
use Appwrite\Event\Hamster as EventHamster;
|
||||
use Exception;
|
||||
use Utopia\App;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\CLI\Console;
|
||||
@@ -120,7 +119,7 @@ class Hamster extends Action
|
||||
->setType(EventHamster::TYPE_ORGANISATION)
|
||||
->setOrganization($organization)
|
||||
->trigger();
|
||||
} catch (Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::error($e->getMessage());
|
||||
}
|
||||
});
|
||||
@@ -135,7 +134,7 @@ class Hamster extends Action
|
||||
->setType(EventHamster::TYPE_PROJECT)
|
||||
->setProject($project)
|
||||
->trigger();
|
||||
} catch (Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::error($e->getMessage());
|
||||
}
|
||||
});
|
||||
@@ -150,7 +149,7 @@ class Hamster extends Action
|
||||
->setType(EventHamster::TYPE_USER)
|
||||
->setUser($user)
|
||||
->trigger();
|
||||
} catch (Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::error($e->getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -36,6 +36,7 @@ class Maintenance extends Action
|
||||
|
||||
// # of days in seconds (1 day = 86400s)
|
||||
$interval = (int) App::getEnv('_APP_MAINTENANCE_INTERVAL', '86400');
|
||||
$delay = (int) App::getEnv('_APP_MAINTENANCE_DELAY', '0');
|
||||
$usageStatsRetentionHourly = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_USAGE_HOURLY', '8640000'); //100 days
|
||||
$cacheRetention = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_CACHE', '2592000'); // 30 days
|
||||
$schedulesDeletionRetention = (int) App::getEnv('_APP_MAINTENANCE_RETENTION_SCHEDULES', '86400'); // 1 Day
|
||||
@@ -60,7 +61,7 @@ class Maintenance extends Action
|
||||
$this->notifyDeleteCache($cacheRetention, $queueForDeletes);
|
||||
$this->notifyDeleteSchedules($schedulesDeletionRetention, $queueForDeletes);
|
||||
$this->notifyDeleteTargets($queueForDeletes);
|
||||
}, $interval);
|
||||
}, $interval, $delay);
|
||||
}
|
||||
|
||||
protected function foreachProject(Database $dbForConsole, callable $callback): void
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Tasks;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Client;
|
||||
use Utopia\Queue\Connection;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class QueueCount extends Action
|
||||
{
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'queue-count';
|
||||
}
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->desc('Return the number of from a specific queue identified by the name parameter with a specific type')
|
||||
->param('name', '', new WhiteList([
|
||||
Event::DATABASE_QUEUE_NAME,
|
||||
Event::DELETE_QUEUE_NAME,
|
||||
Event::AUDITS_QUEUE_NAME,
|
||||
Event::MAILS_QUEUE_NAME,
|
||||
Event::FUNCTIONS_QUEUE_NAME,
|
||||
Event::USAGE_QUEUE_NAME,
|
||||
Event::WEBHOOK_QUEUE_NAME,
|
||||
Event::CERTIFICATES_QUEUE_NAME,
|
||||
Event::BUILDS_QUEUE_NAME,
|
||||
Event::MESSAGING_QUEUE_NAME,
|
||||
Event::MIGRATIONS_QUEUE_NAME,
|
||||
Event::HAMSTER_QUEUE_NAME
|
||||
]), 'Queue name')
|
||||
->param('type', '', new WhiteList([
|
||||
'success',
|
||||
'failed',
|
||||
'processing',
|
||||
]), 'Queue type')
|
||||
->inject('queue')
|
||||
->callback(fn ($name, $type, $queue) => $this->action($name, $type, $queue));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name The name of the queue to count the jobs from
|
||||
* @param string $type The type of jobs to count
|
||||
* @param Connection $queue
|
||||
*/
|
||||
public function action(string $name, string $type, Connection $queue): void
|
||||
{
|
||||
if (!$name) {
|
||||
Console::error('Missing required parameter $name');
|
||||
return;
|
||||
}
|
||||
|
||||
$queueClient = new Client($name, $queue);
|
||||
|
||||
$count = match ($type) {
|
||||
'success' => $queueClient->countSuccessfulJobs(),
|
||||
'failed' => $queueClient->countFailedJobs(),
|
||||
'processing' => $queueClient->countProcessingJobs(),
|
||||
default => 0
|
||||
};
|
||||
|
||||
Console::log("Queue: '{$name}' has {$count} {$type} jobs.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Tasks;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Client;
|
||||
use Utopia\Queue\Connection;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class QueueRetry extends Action
|
||||
{
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'queue-retry';
|
||||
}
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->desc('Retry failed jobs from a specific queue identified by the name parameter')
|
||||
->param('name', '', new WhiteList([
|
||||
Event::DATABASE_QUEUE_NAME,
|
||||
Event::DELETE_QUEUE_NAME,
|
||||
Event::AUDITS_QUEUE_NAME,
|
||||
Event::MAILS_QUEUE_NAME,
|
||||
Event::FUNCTIONS_QUEUE_NAME,
|
||||
Event::USAGE_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
|
||||
]), 'Queue name')
|
||||
->inject('queue')
|
||||
->callback(fn ($name, $queue) => $this->action($name, $queue));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name The name of the queue to retry jobs from
|
||||
* @param Connection $queue
|
||||
*/
|
||||
public function action(string $name, Connection $queue): void
|
||||
{
|
||||
if (!$name) {
|
||||
Console::error('Missing required parameter $name');
|
||||
return;
|
||||
}
|
||||
|
||||
$queueClient = new Client($name, $queue);
|
||||
|
||||
if ($queueClient->countFailedJobs() === 0) {
|
||||
Console::error('No failed jobs found.');
|
||||
return;
|
||||
}
|
||||
|
||||
Console::log('Retrying failed jobs...');
|
||||
|
||||
$queueClient->retry();
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,6 @@ use Appwrite\SDK\Language\Python;
|
||||
use Appwrite\SDK\Language\REST;
|
||||
use Appwrite\SDK\Language\Ruby;
|
||||
use Appwrite\SDK\Language\Swift;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
use Appwrite\SDK\Language\Apple;
|
||||
use Appwrite\SDK\Language\Web;
|
||||
use Appwrite\SDK\SDK;
|
||||
@@ -242,9 +240,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
|
||||
try {
|
||||
$sdk->generate($result);
|
||||
} catch (Exception $exception) {
|
||||
Console::error($exception->getMessage());
|
||||
} catch (Throwable $exception) {
|
||||
} catch (\Throwable $exception) {
|
||||
Console::error($exception->getMessage());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use Appwrite\Event\Certificate;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Hostname;
|
||||
|
||||
class SSL extends Action
|
||||
@@ -21,19 +22,22 @@ class SSL extends Action
|
||||
$this
|
||||
->desc('Validate server certificates')
|
||||
->param('domain', App::getEnv('_APP_DOMAIN', ''), new Hostname(), 'Domain to generate certificate for. If empty, main domain will be used.', true)
|
||||
->param('skip-check', true, new Boolean(true), 'If DNS and renew check should be skipped. Defaults to true, and when true, all jobs will result in certificate generation attempt.', true)
|
||||
->inject('queueForCertificates')
|
||||
->callback(fn (string $domain, Certificate $queueForCertificates) => $this->action($domain, $queueForCertificates));
|
||||
->callback(fn (string $domain, bool|string $skipCheck, Certificate $queueForCertificates) => $this->action($domain, $skipCheck, $queueForCertificates));
|
||||
}
|
||||
|
||||
public function action(string $domain, Certificate $queueForCertificates): void
|
||||
public function action(string $domain, bool|string $skipCheck, Certificate $queueForCertificates): void
|
||||
{
|
||||
$skipCheck = \strval($skipCheck) === 'true';
|
||||
|
||||
Console::success('Scheduling a job to issue a TLS certificate for domain: ' . $domain);
|
||||
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $domain
|
||||
]))
|
||||
->setSkipRenewCheck(true)
|
||||
->setSkipRenewCheck($skipCheck)
|
||||
->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ class Specs extends Action
|
||||
$formatInstance
|
||||
->setParam('name', APP_NAME)
|
||||
->setParam('description', 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)')
|
||||
->setParam('endpoint', 'https://HOSTNAME/v1')
|
||||
->setParam('endpoint', 'https://cloud.appwrite.io/v1')
|
||||
->setParam('version', APP_VERSION_STABLE)
|
||||
->setParam('terms', $endpoint . '/policy/terms')
|
||||
->setParam('support.email', $email)
|
||||
|
||||
@@ -8,7 +8,6 @@ use Appwrite\Event\Usage;
|
||||
use Appwrite\Messaging\Adapter\Realtime;
|
||||
use Appwrite\Utopia\Response\Model\Deployment;
|
||||
use Appwrite\Vcs\Comment;
|
||||
use Exception;
|
||||
use Swoole\Coroutine as Co;
|
||||
use Executor\Executor;
|
||||
use Utopia\App;
|
||||
@@ -420,7 +419,7 @@ class Builds extends Action
|
||||
variables: $vars,
|
||||
command: $command
|
||||
);
|
||||
} catch (Exception $error) {
|
||||
} catch (\Throwable $error) {
|
||||
$err = $error;
|
||||
}
|
||||
}),
|
||||
@@ -459,7 +458,7 @@ class Builds extends Action
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (Exception $error) {
|
||||
} catch (\Throwable $error) {
|
||||
if (empty($err)) {
|
||||
$err = $error;
|
||||
}
|
||||
@@ -617,7 +616,7 @@ class Builds extends Action
|
||||
'$id' => $commentId
|
||||
]));
|
||||
break;
|
||||
} catch (Exception $err) {
|
||||
} catch (\Throwable $err) {
|
||||
if ($retries >= 9) {
|
||||
throw $err;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ class Certificates extends Action
|
||||
|
||||
$log->addTag('domain', $domain->get());
|
||||
|
||||
$this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $skipRenewCheck);
|
||||
$this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $skipRenewCheck);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +89,7 @@ class Certificates extends Action
|
||||
* @throws Throwable
|
||||
* @throws \Utopia\Database\Exception
|
||||
*/
|
||||
private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, bool $skipRenewCheck = false): void
|
||||
private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, bool $skipRenewCheck = false): void
|
||||
{
|
||||
/**
|
||||
* 1. Read arguments and validate domain
|
||||
@@ -143,11 +143,11 @@ class Certificates extends Action
|
||||
if (!$skipRenewCheck) {
|
||||
$mainDomain = $this->getMainDomain();
|
||||
$isMainDomain = !isset($mainDomain) || $domain->get() === $mainDomain;
|
||||
$this->validateDomain($domain, $isMainDomain);
|
||||
$this->validateDomain($domain, $isMainDomain, $log);
|
||||
}
|
||||
|
||||
// If certificate exists already, double-check expiry date. Skip if job is forced
|
||||
if (!$skipRenewCheck && !$this->isRenewRequired($domain->get())) {
|
||||
if (!$skipRenewCheck && !$this->isRenewRequired($domain->get(), $log)) {
|
||||
throw new Exception('Renew isn\'t required.');
|
||||
}
|
||||
|
||||
@@ -185,6 +185,8 @@ class Certificates extends Action
|
||||
|
||||
// Send email to security email
|
||||
$this->notifyError($domain->get(), $e->getMessage(), $attempts, $queueForMails);
|
||||
|
||||
throw $e;
|
||||
} finally {
|
||||
// All actions result in new updatedAt date
|
||||
$certificate->setAttribute('updated', DateTime::now());
|
||||
@@ -252,7 +254,7 @@ class Certificates extends Action
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function validateDomain(Domain $domain, bool $isMainDomain): void
|
||||
private function validateDomain(Domain $domain, bool $isMainDomain, Log $log): void
|
||||
{
|
||||
if (empty($domain->get())) {
|
||||
throw new Exception('Missing certificate domain.');
|
||||
@@ -272,8 +274,15 @@ class Certificates extends Action
|
||||
}
|
||||
|
||||
// Verify domain with DNS records
|
||||
$validationStart = \microtime(true);
|
||||
$validator = new CNAME($target->get());
|
||||
if (!$validator->isValid($domain->get())) {
|
||||
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
|
||||
$error = $validator->getLogs();
|
||||
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
|
||||
|
||||
throw new Exception('Failed to verify domain DNS records.');
|
||||
}
|
||||
} else {
|
||||
@@ -289,7 +298,7 @@ class Certificates extends Action
|
||||
* @return bool True, if certificate needs to be renewed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function isRenewRequired(string $domain): bool
|
||||
private function isRenewRequired(string $domain, Log $log): bool
|
||||
{
|
||||
$certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem';
|
||||
if (\file_exists($certPath)) {
|
||||
@@ -299,12 +308,15 @@ class Certificates extends Action
|
||||
$validTo = $certData['validTo_time_t'] ?? 0;
|
||||
|
||||
if (empty($validTo)) {
|
||||
$log->addTag('certificateDomain', $domain);
|
||||
throw new Exception('Unable to read certificate file (cert.pem).');
|
||||
}
|
||||
|
||||
// LetsEncrypt allows renewal 30 days before expiry
|
||||
$expiryInAdvance = (60 * 60 * 24 * 30);
|
||||
if ($validTo - $expiryInAdvance > \time()) {
|
||||
$log->addTag('certificateDomain', $domain);
|
||||
$log->addExtra('certificateData', \is_array($certData) ? \json_encode($certData) : \strval($certData));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ class Databases extends Action
|
||||
}
|
||||
|
||||
$dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available'));
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Send non DatabaseExceptions to Sentry
|
||||
Console::error($e->getMessage());
|
||||
|
||||
@@ -269,7 +269,7 @@ class Databases extends Action
|
||||
if (!$relatedAttribute->isEmpty()) {
|
||||
$dbForProject->deleteDocument('attributes', $relatedAttribute->getId());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Send non DatabaseExceptions to Sentry
|
||||
Console::error($e->getMessage());
|
||||
|
||||
@@ -397,7 +397,7 @@ class Databases extends Action
|
||||
throw new DatabaseException('Failed to create Index');
|
||||
}
|
||||
$dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available'));
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Send non DatabaseExceptions to Sentry
|
||||
Console::error($e->getMessage());
|
||||
|
||||
@@ -455,7 +455,7 @@ class Databases extends Action
|
||||
}
|
||||
$dbForProject->deleteDocument('indexes', $index->getId());
|
||||
$index->setAttribute('status', 'deleted');
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Send non DatabaseExceptions to Sentry
|
||||
Console::error($e->getMessage());
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ use Utopia\Audit\Audit;
|
||||
use Utopia\Cache\Adapter\Filesystem;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\Database\Database;
|
||||
use Exception;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\DateTime;
|
||||
@@ -585,7 +584,7 @@ class Deletes extends Action
|
||||
// Delete metadata tables
|
||||
try {
|
||||
$dbForProject->deleteCollection('_metadata');
|
||||
} catch (Exception) {
|
||||
} catch (\Throwable) {
|
||||
// Ignore: deleteCollection tries to delete a metadata entry after the collection is deleted,
|
||||
// which will throw an exception here because the metadata collection is already deleted.
|
||||
}
|
||||
@@ -630,12 +629,7 @@ class Deletes extends Action
|
||||
$teamId = $document->getAttribute('teamId');
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
if (!$team->isEmpty()) {
|
||||
$team = $dbForProject->updateDocument(
|
||||
'teams',
|
||||
$teamId,
|
||||
// Ensure that total >= 0
|
||||
$team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0))
|
||||
);
|
||||
$dbForProject->decreaseDocumentAttribute('teams', $teamId, 'total', 1, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -340,7 +340,7 @@ class Hamster extends Action
|
||||
if (!$res) {
|
||||
Console::error('Failed to create event for project: ' . $project->getId());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::error('Failed to send stats for project: ' . $project->getId());
|
||||
Console::error($e->getMessage());
|
||||
} finally {
|
||||
@@ -410,7 +410,7 @@ class Hamster extends Action
|
||||
if (!$res) {
|
||||
throw new \Exception('Failed to create event for organization : ' . $organization->getId());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
@@ -464,7 +464,7 @@ class Hamster extends Action
|
||||
if (!$res) {
|
||||
throw new \Exception('Failed to create user profile for user: ' . $user->getId());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
Console::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class Mails extends Action
|
||||
|
||||
try {
|
||||
$mail->send();
|
||||
} catch (\Exception $error) {
|
||||
} catch (\Throwable $error) {
|
||||
throw new Exception('Error sending mail: ' . $error->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,22 @@
|
||||
|
||||
namespace Appwrite\Platform\Workers;
|
||||
|
||||
use Appwrite\Event\Usage;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Messaging\Status as MessageStatus;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Message;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Messaging\Adapter\Email as EmailAdapter;
|
||||
use Utopia\Messaging\Adapter\Email\Mailgun;
|
||||
use Utopia\Messaging\Adapter\Email\Sendgrid;
|
||||
use Utopia\Messaging\Adapter\Email\SMTP;
|
||||
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;
|
||||
@@ -32,7 +31,8 @@ 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 Utopia\Platform\Action;
|
||||
use Utopia\Queue\Message;
|
||||
|
||||
use function Swoole\Coroutine\batch;
|
||||
|
||||
@@ -53,31 +53,40 @@ class Messaging extends Action
|
||||
->inject('message')
|
||||
->inject('log')
|
||||
->inject('dbForProject')
|
||||
->callback(fn(Message $message, Log $log, Database $dbForProject) => $this->action($message, $log, $dbForProject));
|
||||
->inject('queueForUsage')
|
||||
->callback(fn(Message $message, Log $log, Database $dbForProject, Usage $queueForUsage) => $this->action($message, $log, $dbForProject, $queueForUsage));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Message $message
|
||||
* @param Log $log
|
||||
* @param Database $dbForProject
|
||||
* @param Usage $queueForUsage
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function action(Message $message, Log $log, Database $dbForProject): void
|
||||
public function action(Message $message, Log $log, Database $dbForProject, Usage $queueForUsage): void
|
||||
{
|
||||
$payload = $message->getPayload() ?? [];
|
||||
|
||||
if (empty($payload)) {
|
||||
throw new \Exception('Payload not found.');
|
||||
throw new Exception('Missing payload');
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
!\is_null($payload['message'])
|
||||
&& !\is_null($payload['recipients'])
|
||||
&& $payload['providerType'] === MESSAGE_TYPE_SMS
|
||||
) {
|
||||
// Message was triggered internally
|
||||
$this->processInternalSMSMessage($log, new Document($payload['message']), $payload['recipients']);
|
||||
$this->processInternalSMSMessage(
|
||||
new Document($payload['message']),
|
||||
new Document($payload['project'] ?? []),
|
||||
$payload['recipients'],
|
||||
$queueForUsage,
|
||||
$log,
|
||||
);
|
||||
} else {
|
||||
$message = $dbForProject->getDocument('messages', $payload['messageId']);
|
||||
|
||||
@@ -254,8 +263,8 @@ class Messaging extends Action
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$deliveryErrors[] = 'Failed sending to targets ' . $batchIndex + 1 . '-' . \count($batch) . ' with error: ' . $e->getMessage();
|
||||
} catch (\Throwable $e) {
|
||||
$deliveryErrors[] = 'Failed sending to targets ' . $batchIndex + 1 . ' of ' . \count($batch) . ' with error: ' . $e->getMessage();
|
||||
} finally {
|
||||
$batchIndex++;
|
||||
|
||||
@@ -279,6 +288,10 @@ class Messaging extends Action
|
||||
$deliveryErrors = \array_merge($deliveryErrors, $result['deliveryErrors']);
|
||||
}
|
||||
|
||||
if (empty($deliveryErrors) && $deliveredTotal === 0) {
|
||||
$deliveryErrors[] = 'Unknown error';
|
||||
}
|
||||
|
||||
$message->setAttribute('deliveryErrors', $deliveryErrors);
|
||||
|
||||
if (\count($message->getAttribute('deliveryErrors')) > 0) {
|
||||
@@ -299,12 +312,26 @@ class Messaging extends Action
|
||||
$dbForProject->updateDocument('messages', $message->getId(), $message);
|
||||
}
|
||||
|
||||
private function processInternalSMSMessage(Log $log, Document $message, array $recipients): void
|
||||
private function processInternalSMSMessage(Document $message, Document $project, array $recipients, Usage $queueForUsage, Log $log): void
|
||||
{
|
||||
if (empty(App::getEnv('_APP_SMS_PROVIDER')) || empty(App::getEnv('_APP_SMS_FROM'))) {
|
||||
throw new \Exception('Skipped SMS processing. Missing "_APP_SMS_PROVIDER" or "_APP_SMS_FROM" environment variables.');
|
||||
}
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not set in payload');
|
||||
}
|
||||
|
||||
Console::log('Project: ' . $project->getId());
|
||||
|
||||
$denyList = App::getEnv('_APP_SMS_PROJECTS_DENY_LIST', '');
|
||||
$denyList = explode(',', $denyList);
|
||||
|
||||
if (\in_array($project->getId(), $denyList)) {
|
||||
Console::error('Project is in the deny list. Skipping...');
|
||||
return;
|
||||
}
|
||||
|
||||
$smsDSN = new DSN(App::getEnv('_APP_SMS_PROVIDER'));
|
||||
$host = $smsDSN->getHost();
|
||||
$password = $smsDSN->getPassword();
|
||||
@@ -330,8 +357,8 @@ class Messaging extends Action
|
||||
'apiKey' => $password
|
||||
],
|
||||
'telesign' => [
|
||||
'username' => $user,
|
||||
'password' => $password
|
||||
'customerId' => $user,
|
||||
'apiKey' => $password
|
||||
],
|
||||
'msg91' => [
|
||||
'senderId' => $user,
|
||||
@@ -354,16 +381,21 @@ class Messaging extends Action
|
||||
$batches = \array_chunk($recipients, $maxBatchSize);
|
||||
$batchIndex = 0;
|
||||
|
||||
batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex) {
|
||||
return function () use ($batch, $message, $provider, $adapter, $batchIndex) {
|
||||
batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex, $project, $queueForUsage) {
|
||||
return function () use ($batch, $message, $provider, $adapter, $batchIndex, $project, $queueForUsage) {
|
||||
$message->setAttribute('to', $batch);
|
||||
|
||||
$data = $this->buildSMSMessage($message, $provider);
|
||||
|
||||
try {
|
||||
$adapter->send($data);
|
||||
} catch (\Exception $e) {
|
||||
Console::error('Failed sending to targets ' . $batchIndex + 1 . '-' . \count($batch) . ' with error: ' . $e->getMessage()); // TODO: Find a way to log into Sentry
|
||||
|
||||
$queueForUsage
|
||||
->setProject($project)
|
||||
->addMetric(METRIC_MESSAGES, 1)
|
||||
->trigger();
|
||||
} catch (\Throwable $e) {
|
||||
throw new Exception('Failed sending to targets ' . $batchIndex + 1 . '-' . \count($batch) . ' with error: ' . $e->getMessage(), 500);
|
||||
}
|
||||
};
|
||||
}, $batches));
|
||||
@@ -376,11 +408,12 @@ class Messaging extends Action
|
||||
private function sms(Document $provider): ?SMSAdapter
|
||||
{
|
||||
$credentials = $provider->getAttribute('credentials');
|
||||
|
||||
return match ($provider->getAttribute('provider')) {
|
||||
'mock' => new Mock('username', 'password'),
|
||||
'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']),
|
||||
'textmagic' => new Textmagic($credentials['username'], $credentials['apiKey']),
|
||||
'telesign' => new Telesign($credentials['username'], $credentials['password']),
|
||||
'telesign' => new Telesign($credentials['customerId'], $credentials['apiKey']),
|
||||
'msg91' => new Msg91($credentials['senderId'], $credentials['authKey'], $credentials['templateId']),
|
||||
'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']),
|
||||
default => null
|
||||
@@ -390,6 +423,7 @@ class Messaging extends Action
|
||||
private function push(Document $provider): ?PushAdapter
|
||||
{
|
||||
$credentials = $provider->getAttribute('credentials');
|
||||
|
||||
return match ($provider->getAttribute('provider')) {
|
||||
'mock' => new Mock('username', 'password'),
|
||||
'apns' => new APNS(
|
||||
@@ -407,6 +441,7 @@ class Messaging extends Action
|
||||
{
|
||||
$credentials = $provider->getAttribute('credentials', []);
|
||||
$options = $provider->getAttribute('options', []);
|
||||
|
||||
return match ($provider->getAttribute('provider')) {
|
||||
'mock' => new Mock('username', 'password'),
|
||||
'smtp' => new SMTP(
|
||||
|
||||
@@ -20,7 +20,6 @@ class Usage extends Action
|
||||
];
|
||||
|
||||
protected const INFINITY_PERIOD = '_inf_';
|
||||
protected const DEBUG_PROJECT_ID = 85293;
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'usage';
|
||||
@@ -70,17 +69,6 @@ class Usage extends Action
|
||||
getProjectDB: $getProjectDB
|
||||
);
|
||||
}
|
||||
if ($project->getInternalId() == self::DEBUG_PROJECT_ID) {
|
||||
var_dump([
|
||||
'type' => 'payload',
|
||||
'project' => $project->getInternalId(),
|
||||
'database' => $project['database'] ?? '',
|
||||
$payload['metrics']
|
||||
]);
|
||||
|
||||
var_dump('==========================');
|
||||
}
|
||||
|
||||
self::$stats[$projectId]['project'] = $project;
|
||||
foreach ($payload['metrics'] ?? [] as $metric) {
|
||||
if (!isset(self::$stats[$projectId]['keys'][$metric['key']])) {
|
||||
@@ -91,7 +79,6 @@ class Usage extends Action
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* On Documents that tied by relations like functions>deployments>build || documents>collection>database || buckets>files.
|
||||
* When we remove a parent document we need to deduct his children aggregation from the project scope.
|
||||
@@ -231,7 +218,7 @@ class Usage extends Action
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
console::error("[reducer] " . " {DateTime::now()} " . " {$project->getInternalId()} " . " {$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,14 +57,6 @@ class UsageHook extends Usage
|
||||
|
||||
try {
|
||||
$dbForProject = $getProjectDB($data['project']);
|
||||
if ($projectInternalId == 85293) {
|
||||
var_dump([
|
||||
'project' => $projectInternalId,
|
||||
'database' => $database,
|
||||
'time' => DateTime::now(),
|
||||
'data' => $data['keys']
|
||||
]);
|
||||
}
|
||||
foreach ($data['keys'] ?? [] as $key => $value) {
|
||||
if ($value == 0) {
|
||||
continue;
|
||||
@@ -75,15 +67,6 @@ class UsageHook extends Usage
|
||||
$id = \md5("{$time}_{$period}_{$key}");
|
||||
|
||||
try {
|
||||
if ($projectInternalId == self::DEBUG_PROJECT_ID) {
|
||||
var_dump([
|
||||
'type' => 'create',
|
||||
'period' => $period,
|
||||
'metric' => $key,
|
||||
'id' => $id,
|
||||
'value' => $value
|
||||
]);
|
||||
}
|
||||
$dbForProject->createDocument('stats_v2', new Document([
|
||||
'$id' => $id,
|
||||
'period' => $period,
|
||||
@@ -94,15 +77,6 @@ class UsageHook extends Usage
|
||||
]));
|
||||
} catch (Duplicate $th) {
|
||||
if ($value < 0) {
|
||||
if ($projectInternalId == self::DEBUG_PROJECT_ID) {
|
||||
var_dump([
|
||||
'type' => 'decrease',
|
||||
'period' => $period,
|
||||
'metric' => $key,
|
||||
'id' => $id,
|
||||
'value' => $value
|
||||
]);
|
||||
}
|
||||
$dbForProject->decreaseDocumentAttribute(
|
||||
'stats_v2',
|
||||
$id,
|
||||
@@ -110,15 +84,6 @@ class UsageHook extends Usage
|
||||
abs($value)
|
||||
);
|
||||
} else {
|
||||
if ($projectInternalId == self::DEBUG_PROJECT_ID) {
|
||||
var_dump([
|
||||
'type' => 'increase',
|
||||
'period' => $period,
|
||||
'metric' => $key,
|
||||
'id' => $id,
|
||||
'value' => $value
|
||||
]);
|
||||
}
|
||||
$dbForProject->increaseDocumentAttribute(
|
||||
'stats_v2',
|
||||
$id,
|
||||
@@ -129,7 +94,7 @@ class UsageHook extends Usage
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
console::error(DateTime::now() . ' ' . $projectInternalId . ' ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ abstract class Format
|
||||
case 'updateEmail':
|
||||
switch ($param) {
|
||||
case 'status':
|
||||
return 'MessageType';
|
||||
return 'MessageStatus';
|
||||
}
|
||||
break;
|
||||
case 'createSMTPProvider':
|
||||
@@ -240,17 +240,24 @@ abstract class Format
|
||||
break;
|
||||
case 'projects':
|
||||
switch ($method) {
|
||||
case 'getSmsTemplate':
|
||||
case 'getEmailTemplate':
|
||||
case 'updateSmsTemplate':
|
||||
case 'updateEmailTemplate':
|
||||
case 'deleteSmsTemplate':
|
||||
case 'deleteEmailTemplate':
|
||||
switch ($param) {
|
||||
case 'type':
|
||||
return 'TemplateType';
|
||||
return 'EmailTemplateType';
|
||||
case 'locale':
|
||||
return 'TemplateLocale';
|
||||
return 'EmailTemplateLocale';
|
||||
}
|
||||
break;
|
||||
case 'getSmsTemplate':
|
||||
case 'updateSmsTemplate':
|
||||
case 'deleteSmsTemplate':
|
||||
switch ($param) {
|
||||
case 'type':
|
||||
return 'SMSTemplateType';
|
||||
case 'locale':
|
||||
return 'SMSTemplateLocale';
|
||||
}
|
||||
break;
|
||||
case 'createPlatform':
|
||||
@@ -327,6 +334,12 @@ abstract class Format
|
||||
return 'MessagingProviderType';
|
||||
}
|
||||
break;
|
||||
case 'createSHAUser':
|
||||
switch ($param) {
|
||||
case 'passwordVersion':
|
||||
return 'PasswordHash';
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ class Users extends Base
|
||||
'passwordUpdate',
|
||||
'registration',
|
||||
'emailVerification',
|
||||
'phoneVerification'
|
||||
'phoneVerification',
|
||||
'labels',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,18 +70,19 @@ use Appwrite\Utopia\Response\Model\Token;
|
||||
use Appwrite\Utopia\Response\Model\Webhook;
|
||||
use Appwrite\Utopia\Response\Model\Preferences;
|
||||
use Appwrite\Utopia\Response\Model\HealthAntivirus;
|
||||
use Appwrite\Utopia\Response\Model\HealthCertificate;
|
||||
use Appwrite\Utopia\Response\Model\HealthQueue;
|
||||
use Appwrite\Utopia\Response\Model\HealthStatus;
|
||||
use Appwrite\Utopia\Response\Model\HealthTime;
|
||||
use Appwrite\Utopia\Response\Model\HealthVersion;
|
||||
use Appwrite\Utopia\Response\Model\MFAChallenge;
|
||||
use Appwrite\Utopia\Response\Model\MFAProvider;
|
||||
use Appwrite\Utopia\Response\Model\MFAProviders;
|
||||
use Appwrite\Utopia\Response\Model\Installation;
|
||||
use Appwrite\Utopia\Response\Model\LocaleCode;
|
||||
use Appwrite\Utopia\Response\Model\MetricBreakdown;
|
||||
use Appwrite\Utopia\Response\Model\Provider;
|
||||
use Appwrite\Utopia\Response\Model\Message;
|
||||
use Appwrite\Utopia\Response\Model\MFAFactors;
|
||||
use Appwrite\Utopia\Response\Model\MFAType;
|
||||
use Appwrite\Utopia\Response\Model\Subscriber;
|
||||
use Appwrite\Utopia\Response\Model\Topic;
|
||||
use Appwrite\Utopia\Response\Model\ProviderRepository;
|
||||
@@ -169,8 +170,8 @@ class Response extends SwooleResponse
|
||||
public const MODEL_PREFERENCES = 'preferences';
|
||||
|
||||
// MFA
|
||||
public const MODEL_MFA_PROVIDER = 'mfaProvider';
|
||||
public const MODEL_MFA_PROVIDERS = 'mfaProviders';
|
||||
public const MODEL_MFA_TYPE = 'mfaType';
|
||||
public const MODEL_MFA_FACTORS = 'mfaFactors';
|
||||
public const MODEL_MFA_OTP = 'mfaTotp';
|
||||
public const MODEL_MFA_CHALLENGE = 'mfaChallenge';
|
||||
|
||||
@@ -279,6 +280,7 @@ class Response extends SwooleResponse
|
||||
public const MODEL_HEALTH_QUEUE = 'healthQueue';
|
||||
public const MODEL_HEALTH_TIME = 'healthTime';
|
||||
public const MODEL_HEALTH_ANTIVIRUS = 'healthAntivirus';
|
||||
public const MODEL_HEALTH_CERTIFICATE = 'healthCertificate';
|
||||
public const MODEL_HEALTH_STATUS_LIST = 'healthStatusList';
|
||||
|
||||
// Console
|
||||
@@ -421,6 +423,7 @@ class Response extends SwooleResponse
|
||||
->setModel(new HealthAntivirus())
|
||||
->setModel(new HealthQueue())
|
||||
->setModel(new HealthStatus())
|
||||
->setModel(new HealthCertificate())
|
||||
->setModel(new HealthTime())
|
||||
->setModel(new HealthVersion())
|
||||
->setModel(new Metric())
|
||||
@@ -440,8 +443,8 @@ class Response extends SwooleResponse
|
||||
->setModel(new TemplateEmail())
|
||||
->setModel(new ConsoleVariables())
|
||||
->setModel(new MFAChallenge())
|
||||
->setModel(new MFAProvider())
|
||||
->setModel(new MFAProviders())
|
||||
->setModel(new MFAType())
|
||||
->setModel(new MFAFactors())
|
||||
->setModel(new Provider())
|
||||
->setModel(new Message())
|
||||
->setModel(new Topic())
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Utopia\Response\Model;
|
||||
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
class HealthCertificate extends Model
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Certificate name',
|
||||
'default' => '',
|
||||
'example' => '/CN=www.google.com',
|
||||
])
|
||||
->addRule('subjectSN', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Subject SN',
|
||||
'default' => 'www.google.com',
|
||||
'example' => '',
|
||||
])
|
||||
->addRule('issuerOrganisation', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Issuer organisation',
|
||||
'default' => 'Google Trust Services LLC',
|
||||
'example' => '',
|
||||
])
|
||||
->addRule('validFrom', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Valid from',
|
||||
'default' => '',
|
||||
'example' => '1704200998',
|
||||
])
|
||||
->addRule('validTo', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Valid to',
|
||||
'default' => '',
|
||||
'example' => '1711458597',
|
||||
])
|
||||
->addRule('signatureTypeSN', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Signature type SN',
|
||||
'default' => '',
|
||||
'example' => 'RSA-SHA256',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'Health Certificate';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return Response::MODEL_HEALTH_CERTIFICATE;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -5,7 +5,7 @@ namespace Appwrite\Utopia\Response\Model;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
class MFAProviders extends Model
|
||||
class MFAFactors extends Model
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
@@ -38,7 +38,7 @@ class MFAProviders extends Model
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'MFAProviders';
|
||||
return 'MFAFactors';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +48,6 @@ class MFAProviders extends Model
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return Response::MODEL_MFA_PROVIDERS;
|
||||
return Response::MODEL_MFA_FACTORS;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -5,7 +5,7 @@ namespace Appwrite\Utopia\Response\Model;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
class MFAProvider extends Model
|
||||
class MFAType extends Model
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
@@ -39,7 +39,7 @@ class MFAProvider extends Model
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'MFAProvider';
|
||||
return 'MFAType';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,6 +49,6 @@ class MFAProvider extends Model
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return Response::MODEL_MFA_PROVIDER;
|
||||
return Response::MODEL_MFA_TYPE;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,13 @@ class Topic extends Model
|
||||
'description' => 'Total count of subscribers subscribed to topic.',
|
||||
'default' => 0,
|
||||
'example' => 100,
|
||||
])
|
||||
->addRule('subscribe', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Subscribe permissions.',
|
||||
'default' => ['users'],
|
||||
'example' => 'users',
|
||||
'array' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user