mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '1.5.x' into fix-limit-failed-webhook-attempts
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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'
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user