Merge branch '1.5.x' into fix-limit-failed-webhook-attempts

This commit is contained in:
Khushboo Verma
2023-12-12 00:17:21 +05:30
25 changed files with 1091 additions and 442 deletions
+7 -7
View File
@@ -11,7 +11,7 @@ class Messaging extends Event
protected ?string $messageId = null;
protected ?Document $message = null;
protected ?array $recipients = null;
protected ?string $deliveryTime = null;
protected ?string $scheduledAt = null;
protected ?string $providerType = null;
@@ -117,14 +117,14 @@ class Messaging extends Event
}
/**
* Sets Delivery time for the messaging event.
* Sets Scheduled delivery time for the messaging event.
*
* @param string $deliveryTime
* @param string $scheduledAt
* @return self
*/
public function setDeliveryTime(string $deliveryTime): self
public function setScheduledAt(string $scheduledAt): self
{
$this->deliveryTime = $deliveryTime;
$this->scheduledAt = $scheduledAt;
return $this;
}
@@ -134,9 +134,9 @@ class Messaging extends Event
*
* @return string
*/
public function getDeliveryTime(): string
public function getScheduledAt(): string
{
return $this->deliveryTime;
return $this->scheduledAt;
}
/**
+6
View File
@@ -55,6 +55,8 @@ class Exception extends \Exception
public const GENERAL_CODES_DISABLED = 'general_codes_disabled';
public const GENERAL_USAGE_DISABLED = 'general_usage_disabled';
public const GENERAL_NOT_IMPLEMENTED = 'general_not_implemented';
public const GENERAL_INVALID_EMAIL = 'general_invalid_email';
public const GENERAL_INVALID_PHONE = 'general_invalid_phone';
/** Users */
public const USER_COUNT_EXCEEDED = 'user_count_exceeded';
@@ -254,6 +256,10 @@ class Exception extends \Exception
public const MESSAGE_MISSING_TARGET = 'message_missing_target';
public const MESSAGE_ALREADY_SENT = 'message_already_sent';
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';
public const MESSAGE_TARGET_NOT_PUSH = 'message_target_not_push';
protected string $type = '';
protected array $errors = [];
@@ -556,6 +556,11 @@ class Deletes extends Action
$this->deleteByGroup('identities', [
Query::equal('userInternalId', [$userInternalId])
], $dbForProject);
// Delete targets
$this->deleteByGroup('targets', [
Query::equal('userInternalId', [$userInternalId])
], $dbForProject);
}
/**
+31 -23
View File
@@ -17,7 +17,7 @@ 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\Textmagic;
use Utopia\Messaging\Adapters\SMS\Twilio;
use Utopia\Messaging\Adapters\SMS\Vonage;
use Utopia\Messaging\Adapters\Push as PushAdapter;
@@ -67,7 +67,7 @@ class Messaging extends Action
}
if (!\is_null($payload['message']) && !\is_null($payload['recipients'])) {
if ($payload['providerType'] === 'SMS') {
if ($payload['providerType'] === MESSAGE_TYPE_SMS) {
$this->processInternalSMSMessage(new Document($payload['message']), $payload['recipients']);
}
} else {
@@ -91,14 +91,16 @@ class Messaging extends Action
if (\count($topicsId) > 0) {
$topics = $dbForProject->find('topics', [Query::equal('$id', $topicsId)]);
foreach ($topics as $topic) {
$recipients = \array_merge($recipients, $topic->getAttribute('targets'));
$targets = \array_filter($topic->getAttribute('targets'), fn (Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
$recipients = \array_merge($recipients, $targets);
}
}
if (\count($usersId) > 0) {
$users = $dbForProject->find('users', [Query::equal('$id', $usersId)]);
foreach ($users as $user) {
$recipients = \array_merge($recipients, $user->getAttribute('targets'));
$targets = \array_filter($user->getAttribute('targets'), fn (Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
$recipients = \array_merge($recipients, $targets);
}
}
@@ -107,7 +109,7 @@ class Messaging extends Action
$recipients = \array_merge($recipients, $targets);
}
$internalProvider = $dbForProject->findOne('providers', [
$primaryProvider = $dbForProject->findOne('providers', [
Query::equal('enabled', [true]),
Query::equal('type', [$recipients[0]->getAttribute('providerType')]),
]);
@@ -124,36 +126,42 @@ class Messaging extends Action
foreach ($recipients as $recipient) {
$providerId = $recipient->getAttribute('providerId');
if (!$providerId) {
$providerId = $internalProvider->getId();
if (!$providerId && $primaryProvider instanceof Document && !$primaryProvider->isEmpty()) {
$providerId = $primaryProvider->getId();
}
if (!isset($identifiersByProviderId[$providerId])) {
$identifiersByProviderId[$providerId] = [];
if ($providerId) {
if (!isset($identifiersByProviderId[$providerId])) {
$identifiersByProviderId[$providerId] = [];
}
$identifiersByProviderId[$providerId][] = $recipient->getAttribute('identifier');
}
$identifiersByProviderId[$providerId][] = $recipient->getAttribute('identifier');
}
/**
* @var array[] $results
*/
$results = batch(\array_map(function ($providerId) use ($identifiersByProviderId, $providers, $internalProvider, $message, $dbForProject) {
return function () use ($providerId, $identifiersByProviderId, $providers, $internalProvider, $message, $dbForProject) {
$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 ($internalProvider->getId() === $providerId) {
$provider = $internalProvider;
if ($primaryProvider->getId() === $providerId) {
$provider = $primaryProvider;
} else {
$provider = $dbForProject->getDocument('providers', $providerId);
$provider = $dbForProject->getDocument('providers', $providerId, [Query::equal('enabled', [true])]);
if ($provider->isEmpty()) {
$provider = $primaryProvider;
}
}
$providers[] = $provider;
$identifiers = $identifiersByProviderId[$providerId];
$adapter = match ($provider->getAttribute('type')) {
'sms' => $this->sms($provider),
'push' => $this->push($provider),
'email' => $this->email($provider),
MESSAGE_TYPE_SMS => $this->sms($provider),
MESSAGE_TYPE_PUSH => $this->push($provider),
MESSAGE_TYPE_EMAIL => $this->email($provider),
default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE)
};
@@ -169,9 +177,9 @@ class Messaging extends Action
$messageData->setAttribute('to', $batch);
$data = match ($provider->getAttribute('type')) {
'sms' => $this->buildSMSMessage($messageData, $provider),
'push' => $this->buildPushMessage($messageData),
'email' => $this->buildEmailMessage($messageData, $provider),
MESSAGE_TYPE_SMS => $this->buildSMSMessage($messageData, $provider),
MESSAGE_TYPE_PUSH => $this->buildPushMessage($messageData),
MESSAGE_TYPE_EMAIL => $this->buildEmailMessage($messageData, $provider),
default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE)
};
@@ -241,7 +249,7 @@ class Messaging extends Action
$provider = new Document([
'$id' => ID::unique(),
'provider' => $host,
'type' => 'sms',
'type' => MESSAGE_TYPE_SMS,
'name' => 'Internal SMS',
'enabled' => true,
'credentials' => match ($host) {
@@ -303,7 +311,7 @@ class Messaging extends Action
return match ($provider->getAttribute('provider')) {
'mock' => new Mock('username', 'password'),
'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']),
'textmagic' => new TextMagic($credentials['username'], $credentials['apiKey']),
'textmagic' => new Textmagic($credentials['username'], $credentials['apiKey']),
'telesign' => new Telesign($credentials['username'], $credentials['password']),
'msg91' => new Msg91($credentials['senderId'], $credentials['authKey']),
'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']),
@@ -6,7 +6,9 @@ class Subscribers extends Base
{
public const ALLOWED_ATTRIBUTES = [
'targetId',
'topicId'
'topicId',
'userId',
'providerType'
];
/**
+10 -3
View File
@@ -5,8 +5,9 @@ namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
use Utopia\Database\DateTime;
use Utopia\Database\Document as DatabaseDocument;
class Message extends Any
class Message extends Model
{
public function __construct()
{
@@ -29,6 +30,12 @@ class Message extends Any
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('providerType', [
'type' => self::TYPE_STRING,
'description' => 'Message provider type.',
'default' => '',
'example' => MESSAGE_TYPE_EMAIL,
])
->addRule('topics', [
'type' => self::TYPE_STRING,
'description' => 'Topic IDs set as recipients.',
@@ -50,7 +57,7 @@ class Message extends Any
'array' => true,
'example' => ['5e5ea5c16897e'],
])
->addRule('deliveryTime', [
->addRule('scheduledAt', [
'type' => self::TYPE_DATETIME,
'description' => 'The scheduled time for message.',
'required' => false,
@@ -91,7 +98,7 @@ class Message extends Any
'type' => self::TYPE_STRING,
'description' => 'Status of delivery.',
'default' => 'processing',
'example' => 'Message status can be one of the following: processing, sent, failed.',
'example' => 'Message status can be one of the following: processing, sent, cancelled, failed.',
])
->addRule('description', [
'type' => self::TYPE_STRING,
@@ -50,7 +50,7 @@ class Provider extends Model
'type' => self::TYPE_STRING,
'description' => 'Type of provider.',
'default' => '',
'example' => 'sms',
'example' => MESSAGE_TYPE_SMS,
])
->addRule('credentials', [
'type' => self::TYPE_JSON,
@@ -34,9 +34,24 @@ class Subscriber extends Model
'default' => '',
'example' => '259125845563242502',
])
->addRule('target', [
'type' => Response::MODEL_TARGET,
'description' => 'Target.',
'default' => [],
'example' => [
'$id' => '259125845563242502',
'$createdAt' => self::TYPE_DATETIME_EXAMPLE,
'$updatedAt' => self::TYPE_DATETIME_EXAMPLE,
'providerType' => 'email',
'providerId' => '259125845563242502',
'name' => 'ageon-app-email',
'identifier' => 'random-mail@email.org',
'userId' => '5e5ea5c16897e',
],
])
->addRule('userId', [
'type' => self::TYPE_STRING,
'description' => 'User ID.',
'description' => 'Topic ID.',
'default' => '',
'example' => '5e5ea5c16897e',
])
@@ -51,6 +66,12 @@ class Subscriber extends Model
'description' => 'Topic ID.',
'default' => '',
'example' => '259125845563242502',
])
->addRule('providerType', [
'type' => self::TYPE_STRING,
'description' => 'The target provider type. Can be one of the following: `email`, `sms` or `push`.',
'default' => '',
'example' => MESSAGE_TYPE_EMAIL,
]);
}
@@ -28,6 +28,12 @@ class Target extends Model
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('name', [
'type' => self::TYPE_STRING,
'description' => 'Target Name.',
'default' => '',
'example' => 'Aegon apple token',
])
->addRule('userId', [
'type' => self::TYPE_STRING,
'description' => 'User ID.',
@@ -45,7 +51,7 @@ class Target extends Model
'type' => self::TYPE_STRING,
'description' => 'The target provider type. Can be one of the following: `email`, `sms` or `push`.',
'default' => '',
'example' => 'email',
'example' => MESSAGE_TYPE_EMAIL,
])
->addRule('identifier', [
'type' => self::TYPE_STRING,