2023-08-21 22:44:50 +12:00
< ? php
2023-11-14 22:50:21 +13:00
use Appwrite\Auth\Validator\Phone ;
2023-11-03 01:30:17 +13:00
use Appwrite\Detector\Detector ;
2023-10-18 06:23:26 +13:00
use Appwrite\Event\Delete ;
2023-11-01 06:47:58 +13:00
use Appwrite\Event\Event ;
2023-09-06 22:10:56 +12:00
use Appwrite\Event\Messaging ;
2023-08-22 04:45:15 +12:00
use Appwrite\Extend\Exception ;
2024-02-02 17:53:19 +13:00
use Appwrite\Messaging\Status as MessageStatus ;
2023-10-26 06:33:23 +13:00
use Appwrite\Network\Validator\Email ;
2023-09-06 22:10:56 +12:00
use Appwrite\Permission ;
use Appwrite\Role ;
2024-02-20 00:08:57 +13:00
use Appwrite\Utopia\Database\Validator\CompoundUID ;
2023-08-25 08:15:17 +12:00
use Appwrite\Utopia\Database\Validator\CustomId ;
2023-10-14 01:56:54 +13:00
use Appwrite\Utopia\Database\Validator\Queries\Messages ;
2023-08-23 04:45:31 +12:00
use Appwrite\Utopia\Database\Validator\Queries\Providers ;
2023-10-18 20:49:21 +13:00
use Appwrite\Utopia\Database\Validator\Queries\Subscribers ;
2024-01-18 14:33:32 +13:00
use Appwrite\Utopia\Database\Validator\Queries\Targets ;
2023-08-25 08:15:17 +12:00
use Appwrite\Utopia\Database\Validator\Queries\Topics ;
2023-08-21 22:44:50 +12:00
use Appwrite\Utopia\Response ;
2024-03-07 06:34:21 +13:00
use MaxMind\Db\Reader ;
2023-08-21 22:44:50 +12:00
use Utopia\App ;
2023-11-03 01:30:17 +13:00
use Utopia\Audit\Audit ;
2023-08-21 22:44:50 +12:00
use Utopia\Database\Database ;
2024-03-07 06:34:21 +13:00
use Utopia\Database\DateTime ;
2023-08-21 22:44:50 +12:00
use Utopia\Database\Document ;
2023-08-29 03:11:05 +12:00
use Utopia\Database\Exception\Duplicate as DuplicateException ;
2024-02-13 05:02:04 +13:00
use Utopia\Database\Exception\Query as QueryException ;
2023-08-25 09:02:51 +12:00
use Utopia\Database\Helpers\ID ;
2023-08-23 04:45:31 +12:00
use Utopia\Database\Query ;
use Utopia\Database\Validator\Authorization ;
2023-09-06 22:10:56 +12:00
use Utopia\Database\Validator\Datetime as DatetimeValidator ;
2023-11-03 01:30:17 +13:00
use Utopia\Database\Validator\Queries ;
use Utopia\Database\Validator\Query\Limit ;
use Utopia\Database\Validator\Query\Offset ;
2024-02-13 17:24:31 +13:00
use Utopia\Database\Validator\Roles ;
2023-08-23 04:45:31 +12:00
use Utopia\Database\Validator\UID ;
2024-02-15 22:36:34 +13:00
use Utopia\Domains\Domain ;
2023-11-03 01:30:17 +13:00
use Utopia\Locale\Locale ;
2023-08-22 04:45:15 +12:00
use Utopia\Validator\ArrayList ;
2023-08-30 04:59:48 +12:00
use Utopia\Validator\Boolean ;
2023-12-15 03:45:51 +13:00
use Utopia\Validator\Integer ;
2023-10-19 20:59:48 +13:00
use Utopia\Validator\JSON ;
2024-02-01 01:30:09 +13:00
use Utopia\Validator\Range ;
2023-08-21 22:44:50 +12:00
use Utopia\Validator\Text ;
2023-09-06 05:10:48 +12:00
use Utopia\Validator\WhiteList ;
2023-08-21 22:44:50 +12:00
2023-11-20 20:04:50 +13:00
use function Swoole\Coroutine\batch ;
2023-08-21 22:44:50 +12:00
App :: post ( '/v1/messaging/providers/mailgun' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Create Mailgun provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'createMailgunProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/create-mailgun-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-08-25 11:13:40 +12:00
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-11-23 08:09:55 +13:00
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Mailgun API Key.' , true )
-> param ( 'domain' , '' , new Text ( 0 ), 'Mailgun Domain.' , true )
-> param ( 'isEuRegion' , null , new Boolean (), 'Set as EU region.' , true )
2024-01-25 20:05:02 +13:00
-> param ( 'fromName' , '' , new Text ( 128 , 0 ), 'Sender Name.' , true )
2023-12-17 12:41:20 +13:00
-> param ( 'fromEmail' , '' , new Email (), 'Sender email address.' , true )
2024-01-25 20:05:02 +13:00
-> param ( 'replyToName' , '' , new Text ( 128 , 0 ), 'Name set in the reply to field for the mail. Default value is sender name. Reply to name must have reply to email as well.' , true )
-> param ( 'replyToEmail' , '' , new Email (), 'Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.' , true )
2024-02-01 01:30:09 +13:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-01 02:33:14 +13:00
-> action ( function ( string $providerId , string $name , string $apiKey , string $domain , ? bool $isEuRegion , string $fromName , string $fromEmail , string $replyToName , string $replyToEmail , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-08-25 11:16:15 +12:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-08-30 04:59:48 +12:00
2023-11-23 08:09:55 +13:00
$credentials = [];
2024-02-01 01:30:09 +13:00
if ( ! \is_null ( $isEuRegion )) {
2023-11-23 08:09:55 +13:00
$credentials [ 'isEuRegion' ] = $isEuRegion ;
}
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
}
if ( ! empty ( $domain )) {
$credentials [ 'domain' ] = $domain ;
}
2024-02-01 01:30:09 +13:00
$options = [
'fromName' => $fromName ,
'fromEmail' => $fromEmail ,
'replyToName' => $replyToName ,
'replyToEmail' => $replyToEmail ,
];
2023-11-23 08:09:55 +13:00
if (
2024-02-01 01:30:09 +13:00
$enabled === true
2024-02-01 17:41:24 +13:00
&& ! empty ( $fromEmail )
2024-02-01 01:30:09 +13:00
&& \array_key_exists ( 'isEuRegion' , $credentials )
&& \array_key_exists ( 'apiKey' , $credentials )
&& \array_key_exists ( 'domain' , $credentials )
2023-11-23 08:09:55 +13:00
) {
$enabled = true ;
} else {
$enabled = false ;
}
2023-08-30 04:59:48 +12:00
$provider = new Document ([
2023-08-25 11:16:15 +12:00
'$id' => $providerId ,
'name' => $name ,
2023-08-24 21:01:22 +12:00
'provider' => 'mailgun' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_EMAIL ,
2023-09-14 00:17:38 +12:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials ,
'options' => $options ,
2023-08-30 04:59:48 +12:00
]);
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-08-30 04:59:48 +12:00
}
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-08-24 21:01:22 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
App :: post ( '/v1/messaging/providers/sendgrid' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Create Sendgrid provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'createSendgridProvider' )
2024-02-26 11:58:33 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/create-sendgrid-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-08-25 11:13:40 +12:00
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-11-23 08:09:55 +13:00
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Sendgrid API key.' , true )
2024-01-25 20:05:02 +13:00
-> param ( 'fromName' , '' , new Text ( 128 , 0 ), 'Sender Name.' , true )
2023-12-17 12:41:20 +13:00
-> param ( 'fromEmail' , '' , new Email (), 'Sender email address.' , true )
2024-01-25 20:05:02 +13:00
-> param ( 'replyToName' , '' , new Text ( 128 , 0 ), 'Name set in the reply to field for the mail. Default value is sender name.' , true )
-> param ( 'replyToEmail' , '' , new Email (), 'Email set in the reply to field for the mail. Default value is sender email.' , true )
2024-02-01 01:30:09 +13:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-01 02:33:14 +13:00
-> action ( function ( string $providerId , string $name , string $apiKey , string $fromName , string $fromEmail , string $replyToName , string $replyToEmail , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-08-25 11:16:15 +12:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-11-23 08:09:55 +13:00
2024-02-01 17:42:19 +13:00
$credentials = [];
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
}
2023-12-06 03:01:32 +13:00
$options = [
'fromName' => $fromName ,
'fromEmail' => $fromEmail ,
2024-02-01 01:30:09 +13:00
'replyToName' => $replyToName ,
'replyToEmail' => $replyToEmail ,
2023-12-06 03:01:32 +13:00
];
2023-11-23 08:09:55 +13:00
if (
$enabled === true
2024-02-01 01:30:09 +13:00
&& ! empty ( $fromEmail )
2023-11-23 08:09:55 +13:00
&& \array_key_exists ( 'apiKey' , $credentials )
) {
$enabled = true ;
} else {
$enabled = false ;
}
2023-08-30 04:59:48 +12:00
$provider = new Document ([
2023-08-25 11:16:15 +12:00
'$id' => $providerId ,
'name' => $name ,
2023-08-24 21:01:22 +12:00
'provider' => 'sendgrid' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_EMAIL ,
2023-09-14 00:17:38 +12:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials ,
'options' => $options ,
2023-08-30 04:59:48 +12:00
]);
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-08-30 04:59:48 +12:00
}
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-08-24 21:01:22 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2024-02-01 01:30:09 +13:00
App :: post ( '/v1/messaging/providers/smtp' )
-> desc ( 'Create SMTP provider' )
-> groups ([ 'api' , 'messaging' ])
-> label ( 'audits.event' , 'provider.create' )
-> label ( 'audits.resource' , 'provider/{response.$id}' )
-> label ( 'event' , 'providers.[providerId].create' )
-> label ( 'scope' , 'providers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.method' , 'createSmtpProvider' )
2024-02-01 01:30:09 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/create-smtp-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2024-02-21 22:04:27 +13:00
-> param ( 'host' , '' , new Text ( 0 ), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls://smtp1.example.com:587;ssl://smtp2.example.com:465"`. Hosts will be tried in order.' )
2024-02-01 01:30:09 +13:00
-> param ( 'port' , 587 , new Range ( 1 , 65535 ), 'The default SMTP server port.' , true )
-> param ( 'username' , '' , new Text ( 0 ), 'Authentication username.' , true )
-> param ( 'password' , '' , new Text ( 0 ), 'Authentication password.' , true )
2024-02-01 17:44:42 +13:00
-> param ( 'encryption' , '' , new WhiteList ([ 'none' , 'ssl' , 'tls' ]), 'Encryption type. Can be omitted, \'ssl\', or \'tls\'' , true )
2024-02-01 01:30:09 +13:00
-> param ( 'autoTLS' , true , new Boolean (), 'Enable SMTP AutoTLS feature.' , true )
-> param ( 'mailer' , '' , new Text ( 0 ), 'The value to use for the X-Mailer header.' , true )
-> param ( 'fromName' , '' , new Text ( 128 , 0 ), 'Sender Name.' , true )
-> param ( 'fromEmail' , '' , new Email (), 'Sender email address.' , true )
-> param ( 'replyToName' , '' , new Text ( 128 , 0 ), 'Name set in the reply to field for the mail. Default value is sender name.' , true )
-> param ( 'replyToEmail' , '' , new Email (), 'Email set in the reply to field for the mail. Default value is sender email.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
-> inject ( 'queueForEvents' )
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-01 02:33:14 +13:00
-> action ( function ( string $providerId , string $name , string $host , int $port , string $username , string $password , string $encryption , bool $autoTLS , string $mailer , string $fromName , string $fromEmail , string $replyToName , string $replyToEmail , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2024-02-01 01:30:09 +13:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2024-02-01 17:45:41 +13:00
$credentials = [
'port' => $port ,
'username' => $username ,
'password' => $password ,
];
2024-02-01 01:30:09 +13:00
if ( ! empty ( $host )) {
$credentials [ 'host' ] = $host ;
}
$options = [
'fromName' => $fromName ,
'fromEmail' => $fromEmail ,
'replyToName' => $replyToName ,
'replyToEmail' => $replyToEmail ,
2024-02-01 17:44:42 +13:00
'encryption' => $encryption === 'none' ? '' : $encryption ,
2024-02-01 01:30:09 +13:00
'autoTLS' => $autoTLS ,
'mailer' => $mailer ,
];
if (
$enabled === true
2024-02-01 17:45:41 +13:00
&& ! empty ( $fromEmail )
2024-02-01 01:30:09 +13:00
&& \array_key_exists ( 'host' , $credentials )
) {
$enabled = true ;
} else {
$enabled = false ;
}
$provider = new Document ([
'$id' => $providerId ,
'name' => $name ,
'provider' => 'smtp' ,
'type' => MESSAGE_TYPE_EMAIL ,
'enabled' => $enabled ,
'credentials' => $credentials ,
'options' => $options ,
]);
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
}
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
App :: post ( '/v1/messaging/providers/msg91' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Create Msg91 provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'createMsg91Provider' )
-> label ( 'sdk.description' , '/docs/references/messaging/create-msg91-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-08-25 11:16:15 +12:00
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-11-23 08:09:55 +13:00
-> param ( 'from' , '' , new Phone (), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.' , true )
-> param ( 'senderId' , '' , new Text ( 0 ), 'Msg91 Sender ID.' , true )
-> param ( 'authKey' , '' , new Text ( 0 ), 'Msg91 Auth Key.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-23 08:09:55 +13:00
-> action ( function ( string $providerId , string $name , string $from , string $senderId , string $authKey , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-08-25 11:16:15 +12:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-11-23 08:09:55 +13:00
$options = [];
if ( ! empty ( $from )) {
2024-01-05 13:10:57 +13:00
$options [ 'from' ] = $from ;
2023-11-23 08:09:55 +13:00
}
$credentials = [];
if ( ! empty ( $senderId )) {
$credentials [ 'senderId' ] = $senderId ;
}
if ( ! empty ( $authKey )) {
$credentials [ 'authKey' ] = $authKey ;
}
if (
$enabled === true
&& \array_key_exists ( 'senderId' , $credentials )
&& \array_key_exists ( 'authKey' , $credentials )
&& \array_key_exists ( 'from' , $options )
) {
$enabled = true ;
} else {
$enabled = false ;
}
2023-08-30 04:59:48 +12:00
$provider = new Document ([
2023-08-25 11:16:15 +12:00
'$id' => $providerId ,
'name' => $name ,
2023-08-24 21:01:22 +12:00
'provider' => 'msg91' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_SMS ,
2023-09-14 00:17:38 +12:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials ,
'options' => $options ,
2023-08-30 04:59:48 +12:00
]);
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-08-30 04:59:48 +12:00
}
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-08-24 21:01:22 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-10-06 00:27:48 +13:00
2023-08-23 04:45:31 +12:00
App :: post ( '/v1/messaging/providers/telesign' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Create Telesign provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'createTelesignProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/create-telesign-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-08-25 11:13:40 +12:00
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-11-23 08:09:55 +13:00
-> param ( 'from' , '' , new Phone (), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.' , true )
2024-02-12 15:10:18 +13:00
-> param ( 'customerId' , '' , new Text ( 0 ), 'Telesign customer ID.' , true )
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Telesign API key.' , true )
2023-11-23 08:09:55 +13:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-12 15:10:18 +13:00
-> action ( function ( string $providerId , string $name , string $from , string $customerId , string $apiKey , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-08-25 11:16:15 +12:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-11-23 08:09:55 +13:00
$options = [];
if ( ! empty ( $from )) {
2024-01-05 13:10:57 +13:00
$options [ 'from' ] = $from ;
2023-11-23 08:09:55 +13:00
}
$credentials = [];
2024-02-12 15:10:18 +13:00
if ( ! empty ( $customerId )) {
$credentials [ 'customerId' ] = $customerId ;
2023-11-23 08:09:55 +13:00
}
2024-02-12 15:10:18 +13:00
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
2023-11-23 08:09:55 +13:00
}
if (
$enabled === true
2024-02-12 15:10:18 +13:00
&& \array_key_exists ( 'customerId' , $credentials )
&& \array_key_exists ( 'apiKey' , $credentials )
2023-11-23 08:09:55 +13:00
&& \array_key_exists ( 'from' , $options )
) {
$enabled = true ;
} else {
$enabled = false ;
}
2023-08-30 04:59:48 +12:00
$provider = new Document ([
2023-08-25 11:16:15 +12:00
'$id' => $providerId ,
'name' => $name ,
2023-08-24 21:01:22 +12:00
'provider' => 'telesign' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_SMS ,
2023-09-14 00:17:38 +12:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials ,
'options' => $options ,
2023-08-30 04:59:48 +12:00
]);
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-08-30 04:59:48 +12:00
}
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-08-24 21:01:22 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2023-10-04 23:45:59 +13:00
App :: post ( '/v1/messaging/providers/textmagic' )
2023-11-21 20:05:36 +13:00
-> desc ( 'Create Textmagic provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-11-21 20:05:36 +13:00
-> label ( 'sdk.method' , 'createTextmagicProvider' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/create-textmagic-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-04 23:45:59 +13:00
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-11-23 08:09:55 +13:00
-> param ( 'from' , '' , new Phone (), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.' , true )
-> param ( 'username' , '' , new Text ( 0 ), 'Textmagic username.' , true )
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Textmagic apiKey.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-23 08:09:55 +13:00
-> action ( function ( string $providerId , string $name , string $from , string $username , string $apiKey , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-04 23:45:59 +13:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-11-23 08:09:55 +13:00
$options = [];
if ( ! empty ( $from )) {
2024-01-05 13:10:57 +13:00
$options [ 'from' ] = $from ;
2023-11-23 08:09:55 +13:00
}
$credentials = [];
if ( ! empty ( $username )) {
$credentials [ 'username' ] = $username ;
}
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
}
if (
$enabled === true
&& \array_key_exists ( 'username' , $credentials )
&& \array_key_exists ( 'apiKey' , $credentials )
&& \array_key_exists ( 'from' , $options )
) {
$enabled = true ;
} else {
$enabled = false ;
}
2023-10-04 23:45:59 +13:00
$provider = new Document ([
'$id' => $providerId ,
'name' => $name ,
2023-11-14 21:37:52 +13:00
'provider' => 'textmagic' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_SMS ,
2023-10-04 23:45:59 +13:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials ,
'options' => $options ,
2023-10-04 23:45:59 +13:00
]);
2023-08-24 21:01:22 +12:00
2023-10-04 23:45:59 +13:00
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-09-14 00:17:38 +12:00
}
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-10-04 23:45:59 +13:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
App :: post ( '/v1/messaging/providers/twilio' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Create Twilio provider' )
2023-10-04 23:45:59 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-10-04 23:45:59 +13:00
-> label ( 'scope' , 'providers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'createTwilioProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/create-twilio-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-11-23 08:09:55 +13:00
-> param ( 'from' , '' , new Phone (), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.' , true )
-> param ( 'accountSid' , '' , new Text ( 0 ), 'Twilio account secret ID.' , true )
-> param ( 'authToken' , '' , new Text ( 0 ), 'Twilio authentication token.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-10-04 23:45:59 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-23 08:09:55 +13:00
-> action ( function ( string $providerId , string $name , string $from , string $accountSid , string $authToken , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-04 23:45:59 +13:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-11-23 08:09:55 +13:00
$options = [];
if ( ! empty ( $from )) {
2024-01-05 13:10:57 +13:00
$options [ 'from' ] = $from ;
2023-11-23 08:09:55 +13:00
}
$credentials = [];
if ( ! empty ( $accountSid )) {
$credentials [ 'accountSid' ] = $accountSid ;
}
if ( ! empty ( $authToken )) {
$credentials [ 'authToken' ] = $authToken ;
}
if (
$enabled === true
&& \array_key_exists ( 'accountSid' , $credentials )
&& \array_key_exists ( 'authToken' , $credentials )
&& \array_key_exists ( 'from' , $options )
) {
$enabled = true ;
} else {
$enabled = false ;
}
2023-10-04 23:45:59 +13:00
$provider = new Document ([
'$id' => $providerId ,
'name' => $name ,
'provider' => 'twilio' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_SMS ,
2023-10-04 23:45:59 +13:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials ,
2023-12-01 11:09:43 +13:00
'options' => $options ,
2023-10-04 23:45:59 +13:00
]);
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-10-04 23:45:59 +13:00
}
2023-08-24 21:01:22 +12:00
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-08-24 21:01:22 +12:00
$response
2023-10-04 23:45:59 +13:00
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
2023-08-24 21:01:22 +12:00
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2023-10-04 23:45:59 +13:00
App :: post ( '/v1/messaging/providers/vonage' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Create Vonage provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'createVonageProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/create-vonage-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-08-25 11:13:40 +12:00
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-11-23 08:09:55 +13:00
-> param ( 'from' , '' , new Phone (), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.' , true )
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Vonage API key.' , true )
-> param ( 'apiSecret' , '' , new Text ( 0 ), 'Vonage API secret.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-23 08:09:55 +13:00
-> action ( function ( string $providerId , string $name , string $from , string $apiKey , string $apiSecret , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-08-25 11:16:15 +12:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-11-23 08:09:55 +13:00
$options = [];
if ( ! empty ( $from )) {
2024-01-05 13:10:57 +13:00
$options [ 'from' ] = $from ;
2023-11-23 08:09:55 +13:00
}
$credentials = [];
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
}
if ( ! empty ( $apiSecret )) {
$credentials [ 'apiSecret' ] = $apiSecret ;
}
if (
$enabled === true
&& \array_key_exists ( 'apiKey' , $credentials )
&& \array_key_exists ( 'apiSecret' , $credentials )
&& \array_key_exists ( 'from' , $options )
) {
$enabled = true ;
} else {
$enabled = false ;
}
2023-08-30 04:59:48 +12:00
$provider = new Document ([
2023-08-25 11:16:15 +12:00
'$id' => $providerId ,
'name' => $name ,
2023-10-04 23:45:59 +13:00
'provider' => 'vonage' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_SMS ,
2023-09-14 00:17:38 +12:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials ,
'options' => $options ,
2023-08-30 04:59:48 +12:00
]);
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-08-30 04:59:48 +12:00
}
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-08-24 21:01:22 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-22 04:45:15 +12:00
2023-10-04 23:45:59 +13:00
App :: post ( '/v1/messaging/providers/fcm' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Create FCM provider' )
2023-10-04 23:45:59 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-10-04 23:45:59 +13:00
-> label ( 'scope' , 'providers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.method' , 'createFcmProvider' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/create-fcm-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-12-20 07:15:20 +13:00
-> param ( 'serviceAccountJSON' , null , new JSON (), 'FCM service account JSON.' , true )
2023-11-23 08:09:55 +13:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-10-04 23:45:59 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-01-24 17:34:59 +13:00
-> action ( function ( string $providerId , string $name , array | string | null $serviceAccountJSON , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-04 23:45:59 +13:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-11-23 08:09:55 +13:00
2024-01-24 17:34:59 +13:00
$serviceAccountJSON = \is_string ( $serviceAccountJSON )
? \json_decode ( $serviceAccountJSON , true )
: $serviceAccountJSON ;
2023-11-23 08:09:55 +13:00
$credentials = [];
2023-12-20 07:15:20 +13:00
if ( ! \is_null ( $serviceAccountJSON )) {
$credentials [ 'serviceAccountJSON' ] = $serviceAccountJSON ;
2023-11-23 08:09:55 +13:00
}
2023-12-20 07:15:20 +13:00
if ( $enabled === true && \array_key_exists ( 'serviceAccountJSON' , $credentials )) {
2023-11-23 08:09:55 +13:00
$enabled = true ;
} else {
$enabled = false ;
}
2023-10-04 23:45:59 +13:00
$provider = new Document ([
'$id' => $providerId ,
'name' => $name ,
'provider' => 'fcm' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_PUSH ,
2023-10-04 23:45:59 +13:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials
2023-08-30 04:59:48 +12:00
]);
2023-10-04 23:45:59 +13:00
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-10-04 23:45:59 +13:00
}
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-10-04 23:45:59 +13:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
App :: post ( '/v1/messaging/providers/apns' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Create APNS provider' )
2023-10-04 23:45:59 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].create' )
2023-10-04 23:45:59 +13:00
-> label ( 'scope' , 'providers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.method' , 'createApnsProvider' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/create-apns-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
-> param ( 'providerId' , '' , new CustomId (), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' )
2023-11-23 08:09:55 +13:00
-> param ( 'authKey' , '' , new Text ( 0 ), 'APNS authentication key.' , true )
-> param ( 'authKeyId' , '' , new Text ( 0 ), 'APNS authentication key ID.' , true )
-> param ( 'teamId' , '' , new Text ( 0 ), 'APNS team ID.' , true )
-> param ( 'bundleId' , '' , new Text ( 0 ), 'APNS bundle ID.' , true )
2024-02-24 13:34:08 +13:00
-> param ( 'sandbox' , false , new Boolean (), 'Use APNS sandbox environment.' , true )
2023-11-23 08:09:55 +13:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-11-01 06:47:58 +13:00
-> inject ( 'queueForEvents' )
2023-10-04 23:45:59 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-24 13:34:08 +13:00
-> action ( function ( string $providerId , string $name , string $authKey , string $authKeyId , string $teamId , string $bundleId , bool $sandbox , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-04 23:45:59 +13:00
$providerId = $providerId == 'unique()' ? ID :: unique () : $providerId ;
2023-11-23 08:09:55 +13:00
$credentials = [];
if ( ! empty ( $authKey )) {
$credentials [ 'authKey' ] = $authKey ;
}
if ( ! empty ( $authKeyId )) {
$credentials [ 'authKeyId' ] = $authKeyId ;
}
if ( ! empty ( $teamId )) {
$credentials [ 'teamId' ] = $teamId ;
}
if ( ! empty ( $bundleId )) {
$credentials [ 'bundleId' ] = $bundleId ;
}
if (
$enabled === true
&& \array_key_exists ( 'authKey' , $credentials )
&& \array_key_exists ( 'authKeyId' , $credentials )
&& \array_key_exists ( 'teamId' , $credentials )
&& \array_key_exists ( 'bundleId' , $credentials )
) {
$enabled = true ;
} else {
$enabled = false ;
}
2024-02-24 13:34:08 +13:00
$options = [
'sandbox' => $sandbox
];
2023-10-04 23:45:59 +13:00
$provider = new Document ([
'$id' => $providerId ,
'name' => $name ,
'provider' => 'apns' ,
2023-11-29 17:08:25 +13:00
'type' => MESSAGE_TYPE_PUSH ,
2023-10-04 23:45:59 +13:00
'enabled' => $enabled ,
2023-11-23 08:09:55 +13:00
'credentials' => $credentials ,
2024-02-24 13:34:08 +13:00
'options' => $options
2023-10-04 23:45:59 +13:00
]);
try {
$provider = $dbForProject -> createDocument ( 'providers' , $provider );
} catch ( DuplicateException ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_ALREADY_EXISTS );
2023-10-04 23:45:59 +13:00
}
2023-11-01 06:47:58 +13:00
$queueForEvents
2023-11-01 07:23:46 +13:00
-> setParam ( 'providerId' , $provider -> getId ());
2023-11-01 06:47:58 +13:00
2023-10-04 23:45:59 +13:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
App :: get ( '/v1/messaging/providers' )
2023-10-26 06:33:23 +13:00
-> desc ( 'List providers' )
2023-10-04 23:45:59 +13:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'providers.read' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listProviders' )
-> label ( 'sdk.description' , '/docs/references/messaging/list-providers.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER_LIST )
-> param ( 'queries' , [], new Providers (), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode ( ', ' , Providers :: ALLOWED_ATTRIBUTES ), true )
2023-10-26 06:33:23 +13:00
-> param ( 'search' , '' , new Text ( 256 ), 'Search term to filter your list results. Max length: 256 chars.' , true )
2023-10-04 23:45:59 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-10-26 07:25:45 +13:00
-> action ( function ( array $queries , string $search , Database $dbForProject , Response $response ) {
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2023-10-04 23:45:59 +13:00
2023-10-26 06:33:23 +13:00
if ( ! empty ( $search )) {
$queries [] = Query :: search ( 'search' , $search );
}
2024-02-12 22:55:45 +13:00
/**
2024-02-12 23:03:31 +13:00
* Get cursor document if there was a cursor query , we use array_filter and reset for reference $cursor to $queries
2024-02-12 22:55:45 +13:00
*/
$cursor = \array_filter ( $queries , function ( $query ) {
return \in_array ( $query -> getMethod (), [ Query :: TYPE_CURSOR_AFTER , Query :: TYPE_CURSOR_BEFORE ]);
});
2023-10-04 23:45:59 +13:00
$cursor = reset ( $cursor );
if ( $cursor ) {
$providerId = $cursor -> getValue ();
2023-10-18 06:23:26 +13:00
$cursorDocument = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'providers' , $providerId ));
2023-10-04 23:45:59 +13:00
2023-10-18 06:23:26 +13:00
if ( $cursorDocument -> isEmpty ()) {
2023-10-04 23:45:59 +13:00
throw new Exception ( Exception :: GENERAL_CURSOR_NOT_FOUND , " Provider ' { $providerId } ' for the 'cursor' value not found. " );
}
2023-10-07 02:53:46 +13:00
$cursor -> setValue ( $cursorDocument );
2023-10-04 23:45:59 +13:00
}
$response -> dynamic ( new Document ([
'providers' => $dbForProject -> find ( 'providers' , $queries ),
2023-10-26 06:33:23 +13:00
'total' => $dbForProject -> count ( 'providers' , $queries , APP_LIMIT_COUNT ),
2023-10-04 23:45:59 +13:00
]), Response :: MODEL_PROVIDER_LIST );
});
2023-11-03 01:30:17 +13:00
App :: get ( '/v1/messaging/providers/:providerId/logs' )
-> desc ( 'List provider logs' )
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'providers.read' )
2023-11-10 09:50:55 +13:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-11-03 01:30:17 +13:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listProviderLogs' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/list-provider-logs.md' )
2023-11-03 01:30:17 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_LOG_LIST )
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
-> param ( 'queries' , [], new Queries ([ new Limit (), new Offset ()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset' , true )
-> inject ( 'response' )
-> inject ( 'dbForProject' )
-> inject ( 'locale' )
-> inject ( 'geodb' )
-> action ( function ( string $providerId , array $queries , Response $response , Database $dbForProject , Locale $locale , Reader $geodb ) {
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2023-11-03 01:30:17 +13:00
$grouped = Query :: groupByType ( $queries );
$limit = $grouped [ 'limit' ] ? ? APP_LIMIT_COUNT ;
$offset = $grouped [ 'offset' ] ? ? 0 ;
$audit = new Audit ( $dbForProject );
$resource = 'provider/' . $providerId ;
$logs = $audit -> getLogsByResource ( $resource , $limit , $offset );
$output = [];
foreach ( $logs as $i => & $log ) {
$log [ 'userAgent' ] = ( ! empty ( $log [ 'userAgent' ])) ? $log [ 'userAgent' ] : 'UNKNOWN' ;
$detector = new Detector ( $log [ 'userAgent' ]);
$detector -> skipBotDetection (); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector -> getOS ();
$client = $detector -> getClient ();
$device = $detector -> getDevice ();
$output [ $i ] = new Document ([
'event' => $log [ 'event' ],
'userId' => ID :: custom ( $log [ 'data' ][ 'userId' ]),
'userEmail' => $log [ 'data' ][ 'userEmail' ] ? ? null ,
'userName' => $log [ 'data' ][ 'userName' ] ? ? null ,
'mode' => $log [ 'data' ][ 'mode' ] ? ? null ,
'ip' => $log [ 'ip' ],
'time' => $log [ 'time' ],
'osCode' => $os [ 'osCode' ],
'osName' => $os [ 'osName' ],
'osVersion' => $os [ 'osVersion' ],
'clientType' => $client [ 'clientType' ],
'clientCode' => $client [ 'clientCode' ],
'clientName' => $client [ 'clientName' ],
'clientVersion' => $client [ 'clientVersion' ],
'clientEngine' => $client [ 'clientEngine' ],
'clientEngineVersion' => $client [ 'clientEngineVersion' ],
'deviceName' => $device [ 'deviceName' ],
'deviceBrand' => $device [ 'deviceBrand' ],
'deviceModel' => $device [ 'deviceModel' ]
]);
$record = $geodb -> get ( $log [ 'ip' ]);
if ( $record ) {
$output [ $i ][ 'countryCode' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), false ) ? \strtolower ( $record [ 'country' ][ 'iso_code' ]) : '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), $locale -> getText ( 'locale.country.unknown' ));
} else {
$output [ $i ][ 'countryCode' ] = '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'locale.country.unknown' );
}
}
$response -> dynamic ( new Document ([
'total' => $audit -> countLogsByResource ( $resource ),
'logs' => $output ,
]), Response :: MODEL_LOG_LIST );
});
2023-10-06 11:00:47 +13:00
App :: get ( '/v1/messaging/providers/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Get provider' )
2023-10-04 23:45:59 +13:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'providers.read' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'getProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/get-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-06 11:00:47 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-10-04 23:45:59 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-10-06 11:00:47 +13:00
-> action ( function ( string $providerId , Database $dbForProject , Response $response ) {
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-10-04 23:45:59 +13:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
$response -> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/mailgun/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Update Mailgun provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'updateMailgunProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/update-mailgun-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
2023-12-17 12:41:20 +13:00
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Mailgun API Key.' , true )
-> param ( 'domain' , '' , new Text ( 0 ), 'Mailgun Domain.' , true )
2023-11-09 22:23:42 +13:00
-> param ( 'isEuRegion' , null , new Boolean (), 'Set as EU region.' , true )
2023-12-17 12:41:20 +13:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-12-06 03:01:32 +13:00
-> param ( 'fromName' , '' , new Text ( 128 ), 'Sender Name.' , true )
-> param ( 'fromEmail' , '' , new Email (), 'Sender email address.' , true )
2023-12-06 07:24:55 +13:00
-> param ( 'replyToName' , '' , new Text ( 128 ), 'Name set in the reply to field for the mail. Default value is sender name.' , true )
-> param ( 'replyToEmail' , '' , new Text ( 128 ), 'Email set in the reply to field for the mail. Default value is sender email.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-12-17 12:41:20 +13:00
-> action ( function ( string $providerId , string $name , string $apiKey , string $domain , ? bool $isEuRegion , ? bool $enabled , string $fromName , string $fromEmail , string $replyToName , string $replyToEmail , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-08-24 21:01:22 +12:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
2023-08-24 08:23:52 +12:00
}
2024-01-24 15:16:19 +13:00
$providerProvider = $provider -> getAttribute ( 'provider' );
if ( $providerProvider !== 'mailgun' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-08-24 21:01:22 +12:00
}
2023-08-24 08:23:52 +12:00
2023-09-20 22:25:22 +12:00
if ( ! empty ( $name )) {
2023-08-24 21:01:22 +12:00
$provider -> setAttribute ( 'name' , $name );
2023-10-04 23:45:59 +13:00
}
2023-12-06 03:01:32 +13:00
$options = $provider -> getAttribute ( 'options' );
if ( ! empty ( $fromName )) {
$options [ 'fromName' ] = $fromName ;
}
if ( ! empty ( $fromEmail )) {
$options [ 'fromEmail' ] = $fromEmail ;
}
if ( ! empty ( $replyToName )) {
$options [ 'replyToName' ] = $replyToName ;
2023-08-24 21:01:22 +12:00
}
2023-12-06 03:01:32 +13:00
if ( ! empty ( $replyToEmail )) {
$options [ 'replyToEmail' ] = $replyToEmail ;
}
$provider -> setAttribute ( 'options' , $options );
2023-10-04 23:45:59 +13:00
$credentials = $provider -> getAttribute ( 'credentials' );
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $isEuRegion )) {
2023-10-04 23:45:59 +13:00
$credentials [ 'isEuRegion' ] = $isEuRegion ;
}
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
}
if ( ! empty ( $domain )) {
$credentials [ 'domain' ] = $domain ;
2023-08-24 21:01:22 +12:00
}
2023-10-04 23:45:59 +13:00
$provider -> setAttribute ( 'credentials' , $credentials );
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if (
\array_key_exists ( 'isEuRegion' , $credentials ) &&
\array_key_exists ( 'apiKey' , $credentials ) &&
\array_key_exists ( 'domain' , $credentials ) &&
2024-01-25 20:05:36 +13:00
\array_key_exists ( 'fromEmail' , $options )
2024-01-24 15:16:19 +13:00
) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-08-24 21:01:22 +12:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-08-24 21:01:22 +12:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/sendgrid/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Update Sendgrid provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'updateSendgridProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/update-sendgrid-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-10-04 23:45:59 +13:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Sendgrid API key.' , true )
2023-12-06 03:01:32 +13:00
-> param ( 'fromName' , '' , new Text ( 128 ), 'Sender Name.' , true )
-> param ( 'fromEmail' , '' , new Email (), 'Sender email address.' , true )
-> param ( 'replyToName' , '' , new Text ( 128 ), 'Name set in the Reply To field for the mail. Default value is Sender Name.' , true )
-> param ( 'replyToEmail' , '' , new Text ( 128 ), 'Email set in the Reply To field for the mail. Default value is Sender Email.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-12-06 07:24:55 +13:00
-> action ( function ( string $providerId , string $name , ? bool $enabled , string $apiKey , string $fromName , string $fromEmail , string $replyToName , string $replyToEmail , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-10-04 23:45:59 +13:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
$providerAttr = $provider -> getAttribute ( 'provider' );
if ( $providerAttr !== 'sendgrid' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-10-04 23:45:59 +13:00
}
if ( ! empty ( $name )) {
$provider -> setAttribute ( 'name' , $name );
}
2023-12-06 03:01:32 +13:00
$options = $provider -> getAttribute ( 'options' );
if ( ! empty ( $fromName )) {
$options [ 'fromName' ] = $fromName ;
2023-10-24 08:35:46 +13:00
}
2023-12-06 03:01:32 +13:00
if ( ! empty ( $fromEmail )) {
$options [ 'fromEmail' ] = $fromEmail ;
}
if ( ! empty ( $replyToName )) {
$options [ 'replyToName' ] = $replyToName ;
}
if ( ! empty ( $replyToEmail )) {
$options [ 'replyToEmail' ] = $replyToEmail ;
}
$provider -> setAttribute ( 'options' , $options );
2023-10-04 23:45:59 +13:00
if ( ! empty ( $apiKey )) {
$provider -> setAttribute ( 'credentials' , [
'apiKey' => $apiKey ,
]);
}
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if (
\array_key_exists ( 'apiKey' , $provider -> getAttribute ( 'credentials' )) &&
2024-01-25 20:05:36 +13:00
\array_key_exists ( 'fromEmail' , $provider -> getAttribute ( 'options' ))
2024-01-24 15:16:19 +13:00
) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-10-04 23:45:59 +13:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2024-02-01 01:30:09 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
App :: patch ( '/v1/messaging/providers/smtp/:providerId' )
-> desc ( 'Update SMTP provider' )
-> groups ([ 'api' , 'messaging' ])
-> label ( 'audits.event' , 'provider.update' )
-> label ( 'audits.resource' , 'provider/{response.$id}' )
-> label ( 'event' , 'providers.[providerId].update' )
-> label ( 'scope' , 'providers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.method' , 'updateSmtpProvider' )
2024-02-01 01:30:09 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/update-smtp-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
2024-02-21 22:04:27 +13:00
-> param ( 'host' , '' , new Text ( 0 ), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls://smtp1.example.com:587;ssl://smtp2.example.com:465"`. Hosts will be tried in order.' , true )
2024-02-01 01:30:09 +13:00
-> param ( 'port' , null , new Range ( 1 , 65535 ), 'SMTP port.' , true )
-> param ( 'username' , '' , new Text ( 0 ), 'Authentication username.' , true )
-> param ( 'password' , '' , new Text ( 0 ), 'Authentication password.' , true )
2024-02-01 17:44:42 +13:00
-> param ( 'encryption' , '' , new WhiteList ([ 'none' , 'ssl' , 'tls' ]), 'Encryption type. Can be \'ssl\' or \'tls\'' , true )
2024-02-01 01:30:09 +13:00
-> param ( 'autoTLS' , null , new Boolean (), 'Enable SMTP AutoTLS feature.' , true )
2024-02-13 15:16:37 +13:00
-> param ( 'mailer' , '' , new Text ( 0 ), 'The value to use for the X-Mailer header.' , true )
2024-02-01 01:30:09 +13:00
-> param ( 'fromName' , '' , new Text ( 128 ), 'Sender Name.' , true )
-> param ( 'fromEmail' , '' , new Email (), 'Sender email address.' , true )
-> param ( 'replyToName' , '' , new Text ( 128 ), 'Name set in the Reply To field for the mail. Default value is Sender Name.' , true )
-> param ( 'replyToEmail' , '' , new Text ( 128 ), 'Email set in the Reply To field for the mail. Default value is Sender Email.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
-> inject ( 'queueForEvents' )
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-13 15:16:37 +13:00
-> action ( function ( string $providerId , string $name , string $host , ? int $port , string $username , string $password , string $encryption , ? bool $autoTLS , string $mailer , string $fromName , string $fromEmail , string $replyToName , string $replyToEmail , ? bool $enabled , Event $queueForEvents , Database $dbForProject , Response $response ) {
2024-02-01 01:30:09 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
2024-02-13 15:16:37 +13:00
if ( $provider -> getAttribute ( 'provider' ) !== 'smtp' ) {
2024-02-01 01:30:09 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
}
if ( ! empty ( $name )) {
$provider -> setAttribute ( 'name' , $name );
}
$options = $provider -> getAttribute ( 'options' );
2024-02-13 15:16:37 +13:00
if ( ! empty ( $encryption )) {
$options [ 'encryption' ] = $encryption === 'none' ? '' : $encryption ;
}
if ( ! \is_null ( $autoTLS )) {
$options [ 'autoTLS' ] = $autoTLS ;
}
if ( ! empty ( $mailer )) {
$options [ 'mailer' ] = $mailer ;
}
2024-02-01 01:30:09 +13:00
if ( ! empty ( $fromName )) {
$options [ 'fromName' ] = $fromName ;
}
if ( ! empty ( $fromEmail )) {
$options [ 'fromEmail' ] = $fromEmail ;
}
if ( ! empty ( $replyToName )) {
$options [ 'replyToName' ] = $replyToName ;
}
if ( ! empty ( $replyToEmail )) {
$options [ 'replyToEmail' ] = $replyToEmail ;
}
$provider -> setAttribute ( 'options' , $options );
$credentials = $provider -> getAttribute ( 'credentials' );
if ( ! empty ( $host )) {
$credentials [ 'host' ] = $host ;
}
if ( ! \is_null ( $port )) {
$credentials [ 'port' ] = $port ;
}
if ( ! empty ( $username )) {
$credentials [ 'username' ] = $username ;
}
if ( ! empty ( $password )) {
$credentials [ 'password' ] = $password ;
}
$provider -> setAttribute ( 'credentials' , $credentials );
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
2024-02-01 17:45:41 +13:00
if (
! empty ( $options [ 'fromEmail' ])
&& \array_key_exists ( 'host' , $credentials )
) {
2024-02-01 01:30:09 +13:00
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
} else {
$provider -> setAttribute ( 'enabled' , false );
}
}
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-10-04 23:45:59 +13:00
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-10-04 23:45:59 +13:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/msg91/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Update Msg91 provider' )
2023-10-04 23:45:59 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 22:03:13 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-10-04 23:45:59 +13:00
-> label ( 'scope' , 'providers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'updateMsg91Provider' )
-> label ( 'sdk.description' , '/docs/references/messaging/update-msg91-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-10-04 23:45:59 +13:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
-> param ( 'senderId' , '' , new Text ( 0 ), 'Msg91 Sender ID.' , true )
-> param ( 'authKey' , '' , new Text ( 0 ), 'Msg91 Auth Key.' , true )
2023-10-26 07:25:45 +13:00
-> param ( 'from' , '' , new Text ( 256 ), 'Sender number.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-04 23:45:59 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-16 09:00:47 +13:00
-> action ( function ( string $providerId , string $name , ? bool $enabled , string $senderId , string $authKey , string $from , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-10-04 23:45:59 +13:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
$providerAttr = $provider -> getAttribute ( 'provider' );
if ( $providerAttr !== 'msg91' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-10-04 23:45:59 +13:00
}
if ( ! empty ( $name )) {
$provider -> setAttribute ( 'name' , $name );
}
2023-10-24 08:35:46 +13:00
if ( ! empty ( $from )) {
$provider -> setAttribute ( 'options' , [
'from' => $from ,
]);
}
2023-10-04 23:45:59 +13:00
$credentials = $provider -> getAttribute ( 'credentials' );
if ( ! empty ( $senderId )) {
$credentials [ 'senderId' ] = $senderId ;
}
if ( ! empty ( $authKey )) {
$credentials [ 'authKey' ] = $authKey ;
}
$provider -> setAttribute ( 'credentials' , $credentials );
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if (
\array_key_exists ( 'senderId' , $credentials ) &&
\array_key_exists ( 'authKey' , $credentials ) &&
\array_key_exists ( 'from' , $provider -> getAttribute ( 'options' ))
) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-10-04 23:45:59 +13:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-10-04 23:45:59 +13:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/telesign/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Update Telesign provider' )
2023-10-04 23:45:59 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-10-04 23:45:59 +13:00
-> label ( 'scope' , 'providers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'updateTelesignProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/update-telesign-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-10-04 23:45:59 +13:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2024-02-12 15:10:18 +13:00
-> param ( 'customerId' , '' , new Text ( 0 ), 'Telesign customer ID.' , true )
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Telesign API key.' , true )
2023-10-26 07:25:45 +13:00
-> param ( 'from' , '' , new Text ( 256 ), 'Sender number.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-04 23:45:59 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-12 15:10:18 +13:00
-> action ( function ( string $providerId , string $name , ? bool $enabled , string $customerId , string $apiKey , string $from , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-10-04 23:45:59 +13:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
$providerAttr = $provider -> getAttribute ( 'provider' );
if ( $providerAttr !== 'telesign' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-10-04 23:45:59 +13:00
}
if ( ! empty ( $name )) {
$provider -> setAttribute ( 'name' , $name );
}
2023-10-24 08:35:46 +13:00
if ( ! empty ( $from )) {
$provider -> setAttribute ( 'options' , [
'from' => $from ,
]);
}
2023-10-04 23:45:59 +13:00
$credentials = $provider -> getAttribute ( 'credentials' );
2024-02-12 15:10:18 +13:00
if ( ! empty ( $customerId )) {
$credentials [ 'customerId' ] = $customerId ;
2023-10-04 23:45:59 +13:00
}
2024-02-12 15:10:18 +13:00
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
2023-08-30 04:59:48 +12:00
}
2023-10-04 23:45:59 +13:00
$provider -> setAttribute ( 'credentials' , $credentials );
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if (
2024-02-12 15:10:18 +13:00
\array_key_exists ( 'customerId' , $credentials ) &&
\array_key_exists ( 'apiKey' , $credentials ) &&
2024-01-24 15:16:19 +13:00
\array_key_exists ( 'from' , $provider -> getAttribute ( 'options' ))
) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-10-04 23:45:59 +13:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-08-24 21:01:22 +12:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-22 04:45:15 +12:00
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/textmagic/:providerId' )
2023-11-21 20:05:36 +13:00
-> desc ( 'Update Textmagic provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-11-21 20:05:36 +13:00
-> label ( 'sdk.method' , 'updateTextmagicProvider' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/update-textmagic-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
2023-09-20 22:25:22 +12:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-08-24 21:01:22 +12:00
-> param ( 'username' , '' , new Text ( 0 ), 'Textmagic username.' , true )
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Textmagic apiKey.' , true )
2023-10-26 07:25:45 +13:00
-> param ( 'from' , '' , new Text ( 256 ), 'Sender number.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-16 09:00:47 +13:00
-> action ( function ( string $providerId , string $name , ? bool $enabled , string $username , string $apiKey , string $from , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-08-24 21:01:22 +12:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
2023-08-24 08:23:52 +12:00
}
2023-08-24 21:01:22 +12:00
$providerAttr = $provider -> getAttribute ( 'provider' );
2023-08-24 08:23:52 +12:00
2023-11-14 21:37:52 +13:00
if ( $providerAttr !== 'textmagic' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-08-24 21:01:22 +12:00
}
2023-08-24 08:23:52 +12:00
2023-09-20 22:25:22 +12:00
if ( ! empty ( $name )) {
2023-08-24 21:01:22 +12:00
$provider -> setAttribute ( 'name' , $name );
}
2023-10-24 08:35:46 +13:00
if ( ! empty ( $from )) {
$provider -> setAttribute ( 'options' , [
'from' => $from ,
]);
}
2023-10-04 23:45:59 +13:00
$credentials = $provider -> getAttribute ( 'credentials' );
2023-08-30 04:59:48 +12:00
2023-10-04 23:45:59 +13:00
if ( ! empty ( $username )) {
$credentials [ 'username' ] = $username ;
2023-08-30 04:59:48 +12:00
}
2023-10-04 23:45:59 +13:00
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
2023-08-30 04:59:48 +12:00
}
2023-10-04 23:45:59 +13:00
$provider -> setAttribute ( 'credentials' , $credentials );
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if (
\array_key_exists ( 'username' , $credentials ) &&
\array_key_exists ( 'apiKey' , $credentials ) &&
\array_key_exists ( 'from' , $provider -> getAttribute ( 'options' ))
) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-10-04 23:45:59 +13:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-08-24 21:01:22 +12:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/twilio/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Update Twilio provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'updateTwilioProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/update-twilio-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
2023-09-20 22:25:22 +12:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-12-05 03:48:37 +13:00
-> param ( 'accountSid' , '' , new Text ( 0 ), 'Twilio account secret ID.' , true )
-> param ( 'authToken' , '' , new Text ( 0 ), 'Twilio authentication token.' , true )
2023-10-26 07:25:45 +13:00
-> param ( 'from' , '' , new Text ( 256 ), 'Sender number.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-16 09:00:47 +13:00
-> action ( function ( string $providerId , string $name , ? bool $enabled , string $accountSid , string $authToken , string $from , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-08-24 21:01:22 +12:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
2023-08-24 08:23:52 +12:00
}
2023-08-24 21:01:22 +12:00
$providerAttr = $provider -> getAttribute ( 'provider' );
2023-08-24 08:23:52 +12:00
2023-08-24 21:01:22 +12:00
if ( $providerAttr !== 'twilio' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-08-24 21:01:22 +12:00
}
2023-09-20 22:25:22 +12:00
if ( ! empty ( $name )) {
2023-08-24 21:01:22 +12:00
$provider -> setAttribute ( 'name' , $name );
}
2023-10-24 08:35:46 +13:00
if ( ! empty ( $from )) {
$provider -> setAttribute ( 'options' , [
'from' => $from ,
]);
}
2023-10-04 23:45:59 +13:00
$credentials = $provider -> getAttribute ( 'credentials' );
2023-08-30 04:59:48 +12:00
2023-10-04 23:45:59 +13:00
if ( ! empty ( $accountSid )) {
$credentials [ 'accountSid' ] = $accountSid ;
2023-08-30 04:59:48 +12:00
}
2023-10-04 23:45:59 +13:00
if ( ! empty ( $authToken )) {
$credentials [ 'authToken' ] = $authToken ;
2023-08-30 04:59:48 +12:00
}
2023-10-04 23:45:59 +13:00
$provider -> setAttribute ( 'credentials' , $credentials );
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if (
\array_key_exists ( 'accountSid' , $credentials ) &&
\array_key_exists ( 'authToken' , $credentials ) &&
\array_key_exists ( 'from' , $provider -> getAttribute ( 'options' ))
) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-10-04 23:45:59 +13:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-08-24 21:01:22 +12:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/vonage/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Update Vonage provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.method' , 'updateVonageProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/update-vonage-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
2023-09-20 22:25:22 +12:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-08-24 21:01:22 +12:00
-> param ( 'apiKey' , '' , new Text ( 0 ), 'Vonage API key.' , true )
-> param ( 'apiSecret' , '' , new Text ( 0 ), 'Vonage API secret.' , true )
2023-10-26 07:25:45 +13:00
-> param ( 'from' , '' , new Text ( 256 ), 'Sender number.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-16 09:00:47 +13:00
-> action ( function ( string $providerId , string $name , ? bool $enabled , string $apiKey , string $apiSecret , string $from , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-08-24 21:01:22 +12:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
$providerAttr = $provider -> getAttribute ( 'provider' );
if ( $providerAttr !== 'vonage' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-08-24 08:23:52 +12:00
}
2023-09-20 22:25:22 +12:00
if ( ! empty ( $name )) {
2023-08-24 21:01:22 +12:00
$provider -> setAttribute ( 'name' , $name );
}
2023-10-24 08:35:46 +13:00
if ( ! empty ( $from )) {
$provider -> setAttribute ( 'options' , [
'from' => $from ,
]);
}
2023-10-04 23:45:59 +13:00
$credentials = $provider -> getAttribute ( 'credentials' );
2023-08-30 04:59:48 +12:00
2023-10-04 23:45:59 +13:00
if ( ! empty ( $apiKey )) {
$credentials [ 'apiKey' ] = $apiKey ;
2023-08-30 04:59:48 +12:00
}
2023-10-04 23:45:59 +13:00
if ( ! empty ( $apiSecret )) {
$credentials [ 'apiSecret' ] = $apiSecret ;
2023-08-30 04:59:48 +12:00
}
2023-10-04 23:45:59 +13:00
$provider -> setAttribute ( 'credentials' , $credentials );
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if (
\array_key_exists ( 'apiKey' , $credentials ) &&
\array_key_exists ( 'apiSecret' , $credentials ) &&
\array_key_exists ( 'from' , $provider -> getAttribute ( 'options' ))
) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-10-04 23:45:59 +13:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-08-24 21:01:22 +12:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/fcm/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Update FCM provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-22 02:26:17 +13:00
-> label ( 'sdk.method' , 'updateFcmProvider' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/update-fcm-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
2023-09-20 22:25:22 +12:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-12-20 07:15:20 +13:00
-> param ( 'serviceAccountJSON' , null , new JSON (), 'FCM service account JSON.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-01-24 17:34:59 +13:00
-> action ( function ( string $providerId , string $name , ? bool $enabled , array | string | null $serviceAccountJSON , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-08-24 21:01:22 +12:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
$providerAttr = $provider -> getAttribute ( 'provider' );
if ( $providerAttr !== 'fcm' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-08-24 21:01:22 +12:00
}
2023-09-20 22:25:22 +12:00
if ( ! empty ( $name )) {
2023-08-24 21:01:22 +12:00
$provider -> setAttribute ( 'name' , $name );
}
2023-12-20 07:15:20 +13:00
if ( ! \is_null ( $serviceAccountJSON )) {
2024-01-24 17:34:59 +13:00
$serviceAccountJSON = \is_string ( $serviceAccountJSON )
? \json_decode ( $serviceAccountJSON , true )
: $serviceAccountJSON ;
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'credentials' , [
'serviceAccountJSON' => $serviceAccountJSON
]);
2023-08-24 21:01:22 +12:00
}
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if ( \array_key_exists ( 'serviceAccountJSON' , $provider -> getAttribute ( 'credentials' ))) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-08-24 21:01:22 +12:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-08-24 21:01:22 +12:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2023-10-07 02:53:46 +13:00
App :: patch ( '/v1/messaging/providers/apns/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Update APNS provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 06:33:23 +13:00
-> label ( 'audits.event' , 'provider.update' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'provider/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].update' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-22 02:26:17 +13:00
-> label ( 'sdk.method' , 'updateApnsProvider' )
2023-10-04 23:45:59 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/update-apns-provider.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_PROVIDER )
2023-10-07 02:53:46 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-08-24 21:01:22 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'Provider name.' , true )
2023-09-20 22:25:22 +12:00
-> param ( 'enabled' , null , new Boolean (), 'Set as enabled.' , true )
2023-08-24 21:01:22 +12:00
-> param ( 'authKey' , '' , new Text ( 0 ), 'APNS authentication key.' , true )
-> param ( 'authKeyId' , '' , new Text ( 0 ), 'APNS authentication key ID.' , true )
-> param ( 'teamId' , '' , new Text ( 0 ), 'APNS team ID.' , true )
-> param ( 'bundleId' , '' , new Text ( 0 ), 'APNS bundle ID.' , true )
2024-02-24 13:34:08 +13:00
-> param ( 'sandbox' , null , new Boolean (), 'Use APNS sandbox environment.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-24 13:34:08 +13:00
-> action ( function ( string $providerId , string $name , ? bool $enabled , string $authKey , string $authKeyId , string $teamId , string $bundleId , ? bool $sandbox , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-07 02:53:46 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-08-24 21:01:22 +12:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
2023-08-24 08:23:52 +12:00
}
2023-08-24 21:01:22 +12:00
$providerAttr = $provider -> getAttribute ( 'provider' );
2023-08-24 08:23:52 +12:00
2023-08-24 21:01:22 +12:00
if ( $providerAttr !== 'apns' ) {
2023-10-06 00:27:48 +13:00
throw new Exception ( Exception :: PROVIDER_INCORRECT_TYPE );
2023-08-24 21:01:22 +12:00
}
2023-08-24 08:23:52 +12:00
2023-09-20 22:25:22 +12:00
if ( ! empty ( $name )) {
2023-08-24 21:01:22 +12:00
$provider -> setAttribute ( 'name' , $name );
}
2023-10-04 23:45:59 +13:00
$credentials = $provider -> getAttribute ( 'credentials' );
if ( ! empty ( $authKey )) {
$credentials [ 'authKey' ] = $authKey ;
}
if ( ! empty ( $authKeyId )) {
$credentials [ 'authKeyId' ] = $authKeyId ;
}
if ( ! empty ( $teamId )) {
$credentials [ 'teamId' ] = $teamId ;
}
if ( ! empty ( $bundleId )) {
$credentials [ 'bundle' ] = $bundleId ;
}
$provider -> setAttribute ( 'credentials' , $credentials );
2024-02-24 13:34:08 +13:00
$options = $provider -> getAttribute ( 'options' );
if ( ! \is_null ( $sandbox )) {
$options [ 'sandbox' ] = $sandbox ;
}
$provider -> setAttribute ( 'options' , $options );
2024-01-24 15:16:19 +13:00
if ( ! \is_null ( $enabled )) {
if ( $enabled ) {
if (
\array_key_exists ( 'authKey' , $credentials ) &&
\array_key_exists ( 'authKeyId' , $credentials ) &&
\array_key_exists ( 'teamId' , $credentials ) &&
\array_key_exists ( 'bundleId' , $credentials )
) {
$provider -> setAttribute ( 'enabled' , true );
} else {
throw new Exception ( Exception :: PROVIDER_MISSING_CREDENTIALS );
}
2023-11-23 08:09:55 +13:00
} else {
2024-01-24 15:16:19 +13:00
$provider -> setAttribute ( 'enabled' , false );
2023-11-23 08:09:55 +13:00
}
}
2023-08-24 21:01:22 +12:00
$provider = $dbForProject -> updateDocument ( 'providers' , $provider -> getId (), $provider );
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-08-24 21:01:22 +12:00
$response
-> dynamic ( $provider , Response :: MODEL_PROVIDER );
});
2023-08-23 04:45:31 +12:00
2023-10-06 11:00:47 +13:00
App :: delete ( '/v1/messaging/providers/:providerId' )
2023-10-26 06:33:23 +13:00
-> desc ( 'Delete provider' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'provider.delete' )
2023-11-10 09:50:55 +13:00
-> label ( 'audits.resource' , 'provider/{request.$providerId}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'providers.[providerId].delete' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'providers.write' )
2023-09-21 22:48:20 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'deleteProvider' )
-> label ( 'sdk.description' , '/docs/references/messaging/delete-provider.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_NOCONTENT )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_NONE )
2023-10-06 11:00:47 +13:00
-> param ( 'providerId' , '' , new UID (), 'Provider ID.' )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-01 07:23:46 +13:00
-> action ( function ( string $providerId , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-06 11:00:47 +13:00
$provider = $dbForProject -> getDocument ( 'providers' , $providerId );
2023-08-24 21:01:22 +12:00
if ( $provider -> isEmpty ()) {
throw new Exception ( Exception :: PROVIDER_NOT_FOUND );
}
$dbForProject -> deleteDocument ( 'providers' , $provider -> getId ());
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'providerId' , $provider -> getId ());
2023-10-17 11:11:42 +13:00
$response
-> setStatusCode ( Response :: STATUS_CODE_NOCONTENT )
-> noContent ();
2023-08-24 21:01:22 +12:00
});
2023-08-23 04:45:31 +12:00
2023-10-05 00:57:56 +13:00
App :: post ( '/v1/messaging/topics' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Create topic' )
2023-10-05 00:57:56 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-11-09 19:59:16 +13:00
-> label ( 'audits.event' , 'topic.create' )
2023-10-26 21:16:45 +13:00
-> label ( 'audits.resource' , 'topic/{response.$id}' )
2023-11-01 22:03:13 +13:00
-> label ( 'event' , 'topics.[topicId].create' )
2023-10-05 00:57:56 +13:00
-> label ( 'scope' , 'topics.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'createTopic' )
-> label ( 'sdk.description' , '/docs/references/messaging/create-topic.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_TOPIC )
-> param ( 'topicId' , '' , new CustomId (), 'Topic ID. Choose a custom Topic ID or a new Topic ID.' )
-> param ( 'name' , '' , new Text ( 128 ), 'Topic Name.' )
2024-02-13 17:24:31 +13:00
-> param ( 'subscribe' , [ Role :: users ()], new Roles ( APP_LIMIT_ARRAY_PARAMS_SIZE ), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-05 00:57:56 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-13 17:24:31 +13:00
-> action ( function ( string $topicId , string $name , array $subscribe , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-05 00:57:56 +13:00
$topicId = $topicId == 'unique()' ? ID :: unique () : $topicId ;
$topic = new Document ([
'$id' => $topicId ,
'name' => $name ,
2024-02-13 17:24:31 +13:00
'subscribe' => $subscribe ,
2023-10-05 00:57:56 +13:00
]);
try {
$topic = $dbForProject -> createDocument ( 'topics' , $topic );
} catch ( DuplicateException ) {
throw new Exception ( Exception :: TOPIC_ALREADY_EXISTS );
}
2023-10-14 01:56:54 +13:00
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'topicId' , $topic -> getId ());
2023-10-14 01:56:54 +13:00
$response
2023-10-18 06:23:26 +13:00
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $topic , Response :: MODEL_TOPIC );
2023-10-05 00:57:56 +13:00
});
2023-08-25 08:15:17 +12:00
App :: get ( '/v1/messaging/topics' )
2024-02-21 22:04:27 +13:00
-> desc ( 'List topics' )
2023-08-25 08:15:17 +12:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'topics.read' )
2023-08-25 11:06:41 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-25 08:15:17 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listTopics' )
-> label ( 'sdk.description' , '/docs/references/messaging/list-topics.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_TOPIC_LIST )
-> param ( 'queries' , [], new Topics (), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode ( ', ' , Topics :: ALLOWED_ATTRIBUTES ), true )
2023-10-26 06:33:23 +13:00
-> param ( 'search' , '' , new Text ( 256 ), 'Search term to filter your list results. Max length: 256 chars.' , true )
2023-08-25 08:15:17 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-10-26 06:33:23 +13:00
-> action ( function ( array $queries , string $search , Database $dbForProject , Response $response ) {
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2023-08-25 08:15:17 +12:00
2023-10-26 06:33:23 +13:00
if ( ! empty ( $search )) {
$queries [] = Query :: search ( 'search' , $search );
}
2024-02-12 22:55:45 +13:00
/**
2024-02-12 23:03:31 +13:00
* Get cursor document if there was a cursor query , we use array_filter and reset for reference $cursor to $queries
2024-02-12 22:55:45 +13:00
*/
$cursor = \array_filter ( $queries , function ( $query ) {
return \in_array ( $query -> getMethod (), [ Query :: TYPE_CURSOR_AFTER , Query :: TYPE_CURSOR_BEFORE ]);
});
2023-08-25 08:15:17 +12:00
$cursor = reset ( $cursor );
if ( $cursor ) {
$topicId = $cursor -> getValue ();
2023-10-18 06:23:26 +13:00
$cursorDocument = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'topics' , $topicId ));
2023-08-25 08:15:17 +12:00
2023-10-18 06:23:26 +13:00
if ( $cursorDocument -> isEmpty ()) {
2023-08-25 08:15:17 +12:00
throw new Exception ( Exception :: GENERAL_CURSOR_NOT_FOUND , " Topic ' { $topicId } ' for the 'cursor' value not found. " );
}
$cursor -> setValue ( $cursorDocument [ 0 ]);
}
$response -> dynamic ( new Document ([
2023-08-25 11:06:41 +12:00
'topics' => $dbForProject -> find ( 'topics' , $queries ),
2023-10-26 06:33:23 +13:00
'total' => $dbForProject -> count ( 'topics' , $queries , APP_LIMIT_COUNT ),
2023-08-25 08:15:17 +12:00
]), Response :: MODEL_TOPIC_LIST );
});
2023-11-03 01:30:17 +13:00
App :: get ( '/v1/messaging/topics/:topicId/logs' )
-> desc ( 'List topic logs' )
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'topics.read' )
2023-11-10 09:50:55 +13:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-11-03 01:30:17 +13:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listTopicLogs' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/list-topic-logs.md' )
2023-11-03 01:30:17 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_LOG_LIST )
-> param ( 'topicId' , '' , new UID (), 'Topic ID.' )
-> param ( 'queries' , [], new Queries ([ new Limit (), new Offset ()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset' , true )
-> inject ( 'response' )
-> inject ( 'dbForProject' )
-> inject ( 'locale' )
-> inject ( 'geodb' )
-> action ( function ( string $topicId , array $queries , Response $response , Database $dbForProject , Locale $locale , Reader $geodb ) {
$topic = $dbForProject -> getDocument ( 'topics' , $topicId );
if ( $topic -> isEmpty ()) {
throw new Exception ( Exception :: TOPIC_NOT_FOUND );
}
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2023-11-03 01:30:17 +13:00
$grouped = Query :: groupByType ( $queries );
$limit = $grouped [ 'limit' ] ? ? APP_LIMIT_COUNT ;
$offset = $grouped [ 'offset' ] ? ? 0 ;
$audit = new Audit ( $dbForProject );
$resource = 'topic/' . $topicId ;
$logs = $audit -> getLogsByResource ( $resource , $limit , $offset );
$output = [];
foreach ( $logs as $i => & $log ) {
$log [ 'userAgent' ] = ( ! empty ( $log [ 'userAgent' ])) ? $log [ 'userAgent' ] : 'UNKNOWN' ;
$detector = new Detector ( $log [ 'userAgent' ]);
$detector -> skipBotDetection (); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector -> getOS ();
$client = $detector -> getClient ();
$device = $detector -> getDevice ();
$output [ $i ] = new Document ([
'event' => $log [ 'event' ],
'userId' => ID :: custom ( $log [ 'data' ][ 'userId' ]),
'userEmail' => $log [ 'data' ][ 'userEmail' ] ? ? null ,
'userName' => $log [ 'data' ][ 'userName' ] ? ? null ,
'mode' => $log [ 'data' ][ 'mode' ] ? ? null ,
'ip' => $log [ 'ip' ],
'time' => $log [ 'time' ],
'osCode' => $os [ 'osCode' ],
'osName' => $os [ 'osName' ],
'osVersion' => $os [ 'osVersion' ],
'clientType' => $client [ 'clientType' ],
'clientCode' => $client [ 'clientCode' ],
'clientName' => $client [ 'clientName' ],
'clientVersion' => $client [ 'clientVersion' ],
'clientEngine' => $client [ 'clientEngine' ],
'clientEngineVersion' => $client [ 'clientEngineVersion' ],
'deviceName' => $device [ 'deviceName' ],
'deviceBrand' => $device [ 'deviceBrand' ],
'deviceModel' => $device [ 'deviceModel' ]
]);
$record = $geodb -> get ( $log [ 'ip' ]);
if ( $record ) {
$output [ $i ][ 'countryCode' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), false ) ? \strtolower ( $record [ 'country' ][ 'iso_code' ]) : '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), $locale -> getText ( 'locale.country.unknown' ));
} else {
$output [ $i ][ 'countryCode' ] = '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'locale.country.unknown' );
}
}
$response -> dynamic ( new Document ([
'total' => $audit -> countLogsByResource ( $resource ),
'logs' => $output ,
]), Response :: MODEL_LOG_LIST );
});
2023-08-29 03:11:05 +12:00
App :: get ( '/v1/messaging/topics/:topicId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Get topic' )
2023-08-25 08:15:17 +12:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'topics.read' )
2023-08-25 11:06:41 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-25 08:15:17 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'getTopic' )
-> label ( 'sdk.description' , '/docs/references/messaging/get-topic.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_TOPIC )
2023-08-29 03:11:05 +12:00
-> param ( 'topicId' , '' , new UID (), 'Topic ID.' )
2023-08-25 08:15:17 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-08-29 03:11:05 +12:00
-> action ( function ( string $topicId , Database $dbForProject , Response $response ) {
$topic = $dbForProject -> getDocument ( 'topics' , $topicId );
2023-08-25 08:15:17 +12:00
if ( $topic -> isEmpty ()) {
throw new Exception ( Exception :: TOPIC_NOT_FOUND );
}
2023-08-29 03:11:05 +12:00
$topic = $dbForProject -> getDocument ( 'topics' , $topicId );
2023-08-25 08:15:17 +12:00
$response
-> dynamic ( $topic , Response :: MODEL_TOPIC );
});
2023-08-25 11:06:41 +12:00
App :: patch ( '/v1/messaging/topics/:topicId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Update topic' )
2023-08-25 08:15:17 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'topic.update' )
-> label ( 'audits.resource' , 'topic/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'topics.[topicId].update' )
2023-08-25 08:15:17 +12:00
-> label ( 'scope' , 'topics.write' )
2023-08-25 11:06:41 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-25 08:15:17 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'updateTopic' )
-> label ( 'sdk.description' , '/docs/references/messaging/update-topic.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_TOPIC )
2023-08-25 11:06:41 +12:00
-> param ( 'topicId' , '' , new UID (), 'Topic ID.' )
2024-02-23 23:56:49 +13:00
-> param ( 'name' , null , new Text ( 128 ), 'Topic Name.' , true )
-> param ( 'subscribe' , null , new Roles ( APP_LIMIT_ARRAY_PARAMS_SIZE ), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-25 08:15:17 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2024-02-23 23:56:49 +13:00
-> action ( function ( string $topicId , ? string $name , ? array $subscribe , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-08-25 11:06:41 +12:00
$topic = $dbForProject -> getDocument ( 'topics' , $topicId );
2023-08-25 08:15:17 +12:00
if ( $topic -> isEmpty ()) {
throw new Exception ( Exception :: TOPIC_NOT_FOUND );
}
2024-02-23 23:56:49 +13:00
if ( ! \is_null ( $name )) {
2023-08-25 08:15:17 +12:00
$topic -> setAttribute ( 'name' , $name );
}
2024-02-23 23:56:49 +13:00
if ( ! \is_null ( $subscribe )) {
$topic -> setAttribute ( 'subscribe' , $subscribe );
}
2023-08-25 11:06:41 +12:00
$topic = $dbForProject -> updateDocument ( 'topics' , $topicId , $topic );
2023-08-25 08:15:17 +12:00
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'topicId' , $topic -> getId ());
2023-08-25 08:15:17 +12:00
$response
-> dynamic ( $topic , Response :: MODEL_TOPIC );
});
2023-08-25 11:06:41 +12:00
App :: delete ( '/v1/messaging/topics/:topicId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Delete topic' )
2023-08-25 08:15:17 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'topic.delete' )
2023-11-10 09:50:55 +13:00
-> label ( 'audits.resource' , 'topic/{request.$topicId}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'topics.[topicId].delete' )
2023-08-25 08:15:17 +12:00
-> label ( 'scope' , 'topics.write' )
2023-08-25 11:06:41 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-25 08:15:17 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'deleteTopic' )
-> label ( 'sdk.description' , '/docs/references/messaging/delete-topic.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_NOCONTENT )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_NONE )
2023-08-25 11:06:41 +12:00
-> param ( 'topicId' , '' , new UID (), 'Topic ID.' )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-25 08:15:17 +12:00
-> inject ( 'dbForProject' )
2023-10-21 00:32:13 +13:00
-> inject ( 'queueForDeletes' )
2023-08-25 08:15:17 +12:00
-> inject ( 'response' )
2023-11-01 07:23:46 +13:00
-> action ( function ( string $topicId , Event $queueForEvents , Database $dbForProject , Delete $queueForDeletes , Response $response ) {
2023-08-25 11:06:41 +12:00
$topic = $dbForProject -> getDocument ( 'topics' , $topicId );
2023-08-25 08:15:17 +12:00
if ( $topic -> isEmpty ()) {
throw new Exception ( Exception :: TOPIC_NOT_FOUND );
}
2023-10-18 06:23:26 +13:00
$dbForProject -> deleteDocument ( 'topics' , $topicId );
2023-10-21 00:32:13 +13:00
$queueForDeletes
2023-10-26 06:33:23 +13:00
-> setType ( DELETE_TYPE_TOPIC )
2023-10-18 06:23:26 +13:00
-> setDocument ( $topic );
2023-10-17 11:11:42 +13:00
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'topicId' , $topic -> getId ());
2023-10-17 11:11:42 +13:00
$response
-> setStatusCode ( Response :: STATUS_CODE_NOCONTENT )
-> noContent ();
2023-08-25 08:15:17 +12:00
});
2023-10-05 00:57:56 +13:00
App :: post ( '/v1/messaging/topics/:topicId/subscribers' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Create subscriber' )
2023-10-05 00:57:56 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'subscriber.create' )
-> label ( 'audits.resource' , 'subscriber/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'topics.[topicId].subscribers.[subscriberId].create' )
2023-10-05 00:57:56 +13:00
-> label ( 'scope' , 'subscribers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_JWT , APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2023-10-14 01:56:54 +13:00
-> label ( 'sdk.method' , 'createSubscriber' )
-> label ( 'sdk.description' , '/docs/references/messaging/create-subscriber.md' )
2023-10-05 00:57:56 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_SUBSCRIBER )
2023-11-09 22:23:42 +13:00
-> param ( 'subscriberId' , '' , new CustomId (), 'Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.' )
-> param ( 'topicId' , '' , new UID (), 'Topic ID. The topic ID to subscribe to.' )
-> param ( 'targetId' , '' , new UID (), 'Target ID. The target ID to link to the specified Topic ID.' )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-05 00:57:56 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-01 07:23:46 +13:00
-> action ( function ( string $subscriberId , string $topicId , string $targetId , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-10-05 00:57:56 +13:00
$subscriberId = $subscriberId == 'unique()' ? ID :: unique () : $subscriberId ;
$topic = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'topics' , $topicId ));
if ( $topic -> isEmpty ()) {
throw new Exception ( Exception :: TOPIC_NOT_FOUND );
}
2024-02-13 17:24:31 +13:00
$validator = new Authorization ( 'subscribe' );
if ( ! $validator -> isValid ( $topic -> getAttribute ( 'subscribe' ))) {
throw new Exception ( Exception :: USER_UNAUTHORIZED , $validator -> getDescription ());
}
2023-10-05 00:57:56 +13:00
$target = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'targets' , $targetId ));
if ( $target -> isEmpty ()) {
throw new Exception ( Exception :: USER_TARGET_NOT_FOUND );
}
2023-11-20 20:04:50 +13:00
$user = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'users' , $target -> getAttribute ( 'userId' )));
2023-10-05 00:57:56 +13:00
$subscriber = new Document ([
'$id' => $subscriberId ,
'$permissions' => [
2024-02-13 17:24:31 +13:00
Permission :: read ( Role :: user ( $user -> getId ())),
Permission :: delete ( Role :: user ( $user -> getId ())),
2023-10-05 00:57:56 +13:00
],
'topicId' => $topicId ,
'topicInternalId' => $topic -> getInternalId (),
'targetId' => $targetId ,
'targetInternalId' => $target -> getInternalId (),
2024-02-13 17:24:31 +13:00
'userId' => $user -> getId (),
2023-12-01 11:09:43 +13:00
'userInternalId' => $user -> getInternalId (),
'providerType' => $target -> getAttribute ( 'providerType' ),
2024-01-18 15:32:32 +13:00
'search' => implode ( ' ' , [
$subscriberId ,
$targetId ,
2024-02-13 17:24:31 +13:00
$user -> getId (),
2024-01-18 15:32:32 +13:00
$target -> getAttribute ( 'providerType' ),
]),
2023-10-05 00:57:56 +13:00
]);
try {
$subscriber = $dbForProject -> createDocument ( 'subscribers' , $subscriber );
2024-02-15 17:23:30 +13:00
$totalAttribute = match ( $target -> getAttribute ( 'providerType' )) {
MESSAGE_TYPE_EMAIL => 'emailTotal' ,
MESSAGE_TYPE_SMS => 'smsTotal' ,
MESSAGE_TYPE_PUSH => 'pushTotal' ,
default => throw new Exception ( Exception :: TARGET_PROVIDER_INVALID_TYPE ),
};
Authorization :: skip ( fn () => $dbForProject -> increaseDocumentAttribute (
'topics' ,
$topicId ,
$totalAttribute ,
));
2023-10-05 00:57:56 +13:00
} catch ( DuplicateException ) {
throw new Exception ( Exception :: SUBSCRIBER_ALREADY_EXISTS );
}
2023-10-14 01:56:54 +13:00
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'topicId' , $topic -> getId ())
-> setParam ( 'subscriberId' , $subscriber -> getId ());
2023-11-23 22:05:16 +13:00
$subscriber
-> setAttribute ( 'target' , $target )
-> setAttribute ( 'userName' , $user -> getAttribute ( 'name' ));
2023-11-20 23:51:06 +13:00
2023-10-14 01:56:54 +13:00
$response
2023-10-18 06:23:26 +13:00
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
2023-11-20 23:51:06 +13:00
-> dynamic ( $subscriber , Response :: MODEL_SUBSCRIBER );
2023-10-05 00:57:56 +13:00
});
2023-08-29 03:11:05 +12:00
App :: get ( '/v1/messaging/topics/:topicId/subscribers' )
2024-02-21 22:04:27 +13:00
-> desc ( 'List subscribers' )
2023-08-29 03:11:05 +12:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'subscribers.read' )
2023-10-14 01:56:54 +13:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-29 03:11:05 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listSubscribers' )
-> label ( 'sdk.description' , '/docs/references/messaging/list-subscribers.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_SUBSCRIBER_LIST )
2023-11-09 22:23:42 +13:00
-> param ( 'topicId' , '' , new UID (), 'Topic ID. The topic ID subscribed to.' )
2023-10-18 20:49:21 +13:00
-> param ( 'queries' , [], new Subscribers (), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode ( ', ' , Providers :: ALLOWED_ATTRIBUTES ), true )
2023-12-01 11:09:43 +13:00
-> param ( 'search' , '' , new Text ( 256 ), 'Search term to filter your list results. Max length: 256 chars.' , true )
2023-08-29 03:11:05 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-12-01 11:25:29 +13:00
-> action ( function ( string $topicId , array $queries , string $search , Database $dbForProject , Response $response ) {
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2023-10-18 20:49:21 +13:00
2023-12-01 11:09:43 +13:00
if ( ! empty ( $search )) {
$queries [] = Query :: search ( 'search' , $search );
}
2023-08-29 03:11:05 +12:00
$topic = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'topics' , $topicId ));
if ( $topic -> isEmpty ()) {
throw new Exception ( Exception :: TOPIC_NOT_FOUND );
}
2024-02-15 17:56:06 +13:00
$queries [] = Query :: equal ( 'topicInternalId' , [ $topic -> getInternalId ()]);
2023-10-18 20:49:21 +13:00
2024-02-12 22:55:45 +13:00
/**
2024-02-12 23:03:31 +13:00
* Get cursor document if there was a cursor query , we use array_filter and reset for reference $cursor to $queries
2024-02-12 22:55:45 +13:00
*/
$cursor = \array_filter ( $queries , function ( $query ) {
return \in_array ( $query -> getMethod (), [ Query :: TYPE_CURSOR_AFTER , Query :: TYPE_CURSOR_BEFORE ]);
});
2023-10-18 20:49:21 +13:00
$cursor = reset ( $cursor );
if ( $cursor ) {
$subscriberId = $cursor -> getValue ();
$cursorDocument = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'subscribers' , $subscriberId ));
if ( $cursorDocument -> isEmpty ()) {
throw new Exception ( Exception :: GENERAL_CURSOR_NOT_FOUND , " Subscriber ' { $subscriberId } ' for the 'cursor' value not found. " );
}
$cursor -> setValue ( $cursorDocument );
}
2023-11-20 20:04:50 +13:00
$subscribers = $dbForProject -> find ( 'subscribers' , $queries );
$subscribers = batch ( \array_map ( function ( Document $subscriber ) use ( $dbForProject ) {
return function () use ( $subscriber , $dbForProject ) {
2023-11-23 08:09:55 +13:00
$target = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'targets' , $subscriber -> getAttribute ( 'targetId' )));
2023-11-23 22:05:16 +13:00
$user = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'users' , $target -> getAttribute ( 'userId' )));
2023-11-20 20:04:50 +13:00
return $subscriber
2023-11-23 22:05:16 +13:00
-> setAttribute ( 'target' , $target )
2023-11-20 20:04:50 +13:00
-> setAttribute ( 'userName' , $user -> getAttribute ( 'name' ));
};
}, $subscribers ));
2023-08-29 03:11:05 +12:00
$response
-> dynamic ( new Document ([
2023-11-20 20:04:50 +13:00
'subscribers' => $subscribers ,
2023-10-26 06:33:23 +13:00
'total' => $dbForProject -> count ( 'subscribers' , $queries , APP_LIMIT_COUNT ),
2023-08-29 03:11:05 +12:00
]), Response :: MODEL_SUBSCRIBER_LIST );
2023-08-29 03:13:18 +12:00
});
2023-08-29 03:11:05 +12:00
2023-11-03 01:30:17 +13:00
App :: get ( '/v1/messaging/subscribers/:subscriberId/logs' )
-> desc ( 'List subscriber logs' )
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'subscribers.read' )
2023-11-10 09:50:55 +13:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-11-03 01:30:17 +13:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listSubscriberLogs' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/list-subscriber-logs.md' )
2023-11-03 01:30:17 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_LOG_LIST )
-> param ( 'subscriberId' , '' , new UID (), 'Subscriber ID.' )
-> param ( 'queries' , [], new Queries ([ new Limit (), new Offset ()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset' , true )
-> inject ( 'response' )
-> inject ( 'dbForProject' )
-> inject ( 'locale' )
-> inject ( 'geodb' )
-> action ( function ( string $subscriberId , array $queries , Response $response , Database $dbForProject , Locale $locale , Reader $geodb ) {
$subscriber = $dbForProject -> getDocument ( 'subscribers' , $subscriberId );
if ( $subscriber -> isEmpty ()) {
throw new Exception ( Exception :: SUBSCRIBER_NOT_FOUND );
}
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2023-11-03 01:30:17 +13:00
$grouped = Query :: groupByType ( $queries );
$limit = $grouped [ 'limit' ] ? ? APP_LIMIT_COUNT ;
$offset = $grouped [ 'offset' ] ? ? 0 ;
$audit = new Audit ( $dbForProject );
$resource = 'subscriber/' . $subscriberId ;
$logs = $audit -> getLogsByResource ( $resource , $limit , $offset );
$output = [];
foreach ( $logs as $i => & $log ) {
$log [ 'userAgent' ] = ( ! empty ( $log [ 'userAgent' ])) ? $log [ 'userAgent' ] : 'UNKNOWN' ;
$detector = new Detector ( $log [ 'userAgent' ]);
$detector -> skipBotDetection (); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector -> getOS ();
$client = $detector -> getClient ();
$device = $detector -> getDevice ();
$output [ $i ] = new Document ([
'event' => $log [ 'event' ],
'userId' => ID :: custom ( $log [ 'data' ][ 'userId' ]),
'userEmail' => $log [ 'data' ][ 'userEmail' ] ? ? null ,
'userName' => $log [ 'data' ][ 'userName' ] ? ? null ,
'mode' => $log [ 'data' ][ 'mode' ] ? ? null ,
'ip' => $log [ 'ip' ],
'time' => $log [ 'time' ],
'osCode' => $os [ 'osCode' ],
'osName' => $os [ 'osName' ],
'osVersion' => $os [ 'osVersion' ],
'clientType' => $client [ 'clientType' ],
'clientCode' => $client [ 'clientCode' ],
'clientName' => $client [ 'clientName' ],
'clientVersion' => $client [ 'clientVersion' ],
'clientEngine' => $client [ 'clientEngine' ],
'clientEngineVersion' => $client [ 'clientEngineVersion' ],
'deviceName' => $device [ 'deviceName' ],
'deviceBrand' => $device [ 'deviceBrand' ],
'deviceModel' => $device [ 'deviceModel' ]
]);
$record = $geodb -> get ( $log [ 'ip' ]);
if ( $record ) {
$output [ $i ][ 'countryCode' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), false ) ? \strtolower ( $record [ 'country' ][ 'iso_code' ]) : '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), $locale -> getText ( 'locale.country.unknown' ));
} else {
$output [ $i ][ 'countryCode' ] = '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'locale.country.unknown' );
}
}
$response -> dynamic ( new Document ([
'total' => $audit -> countLogsByResource ( $resource ),
'logs' => $output ,
]), Response :: MODEL_LOG_LIST );
});
2023-11-09 22:23:42 +13:00
App :: get ( '/v1/messaging/topics/:topicId/subscribers/:subscriberId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Get subscriber' )
2023-08-29 03:11:05 +12:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'subscribers.read' )
2023-10-14 01:56:54 +13:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-08-29 03:11:05 +12:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'getSubscriber' )
-> label ( 'sdk.description' , '/docs/references/messaging/get-subscriber.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_SUBSCRIBER )
2023-11-09 22:23:42 +13:00
-> param ( 'topicId' , '' , new UID (), 'Topic ID. The topic ID subscribed to.' )
2023-08-29 03:11:05 +12:00
-> param ( 'subscriberId' , '' , new UID (), 'Subscriber ID.' )
-> inject ( 'dbForProject' )
-> inject ( 'response' )
-> action ( function ( string $topicId , string $subscriberId , Database $dbForProject , Response $response ) {
$topic = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'topics' , $topicId ));
if ( $topic -> isEmpty ()) {
throw new Exception ( Exception :: TOPIC_NOT_FOUND );
}
2023-08-29 03:13:18 +12:00
2023-08-29 03:11:05 +12:00
$subscriber = $dbForProject -> getDocument ( 'subscribers' , $subscriberId );
2023-08-29 03:13:18 +12:00
if ( $subscriber -> isEmpty () || $subscriber -> getAttribute ( 'topicId' ) !== $topicId ) {
2023-08-29 03:11:05 +12:00
throw new Exception ( Exception :: SUBSCRIBER_NOT_FOUND );
}
2023-11-23 08:09:55 +13:00
$target = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'targets' , $subscriber -> getAttribute ( 'targetId' )));
2023-11-23 22:05:16 +13:00
$user = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'users' , $target -> getAttribute ( 'userId' )));
2023-11-20 20:04:50 +13:00
2023-11-23 08:09:55 +13:00
$subscriber
2023-11-23 22:05:16 +13:00
-> setAttribute ( 'target' , $target )
2023-11-23 08:09:55 +13:00
-> setAttribute ( 'userName' , $user -> getAttribute ( 'name' ));
2023-11-20 23:51:06 +13:00
2023-08-29 03:11:05 +12:00
$response
2023-11-20 23:51:06 +13:00
-> dynamic ( $subscriber , Response :: MODEL_SUBSCRIBER );
2023-08-29 03:11:05 +12:00
});
2023-11-09 22:23:42 +13:00
App :: delete ( '/v1/messaging/topics/:topicId/subscribers/:subscriberId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Delete subscriber' )
2023-08-29 03:11:05 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'subscriber.delete' )
2023-11-10 09:50:55 +13:00
-> label ( 'audits.resource' , 'subscriber/{request.$subscriberId}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'topics.[topicId].subscribers.[subscriberId].delete' )
2023-08-29 03:11:05 +12:00
-> label ( 'scope' , 'subscribers.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_JWT , APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'deleteSubscriber' )
-> label ( 'sdk.description' , '/docs/references/messaging/delete-subscriber.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_NOCONTENT )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_NONE )
2023-11-09 22:23:42 +13:00
-> param ( 'topicId' , '' , new UID (), 'Topic ID. The topic ID subscribed to.' )
2023-08-29 03:11:05 +12:00
-> param ( 'subscriberId' , '' , new UID (), 'Subscriber ID.' )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-29 03:11:05 +12:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-11-01 07:23:46 +13:00
-> action ( function ( string $topicId , string $subscriberId , Event $queueForEvents , Database $dbForProject , Response $response ) {
2023-08-29 03:11:05 +12:00
$topic = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'topics' , $topicId ));
if ( $topic -> isEmpty ()) {
throw new Exception ( Exception :: TOPIC_NOT_FOUND );
}
$subscriber = $dbForProject -> getDocument ( 'subscribers' , $subscriberId );
if ( $subscriber -> isEmpty () || $subscriber -> getAttribute ( 'topicId' ) !== $topicId ) {
throw new Exception ( Exception :: SUBSCRIBER_NOT_FOUND );
}
2023-10-26 20:07:39 +13:00
2024-02-15 17:23:30 +13:00
$target = $dbForProject -> getDocument ( 'targets' , $subscriber -> getAttribute ( 'targetId' ));
2023-11-01 07:23:46 +13:00
$dbForProject -> deleteDocument ( 'subscribers' , $subscriberId );
2024-02-15 17:23:30 +13:00
$totalAttribute = match ( $target -> getAttribute ( 'providerType' )) {
MESSAGE_TYPE_EMAIL => 'emailTotal' ,
MESSAGE_TYPE_SMS => 'smsTotal' ,
MESSAGE_TYPE_PUSH => 'pushTotal' ,
default => throw new Exception ( Exception :: TARGET_PROVIDER_INVALID_TYPE ),
};
Authorization :: skip ( fn () => $dbForProject -> decreaseDocumentAttribute (
'topics' ,
$topicId ,
$totalAttribute ,
min : 0
));
2023-08-29 03:11:05 +12:00
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'topicId' , $topic -> getId ())
-> setParam ( 'subscriberId' , $subscriber -> getId ());
2023-08-29 03:11:05 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_NOCONTENT )
-> noContent ();
});
2023-08-22 04:45:15 +12:00
App :: post ( '/v1/messaging/messages/email' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Create email' )
2023-08-24 21:01:22 +12:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'message.create' )
-> label ( 'audits.resource' , 'message/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'messages.[messageId].create' )
2023-08-24 21:01:22 +12:00
-> label ( 'scope' , 'messages.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-01-11 15:58:24 +13:00
-> label ( 'sdk.method' , 'createEmail' )
2023-10-14 01:56:54 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/create-email.md' )
2023-08-24 21:01:22 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_MESSAGE )
2023-09-22 03:47:15 +12:00
-> param ( 'messageId' , '' , new CustomId (), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
2023-10-04 23:45:59 +13:00
-> param ( 'subject' , '' , new Text ( 998 ), 'Email Subject.' )
2023-10-06 00:27:48 +13:00
-> param ( 'content' , '' , new Text ( 64230 ), 'Email Content.' )
2024-01-05 13:10:57 +13:00
-> param ( 'topics' , [], new ArrayList ( new UID ()), 'List of Topic IDs.' , true )
-> param ( 'users' , [], new ArrayList ( new UID ()), 'List of User IDs.' , true )
-> param ( 'targets' , [], new ArrayList ( new UID ()), 'List of Targets IDs.' , true )
2023-12-15 03:19:24 +13:00
-> param ( 'cc' , [], new ArrayList ( new UID ()), 'Array of target IDs to be added as CC.' , true )
-> param ( 'bcc' , [], new ArrayList ( new UID ()), 'Array of target IDs to be added as BCC.' , true )
2024-02-20 00:08:57 +13:00
-> param ( 'attachments' , [], new ArrayList ( new CompoundUID ()), 'Array of compound bucket IDs to file IDs to be attached to the email.' , true )
2024-02-27 00:27:35 +13:00
-> param ( 'draft' , false , new Boolean (), 'Is message a draft' , true )
2023-10-04 23:45:59 +13:00
-> param ( 'html' , false , new Boolean (), 'Is content of type HTML' , true )
2023-11-29 17:08:25 +13:00
-> param ( 'scheduledAt' , null , new DatetimeValidator ( requireDateInFuture : true ), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-08-24 21:01:22 +12:00
-> inject ( 'dbForProject' )
2023-12-07 23:25:19 +13:00
-> inject ( 'dbForConsole' )
2023-09-06 22:10:56 +12:00
-> inject ( 'project' )
2023-10-20 22:25:17 +13:00
-> inject ( 'queueForMessaging' )
2023-08-24 21:01:22 +12:00
-> inject ( 'response' )
2024-02-26 23:52:32 +13:00
-> action ( function ( string $messageId , string $subject , string $content , array $topics , array $users , array $targets , array $cc , array $bcc , array $attachments , bool $draft , bool $html , ? string $scheduledAt , Event $queueForEvents , Database $dbForProject , Database $dbForConsole , Document $project , Messaging $queueForMessaging , Response $response ) {
2023-12-15 03:19:24 +13:00
$messageId = $messageId == 'unique()'
? ID :: unique ()
: $messageId ;
2023-09-22 03:47:15 +12:00
2024-02-26 23:52:32 +13:00
if ( $draft ) {
$status = MessageStatus :: DRAFT ;
} else {
$status = \is_null ( $scheduledAt )
? MessageStatus :: PROCESSING
: MessageStatus :: SCHEDULED ;
}
2024-01-11 14:15:37 +13:00
if ( $status !== MessageStatus :: DRAFT && \count ( $topics ) === 0 && \count ( $users ) === 0 && \count ( $targets ) === 0 ) {
2023-10-31 07:07:57 +13:00
throw new Exception ( Exception :: MESSAGE_MISSING_TARGET );
}
2024-01-19 16:16:24 +13:00
if ( $status === MessageStatus :: SCHEDULED && \is_null ( $scheduledAt )) {
throw new Exception ( Exception :: MESSAGE_MISSING_SCHEDULE );
}
2023-12-15 03:19:24 +13:00
$mergedTargets = \array_merge ( $targets , $cc , $bcc );
2023-12-01 11:09:43 +13:00
2023-12-17 12:41:20 +13:00
if ( ! empty ( $mergedTargets )) {
$foundTargets = $dbForProject -> find ( 'targets' , [
Query :: equal ( '$id' , $mergedTargets ),
Query :: equal ( 'providerType' , [ MESSAGE_TYPE_EMAIL ]),
Query :: limit ( \count ( $mergedTargets )),
]);
2023-12-15 03:19:24 +13:00
2023-12-17 12:41:20 +13:00
if ( \count ( $foundTargets ) !== \count ( $mergedTargets )) {
throw new Exception ( Exception :: MESSAGE_TARGET_NOT_EMAIL );
}
2023-12-01 11:09:43 +13:00
2023-12-17 12:41:20 +13:00
foreach ( $foundTargets as $target ) {
if ( $target -> isEmpty ()) {
throw new Exception ( Exception :: USER_TARGET_NOT_FOUND );
}
2023-12-01 11:09:43 +13:00
}
}
2024-02-20 00:08:57 +13:00
if ( ! empty ( $attachments )) {
foreach ( $attachments as & $attachment ) {
[ $bucketId , $fileId ] = CompoundUID :: parse ( $attachment );
$bucket = $dbForProject -> getDocument ( 'buckets' , $bucketId );
if ( $bucket -> isEmpty ()) {
throw new Exception ( Exception :: STORAGE_BUCKET_NOT_FOUND );
}
$file = $dbForProject -> getDocument ( 'bucket_' . $bucket -> getInternalId (), $fileId );
if ( $file -> isEmpty ()) {
throw new Exception ( Exception :: STORAGE_FILE_NOT_FOUND );
}
$attachment = [
'bucketId' => $bucketId ,
'fileId' => $fileId ,
];
}
}
2023-08-24 21:01:22 +12:00
$message = $dbForProject -> createDocument ( 'messages' , new Document ([
2023-09-22 03:47:15 +12:00
'$id' => $messageId ,
2023-11-29 17:09:44 +13:00
'providerType' => MESSAGE_TYPE_EMAIL ,
2023-10-31 07:07:57 +13:00
'topics' => $topics ,
'users' => $users ,
'targets' => $targets ,
2023-12-07 23:25:19 +13:00
'scheduledAt' => $scheduledAt ,
2023-08-24 21:01:22 +12:00
'data' => [
'subject' => $subject ,
'content' => $content ,
2023-09-26 20:42:44 +13:00
'html' => $html ,
2023-12-06 07:24:55 +13:00
'cc' => $cc ,
'bcc' => $bcc ,
2024-02-20 00:08:57 +13:00
'attachments' => $attachments ,
2023-08-24 21:01:22 +12:00
],
2023-10-07 02:53:46 +13:00
'status' => $status ,
2023-10-19 20:59:48 +13:00
]));
2024-01-19 16:15:54 +13:00
switch ( $status ) {
case MessageStatus :: PROCESSING :
$queueForMessaging
2024-02-21 01:06:35 +13:00
-> setType ( MESSAGE_SEND_TYPE_EXTERNAL )
-> setMessageId ( $message -> getId ());
2024-01-19 16:15:54 +13:00
break ;
case MessageStatus :: SCHEDULED :
$schedule = $dbForConsole -> createDocument ( 'schedules' , new Document ([
'region' => App :: getEnv ( '_APP_REGION' , 'default' ),
'resourceType' => 'message' ,
'resourceId' => $message -> getId (),
'resourceInternalId' => $message -> getInternalId (),
'resourceUpdatedAt' => DateTime :: now (),
'projectId' => $project -> getId (),
'schedule' => $scheduledAt ,
'active' => true ,
]));
$message -> setAttribute ( 'scheduleId' , $schedule -> getId ());
$dbForProject -> updateDocument (
'messages' ,
$message -> getId (),
$message
);
break ;
default :
break ;
2023-10-19 20:59:48 +13:00
}
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'messageId' , $message -> getId ());
2023-10-19 20:59:48 +13:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $message , Response :: MODEL_MESSAGE );
});
App :: post ( '/v1/messaging/messages/sms' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Create SMS' )
2023-10-19 20:59:48 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'message.create' )
-> label ( 'audits.resource' , 'message/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'messages.[messageId].create' )
2023-10-19 20:59:48 +13:00
-> label ( 'scope' , 'messages.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.method' , 'createSms' )
2023-10-19 20:59:48 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/create-sms.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_MESSAGE )
-> param ( 'messageId' , '' , new CustomId (), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
-> param ( 'content' , '' , new Text ( 64230 ), 'SMS Content.' )
2024-01-05 13:10:57 +13:00
-> param ( 'topics' , [], new ArrayList ( new UID ()), 'List of Topic IDs.' , true )
-> param ( 'users' , [], new ArrayList ( new UID ()), 'List of User IDs.' , true )
-> param ( 'targets' , [], new ArrayList ( new UID ()), 'List of Targets IDs.' , true )
2024-02-27 00:27:35 +13:00
-> param ( 'draft' , false , new Boolean (), 'Is message a draft' , true )
2023-11-29 17:08:25 +13:00
-> param ( 'scheduledAt' , null , new DatetimeValidator ( requireDateInFuture : true ), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-19 20:59:48 +13:00
-> inject ( 'dbForProject' )
2023-12-07 23:25:19 +13:00
-> inject ( 'dbForConsole' )
2023-10-19 20:59:48 +13:00
-> inject ( 'project' )
2023-10-20 22:30:22 +13:00
-> inject ( 'queueForMessaging' )
2023-10-19 20:59:48 +13:00
-> inject ( 'response' )
2024-02-26 23:52:32 +13:00
-> action ( function ( string $messageId , string $content , array $topics , array $users , array $targets , bool $draft , ? string $scheduledAt , Event $queueForEvents , Database $dbForProject , Database $dbForConsole , Document $project , Messaging $queueForMessaging , Response $response ) {
2023-12-15 03:19:24 +13:00
$messageId = $messageId == 'unique()'
? ID :: unique ()
: $messageId ;
2023-10-19 20:59:48 +13:00
2024-02-26 23:52:32 +13:00
if ( $draft ) {
$status = MessageStatus :: DRAFT ;
} else {
$status = \is_null ( $scheduledAt )
? MessageStatus :: PROCESSING
: MessageStatus :: SCHEDULED ;
}
2024-01-11 14:15:37 +13:00
if ( $status !== MessageStatus :: DRAFT && \count ( $topics ) === 0 && \count ( $users ) === 0 && \count ( $targets ) === 0 ) {
2023-10-31 07:07:57 +13:00
throw new Exception ( Exception :: MESSAGE_MISSING_TARGET );
}
2024-01-19 16:16:24 +13:00
if ( $status === MessageStatus :: SCHEDULED && \is_null ( $scheduledAt )) {
throw new Exception ( Exception :: MESSAGE_MISSING_SCHEDULE );
}
2024-01-11 14:15:37 +13:00
if ( ! empty ( $targets )) {
$foundTargets = $dbForProject -> find ( 'targets' , [
Query :: equal ( '$id' , $targets ),
Query :: equal ( 'providerType' , [ MESSAGE_TYPE_SMS ]),
Query :: limit ( \count ( $targets )),
]);
2023-12-01 11:09:43 +13:00
2024-01-11 14:15:37 +13:00
if ( \count ( $foundTargets ) !== \count ( $targets )) {
throw new Exception ( Exception :: MESSAGE_TARGET_NOT_SMS );
}
2023-12-01 11:09:43 +13:00
2024-01-11 14:15:37 +13:00
foreach ( $foundTargets as $target ) {
if ( $target -> isEmpty ()) {
throw new Exception ( Exception :: USER_TARGET_NOT_FOUND );
}
2023-12-01 11:09:43 +13:00
}
}
2023-10-19 20:59:48 +13:00
$message = $dbForProject -> createDocument ( 'messages' , new Document ([
'$id' => $messageId ,
2023-11-29 17:09:44 +13:00
'providerType' => MESSAGE_TYPE_SMS ,
2023-10-31 07:07:57 +13:00
'topics' => $topics ,
'users' => $users ,
'targets' => $targets ,
2023-10-19 20:59:48 +13:00
'data' => [
'content' => $content ,
],
'status' => $status ,
]));
2024-01-19 16:15:54 +13:00
switch ( $status ) {
case MessageStatus :: PROCESSING :
$queueForMessaging
2024-02-21 01:06:35 +13:00
-> setType ( MESSAGE_SEND_TYPE_EXTERNAL )
-> setMessageId ( $message -> getId ());
2024-01-19 16:15:54 +13:00
break ;
case MessageStatus :: SCHEDULED :
$schedule = $dbForConsole -> createDocument ( 'schedules' , new Document ([
'region' => App :: getEnv ( '_APP_REGION' , 'default' ),
'resourceType' => 'message' ,
'resourceId' => $message -> getId (),
'resourceInternalId' => $message -> getInternalId (),
'resourceUpdatedAt' => DateTime :: now (),
'projectId' => $project -> getId (),
'schedule' => $scheduledAt ,
'active' => true ,
]));
$message -> setAttribute ( 'scheduleId' , $schedule -> getId ());
$dbForProject -> updateDocument (
'messages' ,
$message -> getId (),
$message
);
break ;
default :
break ;
2023-10-19 20:59:48 +13:00
}
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'messageId' , $message -> getId ());
2023-10-19 20:59:48 +13:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $message , Response :: MODEL_MESSAGE );
});
App :: post ( '/v1/messaging/messages/push' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Create push notification' )
2023-10-19 20:59:48 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'message.create' )
-> label ( 'audits.resource' , 'message/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'messages.[messageId].create' )
2023-10-19 20:59:48 +13:00
-> label ( 'scope' , 'messages.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-01-11 15:58:24 +13:00
-> label ( 'sdk.method' , 'createPush' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/create-push.md' )
2023-10-19 20:59:48 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_MESSAGE )
-> param ( 'messageId' , '' , new CustomId (), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
-> param ( 'title' , '' , new Text ( 256 ), 'Title for push notification.' )
-> param ( 'body' , '' , new Text ( 64230 ), 'Body for push notification.' )
2024-01-05 13:10:57 +13:00
-> param ( 'topics' , [], new ArrayList ( new UID ()), 'List of Topic IDs.' , true )
-> param ( 'users' , [], new ArrayList ( new UID ()), 'List of User IDs.' , true )
-> param ( 'targets' , [], new ArrayList ( new UID ()), 'List of Targets IDs.' , true )
2023-10-19 20:59:48 +13:00
-> param ( 'data' , null , new JSON (), 'Additional Data for push notification.' , true )
-> param ( 'action' , '' , new Text ( 256 ), 'Action for push notification.' , true )
2024-02-20 18:25:57 +13:00
-> param ( 'image' , '' , new CompoundUID (), 'Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage.' , true )
2023-10-20 20:58:23 +13:00
-> param ( 'icon' , '' , new Text ( 256 ), 'Icon for push notification. Available only for Android and Web Platform.' , true )
-> param ( 'sound' , '' , new Text ( 256 ), 'Sound for push notification. Available only for Android and IOS Platform.' , true )
-> param ( 'color' , '' , new Text ( 256 ), 'Color for push notification. Available only for Android Platform.' , true )
-> param ( 'tag' , '' , new Text ( 256 ), 'Tag for push notification. Available only for Android Platform.' , true )
-> param ( 'badge' , '' , new Text ( 256 ), 'Badge for push notification. Available only for IOS Platform.' , true )
2024-02-27 00:27:35 +13:00
-> param ( 'draft' , false , new Boolean (), 'Is message a draft' , true )
2023-11-29 17:08:25 +13:00
-> param ( 'scheduledAt' , null , new DatetimeValidator ( requireDateInFuture : true ), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-19 20:59:48 +13:00
-> inject ( 'dbForProject' )
2023-12-07 23:25:19 +13:00
-> inject ( 'dbForConsole' )
2023-10-19 20:59:48 +13:00
-> inject ( 'project' )
2023-10-20 22:30:22 +13:00
-> inject ( 'queueForMessaging' )
2023-10-19 20:59:48 +13:00
-> inject ( 'response' )
2024-02-26 23:52:32 +13:00
-> action ( function ( string $messageId , string $title , string $body , array $topics , array $users , array $targets , ? array $data , string $action , string $image , string $icon , string $sound , string $color , string $tag , string $badge , bool $draft , ? string $scheduledAt , Event $queueForEvents , Database $dbForProject , Database $dbForConsole , Document $project , Messaging $queueForMessaging , Response $response ) {
2023-12-15 03:19:24 +13:00
$messageId = $messageId == 'unique()'
? ID :: unique ()
: $messageId ;
2023-10-19 20:59:48 +13:00
2024-02-26 23:52:32 +13:00
if ( $draft ) {
$status = MessageStatus :: DRAFT ;
} else {
$status = \is_null ( $scheduledAt )
? MessageStatus :: PROCESSING
: MessageStatus :: SCHEDULED ;
}
2024-01-11 14:15:37 +13:00
if ( $status !== MessageStatus :: DRAFT && \count ( $topics ) === 0 && \count ( $users ) === 0 && \count ( $targets ) === 0 ) {
2023-10-31 07:07:57 +13:00
throw new Exception ( Exception :: MESSAGE_MISSING_TARGET );
}
2024-01-19 16:16:24 +13:00
if ( $status === MessageStatus :: SCHEDULED && \is_null ( $scheduledAt )) {
throw new Exception ( Exception :: MESSAGE_MISSING_SCHEDULE );
}
2024-01-11 14:15:37 +13:00
if ( ! empty ( $targets )) {
$foundTargets = $dbForProject -> find ( 'targets' , [
Query :: equal ( '$id' , $targets ),
Query :: equal ( 'providerType' , [ MESSAGE_TYPE_PUSH ]),
Query :: limit ( \count ( $targets )),
]);
2023-12-15 03:19:24 +13:00
2024-01-11 14:15:37 +13:00
if ( \count ( $foundTargets ) !== \count ( $targets )) {
throw new Exception ( Exception :: MESSAGE_TARGET_NOT_PUSH );
}
2023-12-01 11:09:43 +13:00
2024-01-11 14:15:37 +13:00
foreach ( $foundTargets as $target ) {
if ( $target -> isEmpty ()) {
throw new Exception ( Exception :: USER_TARGET_NOT_FOUND );
}
2023-12-01 11:09:43 +13:00
}
}
2024-02-15 22:36:34 +13:00
if ( ! empty ( $image )) {
2024-02-20 18:25:57 +13:00
[ $bucketId , $fileId ] = CompoundUID :: parse ( $image );
2024-02-15 22:36:34 +13:00
2024-02-20 18:25:57 +13:00
$bucket = $dbForProject -> getDocument ( 'buckets' , $bucketId );
if ( $bucket -> isEmpty ()) {
throw new Exception ( Exception :: STORAGE_BUCKET_NOT_FOUND );
2024-02-15 22:36:34 +13:00
}
2024-02-20 18:25:57 +13:00
$file = $dbForProject -> getDocument ( 'bucket_' . $bucket -> getInternalId (), $fileId );
if ( $file -> isEmpty ()) {
throw new Exception ( Exception :: STORAGE_BUCKET_NOT_FOUND );
}
2024-02-19 20:48:52 +13:00
2024-02-20 18:25:57 +13:00
if ( ! \in_array ( Permission :: read ( Role :: any ()), \array_merge ( $file -> getRead (), $bucket -> getRead ()))) {
2024-02-15 22:36:34 +13:00
throw new Exception ( Exception :: STORAGE_FILE_NOT_PUBLIC );
}
2024-02-20 18:25:57 +13:00
if ( ! \in_array ( $file -> getAttribute ( 'mimeType' ), [ 'image/png' , 'image/jpeg' ])) {
2024-02-15 22:36:34 +13:00
throw new Exception ( Exception :: STORAGE_FILE_TYPE_UNSUPPORTED );
}
$host = App :: getEnv ( '_APP_DOMAIN' , 'localhost' );
$domain = new Domain ( \parse_url ( $host , PHP_URL_HOST ));
$protocol = App :: getEnv ( '_APP_OPTIONS_FORCE_HTTPS' ) === 'disabled' ? 'http' : 'https' ;
if ( ! $domain -> isKnown ()) {
throw new Exception ( Exception :: STORAGE_FILE_NOT_PUBLIC );
}
2024-03-08 06:40:45 +13:00
$image = [
'bucketId' => $bucket -> getId (),
'fileId' => $file -> getId (),
'url' => " { $protocol } :// { $host } /v1/storage/buckets/ { $bucket -> getId () } /files/ { $file -> getId () } /view?project= { $project -> getId () } " ,
];
2024-02-15 22:36:34 +13:00
}
2023-11-29 17:09:44 +13:00
$pushData = [];
2023-10-19 20:59:48 +13:00
2024-02-15 22:36:34 +13:00
$keys = [ 'title' , 'body' , 'data' , 'action' , 'image' , 'icon' , 'sound' , 'color' , 'tag' , 'badge' ];
2023-10-19 20:59:48 +13:00
2023-11-29 17:09:44 +13:00
foreach ( $keys as $key ) {
if ( ! empty ( $$key )) {
$pushData [ $key ] = $$key ;
}
2023-10-19 20:59:48 +13:00
}
$message = $dbForProject -> createDocument ( 'messages' , new Document ([
'$id' => $messageId ,
2023-11-29 17:09:44 +13:00
'providerType' => MESSAGE_TYPE_PUSH ,
2023-10-31 07:07:57 +13:00
'topics' => $topics ,
'users' => $users ,
'targets' => $targets ,
2023-11-29 17:08:25 +13:00
'scheduledAt' => $scheduledAt ,
2023-10-19 20:59:48 +13:00
'data' => $pushData ,
'status' => $status ,
2023-08-24 21:01:22 +12:00
]));
2024-01-19 16:15:54 +13:00
switch ( $status ) {
case MessageStatus :: PROCESSING :
$queueForMessaging
2024-02-21 01:06:35 +13:00
-> setType ( MESSAGE_SEND_TYPE_EXTERNAL )
-> setMessageId ( $message -> getId ());
2024-01-19 16:15:54 +13:00
break ;
case MessageStatus :: SCHEDULED :
$schedule = $dbForConsole -> createDocument ( 'schedules' , new Document ([
'region' => App :: getEnv ( '_APP_REGION' , 'default' ),
'resourceType' => 'message' ,
'resourceId' => $message -> getId (),
'resourceInternalId' => $message -> getInternalId (),
'resourceUpdatedAt' => DateTime :: now (),
'projectId' => $project -> getId (),
'schedule' => $scheduledAt ,
'active' => true ,
]));
$message -> setAttribute ( 'scheduleId' , $schedule -> getId ());
$dbForProject -> updateDocument (
'messages' ,
$message -> getId (),
$message
);
break ;
default :
break ;
2023-10-07 02:53:46 +13:00
}
2023-08-24 21:01:22 +12:00
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'messageId' , $message -> getId ());
2023-08-24 21:01:22 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
2023-09-06 23:00:46 +12:00
-> dynamic ( $message , Response :: MODEL_MESSAGE );
2023-08-24 21:01:22 +12:00
});
2023-10-04 23:45:59 +13:00
2023-10-07 02:53:46 +13:00
App :: get ( '/v1/messaging/messages' )
2023-10-26 06:33:23 +13:00
-> desc ( 'List messages' )
2023-10-07 02:53:46 +13:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'messages.read' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listMessages' )
-> label ( 'sdk.description' , '/docs/references/messaging/list-messages.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_MESSAGE_LIST )
2024-01-03 11:58:30 +13:00
-> param ( 'queries' , [], new Messages (), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode ( ', ' , Messages :: ALLOWED_ATTRIBUTES ), true )
2023-10-26 06:33:23 +13:00
-> param ( 'search' , '' , new Text ( 256 ), 'Search term to filter your list results. Max length: 256 chars.' , true )
2023-10-07 02:53:46 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-10-26 06:33:23 +13:00
-> action ( function ( array $queries , string $search , Database $dbForProject , Response $response ) {
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2023-10-07 02:53:46 +13:00
2023-10-26 06:33:23 +13:00
if ( ! empty ( $search )) {
$queries [] = Query :: search ( 'search' , $search );
}
2024-02-12 22:55:45 +13:00
/**
2024-02-12 23:03:31 +13:00
* Get cursor document if there was a cursor query , we use array_filter and reset for reference $cursor to $queries
2024-02-12 22:55:45 +13:00
*/
$cursor = \array_filter ( $queries , function ( $query ) {
return \in_array ( $query -> getMethod (), [ Query :: TYPE_CURSOR_AFTER , Query :: TYPE_CURSOR_BEFORE ]);
});
2023-10-07 02:53:46 +13:00
$cursor = reset ( $cursor );
if ( $cursor ) {
$messageId = $cursor -> getValue ();
2023-10-18 06:23:26 +13:00
$cursorDocument = Authorization :: skip ( fn () => $dbForProject -> getDocument ( 'messages' , $messageId ));
2023-10-07 02:53:46 +13:00
2023-10-18 06:23:26 +13:00
if ( $cursorDocument -> isEmpty ()) {
2023-10-07 02:53:46 +13:00
throw new Exception ( Exception :: GENERAL_CURSOR_NOT_FOUND , " Message ' { $messageId } ' for the 'cursor' value not found. " );
}
$cursor -> setValue ( $cursorDocument );
}
$response -> dynamic ( new Document ([
'messages' => $dbForProject -> find ( 'messages' , $queries ),
2023-10-26 06:33:23 +13:00
'total' => $dbForProject -> count ( 'messages' , $queries , APP_LIMIT_COUNT ),
2023-10-07 02:53:46 +13:00
]), Response :: MODEL_MESSAGE_LIST );
});
2023-11-03 01:30:17 +13:00
App :: get ( '/v1/messaging/messages/:messageId/logs' )
-> desc ( 'List message logs' )
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'messages.read' )
2023-11-10 09:50:55 +13:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
2023-11-03 01:30:17 +13:00
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listMessageLogs' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/list-message-logs.md' )
2023-11-03 01:30:17 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_LOG_LIST )
-> param ( 'messageId' , '' , new UID (), 'Message ID.' )
-> param ( 'queries' , [], new Queries ([ new Limit (), new Offset ()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset' , true )
-> inject ( 'response' )
-> inject ( 'dbForProject' )
-> inject ( 'locale' )
-> inject ( 'geodb' )
-> action ( function ( string $messageId , array $queries , Response $response , Database $dbForProject , Locale $locale , Reader $geodb ) {
$message = $dbForProject -> getDocument ( 'messages' , $messageId );
if ( $message -> isEmpty ()) {
throw new Exception ( Exception :: MESSAGE_NOT_FOUND );
}
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2023-11-03 01:30:17 +13:00
$grouped = Query :: groupByType ( $queries );
$limit = $grouped [ 'limit' ] ? ? APP_LIMIT_COUNT ;
$offset = $grouped [ 'offset' ] ? ? 0 ;
$audit = new Audit ( $dbForProject );
$resource = 'message/' . $messageId ;
$logs = $audit -> getLogsByResource ( $resource , $limit , $offset );
$output = [];
foreach ( $logs as $i => & $log ) {
$log [ 'userAgent' ] = ( ! empty ( $log [ 'userAgent' ])) ? $log [ 'userAgent' ] : 'UNKNOWN' ;
$detector = new Detector ( $log [ 'userAgent' ]);
$detector -> skipBotDetection (); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector -> getOS ();
$client = $detector -> getClient ();
$device = $detector -> getDevice ();
$output [ $i ] = new Document ([
'event' => $log [ 'event' ],
'userId' => ID :: custom ( $log [ 'data' ][ 'userId' ]),
'userEmail' => $log [ 'data' ][ 'userEmail' ] ? ? null ,
'userName' => $log [ 'data' ][ 'userName' ] ? ? null ,
'mode' => $log [ 'data' ][ 'mode' ] ? ? null ,
'ip' => $log [ 'ip' ],
'time' => $log [ 'time' ],
'osCode' => $os [ 'osCode' ],
'osName' => $os [ 'osName' ],
'osVersion' => $os [ 'osVersion' ],
'clientType' => $client [ 'clientType' ],
'clientCode' => $client [ 'clientCode' ],
'clientName' => $client [ 'clientName' ],
'clientVersion' => $client [ 'clientVersion' ],
'clientEngine' => $client [ 'clientEngine' ],
'clientEngineVersion' => $client [ 'clientEngineVersion' ],
'deviceName' => $device [ 'deviceName' ],
'deviceBrand' => $device [ 'deviceBrand' ],
'deviceModel' => $device [ 'deviceModel' ]
]);
$record = $geodb -> get ( $log [ 'ip' ]);
if ( $record ) {
$output [ $i ][ 'countryCode' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), false ) ? \strtolower ( $record [ 'country' ][ 'iso_code' ]) : '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), $locale -> getText ( 'locale.country.unknown' ));
} else {
$output [ $i ][ 'countryCode' ] = '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'locale.country.unknown' );
}
}
$response -> dynamic ( new Document ([
'total' => $audit -> countLogsByResource ( $resource ),
'logs' => $output ,
]), Response :: MODEL_LOG_LIST );
});
2024-01-18 14:33:32 +13:00
App :: get ( '/v1/messaging/messages/:messageId/targets' )
-> desc ( 'List message targets' )
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'messages.read' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'listTargets' )
-> label ( 'sdk.description' , '/docs/references/messaging/list-message-targets.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_TARGET_LIST )
-> param ( 'messageId' , '' , new UID (), 'Message ID.' )
-> param ( 'queries' , [], new Targets (), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode ( ', ' , Targets :: ALLOWED_ATTRIBUTES ), true )
-> inject ( 'response' )
-> inject ( 'dbForProject' )
2024-02-13 02:27:19 +13:00
-> action ( function ( string $messageId , array $queries , Response $response , Database $dbForProject ) {
2024-01-18 14:33:32 +13:00
$message = $dbForProject -> getDocument ( 'messages' , $messageId );
if ( $message -> isEmpty ()) {
throw new Exception ( Exception :: MESSAGE_NOT_FOUND );
}
$targetIDs = $message -> getAttribute ( 'targets' );
if ( empty ( $targetIDs )) {
$response -> dynamic ( new Document ([
'targets' => [],
'total' => 0 ,
]), Response :: MODEL_TARGET_LIST );
return ;
}
2024-02-13 05:02:04 +13:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2024-01-18 14:33:32 +13:00
$queries [] = Query :: equal ( '$id' , $targetIDs );
2024-02-12 22:55:45 +13:00
/**
2024-02-12 23:03:31 +13:00
* Get cursor document if there was a cursor query , we use array_filter and reset for reference $cursor to $queries
2024-02-12 22:55:45 +13:00
*/
$cursor = \array_filter ( $queries , function ( $query ) {
return \in_array ( $query -> getMethod (), [ Query :: TYPE_CURSOR_AFTER , Query :: TYPE_CURSOR_BEFORE ]);
});
2024-01-18 14:33:32 +13:00
$cursor = reset ( $cursor );
if ( $cursor ) {
$targetId = $cursor -> getValue ();
$cursorDocument = $dbForProject -> getDocument ( 'targets' , $targetId );
if ( $cursorDocument -> isEmpty ()) {
throw new Exception ( Exception :: GENERAL_CURSOR_NOT_FOUND , " Target ' { $targetId } ' for the 'cursor' value not found. " );
}
$cursor -> setValue ( $cursorDocument );
}
$response -> dynamic ( new Document ([
'targets' => $dbForProject -> find ( 'targets' , $queries ),
'total' => $dbForProject -> count ( 'targets' , $queries , APP_LIMIT_COUNT ),
]), Response :: MODEL_TARGET_LIST );
});
2023-10-06 11:00:47 +13:00
App :: get ( '/v1/messaging/messages/:messageId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Get message' )
2023-10-04 23:45:59 +13:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'scope' , 'messages.read' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'getMessage' )
-> label ( 'sdk.description' , '/docs/references/messaging/get-message.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_MESSAGE )
2023-10-06 11:00:47 +13:00
-> param ( 'messageId' , '' , new UID (), 'Message ID.' )
2023-10-04 23:45:59 +13:00
-> inject ( 'dbForProject' )
-> inject ( 'response' )
2023-10-06 11:00:47 +13:00
-> action ( function ( string $messageId , Database $dbForProject , Response $response ) {
$message = $dbForProject -> getDocument ( 'messages' , $messageId );
2023-10-04 23:45:59 +13:00
if ( $message -> isEmpty ()) {
throw new Exception ( Exception :: MESSAGE_NOT_FOUND );
}
$response -> dynamic ( $message , Response :: MODEL_MESSAGE );
});
2023-10-07 02:53:46 +13:00
2023-10-12 19:18:26 +13:00
App :: patch ( '/v1/messaging/messages/email/:messageId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Update email' )
2023-10-07 02:53:46 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'message.update' )
-> label ( 'audits.resource' , 'message/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'messages.[messageId].update' )
2023-10-07 02:53:46 +13:00
-> label ( 'scope' , 'messages.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'updateEmail' )
-> label ( 'sdk.description' , '/docs/references/messaging/update-email.md' )
2023-10-19 20:59:48 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
2023-10-07 02:53:46 +13:00
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_MESSAGE )
-> param ( 'messageId' , '' , new UID (), 'Message ID.' )
2024-01-05 13:10:57 +13:00
-> param ( 'topics' , null , new ArrayList ( new UID ()), 'List of Topic IDs.' , true )
-> param ( 'users' , null , new ArrayList ( new UID ()), 'List of User IDs.' , true )
-> param ( 'targets' , null , new ArrayList ( new UID ()), 'List of Targets IDs.' , true )
2023-12-15 03:45:51 +13:00
-> param ( 'subject' , null , new Text ( 998 ), 'Email Subject.' , true )
-> param ( 'content' , null , new Text ( 64230 ), 'Email Content.' , true )
2024-02-26 23:52:32 +13:00
-> param ( 'draft' , null , new Boolean (), 'Is message a draft' , true )
2023-12-15 03:45:51 +13:00
-> param ( 'html' , null , new Boolean (), 'Is content of type HTML' , true )
-> param ( 'cc' , null , new ArrayList ( new UID ()), 'Array of target IDs to be added as CC.' , true )
-> param ( 'bcc' , null , new ArrayList ( new UID ()), 'Array of target IDs to be added as BCC.' , true )
2023-11-29 17:08:25 +13:00
-> param ( 'scheduledAt' , null , new DatetimeValidator ( requireDateInFuture : true ), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-07 02:53:46 +13:00
-> inject ( 'dbForProject' )
2023-12-07 23:25:19 +13:00
-> inject ( 'dbForConsole' )
2023-10-07 02:53:46 +13:00
-> inject ( 'project' )
2023-10-20 22:25:17 +13:00
-> inject ( 'queueForMessaging' )
2023-10-07 02:53:46 +13:00
-> inject ( 'response' )
2024-02-26 23:52:32 +13:00
-> action ( function ( string $messageId , ? array $topics , ? array $users , ? array $targets , ? string $subject , ? string $content , ? bool $draft , ? bool $html , ? array $cc , ? array $bcc , ? string $scheduledAt , Event $queueForEvents , Database $dbForProject , Database $dbForConsole , Document $project , Messaging $queueForMessaging , Response $response ) {
2023-10-07 02:53:46 +13:00
$message = $dbForProject -> getDocument ( 'messages' , $messageId );
if ( $message -> isEmpty ()) {
throw new Exception ( Exception :: MESSAGE_NOT_FOUND );
}
2024-02-26 23:52:32 +13:00
if ( ! \is_null ( $draft ) || ! \is_null ( $scheduledAt )) {
if ( $draft ) {
$status = MessageStatus :: DRAFT ;
} else {
$status = \is_null ( $scheduledAt )
? MessageStatus :: PROCESSING
: MessageStatus :: SCHEDULED ;
}
} else {
$status = null ;
}
2024-02-26 23:37:12 +13:00
if (
$status !== MessageStatus :: DRAFT
&& \count ( $topics ? ? $message -> getAttribute ( 'topics' , [])) === 0
&& \count ( $users ? ? $message -> getAttribute ( 'users' , [])) === 0
&& \count ( $targets ? ? $message -> getAttribute ( 'targets' , [])) === 0
) {
2024-02-26 17:14:59 +13:00
throw new Exception ( Exception :: MESSAGE_MISSING_TARGET );
}
$currentScheduledAt = $message -> getAttribute ( 'scheduledAt' );
2024-02-12 16:55:00 +13:00
switch ( $message -> getAttribute ( 'status' )) {
case MessageStatus :: PROCESSING :
throw new Exception ( Exception :: MESSAGE_ALREADY_PROCESSING );
case MessageStatus :: SENT :
throw new Exception ( Exception :: MESSAGE_ALREADY_SENT );
case MessageStatus :: FAILED :
throw new Exception ( Exception :: MESSAGE_ALREADY_FAILED );
2023-10-14 02:05:49 +13:00
}
2024-02-26 23:37:12 +13:00
if (
$status === MessageStatus :: SCHEDULED
&& \is_null ( $scheduledAt )
&& \is_null ( $currentScheduledAt )
) {
throw new Exception ( Exception :: MESSAGE_MISSING_SCHEDULE );
}
if ( ! \is_null ( $currentScheduledAt ) && new \DateTime ( $currentScheduledAt ) < new \DateTime ()) {
2023-10-20 20:58:23 +13:00
throw new Exception ( Exception :: MESSAGE_ALREADY_SCHEDULED );
}
2024-02-26 23:37:12 +13:00
if ( \is_null ( $currentScheduledAt ) && ! \is_null ( $scheduledAt )) {
2024-02-26 17:14:59 +13:00
$schedule = $dbForConsole -> createDocument ( 'schedules' , new Document ([
'region' => App :: getEnv ( '_APP_REGION' , 'default' ),
'resourceType' => 'message' ,
'resourceId' => $message -> getId (),
'resourceInternalId' => $message -> getInternalId (),
'resourceUpdatedAt' => DateTime :: now (),
'projectId' => $project -> getId (),
'schedule' => $scheduledAt ,
'active' => $status === MessageStatus :: SCHEDULED ,
]));
$message -> setAttribute ( 'scheduleId' , $schedule -> getId ());
}
if ( ! \is_null ( $currentScheduledAt )) {
$schedule = $dbForConsole -> getDocument ( 'schedules' , $message -> getAttribute ( 'scheduleId' ));
2024-02-26 23:37:12 +13:00
$scheduledStatus = ( $status ? ? $message -> getAttribute ( 'status' )) === MessageStatus :: SCHEDULED ;
2024-02-26 17:14:59 +13:00
if ( $schedule -> isEmpty ()) {
throw new Exception ( Exception :: SCHEDULE_NOT_FOUND );
}
2024-02-26 23:37:12 +13:00
$schedule
-> setAttribute ( 'resourceUpdatedAt' , DateTime :: now ())
-> setAttribute ( 'active' , $scheduledStatus );
2024-02-26 17:14:59 +13:00
if ( ! \is_null ( $scheduledAt )) {
2024-02-26 23:37:12 +13:00
$schedule -> setAttribute ( 'schedule' , $scheduledAt );
2024-02-26 17:14:59 +13:00
}
$dbForConsole -> updateDocument ( 'schedules' , $schedule -> getId (), $schedule );
}
2024-02-26 18:46:26 +13:00
if ( ! \is_null ( $scheduledAt )) {
$message -> setAttribute ( 'scheduledAt' , $scheduledAt );
}
2023-11-03 00:13:24 +13:00
if ( ! \is_null ( $topics )) {
2023-10-31 07:07:57 +13:00
$message -> setAttribute ( 'topics' , $topics );
}
2023-11-03 00:13:24 +13:00
if ( ! \is_null ( $users )) {
2023-10-31 07:07:57 +13:00
$message -> setAttribute ( 'users' , $users );
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $targets )) {
$message -> setAttribute ( 'targets' , $targets );
}
2024-01-11 15:58:24 +13:00
$data = $message -> getAttribute ( 'data' );
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $subject )) {
2023-10-07 02:53:46 +13:00
$data [ 'subject' ] = $subject ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $content )) {
2023-10-07 02:53:46 +13:00
$data [ 'content' ] = $content ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $html )) {
2023-10-19 20:59:48 +13:00
$data [ 'html' ] = $html ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $cc )) {
2023-12-06 07:24:55 +13:00
$data [ 'cc' ] = $cc ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $bcc )) {
2023-12-06 07:24:55 +13:00
$data [ 'bcc' ] = $bcc ;
}
2023-10-19 20:59:48 +13:00
$message -> setAttribute ( 'data' , $data );
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $status )) {
2023-10-19 20:59:48 +13:00
$message -> setAttribute ( 'status' , $status );
}
$message = $dbForProject -> updateDocument ( 'messages' , $message -> getId (), $message );
2024-01-11 14:15:37 +13:00
if ( $status === MessageStatus :: PROCESSING ) {
2023-10-20 22:30:22 +13:00
$queueForMessaging
2024-02-21 01:06:35 +13:00
-> setType ( MESSAGE_SEND_TYPE_EXTERNAL )
-> setMessageId ( $message -> getId ());
2023-10-19 20:59:48 +13:00
}
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'messageId' , $message -> getId ());
2023-10-19 20:59:48 +13:00
$response
-> dynamic ( $message , Response :: MODEL_MESSAGE );
});
App :: patch ( '/v1/messaging/messages/sms/:messageId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Update SMS' )
2023-10-19 20:59:48 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'message.update' )
-> label ( 'audits.resource' , 'message/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'messages.[messageId].update' )
2023-10-19 20:59:48 +13:00
-> label ( 'scope' , 'messages.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.method' , 'updateSms' )
2023-10-19 20:59:48 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/update-email.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_MESSAGE )
-> param ( 'messageId' , '' , new UID (), 'Message ID.' )
2024-01-05 13:10:57 +13:00
-> param ( 'topics' , null , new ArrayList ( new UID ()), 'List of Topic IDs.' , true )
-> param ( 'users' , null , new ArrayList ( new UID ()), 'List of User IDs.' , true )
-> param ( 'targets' , null , new ArrayList ( new UID ()), 'List of Targets IDs.' , true )
2023-12-15 03:45:51 +13:00
-> param ( 'content' , null , new Text ( 64230 ), 'Email Content.' , true )
2024-02-27 00:27:35 +13:00
-> param ( 'draft' , null , new Boolean (), 'Is message a draft' , true )
2023-11-29 17:08:25 +13:00
-> param ( 'scheduledAt' , null , new DatetimeValidator ( requireDateInFuture : true ), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-19 20:59:48 +13:00
-> inject ( 'dbForProject' )
2023-12-07 23:25:19 +13:00
-> inject ( 'dbForConsole' )
2023-10-19 20:59:48 +13:00
-> inject ( 'project' )
2023-10-20 22:30:22 +13:00
-> inject ( 'queueForMessaging' )
2023-10-19 20:59:48 +13:00
-> inject ( 'response' )
2024-02-26 23:52:32 +13:00
-> action ( function ( string $messageId , ? array $topics , ? array $users , ? array $targets , ? string $content , ? bool $draft , ? string $scheduledAt , Event $queueForEvents , Database $dbForProject , Database $dbForConsole , Document $project , Messaging $queueForMessaging , Response $response ) {
2023-10-19 20:59:48 +13:00
$message = $dbForProject -> getDocument ( 'messages' , $messageId );
if ( $message -> isEmpty ()) {
throw new Exception ( Exception :: MESSAGE_NOT_FOUND );
}
2024-02-26 23:52:32 +13:00
if ( ! \is_null ( $draft ) || ! \is_null ( $scheduledAt )) {
if ( $draft ) {
$status = MessageStatus :: DRAFT ;
} else {
$status = \is_null ( $scheduledAt )
? MessageStatus :: PROCESSING
: MessageStatus :: SCHEDULED ;
}
} else {
$status = null ;
}
2024-02-26 23:37:12 +13:00
if (
$status !== MessageStatus :: DRAFT
&& \count ( $topics ? ? $message -> getAttribute ( 'topics' , [])) === 0
&& \count ( $users ? ? $message -> getAttribute ( 'users' , [])) === 0
&& \count ( $targets ? ? $message -> getAttribute ( 'targets' , [])) === 0
) {
2024-02-26 17:14:59 +13:00
throw new Exception ( Exception :: MESSAGE_MISSING_TARGET );
}
$currentScheduledAt = $message -> getAttribute ( 'scheduledAt' );
2024-02-12 16:55:00 +13:00
switch ( $message -> getAttribute ( 'status' )) {
case MessageStatus :: PROCESSING :
throw new Exception ( Exception :: MESSAGE_ALREADY_PROCESSING );
case MessageStatus :: SENT :
throw new Exception ( Exception :: MESSAGE_ALREADY_SENT );
case MessageStatus :: FAILED :
throw new Exception ( Exception :: MESSAGE_ALREADY_FAILED );
2023-10-19 20:59:48 +13:00
}
2024-02-26 23:37:12 +13:00
if (
$status === MessageStatus :: SCHEDULED
&& \is_null ( $scheduledAt )
&& \is_null ( $currentScheduledAt )
) {
throw new Exception ( Exception :: MESSAGE_MISSING_SCHEDULE );
}
if ( ! \is_null ( $currentScheduledAt ) && new \DateTime ( $currentScheduledAt ) < new \DateTime ()) {
2023-10-20 20:58:23 +13:00
throw new Exception ( Exception :: MESSAGE_ALREADY_SCHEDULED );
}
2024-02-26 23:37:12 +13:00
if ( \is_null ( $currentScheduledAt ) && ! \is_null ( $scheduledAt )) {
2024-02-26 17:14:59 +13:00
$schedule = $dbForConsole -> createDocument ( 'schedules' , new Document ([
'region' => App :: getEnv ( '_APP_REGION' , 'default' ),
'resourceType' => 'message' ,
'resourceId' => $message -> getId (),
'resourceInternalId' => $message -> getInternalId (),
'resourceUpdatedAt' => DateTime :: now (),
'projectId' => $project -> getId (),
'schedule' => $scheduledAt ,
'active' => $status === MessageStatus :: SCHEDULED ,
]));
$message -> setAttribute ( 'scheduleId' , $schedule -> getId ());
}
if ( ! \is_null ( $currentScheduledAt )) {
$schedule = $dbForConsole -> getDocument ( 'schedules' , $message -> getAttribute ( 'scheduleId' ));
2024-02-26 23:37:12 +13:00
$scheduledStatus = ( $status ? ? $message -> getAttribute ( 'status' )) === MessageStatus :: SCHEDULED ;
2024-02-26 17:14:59 +13:00
if ( $schedule -> isEmpty ()) {
throw new Exception ( Exception :: SCHEDULE_NOT_FOUND );
}
2024-02-26 23:37:12 +13:00
$schedule
-> setAttribute ( 'resourceUpdatedAt' , DateTime :: now ())
-> setAttribute ( 'active' , $scheduledStatus );
2024-02-26 17:14:59 +13:00
if ( ! \is_null ( $scheduledAt )) {
2024-02-26 23:37:12 +13:00
$schedule -> setAttribute ( 'schedule' , $scheduledAt );
2024-02-26 17:14:59 +13:00
}
$dbForConsole -> updateDocument ( 'schedules' , $schedule -> getId (), $schedule );
}
2024-02-26 18:46:26 +13:00
if ( ! \is_null ( $scheduledAt )) {
$message -> setAttribute ( 'scheduledAt' , $scheduledAt );
}
2023-11-03 00:13:24 +13:00
if ( ! \is_null ( $topics )) {
2023-10-31 07:07:57 +13:00
$message -> setAttribute ( 'topics' , $topics );
}
2023-11-03 00:13:24 +13:00
if ( ! \is_null ( $users )) {
2023-10-31 07:07:57 +13:00
$message -> setAttribute ( 'users' , $users );
}
2023-11-03 00:13:24 +13:00
if ( ! \is_null ( $targets )) {
2023-10-31 07:07:57 +13:00
$message -> setAttribute ( 'targets' , $targets );
2023-10-19 20:59:48 +13:00
}
$data = $message -> getAttribute ( 'data' );
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $content )) {
2023-10-19 20:59:48 +13:00
$data [ 'content' ] = $content ;
2023-10-07 02:53:46 +13:00
}
$message -> setAttribute ( 'data' , $data );
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $status )) {
2023-10-07 02:53:46 +13:00
$message -> setAttribute ( 'status' , $status );
}
2023-10-19 20:59:48 +13:00
$message = $dbForProject -> updateDocument ( 'messages' , $message -> getId (), $message );
2024-02-12 16:55:34 +13:00
if ( $status === MessageStatus :: PROCESSING ) {
2023-10-20 22:30:22 +13:00
$queueForMessaging
2024-02-21 01:06:35 +13:00
-> setType ( MESSAGE_SEND_TYPE_EXTERNAL )
-> setMessageId ( $message -> getId ());
2023-10-19 20:59:48 +13:00
}
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'messageId' , $message -> getId ());
2023-10-19 20:59:48 +13:00
$response
-> dynamic ( $message , Response :: MODEL_MESSAGE );
});
App :: patch ( '/v1/messaging/messages/push/:messageId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Update push notification' )
2023-10-19 20:59:48 +13:00
-> groups ([ 'api' , 'messaging' ])
2023-10-26 21:16:45 +13:00
-> label ( 'audits.event' , 'message.update' )
-> label ( 'audits.resource' , 'message/{response.$id}' )
2023-11-01 07:23:46 +13:00
-> label ( 'event' , 'messages.[messageId].update' )
2023-10-19 20:59:48 +13:00
-> label ( 'scope' , 'messages.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
2024-02-05 20:25:34 +13:00
-> label ( 'sdk.method' , 'updatePush' )
2024-02-21 22:04:27 +13:00
-> label ( 'sdk.description' , '/docs/references/messaging/update-push.md' )
2023-10-19 20:59:48 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_MESSAGE )
-> param ( 'messageId' , '' , new UID (), 'Message ID.' )
2024-01-05 13:10:57 +13:00
-> param ( 'topics' , null , new ArrayList ( new UID ()), 'List of Topic IDs.' , true )
-> param ( 'users' , null , new ArrayList ( new UID ()), 'List of User IDs.' , true )
-> param ( 'targets' , null , new ArrayList ( new UID ()), 'List of Targets IDs.' , true )
2023-12-15 03:45:51 +13:00
-> param ( 'title' , null , new Text ( 256 ), 'Title for push notification.' , true )
-> param ( 'body' , null , new Text ( 64230 ), 'Body for push notification.' , true )
2023-10-19 20:59:48 +13:00
-> param ( 'data' , null , new JSON (), 'Additional Data for push notification.' , true )
2023-12-15 03:45:51 +13:00
-> param ( 'action' , null , new Text ( 256 ), 'Action for push notification.' , true )
2024-02-21 17:07:52 +13:00
-> param ( 'image' , null , new CompoundUID (), 'Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage.' , true )
2023-12-15 03:45:51 +13:00
-> param ( 'icon' , null , new Text ( 256 ), 'Icon for push notification. Available only for Android and Web platforms.' , true )
-> param ( 'sound' , null , new Text ( 256 ), 'Sound for push notification. Available only for Android and iOS platforms.' , true )
-> param ( 'color' , null , new Text ( 256 ), 'Color for push notification. Available only for Android platforms.' , true )
-> param ( 'tag' , null , new Text ( 256 ), 'Tag for push notification. Available only for Android platforms.' , true )
-> param ( 'badge' , null , new Integer (), 'Badge for push notification. Available only for iOS platforms.' , true )
2024-02-27 00:27:35 +13:00
-> param ( 'draft' , null , new Boolean (), 'Is message a draft' , true )
2023-11-29 17:08:25 +13:00
-> param ( 'scheduledAt' , null , new DatetimeValidator ( requireDateInFuture : true ), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.' , true )
2023-11-01 07:23:46 +13:00
-> inject ( 'queueForEvents' )
2023-10-19 20:59:48 +13:00
-> inject ( 'dbForProject' )
2023-12-07 23:25:19 +13:00
-> inject ( 'dbForConsole' )
2023-10-19 20:59:48 +13:00
-> inject ( 'project' )
2023-10-20 22:30:22 +13:00
-> inject ( 'queueForMessaging' )
2023-10-19 20:59:48 +13:00
-> inject ( 'response' )
2024-02-26 23:52:32 +13:00
-> action ( function ( string $messageId , ? array $topics , ? array $users , ? array $targets , ? string $title , ? string $body , ? array $data , ? string $action , ? string $image , ? string $icon , ? string $sound , ? string $color , ? string $tag , ? int $badge , ? bool $draft , ? string $scheduledAt , Event $queueForEvents , Database $dbForProject , Database $dbForConsole , Document $project , Messaging $queueForMessaging , Response $response ) {
2023-10-19 20:59:48 +13:00
$message = $dbForProject -> getDocument ( 'messages' , $messageId );
if ( $message -> isEmpty ()) {
throw new Exception ( Exception :: MESSAGE_NOT_FOUND );
}
2024-02-26 23:52:32 +13:00
if ( ! \is_null ( $draft ) || ! \is_null ( $scheduledAt )) {
if ( $draft ) {
$status = MessageStatus :: DRAFT ;
} else {
$status = \is_null ( $scheduledAt )
? MessageStatus :: PROCESSING
: MessageStatus :: SCHEDULED ;
}
} else {
$status = null ;
}
2024-02-26 23:37:12 +13:00
if (
$status !== MessageStatus :: DRAFT
&& \count ( $topics ? ? $message -> getAttribute ( 'topics' , [])) === 0
&& \count ( $users ? ? $message -> getAttribute ( 'users' , [])) === 0
&& \count ( $targets ? ? $message -> getAttribute ( 'targets' , [])) === 0
) {
throw new Exception ( Exception :: MESSAGE_MISSING_TARGET );
}
$currentScheduledAt = $message -> getAttribute ( 'scheduledAt' );
2024-02-12 16:55:00 +13:00
switch ( $message -> getAttribute ( 'status' )) {
case MessageStatus :: PROCESSING :
throw new Exception ( Exception :: MESSAGE_ALREADY_PROCESSING );
case MessageStatus :: SENT :
throw new Exception ( Exception :: MESSAGE_ALREADY_SENT );
case MessageStatus :: FAILED :
throw new Exception ( Exception :: MESSAGE_ALREADY_FAILED );
2023-10-19 20:59:48 +13:00
}
2024-02-26 23:37:12 +13:00
if (
$status === MessageStatus :: SCHEDULED
&& \is_null ( $scheduledAt )
&& \is_null ( $currentScheduledAt )
) {
throw new Exception ( Exception :: MESSAGE_MISSING_SCHEDULE );
2024-02-26 17:14:59 +13:00
}
2024-02-26 23:37:12 +13:00
if ( ! \is_null ( $currentScheduledAt ) && new \DateTime ( $currentScheduledAt ) < new \DateTime ()) {
2023-10-20 20:58:23 +13:00
throw new Exception ( Exception :: MESSAGE_ALREADY_SCHEDULED );
}
2024-02-26 23:37:12 +13:00
if ( \is_null ( $currentScheduledAt ) && ! \is_null ( $scheduledAt )) {
2024-02-26 17:14:59 +13:00
$schedule = $dbForConsole -> createDocument ( 'schedules' , new Document ([
'region' => App :: getEnv ( '_APP_REGION' , 'default' ),
'resourceType' => 'message' ,
'resourceId' => $message -> getId (),
'resourceInternalId' => $message -> getInternalId (),
'resourceUpdatedAt' => DateTime :: now (),
'projectId' => $project -> getId (),
'schedule' => $scheduledAt ,
'active' => $status === MessageStatus :: SCHEDULED ,
]));
$message -> setAttribute ( 'scheduleId' , $schedule -> getId ());
}
if ( ! \is_null ( $currentScheduledAt )) {
$schedule = $dbForConsole -> getDocument ( 'schedules' , $message -> getAttribute ( 'scheduleId' ));
2024-02-26 23:37:12 +13:00
$scheduledStatus = ( $status ? ? $message -> getAttribute ( 'status' )) === MessageStatus :: SCHEDULED ;
2024-02-26 17:14:59 +13:00
if ( $schedule -> isEmpty ()) {
throw new Exception ( Exception :: SCHEDULE_NOT_FOUND );
}
2024-02-26 23:37:12 +13:00
$schedule
-> setAttribute ( 'resourceUpdatedAt' , DateTime :: now ())
-> setAttribute ( 'active' , $scheduledStatus );
2024-02-26 17:14:59 +13:00
if ( ! \is_null ( $scheduledAt )) {
2024-02-26 23:37:12 +13:00
$schedule -> setAttribute ( 'schedule' , $scheduledAt );
2024-02-26 17:14:59 +13:00
}
$dbForConsole -> updateDocument ( 'schedules' , $schedule -> getId (), $schedule );
}
2024-02-26 18:46:26 +13:00
if ( ! \is_null ( $scheduledAt )) {
$message -> setAttribute ( 'scheduledAt' , $scheduledAt );
}
2023-11-03 00:13:24 +13:00
if ( ! \is_null ( $topics )) {
2023-10-31 07:07:57 +13:00
$message -> setAttribute ( 'topics' , $topics );
}
2023-11-03 00:13:24 +13:00
if ( ! \is_null ( $users )) {
2023-10-31 07:07:57 +13:00
$message -> setAttribute ( 'users' , $users );
}
2023-11-03 00:13:24 +13:00
if ( ! \is_null ( $targets )) {
2023-10-31 07:07:57 +13:00
$message -> setAttribute ( 'targets' , $targets );
2023-10-19 20:59:48 +13:00
}
$pushData = $message -> getAttribute ( 'data' );
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $title )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'title' ] = $title ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $body )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'body' ] = $body ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $data )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'data' ] = $data ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $action )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'action' ] = $action ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $icon )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'icon' ] = $icon ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $sound )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'sound' ] = $sound ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $color )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'color' ] = $color ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $tag )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'tag' ] = $tag ;
}
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $badge )) {
2023-10-19 20:59:48 +13:00
$pushData [ 'badge' ] = $badge ;
}
2024-02-15 22:36:34 +13:00
if ( ! \is_null ( $image )) {
2024-02-21 17:07:52 +13:00
[ $bucketId , $fileId ] = CompoundUID :: parse ( $image );
2024-02-15 22:36:34 +13:00
2024-02-21 17:07:52 +13:00
$bucket = $dbForProject -> getDocument ( 'buckets' , $bucketId );
if ( $bucket -> isEmpty ()) {
throw new Exception ( Exception :: STORAGE_BUCKET_NOT_FOUND );
2024-02-15 22:36:34 +13:00
}
2024-02-21 17:07:52 +13:00
$file = $dbForProject -> getDocument ( 'bucket_' . $bucket -> getInternalId (), $fileId );
if ( $file -> isEmpty ()) {
throw new Exception ( Exception :: STORAGE_BUCKET_NOT_FOUND );
}
if ( ! \in_array ( Permission :: read ( Role :: any ()), \array_merge ( $file -> getRead (), $bucket -> getRead ()))) {
2024-02-15 22:36:34 +13:00
throw new Exception ( Exception :: STORAGE_FILE_NOT_PUBLIC );
}
2024-02-21 17:07:52 +13:00
if ( ! \in_array ( $file -> getAttribute ( 'mimeType' ), [ 'image/png' , 'image/jpeg' ])) {
2024-02-15 22:36:34 +13:00
throw new Exception ( Exception :: STORAGE_FILE_TYPE_UNSUPPORTED );
}
$host = App :: getEnv ( '_APP_DOMAIN' , 'localhost' );
$domain = new Domain ( \parse_url ( $host , PHP_URL_HOST ));
$protocol = App :: getEnv ( '_APP_OPTIONS_FORCE_HTTPS' ) === 'disabled' ? 'http' : 'https' ;
if ( ! $domain -> isKnown ()) {
throw new Exception ( Exception :: STORAGE_FILE_NOT_PUBLIC );
}
2024-03-08 06:40:45 +13:00
$pushData [ 'image' ] = [
'bucketId' => $bucket -> getId (),
'fileId' => $file -> getId (),
'url' => " { $protocol } :// { $host } /v1/storage/buckets/ { $bucket -> getId () } /files/ { $file -> getId () } /view?project= { $project -> getId () } "
];
2024-02-15 22:36:34 +13:00
}
2023-10-19 20:59:48 +13:00
$message -> setAttribute ( 'data' , $pushData );
2023-10-07 02:53:46 +13:00
2023-12-15 03:45:51 +13:00
if ( ! \is_null ( $status )) {
2023-10-07 02:53:46 +13:00
$message -> setAttribute ( 'status' , $status );
}
$message = $dbForProject -> updateDocument ( 'messages' , $message -> getId (), $message );
2024-02-12 16:55:34 +13:00
if ( $status === MessageStatus :: PROCESSING ) {
2023-10-20 22:25:17 +13:00
$queueForMessaging
2024-02-21 01:06:35 +13:00
-> setType ( MESSAGE_SEND_TYPE_EXTERNAL )
-> setMessageId ( $message -> getId ());
2023-10-07 02:53:46 +13:00
}
2023-11-01 07:23:46 +13:00
$queueForEvents
-> setParam ( 'messageId' , $message -> getId ());
2023-10-07 02:53:46 +13:00
$response
-> dynamic ( $message , Response :: MODEL_MESSAGE );
});
2024-01-29 17:20:45 +13:00
App :: delete ( '/v1/messaging/messages/:messageId' )
2024-02-26 15:25:45 +13:00
-> desc ( 'Delete message' )
2024-01-29 17:20:45 +13:00
-> groups ([ 'api' , 'messaging' ])
-> label ( 'audits.event' , 'message.delete' )
-> label ( 'audits.resource' , 'message/{request.route.messageId}' )
-> label ( 'event' , 'messages.[messageId].delete' )
-> label ( 'scope' , 'messages.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN , APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'messaging' )
-> label ( 'sdk.method' , 'delete' )
-> label ( 'sdk.description' , '/docs/references/messaging/delete-message.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_NOCONTENT )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_NONE )
-> param ( 'messageId' , '' , new UID (), 'Message ID.' )
-> inject ( 'dbForProject' )
-> inject ( 'dbForConsole' )
-> inject ( 'response' )
-> action ( function ( string $messageId , Database $dbForProject , Database $dbForConsole , Response $response ) {
$message = $dbForProject -> getDocument ( 'messages' , $messageId );
if ( $message -> isEmpty ()) {
throw new Exception ( Exception :: MESSAGE_NOT_FOUND );
}
switch ( $message -> getAttribute ( 'status' )) {
case MessageStatus :: PROCESSING :
throw new Exception ( Exception :: MESSAGE_ALREADY_SCHEDULED );
case MessageStatus :: SCHEDULED :
$scheduleId = $message -> getAttribute ( 'scheduleId' );
2024-01-30 16:33:18 +13:00
$scheduledAt = $message -> getAttribute ( 'scheduledAt' );
$now = DateTime :: now ();
$scheduledDate = DateTime :: formatTz ( $scheduledAt );
if ( $now > $scheduledDate ) {
throw new Exception ( Exception :: MESSAGE_ALREADY_SCHEDULED );
}
2024-01-29 17:20:45 +13:00
if ( ! empty ( $scheduleId )) {
try {
$dbForConsole -> deleteDocument ( 'schedules' , $scheduleId );
} catch ( Exception ) {
// Ignore
}
}
break ;
default :
break ;
}
$dbForProject -> deleteDocument ( 'messages' , $message -> getId ());
$response -> noContent ();
});