2019-12-14 19:33:29 +00:00
< ? php
2024-05-29 08:57:25 +00:00
use Ahc\Jwt\JWT ;
2024-02-11 14:51:19 +00:00
use Appwrite\Auth\Validator\MockNumber ;
2022-05-08 15:25:01 +00:00
use Appwrite\Event\Delete ;
2023-12-19 15:08:09 +00:00
use Appwrite\Event\Mail ;
2023-08-23 02:04:36 +00:00
use Appwrite\Extend\Exception ;
2025-04-14 11:56:42 +00:00
use Appwrite\Network\Platform ;
2025-01-17 04:31:39 +00:00
use Appwrite\SDK\AuthType ;
use Appwrite\SDK\ContentType ;
2025-08-20 14:08:27 +00:00
use Appwrite\SDK\Deprecated ;
2025-01-17 04:31:39 +00:00
use Appwrite\SDK\Method ;
use Appwrite\SDK\Response as SDKResponse ;
2023-08-23 02:04:36 +00:00
use Appwrite\Template\Template ;
2026-02-09 13:34:05 +00:00
use Appwrite\Utopia\Database\Validator\CustomId ;
2026-02-10 10:43:22 +00:00
use Appwrite\Utopia\Database\Validator\Queries\Keys ;
2020-08-14 21:56:50 +00:00
use Appwrite\Utopia\Response ;
2023-08-23 02:04:36 +00:00
use PHPMailer\PHPMailer\PHPMailer ;
2021-06-07 05:17:29 +00:00
use Utopia\Config\Config ;
2021-08-16 13:27:15 +00:00
use Utopia\Database\Database ;
2021-05-15 22:41:42 +00:00
use Utopia\Database\Document ;
2023-08-04 19:15:32 +00:00
use Utopia\Database\Exception\Duplicate ;
2026-02-09 15:58:44 +00:00
use Utopia\Database\Exception\Query as QueryException ;
2022-12-14 15:42:25 +00:00
use Utopia\Database\Helpers\ID ;
2022-12-14 16:04:06 +00:00
use Utopia\Database\Helpers\Permission ;
use Utopia\Database\Helpers\Role ;
2023-08-23 02:04:36 +00:00
use Utopia\Database\Query ;
2023-03-01 12:00:36 +00:00
use Utopia\Database\Validator\Datetime as DatetimeValidator ;
2026-02-09 15:58:44 +00:00
use Utopia\Database\Validator\Query\Cursor ;
2021-05-15 22:41:42 +00:00
use Utopia\Database\Validator\UID ;
2026-03-19 21:54:45 +00:00
use Utopia\Emails\Validator\Email ;
2026-02-10 05:04:24 +00:00
use Utopia\Http\Http ;
2024-03-08 12:57:20 +00:00
use Utopia\Locale\Locale ;
2024-04-01 11:08:46 +00:00
use Utopia\System\System ;
2024-10-08 07:54:40 +00:00
use Utopia\Validator\ArrayList ;
use Utopia\Validator\Boolean ;
use Utopia\Validator\Hostname ;
use Utopia\Validator\Integer ;
2025-11-10 04:45:49 +00:00
use Utopia\Validator\Nullable ;
2024-10-08 07:54:40 +00:00
use Utopia\Validator\Range ;
use Utopia\Validator\Text ;
use Utopia\Validator\WhiteList ;
2026-02-04 05:30:22 +00:00
Http :: init ()
2022-07-22 06:00:42 +00:00
-> groups ([ 'projects' ])
2022-08-02 01:10:48 +00:00
-> inject ( 'project' )
2022-07-22 06:00:42 +00:00
-> action ( function ( Document $project ) {
if ( $project -> getId () !== 'console' ) {
2022-08-08 14:03:01 +00:00
throw new Exception ( Exception :: GENERAL_ACCESS_FORBIDDEN );
2022-07-22 06:00:42 +00:00
}
});
2021-07-31 21:36:18 +00:00
2026-02-04 05:30:22 +00:00
Http :: get ( '/v1/projects/:projectId' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Get project' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2019-12-14 19:33:29 +00:00
-> label ( 'scope' , 'projects.read' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'projects' ,
2025-01-17 04:31:39 +00:00
name : 'get' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/get.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-14 19:33:29 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-14 19:33:29 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
2020-12-26 16:33:36 +00:00
});
2019-12-14 19:33:29 +00:00
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/service' )
2021-07-29 10:28:17 +00:00
-> desc ( 'Update service status' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'projects' ,
2025-01-17 04:31:39 +00:00
name : 'updateServiceStatus' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-service-status.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2024-06-07 00:54:51 +00:00
-> param ( 'service' , '' , new WhiteList ( array_keys ( array_filter ( Config :: getParam ( 'services' ), fn ( $element ) => $element [ 'optional' ])), true ), 'Service name.' )
2021-07-31 21:36:18 +00:00
-> param ( 'status' , null , new Boolean (), 'Service status.' )
2021-07-29 10:28:17 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $service , bool $status , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2021-07-29 10:28:17 +00:00
2021-07-29 10:56:25 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2021-07-29 10:28:17 +00:00
}
2021-07-31 20:54:50 +00:00
$services = $project -> getAttribute ( 'services' , []);
$services [ $service ] = $status ;
2021-07-29 10:28:17 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'services' , $services ));
2021-07-29 10:28:17 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/service/all' )
2023-04-05 02:33:38 +00:00
-> desc ( 'Update all service status' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'projects' ,
2025-01-17 04:31:39 +00:00
name : 'updateServiceStatusAll' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-service-status-all.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2023-04-05 02:33:38 +00:00
-> param ( 'status' , null , new Boolean (), 'Service status.' )
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , bool $status , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-04-05 02:33:38 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
2024-06-07 00:54:51 +00:00
$allServices = array_keys ( array_filter ( Config :: getParam ( 'services' ), fn ( $element ) => $element [ 'optional' ]));
2023-04-05 02:33:38 +00:00
$services = [];
2023-04-05 05:52:59 +00:00
foreach ( $allServices as $service ) {
2023-04-05 02:33:38 +00:00
$services [ $service ] = $status ;
}
2023-04-05 05:52:59 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'services' , $services ));
2023-04-05 02:33:38 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/api' )
2024-03-04 22:12:54 +00:00
-> desc ( 'Update API status' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-08-20 14:08:27 +00:00
-> label ( 'sdk' , [
new Method (
namespace : 'projects' ,
group : 'projects' ,
name : 'updateApiStatus' ,
description : '/docs/references/projects/update-api-status.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
],
deprecated : new Deprecated (
since : '1.8.0' ,
2025-08-23 09:36:02 +00:00
replaceWith : 'projects.updateAPIStatus' ,
2025-08-20 14:08:27 +00:00
),
2025-12-11 08:23:34 +00:00
public : false ,
2025-08-20 14:08:27 +00:00
),
new Method (
namespace : 'projects' ,
group : 'projects' ,
name : 'updateAPIStatus' ,
description : '/docs/references/projects/update-api-status.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
)
])
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2024-03-04 22:12:54 +00:00
-> param ( 'api' , '' , new WhiteList ( array_keys ( Config :: getParam ( 'apis' )), true ), 'API name.' )
-> param ( 'status' , null , new Boolean (), 'API status.' )
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $api , bool $status , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2024-03-04 22:12:54 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$apis = $project -> getAttribute ( 'apis' , []);
$apis [ $api ] = $status ;
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'apis' , $apis ));
2024-03-04 22:12:54 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/api/all' )
2024-03-04 22:28:42 +00:00
-> desc ( 'Update all API status' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-08-20 14:08:27 +00:00
-> label ( 'sdk' , [
new Method (
namespace : 'projects' ,
group : 'projects' ,
name : 'updateApiStatusAll' ,
description : '/docs/references/projects/update-api-status-all.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
],
deprecated : new Deprecated (
since : '1.8.0' ,
2025-08-23 09:36:02 +00:00
replaceWith : 'projects.updateAPIStatusAll' ,
2025-08-20 14:08:27 +00:00
),
2025-12-11 08:23:34 +00:00
public : false ,
2025-08-20 14:08:27 +00:00
),
new Method (
namespace : 'projects' ,
group : 'projects' ,
name : 'updateAPIStatusAll' ,
description : '/docs/references/projects/update-api-status-all.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
)
])
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2024-03-04 22:28:42 +00:00
-> param ( 'status' , null , new Boolean (), 'API status.' )
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , bool $status , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2024-03-04 22:28:42 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$allApis = array_keys ( Config :: getParam ( 'apis' ));
$apis = [];
foreach ( $allApis as $api ) {
$apis [ $api ] = $status ;
}
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'apis' , $apis ));
2024-03-04 22:28:42 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/oauth2' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Update project OAuth2' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2019-12-14 19:33:29 +00:00
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateOAuth2' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-oauth2.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2023-10-25 17:33:23 +00:00
-> param ( 'provider' , '' , new WhiteList ( \array_keys ( Config :: getParam ( 'oAuthProviders' )), true ), 'Provider Name' )
2025-11-10 04:45:49 +00:00
-> param ( 'appId' , null , new Nullable ( new Text ( 256 )), 'Provider app ID. Max length: 256 chars.' , true )
-> param ( 'secret' , null , new Nullable ( new text ( 512 )), 'Provider secret key. Max length: 512 chars.' , true )
-> param ( 'enabled' , null , new Nullable ( new Boolean ()), 'Provider status. Set to \'false\' to disable new session creation.' , true )
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $provider , ? string $appId , ? string $secret , ? bool $enabled , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-14 19:33:29 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-14 19:33:29 +00:00
2023-10-25 17:33:23 +00:00
$providers = $project -> getAttribute ( 'oAuthProviders' , []);
2022-08-19 09:21:51 +00:00
2022-08-19 09:43:03 +00:00
if ( $appId !== null ) {
2022-08-19 09:21:51 +00:00
$providers [ $provider . 'Appid' ] = $appId ;
}
2022-08-19 09:43:03 +00:00
if ( $secret !== null ) {
2022-08-19 09:21:51 +00:00
$providers [ $provider . 'Secret' ] = $secret ;
}
2022-08-19 09:43:03 +00:00
if ( $enabled !== null ) {
2022-08-19 09:21:51 +00:00
$providers [ $provider . 'Enabled' ] = $enabled ;
}
2021-08-06 10:35:50 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'oAuthProviders' , $providers ));
2020-06-30 15:46:42 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
2020-12-26 16:33:36 +00:00
});
2019-12-14 19:33:29 +00:00
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/session-alerts' )
2024-06-21 18:21:05 +00:00
-> desc ( 'Update project sessions emails' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateSessionAlerts' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-session-alerts.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2024-07-03 07:11:15 +00:00
-> param ( 'alerts' , false , new Boolean ( true ), 'Set to true to enable session emails.' )
2024-06-21 18:21:05 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , bool $alerts , Response $response , Database $dbForPlatform ) {
2024-06-21 18:21:05 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2024-06-21 18:21:05 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$auths = $project -> getAttribute ( 'auths' , []);
2024-07-03 07:11:15 +00:00
$auths [ 'sessionAlerts' ] = $alerts ;
2024-06-21 18:21:05 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2024-06-21 18:21:05 +00:00
-> setAttribute ( 'auths' , $auths ));
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/memberships-privacy' )
2024-11-07 14:33:44 +00:00
-> desc ( 'Update project memberships privacy attributes' )
2024-11-01 11:38:56 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateMembershipsPrivacy' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-memberships-privacy.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2024-11-06 20:15:31 +00:00
-> param ( 'userName' , true , new Boolean ( true ), 'Set to true to show userName to members of a team.' )
-> param ( 'userEmail' , true , new Boolean ( true ), 'Set to true to show email to members of a team.' )
-> param ( 'mfa' , true , new Boolean ( true ), 'Set to true to show mfa to members of a team.' )
2024-11-01 11:38:56 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , bool $userName , bool $userEmail , bool $mfa , Response $response , Database $dbForPlatform ) {
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2024-11-01 11:38:56 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$auths = $project -> getAttribute ( 'auths' , []);
2024-11-05 16:05:21 +00:00
2024-11-06 20:15:31 +00:00
$auths [ 'membershipsUserName' ] = $userName ;
$auths [ 'membershipsUserEmail' ] = $userEmail ;
$auths [ 'membershipsMfa' ] = $mfa ;
2024-11-01 11:38:56 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2024-11-01 11:38:56 +00:00
-> setAttribute ( 'auths' , $auths ));
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/limit' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Update project users limit' )
2021-02-28 11:40:59 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateAuthLimit' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-auth-limit.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2022-01-15 23:25:00 +00:00
-> param ( 'limit' , false , new Range ( 0 , APP_LIMIT_USERS ), 'Set the max number of users allowed in this project. Use 0 for unlimited.' )
2021-02-28 11:40:59 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , int $limit , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2021-02-28 11:40:59 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2021-02-28 11:40:59 +00:00
}
2021-08-06 08:34:17 +00:00
$auths = $project -> getAttribute ( 'auths' , []);
$auths [ 'limit' ] = $limit ;
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2024-10-08 07:54:40 +00:00
-> setAttribute ( 'auths' , $auths ));
2021-02-28 11:40:59 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
2022-11-14 09:15:55 +00:00
});
2022-11-14 09:33:49 +00:00
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/duration' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Update project authentication duration' )
2022-11-14 09:15:55 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateAuthDuration' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-auth-duration.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2022-11-15 10:25:34 +00:00
-> param ( 'duration' , 31536000 , new Range ( 0 , 31536000 ), 'Project session length in seconds. Max length: 31536000 seconds.' )
2022-11-14 09:15:55 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , int $duration , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2022-11-14 09:15:55 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
2022-11-14 09:30:45 +00:00
$auths = $project -> getAttribute ( 'auths' , []);
2022-11-15 10:25:34 +00:00
$auths [ 'duration' ] = $duration ;
2022-11-14 09:30:45 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2024-10-08 07:54:40 +00:00
-> setAttribute ( 'auths' , $auths ));
2022-11-14 09:15:55 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
2021-02-28 11:40:59 +00:00
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/:method' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Update project auth method status. Use this endpoint to enable or disable a given auth method for this project.' )
2021-02-28 11:40:59 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateAuthStatus' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-auth-status.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2021-06-07 05:17:29 +00:00
-> param ( 'method' , '' , new WhiteList ( \array_keys ( Config :: getParam ( 'auth' )), true ), 'Auth Method. Possible values: ' . implode ( ',' , \array_keys ( Config :: getParam ( 'auth' ))), false )
2021-02-28 15:00:27 +00:00
-> param ( 'status' , false , new Boolean ( true ), 'Set the status of this auth method.' )
2021-02-28 11:40:59 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $method , bool $status , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2024-10-08 07:54:40 +00:00
$auth = Config :: getParam ( 'auth' )[ $method ] ? ? [];
$authKey = $auth [ 'key' ] ? ? '' ;
2021-02-28 15:00:27 +00:00
$status = ( $status === '1' || $status === 'true' || $status === 1 || $status === true );
2021-02-28 11:40:59 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2021-02-28 11:40:59 +00:00
}
2021-08-06 07:42:31 +00:00
$auths = $project -> getAttribute ( 'auths' , []);
$auths [ $authKey ] = $status ;
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'auths' , $auths ));
2021-02-28 11:40:59 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
2021-02-28 11:40:59 +00:00
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/password-history' )
2023-01-30 06:05:32 +00:00
-> desc ( 'Update authentication password history. Use this endpoint to set the number of password history to save and 0 to disable password history.' )
2022-12-16 10:37:49 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateAuthPasswordHistory' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-auth-password-history.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2022-12-19 05:07:41 +00:00
-> param ( 'limit' , 0 , new Range ( 0 , APP_LIMIT_USER_PASSWORD_HISTORY ), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0' )
2022-12-16 10:37:49 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , int $limit , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2022-12-16 10:37:49 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$auths = $project -> getAttribute ( 'auths' , []);
$auths [ 'passwordHistory' ] = $limit ;
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2024-10-08 07:54:40 +00:00
-> setAttribute ( 'auths' , $auths ));
2022-12-16 10:37:49 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/password-dictionary' )
2023-04-11 23:01:50 +00:00
-> desc ( 'Update authentication password dictionary status. Use this endpoint to enable or disable the dicitonary check for user password' )
2022-12-26 05:31:49 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateAuthPasswordDictionary' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-auth-password-dictionary.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2023-01-30 06:06:52 +00:00
-> param ( 'enabled' , false , new Boolean ( false ), 'Set whether or not to enable checking user\'s password against most commonly used passwords. Default is false.' )
2022-12-26 05:31:49 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , bool $enabled , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2022-12-26 05:31:49 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$auths = $project -> getAttribute ( 'auths' , []);
2023-01-30 06:06:52 +00:00
$auths [ 'passwordDictionary' ] = $enabled ;
2022-12-26 05:31:49 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2024-10-08 07:54:40 +00:00
-> setAttribute ( 'auths' , $auths ));
2022-12-26 05:31:49 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/personal-data' )
2025-04-14 18:40:48 +00:00
-> desc ( 'Update personal data check' )
2023-04-11 23:01:50 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updatePersonalDataCheck' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-personal-data-check.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2023-04-13 20:20:03 +00:00
-> param ( 'enabled' , false , new Boolean ( false ), 'Set whether or not to check a password for similarity with personal data. Default is false.' )
2023-04-11 23:01:50 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , bool $enabled , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-04-11 23:01:50 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$auths = $project -> getAttribute ( 'auths' , []);
2023-07-19 22:24:32 +00:00
$auths [ 'personalDataCheck' ] = $enabled ;
2023-04-11 23:01:50 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2024-10-08 07:54:40 +00:00
-> setAttribute ( 'auths' , $auths ));
2023-04-11 23:01:50 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/max-sessions' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Update project user sessions limit' )
2022-12-06 10:45:04 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateAuthSessionsLimit' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-auth-sessions-limit.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2022-12-12 05:07:18 +00:00
-> param ( 'limit' , false , new Range ( 1 , APP_LIMIT_USER_SESSIONS_MAX ), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT )
2022-12-06 10:45:04 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , int $limit , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2022-12-06 10:45:04 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$auths = $project -> getAttribute ( 'auths' , []);
2022-12-09 11:33:26 +00:00
$auths [ 'maxSessions' ] = $limit ;
2022-12-06 10:45:04 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2024-10-08 07:54:40 +00:00
-> setAttribute ( 'auths' , $auths ));
2022-12-06 10:45:04 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/mock-numbers' )
2024-02-11 14:51:19 +00:00
-> desc ( 'Update the mock numbers for the project' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'updateMockNumbers' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-mock-numbers.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2024-02-11 14:51:19 +00:00
-> param ( 'numbers' , '' , new ArrayList ( new MockNumber (), 10 ), 'An array of mock numbers and their corresponding verification codes (OTPs). Each number should be a valid E.164 formatted phone number. Maximum of 10 numbers are allowed.' )
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , array $numbers , Response $response , Database $dbForPlatform ) {
2024-02-11 14:51:19 +00:00
2024-07-21 19:30:06 +00:00
$uniqueNumbers = [];
foreach ( $numbers as $number ) {
2024-07-21 19:45:39 +00:00
if ( isset ( $uniqueNumbers [ $number [ 'phone' ]])) {
throw new Exception ( Exception :: GENERAL_BAD_REQUEST , 'Duplicate phone numbers are not allowed.' );
2024-07-21 19:30:06 +00:00
}
2024-07-21 19:45:39 +00:00
$uniqueNumbers [ $number [ 'phone' ]] = $number [ 'otp' ];
2024-07-21 19:30:06 +00:00
}
2024-07-22 09:08:02 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2024-02-11 14:51:19 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$auths = $project -> getAttribute ( 'auths' , []);
$auths [ 'mockNumbers' ] = $numbers ;
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'auths' , $auths ));
2024-02-11 14:51:19 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: delete ( '/v1/projects/:projectId' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Delete project' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-07-22 08:03:53 +00:00
-> label ( 'audits.event' , 'projects.delete' )
2024-12-02 09:47:17 +00:00
-> label ( 'audits.resource' , 'project/{request.projectId}' )
2019-12-14 19:33:29 +00:00
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'projects' ,
2025-01-17 04:31:39 +00:00
name : 'delete' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/delete.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_NOCONTENT ,
model : Response :: MODEL_NONE ,
)
],
contentType : ContentType :: NONE
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
-> inject ( 'user' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
2022-12-20 16:11:30 +00:00
-> inject ( 'queueForDeletes' )
2024-12-12 10:30:26 +00:00
-> action ( function ( string $projectId , Response $response , Document $user , Database $dbForPlatform , Delete $queueForDeletes ) {
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-14 19:33:29 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-14 19:33:29 +00:00
2022-12-20 16:11:30 +00:00
$queueForDeletes
2024-10-01 14:17:36 +00:00
-> setProject ( $project )
2022-04-17 20:34:32 +00:00
-> setType ( DELETE_TYPE_DOCUMENT )
2023-08-28 12:19:37 +00:00
-> setDocument ( $project );
2021-06-07 05:17:29 +00:00
2024-12-12 10:30:26 +00:00
if ( ! $dbForPlatform -> deleteDocument ( 'projects' , $projectId )) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: GENERAL_SERVER_ERROR , 'Failed to remove project from DB' );
2019-12-18 10:24:54 +00:00
}
2020-06-30 15:46:42 +00:00
$response -> noContent ();
2020-12-26 16:33:36 +00:00
});
2019-12-18 10:24:54 +00:00
// Keys
2026-02-04 05:30:22 +00:00
Http :: post ( '/v1/projects/:projectId/keys' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Create key' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'keys.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'keys' ,
2025-01-17 04:31:39 +00:00
name : 'createKey' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/create-key.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_CREATED ,
model : Response :: MODEL_KEY ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2026-02-09 15:42:14 +00:00
// TODO: When migrating to Platform API, mark keyId required for consistency
2026-02-12 10:35:21 +00:00
-> param ( 'keyId' , 'unique()' , fn ( Database $dbForPlatform ) => new CustomId ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Key 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.' , true , [ 'dbForPlatform' ]) -> param ( 'name' , null , new Text ( 128 ), 'Key name. Max length: 128 chars.' )
2025-12-23 12:06:19 +00:00
-> param ( 'scopes' , null , new Nullable ( new ArrayList ( new WhiteList ( array_keys ( Config :: getParam ( 'projectScopes' )), true ), APP_LIMIT_ARRAY_PARAMS_SIZE )), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.' )
2025-11-10 04:45:49 +00:00
-> param ( 'expire' , null , new Nullable ( new DatetimeValidator ()), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.' , true )
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
2026-02-09 13:34:05 +00:00
-> action ( function ( string $projectId , string $keyId , string $name , array $scopes , ? string $expire , Response $response , Database $dbForPlatform ) {
2026-02-09 15:42:14 +00:00
$keyId = $keyId == 'unique()' ? ID :: unique () : $keyId ;
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-18 10:24:54 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2021-05-15 22:41:42 +00:00
$key = new Document ([
2026-02-09 13:34:05 +00:00
'$id' => $keyId ,
2022-08-02 09:21:53 +00:00
'$permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-02 09:21:53 +00:00
],
2025-12-19 12:40:32 +00:00
'resourceInternalId' => $project -> getSequence (),
'resourceId' => $project -> getId (),
'resourceType' => 'projects' ,
2020-06-30 15:46:42 +00:00
'name' => $name ,
'scopes' => $scopes ,
2022-05-31 15:41:12 +00:00
'expire' => $expire ,
2022-08-05 10:20:48 +00:00
'sdks' => [],
2022-08-19 09:54:26 +00:00
'accessedAt' => null ,
2024-05-16 08:39:15 +00:00
'secret' => API_KEY_STANDARD . '_' . \bin2hex ( \random_bytes ( 128 )),
2020-06-30 15:46:42 +00:00
]);
2026-02-10 10:43:22 +00:00
try {
$key = $dbForPlatform -> createDocument ( 'keys' , $key );
} catch ( Duplicate ) {
throw new Exception ( Exception :: KEY_ALREADY_EXISTS );
}
2021-08-30 14:24:50 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> purgeCachedDocument ( 'projects' , $project -> getId ());
2020-06-30 15:46:42 +00:00
2022-09-07 11:02:36 +00:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $key , Response :: MODEL_KEY );
2020-12-26 16:33:36 +00:00
});
2019-12-18 10:24:54 +00:00
2026-02-04 05:30:22 +00:00
Http :: get ( '/v1/projects/:projectId/keys' )
2023-08-01 15:26:48 +00:00
-> desc ( 'List keys' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'keys.read' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'keys' ,
2025-01-17 04:31:39 +00:00
name : 'listKeys' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/list-keys.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_KEY_LIST ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2026-02-09 15:58:44 +00:00
-> param ( 'queries' , [], new Keys (), '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 ( ', ' , Keys :: ALLOWED_ATTRIBUTES ), true )
2025-10-29 09:08:08 +00:00
-> param ( 'total' , true , new Boolean ( true ), 'When set to false, the total count returned will be 0 and will not be calculated.' , true )
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
2026-02-09 15:58:44 +00:00
-> action ( function ( string $projectId , array $queries , bool $includeTotal , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2020-06-30 15:46:42 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-01-31 22:34:07 +00:00
}
2020-06-30 15:46:42 +00:00
2026-02-09 13:58:36 +00:00
try {
$queries = Query :: parseQueries ( $queries );
} catch ( QueryException $e ) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $e -> getMessage ());
}
2026-02-10 10:48:29 +00:00
// Backwards compatibility
if ( \count ( Query :: getByType ( $queries , [ Query :: TYPE_LIMIT ])) === 0 ) {
$queries [] = Query :: limit ( 5000 );
}
2026-02-09 13:58:36 +00:00
$queries [] = Query :: equal ( 'resourceType' , [ 'projects' ]);
$queries [] = Query :: equal ( 'resourceInternalId' , [ $project -> getSequence ()]);
$cursor = Query :: getCursorQueries ( $queries , false );
$cursor = \reset ( $cursor );
if ( $cursor !== false ) {
$validator = new Cursor ();
if ( ! $validator -> isValid ( $cursor )) {
throw new Exception ( Exception :: GENERAL_QUERY_INVALID , $validator -> getDescription ());
}
$keyId = $cursor -> getValue ();
2026-02-09 19:07:33 +00:00
$cursorDocument = $dbForPlatform -> getDocument ( 'keys' , $keyId );
2026-02-09 13:58:36 +00:00
if ( $cursorDocument -> isEmpty ()) {
throw new Exception ( Exception :: GENERAL_CURSOR_NOT_FOUND , " Key ' { $keyId } ' for the 'cursor' value not found. " );
}
$cursor -> setValue ( $cursorDocument );
}
$filterQueries = Query :: groupByType ( $queries )[ 'filters' ];
$keys = $dbForPlatform -> find ( 'keys' , $queries );
2020-08-14 21:56:50 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( new Document ([
2021-05-27 10:09:14 +00:00
'keys' => $keys ,
2026-02-09 13:58:36 +00:00
'total' => $includeTotal ? $dbForPlatform -> count ( 'keys' , $filterQueries , APP_LIMIT_COUNT ) : 0 ,
2020-08-14 21:56:50 +00:00
]), Response :: MODEL_KEY_LIST );
2020-12-26 16:33:36 +00:00
});
2020-01-31 22:34:07 +00:00
2026-02-04 05:30:22 +00:00
Http :: get ( '/v1/projects/:projectId/keys/:keyId' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Get key' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'keys.read' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'keys' ,
2025-01-17 04:31:39 +00:00
name : 'getKey' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/get-key.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_KEY ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
-> param ( 'keyId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Key unique ID.' , false , [ 'dbForPlatform' ])
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $keyId , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2020-01-31 22:34:07 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2020-01-31 22:34:07 +00:00
2024-12-12 10:30:26 +00:00
$key = $dbForPlatform -> findOne ( 'keys' , [
2023-05-03 11:53:40 +00:00
Query :: equal ( '$id' , [ $keyId ]),
2025-12-19 12:40:32 +00:00
Query :: equal ( 'resourceType' , [ 'projects' ]),
2026-01-06 12:19:32 +00:00
Query :: equal ( 'resourceInternalId' , [ $project -> getSequence ()]),
2021-09-01 08:25:54 +00:00
]);
2020-01-31 22:34:07 +00:00
2024-10-31 08:13:23 +00:00
if ( $key -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: KEY_NOT_FOUND );
2020-01-31 22:34:07 +00:00
}
2020-06-30 15:46:42 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( $key , Response :: MODEL_KEY );
2020-12-26 16:33:36 +00:00
});
2020-01-31 22:34:07 +00:00
2026-02-04 05:30:22 +00:00
Http :: put ( '/v1/projects/:projectId/keys/:keyId' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Update key' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'keys.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'keys' ,
2025-01-17 04:31:39 +00:00
name : 'updateKey' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-key.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_KEY ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
-> param ( 'keyId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Key unique ID.' , false , [ 'dbForPlatform' ])
2020-09-10 14:40:14 +00:00
-> param ( 'name' , null , new Text ( 128 ), 'Key name. Max length: 128 chars.' )
2025-12-23 12:06:19 +00:00
-> param ( 'scopes' , null , new Nullable ( new ArrayList ( new WhiteList ( array_keys ( Config :: getParam ( 'projectScopes' )), true ), APP_LIMIT_ARRAY_PARAMS_SIZE )), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.' )
2025-11-10 04:45:49 +00:00
-> param ( 'expire' , null , new Nullable ( new DatetimeValidator ()), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.' , true )
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $keyId , string $name , array $scopes , ? string $expire , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-18 10:24:54 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$key = $dbForPlatform -> findOne ( 'keys' , [
2023-05-03 11:53:40 +00:00
Query :: equal ( '$id' , [ $keyId ]),
2025-12-19 12:40:32 +00:00
Query :: equal ( 'resourceType' , [ 'projects' ]),
2026-01-06 12:19:32 +00:00
Query :: equal ( 'resourceInternalId' , [ $project -> getSequence ()]),
2021-09-01 08:25:54 +00:00
]);
2019-12-18 10:24:54 +00:00
2024-10-31 08:13:23 +00:00
if ( $key -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: KEY_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2021-09-14 06:57:55 +00:00
$key
-> setAttribute ( 'name' , $name )
-> setAttribute ( 'scopes' , $scopes )
2023-08-28 12:19:37 +00:00
-> setAttribute ( 'expire' , $expire );
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'keys' , $key -> getId (), $key );
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> purgeCachedDocument ( 'projects' , $project -> getId ());
2021-06-07 05:17:29 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( $key , Response :: MODEL_KEY );
2020-12-26 16:33:36 +00:00
});
2019-12-18 10:24:54 +00:00
2026-02-04 05:30:22 +00:00
Http :: delete ( '/v1/projects/:projectId/keys/:keyId' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Delete key' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'keys.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'keys' ,
2025-01-17 04:31:39 +00:00
name : 'deleteKey' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/delete-key.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_NOCONTENT ,
model : Response :: MODEL_NONE ,
)
],
contentType : ContentType :: NONE
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
-> param ( 'keyId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Key unique ID.' , false , [ 'dbForPlatform' ])
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $keyId , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-18 10:24:54 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$key = $dbForPlatform -> findOne ( 'keys' , [
2023-05-03 11:53:40 +00:00
Query :: equal ( '$id' , [ $keyId ]),
2025-12-19 12:40:32 +00:00
Query :: equal ( 'resourceType' , [ 'projects' ]),
2026-01-06 12:19:32 +00:00
Query :: equal ( 'resourceInternalId' , [ $project -> getSequence ()]),
2021-09-01 08:25:54 +00:00
]);
2021-08-30 14:24:50 +00:00
2024-10-31 08:13:23 +00:00
if ( $key -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: KEY_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> deleteDocument ( 'keys' , $key -> getId ());
2021-08-30 14:24:50 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> purgeCachedDocument ( 'projects' , $project -> getId ());
2020-06-30 15:46:42 +00:00
$response -> noContent ();
2020-12-26 16:33:36 +00:00
});
2019-12-18 10:24:54 +00:00
2024-05-29 08:57:25 +00:00
// JWT Keys
2026-02-04 05:30:22 +00:00
Http :: post ( '/v1/projects/:projectId/jwts' )
2024-05-29 08:57:25 +00:00
-> groups ([ 'api' , 'projects' ])
-> desc ( 'Create JWT' )
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'auth' ,
2025-01-17 04:31:39 +00:00
name : 'createJWT' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/create-jwt.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_CREATED ,
model : Response :: MODEL_JWT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2025-12-23 12:06:19 +00:00
-> param ( 'scopes' , [], new ArrayList ( new WhiteList ( array_keys ( Config :: getParam ( 'projectScopes' )), true ), APP_LIMIT_ARRAY_PARAMS_SIZE ), 'List of scopes allowed for JWT key. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.' )
2024-05-29 08:57:25 +00:00
-> param ( 'duration' , 900 , new Range ( 0 , 3600 ), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.' , true )
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , array $scopes , int $duration , Response $response , Database $dbForPlatform ) {
2024-05-29 08:57:25 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2024-05-29 08:57:25 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$jwt = new JWT ( System :: getEnv ( '_APP_OPENSSL_KEY_V1' ), 'HS256' , $duration , 0 );
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( new Document ([ 'jwt' => API_KEY_DYNAMIC . '_' . $jwt -> encode ([
'projectId' => $project -> getId (),
'scopes' => $scopes
])]), Response :: MODEL_JWT );
});
2019-12-18 10:24:54 +00:00
// Platforms
2026-02-04 05:30:22 +00:00
Http :: post ( '/v1/projects/:projectId/platforms' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Create platform' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-07-22 08:03:53 +00:00
-> label ( 'audits.event' , 'platforms.create' )
2024-12-02 09:47:17 +00:00
-> label ( 'audits.resource' , 'project/{request.projectId}' )
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'platforms.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'platforms' ,
2025-01-17 04:31:39 +00:00
name : 'createPlatform' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/create-platform.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_CREATED ,
model : Response :: MODEL_PLATFORM ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2025-09-26 07:03:10 +00:00
-> param (
'type' ,
null ,
new WhiteList ([
Platform :: TYPE_WEB ,
Platform :: TYPE_FLUTTER_WEB ,
Platform :: TYPE_FLUTTER_IOS ,
Platform :: TYPE_FLUTTER_ANDROID ,
Platform :: TYPE_FLUTTER_LINUX ,
Platform :: TYPE_FLUTTER_MACOS ,
Platform :: TYPE_FLUTTER_WINDOWS ,
Platform :: TYPE_APPLE_IOS ,
Platform :: TYPE_APPLE_MACOS ,
Platform :: TYPE_APPLE_WATCHOS ,
Platform :: TYPE_APPLE_TVOS ,
Platform :: TYPE_ANDROID ,
Platform :: TYPE_UNITY ,
Platform :: TYPE_REACT_NATIVE_IOS ,
Platform :: TYPE_REACT_NATIVE_ANDROID ,
], true ),
'Platform type. Possible values are: web, flutter-web, flutter-ios, flutter-android, flutter-linux, flutter-macos, flutter-windows, apple-ios, apple-macos, apple-watchos, apple-tvos, android, unity, react-native-ios, react-native-android.'
)
2020-09-10 14:40:14 +00:00
-> param ( 'name' , null , new Text ( 128 ), 'Platform name. Max length: 128 chars.' )
2021-09-28 10:24:54 +00:00
-> param ( 'key' , '' , new Text ( 256 ), 'Package name for Android or bundle ID for iOS or macOS. Max length: 256 chars.' , true )
2020-09-10 14:40:14 +00:00
-> param ( 'store' , '' , new Text ( 256 ), 'App store or Google Play store ID. Max length: 256 chars.' , true )
2022-05-12 18:53:54 +00:00
-> param ( 'hostname' , '' , new Hostname (), 'Platform client hostname. Max length: 256 chars.' , true )
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
2025-01-31 22:15:22 +00:00
-> action ( function ( string $projectId , string $type , string $name , string $key , string $store , string $hostname , Response $response , Database $dbForPlatform ) {
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-18 10:24:54 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2021-05-15 22:41:42 +00:00
$platform = new Document ([
2022-08-14 14:22:38 +00:00
'$id' => ID :: unique (),
2022-08-02 09:21:53 +00:00
'$permissions' => [
2022-08-15 10:11:17 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-02 09:21:53 +00:00
],
2025-05-26 05:42:11 +00:00
'projectInternalId' => $project -> getSequence (),
2021-08-30 14:24:50 +00:00
'projectId' => $project -> getId (),
2020-06-30 15:46:42 +00:00
'type' => $type ,
'name' => $name ,
'key' => $key ,
'store' => $store ,
2022-06-15 12:46:52 +00:00
'hostname' => $hostname
2020-06-30 15:46:42 +00:00
]);
2024-12-12 10:30:26 +00:00
$platform = $dbForPlatform -> createDocument ( 'platforms' , $platform );
2021-08-30 14:24:50 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> purgeCachedDocument ( 'projects' , $project -> getId ());
2020-06-30 15:46:42 +00:00
2022-09-07 11:02:36 +00:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> dynamic ( $platform , Response :: MODEL_PLATFORM );
2020-12-26 16:33:36 +00:00
});
2021-06-07 05:17:29 +00:00
2026-02-04 05:30:22 +00:00
Http :: get ( '/v1/projects/:projectId/platforms' )
2023-08-01 15:26:48 +00:00
-> desc ( 'List platforms' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'platforms.read' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'platforms' ,
2025-01-17 04:31:39 +00:00
name : 'listPlatforms' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/list-platforms.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PLATFORM_LIST ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2025-10-29 09:08:08 +00:00
-> param ( 'total' , true , new Boolean ( true ), 'When set to false, the total count returned will be 0 and will not be calculated.' , true )
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
2025-10-19 12:45:16 +00:00
-> action ( function ( string $projectId , bool $includeTotal , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2020-01-31 22:34:07 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-01-31 22:34:07 +00:00
}
2020-06-30 15:46:42 +00:00
2024-12-12 10:30:26 +00:00
$platforms = $dbForPlatform -> find ( 'platforms' , [
2025-05-26 05:42:11 +00:00
Query :: equal ( 'projectInternalId' , [ $project -> getSequence ()]),
2022-08-11 23:53:52 +00:00
Query :: limit ( 5000 ),
]);
2020-06-30 15:46:42 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( new Document ([
2021-05-27 10:09:14 +00:00
'platforms' => $platforms ,
2025-10-19 12:45:16 +00:00
'total' => $includeTotal ? count ( $platforms ) : 0 ,
2020-08-14 21:56:50 +00:00
]), Response :: MODEL_PLATFORM_LIST );
2020-12-26 16:33:36 +00:00
});
2020-01-31 22:34:07 +00:00
2026-02-04 05:30:22 +00:00
Http :: get ( '/v1/projects/:projectId/platforms/:platformId' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Get platform' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'platforms.read' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'platforms' ,
2025-01-17 04:31:39 +00:00
name : 'getPlatform' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/get-platform.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PLATFORM ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
-> param ( 'platformId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Platform unique ID.' , false , [ 'dbForPlatform' ])
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $platformId , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2020-01-31 22:34:07 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2020-01-31 22:34:07 +00:00
2024-12-12 10:30:26 +00:00
$platform = $dbForPlatform -> findOne ( 'platforms' , [
2023-05-03 11:53:40 +00:00
Query :: equal ( '$id' , [ $platformId ]),
2025-05-26 05:42:11 +00:00
Query :: equal ( 'projectInternalId' , [ $project -> getSequence ()]),
2021-09-01 08:25:54 +00:00
]);
2020-01-31 22:34:07 +00:00
2024-10-31 08:13:23 +00:00
if ( $platform -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PLATFORM_NOT_FOUND );
2020-01-31 22:34:07 +00:00
}
2020-06-30 15:46:42 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( $platform , Response :: MODEL_PLATFORM );
2020-12-26 16:33:36 +00:00
});
2019-12-18 10:24:54 +00:00
2026-02-04 05:30:22 +00:00
Http :: put ( '/v1/projects/:projectId/platforms/:platformId' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Update platform' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'platforms.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'platforms' ,
2025-01-17 04:31:39 +00:00
name : 'updatePlatform' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-platform.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PLATFORM ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
-> param ( 'platformId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Platform unique ID.' , false , [ 'dbForPlatform' ])
2020-09-10 14:40:14 +00:00
-> param ( 'name' , null , new Text ( 128 ), 'Platform name. Max length: 128 chars.' )
-> param ( 'key' , '' , new Text ( 256 ), 'Package name for android or bundle ID for iOS. Max length: 256 chars.' , true )
-> param ( 'store' , '' , new Text ( 256 ), 'App store or Google Play store ID. Max length: 256 chars.' , true )
2022-05-12 18:53:54 +00:00
-> param ( 'hostname' , '' , new Hostname (), 'Platform client URL. Max length: 256 chars.' , true )
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $platformId , string $name , string $key , string $store , string $hostname , Response $response , Database $dbForPlatform ) {
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-18 10:24:54 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$platform = $dbForPlatform -> findOne ( 'platforms' , [
2023-05-03 11:53:40 +00:00
Query :: equal ( '$id' , [ $platformId ]),
2025-05-26 05:42:11 +00:00
Query :: equal ( 'projectInternalId' , [ $project -> getSequence ()]),
2021-09-01 08:25:54 +00:00
]);
2019-12-18 10:24:54 +00:00
2024-10-31 08:13:23 +00:00
if ( $platform -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PLATFORM_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2020-06-30 15:46:42 +00:00
$platform
-> setAttribute ( 'name' , $name )
-> setAttribute ( 'key' , $key )
-> setAttribute ( 'store' , $store )
2023-08-28 12:19:37 +00:00
-> setAttribute ( 'hostname' , $hostname );
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> updateDocument ( 'platforms' , $platform -> getId (), $platform );
2020-06-30 15:46:42 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> purgeCachedDocument ( 'projects' , $project -> getId ());
2021-05-15 22:41:42 +00:00
2021-07-25 14:47:18 +00:00
$response -> dynamic ( $platform , Response :: MODEL_PLATFORM );
2020-12-26 16:33:36 +00:00
});
2019-12-18 10:24:54 +00:00
2026-02-04 05:30:22 +00:00
Http :: delete ( '/v1/projects/:projectId/platforms/:platformId' )
2023-08-01 15:26:48 +00:00
-> desc ( 'Delete platform' )
2020-06-25 18:32:12 +00:00
-> groups ([ 'api' , 'projects' ])
2024-07-22 08:03:53 +00:00
-> label ( 'audits.event' , 'platforms.delete' )
2024-12-02 09:47:17 +00:00
-> label ( 'audits.resource' , 'project/{request.projectId}/platform/${request.platformId}' )
2024-09-04 01:51:32 +00:00
-> label ( 'scope' , 'platforms.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'platforms' ,
2025-01-17 04:31:39 +00:00
name : 'deletePlatform' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/delete-platform.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_NOCONTENT ,
model : Response :: MODEL_NONE ,
)
],
contentType : ContentType :: NONE
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
-> param ( 'platformId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Platform unique ID.' , false , [ 'dbForPlatform' ])
2020-12-26 16:33:36 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $platformId , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2019-12-18 10:24:54 +00:00
2021-05-15 22:41:42 +00:00
if ( $project -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$platform = $dbForPlatform -> findOne ( 'platforms' , [
2023-05-03 11:53:40 +00:00
Query :: equal ( '$id' , [ $platformId ]),
2025-05-26 05:42:11 +00:00
Query :: equal ( 'projectInternalId' , [ $project -> getSequence ()]),
2021-09-01 08:25:54 +00:00
]);
2021-08-30 07:33:45 +00:00
2024-10-31 08:13:23 +00:00
if ( $platform -> isEmpty ()) {
2022-07-26 14:24:32 +00:00
throw new Exception ( Exception :: PLATFORM_NOT_FOUND );
2020-06-30 15:46:42 +00:00
}
2019-12-18 10:24:54 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> deleteDocument ( 'platforms' , $platformId );
2021-09-01 08:25:54 +00:00
2024-12-12 10:30:26 +00:00
$dbForPlatform -> purgeCachedDocument ( 'projects' , $project -> getId ());
2020-06-30 15:46:42 +00:00
$response -> noContent ();
2020-12-26 16:33:36 +00:00
});
2020-02-22 08:10:30 +00:00
2023-03-09 01:59:10 +00:00
// CUSTOM SMTP and Templates
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/smtp' )
2023-12-19 15:08:09 +00:00
-> desc ( 'Update SMTP' )
2023-03-09 01:59:10 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-08-20 14:08:27 +00:00
-> label ( 'sdk' , [
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'updateSmtp' ,
description : '/docs/references/projects/update-smtp.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
],
deprecated : new Deprecated (
since : '1.8.0' ,
2025-08-23 09:36:02 +00:00
replaceWith : 'projects.updateSMTP' ,
2025-08-20 14:08:27 +00:00
),
2025-12-11 08:23:34 +00:00
public : false ,
2025-08-20 14:08:27 +00:00
),
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'updateSMTP' ,
description : '/docs/references/projects/update-smtp.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
)
])
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2023-03-09 01:59:10 +00:00
-> param ( 'enabled' , false , new Boolean (), 'Enable custom SMTP service' )
2023-08-28 14:08:50 +00:00
-> param ( 'senderName' , '' , new Text ( 255 , 0 ), 'Name of the email sender' , true )
2023-08-28 12:19:37 +00:00
-> param ( 'senderEmail' , '' , new Email (), 'Email of the sender' , true )
-> param ( 'replyTo' , '' , new Email (), 'Reply to email' , true )
-> param ( 'host' , '' , new HostName (), 'SMTP server host name' , true )
-> param ( 'port' , 587 , new Integer (), 'SMTP server port' , true )
2023-08-30 05:31:02 +00:00
-> param ( 'username' , '' , new Text ( 0 , 0 ), 'SMTP server username' , true )
-> param ( 'password' , '' , new Text ( 0 , 0 ), 'SMTP server password' , true )
2024-02-26 15:10:41 +00:00
-> param ( 'secure' , '' , new WhiteList ([ 'tls' , 'ssl' ], true ), 'Does SMTP server use secure connection' , true )
2023-03-09 01:59:10 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , bool $enabled , string $senderName , string $senderEmail , string $replyTo , string $host , int $port , string $username , string $password , string $secure , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-03-09 01:59:10 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
2023-08-28 12:19:37 +00:00
// Ensure required params for when enabling SMTP
if ( $enabled ) {
if ( empty ( $senderName )) {
throw new Exception ( Exception :: GENERAL_ARGUMENT_INVALID , 'Sender name is required when enabling SMTP.' );
2023-08-28 12:21:35 +00:00
} elseif ( empty ( $senderEmail )) {
2023-08-28 12:19:37 +00:00
throw new Exception ( Exception :: GENERAL_ARGUMENT_INVALID , 'Sender email is required when enabling SMTP.' );
2023-08-28 12:21:35 +00:00
} elseif ( empty ( $host )) {
2023-08-28 12:19:37 +00:00
throw new Exception ( Exception :: GENERAL_ARGUMENT_INVALID , 'Host is required when enabling SMTP.' );
2023-08-28 12:21:35 +00:00
} elseif ( empty ( $port )) {
2023-08-28 12:19:37 +00:00
throw new Exception ( Exception :: GENERAL_ARGUMENT_INVALID , 'Port is required when enabling SMTP.' );
}
}
2023-05-23 05:09:17 +00:00
// validate SMTP settings
2023-08-28 12:19:37 +00:00
if ( $enabled ) {
$mail = new PHPMailer ( true );
$mail -> isSMTP ();
2025-12-12 04:58:59 +00:00
$mail -> SMTPAuth = ( ! empty ( $username ) && ! empty ( $password ));
2023-08-28 12:19:37 +00:00
$mail -> Username = $username ;
$mail -> Password = $password ;
$mail -> Host = $host ;
$mail -> Port = $port ;
$mail -> SMTPSecure = $secure ;
$mail -> SMTPAutoTLS = false ;
$mail -> Timeout = 5 ;
try {
$valid = $mail -> SmtpConnect ();
if ( ! $valid ) {
throw new Exception ( 'Connection is not valid.' );
}
} catch ( Throwable $error ) {
2025-12-12 04:58:59 +00:00
throw new Exception ( Exception :: PROJECT_SMTP_CONFIG_INVALID , $error -> getMessage ());
2023-08-28 12:19:37 +00:00
}
}
2023-05-23 05:09:17 +00:00
2023-08-28 12:19:37 +00:00
// Save SMTP settings
if ( $enabled ) {
$smtp = [
'enabled' => $enabled ,
'senderName' => $senderName ,
'senderEmail' => $senderEmail ,
'replyTo' => $replyTo ,
'host' => $host ,
'port' => $port ,
'username' => $username ,
'password' => $password ,
'secure' => $secure ,
];
} else {
$smtp = [
'enabled' => false
];
}
2023-03-09 01:59:10 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'smtp' , $smtp ));
2023-03-09 01:59:10 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});
2026-02-04 05:30:22 +00:00
Http :: post ( '/v1/projects/:projectId/smtp/tests' )
2023-12-19 15:08:09 +00:00
-> desc ( 'Create SMTP test' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-08-20 14:08:27 +00:00
-> label ( 'sdk' , [
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'createSmtpTest' ,
description : '/docs/references/projects/create-smtp-test.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_NOCONTENT ,
model : Response :: MODEL_NONE ,
)
],
deprecated : new Deprecated (
since : '1.8.0' ,
2025-08-23 09:36:02 +00:00
replaceWith : 'projects.createSMTPTest' ,
2025-08-20 14:08:27 +00:00
),
2025-12-11 08:23:34 +00:00
public : false ,
2025-08-20 14:08:27 +00:00
),
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'createSMTPTest' ,
description : '/docs/references/projects/create-smtp-test.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_NOCONTENT ,
model : Response :: MODEL_NONE ,
)
]
)
])
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2024-01-15 10:18:17 +00:00
-> param ( 'emails' , [], new ArrayList ( new Email (), 10 ), 'Array of emails to send test email to. Maximum of 10 emails are allowed.' )
2024-04-01 11:02:47 +00:00
-> param ( 'senderName' , System :: getEnv ( '_APP_SYSTEM_EMAIL_NAME' , APP_NAME . ' Server' ), new Text ( 255 , 0 ), 'Name of the email sender' )
-> param ( 'senderEmail' , System :: getEnv ( '_APP_SYSTEM_EMAIL_ADDRESS' , APP_EMAIL_TEAM ), new Email (), 'Email of the sender' )
2024-01-15 10:18:17 +00:00
-> param ( 'replyTo' , '' , new Email (), 'Reply to email' , true )
-> param ( 'host' , '' , new HostName (), 'SMTP server host name' )
-> param ( 'port' , 587 , new Integer (), 'SMTP server port' , true )
-> param ( 'username' , '' , new Text ( 0 , 0 ), 'SMTP server username' , true )
-> param ( 'password' , '' , new Text ( 0 , 0 ), 'SMTP server password' , true )
2024-10-02 17:26:45 +00:00
-> param ( 'secure' , '' , new WhiteList ([ 'tls' , 'ssl' ], true ), 'Does SMTP server use secure connection' , true )
2023-12-19 15:08:09 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
2023-12-19 15:08:09 +00:00
-> inject ( 'queueForMails' )
2025-05-12 13:10:58 +00:00
-> inject ( 'plan' )
-> action ( function ( string $projectId , array $emails , string $senderName , string $senderEmail , string $replyTo , string $host , int $port , string $username , string $password , string $secure , Response $response , Database $dbForPlatform , Mail $queueForMails , array $plan ) {
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-12-19 15:08:09 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
2023-12-19 21:46:35 +00:00
2024-01-17 11:22:08 +00:00
$replyToEmail = ! empty ( $replyTo ) ? $replyTo : $senderEmail ;
$subject = 'Custom SMTP email sample' ;
$template = Template :: fromFile ( __DIR__ . '/../../config/locale/templates/email-smtp-test.tpl' );
$template
-> setParam ( '{{from}}' , " { $senderName } ( { $senderEmail } ) " )
2025-05-12 13:10:58 +00:00
-> setParam ( '{{replyTo}}' , " { $senderName } ( { $replyToEmail } ) " )
2025-05-12 13:20:59 +00:00
-> setParam ( '{{logoUrl}}' , $plan [ 'logoUrl' ] ? ? APP_EMAIL_LOGO_URL )
2025-05-15 07:44:14 +00:00
-> setParam ( '{{accentColor}}' , $plan [ 'accentColor' ] ? ? APP_EMAIL_ACCENT_COLOR )
2025-05-12 13:20:59 +00:00
-> setParam ( '{{twitterUrl}}' , $plan [ 'twitterUrl' ] ? ? APP_SOCIAL_TWITTER )
-> setParam ( '{{discordUrl}}' , $plan [ 'discordUrl' ] ? ? APP_SOCIAL_DISCORD )
-> setParam ( '{{githubUrl}}' , $plan [ 'githubUrl' ] ? ? APP_SOCIAL_GITHUB_APPWRITE )
-> setParam ( '{{termsUrl}}' , $plan [ 'termsUrl' ] ? ? APP_EMAIL_TERMS_URL )
-> setParam ( '{{privacyUrl}}' , $plan [ 'privacyUrl' ] ? ? APP_EMAIL_PRIVACY_URL );
2024-01-15 10:18:17 +00:00
2024-01-15 11:02:05 +00:00
foreach ( $emails as $email ) {
2024-01-15 10:18:17 +00:00
$queueForMails
-> setSmtpHost ( $host )
-> setSmtpPort ( $port )
-> setSmtpUsername ( $username )
-> setSmtpPassword ( $password )
-> setSmtpSecure ( $secure )
-> setSmtpReplyTo ( $replyTo )
-> setSmtpSenderEmail ( $senderEmail )
-> setSmtpSenderName ( $senderName )
-> setRecipient ( $email )
-> setName ( '' )
2025-07-20 09:10:30 +00:00
-> setBodyTemplate ( __DIR__ . '/../../config/locale/templates/email-base-styled.tpl' )
2024-01-17 11:22:08 +00:00
-> setBody ( $template -> render ())
2024-01-15 10:18:17 +00:00
-> setVariables ([])
-> setSubject ( $subject )
-> trigger ();
2023-12-19 15:08:09 +00:00
}
2026-04-01 17:31:11 +00:00
$response -> noContent ();
2023-12-19 15:08:09 +00:00
});
2026-02-04 05:30:22 +00:00
Http :: get ( '/v1/projects/:projectId/templates/sms/:type/:locale' )
2023-05-11 06:56:16 +00:00
-> desc ( 'Get custom SMS template' )
2023-03-09 13:44:31 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-08-20 14:08:27 +00:00
-> label ( 'sdk' , [
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'getSmsTemplate' ,
description : '/docs/references/projects/get-sms-template.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_SMS_TEMPLATE ,
)
],
deprecated : new Deprecated (
since : '1.8.0' ,
2025-08-23 09:36:02 +00:00
replaceWith : 'projects.getSMSTemplate' ,
2025-08-20 14:08:27 +00:00
),
2025-12-11 08:23:34 +00:00
public : false ,
2025-08-20 14:08:27 +00:00
),
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'getSMSTemplate' ,
description : '/docs/references/projects/get-sms-template.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_SMS_TEMPLATE ,
)
]
)
])
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2026-02-18 10:52:33 +00:00
-> param ( 'type' , '' , new WhiteList ( Config :: getParam ( 'locale-templates' )[ 'sms' ] ? ? [], true ), 'Template type' )
2024-06-07 00:54:51 +00:00
-> param ( 'locale' , '' , fn ( $localeCodes ) => new WhiteList ( $localeCodes ), 'Template locale' , false , [ 'localeCodes' ])
2023-03-09 13:44:31 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $type , string $locale , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2023-08-25 15:13:25 +00:00
throw new Exception ( Exception :: GENERAL_NOT_IMPLEMENTED );
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-03-09 13:44:31 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$templates = $project -> getAttribute ( 'templates' , []);
2024-10-08 07:54:40 +00:00
$template = $templates [ 'sms.' . $type . '-' . $locale ] ? ? null ;
2023-03-09 13:44:31 +00:00
2023-05-11 06:56:16 +00:00
if ( is_null ( $template )) {
$template = [
2023-08-28 12:19:37 +00:00
'message' => Template :: fromFile ( __DIR__ . '/../../config/locale/templates/sms-base.tpl' ) -> render (),
2023-05-11 06:56:16 +00:00
];
}
2023-03-09 13:44:31 +00:00
2023-05-11 06:56:16 +00:00
$template [ 'type' ] = $type ;
$template [ 'locale' ] = $locale ;
$response -> dynamic ( new Document ( $template ), Response :: MODEL_SMS_TEMPLATE );
2023-03-09 13:44:31 +00:00
});
2023-09-27 15:11:58 +00:00
2026-02-04 05:30:22 +00:00
Http :: get ( '/v1/projects/:projectId/templates/email/:type/:locale' )
2023-05-11 06:56:16 +00:00
-> desc ( 'Get custom email template' )
2023-03-09 13:44:31 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'templates' ,
2025-01-17 04:31:39 +00:00
name : 'getEmailTemplate' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/get-email-template.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_EMAIL_TEMPLATE ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2026-02-18 10:52:33 +00:00
-> param ( 'type' , '' , new WhiteList ( Config :: getParam ( 'locale-templates' )[ 'email' ] ? ? [], true ), 'Template type' )
2024-06-07 00:54:51 +00:00
-> param ( 'locale' , '' , fn ( $localeCodes ) => new WhiteList ( $localeCodes ), 'Template locale' , false , [ 'localeCodes' ])
2023-03-09 13:44:31 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $type , string $locale , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-03-09 13:44:31 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$templates = $project -> getAttribute ( 'templates' , []);
2024-10-08 07:54:40 +00:00
$template = $templates [ 'email.' . $type . '-' . $locale ] ? ? null ;
2023-03-09 13:44:31 +00:00
2023-05-11 06:56:16 +00:00
$localeObj = new Locale ( $locale );
2025-08-12 13:13:08 +00:00
$localeObj -> setFallback ( System :: getEnv ( '_APP_LOCALE' , 'en' ));
2023-05-11 06:56:16 +00:00
if ( is_null ( $template )) {
2025-07-20 09:10:30 +00:00
/**
* different templates , different placeholders .
*/
$templateConfigs = [
'magicSession' => [
'file' => 'email-magic-url.tpl' ,
'placeholders' => [ 'optionButton' , 'buttonText' , 'optionUrl' , 'clientInfo' , 'securityPhrase' ]
],
'mfaChallenge' => [
'file' => 'email-mfa-challenge.tpl' ,
'placeholders' => [ 'description' , 'clientInfo' ]
],
'otpSession' => [
'file' => 'email-otp.tpl' ,
'placeholders' => [ 'description' , 'clientInfo' , 'securityPhrase' ]
],
'sessionAlert' => [
2025-07-20 11:09:08 +00:00
'file' => 'email-session-alert.tpl' ,
2025-07-20 09:10:30 +00:00
'placeholders' => [ 'body' , 'listDevice' , 'listIpAddress' , 'listCountry' , 'footer' ]
],
];
// fallback to the base template.
$config = $templateConfigs [ $type ] ? ? [
'file' => 'email-inner-base.tpl' ,
'placeholders' => [ 'buttonText' , 'body' , 'footer' ]
];
$templateString = file_get_contents ( __DIR__ . '/../../config/locale/templates/' . $config [ 'file' ]);
// We use `fromString` due to the replace above
$message = Template :: fromString ( $templateString );
// Set type-specific parameters
foreach ( $config [ 'placeholders' ] as $param ) {
$escapeHtml = ! in_array ( $param , [ 'clientInfo' , 'body' , 'footer' , 'description' ]);
$message -> setParam ( " { { { $param } }} " , $localeObj -> getText ( " emails. { $type } . { $param } " ), escapeHtml : $escapeHtml );
}
2023-08-28 08:03:55 +00:00
$message
2025-07-20 09:10:30 +00:00
// common placeholders on all the templates
2023-05-11 06:56:16 +00:00
-> setParam ( '{{hello}}' , $localeObj -> getText ( " emails. { $type } .hello " ))
-> setParam ( '{{thanks}}' , $localeObj -> getText ( " emails. { $type } .thanks " ))
2025-07-20 09:10:30 +00:00
-> setParam ( '{{signature}}' , $localeObj -> getText ( " emails. { $type } .signature " ));
// `useContent: false` will strip new lines!
$message = $message -> render ( useContent : true );
2023-05-17 08:25:24 +00:00
2023-05-11 06:56:16 +00:00
$template = [
'message' => $message ,
'subject' => $localeObj -> getText ( 'emails.' . $type . '.subject' ),
2023-08-29 09:40:30 +00:00
'senderEmail' => '' ,
'senderName' => ''
2023-05-11 06:56:16 +00:00
];
}
2023-03-09 13:44:31 +00:00
2023-05-11 06:56:16 +00:00
$template [ 'type' ] = $type ;
$template [ 'locale' ] = $locale ;
$response -> dynamic ( new Document ( $template ), Response :: MODEL_EMAIL_TEMPLATE );
2023-03-10 06:27:42 +00:00
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/templates/sms/:type/:locale' )
2023-05-11 06:56:16 +00:00
-> desc ( 'Update custom SMS template' )
2023-03-10 06:27:42 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-08-20 14:08:27 +00:00
-> label ( 'sdk' , [
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'updateSmsTemplate' ,
description : '/docs/references/projects/update-sms-template.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_SMS_TEMPLATE ,
)
],
deprecated : new Deprecated (
since : '1.8.0' ,
2025-08-23 09:36:02 +00:00
replaceWith : 'projects.updateSMSTemplate' ,
2025-08-20 14:08:27 +00:00
),
2025-12-11 08:23:34 +00:00
public : false ,
2025-08-20 14:08:27 +00:00
),
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'updateSMSTemplate' ,
description : '/docs/references/projects/update-sms-template.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_SMS_TEMPLATE ,
)
]
)
])
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2026-02-18 10:52:33 +00:00
-> param ( 'type' , '' , new WhiteList ( Config :: getParam ( 'locale-templates' )[ 'sms' ] ? ? [], true ), 'Template type' )
2024-06-07 00:54:51 +00:00
-> param ( 'locale' , '' , fn ( $localeCodes ) => new WhiteList ( $localeCodes ), 'Template locale' , false , [ 'localeCodes' ])
2023-05-11 06:56:16 +00:00
-> param ( 'message' , '' , new Text ( 0 ), 'Template message' )
2023-03-10 06:27:42 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $type , string $locale , string $message , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2023-08-25 15:13:25 +00:00
throw new Exception ( Exception :: GENERAL_NOT_IMPLEMENTED );
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-03-10 06:27:42 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$templates = $project -> getAttribute ( 'templates' , []);
2023-05-11 06:56:16 +00:00
$templates [ 'sms.' . $type . '-' . $locale ] = [
'message' => $message
];
2023-03-10 06:27:42 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'templates' , $templates ));
2023-03-10 06:27:42 +00:00
2023-05-11 06:56:16 +00:00
$response -> dynamic ( new Document ([
'message' => $message ,
'type' => $type ,
'locale' => $locale ,
]), Response :: MODEL_SMS_TEMPLATE );
2023-03-10 06:27:42 +00:00
});
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/templates/email/:type/:locale' )
2023-05-11 06:56:16 +00:00
-> desc ( 'Update custom email templates' )
2023-03-10 06:27:42 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'templates' ,
2025-01-17 04:31:39 +00:00
name : 'updateEmailTemplate' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/update-email-template.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_EMAIL_TEMPLATE ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2026-02-18 10:52:33 +00:00
-> param ( 'type' , '' , new WhiteList ( Config :: getParam ( 'locale-templates' )[ 'email' ] ? ? [], true ), 'Template type' )
2024-06-07 00:54:51 +00:00
-> param ( 'locale' , '' , fn ( $localeCodes ) => new WhiteList ( $localeCodes ), 'Template locale' , false , [ 'localeCodes' ])
2023-05-11 06:56:16 +00:00
-> param ( 'subject' , '' , new Text ( 255 ), 'Email Subject' )
-> param ( 'message' , '' , new Text ( 0 ), 'Template message' )
2023-08-28 14:08:50 +00:00
-> param ( 'senderName' , '' , new Text ( 255 , 0 ), 'Name of the email sender' , true )
2023-08-28 12:19:37 +00:00
-> param ( 'senderEmail' , '' , new Email (), 'Email of the sender' , true )
2023-05-11 06:56:16 +00:00
-> param ( 'replyTo' , '' , new Email (), 'Reply to email' , true )
2023-03-10 06:27:42 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $type , string $locale , string $subject , string $message , string $senderName , string $senderEmail , string $replyTo , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-03-10 06:27:42 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$templates = $project -> getAttribute ( 'templates' , []);
2023-05-11 06:56:16 +00:00
$templates [ 'email.' . $type . '-' . $locale ] = [
'senderName' => $senderName ,
'senderEmail' => $senderEmail ,
'subject' => $subject ,
'replyTo' => $replyTo ,
'message' => $message
];
2023-03-10 06:27:42 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'templates' , $templates ));
2023-03-10 06:27:42 +00:00
2023-05-11 06:56:16 +00:00
$response -> dynamic ( new Document ([
'type' => $type ,
'locale' => $locale ,
'senderName' => $senderName ,
'senderEmail' => $senderEmail ,
'subject' => $subject ,
'replyTo' => $replyTo ,
'message' => $message
]), Response :: MODEL_EMAIL_TEMPLATE );
2023-03-09 13:44:31 +00:00
});
2023-04-19 08:44:22 +00:00
2026-02-04 05:30:22 +00:00
Http :: delete ( '/v1/projects/:projectId/templates/sms/:type/:locale' )
2023-04-19 08:44:22 +00:00
-> desc ( 'Reset custom SMS template' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-08-20 14:08:27 +00:00
-> label ( 'sdk' , [
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'deleteSmsTemplate' ,
description : '/docs/references/projects/delete-sms-template.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_SMS_TEMPLATE ,
)
],
contentType : ContentType :: JSON ,
deprecated : new Deprecated (
since : '1.8.0' ,
2025-08-23 09:36:02 +00:00
replaceWith : 'projects.deleteSMSTemplate' ,
2025-08-20 14:08:27 +00:00
),
2025-12-11 08:23:34 +00:00
public : false ,
2025-08-20 14:08:27 +00:00
),
new Method (
namespace : 'projects' ,
group : 'templates' ,
name : 'deleteSMSTemplate' ,
description : '/docs/references/projects/delete-sms-template.md' ,
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_SMS_TEMPLATE ,
)
],
contentType : ContentType :: JSON
)
])
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2026-02-18 10:52:33 +00:00
-> param ( 'type' , '' , new WhiteList ( Config :: getParam ( 'locale-templates' )[ 'sms' ] ? ? [], true ), 'Template type' )
2024-06-07 00:54:51 +00:00
-> param ( 'locale' , '' , fn ( $localeCodes ) => new WhiteList ( $localeCodes ), 'Template locale' , false , [ 'localeCodes' ])
2023-04-19 08:44:22 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $type , string $locale , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2023-08-25 15:13:25 +00:00
throw new Exception ( Exception :: GENERAL_NOT_IMPLEMENTED );
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-04-19 08:44:22 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$templates = $project -> getAttribute ( 'templates' , []);
2024-10-08 07:54:40 +00:00
$template = $templates [ 'sms.' . $type . '-' . $locale ] ? ? null ;
2023-04-19 08:44:22 +00:00
if ( is_null ( $template )) {
2023-05-11 06:52:27 +00:00
throw new Exception ( Exception :: PROJECT_TEMPLATE_DEFAULT_DELETION );
2023-04-19 08:44:22 +00:00
}
unset ( $template [ 'sms.' . $type . '-' . $locale ]);
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'templates' , $templates ));
2023-04-19 08:44:22 +00:00
$response -> dynamic ( new Document ([
'type' => $type ,
'locale' => $locale ,
'message' => $template [ 'message' ]
]), Response :: MODEL_SMS_TEMPLATE );
});
2026-02-04 05:30:22 +00:00
Http :: delete ( '/v1/projects/:projectId/templates/email/:type/:locale' )
2025-04-14 18:40:48 +00:00
-> desc ( 'Delete custom email template' )
2023-04-19 08:44:22 +00:00
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
2025-03-31 05:48:17 +00:00
group : 'templates' ,
2025-01-17 04:31:39 +00:00
name : 'deleteEmailTemplate' ,
2025-01-20 03:16:00 +00:00
description : '/docs/references/projects/delete-email-template.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_EMAIL_TEMPLATE ,
)
],
contentType : ContentType :: JSON
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2026-02-18 10:52:33 +00:00
-> param ( 'type' , '' , new WhiteList ( Config :: getParam ( 'locale-templates' )[ 'email' ] ? ? [], true ), 'Template type' )
2024-06-07 00:54:51 +00:00
-> param ( 'locale' , '' , fn ( $localeCodes ) => new WhiteList ( $localeCodes ), 'Template locale' , false , [ 'localeCodes' ])
2023-04-19 08:44:22 +00:00
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
-> action ( function ( string $projectId , string $type , string $locale , Response $response , Database $dbForPlatform ) {
2024-10-08 07:54:40 +00:00
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
2023-04-19 08:44:22 +00:00
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$templates = $project -> getAttribute ( 'templates' , []);
2024-10-08 07:54:40 +00:00
$template = $templates [ 'email.' . $type . '-' . $locale ] ? ? null ;
2023-04-19 08:44:22 +00:00
if ( is_null ( $template )) {
2023-05-11 06:52:27 +00:00
throw new Exception ( Exception :: PROJECT_TEMPLATE_DEFAULT_DELETION );
2023-04-19 08:44:22 +00:00
}
unset ( $templates [ 'email.' . $type . '-' . $locale ]);
2024-12-12 10:30:26 +00:00
$project = $dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project -> setAttribute ( 'templates' , $templates ));
2023-04-19 08:44:22 +00:00
$response -> dynamic ( new Document ([
'type' => $type ,
'locale' => $locale ,
'senderName' => $template [ 'senderName' ],
'senderEmail' => $template [ 'senderEmail' ],
'subject' => $template [ 'subject' ],
'replyTo' => $template [ 'replyTo' ],
'message' => $template [ 'message' ]
]), Response :: MODEL_EMAIL_TEMPLATE );
2025-01-17 04:39:16 +00:00
});
2025-06-14 12:37:42 +00:00
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/projects/:projectId/auth/session-invalidation' )
2025-06-16 18:18:08 +00:00
-> desc ( 'Update invalidate session option of the project' )
-> groups ([ 'api' , 'projects' ])
-> label ( 'scope' , 'projects.write' )
-> label ( 'sdk' , new Method (
namespace : 'projects' ,
group : 'auth' ,
2025-06-16 19:10:32 +00:00
name : 'updateSessionInvalidation' ,
description : '/docs/references/projects/update-session-invalidation.md' ,
2025-06-16 18:18:08 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_OK ,
model : Response :: MODEL_PROJECT ,
)
]
))
2025-10-21 02:04:08 +00:00
-> param ( 'projectId' , '' , fn ( Database $dbForPlatform ) => new UID ( $dbForPlatform -> getAdapter () -> getMaxUIDLength ()), 'Project unique ID.' , false , [ 'dbForPlatform' ])
2025-06-16 19:10:32 +00:00
-> param ( 'enabled' , false , new Boolean (), 'Update authentication session invalidation status. Use this endpoint to enable or disable session invalidation on password change' )
2025-06-16 18:18:08 +00:00
-> inject ( 'response' )
-> inject ( 'dbForPlatform' )
2025-07-22 02:43:32 +00:00
-> action ( function ( string $projectId , bool $enabled , Response $response , Database $dbForPlatform ) {
2025-06-16 18:18:08 +00:00
$project = $dbForPlatform -> getDocument ( 'projects' , $projectId );
if ( $project -> isEmpty ()) {
throw new Exception ( Exception :: PROJECT_NOT_FOUND );
}
$auths = $project -> getAttribute ( 'auths' , []);
2025-07-22 02:43:32 +00:00
$auths [ 'invalidateSessions' ] = $enabled ;
2025-06-16 18:18:08 +00:00
$dbForPlatform -> updateDocument ( 'projects' , $project -> getId (), $project
2025-12-12 04:58:59 +00:00
-> setAttribute ( 'auths' , $auths ));
2025-06-16 18:18:08 +00:00
$response -> dynamic ( $project , Response :: MODEL_PROJECT );
});