2020-07-08 09:11:12 +00:00
< ? php
2020-12-26 12:10:14 +00:00
namespace Tests\E2E\Services\Projects ;
2020-07-08 09:11:12 +00:00
2023-04-13 20:20:03 +00:00
use Appwrite\Extend\Exception ;
2025-02-03 00:53:00 +00:00
use Appwrite\Tests\Async ;
2026-02-25 10:38:40 +00:00
use PHPUnit\Framework\Attributes\Group ;
2020-07-08 09:11:12 +00:00
use Tests\E2E\Client ;
2023-12-10 10:03:01 +00:00
use Tests\E2E\General\UsageTest ;
2024-03-06 17:34:21 +00:00
use Tests\E2E\Scopes\ProjectConsole ;
use Tests\E2E\Scopes\Scope ;
use Tests\E2E\Scopes\SideClient ;
2022-07-12 13:32:39 +00:00
use Utopia\Database\DateTime ;
2023-12-20 10:55:09 +00:00
use Utopia\Database\Document ;
2022-12-14 15:42:25 +00:00
use Utopia\Database\Helpers\ID ;
2026-03-19 15:00:42 +00:00
use Utopia\Database\Helpers\Permission ;
use Utopia\Database\Helpers\Role ;
2023-12-20 10:55:09 +00:00
use Utopia\Database\Query ;
2025-03-19 07:32:48 +00:00
use Utopia\System\System ;
2020-07-08 09:11:12 +00:00
class ProjectsConsoleClientTest extends Scope
{
use ProjectsBase ;
use ProjectConsole ;
use SideClient ;
2025-02-03 00:53:00 +00:00
use Async ;
2020-07-08 09:11:12 +00:00
2026-02-25 10:38:40 +00:00
#[Group('smtpAndTemplates')]
#[Group('projectsCRUD')]
public function testCreateProject () : void
2020-07-08 09:11:12 +00:00
{
/**
* Test for SUCCESS
*/
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'teamId' => ID :: unique (),
2020-07-08 09:11:12 +00:00
'name' => 'Project Test' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Project Test' , $team [ 'body' ][ 'name' ]);
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'projectId' => ID :: unique (),
2020-07-08 09:11:12 +00:00
'name' => 'Project Test' ,
'teamId' => $team [ 'body' ][ '$id' ],
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2020-07-08 09:11:12 +00:00
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Project Test' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( $team [ 'body' ][ '$id' ], $response [ 'body' ][ 'teamId' ]);
2026-02-17 06:24:22 +00:00
$this -> assertEquals ( PROJECT_STATUS_ACTIVE , $response [ 'body' ][ 'status' ]);
2020-07-08 09:11:12 +00:00
$this -> assertArrayHasKey ( 'platforms' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'webhooks' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'keys' , $response [ 'body' ]);
2026-03-14 08:21:22 +00:00
$this -> assertEquals ( false , $response [ 'body' ][ 'authDisposableEmails' ]);
$this -> assertEquals ( false , $response [ 'body' ][ 'authCanonicalEmails' ]);
$this -> assertEquals ( false , $response [ 'body' ][ 'authFreeEmails' ]);
2020-07-08 09:11:12 +00:00
2022-11-24 21:37:11 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $team [ 'body' ][ '$id' ],
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Project Test' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( $team [ 'body' ][ '$id' ], $response [ 'body' ][ 'teamId' ]);
2026-02-17 06:24:22 +00:00
$this -> assertEquals ( PROJECT_STATUS_ACTIVE , $response [ 'body' ][ 'status' ]);
2022-11-24 21:37:11 +00:00
$this -> assertArrayHasKey ( 'platforms' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'webhooks' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'keys' , $response [ 'body' ]);
2020-07-08 09:11:12 +00:00
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'projectId' => ID :: unique (),
2020-07-08 09:11:12 +00:00
'name' => '' ,
'teamId' => $team [ 'body' ][ '$id' ],
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2020-07-08 09:11:12 +00:00
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2021-08-09 12:47:16 +00:00
2020-07-08 09:11:12 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'projectId' => ID :: unique (),
2020-07-08 09:11:12 +00:00
'name' => 'Project Test' ,
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2020-07-08 09:11:12 +00:00
]);
2024-09-05 03:20:19 +00:00
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
2023-04-29 07:43:33 +00:00
}
2026-03-19 15:00:42 +00:00
public function testDeleteProjectWithMultiDB () : void
{
// Create a team and project
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'MultiDB Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'MultiDB Project' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$projectId = $project [ 'body' ][ '$id' ];
$projectAdminHeaders = array_merge ( $this -> getHeaders (), [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-mode' => 'admin' ,
]);
// Create legacy database and collection
$database = $this -> client -> call ( Client :: METHOD_POST , '/databases' , $projectAdminHeaders , [
'databaseId' => ID :: unique (),
'name' => 'Legacy DB' ,
]);
$this -> assertEquals ( 201 , $database [ 'headers' ][ 'status-code' ]);
$databaseId = $database [ 'body' ][ '$id' ];
$collection = $this -> client -> call ( Client :: METHOD_POST , '/databases/' . $databaseId . '/collections' , $projectAdminHeaders , [
'collectionId' => ID :: unique (),
'name' => 'Legacy Collection' ,
'documentSecurity' => true ,
'permissions' => [
Permission :: create ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $collection [ 'headers' ][ 'status-code' ]);
// Create documentsdb database and collection
$documentsDb = $this -> client -> call ( Client :: METHOD_POST , '/documentsdb' , $projectAdminHeaders , [
'databaseId' => ID :: unique (),
'name' => 'Documents DB' ,
]);
$this -> assertEquals ( 201 , $documentsDb [ 'headers' ][ 'status-code' ]);
$documentsDbId = $documentsDb [ 'body' ][ '$id' ];
$documentsCollection = $this -> client -> call ( Client :: METHOD_POST , '/documentsdb/' . $documentsDbId . '/collections' , $projectAdminHeaders , [
'collectionId' => ID :: unique (),
'name' => 'Documents Collection' ,
'documentSecurity' => true ,
'permissions' => [
Permission :: create ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $documentsCollection [ 'headers' ][ 'status-code' ]);
// Create vectorsdb database and collection
$vectorDb = $this -> client -> call ( Client :: METHOD_POST , '/vectorsdb' , $projectAdminHeaders , [
'databaseId' => ID :: unique (),
'name' => 'Vector DB' ,
]);
$this -> assertEquals ( 201 , $vectorDb [ 'headers' ][ 'status-code' ]);
$vectorDbId = $vectorDb [ 'body' ][ '$id' ];
$vectorCollection = $this -> client -> call ( Client :: METHOD_POST , '/vectorsdb/' . $vectorDbId . '/collections' , $projectAdminHeaders , [
'collectionId' => ID :: unique (),
'name' => 'Vector Collection' ,
'dimension' => 3 ,
'documentSecurity' => true ,
'permissions' => [
Permission :: create ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $vectorCollection [ 'headers' ][ 'status-code' ]);
// Delete project
$delete = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $delete [ 'headers' ][ 'status-code' ]);
// Ensure project is gone
$getProject = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $getProject [ 'headers' ][ 'status-code' ]);
}
2025-10-16 08:51:30 +00:00
public function testCreateDuplicateProject () : void
2023-04-29 07:43:33 +00:00
{
2025-10-16 08:51:30 +00:00
// Create a team
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Duplicate Test Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
// Create a project
$projectId = ID :: unique ();
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => $projectId ,
'name' => 'Original Project' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2023-04-29 07:43:33 +00:00
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => $projectId ,
'name' => 'Project Duplicate' ,
'teamId' => $teamId ,
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2023-04-29 07:43:33 +00:00
]);
2023-04-29 20:24:45 +00:00
$this -> assertEquals ( 409 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 409 , $response [ 'body' ][ 'code' ]);
2023-04-29 07:43:33 +00:00
$this -> assertEquals ( Exception :: PROJECT_ALREADY_EXISTS , $response [ 'body' ][ 'type' ]);
2020-07-08 09:11:12 +00:00
}
2026-02-25 10:38:40 +00:00
#[Group('projectsCRUD')]
2023-05-02 07:28:46 +00:00
public function testTransferProjectTeam ()
{
/**
* Test for SUCCESS
*/
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
2023-05-10 06:46:30 +00:00
'name' => 'Team 1' ,
2023-05-02 07:28:46 +00:00
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
2023-05-10 06:46:30 +00:00
$this -> assertEquals ( 'Team 1' , $team [ 'body' ][ 'name' ]);
2023-05-02 07:28:46 +00:00
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$team1 = $team [ 'body' ][ '$id' ];
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
2023-05-10 06:46:30 +00:00
'name' => 'Team 2' ,
2023-05-02 07:28:46 +00:00
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
2023-05-10 06:46:30 +00:00
$this -> assertEquals ( 'Team 2' , $team [ 'body' ][ 'name' ]);
2023-05-02 07:28:46 +00:00
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$team2 = $team [ 'body' ][ '$id' ];
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
2023-05-10 06:46:30 +00:00
'name' => 'Team 1 Project' ,
2023-05-02 07:28:46 +00:00
'teamId' => $team1 ,
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' ),
2023-05-02 07:28:46 +00:00
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2023-05-10 06:46:30 +00:00
$this -> assertEquals ( 'Team 1 Project' , $response [ 'body' ][ 'name' ]);
2023-05-02 07:28:46 +00:00
$this -> assertEquals ( $team1 , $response [ 'body' ][ 'teamId' ]);
$this -> assertArrayHasKey ( 'platforms' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'webhooks' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'keys' , $response [ 'body' ]);
$projectId = $response [ 'body' ][ '$id' ];
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $projectId . '/team' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => $team2 ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2023-05-10 06:46:30 +00:00
$this -> assertEquals ( 'Team 1 Project' , $response [ 'body' ][ 'name' ]);
2023-05-02 07:28:46 +00:00
$this -> assertEquals ( $team2 , $response [ 'body' ][ 'teamId' ]);
2020-07-08 09:11:12 +00:00
}
2026-02-25 10:38:40 +00:00
#[Group('projectsCRUD')]
public function testListProject () : void
2020-07-08 15:20:18 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2020-07-08 15:20:18 +00:00
/**
* Test for SUCCESS
*/
2021-09-23 07:01:10 +00:00
2020-07-08 15:20:18 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
2026-02-25 10:38:40 +00:00
$this -> assertGreaterThan ( 0 , count ( $response [ 'body' ][ 'projects' ]));
2020-07-08 15:20:18 +00:00
2021-09-23 07:01:10 +00:00
/**
* Test search queries
*/
2021-09-21 08:22:13 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders (), [
'search' => $id
]));
2025-12-12 07:16:49 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertGreaterThan ( 0 , $response [ 'body' ][ 'total' ]);
2021-09-23 07:01:10 +00:00
$this -> assertIsArray ( $response [ 'body' ][ 'projects' ]);
2021-09-21 08:22:13 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders (), [
'search' => 'Project Test'
]));
2021-09-23 07:01:10 +00:00
$this -> assertEquals ( $response [ 'headers' ][ 'status-code' ], 200 );
2026-02-25 10:38:40 +00:00
$this -> assertGreaterThan ( 0 , $response [ 'body' ][ 'total' ]);
2021-09-23 07:01:10 +00:00
$this -> assertIsArray ( $response [ 'body' ][ 'projects' ]);
2021-09-21 08:22:13 +00:00
2021-08-09 12:47:16 +00:00
/**
2022-08-31 16:00:14 +00:00
* Test pagination
2021-08-09 12:47:16 +00:00
*/
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'teamId' => ID :: unique (),
2021-08-09 12:47:16 +00:00
'name' => 'Project Test 2' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Project Test 2' , $team [ 'body' ][ 'name' ]);
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'projectId' => ID :: unique (),
2021-08-09 12:47:16 +00:00
'name' => 'Project Test 2' ,
'teamId' => $team [ 'body' ][ '$id' ],
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2021-08-09 12:47:16 +00:00
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Project Test 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( $team [ 'body' ][ '$id' ], $response [ 'body' ][ 'teamId' ]);
$this -> assertArrayHasKey ( 'platforms' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'webhooks' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'keys' , $response [ 'body' ]);
2022-08-31 16:00:14 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
2022-10-03 07:16:49 +00:00
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: equal ( 'teamId' , [ $team [ 'body' ][ '$id' ]]) -> toString (),
],
2022-10-03 07:16:49 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertCount ( 1 , $response [ 'body' ][ 'projects' ]);
2022-10-03 07:54:55 +00:00
$this -> assertEquals ( $team [ 'body' ][ '$id' ], $response [ 'body' ][ 'projects' ][ 0 ][ 'teamId' ]);
2022-10-03 07:16:49 +00:00
2022-08-31 16:00:14 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: limit ( 1 ) -> toString (),
],
2022-08-31 16:00:14 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertCount ( 1 , $response [ 'body' ][ 'projects' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
2026-02-25 10:38:40 +00:00
Query :: offset ( 1 ) -> toString (),
2023-12-20 10:55:09 +00:00
],
2022-08-31 16:00:14 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: equal ( 'name' , [ 'Project Test 2' ]) -> toString (),
],
2022-08-31 16:00:14 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
2026-02-25 10:38:40 +00:00
$this -> assertGreaterThanOrEqual ( 1 , count ( $response [ 'body' ][ 'projects' ]));
2022-08-31 16:00:14 +00:00
$this -> assertEquals ( 'Project Test 2' , $response [ 'body' ][ 'projects' ][ 0 ][ 'name' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: orderDesc () -> toString (),
],
2022-08-31 16:00:14 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
2026-02-25 10:38:40 +00:00
$this -> assertGreaterThan ( 0 , count ( $response [ 'body' ][ 'projects' ]));
2022-08-31 16:00:14 +00:00
2021-08-09 12:47:16 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
2026-02-25 10:38:40 +00:00
$this -> assertGreaterThan ( 0 , count ( $response [ 'body' ][ 'projects' ]));
2021-08-09 12:47:16 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2022-04-18 16:21:45 +00:00
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: cursorAfter ( new Document ([ '$id' => $response [ 'body' ][ 'projects' ][ 0 ][ '$id' ]])) -> toString (),
],
2021-08-09 12:47:16 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
2021-10-05 10:30:33 +00:00
2020-07-08 15:20:18 +00:00
/**
* Test for FAILURE
*/
2021-10-05 10:30:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2022-04-18 16:21:45 +00:00
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: cursorAfter ( new Document ([ '$id' => 'unknown' ])) -> toString (),
],
2021-10-05 10:30:33 +00:00
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2020-07-08 15:20:18 +00:00
}
2026-02-25 10:38:40 +00:00
#[Group('projectsCRUD')]
2025-12-19 08:43:52 +00:00
public function testListProjectsQuerySelect () : void
{
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Query Select Test Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Query Select Test Project' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$projectId = $project [ 'body' ][ '$id' ];
/**
* Test Query . select - basic fields
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: select ([ '$id' , 'name' ]) -> toString (),
],
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertGreaterThan ( 0 , count ( $response [ 'body' ][ 'projects' ]));
$project = $response [ 'body' ][ 'projects' ][ 0 ];
$this -> assertArrayHasKey ( '$id' , $project );
$this -> assertArrayHasKey ( 'name' , $project );
$this -> assertArrayNotHasKey ( 'platforms' , $project );
$this -> assertArrayNotHasKey ( 'webhooks' , $project );
$this -> assertArrayNotHasKey ( 'keys' , $project );
$this -> assertArrayNotHasKey ( 'devKeys' , $project );
$this -> assertArrayNotHasKey ( 'oAuthProviders' , $project );
$this -> assertArrayNotHasKey ( 'smtpEnabled' , $project );
$this -> assertArrayNotHasKey ( 'smtpHost' , $project );
$this -> assertArrayNotHasKey ( 'authLimit' , $project );
$this -> assertArrayNotHasKey ( 'authDuration' , $project );
/**
* Test Query . select - multiple fields
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: select ([ '$id' , 'name' , 'teamId' , 'description' , '$createdAt' , '$updatedAt' ]) -> toString (),
],
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertGreaterThan ( 0 , count ( $response [ 'body' ][ 'projects' ]));
$project = $response [ 'body' ][ 'projects' ][ 0 ];
$this -> assertArrayHasKey ( '$id' , $project );
$this -> assertArrayHasKey ( 'name' , $project );
$this -> assertArrayHasKey ( 'teamId' , $project );
$this -> assertArrayHasKey ( 'description' , $project );
$this -> assertArrayHasKey ( '$createdAt' , $project );
$this -> assertArrayHasKey ( '$updatedAt' , $project );
$this -> assertArrayNotHasKey ( 'platforms' , $project );
$this -> assertArrayNotHasKey ( 'webhooks' , $project );
$this -> assertArrayNotHasKey ( 'keys' , $project );
$this -> assertArrayNotHasKey ( 'devKeys' , $project );
$this -> assertArrayNotHasKey ( 'oAuthProviders' , $project );
$this -> assertArrayNotHasKey ( 'smtpEnabled' , $project );
$this -> assertArrayNotHasKey ( 'authLimit' , $project );
/**
* Test Query . select combined with filters
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: select ([ '$id' , 'name' , 'teamId' ]) -> toString (),
Query :: equal ( 'name' , [ 'Query Select Test Project' ]) -> toString (),
],
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertCount ( 1 , $response [ 'body' ][ 'projects' ]);
$project = $response [ 'body' ][ 'projects' ][ 0 ];
$this -> assertArrayHasKey ( '$id' , $project );
$this -> assertArrayHasKey ( 'name' , $project );
$this -> assertArrayHasKey ( 'teamId' , $project );
$this -> assertEquals ( 'Query Select Test Project' , $project [ 'name' ]);
$this -> assertEquals ( $teamId , $project [ 'teamId' ]);
$this -> assertArrayNotHasKey ( 'platforms' , $project );
$this -> assertArrayNotHasKey ( 'webhooks' , $project );
$this -> assertArrayNotHasKey ( 'keys' , $project );
$this -> assertArrayNotHasKey ( 'devKeys' , $project );
$this -> assertArrayNotHasKey ( 'oAuthProviders' , $project );
$this -> assertArrayNotHasKey ( 'smtpEnabled' , $project );
$this -> assertArrayNotHasKey ( 'authLimit' , $project );
/**
* Test Query . select combined with limit
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: select ([ '$id' , 'name' ]) -> toString (),
Query :: limit ( 2 ) -> toString (),
],
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertLessThanOrEqual ( 2 , count ( $response [ 'body' ][ 'projects' ]));
foreach ( $response [ 'body' ][ 'projects' ] as $p ) {
$this -> assertArrayHasKey ( '$id' , $p );
$this -> assertArrayHasKey ( 'name' , $p );
$this -> assertArrayNotHasKey ( 'platforms' , $p );
$this -> assertArrayNotHasKey ( 'webhooks' , $p );
$this -> assertArrayNotHasKey ( 'keys' , $p );
$this -> assertArrayNotHasKey ( 'devKeys' , $p );
$this -> assertArrayNotHasKey ( 'oAuthProviders' , $p );
$this -> assertArrayNotHasKey ( 'smtpEnabled' , $p );
$this -> assertArrayNotHasKey ( 'authLimit' , $p );
}
/**
* Test Query . select with subquery attributes ( platforms , webhooks , etc . )
* When explicitly selected , subqueries should still run
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: select ([ '$id' , 'name' , 'platforms' ]) -> toString (),
],
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertGreaterThan ( 0 , count ( $response [ 'body' ][ 'projects' ]));
$project = $response [ 'body' ][ 'projects' ][ 0 ];
$this -> assertArrayHasKey ( '$id' , $project );
$this -> assertArrayHasKey ( 'name' , $project );
$this -> assertArrayHasKey ( 'platforms' , $project );
$this -> assertIsArray ( $project [ 'platforms' ]);
$this -> assertArrayNotHasKey ( 'webhooks' , $project );
$this -> assertArrayNotHasKey ( 'keys' , $project );
$this -> assertArrayNotHasKey ( 'devKeys' , $project );
$this -> assertArrayNotHasKey ( 'oAuthProviders' , $project );
$this -> assertArrayNotHasKey ( 'smtpEnabled' , $project );
$this -> assertArrayNotHasKey ( 'authLimit' , $project );
/**
* Test Query . select with expanded attributes
* webhooks and keys should load their subquery data when selected
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: select ([ '$id' , 'name' , 'webhooks' , 'keys' ]) -> toString (),
],
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertGreaterThan ( 0 , count ( $response [ 'body' ][ 'projects' ]));
$project = $response [ 'body' ][ 'projects' ][ 0 ];
$this -> assertArrayHasKey ( '$id' , $project );
$this -> assertArrayHasKey ( 'name' , $project );
$this -> assertArrayHasKey ( 'webhooks' , $project );
$this -> assertArrayHasKey ( 'keys' , $project );
$this -> assertIsArray ( $project [ 'webhooks' ]);
$this -> assertIsArray ( $project [ 'keys' ]);
$this -> assertArrayNotHasKey ( 'platforms' , $project );
$this -> assertArrayNotHasKey ( 'devKeys' , $project );
$this -> assertArrayNotHasKey ( 'smtpEnabled' , $project );
$this -> assertArrayNotHasKey ( 'authLimit' , $project );
2025-12-19 10:22:19 +00:00
/**
* Test Query . select with wildcard '*'
* Should return all fields like no select query
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: select ([ '*' ]) -> toString (),
],
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertGreaterThan ( 0 , count ( $response [ 'body' ][ 'projects' ]));
$project = $response [ 'body' ][ 'projects' ][ 0 ];
$this -> assertArrayHasKey ( '$id' , $project );
$this -> assertArrayHasKey ( 'name' , $project );
$this -> assertArrayHasKey ( 'teamId' , $project );
$this -> assertArrayHasKey ( 'platforms' , $project );
$this -> assertArrayHasKey ( 'webhooks' , $project );
$this -> assertArrayHasKey ( 'keys' , $project );
$this -> assertArrayHasKey ( 'devKeys' , $project );
$this -> assertArrayHasKey ( 'oAuthProviders' , $project );
$this -> assertArrayHasKey ( 'smtpEnabled' , $project );
$this -> assertArrayHasKey ( 'smtpHost' , $project );
$this -> assertArrayHasKey ( 'authLimit' , $project );
$this -> assertArrayHasKey ( 'authDuration' , $project );
2025-12-19 08:43:52 +00:00
/**
* Test Query . select with invalid attribute
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: select ([ '$id' , 'invalidAttribute' ]) -> toString (),
],
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Invalid `queries` param: Invalid query: Attribute not found in schema: invalidAttribute' , $response [ 'body' ][ 'message' ]);
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
}
2025-10-16 08:51:30 +00:00
public function testGetProject () : void
2020-07-08 09:11:12 +00:00
{
2025-10-16 08:51:30 +00:00
// Create a team
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Get Project Test Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
// Create a project
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $team [ 'body' ][ '$id' ],
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$id = $response [ 'body' ][ '$id' ];
2025-09-16 16:13:38 +00:00
2020-07-08 09:11:12 +00:00
/**
* Test for SUCCESS
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
2020-07-08 09:11:12 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertEquals ( $id , $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Project Test' , $response [ 'body' ][ 'name' ]);
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/empty' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$projectId = str_repeat ( 'very_long_id' , 25 ); // 12 chars * 25 = 300 chars > MongoDB max (255)
2020-07-08 09:11:12 +00:00
2025-08-11 19:05:18 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId , array_merge ([
2020-07-08 09:11:12 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2020-07-08 09:11:12 +00:00
}
2020-07-08 15:20:18 +00:00
2026-02-25 10:38:40 +00:00
public function testGetProjectUsage () : void
2020-07-08 15:20:18 +00:00
{
2024-01-09 11:58:36 +00:00
$this -> markTestIncomplete (
'This test is failing right now due to functions collection.'
);
2020-07-08 15:20:18 +00:00
/**
* Test for SUCCESS
*/
2023-10-25 07:39:59 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/project/usage' , array_merge ([
2020-07-08 15:20:18 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2023-12-10 10:03:01 +00:00
], $this -> getHeaders ()), [
'startDate' => UsageTest :: getToday (),
'endDate' => UsageTest :: getTomorrow (),
]);
2020-07-08 15:20:18 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2023-12-10 10:03:01 +00:00
$this -> assertEquals ( 8 , count ( $response [ 'body' ]));
2020-07-08 15:20:18 +00:00
$this -> assertNotEmpty ( $response [ 'body' ]);
2023-08-20 12:29:43 +00:00
$this -> assertIsArray ( $response [ 'body' ][ 'requests' ]);
2021-08-29 08:11:29 +00:00
$this -> assertIsArray ( $response [ 'body' ][ 'network' ]);
2023-11-26 20:57:57 +00:00
$this -> assertIsNumeric ( $response [ 'body' ][ 'executionsTotal' ]);
2025-05-05 09:15:55 +00:00
$this -> assertIsNumeric ( $response [ 'body' ][ 'rowsTotal' ]);
2023-11-26 20:57:57 +00:00
$this -> assertIsNumeric ( $response [ 'body' ][ 'databasesTotal' ]);
$this -> assertIsNumeric ( $response [ 'body' ][ 'bucketsTotal' ]);
$this -> assertIsNumeric ( $response [ 'body' ][ 'usersTotal' ]);
$this -> assertIsNumeric ( $response [ 'body' ][ 'filesStorageTotal' ]);
2024-06-11 05:36:32 +00:00
$this -> assertIsNumeric ( $response [ 'body' ][ 'deploymentStorageTotal' ]);
2025-01-09 16:37:26 +00:00
$this -> assertIsNumeric ( $response [ 'body' ][ 'authPhoneTotal' ]);
$this -> assertIsNumeric ( $response [ 'body' ][ 'authPhoneEstimate' ]);
2023-11-26 20:57:57 +00:00
2020-07-08 15:20:18 +00:00
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/empty' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/id-is-really-long-id-is-really-long-id-is-really-long-id-is-really-long' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2020-07-09 09:13:14 +00:00
}
2025-10-16 08:55:12 +00:00
public function testUpdateProject () : void
2020-07-09 09:13:14 +00:00
{
2025-10-16 08:55:12 +00:00
// Create a team
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Update Project Test Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
// Create a project
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$id = $response [ 'body' ][ '$id' ];
2020-07-09 09:13:14 +00:00
/**
* Test for SUCCESS
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id , array_merge ([
2020-07-09 09:13:14 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'projectId' => ID :: unique (),
2020-07-09 09:13:14 +00:00
'name' => 'Project Test 2' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Project Test 2' , $response [ 'body' ][ 'name' ]);
2020-11-20 23:31:17 +00:00
$this -> assertArrayHasKey ( 'platforms' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'webhooks' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'keys' , $response [ 'body' ]);
2020-07-09 09:13:14 +00:00
$projectId = $response [ 'body' ][ '$id' ];
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'projectId' => ID :: unique (),
2020-07-09 09:13:14 +00:00
'name' => '' ,
]);
2024-09-05 03:22:10 +00:00
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
2020-07-09 09:13:14 +00:00
}
2026-02-25 10:38:40 +00:00
#[Group('smtpAndTemplates')]
public function testUpdateProjectSMTP () : void
2023-03-10 02:46:34 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
2023-03-10 02:44:43 +00:00
$id = $data [ 'projectId' ];
2025-12-12 04:58:59 +00:00
$smtpHost = System :: getEnv ( '_APP_SMTP_HOST' , " maildev " );
$smtpPort = intval ( System :: getEnv ( '_APP_SMTP_PORT' , " 1025 " ));
$smtpUsername = System :: getEnv ( '_APP_SMTP_USERNAME' , 'user' );
$smtpPassword = System :: getEnv ( '_APP_SMTP_PASSWORD' , 'password' );
/**
* Test for SUCCESS : Valid Credentials
*/
2023-03-10 02:44:43 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/smtp' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'enabled' => true ,
2023-08-30 04:30:44 +00:00
'senderEmail' => 'mailer@appwrite.io' ,
'senderName' => 'Mailer' ,
2025-12-12 04:58:59 +00:00
'host' => $smtpHost ,
'port' => $smtpPort ,
'username' => $smtpUsername ,
'password' => $smtpPassword ,
2023-03-10 02:44:43 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertTrue ( $response [ 'body' ][ 'smtpEnabled' ]);
2023-08-30 04:30:44 +00:00
$this -> assertEquals ( 'mailer@appwrite.io' , $response [ 'body' ][ 'smtpSenderEmail' ]);
$this -> assertEquals ( 'Mailer' , $response [ 'body' ][ 'smtpSenderName' ]);
2025-12-12 04:58:59 +00:00
$this -> assertEquals ( $smtpHost , $response [ 'body' ][ 'smtpHost' ]);
$this -> assertEquals ( $smtpPort , $response [ 'body' ][ 'smtpPort' ]);
$this -> assertEquals ( $smtpUsername , $response [ 'body' ][ 'smtpUsername' ]);
$this -> assertEquals ( $smtpPassword , $response [ 'body' ][ 'smtpPassword' ]);
2023-03-10 02:44:43 +00:00
$this -> assertEquals ( '' , $response [ 'body' ][ 'smtpSecure' ]);
2023-03-14 07:21:56 +00:00
2025-12-12 04:58:59 +00:00
// Check the project
2023-03-14 07:21:56 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertTrue ( $response [ 'body' ][ 'smtpEnabled' ]);
2023-08-30 04:30:44 +00:00
$this -> assertEquals ( 'mailer@appwrite.io' , $response [ 'body' ][ 'smtpSenderEmail' ]);
$this -> assertEquals ( 'Mailer' , $response [ 'body' ][ 'smtpSenderName' ]);
2025-12-12 04:58:59 +00:00
$this -> assertEquals ( $smtpHost , $response [ 'body' ][ 'smtpHost' ]);
$this -> assertEquals ( $smtpPort , $response [ 'body' ][ 'smtpPort' ]);
$this -> assertEquals ( $smtpUsername , $response [ 'body' ][ 'smtpUsername' ]);
$this -> assertEquals ( $smtpPassword , $response [ 'body' ][ 'smtpPassword' ]);
2023-03-14 07:21:56 +00:00
$this -> assertEquals ( '' , $response [ 'body' ][ 'smtpSecure' ]);
2023-03-17 06:37:16 +00:00
2025-12-12 04:58:59 +00:00
/**
* Test for FAILURE : Invalid Credentials
*/
2025-12-08 14:52:18 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/smtp' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'enabled' => true ,
'senderEmail' => 'fail@appwrite.io' ,
'senderName' => 'Failing Mailer' ,
2025-12-12 04:58:59 +00:00
'host' => $smtpHost ,
'port' => $smtpPort ,
2025-12-08 14:52:18 +00:00
'username' => 'invalid-user' ,
'password' => 'bad-password' ,
]);
2025-12-12 04:58:59 +00:00
2025-12-08 14:52:18 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( Exception :: PROJECT_SMTP_CONFIG_INVALID , $response [ 'body' ][ 'type' ]);
2025-12-12 04:58:59 +00:00
$this -> assertStringContainsStringIgnoringCase ( 'Could not authenticate' , $response [ 'body' ][ 'message' ]);
2023-03-14 07:21:56 +00:00
}
2026-02-25 10:38:40 +00:00
#[Group('smtpAndTemplates')]
2025-10-16 08:55:12 +00:00
public function testCreateProjectSMTPTests () : void
2023-12-19 15:19:57 +00:00
{
2025-12-12 04:58:59 +00:00
$smtpHost = System :: getEnv ( '_APP_SMTP_HOST' , " maildev " );
$smtpPort = intval ( System :: getEnv ( '_APP_SMTP_PORT' , " 1025 " ));
$smtpUsername = System :: getEnv ( '_APP_SMTP_USERNAME' , 'user' );
$smtpPassword = System :: getEnv ( '_APP_SMTP_PASSWORD' , 'password' );
2025-10-16 08:55:12 +00:00
// Create a team
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Create Project SMTP Tests Test Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
// Create a project
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$id = $response [ 'body' ][ '$id' ];
2023-12-19 22:31:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/smtp/tests' , array_merge ([
2023-12-19 15:19:57 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2024-06-20 14:49:56 +00:00
'emails' => [ 'testuser@appwrite.io' , 'testusertwo@appwrite.io' ],
2024-01-15 11:00:33 +00:00
'senderEmail' => 'custommailer@appwrite.io' ,
'senderName' => 'Custom Mailer' ,
'replyTo' => 'reply@appwrite.io' ,
2025-12-12 04:58:59 +00:00
'host' => $smtpHost ,
'port' => $smtpPort ,
'username' => $smtpUsername ,
'password' => $smtpPassword ,
2023-12-19 15:19:57 +00:00
]);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
2026-03-05 12:19:18 +00:00
$smtpProbe = function ( $email ) {
$this -> assertEquals ( 'Custom SMTP email sample' , $email [ 'subject' ]);
};
$email1 = $this -> getLastEmailByAddress ( 'testuser@appwrite.io' , $smtpProbe );
$email2 = $this -> getLastEmailByAddress ( 'testusertwo@appwrite.io' , $smtpProbe );
$this -> assertEquals ( 'custommailer@appwrite.io' , $email1 [ 'from' ][ 0 ][ 'address' ]);
$this -> assertEquals ( 'Custom Mailer' , $email1 [ 'from' ][ 0 ][ 'name' ]);
$this -> assertEquals ( 'reply@appwrite.io' , $email1 [ 'replyTo' ][ 0 ][ 'address' ]);
$this -> assertEquals ( 'Custom Mailer' , $email1 [ 'replyTo' ][ 0 ][ 'name' ]);
$this -> assertEquals ( 'Custom SMTP email sample' , $email1 [ 'subject' ]);
$this -> assertStringContainsStringIgnoringCase ( 'working correctly' , $email1 [ 'text' ]);
$this -> assertStringContainsStringIgnoringCase ( 'working correctly' , $email1 [ 'html' ]);
$this -> assertStringContainsStringIgnoringCase ( '251 Little Falls Drive' , $email1 [ 'text' ]);
$this -> assertStringContainsStringIgnoringCase ( '251 Little Falls Drive' , $email1 [ 'html' ]);
$this -> assertEquals ( 'custommailer@appwrite.io' , $email2 [ 'from' ][ 0 ][ 'address' ]);
2023-12-19 21:39:40 +00:00
2024-01-17 16:47:26 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/smtp/tests' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2024-06-20 14:49:56 +00:00
'emails' => [ 'u1@appwrite.io' , 'u2@appwrite.io' , 'u3@appwrite.io' , 'u4@appwrite.io' , 'u5@appwrite.io' , 'u6@appwrite.io' , 'u7@appwrite.io' , 'u8@appwrite.io' , 'u9@appwrite.io' , 'u10@appwrite.io' ],
2024-01-17 16:47:26 +00:00
'senderEmail' => 'custommailer@appwrite.io' ,
'senderName' => 'Custom Mailer' ,
'replyTo' => 'reply@appwrite.io' ,
2025-12-12 04:58:59 +00:00
'host' => $smtpHost ,
'port' => $smtpPort ,
'username' => $smtpUsername ,
'password' => $smtpPassword ,
2024-01-17 16:47:26 +00:00
]);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/smtp/tests' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2024-06-20 14:49:56 +00:00
'emails' => [ 'u1@appwrite.io' , 'u2@appwrite.io' , 'u3@appwrite.io' , 'u4@appwrite.io' , 'u5@appwrite.io' , 'u6@appwrite.io' , 'u7@appwrite.io' , 'u8@appwrite.io' , 'u9@appwrite.io' , 'u10@appwrite.io' , 'u11@appwrite.io' ],
2024-01-17 16:47:26 +00:00
'senderEmail' => 'custommailer@appwrite.io' ,
'senderName' => 'Custom Mailer' ,
'replyTo' => 'reply@appwrite.io' ,
2025-12-12 04:58:59 +00:00
'host' => $smtpHost ,
'port' => $smtpPort ,
'username' => $smtpUsername ,
'password' => $smtpPassword ,
2024-01-17 16:47:26 +00:00
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2023-12-19 15:19:57 +00:00
}
2026-02-25 10:38:40 +00:00
#[Group('smtpAndTemplates')]
public function testUpdateTemplates () : void
2023-03-14 07:21:56 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
2023-03-14 07:21:56 +00:00
$id = $data [ 'projectId' ];
2023-03-14 09:13:43 +00:00
/** Get Default Email Template */
2023-04-18 07:13:52 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/templates/email/verification/en-us' , array_merge ([
2023-03-14 07:21:56 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-12-12 04:58:59 +00:00
$this -> assertEquals ( 'Account Verification for {{project}}' , $response [ 'body' ][ 'subject' ]);
2023-08-30 05:31:21 +00:00
$this -> assertEquals ( '' , $response [ 'body' ][ 'senderEmail' ]);
2023-03-14 07:21:56 +00:00
$this -> assertEquals ( 'verification' , $response [ 'body' ][ 'type' ]);
2023-04-18 07:13:52 +00:00
$this -> assertEquals ( 'en-us' , $response [ 'body' ][ 'locale' ]);
2023-03-14 07:24:03 +00:00
2023-03-14 09:13:43 +00:00
/** Update Email template */
2023-04-18 07:13:52 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/templates/email/verification/en-us' , array_merge ([
2023-03-14 07:21:56 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'subject' => 'Please verify your email' ,
'message' => 'Please verify your email {{url}}' ,
'senderName' => 'Appwrite Custom' ,
'senderEmail' => 'custom@appwrite.io' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Please verify your email' , $response [ 'body' ][ 'subject' ]);
$this -> assertEquals ( 'Appwrite Custom' , $response [ 'body' ][ 'senderName' ]);
$this -> assertEquals ( 'custom@appwrite.io' , $response [ 'body' ][ 'senderEmail' ]);
$this -> assertEquals ( 'verification' , $response [ 'body' ][ 'type' ]);
2023-04-18 07:13:52 +00:00
$this -> assertEquals ( 'en-us' , $response [ 'body' ][ 'locale' ]);
2023-03-14 07:21:56 +00:00
$this -> assertEquals ( 'Please verify your email {{url}}' , $response [ 'body' ][ 'message' ]);
2023-03-14 09:13:43 +00:00
/** Get Updated Email Template */
2023-04-18 07:13:52 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/templates/email/verification/en-us' , array_merge ([
2023-03-14 07:21:56 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Please verify your email' , $response [ 'body' ][ 'subject' ]);
$this -> assertEquals ( 'Appwrite Custom' , $response [ 'body' ][ 'senderName' ]);
$this -> assertEquals ( 'custom@appwrite.io' , $response [ 'body' ][ 'senderEmail' ]);
$this -> assertEquals ( 'verification' , $response [ 'body' ][ 'type' ]);
2023-04-18 07:13:52 +00:00
$this -> assertEquals ( 'en-us' , $response [ 'body' ][ 'locale' ]);
2023-03-14 07:21:56 +00:00
$this -> assertEquals ( 'Please verify your email {{url}}' , $response [ 'body' ][ 'message' ]);
2023-03-10 02:44:43 +00:00
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectAuthDuration () : void
2022-11-01 11:15:45 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
2022-11-01 11:15:45 +00:00
$id = $data [ 'projectId' ];
2022-11-15 10:19:35 +00:00
// Check defaults
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-11-04 07:51:03 +00:00
$this -> assertEquals ( TOKEN_EXPIRATION_LOGIN_LONG , $response [ 'body' ][ 'authDuration' ]); // 1 Year
2022-11-15 10:19:35 +00:00
2022-11-01 11:15:45 +00:00
/**
* Test for SUCCESS
*/
2022-11-14 13:00:50 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/duration' , array_merge ([
2022-11-01 11:15:45 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-10 10:43:22 +00:00
'duration' => 10 , // Set session duration to 10 seconds
2022-11-01 11:15:45 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2025-12-12 05:24:33 +00:00
$this -> assertEquals ( 'Project Test' , $response [ 'body' ][ 'name' ]);
2022-11-01 11:15:45 +00:00
$this -> assertArrayHasKey ( 'platforms' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'webhooks' , $response [ 'body' ]);
$this -> assertArrayHasKey ( 'keys' , $response [ 'body' ]);
2026-02-10 10:43:22 +00:00
$this -> assertEquals ( 10 , $response [ 'body' ][ 'authDuration' ]);
2022-11-01 11:15:45 +00:00
$projectId = $response [ 'body' ][ '$id' ];
// Create New User
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
], $this -> getHeaders ()), [
'userId' => 'unique()' ,
'email' => 'test' . rand ( 0 , 9999 ) . '@example.com' ,
'password' => 'password' ,
'name' => 'Test User' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$userEmail = $response [ 'body' ][ 'email' ];
// Create New User Session
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
]), [
'email' => $userEmail ,
'password' => 'password' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$sessionCookie = $response [ 'headers' ][ 'set-cookie' ];
// Test for SUCCESS
$response = $this -> client -> call ( Client :: METHOD_GET , '/account' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'Cookie' => $sessionCookie ,
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-10 10:43:22 +00:00
// Eventually session expires, within 15 seconds (10+variance)
$this -> assertEventually ( function () use ( $projectId , $sessionCookie ) {
// Get User
$response = $this -> client -> call ( Client :: METHOD_GET , '/account' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'Cookie' => $sessionCookie ,
]));
2022-11-01 11:15:45 +00:00
2026-02-10 10:43:22 +00:00
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
}, timeoutMs : 15 * 1000 );
2022-11-01 11:15:45 +00:00
2026-02-10 10:43:22 +00:00
// Set session duration to 10min
2024-01-15 20:04:36 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/duration' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-10 10:43:22 +00:00
'duration' => 600 , // seconds
2024-01-15 20:04:36 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-10 10:43:22 +00:00
$this -> assertEquals ( 600 , $response [ 'body' ][ 'authDuration' ]);
2024-01-15 20:04:36 +00:00
2026-02-10 11:01:38 +00:00
// Ensure session is still expired (new duration only affects new sessions)
2024-01-15 20:04:36 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/account' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'Cookie' => $sessionCookie ,
]));
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
2022-11-01 11:15:45 +00:00
// Return project back to normal
2022-11-14 13:00:50 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/duration' , array_merge ([
2022-11-01 11:15:45 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2025-11-04 07:51:03 +00:00
'duration' => TOKEN_EXPIRATION_LOGIN_LONG ,
2022-11-01 11:15:45 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$projectId = $response [ 'body' ][ '$id' ];
2022-11-01 11:34:56 +00:00
// Check project is back to normal
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-11-04 07:51:03 +00:00
$this -> assertEquals ( TOKEN_EXPIRATION_LOGIN_LONG , $response [ 'body' ][ 'authDuration' ]); // 1 Year
2022-11-01 11:15:45 +00:00
}
2025-10-16 08:51:30 +00:00
public function testUpdateProjectInvalidateSessions () : void
2025-06-14 12:37:42 +00:00
{
2025-10-16 08:51:30 +00:00
// Create a team for the test project
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Session Invalidation Test Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
// Create a test project
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Session Invalidation Test Project' ,
'teamId' => $team [ 'body' ][ '$id' ],
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$id = $response [ 'body' ][ '$id' ];
2025-06-14 12:37:42 +00:00
// Check defaults
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-06-16 19:10:32 +00:00
$this -> assertTrue ( $response [ 'body' ][ 'authInvalidateSessions' ]);
2025-06-14 12:37:42 +00:00
2025-06-16 17:35:52 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/session-invalidation' , array_merge ([
2025-06-14 12:37:42 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2025-06-16 19:10:32 +00:00
'enabled' => false ,
2025-06-14 12:37:42 +00:00
]);
2025-06-16 19:10:32 +00:00
$this -> assertFalse ( $response [ 'body' ][ 'authInvalidateSessions' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertFalse ( $response [ 'body' ][ 'authInvalidateSessions' ]);
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/session-invalidation' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'enabled' => true ,
]);
$this -> assertTrue ( $response [ 'body' ][ 'authInvalidateSessions' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertTrue ( $response [ 'body' ][ 'authInvalidateSessions' ]);
2025-06-14 12:37:42 +00:00
}
2025-10-16 08:59:57 +00:00
public function testUpdateProjectOAuth () : void
2020-07-09 09:13:14 +00:00
{
2025-10-16 08:59:57 +00:00
// Create a team
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Update Project OAuth Test Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
// Create a project
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$id = $response [ 'body' ][ '$id' ];
2024-05-06 06:29:15 +00:00
$providers = require ( __DIR__ . '/../../../../app/config/oAuthProviders.php' );
2020-07-09 09:13:14 +00:00
/**
* Test for SUCCESS
*/
2020-10-27 19:48:38 +00:00
foreach ( $providers as $key => $provider ) {
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/oauth2' , array_merge ([
2020-07-09 09:13:14 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'provider' => $key ,
2022-04-18 16:21:45 +00:00
'appId' => 'AppId-' . ucfirst ( $key ),
'secret' => 'Secret-' . ucfirst ( $key ),
2020-07-09 09:13:14 +00:00
]);
2022-04-18 16:21:45 +00:00
2020-07-09 09:13:14 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
}
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
2020-07-09 09:13:14 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertEquals ( $id , $response [ 'body' ][ '$id' ]);
2020-10-27 19:48:38 +00:00
foreach ( $providers as $key => $provider ) {
2022-08-19 09:43:03 +00:00
$asserted = false ;
2023-10-25 17:33:23 +00:00
foreach ( $response [ 'body' ][ 'oAuthProviders' ] as $responseProvider ) {
2023-07-20 22:54:38 +00:00
if ( $responseProvider [ 'key' ] === $key ) {
2022-08-19 09:43:03 +00:00
$this -> assertEquals ( 'AppId-' . ucfirst ( $key ), $responseProvider [ 'appId' ]);
$this -> assertEquals ( 'Secret-' . ucfirst ( $key ), $responseProvider [ 'secret' ]);
$this -> assertFalse ( $responseProvider [ 'enabled' ]);
$asserted = true ;
break ;
}
}
$this -> assertTrue ( $asserted );
}
// Enable providers
$i = 0 ;
foreach ( $providers as $key => $provider ) {
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/oauth2' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'provider' => $key ,
'enabled' => $i === 0 ? false : true // On first provider, test enabled=false
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$i ++ ;
}
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertEquals ( $id , $response [ 'body' ][ '$id' ]);
$i = 0 ;
foreach ( $providers as $key => $provider ) {
$asserted = false ;
2023-10-25 17:33:23 +00:00
foreach ( $response [ 'body' ][ 'oAuthProviders' ] as $responseProvider ) {
2023-07-20 22:54:38 +00:00
if ( $responseProvider [ 'key' ] === $key ) {
2022-08-19 09:43:03 +00:00
// On first provider, test enabled=false
$this -> assertEquals ( $i !== 0 , $responseProvider [ 'enabled' ]);
$asserted = true ;
break ;
}
}
$this -> assertTrue ( $asserted );
$i ++ ;
2020-07-09 09:13:14 +00:00
}
/**
* Test for FAILURE
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/oauth2' , array_merge ([
2020-07-09 09:13:14 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'provider' => 'unknown' ,
2022-08-27 03:16:37 +00:00
'appId' => 'AppId' ,
2020-07-09 09:13:14 +00:00
'secret' => 'Secret' ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
}
2025-10-16 08:59:57 +00:00
public function testUpdateProjectAuthStatus () : void
2021-02-28 21:22:03 +00:00
{
2025-10-16 08:59:57 +00:00
// Create a team
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Update Project Auth Status Test Team' ,
]);
2022-04-18 16:21:45 +00:00
2025-10-16 08:59:57 +00:00
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
// Create a project
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$id = $response [ 'body' ][ '$id' ];
2022-04-18 16:21:45 +00:00
2025-10-16 08:59:57 +00:00
$auth = require ( __DIR__ . '/../../../../app/config/auth.php' );
2022-04-18 16:21:45 +00:00
$originalEmail = uniqid () . 'user@localhost.test' ;
2021-02-28 21:22:03 +00:00
$originalPassword = 'password' ;
$originalName = 'User Name' ;
2022-04-18 16:21:45 +00:00
2021-02-28 21:22:03 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
2022-08-14 10:33:36 +00:00
'userId' => ID :: unique (),
2021-02-28 21:22:03 +00:00
'email' => $originalEmail ,
'password' => $originalPassword ,
'name' => $originalName ,
]);
2022-06-14 08:17:50 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , array_merge ([
2021-02-28 21:22:03 +00:00
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'email' => $originalEmail ,
'password' => $originalPassword ,
]);
2023-12-08 23:17:13 +00:00
$session = $response [ 'cookies' ][ 'a_session_' . $id ];
2021-02-28 21:22:03 +00:00
/**
* Test for SUCCESS
*/
foreach ( $auth as $index => $method ) {
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/' . $index , array_merge ([
2021-02-28 21:22:03 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'status' => false ,
]);
2022-04-18 16:21:45 +00:00
2021-02-28 21:22:03 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
2021-02-28 21:22:03 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$this -> assertEquals ( false , $response [ 'body' ][ 'auth' . ucfirst ( $method [ 'key' ])]);
2021-02-28 21:22:03 +00:00
}
2022-04-18 16:21:45 +00:00
$email = uniqid () . 'user@localhost.test' ;
2021-02-28 21:22:03 +00:00
$password = 'password' ;
$name = 'User Name' ;
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
2022-08-14 10:33:36 +00:00
'userId' => ID :: unique (),
2021-02-28 21:22:03 +00:00
'email' => $email ,
'password' => $password ,
'name' => $name ,
]);
$this -> assertEquals ( $response [ 'headers' ][ 'status-code' ], 501 );
$response = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
2022-04-18 16:21:45 +00:00
'cookie' => 'a_session_' . $id . '=' . $session ,
2021-02-28 21:22:03 +00:00
]), [
2022-08-14 10:33:36 +00:00
'teamId' => ID :: unique (),
2021-02-28 21:22:03 +00:00
'name' => 'Arsenal'
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$teamUid = $response [ 'body' ][ '$id' ];
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/teams/' . $teamUid . '/memberships' , array_merge ([
2021-02-28 21:22:03 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
2022-04-18 16:21:45 +00:00
'cookie' => 'a_session_' . $id . '=' . $session ,
2021-02-28 21:22:03 +00:00
]), [
'email' => $email ,
'name' => 'Friend User' ,
'roles' => [ 'admin' , 'editor' ],
'url' => 'http://localhost:5000/join-us#title'
]);
$this -> assertEquals ( $response [ 'headers' ][ 'status-code' ], 501 );
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/jwt' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
2022-04-18 16:21:45 +00:00
'cookie' => 'a_session_' . $id . '=' . $session ,
2021-02-28 21:22:03 +00:00
]));
$this -> assertEquals ( $response [ 'headers' ][ 'status-code' ], 501 );
2022-06-14 08:17:50 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , array_merge ([
2021-02-28 21:22:03 +00:00
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'email' => $originalEmail ,
'password' => $originalPassword ,
]);
2022-04-18 16:21:45 +00:00
2021-02-28 21:22:03 +00:00
$this -> assertEquals ( $response [ 'headers' ][ 'status-code' ], 501 );
2023-05-30 06:26:17 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/anonymous' , array_merge ([
2021-04-03 08:56:32 +00:00
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
2023-05-30 06:26:17 +00:00
]));
2021-04-03 08:56:32 +00:00
$this -> assertEquals ( $response [ 'headers' ][ 'status-code' ], 501 );
2021-02-28 21:22:03 +00:00
// Cleanup
foreach ( $auth as $index => $method ) {
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/' . $index , array_merge ([
2021-02-28 21:22:03 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'status' => true ,
]);
}
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectAuthLimit () : void
2021-02-28 21:22:03 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2022-04-18 16:21:45 +00:00
2021-02-28 21:22:03 +00:00
/**
* Test for SUCCESS
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/limit' , array_merge ([
2021-02-28 21:22:03 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 1 ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$email = uniqid () . 'user@localhost.test' ;
2021-02-28 21:22:03 +00:00
$password = 'password' ;
$name = 'User Name' ;
/**
* Test for SUCCESS
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
2022-08-14 10:33:36 +00:00
'userId' => ID :: unique (),
2021-02-28 21:22:03 +00:00
'email' => $email ,
'password' => $password ,
'name' => $name ,
]);
2024-05-20 11:46:37 +00:00
// Creating A Team
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Test Team 1' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
$email = uniqid () . 'user@localhost.test' ;
// Creating A User Using Team membership
$response = $this -> client -> call ( Client :: METHOD_POST , '/teams/' . $teamId . '/memberships' , array_merge ( $this -> getHeaders (), [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin' ,
]), [
'email' => $email ,
'roles' => [],
'url' => 'http://localhost' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2023-05-30 06:26:17 +00:00
$email = uniqid () . 'user@localhost.test' ;
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'userId' => ID :: unique (),
'email' => $email ,
'password' => $password ,
'name' => $name ,
]);
2024-05-23 03:37:13 +00:00
$this -> assertEquals ( Exception :: USER_COUNT_EXCEEDED , $response [ 'body' ][ 'type' ]);
2024-05-22 01:42:34 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2021-02-28 21:22:03 +00:00
/**
* Test for FAILURE
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/limit' , array_merge ([
2021-02-28 21:22:03 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 0 ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
2023-05-30 06:26:17 +00:00
$email = uniqid () . 'user@localhost.test' ;
2021-02-28 21:22:03 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
2022-08-14 10:33:36 +00:00
'userId' => ID :: unique (),
2021-02-28 21:22:03 +00:00
'email' => $email ,
'password' => $password ,
'name' => $name ,
]);
$this -> assertEquals ( $response [ 'headers' ][ 'status-code' ], 201 );
}
2025-12-29 17:41:35 +00:00
public function testUpdateProjectAuthSessionsLimit () : void
2022-12-09 11:54:23 +00:00
{
2025-12-29 17:41:35 +00:00
$id = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testUpdateProjectAuthSessionsLimit' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
2022-12-09 11:54:23 +00:00
/**
* Test for failure
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/max-sessions' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 0 ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
/**
* Test for SUCCESS
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/max-sessions' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 1 ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-12-27 10:40:24 +00:00
$this -> assertEquals ( 1 , $response [ 'body' ][ 'authSessionsLimit' ]);
2022-12-09 11:54:23 +00:00
$email = uniqid () . 'user@localhost.test' ;
$password = 'password' ;
$name = 'User Name' ;
/**
* Create new user
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'userId' => ID :: unique (),
'email' => $email ,
'password' => $password ,
'name' => $name ,
]);
2022-12-11 07:15:47 +00:00
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2022-12-09 11:54:23 +00:00
/**
2026-02-25 10:38:40 +00:00
* Create sessions and verify limit enforcement .
* Each session creation triggers the session limit shutdown hook .
* We retry session creation to handle potential cache propagation delays
* where the shutdown hook may not see the updated maxSessions on the first attempt .
2022-12-09 11:54:23 +00:00
*/
2026-02-25 10:38:40 +00:00
$this -> assertEventually ( function () use ( $id , $email , $password ) {
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
], [
'email' => $email ,
'password' => $password ,
]);
2022-12-09 11:54:23 +00:00
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$latestSessionId = $response [ 'body' ][ '$id' ];
$sessionCookie = 'a_session_' . $id . '=' . ( $response [ 'cookies' ][ 'a_session_' . $id ] ? ? '' );
2022-12-09 11:54:23 +00:00
2026-02-25 10:38:40 +00:00
// Small delay for shutdown hook to complete
\usleep ( 500_000 );
2025-12-31 09:30:23 +00:00
2025-02-03 00:53:00 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
2026-02-25 10:38:40 +00:00
'cookie' => $sessionCookie ,
2025-02-03 00:53:00 +00:00
]);
2022-12-09 11:54:23 +00:00
2025-02-03 00:53:00 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$sessions = $response [ 'body' ][ 'sessions' ];
2022-12-09 11:54:23 +00:00
2026-02-25 10:38:40 +00:00
$this -> assertCount ( 1 , $sessions );
$this -> assertEquals ( $latestSessionId , $sessions [ 0 ][ '$id' ]);
}, 30_000 , 2_000 );
2022-12-09 11:54:23 +00:00
2022-12-12 05:02:48 +00:00
/**
* Reset Limit
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/max-sessions' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 10 ,
]);
2025-12-29 17:41:35 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2022-12-09 11:54:23 +00:00
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectAuthPasswordHistory () : void
2022-12-18 06:27:41 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithAuthLimit ();
$id = $data [ 'projectId' ];
2022-12-18 06:27:41 +00:00
2022-12-21 06:42:27 +00:00
/**
* Test for Failure
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/password-history' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 25 ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2022-12-18 06:27:41 +00:00
/**
* Test for Success
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/password-history' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 1 ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 1 , $response [ 'body' ][ 'authPasswordHistory' ]);
$email = uniqid () . 'user@localhost.test' ;
$password = 'password' ;
$name = 'User Name' ;
/**
* Create new user
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'userId' => ID :: unique (),
'email' => $email ,
'password' => $password ,
'name' => $name ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2022-12-19 05:07:41 +00:00
$userId = $response [ 'body' ][ '$id' ];
2022-12-18 06:27:41 +00:00
// create session
$session = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
], [
'email' => $email ,
'password' => $password ,
]);
$this -> assertEquals ( 201 , $session [ 'headers' ][ 'status-code' ]);
2023-12-08 23:36:01 +00:00
$session = $session [ 'cookies' ][ 'a_session_' . $id ];
2022-12-18 06:27:41 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/account/password' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'cookie' => 'a_session_' . $id . '=' . $session ,
]), [
'oldPassword' => $password ,
'password' => $password ,
]);
2023-04-13 20:20:03 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2022-12-19 05:07:41 +00:00
2022-12-19 08:28:02 +00:00
$headers = array_merge ( $this -> getHeaders (), [
'x-appwrite-mode' => 'admin' ,
2022-12-19 05:07:41 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
2022-12-19 08:28:02 +00:00
]);
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/users/' . $userId . '/password' , $headers , [
2022-12-19 05:07:41 +00:00
'password' => $password ,
]);
2022-12-18 06:27:41 +00:00
2023-04-13 20:20:03 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2022-12-18 06:27:41 +00:00
2022-12-18 06:31:14 +00:00
2024-03-06 17:34:21 +00:00
/**
2024-06-20 14:49:56 +00:00
* Reset
*/
2022-12-18 06:27:41 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/password-history' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 0 ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 0 , $response [ 'body' ][ 'authPasswordHistory' ]);
}
2026-02-25 10:38:40 +00:00
#[Group('smtpAndTemplates')]
#[Group('projectsCRUD')]
public function testUpdateMockNumbers () : void
2024-02-14 06:40:19 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2024-02-14 06:40:19 +00:00
/**
* Test for Failure
*/
/** Trying to pass an empty body to the endpoint */
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2024-06-20 14:49:56 +00:00
], $this -> getHeaders ()), []);
2024-02-14 06:40:19 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Param "numbers" is not optional.' , $response [ 'body' ][ 'message' ]);
/** Trying to pass body with incorrect structure */
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => [
2024-02-14 17:22:43 +00:00
'phone' => '+1655513432' ,
2024-02-14 06:40:19 +00:00
'otp' => '123456'
]
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2024-06-20 14:49:56 +00:00
$this -> assertEquals ( 'Invalid `numbers` param: Value must a valid array no longer than 10 items and Invalid payload structure. Please check the "phone" and "otp" fields' , $response [ 'body' ][ 'message' ]);
2024-02-14 06:40:19 +00:00
/** Trying to pass an OTP longer than 6 characters*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => [
[
2024-02-14 17:22:43 +00:00
'phone' => '+1655513432' ,
2024-02-14 06:40:19 +00:00
'otp' => '12345678'
]
]
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2024-07-21 19:30:06 +00:00
$this -> assertEquals ( 'Invalid `numbers` param: Value must a valid array no longer than 10 items and Invalid OTP. Please make sure the OTP is a 6 digit number' , $response [ 'body' ][ 'message' ]);
2024-02-14 06:40:19 +00:00
/** Trying to pass an OTP shorter than 6 characters*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => [
[
2024-02-14 17:22:43 +00:00
'phone' => '+1655513432' ,
2024-02-14 06:40:19 +00:00
'otp' => '123'
]
]
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2024-07-21 19:30:06 +00:00
$this -> assertEquals ( 'Invalid `numbers` param: Value must a valid array no longer than 10 items and Invalid OTP. Please make sure the OTP is a 6 digit number' , $response [ 'body' ][ 'message' ]);
/** Trying to pass an OTP with non numeric characters */
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => [
[
'phone' => '+1655513432' ,
'otp' => '123re2'
]
]
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Invalid `numbers` param: Value must a valid array no longer than 10 items and Invalid OTP. Please make sure the OTP is a 6 digit number' , $response [ 'body' ][ 'message' ]);
2024-02-14 06:40:19 +00:00
/** Trying to pass an invalid phone number */
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => [
[
2024-02-14 17:22:43 +00:00
'phone' => '1655234' ,
2024-02-14 06:40:19 +00:00
'otp' => '123456'
]
]
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2024-06-20 14:49:56 +00:00
$this -> assertEquals ( 'Invalid `numbers` param: Value must a valid array no longer than 10 items and Phone number must start with a \'+\' can have a maximum of fifteen digits.' , $response [ 'body' ][ 'message' ]);
2024-02-14 06:40:19 +00:00
/** Trying to pass a number longer than 15 digits */
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => [
[
2024-02-14 17:22:43 +00:00
'phone' => '+1234567890987654' ,
2024-02-14 06:40:19 +00:00
'otp' => '123456'
]
]
]);
2024-07-21 19:30:06 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Invalid `numbers` param: Value must a valid array no longer than 10 items and Phone number must start with a \'+\' can have a maximum of fifteen digits.' , $response [ 'body' ][ 'message' ]);
/** Trying to pass duplicate numbers */
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => [
[
'phone' => '+1655513432' ,
'otp' => '123456'
],
[
'phone' => '+1655513432' ,
'otp' => '123456'
]
]
]);
2024-02-14 06:40:19 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2024-07-21 19:45:39 +00:00
$this -> assertEquals ( 'Duplicate phone numbers are not allowed.' , $response [ 'body' ][ 'message' ]);
2024-02-14 06:40:19 +00:00
$numbers = [];
for ( $i = 0 ; $i < 11 ; $i ++ ) {
$numbers [] = [
2024-02-14 17:22:43 +00:00
'phone' => '+1655513432' ,
2024-02-14 06:40:19 +00:00
'otp' => '123456'
];
}
2024-02-14 17:22:43 +00:00
2024-02-14 06:40:19 +00:00
/** Trying to pass more than 10 values */
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => $numbers
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertStringContainsString ( 'Value must a valid array no longer than 10 items' , $response [ 'body' ][ 'message' ]);
2024-02-14 06:40:19 +00:00
/**
* Test for success
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => []
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/mock-numbers' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'numbers' => [
[
2024-02-14 17:22:43 +00:00
'phone' => '+1655513432' ,
2024-02-14 06:40:19 +00:00
'otp' => '123456'
]
]
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
// Create phone session for this project and check if the mock number is used
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/phone' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
2024-06-20 14:31:33 +00:00
'userId' => 'unique()' ,
'phone' => '+1655513432' ,
2024-02-14 06:40:19 +00:00
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$userId = $response [ 'body' ][ 'userId' ];
$response = $this -> client -> call ( Client :: METHOD_PUT , '/account/sessions/phone' , array_merge ([
'content-type' => 'application/json' ,
2024-06-20 15:01:20 +00:00
'x-appwrite-project' => $id ,
]), [
'userId' => $userId ,
'secret' => '654321' , // Try a random code
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_PUT , '/account/sessions/phone' , array_merge ([
'content-type' => 'application/json' ,
2024-02-14 06:40:19 +00:00
'x-appwrite-project' => $id ,
]), [
2024-06-20 14:31:33 +00:00
'userId' => $userId ,
'secret' => '123456' ,
2024-02-14 06:40:19 +00:00
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectAuthPasswordDictionary () : void
2022-12-26 05:46:35 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithAuthLimit ();
$id = $data [ 'projectId' ];
2022-12-26 05:46:35 +00:00
$password = 'password' ;
$name = 'User Name' ;
/**
* Test for Success
*/
/**
* create account
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'userId' => ID :: unique (),
'email' => uniqid () . 'user@localhost.test' ,
'password' => $password ,
'name' => $name ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$userId = $response [ 'body' ][ '$id' ];
/**
* Create user
*/
$user = $this -> client -> call ( Client :: METHOD_POST , '/users' , array_merge ( $this -> getHeaders (), [
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin' ,
]), [
'userId' => ID :: unique (),
'email' => uniqid () . 'user@localhost.test' ,
'password' => 'password' ,
'name' => 'Cristiano Ronaldo' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
/**
* Enable Disctionary
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/password-dictionary' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'enabled' => true ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( true , $response [ 'body' ][ 'authPasswordDictionary' ]);
/**
* Test for failure
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'userId' => ID :: unique (),
'email' => uniqid () . 'user@localhost.test' ,
'password' => $password ,
'name' => $name ,
]);
2022-12-26 10:22:25 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2022-12-26 05:47:20 +00:00
2022-12-26 05:46:35 +00:00
/**
* Create user
*/
$user = $this -> client -> call ( Client :: METHOD_POST , '/users' , array_merge ( $this -> getHeaders (), [
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin' ,
]), [
'userId' => ID :: unique (),
'email' => uniqid () . 'user@localhost.test' ,
'password' => 'password' ,
'name' => 'Cristiano Ronaldo' ,
]);
2022-12-26 10:22:25 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2022-12-26 05:46:35 +00:00
$headers = array_merge ( $this -> getHeaders (), [
'x-appwrite-mode' => 'admin' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]);
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/users/' . $userId . '/password' , $headers , [
'password' => $password ,
]);
2022-12-26 10:22:25 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2022-12-26 05:46:35 +00:00
2024-03-06 17:34:21 +00:00
/**
2024-06-20 14:49:56 +00:00
* Reset
*/
2022-12-26 05:46:35 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/password-history' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'limit' => 0 ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 0 , $response [ 'body' ][ 'authPasswordHistory' ]);
/**
* Reset
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/password-dictionary' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-12-26 10:22:25 +00:00
'enabled' => false ,
2022-12-26 05:46:35 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2022-12-26 10:22:25 +00:00
$this -> assertEquals ( false , $response [ 'body' ][ 'authPasswordDictionary' ]);
2022-12-26 05:46:35 +00:00
}
2026-02-25 10:38:40 +00:00
public function testUpdateDisallowPersonalData () : void
2023-04-13 20:20:03 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2023-04-13 20:20:03 +00:00
/**
* Enable Disallowing of Personal Data
*/
2023-07-20 13:12:41 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/personal-data' , array_merge ([
2023-04-13 20:20:03 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'enabled' => true ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2023-07-19 22:24:32 +00:00
$this -> assertEquals ( true , $response [ 'body' ][ 'authPersonalDataCheck' ]);
2023-04-13 20:20:03 +00:00
/**
* Test for failure
*/
$email = uniqid () . 'user@localhost.test' ;
$password = 'password' ;
$name = 'username' ;
$userId = ID :: unique ();
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'email' => $email ,
'password' => $email ,
'name' => $name ,
'userId' => $userId
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 400 , $response [ 'body' ][ 'code' ]);
$this -> assertEquals ( Exception :: USER_PASSWORD_PERSONAL_DATA , $response [ 'body' ][ 'type' ]);
2023-04-13 20:59:35 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'email' => $email ,
'password' => $name ,
'name' => $name ,
'userId' => $userId
]);
2023-04-13 20:20:03 +00:00
$phone = '+123456789' ;
$response = $this -> client -> call ( Client :: METHOD_POST , '/users' , array_merge ( $this -> getHeaders (), [
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin' ,
]), [
'email' => $email ,
'password' => $phone ,
'name' => $name ,
'userId' => $userId ,
'phone' => $phone
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 400 , $response [ 'body' ][ 'code' ]);
$this -> assertEquals ( Exception :: USER_PASSWORD_PERSONAL_DATA , $response [ 'body' ][ 'type' ]);
/** Test for success */
$email = uniqid () . 'user@localhost.test' ;
$password = 'password' ;
$name = 'username' ;
$userId = ID :: unique ();
$response = $this -> client -> call ( Client :: METHOD_POST , '/account' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
'email' => $email ,
'password' => $password ,
'name' => $name ,
'userId' => $userId
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2024-02-25 10:25:51 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/users' , array_merge ( $this -> getHeaders (), [
2024-02-25 09:19:30 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
2024-02-25 10:25:51 +00:00
'x-appwrite-mode' => 'admin' ,
2024-02-25 09:19:30 +00:00
]), [
2024-02-25 10:25:51 +00:00
// Empty password
'email' => uniqid () . 'user@localhost.test' ,
'name' => 'User' ,
'userId' => ID :: unique (),
2024-02-25 09:19:30 +00:00
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2023-04-13 20:20:03 +00:00
$email = uniqid () . 'user@localhost.test' ;
$userId = ID :: unique ();
$response = $this -> client -> call ( Client :: METHOD_POST , '/users' , array_merge ( $this -> getHeaders (), [
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin' ,
]), [
'email' => $email ,
'password' => $password ,
'name' => $name ,
'userId' => $userId ,
'phone' => $phone
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
/**
* Reset
*/
2023-07-20 13:12:41 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/auth/personal-data' , array_merge ([
2023-04-13 20:20:03 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'enabled' => false ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2023-07-19 22:24:32 +00:00
$this -> assertEquals ( false , $response [ 'body' ][ 'authPersonalDataCheck' ]);
2023-04-13 20:20:03 +00:00
}
2023-11-05 23:34:44 +00:00
public function testUpdateProjectServicesAll () : void
{
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'teamId' => ID :: unique (),
'name' => 'Project Test' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $team [ 'body' ][ '$id' ],
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2023-11-05 23:34:44 +00:00
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $project [ 'body' ][ '$id' ]);
$id = $project [ 'body' ][ '$id' ];
2026-04-09 13:54:00 +00:00
// Bulk disable should no longer work
2023-11-05 23:34:44 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/service/all' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-09 13:54:00 +00:00
'x-appwrite-response-format' => '1.9.0' ,
2023-11-05 23:34:44 +00:00
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'status' => false ,
]);
2026-04-09 13:54:00 +00:00
$this -> assertEquals ( 405 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'general_not_implemented' , $response [ 'body' ][ 'type' ]);
2023-11-05 23:34:44 +00:00
2026-04-09 13:54:00 +00:00
// Bulk enable should no longer work
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/service/all' , array_merge ([
2023-11-05 23:34:44 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-09 13:54:00 +00:00
'x-appwrite-response-format' => '1.9.0' ,
2023-11-05 23:34:44 +00:00
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
2026-04-09 13:54:00 +00:00
]), [
'status' => true ,
]);
2023-11-05 23:34:44 +00:00
2026-04-09 13:54:00 +00:00
$this -> assertEquals ( 405 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'general_not_implemented' , $response [ 'body' ][ 'type' ]);
}
2023-11-05 23:34:44 +00:00
2026-04-09 13:54:00 +00:00
public function testUpdateProjectApisAll () : void
{
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'teamId' => ID :: unique (),
'name' => 'Project Test' ,
]);
2023-11-05 23:34:44 +00:00
2026-04-09 13:54:00 +00:00
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $team [ 'body' ][ '$id' ],
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $project [ 'body' ][ '$id' ]);
$id = $project [ 'body' ][ '$id' ];
// Bulk disable should no longer work
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/api/all' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-response-format' => '1.9.0' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'status' => false ,
]);
$this -> assertEquals ( 405 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'general_not_implemented' , $response [ 'body' ][ 'type' ]);
// Bulk enable should no longer work
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/api/all' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-response-format' => '1.9.0' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'status' => true ,
]);
$this -> assertEquals ( 405 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'general_not_implemented' , $response [ 'body' ][ 'type' ]);
}
public function testUpdateProjectApiStatus () : void
{
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'teamId' => ID :: unique (),
'name' => 'Project Test' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $team [ 'body' ][ '$id' ],
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $project [ 'body' ][ '$id' ]);
$id = $project [ 'body' ][ '$id' ];
$protocols = [ 'rest' , 'graphql' , 'websocket' ];
/**
* Test for Disabled using old format ( api + status )
*/
foreach ( $protocols as $key ) {
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/api' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-response-format' => '1.9.0' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'api' => $key ,
'status' => false ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( false , $response [ 'body' ][ 'protocolStatusFor' . ucfirst ( $key )]);
2023-11-05 23:34:44 +00:00
}
2026-04-09 13:54:00 +00:00
/**
* Test for Enabled using old format ( api + status )
*/
foreach ( $protocols as $key ) {
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/api' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-response-format' => '1.9.0' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'api' => $key ,
'status' => true ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( true , $response [ 'body' ][ 'protocolStatusFor' . ucfirst ( $key )]);
2023-11-05 23:34:44 +00:00
}
2026-04-09 13:54:00 +00:00
}
2023-11-05 23:34:44 +00:00
2026-04-09 13:54:00 +00:00
public function testUpdateProjectApiStatusRealtimeBackwardsCompat () : void
{
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
2023-11-05 23:34:44 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
2026-04-09 13:54:00 +00:00
'teamId' => ID :: unique (),
'name' => 'Project Test' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'projectId' => ID :: unique (),
'name' => 'Project Test' ,
'teamId' => $team [ 'body' ][ '$id' ],
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$id = $project [ 'body' ][ '$id' ];
/**
* Test that " realtime " gets renamed to " websocket " via request filter
*/
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/api' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-response-format' => '1.9.0' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'api' => 'realtime' ,
'status' => false ,
2023-11-05 23:34:44 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-04-09 13:54:00 +00:00
$this -> assertEquals ( false , $response [ 'body' ][ 'protocolStatusForWebsocket' ]);
2023-11-05 23:34:44 +00:00
2026-04-09 13:54:00 +00:00
// Re-enable via old "realtime" name
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/api' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-response-format' => '1.9.0' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'api' => 'realtime' ,
'status' => true ,
]);
2023-11-05 23:34:44 +00:00
2026-04-09 13:54:00 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( true , $response [ 'body' ][ 'protocolStatusForWebsocket' ]);
2023-11-05 23:34:44 +00:00
}
2022-12-18 06:27:41 +00:00
2021-07-29 10:56:25 +00:00
public function testUpdateProjectServiceStatusAdmin () : array
2021-07-29 10:28:17 +00:00
{
2021-07-29 10:56:25 +00:00
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
2022-08-14 10:33:36 +00:00
'teamId' => ID :: unique (),
2021-07-29 10:56:25 +00:00
'name' => 'Project Test' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
2022-08-14 10:33:36 +00:00
'projectId' => ID :: unique (),
2021-07-29 10:56:25 +00:00
'name' => 'Project Test' ,
'teamId' => $team [ 'body' ][ '$id' ],
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2021-07-29 10:56:25 +00:00
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $project [ 'body' ][ '$id' ]);
$id = $project [ 'body' ][ '$id' ];
2024-03-04 12:58:28 +00:00
$services = require ( __DIR__ . '/../../../../app/config/services.php' );
2021-07-29 10:28:17 +00:00
/**
* Test for Disabled
*/
foreach ( $services as $service ) {
2022-04-18 16:21:45 +00:00
if ( ! $service [ 'optional' ]) {
2021-08-01 08:00:13 +00:00
continue ;
}
2021-08-01 10:15:06 +00:00
$key = $service [ 'key' ] ? ? '' ;
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/service' , array_merge ([
2021-07-29 10:28:17 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-09 13:54:00 +00:00
'x-appwrite-response-format' => '1.9.0' ,
2021-07-29 10:56:25 +00:00
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
2021-08-01 10:15:06 +00:00
'service' => $key ,
2021-07-29 10:28:17 +00:00
'status' => false ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
2021-07-29 10:28:17 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2021-07-29 10:56:25 +00:00
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]));
2021-07-29 10:28:17 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$this -> assertEquals ( false , $response [ 'body' ][ 'serviceStatusFor' . ucfirst ( $key )]);
2021-07-29 10:28:17 +00:00
}
2022-04-18 16:21:45 +00:00
2021-07-29 10:28:17 +00:00
/**
2021-07-29 10:56:25 +00:00
* Admin request must succeed
2021-07-29 10:28:17 +00:00
*/
2022-04-18 16:21:45 +00:00
2021-07-29 10:28:17 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/functions' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
2021-07-29 10:56:25 +00:00
// 'x-appwrite-project' => $this->getProject()['$id'],
2021-07-29 10:28:17 +00:00
'x-appwrite-project' => $id ,
2021-07-29 10:56:25 +00:00
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
'x-appwrite-mode' => 'admin'
]));
2022-04-18 16:21:45 +00:00
2021-07-29 10:56:25 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2021-07-29 10:28:17 +00:00
foreach ( $services as $service ) {
2022-04-18 16:21:45 +00:00
if ( ! $service [ 'optional' ]) {
2021-08-01 10:15:06 +00:00
continue ;
}
$key = $service [ 'key' ] ? ? '' ;
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/service/' , array_merge ([
2021-07-29 10:28:17 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-09 13:54:00 +00:00
'x-appwrite-response-format' => '1.9.0' ,
2021-07-29 10:28:17 +00:00
], $this -> getHeaders ()), [
2021-08-01 10:15:06 +00:00
'service' => $key ,
2021-07-29 10:28:17 +00:00
'status' => true ,
]);
}
2021-07-29 10:56:25 +00:00
return [ 'projectId' => $id ];
2021-07-29 10:28:17 +00:00
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectServiceStatus () : void
2021-07-29 10:28:17 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithServicesDisabled ();
2021-07-29 10:56:25 +00:00
$id = $data [ 'projectId' ];
2021-07-29 10:28:17 +00:00
2024-03-04 12:58:28 +00:00
$services = require ( __DIR__ . '/../../../../app/config/services.php' );
2021-07-29 10:28:17 +00:00
/**
* Test for Disabled
*/
foreach ( $services as $service ) {
2022-04-18 16:21:45 +00:00
if ( ! $service [ 'optional' ]) {
2021-08-01 10:15:06 +00:00
continue ;
}
$key = $service [ 'key' ] ? ? '' ;
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/service' , array_merge ([
2021-07-29 10:28:17 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-09 13:54:00 +00:00
'x-appwrite-response-format' => '1.9.0' ,
2021-07-29 10:28:17 +00:00
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
2021-08-01 10:15:06 +00:00
'service' => $key ,
2021-07-29 10:28:17 +00:00
'status' => false ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
2021-07-29 10:28:17 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$this -> assertEquals ( false , $response [ 'body' ][ 'serviceStatusFor' . ucfirst ( $key )]);
2021-07-29 10:28:17 +00:00
}
/**
2021-07-29 10:56:25 +00:00
* Test for FAILURE
2021-07-29 10:28:17 +00:00
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/functions' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
2021-07-29 10:56:25 +00:00
], $this -> getHeaders ()));
2021-07-29 10:28:17 +00:00
2024-02-26 12:28:57 +00:00
$this -> assertEquals ( 403 , $response [ 'headers' ][ 'status-code' ]);
2021-07-29 10:56:25 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
]), [
2022-08-14 10:33:36 +00:00
'teamId' => ID :: unique (),
2021-07-29 10:56:25 +00:00
'name' => 'Arsenal'
]);
2024-02-26 12:28:57 +00:00
$this -> assertEquals ( 403 , $response [ 'headers' ][ 'status-code' ]);
2021-07-29 10:56:25 +00:00
// Cleanup
foreach ( $services as $service ) {
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/service/' , array_merge ([
2021-07-29 10:56:25 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-09 13:54:00 +00:00
'x-appwrite-response-format' => '1.9.0' ,
2021-07-29 10:56:25 +00:00
], $this -> getHeaders ()), [
'service' => $service ,
'status' => true ,
]);
}
2021-07-29 10:28:17 +00:00
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectServiceStatusServer () : void
2022-05-22 06:57:59 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithServicesDisabled ();
2022-05-22 06:57:59 +00:00
$id = $data [ 'projectId' ];
2024-03-04 12:58:28 +00:00
$services = require ( __DIR__ . '/../../../../app/config/services.php' );
2022-05-22 06:57:59 +00:00
/**
* Test for Disabled
*/
foreach ( $services as $service ) {
if ( ! $service [ 'optional' ]) {
continue ;
}
$key = $service [ 'key' ] ? ? '' ;
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/service' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-09 13:54:00 +00:00
'x-appwrite-response-format' => '1.9.0' ,
2022-05-22 06:57:59 +00:00
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
'service' => $key ,
'status' => false ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( false , $response [ 'body' ][ 'serviceStatusFor' . ucfirst ( $key )]);
}
// Create API Key
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), [
2026-02-09 13:34:05 +00:00
'keyId' => ID :: unique (),
2022-05-22 06:57:59 +00:00
'name' => 'Key Test' ,
'scopes' => [ 'functions.read' , 'teams.write' ],
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$keyId = $response [ 'body' ][ '$id' ];
$keySecret = $response [ 'body' ][ 'secret' ];
/**
* Request with API Key must succeed
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/functions' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-key' => $keySecret ,
2022-08-30 14:04:42 +00:00
'x-sdk-name' => 'python'
2022-05-22 06:57:59 +00:00
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-key' => $keySecret ,
2022-08-30 14:04:42 +00:00
'x-sdk-name' => 'php'
2022-05-22 06:57:59 +00:00
]), [
2022-08-14 10:33:36 +00:00
'teamId' => ID :: unique (),
2022-05-22 06:57:59 +00:00
'name' => 'Arsenal'
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2022-08-30 14:04:42 +00:00
/** Check that the API key has been updated */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'sdks' , $response [ 'body' ]);
$this -> assertCount ( 2 , $response [ 'body' ][ 'sdks' ]);
2022-08-30 17:33:54 +00:00
$this -> assertContains ( 'python' , $response [ 'body' ][ 'sdks' ]);
$this -> assertContains ( 'php' , $response [ 'body' ][ 'sdks' ]);
2022-08-30 14:04:42 +00:00
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'accessedAt' ]);
2022-08-30 18:26:02 +00:00
2022-05-22 06:57:59 +00:00
// Cleanup
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
]), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
foreach ( $services as $service ) {
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $id . '/service/' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-09 13:54:00 +00:00
'x-appwrite-response-format' => '1.9.0' ,
2022-05-22 06:57:59 +00:00
], $this -> getHeaders ()), [
'service' => $service ,
'status' => true ,
]);
}
}
2026-02-25 10:38:40 +00:00
public function testCreateProjectWebhook () : void
2020-07-09 09:13:14 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2020-07-09 09:13:14 +00:00
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/webhooks' , array_merge ([
2020-07-09 09:13:14 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-09 09:13:14 +00:00
], $this -> getHeaders ()), [
2026-03-19 11:20:33 +00:00
'webhookId' => 'unique()' ,
2020-07-09 09:13:14 +00:00
'name' => 'Webhook Test' ,
2022-04-18 16:21:45 +00:00
'events' => [ 'users.*.create' , 'users.*.update.email' ],
2020-07-09 09:13:14 +00:00
'url' => 'https://appwrite.io' ,
2026-04-11 12:19:05 +00:00
'tls' => true ,
'authUsername' => 'username' ,
'authPassword' => 'password' ,
2020-07-09 09:13:14 +00:00
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$this -> assertContains ( 'users.*.create' , $response [ 'body' ][ 'events' ]);
$this -> assertContains ( 'users.*.update.email' , $response [ 'body' ][ 'events' ]);
2020-07-09 09:13:14 +00:00
$this -> assertCount ( 2 , $response [ 'body' ][ 'events' ]);
$this -> assertEquals ( 'https://appwrite.io' , $response [ 'body' ][ 'url' ]);
2026-04-11 12:19:05 +00:00
$this -> assertIsBool ( $response [ 'body' ][ 'tls' ]);
$this -> assertEquals ( true , $response [ 'body' ][ 'tls' ]);
$this -> assertEquals ( 'username' , $response [ 'body' ][ 'authUsername' ]);
2022-04-18 16:21:45 +00:00
2020-07-09 09:13:14 +00:00
/**
* Test for FAILURE
*/
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/webhooks' , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), [
2026-03-19 11:20:33 +00:00
'webhookId' => 'unique()' ,
2020-07-11 13:01:04 +00:00
'name' => 'Webhook Test' ,
2022-04-18 16:21:45 +00:00
'events' => [ 'account.unknown' , 'users.*.update.email' ],
2020-07-11 13:01:04 +00:00
'url' => 'https://appwrite.io' ,
2026-04-11 12:19:05 +00:00
'tls' => true ,
'authUsername' => 'username' ,
'authPassword' => 'password' ,
2020-07-11 13:01:04 +00:00
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/webhooks' , array_merge ([
2022-02-16 15:16:37 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2022-02-16 15:16:37 +00:00
], $this -> getHeaders ()), [
2026-03-19 11:20:33 +00:00
'webhookId' => 'unique()' ,
2022-02-16 15:16:37 +00:00
'name' => 'Webhook Test' ,
2022-04-18 16:21:45 +00:00
'events' => [ 'users.*.create' , 'users.*.update.email' ],
2022-02-16 15:16:37 +00:00
'url' => 'invalid://appwrite.io' ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2020-07-11 13:01:04 +00:00
}
2026-02-25 10:38:40 +00:00
public function testListProjectWebhook () : void
2020-07-12 13:43:47 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithWebhook ();
$id = $data [ 'projectId' ];
2020-07-12 13:43:47 +00:00
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/webhooks' , array_merge ([
2020-07-12 13:43:47 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-12 13:43:47 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
// In parallel mode, multiple tests may create webhooks on the same project
$this -> assertGreaterThanOrEqual ( 1 , $response [ 'body' ][ 'total' ]);
2022-04-18 16:21:45 +00:00
2020-07-12 13:43:47 +00:00
/**
* Test for FAILURE
*/
}
2026-02-25 10:38:40 +00:00
public function testGetProjectWebhook () : void
2020-07-11 13:01:04 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithWebhook ();
$id = $data [ 'projectId' ];
$webhookId = $data [ 'webhookId' ];
2020-07-11 13:01:04 +00:00
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/webhooks/' . $webhookId , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $webhookId , $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
$this -> assertContains ( 'users.*.create' , $response [ 'body' ][ 'events' ]);
$this -> assertContains ( 'users.*.update.email' , $response [ 'body' ][ 'events' ]);
2020-07-11 13:01:04 +00:00
$this -> assertCount ( 2 , $response [ 'body' ][ 'events' ]);
$this -> assertEquals ( 'https://appwrite.io' , $response [ 'body' ][ 'url' ]);
2026-04-11 12:19:05 +00:00
$this -> assertEquals ( 'username' , $response [ 'body' ][ 'authUsername' ]);
$this -> assertEquals ( 'password' , $response [ 'body' ][ 'authPassword' ]);
2022-04-18 16:21:45 +00:00
2020-07-11 13:01:04 +00:00
/**
* Test for FAILURE
*/
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/webhooks/error' , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectWebhook () : void
2020-07-11 13:01:04 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithWebhook ();
$id = $data [ 'projectId' ];
$webhookId = $data [ 'webhookId' ];
2020-07-11 13:01:04 +00:00
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/webhooks/' . $webhookId , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), [
'name' => 'Webhook Test Update' ,
2022-04-18 16:21:45 +00:00
'events' => [ 'users.*.delete' , 'users.*.sessions.*.delete' , 'buckets.*.files.*.create' ],
2020-07-11 13:01:04 +00:00
'url' => 'https://appwrite.io/new' ,
2026-04-11 12:19:05 +00:00
'tls' => false ,
2020-07-11 13:01:04 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $webhookId , $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Webhook Test Update' , $response [ 'body' ][ 'name' ]);
2022-04-18 16:21:45 +00:00
$this -> assertContains ( 'users.*.delete' , $response [ 'body' ][ 'events' ]);
$this -> assertContains ( 'users.*.sessions.*.delete' , $response [ 'body' ][ 'events' ]);
$this -> assertContains ( 'buckets.*.files.*.create' , $response [ 'body' ][ 'events' ]);
2020-07-11 13:01:04 +00:00
$this -> assertCount ( 3 , $response [ 'body' ][ 'events' ]);
$this -> assertEquals ( 'https://appwrite.io/new' , $response [ 'body' ][ 'url' ]);
2026-04-11 12:19:05 +00:00
$this -> assertIsBool ( $response [ 'body' ][ 'tls' ]);
$this -> assertEquals ( false , $response [ 'body' ][ 'tls' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'authUsername' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'authPassword' ]);
2020-07-11 13:01:04 +00:00
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/webhooks/' . $webhookId , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $webhookId , $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Webhook Test Update' , $response [ 'body' ][ 'name' ]);
2022-04-18 16:21:45 +00:00
$this -> assertContains ( 'users.*.delete' , $response [ 'body' ][ 'events' ]);
$this -> assertContains ( 'users.*.sessions.*.delete' , $response [ 'body' ][ 'events' ]);
$this -> assertContains ( 'buckets.*.files.*.create' , $response [ 'body' ][ 'events' ]);
2020-07-11 13:01:04 +00:00
$this -> assertCount ( 3 , $response [ 'body' ][ 'events' ]);
$this -> assertEquals ( 'https://appwrite.io/new' , $response [ 'body' ][ 'url' ]);
2026-04-11 12:19:05 +00:00
$this -> assertIsBool ( $response [ 'body' ][ 'tls' ]);
$this -> assertEquals ( false , $response [ 'body' ][ 'tls' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'authUsername' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'authPassword' ]);
2022-04-18 16:21:45 +00:00
2020-07-11 13:01:04 +00:00
/**
* Test for FAILURE
*/
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/webhooks/' . $webhookId , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), [
'name' => 'Webhook Test Update' ,
2022-04-18 16:21:45 +00:00
'events' => [ 'users.*.delete' , 'users.*.sessions.*.delete' , 'buckets.*.files.*.unknown' ],
2020-07-11 13:01:04 +00:00
'url' => 'https://appwrite.io/new' ,
2026-04-11 12:19:05 +00:00
'tls' => false ,
2020-07-11 13:01:04 +00:00
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/webhooks/' . $webhookId , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), [
'name' => 'Webhook Test Update' ,
2022-04-18 16:21:45 +00:00
'events' => [ 'users.*.delete' , 'users.*.sessions.*.delete' , 'buckets.*.files.*.create' ],
2020-07-11 13:01:04 +00:00
'url' => 'appwrite.io/new' ,
2026-04-11 12:19:05 +00:00
'tls' => false ,
2020-07-11 13:01:04 +00:00
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/webhooks/' . $webhookId , array_merge ([
2022-02-16 15:16:37 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2022-02-16 15:16:37 +00:00
], $this -> getHeaders ()), [
'name' => 'Webhook Test Update' ,
2022-04-18 16:21:45 +00:00
'events' => [ 'users.*.delete' , 'users.*.sessions.*.delete' , 'buckets.*.files.*.create' ],
2022-02-16 15:16:37 +00:00
'url' => 'invalid://appwrite.io/new' ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2020-07-11 13:01:04 +00:00
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectWebhookSignature () : void
2022-06-20 18:35:33 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithWebhook ();
$id = $data [ 'projectId' ];
$webhookId = $data [ 'webhookId' ];
$signatureKey = $data [ 'signatureKey' ];
2022-06-20 18:35:33 +00:00
2026-04-11 12:19:05 +00:00
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/webhooks/' . $webhookId . '/secret' , array_merge ([
2022-06-20 18:35:33 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2022-06-20 18:35:33 +00:00
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-04-11 12:19:05 +00:00
$this -> assertNotEmpty ( $response [ 'body' ][ 'secret' ]);
$this -> assertNotEquals ( $signatureKey , $response [ 'body' ][ 'secret' ]);
2022-06-20 18:35:33 +00:00
}
2026-02-25 10:38:40 +00:00
public function testDeleteProjectWebhook () : void
2020-07-11 13:01:04 +00:00
{
2026-02-25 10:38:40 +00:00
// Create a fresh project with webhook for deletion test
$projectData = $this -> setupProjectData ();
$id = $projectData [ 'projectId' ];
// Create a webhook to delete
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/webhooks' , array_merge ([
2026-02-25 10:38:40 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
2026-03-19 11:20:33 +00:00
'webhookId' => 'unique()' ,
2026-02-25 10:38:40 +00:00
'name' => 'Webhook To Delete' ,
'events' => [ 'users.*.create' ],
'url' => 'https://appwrite.io' ,
2026-04-11 12:19:05 +00:00
'tls' => true ,
'authUsername' => 'username' ,
'authPassword' => 'password' ,
2026-02-25 10:38:40 +00:00
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$webhookId = $response [ 'body' ][ '$id' ];
2020-07-11 13:01:04 +00:00
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/webhooks/' . $webhookId , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/webhooks/' . $webhookId , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2022-04-18 16:21:45 +00:00
2020-07-11 13:01:04 +00:00
/**
* Test for FAILURE
*/
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/webhooks/error' , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-11 13:01:04 +00:00
], $this -> getHeaders ()), []);
2020-07-09 09:13:14 +00:00
2020-07-11 13:01:04 +00:00
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2020-07-08 15:20:18 +00:00
}
2020-07-11 13:01:04 +00:00
// Keys
2026-02-25 10:38:40 +00:00
public function testCreateProjectKey () : void
2020-07-11 13:01:04 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2020-07-11 13:01:04 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-09 13:34:05 +00:00
'keyId' => ID :: unique (),
2020-07-11 13:01:04 +00:00
'name' => 'Key Test' ,
'scopes' => [ 'teams.read' , 'teams.write' ],
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Key Test' , $response [ 'body' ][ 'name' ]);
$this -> assertContains ( 'teams.read' , $response [ 'body' ][ 'scopes' ]);
$this -> assertContains ( 'teams.write' , $response [ 'body' ][ 'scopes' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'secret' ]);
2022-08-30 14:04:42 +00:00
$this -> assertArrayHasKey ( 'sdks' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'sdks' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
2022-04-18 16:21:45 +00:00
2026-02-09 13:34:05 +00:00
/**
* Test for SUCCESS without key ID
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-08 08:52:20 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-09 13:34:05 +00:00
], $this -> getHeaders ()), [
'name' => 'Key Custom' ,
'scopes' => [ 'teams.read' , 'teams.write' ],
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
/**
* Test for SUCCESS with custom ID
*/
2026-02-10 10:43:22 +00:00
$customKeyId = \uniqid () . 'custom-id' ;
2026-02-09 13:34:05 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'keyId' => $customKeyId ,
'name' => 'Key Custom' ,
'scopes' => [ 'teams.read' , 'teams.write' ],
]);
2026-02-09 15:53:18 +00:00
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertSame ( $customKeyId , $response [ 'body' ][ '$id' ]);
2026-02-10 10:43:22 +00:00
/**
* Test for FAILURE with custom ID
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'keyId' => $customKeyId ,
'name' => 'Key Custom' ,
'scopes' => [ 'teams.read' , 'teams.write' ],
]);
$this -> assertEquals ( 409 , $response [ 'headers' ][ 'status-code' ]);
2026-02-09 15:42:14 +00:00
/**
* Test for SUCCESS with magic string ID
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'keyId' => 'unique()' ,
'name' => 'Key Custom' ,
'scopes' => [ 'teams.read' , 'teams.write' ],
]);
2026-02-09 13:34:05 +00:00
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2026-02-09 15:42:14 +00:00
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2026-02-09 15:53:18 +00:00
$this -> assertNotSame ( 'unique()' , $response [ 'body' ][ '$id' ]);
2022-04-18 16:21:45 +00:00
2022-05-31 15:41:12 +00:00
$data = array_merge ( $data , [
'keyId' => $response [ 'body' ][ '$id' ],
'secret' => $response [ 'body' ][ 'secret' ]
]);
2020-07-11 13:01:04 +00:00
/**
* Test for FAILURE
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
2020-07-11 13:01:04 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-09 13:34:05 +00:00
'keyId' => ID :: unique (),
2020-07-11 13:01:04 +00:00
'name' => 'Key Test' ,
'scopes' => [ 'unknown' ],
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
}
2022-05-31 15:41:12 +00:00
2026-02-25 10:38:40 +00:00
public function testListProjectKey () : void
2020-07-12 13:43:47 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithKey ();
$id = $data [ 'projectId' ];
2020-07-12 13:43:47 +00:00
2026-02-09 13:58:36 +00:00
/** Create a second key with an expiry for query testing */
$expireDate = DateTime :: addSeconds ( new \DateTime (), 3600 );
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-08 08:52:20 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-09 13:58:36 +00:00
], $this -> getHeaders ()), [
'name' => 'Key Test 2' ,
'scopes' => [ 'users.read' ],
'expire' => $expireDate ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$key2Id = $response [ 'body' ][ '$id' ];
2026-02-25 10:38:40 +00:00
/** List all keys (no queries) — count depends on how many test methods ran before this in the same worker */
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys' , array_merge ([
2020-07-12 13:43:47 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
2026-02-09 13:58:36 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$totalKeys = $response [ 'body' ][ 'total' ];
$this -> assertGreaterThanOrEqual ( 2 , $totalKeys );
$this -> assertCount ( $totalKeys , $response [ 'body' ][ 'keys' ]);
2026-02-09 13:58:36 +00:00
/** List keys with limit */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: limit ( 1 ) -> toString (),
]
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertCount ( 1 , $response [ 'body' ][ 'keys' ]);
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( $totalKeys , $response [ 'body' ][ 'total' ]);
2026-02-09 13:58:36 +00:00
/** List keys with offset */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: offset ( 1 ) -> toString (),
]
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertCount ( $totalKeys - 1 , $response [ 'body' ][ 'keys' ]);
$this -> assertEquals ( $totalKeys , $response [ 'body' ][ 'total' ]);
2026-02-09 13:58:36 +00:00
/** List keys with cursor after */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: cursorAfter ( new Document ([ '$id' => $data [ 'keyId' ]])) -> toString (),
]
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertGreaterThanOrEqual ( 1 , $response [ 'body' ][ 'keys' ]);
$this -> assertEquals ( $totalKeys , $response [ 'body' ][ 'total' ]);
2026-02-09 13:58:36 +00:00
/** List keys filtering by expire (lessThan now — should match none) */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: lessThan ( 'expire' , ( new \DateTime ()) -> format ( 'Y-m-d H:i:s' )) -> toString (),
]
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 0 , $response [ 'body' ][ 'total' ]);
/** List keys filtering by expire (greaterThan now — should match the key with expiry) */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: greaterThan ( 'expire' , ( new \DateTime ()) -> format ( 'Y-m-d H:i:s' )) -> toString (),
]
]);
2022-06-01 06:26:55 +00:00
2020-07-12 13:43:47 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
// In parallel mode, multiple tests may create keys on the same project
$this -> assertGreaterThanOrEqual ( 1 , $response [ 'body' ][ 'total' ]);
/**
* Test for FAILURE
*/
2026-02-09 13:58:36 +00:00
2026-02-25 10:38:40 +00:00
/** Test invalid query attribute */
2026-02-09 15:58:44 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
2026-02-25 10:38:40 +00:00
Query :: equal ( 'secret' , [ 'test' ]) -> toString (),
2026-02-09 15:58:44 +00:00
]
]);
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2026-02-09 15:58:44 +00:00
2026-02-25 10:38:40 +00:00
/** Test invalid cursor */
2026-02-09 15:58:44 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
2026-02-25 10:38:40 +00:00
Query :: cursorAfter ( new Document ([ '$id' => 'invalid' ])) -> toString (),
2026-02-09 15:58:44 +00:00
]
]);
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-09 15:58:44 +00:00
2026-02-25 10:38:40 +00:00
public function testGetProjectKey () : void
{
$data = $this -> setupProjectWithKey ();
$id = $data [ 'projectId' ];
$keyId = $data [ 'keyId' ];
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
2026-02-09 15:58:44 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), []);
2026-02-09 15:58:44 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $keyId , $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Key Test' , $response [ 'body' ][ 'name' ]);
$this -> assertContains ( 'teams.read' , $response [ 'body' ][ 'scopes' ]);
$this -> assertContains ( 'teams.write' , $response [ 'body' ][ 'scopes' ]);
$this -> assertCount ( 2 , $response [ 'body' ][ 'scopes' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'secret' ]);
$this -> assertArrayHasKey ( 'sdks' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'sdks' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
2026-02-09 15:58:44 +00:00
2026-02-25 10:38:40 +00:00
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys/error' , array_merge ([
2026-02-09 15:58:44 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), []);
2022-06-01 06:26:55 +00:00
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-09 15:58:44 +00:00
2026-02-25 10:38:40 +00:00
public function testValidateProjectKey () : void
{
$data = $this -> setupProjectData ();
$projectId = $data [ 'projectId' ];
$teamId = $data [ 'teamId' ];
/**
* Test for SUCCESS
*/
// Expiring key
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $projectId . '/keys' , array_merge ([
2026-02-09 15:58:44 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-25 10:38:40 +00:00
'keyId' => ID :: unique (),
'name' => 'Key Test' ,
'scopes' => [ 'users.write' ],
'expire' => DateTime :: addSeconds ( new \DateTime (), 3600 ),
2026-02-09 15:58:44 +00:00
]);
2026-02-25 10:38:40 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/users' , [
2026-02-09 15:58:44 +00:00
'content-type' => 'application/json' ,
2026-02-25 10:38:40 +00:00
'x-appwrite-project' => $projectId ,
'x-appwrite-key' => $response [ 'body' ][ 'secret' ]
], [
'userId' => ID :: unique (),
2026-02-09 15:58:44 +00:00
]);
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
2026-02-09 15:58:44 +00:00
2026-02-25 10:38:40 +00:00
// No expiry
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $projectId . '/keys' , array_merge ([
2026-02-09 15:58:44 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-25 10:38:40 +00:00
'keyId' => ID :: unique (),
'name' => 'Key Test' ,
'scopes' => [ 'health.read' ],
'expire' => null ,
2026-02-09 15:58:44 +00:00
]);
2026-02-25 10:38:40 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/health' , [
2022-06-01 06:26:55 +00:00
'content-type' => 'application/json' ,
2025-04-16 00:30:22 +00:00
'x-appwrite-project' => $projectId ,
2022-06-01 06:26:55 +00:00
'x-appwrite-key' => $response [ 'body' ][ 'secret' ]
], []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
/**
* Test for FAILURE
*/
2025-04-16 00:30:22 +00:00
// Expired key
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $projectId . '/keys' , array_merge ([
2022-06-01 06:26:55 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-09 13:34:05 +00:00
'keyId' => ID :: unique (),
2022-06-01 06:26:55 +00:00
'name' => 'Key Test' ,
'scopes' => [ 'health.read' ],
2022-07-13 14:02:49 +00:00
'expire' => DateTime :: addSeconds ( new \DateTime (), - 3600 ),
2022-06-01 06:26:55 +00:00
]);
2022-06-03 09:12:19 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/health' , [
2022-06-01 06:26:55 +00:00
'content-type' => 'application/json' ,
2025-04-16 00:30:22 +00:00
'x-appwrite-project' => $projectId ,
2022-06-01 06:26:55 +00:00
'x-appwrite-key' => $response [ 'body' ][ 'secret' ]
2025-04-16 00:30:22 +00:00
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
// Invalid key
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket' ,
]);
$this -> assertEquals ( 201 , $bucket [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $bucket [ 'body' ][ '$id' ]);
$bucketId = $bucket [ 'body' ][ '$id' ];
$response = $this -> client -> call ( Client :: METHOD_GET , " /storage/buckets/ { $bucketId } /files " , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-key' => 'invalid-key'
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
// Invalid scopes
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $projectId . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-09 13:34:05 +00:00
'keyId' => ID :: unique (),
2025-04-16 00:30:22 +00:00
'name' => 'Key Test' ,
'scopes' => [ 'teams.read' ],
'expire' => DateTime :: addSeconds ( new \DateTime (), 3600 ),
]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/users' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-key' => $response [ 'body' ][ 'secret' ]
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
// Invalid key from different project
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Project Test 2' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$project2Id = $response [ 'body' ][ '$id' ];
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $project2Id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-09 13:34:05 +00:00
'keyId' => ID :: unique (),
2025-04-16 00:30:22 +00:00
'name' => 'Key Test' ,
'scopes' => [ 'health.read' ],
'expire' => DateTime :: addSeconds ( new \DateTime (), 3600 ),
]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/health' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-key' => $response [ 'body' ][ 'secret' ]
]);
2022-06-01 06:26:55 +00:00
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
2022-05-31 15:41:12 +00:00
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectKey () : void
2020-07-11 13:26:04 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithKey ();
$id = $data [ 'projectId' ];
$keyId = $data [ 'keyId' ];
2020-07-11 13:26:04 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
2020-07-11 13:26:04 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'name' => 'Key Test Update' ,
2025-06-25 11:32:21 +00:00
'scopes' => [ 'users.read' , 'users.write' , 'collections.read' , 'tables.read' ],
2022-07-13 14:02:49 +00:00
'expire' => DateTime :: addSeconds ( new \DateTime (), 360 ),
2020-07-11 13:26:04 +00:00
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $keyId , $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Key Test Update' , $response [ 'body' ][ 'name' ]);
$this -> assertContains ( 'users.read' , $response [ 'body' ][ 'scopes' ]);
$this -> assertContains ( 'users.write' , $response [ 'body' ][ 'scopes' ]);
$this -> assertContains ( 'collections.read' , $response [ 'body' ][ 'scopes' ]);
2025-06-25 11:32:21 +00:00
$this -> assertContains ( 'tables.read' , $response [ 'body' ][ 'scopes' ]);
2025-08-11 19:05:18 +00:00
$this -> assertCount ( 4 , $response [ 'body' ][ 'scopes' ]);
2022-08-30 14:04:42 +00:00
$this -> assertArrayHasKey ( 'sdks' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'sdks' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
2020-07-11 13:26:04 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
2020-07-11 13:26:04 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $keyId , $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Key Test Update' , $response [ 'body' ][ 'name' ]);
$this -> assertContains ( 'users.read' , $response [ 'body' ][ 'scopes' ]);
$this -> assertContains ( 'users.write' , $response [ 'body' ][ 'scopes' ]);
$this -> assertContains ( 'collections.read' , $response [ 'body' ][ 'scopes' ]);
2025-06-25 11:32:21 +00:00
$this -> assertContains ( 'tables.read' , $response [ 'body' ][ 'scopes' ]);
2025-08-11 19:05:18 +00:00
$this -> assertCount ( 4 , $response [ 'body' ][ 'scopes' ]);
2022-08-30 14:04:42 +00:00
$this -> assertArrayHasKey ( 'sdks' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'sdks' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
2022-04-18 16:21:45 +00:00
2020-07-11 13:26:04 +00:00
/**
* Test for FAILURE
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
2020-07-11 13:26:04 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'name' => 'Key Test Update' ,
'scopes' => [ 'users.read' , 'users.write' , 'collections.read' , 'unknown' ],
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-25 10:38:40 +00:00
public function testDeleteProjectKey () : void
2020-07-11 13:26:04 +00:00
{
2026-02-25 10:38:40 +00:00
// Create a fresh key for deletion testing (cannot use cached key)
$projectData = $this -> setupProjectData ();
$id = $projectData [ 'projectId' ];
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-04-08 08:52:20 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'name' => 'Key For Deletion' ,
'scopes' => [ 'teams.read' , 'teams.write' ],
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$keyId = $response [ 'body' ][ '$id' ];
2020-07-11 13:26:04 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
2020-07-11 13:26:04 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
2020-07-11 13:26:04 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2022-04-18 16:21:45 +00:00
2020-07-11 13:26:04 +00:00
/**
* Test for FAILURE
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/keys/error' , array_merge ([
2020-07-11 13:26:04 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
2020-07-11 19:40:58 +00:00
2026-02-25 10:38:40 +00:00
public function testCreateProjectKeyOutdated () : void
2024-05-16 08:39:15 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2024-05-16 08:39:15 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/mock/api-key-unprefixed' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => $id
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertContains ( 'users.read' , $response [ 'body' ][ 'scopes' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'secret' ]);
$this -> assertStringStartsNotWith ( API_KEY_STANDARD . '_' , $response [ 'body' ][ 'secret' ]);
$keyId = $response [ 'body' ][ '$id' ];
$secret = $response [ 'body' ][ 'secret' ];
$response = $this -> client -> call ( Client :: METHOD_GET , '/users' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-key' => $secret
], []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/keys/' . $keyId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
}
2024-05-29 09:33:39 +00:00
// JWT Keys
2026-02-25 10:38:40 +00:00
public function testJWTKey () : void
2024-05-29 09:33:39 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2024-05-29 09:33:39 +00:00
// Create JWT key
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/jwts' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'duration' => 5 ,
'scopes' => [ 'users.read' ],
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'jwt' ]);
$jwt = $response [ 'body' ][ 'jwt' ];
// Ensure JWT key works
$response = $this -> client -> call ( Client :: METHOD_GET , '/users' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-key' => $jwt ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'users' , $response [ 'body' ]);
// Ensure JWT key respect scopes
$response = $this -> client -> call ( Client :: METHOD_GET , '/functions' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-key' => $jwt ,
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
// Ensure JWT key expires
\sleep ( 10 );
$response = $this -> client -> call ( Client :: METHOD_GET , '/users' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $id ,
'x-appwrite-key' => $jwt ,
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
}
2020-07-12 11:57:31 +00:00
// Platforms
2026-02-25 10:38:40 +00:00
public function testCreateProjectPlatform () : void
2020-07-12 11:57:31 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
$id = $data [ 'projectId' ];
2020-07-12 11:57:31 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), [
'type' => 'web' ,
'name' => 'Web App' ,
'hostname' => 'localhost' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'web' , $response [ 'body' ][ 'type' ]);
$this -> assertEquals ( 'Web App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( 'localhost' , $response [ 'body' ][ 'hostname' ]);
2022-04-18 16:21:45 +00:00
2020-07-12 11:57:31 +00:00
$data = array_merge ( $data , [ 'platformWebId' => $response [ 'body' ][ '$id' ]]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), [
'type' => 'flutter-ios' ,
'name' => 'Flutter App (iOS)' ,
'key' => 'com.example.ios' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Origianlly flutter-ios, but new version renames
2020-07-12 11:57:31 +00:00
$this -> assertEquals ( 'Flutter App (iOS)' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.ios' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2022-04-18 16:21:45 +00:00
2020-07-12 11:57:31 +00:00
$data = array_merge ( $data , [ 'platformFultteriOSId' => $response [ 'body' ][ '$id' ]]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), [
'type' => 'flutter-android' ,
'name' => 'Flutter App (Android)' ,
'key' => 'com.example.android' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'android' , $response [ 'body' ][ 'type' ]); // Origianlly flutter-android, but new version renames
2020-07-12 11:57:31 +00:00
$this -> assertEquals ( 'Flutter App (Android)' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.android' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2022-04-18 16:21:45 +00:00
2020-07-12 11:57:31 +00:00
$data = array_merge ( $data , [ 'platformFultterAndroidId' => $response [ 'body' ][ '$id' ]]);
2023-01-11 23:38:09 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2023-01-11 23:38:09 +00:00
], $this -> getHeaders ()), [
'type' => 'flutter-web' ,
'name' => 'Flutter App (Web)' ,
'hostname' => 'flutter.appwrite.io' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'web' , $response [ 'body' ][ 'type' ]); // Origianlly flutter-web, but new version renames
2023-01-11 23:38:09 +00:00
$this -> assertEquals ( 'Flutter App (Web)' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( 'flutter.appwrite.io' , $response [ 'body' ][ 'hostname' ]);
$data = array_merge ( $data , [ 'platformFultterWebId' => $response [ 'body' ][ '$id' ]]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), [
'type' => 'apple-ios' ,
'name' => 'iOS App' ,
'key' => 'com.example.ios' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Origianlly apple-ios, but new version renames
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'iOS App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.ios' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
$data = array_merge ( $data , [ 'platformAppleIosId' => $response [ 'body' ][ '$id' ]]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), [
'type' => 'apple-macos' ,
'name' => 'macOS App' ,
'key' => 'com.example.macos' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Origianlly apple-macos, but new version renames
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'macOS App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.macos' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
$data = array_merge ( $data , [ 'platformAppleMacOsId' => $response [ 'body' ][ '$id' ]]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), [
'type' => 'apple-watchos' ,
'name' => 'watchOS App' ,
'key' => 'com.example.watchos' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Origianlly apple-watchos, but new version renames
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'watchOS App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.watchos' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
$data = array_merge ( $data , [ 'platformAppleWatchOsId' => $response [ 'body' ][ '$id' ]]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), [
'type' => 'apple-tvos' ,
'name' => 'tvOS App' ,
'key' => 'com.example.tvos' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Origianlly apple-tvos, but new version renames
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'tvOS App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.tvos' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
$data = array_merge ( $data , [ 'platformAppleTvOsId' => $response [ 'body' ][ '$id' ]]);
2020-07-12 11:57:31 +00:00
/**
* Test for FAILURE
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), [
'type' => 'unknown' ,
'name' => 'Web App' ,
'hostname' => 'localhost' ,
]);
2021-12-01 11:48:23 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2020-07-12 11:57:31 +00:00
}
2026-02-25 10:38:40 +00:00
public function testListProjectPlatform () : void
2020-07-12 13:43:47 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithPlatform ();
$id = $data [ 'projectId' ];
2021-12-01 11:48:23 +00:00
2025-10-16 08:51:30 +00:00
$this -> assertEventually ( function () use ( $id ) {
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2025-10-16 08:51:30 +00:00
], $this -> getHeaders ()), []);
2020-07-12 13:43:47 +00:00
2025-10-16 08:51:30 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
// In parallel mode, multiple tests may create platforms on the same project
// The setup creates 8 platforms, so we should have at least that many
$this -> assertGreaterThanOrEqual ( 8 , $response [ 'body' ][ 'total' ]);
2025-10-16 08:51:30 +00:00
});
2020-07-12 13:43:47 +00:00
/**
* Test for FAILURE
*/
}
2026-02-25 10:38:40 +00:00
public function testGetProjectPlatform () : void
2020-07-12 11:57:31 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithPlatform ();
$id = $data [ 'projectId' ];
2021-12-01 11:48:23 +00:00
2026-02-25 10:38:40 +00:00
$platformWebId = $data [ 'platformWebId' ];
2020-07-12 11:57:31 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformWebId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformWebId , $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'web' , $response [ 'body' ][ 'type' ]);
$this -> assertEquals ( 'Web App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( 'localhost' , $response [ 'body' ][ 'hostname' ]);
2022-04-18 16:21:45 +00:00
2026-02-25 10:38:40 +00:00
$platformFultteriOSId = $data [ 'platformFultteriOSId' ];
2020-07-12 11:57:31 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformFultteriOSId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformFultteriOSId , $response [ 'body' ][ '$id' ]);
2026-03-27 14:34:34 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]);
2020-07-12 11:57:31 +00:00
$this -> assertEquals ( 'Flutter App (iOS)' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.ios' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2022-04-18 16:21:45 +00:00
2026-02-25 10:38:40 +00:00
$platformFultterAndroidId = $data [ 'platformFultterAndroidId' ];
2020-07-12 11:57:31 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformFultterAndroidId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformFultterAndroidId , $response [ 'body' ][ '$id' ]);
2026-03-27 14:34:34 +00:00
$this -> assertEquals ( 'android' , $response [ 'body' ][ 'type' ]);
2020-07-12 11:57:31 +00:00
$this -> assertEquals ( 'Flutter App (Android)' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.android' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2021-10-13 13:44:52 +00:00
2026-02-25 10:38:40 +00:00
$platformFultterWebId = $data [ 'platformFultterWebId' ];
2023-01-11 23:38:09 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformFultterWebId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2023-01-11 23:38:09 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformFultterWebId , $response [ 'body' ][ '$id' ]);
2026-03-27 14:34:34 +00:00
$this -> assertEquals ( 'web' , $response [ 'body' ][ 'type' ]);
2023-01-11 23:38:09 +00:00
$this -> assertEquals ( 'Flutter App (Web)' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( 'flutter.appwrite.io' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformAppleIosId = $data [ 'platformAppleIosId' ];
2021-10-13 13:44:52 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformAppleIosId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformAppleIosId , $response [ 'body' ][ '$id' ]);
2026-03-27 14:34:34 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]);
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'iOS App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.ios' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformAppleMacOsId = $data [ 'platformAppleMacOsId' ];
2021-10-13 13:44:52 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformAppleMacOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformAppleMacOsId , $response [ 'body' ][ '$id' ]);
2026-03-27 14:34:34 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]);
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'macOS App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.macos' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformAppleWatchOsId = $data [ 'platformAppleWatchOsId' ];
2021-10-13 13:44:52 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformAppleWatchOsId , $response [ 'body' ][ '$id' ]);
2026-03-27 14:34:34 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]);
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'watchOS App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.watchos' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformAppleTvOsId = $data [ 'platformAppleTvOsId' ];
2021-10-13 13:44:52 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformAppleTvOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformAppleTvOsId , $response [ 'body' ][ '$id' ]);
2026-03-27 14:34:34 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]);
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'tvOS App' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.tvos' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2020-07-12 11:57:31 +00:00
/**
* Test for FAILURE
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/error' , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-25 10:38:40 +00:00
public function testUpdateProjectPlatform () : void
2020-07-12 11:57:31 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithPlatform ();
$id = $data [ 'projectId' ];
2020-07-12 11:57:31 +00:00
2026-02-25 10:38:40 +00:00
$platformWebId = $data [ 'platformWebId' ];
2020-07-12 11:57:31 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/' . $platformWebId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), [
'name' => 'Web App 2' ,
'hostname' => 'localhost-new' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformWebId , $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'web' , $response [ 'body' ][ 'type' ]);
$this -> assertEquals ( 'Web App 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( 'localhost-new' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformFultteriOSId = $data [ 'platformFultteriOSId' ];
2020-07-12 11:57:31 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/' . $platformFultteriOSId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), [
'name' => 'Flutter App (iOS) 2' ,
'key' => 'com.example.ios2' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformFultteriOSId , $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Origianlly flutter-ios, but new version renames
2020-07-12 11:57:31 +00:00
$this -> assertEquals ( 'Flutter App (iOS) 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.ios2' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2022-04-18 16:21:45 +00:00
2026-02-25 10:38:40 +00:00
$platformFultterAndroidId = $data [ 'platformFultterAndroidId' ];
2020-07-12 11:57:31 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/' . $platformFultterAndroidId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), [
'name' => 'Flutter App (Android) 2' ,
'key' => 'com.example.android2' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformFultterAndroidId , $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'android' , $response [ 'body' ][ 'type' ]); // Origianlly flutter-android, but new version renames
2020-07-12 11:57:31 +00:00
$this -> assertEquals ( 'Flutter App (Android) 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.android2' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformFultterWebId = $data [ 'platformFultterWebId' ];
2023-01-11 23:38:09 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/' . $platformFultterWebId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2023-01-11 23:38:09 +00:00
], $this -> getHeaders ()), [
'name' => 'Flutter App (Web) 2' ,
'hostname' => 'flutter2.appwrite.io' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformFultterWebId , $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'web' , $response [ 'body' ][ 'type' ]); // Originally flutter-web, but new version renames
2023-01-11 23:38:09 +00:00
$this -> assertEquals ( 'Flutter App (Web) 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( 'flutter2.appwrite.io' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformAppleIosId = $data [ 'platformAppleIosId' ];
2021-10-13 13:44:52 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/' . $platformAppleIosId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), [
'name' => 'iOS App 2' ,
'key' => 'com.example.ios2' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformAppleIosId , $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Originally apple-ios, but new version renames
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'iOS App 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.ios2' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformAppleMacOsId = $data [ 'platformAppleMacOsId' ];
2021-10-13 13:44:52 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/' . $platformAppleMacOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), [
'name' => 'macOS App 2' ,
'key' => 'com.example.macos2' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformAppleMacOsId , $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Originally apple-macos, but new version renames
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'macOS App 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.macos2' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformAppleWatchOsId = $data [ 'platformAppleWatchOsId' ];
2021-10-13 13:44:52 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), [
'name' => 'watchOS App 2' ,
'key' => 'com.example.watchos2' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformAppleWatchOsId , $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Originally apple-watchos, but new version renames
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'watchOS App 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.watchos2' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2026-02-25 10:38:40 +00:00
$platformAppleTvOsId = $data [ 'platformAppleTvOsId' ];
2021-10-13 13:44:52 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/' . $platformAppleTvOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), [
'name' => 'tvOS App 2' ,
'key' => 'com.example.tvos2' ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $platformAppleTvOsId , $response [ 'body' ][ '$id' ]);
2026-04-07 10:07:21 +00:00
$this -> assertEquals ( 'apple' , $response [ 'body' ][ 'type' ]); // Originally apple-tvos, but new version renames
2021-10-13 13:44:52 +00:00
$this -> assertEquals ( 'tvOS App 2' , $response [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'com.example.tvos2' , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'store' ]);
$this -> assertEquals ( '' , $response [ 'body' ][ 'hostname' ]);
2020-07-12 11:57:31 +00:00
/**
* Test for FAILURE
*/
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $id . '/platforms/error' , array_merge ([
2021-09-01 07:03:22 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-09-01 07:03:22 +00:00
], $this -> getHeaders ()), [
'name' => 'Flutter App (Android) 2' ,
'key' => 'com.example.android2' ,
]);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2020-07-12 11:57:31 +00:00
}
2026-02-25 10:38:40 +00:00
public function testDeleteProjectPlatform () : void
2020-07-12 11:57:31 +00:00
{
2026-02-25 10:38:40 +00:00
// Create a fresh project with platforms for deletion testing (cannot use cached platforms)
$projectData = $this -> setupProjectData ();
$id = $projectData [ 'projectId' ];
// Create web platform
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'type' => 'web' ,
'name' => 'Web App' ,
'hostname' => 'localhost' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$platformWebId = $response [ 'body' ][ '$id' ];
// Create flutter-ios platform
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'type' => 'flutter-ios' ,
'name' => 'Flutter App (iOS)' ,
'key' => 'com.example.ios' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$platformFultteriOSId = $response [ 'body' ][ '$id' ];
// Create flutter-android platform
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'type' => 'flutter-android' ,
'name' => 'Flutter App (Android)' ,
'key' => 'com.example.android' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$platformFultterAndroidId = $response [ 'body' ][ '$id' ];
// Create flutter-web platform
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'type' => 'flutter-web' ,
'name' => 'Flutter App (Web)' ,
'hostname' => 'flutter.appwrite.io' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$platformFultterWebId = $response [ 'body' ][ '$id' ];
// Create apple-ios platform
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'type' => 'apple-ios' ,
'name' => 'iOS App' ,
'key' => 'com.example.ios' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$platformAppleIosId = $response [ 'body' ][ '$id' ];
// Create apple-macos platform
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'type' => 'apple-macos' ,
'name' => 'macOS App' ,
'key' => 'com.example.macos' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$platformAppleMacOsId = $response [ 'body' ][ '$id' ];
// Create apple-watchos platform
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'type' => 'apple-watchos' ,
'name' => 'watchOS App' ,
'key' => 'com.example.watchos' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$platformAppleWatchOsId = $response [ 'body' ][ '$id' ];
2022-04-18 16:21:45 +00:00
2026-02-25 10:38:40 +00:00
// Create apple-tvos platform
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/platforms' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2026-02-25 10:38:40 +00:00
], $this -> getHeaders ()), [
'type' => 'apple-tvos' ,
'name' => 'tvOS App' ,
'key' => 'com.example.tvos' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$platformAppleTvOsId = $response [ 'body' ][ '$id' ];
2020-07-12 11:57:31 +00:00
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/platforms/' . $platformWebId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformWebId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/platforms/' . $platformFultteriOSId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformFultteriOSId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/platforms/' . $platformFultterAndroidId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformFultterAndroidId , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2023-01-11 23:38:09 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/platforms/' . $platformFultterWebId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2023-01-11 23:38:09 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformFultterWebId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2023-01-11 23:38:09 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/platforms/' . $platformAppleIosId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformAppleIosId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/platforms/' . $platformAppleMacOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformAppleMacOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformAppleWatchOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $id . '/platforms/' . $platformAppleTvOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2021-10-13 13:44:52 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
2022-04-18 16:21:45 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $id . '/platforms/' . $platformAppleTvOsId , array_merge ([
2021-10-13 13:44:52 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2026-03-24 11:53:25 +00:00
'x-appwrite-response-format' => '1.8.0' ,
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
/**
* Test for FAILURE
*/
2026-03-19 11:20:33 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/webhooks/error' , array_merge ([
2020-07-12 11:57:31 +00:00
'content-type' => 'application/json' ,
2026-03-19 11:20:33 +00:00
'x-appwrite-project' => $id ,
'x-appwrite-mode' => 'admin'
2020-07-12 11:57:31 +00:00
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
2020-07-12 13:43:47 +00:00
2022-10-03 08:06:48 +00:00
public function testDeleteProject () : array
{
$data = [];
// Create a team and a project
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
2024-11-15 12:14:14 +00:00
'name' => 'Amazing Team' ,
2022-10-03 08:06:48 +00:00
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
2024-11-15 12:14:14 +00:00
$this -> assertEquals ( 'Amazing Team' , $team [ 'body' ][ 'name' ]);
2022-10-03 08:06:48 +00:00
$this -> assertNotEmpty ( $team [ 'body' ][ '$id' ]);
$teamId = $team [ 'body' ][ '$id' ];
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Amazing Project' ,
'teamId' => $teamId ,
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2022-10-03 08:06:48 +00:00
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Amazing Project' , $project [ 'body' ][ 'name' ]);
$this -> assertEquals ( $teamId , $project [ 'body' ][ 'teamId' ]);
$this -> assertNotEmpty ( $project [ 'body' ][ '$id' ]);
$projectId = $project [ 'body' ][ '$id' ];
// Ensure I can get both team and project
$team = $this -> client -> call ( Client :: METHOD_GET , '/teams/' . $teamId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $team [ 'headers' ][ 'status-code' ]);
$project = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $project [ 'headers' ][ 'status-code' ]);
2023-05-25 00:32:49 +00:00
// Delete Project
2023-05-25 01:26:13 +00:00
$project = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId , array_merge ([
2022-10-03 08:06:48 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2023-05-25 00:32:49 +00:00
], $this -> getHeaders ()));
2022-10-03 08:06:48 +00:00
2023-05-25 00:32:49 +00:00
$this -> assertEquals ( 204 , $project [ 'headers' ][ 'status-code' ]);
2022-10-03 08:06:48 +00:00
// Ensure I can get team but not a project
$team = $this -> client -> call ( Client :: METHOD_GET , '/teams/' . $teamId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $team [ 'headers' ][ 'status-code' ]);
$project = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $project [ 'headers' ][ 'status-code' ]);
return $data ;
}
2024-10-17 14:05:17 +00:00
2024-11-15 12:14:14 +00:00
public function testDeleteSharedProject () : void
{
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Amazing Team' ,
]);
$teamId = $team [ 'body' ][ '$id' ];
// Ensure deleting one project does not affect another project
$project1 = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Amazing Project 1' ,
'teamId' => $teamId ,
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2024-11-15 12:14:14 +00:00
]);
$project2 = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Amazing Project 2' ,
'teamId' => $teamId ,
2025-03-19 07:32:48 +00:00
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
2024-11-15 12:14:14 +00:00
]);
$project1Id = $project1 [ 'body' ][ '$id' ];
$project2Id = $project2 [ 'body' ][ '$id' ];
// Create user in each project
$key1 = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $project1Id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-09 13:34:05 +00:00
'keyId' => ID :: unique (),
2024-11-15 12:14:14 +00:00
'name' => 'Key Test' ,
'scopes' => [ 'users.read' , 'users.write' ],
]);
$user1 = $this -> client -> call ( Client :: METHOD_POST , '/users' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $project1Id ,
'x-appwrite-key' => $key1 [ 'body' ][ 'secret' ],
], [
'userId' => ID :: unique (),
'email' => 'test1@appwrite.io' ,
'password' => 'password' ,
]);
$this -> assertEquals ( 201 , $user1 [ 'headers' ][ 'status-code' ]);
$key2 = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $project2Id . '/keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2026-02-09 13:34:05 +00:00
'keyId' => ID :: unique (),
2024-11-15 12:14:14 +00:00
'name' => 'Key Test' ,
'scopes' => [ 'users.read' , 'users.write' ],
]);
$user2 = $this -> client -> call ( Client :: METHOD_POST , '/users' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $project2Id ,
'x-appwrite-key' => $key2 [ 'body' ][ 'secret' ],
], [
'userId' => ID :: unique (),
'email' => 'test2@appwrite.io' ,
'password' => 'password' ,
]);
$this -> assertEquals ( 201 , $user2 [ 'headers' ][ 'status-code' ]);
// Delete project 1
$project1 = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $project1Id , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $project1 [ 'headers' ][ 'status-code' ]);
// Ensure project 2 user is still there
2025-10-16 08:51:30 +00:00
$this -> assertEventually ( function () use ( $user2 , $project2Id , $key2 ) {
$response = $this -> client -> call ( Client :: METHOD_GET , '/users/' . $user2 [ 'body' ][ '$id' ], [
'content-type' => 'application/json' ,
'x-appwrite-project' => $project2Id ,
'x-appwrite-key' => $key2 [ 'body' ][ 'secret' ],
]);
2024-11-15 12:14:14 +00:00
2025-10-16 08:51:30 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
});
2024-11-21 03:49:49 +00:00
// Create another user in project 2 in case read hits stale cache
$user3 = $this -> client -> call ( Client :: METHOD_POST , '/users' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $project2Id ,
'x-appwrite-key' => $key2 [ 'body' ][ 'secret' ],
], [
'userId' => ID :: unique (),
'email' => 'test3@appwrite.io'
]);
$this -> assertEquals ( 201 , $user3 [ 'headers' ][ 'status-code' ]);
2024-11-15 12:14:14 +00:00
}
2026-02-25 10:38:40 +00:00
public function testCreateProjectVariable () : void
2024-10-17 14:05:17 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectData ();
2024-10-17 14:05:17 +00:00
/**
* Test for SUCCESS
*/
$variable = $this -> client -> call ( Client :: METHOD_POST , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
2026-03-19 14:21:22 +00:00
'variableId' => 'unique()' ,
2026-02-25 10:38:40 +00:00
'key' => 'APP_TEST_CREATE' ,
2025-02-10 14:29:28 +00:00
'value' => 'TESTINGVALUE' ,
'secret' => false
2024-10-17 14:05:17 +00:00
]);
$this -> assertEquals ( 201 , $variable [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 'APP_TEST_CREATE' , $variable [ 'body' ][ 'key' ]);
2025-02-10 16:37:07 +00:00
$this -> assertEquals ( 'TESTINGVALUE' , $variable [ 'body' ][ 'value' ]);
$this -> assertFalse ( $variable [ 'body' ][ 'secret' ]);
2024-10-17 14:05:17 +00:00
2024-10-21 14:33:57 +00:00
// test for secret variable
$variable = $this -> client -> call ( Client :: METHOD_POST , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
2026-03-19 14:21:22 +00:00
'variableId' => 'unique()' ,
2026-02-25 10:38:40 +00:00
'key' => 'APP_TEST_CREATE_1' ,
2024-10-21 14:33:57 +00:00
'value' => 'TESTINGVALUE_1' ,
'secret' => true
]);
$this -> assertEquals ( 201 , $variable [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 'APP_TEST_CREATE_1' , $variable [ 'body' ][ 'key' ]);
2024-10-21 14:33:57 +00:00
$this -> assertEmpty ( $variable [ 'body' ][ 'value' ]);
2024-10-17 14:05:17 +00:00
/**
* Test for FAILURE
*/
// Test for duplicate key
$variable = $this -> client -> call ( Client :: METHOD_POST , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
2026-03-19 14:21:22 +00:00
'variableId' => 'unique()' ,
2026-02-25 10:38:40 +00:00
'key' => 'APP_TEST_CREATE' ,
2024-10-17 14:05:17 +00:00
'value' => 'ANOTHERTESTINGVALUE'
]);
$this -> assertEquals ( 409 , $variable [ 'headers' ][ 'status-code' ]);
// Test for invalid key
$variable = $this -> client -> call ( Client :: METHOD_POST , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
2026-03-19 14:21:22 +00:00
'variableId' => 'unique()' ,
2024-10-17 14:05:17 +00:00
'key' => str_repeat ( " A " , 256 ),
'value' => 'TESTINGVALUE'
]);
$this -> assertEquals ( 400 , $variable [ 'headers' ][ 'status-code' ]);
// Test for invalid value
$variable = $this -> client -> call ( Client :: METHOD_POST , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
2026-03-19 14:21:22 +00:00
'variableId' => 'unique()' ,
2024-10-17 14:05:17 +00:00
'key' => 'LONGKEY' ,
'value' => str_repeat ( " # " , 8193 ),
]);
$this -> assertEquals ( 400 , $variable [ 'headers' ][ 'status-code' ]);
}
2026-02-25 10:38:40 +00:00
public function testListVariables () : void
2024-10-17 14:05:17 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithVariable ();
2024-10-17 14:05:17 +00:00
/**
* Test for SUCCESS
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertGreaterThanOrEqual ( 2 , count ( $response [ 'body' ][ 'variables' ]));
$this -> assertGreaterThanOrEqual ( 2 , $response [ 'body' ][ 'total' ]);
2024-10-17 14:05:17 +00:00
}
2026-02-25 10:38:40 +00:00
public function testGetVariable () : void
2024-10-17 14:05:17 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithVariable ();
2024-10-17 14:05:17 +00:00
/**
* Test for SUCCESS
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/project/variables/' . $data [ 'variableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( " APP_TEST " , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( " TESTINGVALUE " , $response [ 'body' ][ 'value' ]);
2024-10-21 14:33:57 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/project/variables/' . $data [ 'secretVariableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( " APP_TEST_1 " , $response [ 'body' ][ 'key' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'value' ]);
2025-02-11 12:50:54 +00:00
$this -> assertTrue ( $response [ 'body' ][ 'secret' ]);
2024-10-21 14:33:57 +00:00
2024-10-17 14:05:17 +00:00
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/project/variables/NON_EXISTING_VARIABLE' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-25 10:38:40 +00:00
public function testUpdateVariable () : void
2024-10-17 14:05:17 +00:00
{
2026-02-25 10:38:40 +00:00
$data = $this -> setupProjectWithVariable ();
2024-10-17 14:05:17 +00:00
/**
* Test for SUCCESS
*/
$response = $this -> client -> call ( Client :: METHOD_PUT , '/project/variables/' . $data [ 'variableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'key' => 'APP_TEST_UPDATE' ,
'value' => 'TESTINGVALUEUPDATED'
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( " APP_TEST_UPDATE " , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( " TESTINGVALUEUPDATED " , $response [ 'body' ][ 'value' ]);
$variable = $this -> client -> call ( Client :: METHOD_GET , '/project/variables/' . $data [ 'variableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $variable [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( " APP_TEST_UPDATE " , $variable [ 'body' ][ 'key' ]);
$this -> assertEquals ( " TESTINGVALUEUPDATED " , $variable [ 'body' ][ 'value' ]);
2024-10-21 14:33:57 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/project/variables/' . $data [ 'secretVariableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'key' => 'APP_TEST_UPDATE_1' ,
'value' => 'TESTINGVALUEUPDATED_1'
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( " APP_TEST_UPDATE_1 " , $response [ 'body' ][ 'key' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'value' ]);
$variable = $this -> client -> call ( Client :: METHOD_GET , '/project/variables/' . $data [ 'secretVariableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $variable [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( " APP_TEST_UPDATE_1 " , $variable [ 'body' ][ 'key' ]);
$this -> assertEmpty ( $variable [ 'body' ][ 'value' ]);
2025-02-11 12:50:54 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/project/variables/' . $data [ 'secretVariableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'key' => 'APP_TEST_UPDATE_1' ,
'secret' => false ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2024-10-17 18:37:44 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/project/variables' , array_merge ([
2024-10-17 14:05:17 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
2024-10-17 18:37:44 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
// In parallel mode, other tests may create variables on the same project
$this -> assertGreaterThanOrEqual ( 2 , count ( $response [ 'body' ][ 'variables' ]));
// Verify our updated variables exist (may not be at specific positions)
$variableKeys = array_column ( $response [ 'body' ][ 'variables' ], 'key' );
$this -> assertContains ( " APP_TEST_UPDATE " , $variableKeys );
$this -> assertContains ( " APP_TEST_UPDATE_1 " , $variableKeys );
2024-10-17 14:05:17 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/project/variables/' . $data [ 'variableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
2026-03-23 11:56:23 +00:00
], $this -> getHeaders ()), [
'value' => 'TESTINGVALUEUPDATED_2'
]);
2024-10-17 14:05:17 +00:00
2026-03-23 11:56:23 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertSame ( 'TESTINGVALUEUPDATED_2' , $response [ 'body' ][ 'value' ]);
$this -> assertSame ( 'APP_TEST_UPDATE' , $response [ 'body' ][ 'key' ]);
2024-10-17 14:05:17 +00:00
2026-03-23 11:56:23 +00:00
/**
* Test for FAILURE
*/
2024-10-17 14:05:17 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/project/variables/' . $data [ 'variableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
2026-03-23 11:56:23 +00:00
], $this -> getHeaders ()));
2024-10-17 14:05:17 +00:00
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$longKey = str_repeat ( " A " , 256 );
$response = $this -> client -> call ( Client :: METHOD_PUT , '/project/variables/' . $data [ 'variableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'key' => $longKey ,
'value' => 'TESTINGVALUEUPDATED'
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$longValue = str_repeat ( " # " , 8193 );
$response = $this -> client -> call ( Client :: METHOD_PUT , '/project/variables/' . $data [ 'variableId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'key' => 'APP_TEST_UPDATE' ,
'value' => $longValue
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2024-10-17 18:37:44 +00:00
$response = $this -> client -> call ( Client :: METHOD_PUT , '/project/variables/NON_EXISTING_VARIABLE' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $data [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'key' => 'APP_TEST_UPDATE' ,
'value' => 'TESTINGVALUEUPDATED'
]);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
2024-10-17 14:05:17 +00:00
}
2026-02-25 10:38:40 +00:00
public function testDeleteVariable () : void
2024-10-17 14:05:17 +00:00
{
2026-02-25 10:38:40 +00:00
// Create a fresh project with variables for deletion testing
$projectData = $this -> setupProjectData ();
// Create a non-secret variable
$variable = $this -> client -> call ( Client :: METHOD_POST , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectData [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
2026-03-19 14:21:22 +00:00
'variableId' => 'unique()' ,
2026-02-25 10:38:40 +00:00
'key' => 'APP_TEST_DELETE' ,
'value' => 'TESTINGVALUE' ,
'secret' => false
]);
$this -> assertEquals ( 201 , $variable [ 'headers' ][ 'status-code' ]);
$variableId = $variable [ 'body' ][ '$id' ];
// Create a secret variable
$variable = $this -> client -> call ( Client :: METHOD_POST , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectData [ 'projectId' ],
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
2026-03-19 14:21:22 +00:00
'variableId' => 'unique()' ,
2026-02-25 10:38:40 +00:00
'key' => 'APP_TEST_DELETE_1' ,
'value' => 'TESTINGVALUE_1' ,
'secret' => true
]);
$this -> assertEquals ( 201 , $variable [ 'headers' ][ 'status-code' ]);
$secretVariableId = $variable [ 'body' ][ '$id' ];
2024-10-17 14:05:17 +00:00
/**
* Test for SUCCESS
*/
2026-02-25 10:38:40 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/project/variables/' . $variableId , array_merge ([
2024-10-17 14:05:17 +00:00
'content-type' => 'application/json' ,
2026-02-25 10:38:40 +00:00
'x-appwrite-project' => $projectData [ 'projectId' ],
2024-10-17 14:05:17 +00:00
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/project/variables/' . $secretVariableId , array_merge ([
2024-10-21 14:33:57 +00:00
'content-type' => 'application/json' ,
2026-02-25 10:38:40 +00:00
'x-appwrite-project' => $projectData [ 'projectId' ],
2024-10-21 14:33:57 +00:00
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
2026-02-25 10:38:40 +00:00
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
2024-10-17 14:05:17 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/project/variables' , array_merge ([
'content-type' => 'application/json' ,
2026-02-25 10:38:40 +00:00
'x-appwrite-project' => $projectData [ 'projectId' ],
2024-10-17 14:05:17 +00:00
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
// In parallel mode, other tests may have created variables on the same project
// Verify our deleted variables no longer exist by checking their IDs are not present
$variableIds = array_column ( $response [ 'body' ][ 'variables' ], '$id' );
$this -> assertNotContains ( $variableId , $variableIds );
$this -> assertNotContains ( $secretVariableId , $variableIds );
2024-10-17 14:05:17 +00:00
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/project/variables/NON_EXISTING_VARIABLE' , array_merge ([
'content-type' => 'application/json' ,
2026-02-25 10:38:40 +00:00
'x-appwrite-project' => $projectData [ 'projectId' ],
2024-10-17 14:05:17 +00:00
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
2025-04-14 18:01:40 +00:00
/**
* Devkeys Tests starts here ------------------------------------------------
*/
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testCreateProjectDevKey () : void
{
/**
* Test for SUCCESS
*/
$id = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testCreateProjectDevKey' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'name' => 'Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Key Test' , $response [ 'body' ][ 'name' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'secret' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
/** Create a second dev key */
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Dev Key Test' , $response [ 'body' ][ 'name' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'secret' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
/**
* Test for FAILURE
*/
/** TEST expiry date is required */
$res = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $id . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'name' => 'Key Test'
]);
$this -> assertEquals ( 400 , $res [ 'headers' ][ 'status-code' ]);
}
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testListProjectDevKey () : void
{
/**
* Test for SUCCESS
*/
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testListProjectDevKey' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
/** Create devKey 1 */
$this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
/** Create devKey 2 */
$this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
/** List all dev keys */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 2 , $response [ 'body' ][ 'total' ]);
/** List dev keys with limit */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: limit ( 1 ) -> toString ()
]
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 1 , $response [ 'body' ][ 'total' ]);
/** List dev keys with search */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2025-05-13 13:29:16 +00:00
], $this -> getHeaders ()));
2025-04-14 18:01:40 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-05-13 13:29:16 +00:00
$this -> assertEquals ( 2 , $response [ 'body' ][ 'total' ]);
$this -> assertEquals ( 'Key Test' , $response [ 'body' ][ 'devKeys' ][ 0 ][ 'name' ]);
$this -> assertEquals ( 'Dev Key Test' , $response [ 'body' ][ 'devKeys' ][ 1 ][ 'name' ]);
2025-04-14 18:01:40 +00:00
/** List dev keys with querying `expire` */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [ Query :: lessThan ( 'expire' , ( new \DateTime ()) -> format ( 'Y-m-d H:i:s' )) -> toString ()]
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 0 , $response [ 'body' ][ 'total' ]); // No dev keys expired
/**
* Test for FAILURE
*/
/** Test for search with invalid query */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: search ( 'name' , 'Invalid' ) -> toString ()
]
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'Invalid `queries` param: Invalid query: Attribute not found in schema: name' , $response [ 'body' ][ 'message' ]);
}
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testGetProjectDevKey () : void
{
/**
* Test for SUCCESS
*/
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testGetProjectDevKey' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$devKey = $this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys/' . $devKey [ '$id' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $devKey [ '$id' ], $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Dev Key Test' , $response [ 'body' ][ 'name' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'secret' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys/error' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testGetDevKeyWithSdks () : void
{
/**
* Test for SUCCESS
*/
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testGetDevKeyWithSdks' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$devKey = $this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
/** Use dev key with python sdk */
$res = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ],
'x-sdk-name' => 'python'
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 401 , $res [ 'headers' ][ 'status-code' ]);
/** Use dev key with php sdk */
$res = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ],
'x-sdk-name' => 'php'
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 401 , $res [ 'headers' ][ 'status-code' ]);
/** Get the dev key */
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys/' . $devKey [ '$id' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'sdks' , $response [ 'body' ]);
$this -> assertCount ( 2 , $response [ 'body' ][ 'sdks' ]);
$this -> assertContains ( 'python' , $response [ 'body' ][ 'sdks' ]);
$this -> assertContains ( 'php' , $response [ 'body' ][ 'sdks' ]);
}
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testNoHostValidationWithDevKey () : void
{
/**
* Test for SUCCESS
*/
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testNoHostValidationWithDevKey' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$devKey = $this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
2025-04-15 10:47:04 +00:00
$provider = 'mock' ;
$appId = '1' ;
$secret = '123456' ;
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $projectId . '/oauth2' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'provider' => $provider ,
'appId' => $appId ,
'secret' => $secret ,
'enabled' => true ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-04-14 18:01:40 +00:00
/** Test oauth2 and get invalid `success` URL */
2025-04-15 10:47:04 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider , [
2025-04-14 18:01:40 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
], [
'success' => 'https://example.com' ,
'failure' => 'https://example.com'
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2026-02-16 16:18:58 +00:00
/** Test oauth2 with devKey and now flow works with untrusted URL too */
2025-04-15 10:47:04 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider , [
2025-04-14 18:01:40 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ]
], [
'success' => 'https://example.com' ,
'failure' => 'https://example.com'
2026-02-16 16:06:11 +00:00
], followRedirects : false );
2026-02-16 16:18:58 +00:00
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'location' , $response [ 'headers' ]);
$location = $response [ 'headers' ][ 'location' ];
$locationClient = new Client ();
$locationClient -> setEndpoint ( '' );
$locationClient -> addHeader ( 'x-appwrite-dev-key' , $devKey [ 'secret' ]);
$response = $locationClient -> call ( Client :: METHOD_GET , $location , followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'location' , $response [ 'headers' ]);
$location = $response [ 'headers' ][ 'location' ];
$this -> assertStringStartsWith ( 'http://appwrite:/v1/account/sessions/oauth2/callback/mock/' , $response [ 'headers' ][ 'location' ]);
$response = $locationClient -> call ( Client :: METHOD_GET , $location , followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'location' , $response [ 'headers' ]);
$location = $response [ 'headers' ][ 'location' ];
$this -> assertStringStartsWith ( 'http://appwrite:/v1/account/sessions/oauth2/mock/redirect' , $response [ 'headers' ][ 'location' ]);
$response = $locationClient -> call ( Client :: METHOD_GET , $location , followRedirects : false );
2026-02-16 16:06:11 +00:00
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
2026-02-16 16:18:58 +00:00
$this -> assertSame ( 'https://example.com/#' , $response [ 'headers' ][ 'location' ]);
2025-04-14 18:01:40 +00:00
2026-02-08 13:44:21 +00:00
/** Ensure any hostname is allowed */
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ],
'origin' => '' ,
'referer' => 'https://domain-without-rule.com'
], [
'success' => 'https://domain-without-rule.com' ,
'failure' => 'https://domain-without-rule.com'
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
2026-02-08 13:47:47 +00:00
2026-02-08 13:44:21 +00:00
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ],
'referer' => '' ,
'origin' => 'https://domain-without-rule.com'
], [
'success' => 'https://domain-without-rule.com' ,
'failure' => 'https://domain-without-rule.com'
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
2025-04-14 18:01:40 +00:00
/** Test hostname in Magic URL */
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/magic-url' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
], [
'userId' => ID :: unique (),
'email' => 'user@appwrite.io' ,
'url' => 'https://example.com' ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
/** Test hostname in Magic URL with devKey */
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/magic-url' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ]
], [
'userId' => ID :: unique (),
'email' => 'user@appwrite.io' ,
'url' => 'https://example.com' ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-08 13:36:34 +00:00
public function testRuleOAuthRedirect () : void
{
// Prepare project
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testRuleOAuthRedirect' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$provider = 'mock' ;
$appId = '1' ;
$secret = '123456' ;
// Prepare OAuth provider
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $projectId . '/oauth2' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'provider' => $provider ,
'appId' => $appId ,
'secret' => $secret ,
'enabled' => true ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
// Prepare rule. In reality this is site rule, but for testing, API rule is enough, and faster to prepare
$domain = \uniqid () . '-with-rule.custom.localhost' ;
$rule = $this -> client -> call ( Client :: METHOD_POST , '/proxy/rules/api' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'domain' => $domain
]);
$this -> assertEquals ( 201 , $rule [ 'headers' ][ 'status-code' ]);
// Ensure unknown domain cannot be redirect URL
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'referer' => 'https://' . $domain ,
2026-02-08 13:44:21 +00:00
'origin' => '' ,
2026-02-08 13:36:34 +00:00
], [
'success' => 'https://domain-without-rule.com' ,
'failure' => 'https://domain-without-rule.com'
], followRedirects : false );
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
2026-02-09 12:57:19 +00:00
// Also ensure final step blocks unknown redirect URL
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider . '/redirect' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'origin' => '' ,
'referer' => 'https://mockserver.com' ,
], [
'code' => 'any-code' ,
'state' => \json_encode ([
'success' => 'https://domain-without-rule.com' ,
'failure' => 'https://domain-without-rule.com'
]),
'error' => '' ,
2026-02-09 16:10:00 +00:00
'error_description' => '' ,
2026-02-09 12:57:19 +00:00
], followRedirects : false );
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( 'project_invalid_success_url' , $response [ 'body' ]);
2026-02-08 13:36:34 +00:00
// Ensure rule's domain can be redirect URL
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'referer' => 'https://' . $domain ,
2026-02-08 13:44:21 +00:00
'origin' => '' ,
2026-02-08 13:36:34 +00:00
], [
'success' => 'https://' . $domain ,
'failure' => 'https://' . $domain
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
2026-02-09 12:57:19 +00:00
// Also ensure final step allows redirect URL
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider . '/redirect' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'origin' => '' ,
'referer' => 'https://mockserver.com' ,
], [
'code' => 'any-code' ,
'state' => \json_encode ([
2026-02-09 13:34:52 +00:00
'success' => 'https://' . $domain ,
'failure' => 'https://' . $domain
2026-02-09 12:57:19 +00:00
]),
'error' => '' ,
2026-02-09 16:10:00 +00:00
'error_deescription' => '' ,
2026-02-09 12:57:19 +00:00
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( 'https://' . $domain , $response [ 'headers' ][ 'location' ]);
2026-02-08 13:36:34 +00:00
// Ensure unknown domain cannot be redirect URL
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/magic-url' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'referer' => 'https://' . $domain ,
2026-02-08 13:44:21 +00:00
'origin' => '' ,
2026-02-08 13:36:34 +00:00
], [
'userId' => ID :: unique (),
'email' => 'user@appwrite.io' ,
'url' => 'https://domain-without-rule.com' ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
// Ensure rule's domain can be redirect URL
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/magic-url' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'referer' => 'https://' . $domain ,
2026-02-08 13:44:21 +00:00
'origin' => '' ,
2026-02-08 13:36:34 +00:00
], [
'userId' => ID :: unique (),
'email' => 'user@appwrite.io' ,
'url' => 'https://' . $domain ,
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-11 04:41:04 +00:00
public function testOAuthRedirectWithCustomSchemeState () : void
{
// Prepare project
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testOAuthRedirectWithCustomSchemeState' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$provider = 'mock' ;
$appId = '1' ;
$secret = '123456' ;
// Prepare OAuth provider
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $projectId . '/oauth2' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'provider' => $provider ,
'appId' => $appId ,
'secret' => $secret ,
'enabled' => true ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$scheme = 'appwrite-callback-' . $projectId ;
$state = \json_encode ([
'success' => $scheme . ':///' ,
'failure' => $scheme . ':///'
]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/account/sessions/oauth2/' . $provider . '/redirect' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'origin' => '' ,
'referer' => '' ,
], [
'code' => 'any-code' ,
'state' => $state ,
'error' => 'access_denied' ,
'error_description' => 'test' ,
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringStartsWith ( $scheme . '://' , $response [ 'headers' ][ 'location' ]);
$this -> assertStringContainsString ( 'error=' , $response [ 'headers' ][ 'location' ]);
}
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testCorsWithDevKey () : void
{
/**
* Test for SUCCESS
*/
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testCorsWithDevKey' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$devKey = $this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
$origin = 'http://example.com' ;
/**
* Test CORS without Dev Key ( should fail due to origin )
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => $origin ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 403 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEquals ( $origin , $response [ 'headers' ][ 'access-control-allow-origin' ] ? ? null );
2025-12-07 20:29:45 +00:00
// you should not return a fallback origin for a disallowed host
$this -> assertNull ( $response [ 'headers' ][ 'access-control-allow-origin' ] ? ? null );
2025-04-14 18:01:40 +00:00
/**
* Test CORS with Dev Key ( should bypass origin check )
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => $origin ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ]
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
2025-12-07 20:29:45 +00:00
$this -> assertEquals ( $origin , $response [ 'headers' ][ 'access-control-allow-origin' ] ? ? null );
2025-04-14 18:01:40 +00:00
}
2026-02-04 13:45:38 +00:00
public function testConsoleCorsWithTrustedProject () : void
{
$trustedProjectIds = [ 'trusted-project' , 'another-trusted-project' ]; // Set in env variable
$projectIds = \array_merge ( $trustedProjectIds , [ 'untrusted-project-id' ]);
foreach ( $projectIds as $projectId ) {
try {
// Create project
$this -> setupProject ([
'projectId' => $projectId ,
'name' => 'Trusted project' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
// Add domain to trusted project; API for simplicity, in real work this will be site
$domain = \uniqid () . '.custom.localhost' ;
$rule = $this -> client -> call ( Client :: METHOD_POST , '/proxy/rules/api' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-mode' => 'admin' ,
], $this -> getHeaders ()), [
'domain' => $domain
]);
$this -> assertEquals ( 201 , $rule [ 'headers' ][ 'status-code' ]);
// Talk to Console APIs from trusted project domain
$currencies = $this -> client -> call (
Client :: METHOD_GET ,
'/locale/currencies' ,
array_merge (
$this -> getHeaders (),
[
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
'origin' => 'http://' . $domain
]
)
);
if ( \in_array ( $projectId , $trustedProjectIds )) {
// Trusted projects can
2026-02-04 14:09:02 +00:00
$this -> assertEquals ( 200 , $currencies [ 'headers' ][ 'status-code' ]);
2026-02-04 13:45:38 +00:00
$this -> assertSame ( 'http://' . $domain , $currencies [ 'headers' ][ 'access-control-allow-origin' ]);
} else {
// Untrusted projects cannot
2026-02-04 14:09:02 +00:00
$this -> assertEquals ( 403 , $currencies [ 'headers' ][ 'status-code' ]);
2026-02-04 13:45:38 +00:00
$this -> assertArrayNotHasKey ( 'access-control-allow-origin' , $currencies [ 'headers' ]);
}
} finally {
// Cleanup
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
}
}
}
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testNoRateLimitWithDevKey () : void
{
/**
* Test for SUCCESS
*/
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testNoRateLimitWithDevKey' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$devKey = $this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
/**
* Test for SUCCESS
*/
2025-08-12 12:20:30 +00:00
for ( $i = 0 ; $i < 10 ; $i ++ ) {
2025-04-14 18:01:40 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
2025-09-16 16:13:38 +00:00
2025-04-14 18:01:40 +00:00
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
}
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
2025-09-16 16:13:38 +00:00
2025-04-14 18:01:40 +00:00
$this -> assertEquals ( 429 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ]
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_POST , '/projects/' . $projectId . '/dev-keys' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'name' => 'Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), - 3600 ),
]);
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $response [ 'body' ][ 'secret' ]
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 429 , $response [ 'headers' ][ 'status-code' ]);
/**
* Test for FAILURE after expire
*/
$devKey = $this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test Expire 5 seconds' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 5 )
]);
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ]
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
2026-02-25 10:38:40 +00:00
$this -> assertEventually ( function () use ( $projectId , $devKey ) {
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ]
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 429 , $response [ 'headers' ][ 'status-code' ]);
}, 15_000 , 500 );
2025-04-14 18:01:40 +00:00
}
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testUpdateProjectDevKey () : void
{
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testUpdateProjectDevKey' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$devKey = $this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
$response = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $projectId . '/dev-keys/' . $devKey [ '$id' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'name' => 'Key Test Update' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 360 ),
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $devKey [ '$id' ], $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Key Test Update' , $response [ 'body' ][ 'name' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys/' . $devKey [ '$id' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( $devKey [ '$id' ], $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Key Test Update' , $response [ 'body' ][ 'name' ]);
$this -> assertArrayHasKey ( 'accessedAt' , $response [ 'body' ]);
$this -> assertEmpty ( $response [ 'body' ][ 'accessedAt' ]);
}
2026-02-25 10:38:40 +00:00
#[Group('abuseEnabled')]
2025-04-14 18:01:40 +00:00
public function testDeleteProjectDevKey () : void
{
$projectId = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'testDeleteProjectDevKey' ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$devKey = $this -> setupDevKey ([
'projectId' => $projectId ,
'name' => 'Dev Key Test' ,
'expire' => DateTime :: addSeconds ( new \DateTime (), 36000 )
]);
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId . '/dev-keys/' . $devKey [ '$id' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $response [ 'body' ]);
/**
2025-12-12 04:58:59 +00:00
* Get rate limit trying to use the deleted key
*/
2025-04-14 18:01:40 +00:00
$response = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-dev-key' => $devKey [ 'secret' ]
], [
'email' => 'user@appwrite.io' ,
'password' => 'password'
]);
$this -> assertEquals ( 429 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects/' . $projectId . '/dev-keys/' . $devKey [ '$id' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
/**
* Test for FAILURE
*/
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId . '/dev-keys/error' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), []);
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
}
/**
* Devkeys Tests ends here ------------------------------------------------
*/
2025-12-31 14:44:18 +00:00
public function testProjectLabels () : void
{
// Setup: Prepare team
$team = $this -> client -> call ( Client :: METHOD_POST , '/teams' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'teamId' => ID :: unique (),
'name' => 'Query Select Test Team' ,
]);
$this -> assertEquals ( 201 , $team [ 'headers' ][ 'status-code' ]);
$teamId = $team [ 'body' ][ '$id' ];
// Setup: Prepare project
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Test project - Labels 1' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertIsArray ( $project [ 'body' ][ 'labels' ]);
$this -> assertCount ( 0 , $project [ 'body' ][ 'labels' ]);
$projectId = $project [ 'body' ][ '$id' ];
// Apply labels
$project = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $projectId . '/labels' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'labels' => [ 'vip' , 'imagine' , 'blocked' ]
]);
$this -> assertEquals ( 200 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertIsArray ( $project [ 'body' ][ 'labels' ]);
$this -> assertCount ( 3 , $project [ 'body' ][ 'labels' ]);
$this -> assertEquals ( 'vip' , $project [ 'body' ][ 'labels' ][ 0 ]);
$this -> assertEquals ( 'imagine' , $project [ 'body' ][ 'labels' ][ 1 ]);
$this -> assertEquals ( 'blocked' , $project [ 'body' ][ 'labels' ][ 2 ]);
// Update labels
$project = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $projectId . '/labels' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'labels' => [ 'nonvip' , 'imagine' ]
]);
$this -> assertEquals ( 200 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertIsArray ( $project [ 'body' ][ 'labels' ]);
$this -> assertCount ( 2 , $project [ 'body' ][ 'labels' ]);
$this -> assertEquals ( 'nonvip' , $project [ 'body' ][ 'labels' ][ 0 ]);
$this -> assertEquals ( 'imagine' , $project [ 'body' ][ 'labels' ][ 1 ]);
// Filter by labels
$projects = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: contains ( 'labels' , [ 'nonvip' ]) -> toString (),
]
]);
2026-01-05 13:42:03 +00:00
$this -> assertEquals ( 200 , $projects [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$this -> assertEquals ( 1 , $projects [ 'body' ][ 'total' ]);
$this -> assertEquals ( $projectId , $projects [ 'body' ][ 'projects' ][ 0 ][ '$id' ]);
$projects = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: contains ( 'labels' , [ 'vip' ]) -> toString (),
]
]);
2026-01-05 13:42:03 +00:00
$this -> assertEquals ( 200 , $projects [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$this -> assertEquals ( 0 , $projects [ 'body' ][ 'total' ]);
$projects = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: contains ( 'labels' , [ 'imagine' ]) -> toString (),
]
]);
2026-01-05 13:42:03 +00:00
$this -> assertEquals ( 200 , $projects [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$this -> assertEquals ( 1 , $projects [ 'body' ][ 'total' ]);
$this -> assertEquals ( $projectId , $projects [ 'body' ][ 'projects' ][ 0 ][ '$id' ]);
$projects = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: contains ( 'labels' , [ 'nonvip' , 'imagine' ]) -> toString (),
]
]);
2026-01-05 13:42:03 +00:00
$this -> assertEquals ( 200 , $projects [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$this -> assertEquals ( 1 , $projects [ 'body' ][ 'total' ]);
$this -> assertEquals ( $projectId , $projects [ 'body' ][ 'projects' ][ 0 ][ '$id' ]);
// Setup: Second project with only imagine label
$project = $this -> client -> call ( Client :: METHOD_POST , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'projectId' => ID :: unique (),
'name' => 'Test project - Labels 2' ,
'teamId' => $teamId ,
'region' => System :: getEnv ( '_APP_REGION' , 'default' )
]);
$this -> assertEquals ( 201 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertIsArray ( $project [ 'body' ][ 'labels' ]);
$this -> assertCount ( 0 , $project [ 'body' ][ 'labels' ]);
$projectId2 = $project [ 'body' ][ '$id' ];
$project = $this -> client -> call ( Client :: METHOD_PUT , '/projects/' . $projectId2 . '/labels' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'labels' => [ 'vip' , 'imagine' ]
]);
$this -> assertEquals ( 200 , $project [ 'headers' ][ 'status-code' ]);
$this -> assertIsArray ( $project [ 'body' ][ 'labels' ]);
$this -> assertCount ( 2 , $project [ 'body' ][ 'labels' ]);
$this -> assertEquals ( 'vip' , $project [ 'body' ][ 'labels' ][ 0 ]);
$this -> assertEquals ( 'imagine' , $project [ 'body' ][ 'labels' ][ 1 ]);
// List of imagine has both
$projects = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: contains ( 'labels' , [ 'imagine' ]) -> toString (),
]
]);
2026-01-05 13:42:03 +00:00
$this -> assertEquals ( 200 , $projects [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$this -> assertEquals ( 2 , $projects [ 'body' ][ 'total' ]);
$this -> assertEquals ( $projectId , $projects [ 'body' ][ 'projects' ][ 0 ][ '$id' ]);
$this -> assertEquals ( $projectId2 , $projects [ 'body' ][ 'projects' ][ 1 ][ '$id' ]);
// List of vip only has second
$projects = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: contains ( 'labels' , [ 'vip' ]) -> toString (),
]
]);
2026-01-05 13:42:03 +00:00
$this -> assertEquals ( 200 , $projects [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$this -> assertEquals ( 1 , $projects [ 'body' ][ 'total' ]);
$this -> assertEquals ( $projectId2 , $projects [ 'body' ][ 'projects' ][ 0 ][ '$id' ]);
// List of vip and imagine has second
$projects = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: contains ( 'labels' , [ 'vip' ]) -> toString (),
Query :: contains ( 'labels' , [ 'imagine' ]) -> toString (),
]
]);
2026-01-05 13:42:03 +00:00
$this -> assertEquals ( 200 , $projects [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$this -> assertEquals ( 1 , $projects [ 'body' ][ 'total' ]);
$this -> assertEquals ( $projectId2 , $projects [ 'body' ][ 'projects' ][ 0 ][ '$id' ]);
// List of vip or imagine has second
$projects = $this -> client -> call ( Client :: METHOD_GET , '/projects' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: contains ( 'labels' , [ 'vip' , 'imagine' ]) -> toString (),
]
]);
2026-01-05 13:42:03 +00:00
$this -> assertEquals ( 200 , $projects [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$this -> assertEquals ( 2 , $projects [ 'body' ][ 'total' ]);
$this -> assertEquals ( $projectId , $projects [ 'body' ][ 'projects' ][ 0 ][ '$id' ]);
$this -> assertEquals ( $projectId2 , $projects [ 'body' ][ 'projects' ][ 1 ][ '$id' ]);
// Cleanup
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
2026-01-05 13:42:03 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId2 , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
2025-12-31 14:44:18 +00:00
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/teams/' . $teamId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
}
2026-02-19 11:18:39 +00:00
2026-02-25 10:38:40 +00:00
#[Group('ciIgnore')]
2026-02-19 11:18:39 +00:00
public function testProjectSpecificPermissionsForListProjects () : void
{
$teamId = ID :: unique ();
$projectIdA = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test A' ,
], $teamId );
$projectIdB = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test B' ,
], $teamId , false );
$testUserEmail = 'test-' . ID :: unique () . '@localhost.test' ;
$testUserName = 'Test User' ;
[ 'membershipId' => $testUserMembershipId ] = $this -> setupUserMembership ([
'teamId' => $teamId ,
'email' => $testUserEmail ,
'name' => $testUserName ,
'roles' => [ " owner " ],
]);
$testCases = [
[
'roles' => [ " owner " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
],
[
'roles' => [ " developer " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
],
[
'roles' => [ " project- $projectIdA -owner " ],
'successProjectIds' => [ $projectIdA ],
],
[
'roles' => [ " project- $projectIdB -owner " ],
'successProjectIds' => [ $projectIdB ],
],
[
'roles' => [ " project- $projectIdA -developer " ],
'successProjectIds' => [ $projectIdA ],
],
[
'roles' => [ " project- $projectIdB -developer " ],
'successProjectIds' => [ $projectIdB ],
],
[
'roles' => [ " developer " , " project- $projectIdA -owner " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
]
];
// Setup session
$session = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], [
'email' => $testUserEmail ,
'password' => 'password' ,
]);
$token = $session [ 'cookies' ][ 'a_session_' . $this -> getProject ()[ '$id' ]];
foreach ( $testCases as $testCase ) {
$this -> updateMembershipRole ( $teamId , $testUserMembershipId , $testCase [ 'roles' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/projects' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_' . $this -> getProject ()[ '$id' ] . '=' . $token ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertCount ( \count ( $testCase [ 'successProjectIds' ]), $response [ 'body' ][ 'projects' ]);
$returnedProjectIds = \array_column ( $response [ 'body' ][ 'projects' ], '$id' );
foreach ( $testCase [ 'successProjectIds' ] as $projectId ) {
$this -> assertContains ( $projectId , $returnedProjectIds );
}
}
}
2026-02-25 10:38:40 +00:00
#[Group('ciIgnore')]
2026-02-19 11:18:39 +00:00
public function testProjectSpecificPermissionsForUpdateProject () : void
{
$teamId = ID :: unique ();
$projectIdA = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test A' ,
], $teamId );
$projectIdB = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test B' ,
], $teamId , false );
$testUserEmail = 'test-' . ID :: unique () . '@localhost.test' ;
$testUserName = 'Test User' ;
[ 'membershipId' => $testUserMembershipId ] = $this -> setupUserMembership ([
'teamId' => $teamId ,
'email' => $testUserEmail ,
'name' => $testUserName ,
'roles' => [ " owner " ],
]);
$testCases = [
[
'roles' => [ " owner " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
'failureProjectIds' => [],
],
[
'roles' => [ " developer " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
'failureProjectIds' => [],
],
[
'roles' => [ " project- $projectIdA -owner " ],
'successProjectIds' => [ $projectIdA ],
'failureProjectIds' => [ $projectIdB ],
],
[
'roles' => [ " project- $projectIdB -owner " ],
'successProjectIds' => [ $projectIdB ],
'failureProjectIds' => [ $projectIdA ],
],
[
'roles' => [ " project- $projectIdA -developer " ],
'successProjectIds' => [ $projectIdA ],
'failureProjectIds' => [ $projectIdB ],
],
[
'roles' => [ " project- $projectIdB -developer " ],
'successProjectIds' => [ $projectIdB ],
'failureProjectIds' => [ $projectIdA ],
],
[
'roles' => [ " developer " , " project- $projectIdA -owner " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
'failureProjectIds' => [],
]
];
// Setup session
$session = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], [
'email' => $testUserEmail ,
'password' => 'password' ,
]);
$token = $session [ 'cookies' ][ 'a_session_' . $this -> getProject ()[ '$id' ]];
foreach ( $testCases as $testCase ) {
$this -> updateMembershipRole ( $teamId , $testUserMembershipId , $testCase [ 'roles' ]);
foreach ( $testCase [ 'successProjectIds' ] as $projectId ) {
$newProjectName = 'Updated Project Name ' . ID :: unique ();
// Success: User should be able to update the project they have access to.
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $projectId , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_' . $this -> getProject ()[ '$id' ] . '=' . $token ,
], [
'name' => $newProjectName ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ]);
$this -> assertEquals ( $newProjectName , $response [ 'body' ][ 'name' ]);
}
foreach ( $testCase [ 'failureProjectIds' ] as $projectId ) {
$newProjectName = 'Updated Project Name ' . ID :: unique ();
// Failure: User should not be able to update the project they do not have access to.
$response = $this -> client -> call ( Client :: METHOD_PATCH , '/projects/' . $projectId , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_' . $this -> getProject ()[ '$id' ] . '=' . $token ,
], [
'name' => $newProjectName ,
]);
$this -> assertTrue ( $response [ 'headers' ][ 'status-code' ] === 401 || $response [ 'headers' ][ 'status-code' ] === 404 );
}
}
}
2026-02-25 10:38:40 +00:00
#[Group('ciIgnore')]
2026-02-19 11:18:39 +00:00
public function testProjectSpecificPermissionsForDeleteProject () : void
{
$teamId = ID :: unique ();
$projectIdA = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test A' ,
], $teamId );
$projectIdB = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test B' ,
], $teamId , false );
$projectIdC = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test C' ,
], $teamId , false );
$projectIdD = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test D' ,
], $teamId , false );
$projectIdE = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test E' ,
], $teamId , false );
$testUserEmail = 'test-' . ID :: unique () . '@localhost.test' ;
$testUserName = 'Test User' ;
[ 'membershipId' => $testUserMembershipId ] = $this -> setupUserMembership ([
'teamId' => $teamId ,
'email' => $testUserEmail ,
'name' => $testUserName ,
'roles' => [ " owner " ],
]);
$testCases = [
[
'roles' => [ " owner " ],
'successProjectIds' => [ $projectIdA ],
'failureProjectIds' => [],
],
[
'roles' => [ " developer " ],
'successProjectIds' => [ $projectIdB , $projectIdC ],
'failureProjectIds' => [],
],
[
'roles' => [ " project- $projectIdD -owner " ],
'successProjectIds' => [ $projectIdD ],
'failureProjectIds' => [ $projectIdE ],
],
[
'roles' => [ " project- $projectIdE -owner " ],
'successProjectIds' => [ $projectIdE ],
'failureProjectIds' => [],
],
];
// Setup session
$session = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], [
'email' => $testUserEmail ,
'password' => 'password' ,
]);
$token = $session [ 'cookies' ][ 'a_session_' . $this -> getProject ()[ '$id' ]];
foreach ( $testCases as $testCase ) {
$this -> updateMembershipRole ( $teamId , $testUserMembershipId , $testCase [ 'roles' ]);
foreach ( $testCase [ 'successProjectIds' ] as $projectId ) {
// Success: User should be able to delete the project they have access to.
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_' . $this -> getProject ()[ '$id' ] . '=' . $token ,
]);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
}
foreach ( $testCase [ 'failureProjectIds' ] as $projectId ) {
// Failure: User should not be able to delete the project they do not have access to.
$response = $this -> client -> call ( Client :: METHOD_DELETE , '/projects/' . $projectId , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'cookie' => 'a_session_' . $this -> getProject ()[ '$id' ] . '=' . $token ,
]);
$this -> assertTrue ( $response [ 'headers' ][ 'status-code' ] === 401 || $response [ 'headers' ][ 'status-code' ] === 404 );
}
}
}
/**
* Test project specific permissions for project resources , in this case 'function variables' .
*/
2026-02-25 10:38:40 +00:00
#[Group('ciIgnore')]
2026-02-19 11:18:39 +00:00
public function testProjectSpecificPermissionsForProjectResources () : void
{
$teamId = ID :: unique ();
$projectIdA = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test A' ,
], $teamId );
$projectIdB = $this -> setupProject ([
'projectId' => ID :: unique (),
'name' => 'Project Test B' ,
], $teamId , false );
$testUserEmail = 'test-' . ID :: unique () . '@localhost.test' ;
$testUserName = 'Test User' ;
[ 'membershipId' => $testUserMembershipId ] = $this -> setupUserMembership ([
'teamId' => $teamId ,
'email' => $testUserEmail ,
'name' => $testUserName ,
'roles' => [ " owner " ],
]);
$testCases = [
[
'roles' => [ " owner " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
'failureProjectIds' => [],
],
[
'roles' => [ " developer " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
'failureProjectIds' => [],
],
[
'roles' => [ " project- $projectIdA -owner " ],
'successProjectIds' => [ $projectIdA ],
'failureProjectIds' => [ $projectIdB ],
],
[
'roles' => [ " project- $projectIdB -owner " ],
'successProjectIds' => [ $projectIdB ],
'failureProjectIds' => [ $projectIdA ],
],
[
'roles' => [ " project- $projectIdA -developer " ],
'successProjectIds' => [ $projectIdA ],
'failureProjectIds' => [ $projectIdB ],
],
[
'roles' => [ " project- $projectIdB -developer " ],
'successProjectIds' => [ $projectIdB ],
'failureProjectIds' => [ $projectIdA ],
],
[
'roles' => [ " developer " , " project- $projectIdA -owner " ],
'successProjectIds' => [ $projectIdA , $projectIdB ],
'failureProjectIds' => [],
]
];
// Setup session
$session = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], [
'email' => $testUserEmail ,
'password' => 'password' ,
]);
$token = $session [ 'cookies' ][ 'a_session_' . $this -> getProject ()[ '$id' ]];
// Setup functions
$functionId = ID :: unique ();
$this -> setupFunction ( $projectIdA , $functionId , $token );
$this -> setupFunction ( $projectIdB , $functionId , $token );
foreach ( $testCases as $testCase ) {
$this -> updateMembershipRole ( $teamId , $testUserMembershipId , $testCase [ 'roles' ]);
foreach ( $testCase [ 'successProjectIds' ] as $projectId ) {
$variableId = ID :: unique ();
$response = $this -> client -> call ( Client :: METHOD_POST , '/functions/' . $functionId . '/variables' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-mode' => 'admin' ,
'cookie' => 'a_session_' . $this -> getProject ()[ '$id' ] . '=' . $token ,
], [
'key' => 'APP_TEST_' . $variableId ,
'value' => 'TESTINGVALUE' ,
'secret' => false
]);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'APP_TEST_' . $variableId , $response [ 'body' ][ 'key' ]);
$this -> assertEquals ( 'TESTINGVALUE' , $response [ 'body' ][ 'value' ]);
}
foreach ( $testCase [ 'failureProjectIds' ] as $projectId ) {
$variableId = ID :: unique ();
$response = $this -> client -> call ( Client :: METHOD_POST , '/functions/' . $functionId . '/variables' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => $projectId ,
'x-appwrite-mode' => 'admin' ,
'cookie' => 'a_session_' . $this -> getProject ()[ '$id' ] . '=' . $token ,
], [
'key' => 'APP_TEST_' . $variableId ,
'value' => 'TESTINGVALUE' ,
'secret' => false
]);
$this -> assertTrue ( $response [ 'headers' ][ 'status-code' ] === 401 || $response [ 'headers' ][ 'status-code' ] === 404 );
}
}
}
2026-02-25 10:38:40 +00:00
public function testPasswordRecoveryUrlParams () : void
{
// With search params
$url = 'http://localhost/auth/signin?id=abcd1234&tenant=efgh5678&domain=example.com&referred=0' ;
$response = $this -> client -> call (
Client :: METHOD_POST ,
'/account/recovery' ,
array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()),
[
'userId' => ID :: unique (),
'email' => $this -> getUser ()[ 'email' ],
'url' => $url ,
]
);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'userId' ]);
$userId = $response [ 'body' ][ 'userId' ];
2026-03-05 14:41:35 +00:00
$userEmail = $this -> getUser ()[ 'email' ];
$lastEmail = $this -> getLastEmailByAddress ( $userEmail , function ( $email ) use ( $url ) {
2026-02-25 10:38:40 +00:00
$this -> assertStringContainsString ( $url , $email [ 'html' ] ? ? '' );
});
$this -> assertEquals ( 'Password Reset for ' . $this -> getProject ()[ 'name' ], $lastEmail [ 'subject' ]);
$expectedUrl = $url . " &userId= " . $userId . " &secret= " ;
$this -> assertStringContainsString ( $expectedUrl , $lastEmail [ 'html' ]);
// With search params, with mobile backlink
$url = 'appwriteio://signin?id=abcd1234&tenant=efgh5678&domain=example.com&referred=0' ;
$response = $this -> client -> call (
Client :: METHOD_POST ,
'/account/recovery' ,
array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()),
[
'userId' => ID :: unique (),
2026-03-05 14:41:35 +00:00
'email' => $userEmail ,
2026-02-25 10:38:40 +00:00
'url' => $url ,
]
);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'userId' ]);
$userId = $response [ 'body' ][ 'userId' ];
2026-03-05 14:41:35 +00:00
$lastEmail = $this -> getLastEmailByAddress ( $userEmail , function ( $email ) use ( $url ) {
2026-02-25 10:38:40 +00:00
$this -> assertStringContainsString ( $url , $email [ 'html' ] ? ? '' );
});
$this -> assertEquals ( 'Password Reset for ' . $this -> getProject ()[ 'name' ], $lastEmail [ 'subject' ]);
$expectedUrl = $url . " &userId= " . $userId . " &secret= " ;
$this -> assertStringContainsString ( $expectedUrl , $lastEmail [ 'html' ]);
// Without search params
$url = 'http://localhost/auth/signin' ;
$response = $this -> client -> call (
Client :: METHOD_POST ,
'/account/recovery' ,
array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()),
[
'userId' => ID :: unique (),
2026-03-05 14:41:35 +00:00
'email' => $userEmail ,
2026-02-25 10:38:40 +00:00
'url' => $url ,
]
);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'userId' ]);
$userId = $response [ 'body' ][ 'userId' ];
2026-03-05 14:41:35 +00:00
$lastEmail = $this -> getLastEmailByAddress ( $userEmail , function ( $email ) use ( $url , $userId ) {
2026-02-25 10:38:40 +00:00
$this -> assertStringContainsString ( $url . '?userId=' . $userId , $email [ 'html' ] ? ? '' );
});
$this -> assertEquals ( 'Password Reset for ' . $this -> getProject ()[ 'name' ], $lastEmail [ 'subject' ]);
$expectedUrl = $url . " ?userId= " . $userId . " &secret= " ;
$this -> assertStringContainsString ( $expectedUrl , $lastEmail [ 'html' ]);
// Without search params, with mobile backlink
$url = 'appwriteio://signin' ;
$response = $this -> client -> call (
Client :: METHOD_POST ,
'/account/recovery' ,
array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()),
[
'userId' => ID :: unique (),
2026-03-05 14:41:35 +00:00
'email' => $userEmail ,
2026-02-25 10:38:40 +00:00
'url' => $url ,
]
);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'userId' ]);
$userId = $response [ 'body' ][ 'userId' ];
2026-03-05 14:41:35 +00:00
$lastEmail = $this -> getLastEmailByAddress ( $userEmail , function ( $email ) use ( $url , $userId ) {
2026-02-25 10:38:40 +00:00
$this -> assertStringContainsString ( $url . '?userId=' . $userId , $email [ 'html' ] ? ? '' );
});
$this -> assertEquals ( 'Password Reset for ' . $this -> getProject ()[ 'name' ], $lastEmail [ 'subject' ]);
$expectedUrl = $url . " ?userId= " . $userId . " &secret= " ;
$this -> assertStringContainsString ( $expectedUrl , $lastEmail [ 'html' ]);
// With injection (allowed, meant to be protected client-side)
$url = 'http://localhost/auth/signin\"></a><h1>INJECTED</h1>' ;
$response = $this -> client -> call (
Client :: METHOD_POST ,
'/account/recovery' ,
array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()),
[
'userId' => ID :: unique (),
2026-03-05 14:41:35 +00:00
'email' => $userEmail ,
2026-02-25 10:38:40 +00:00
'url' => $url ,
]
);
$this -> assertEquals ( 201 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ 'userId' ]);
$userId = $response [ 'body' ][ 'userId' ];
2026-03-05 14:41:35 +00:00
$lastEmail = $this -> getLastEmailByAddress ( $userEmail , function ( $email ) {
2026-02-25 10:38:40 +00:00
$this -> assertStringContainsString ( 'INJECTED' , $email [ 'html' ] ? ? '' );
});
$this -> assertEquals ( 'Password Reset for ' . $this -> getProject ()[ 'name' ], $lastEmail [ 'subject' ]);
$this -> assertStringContainsString ( 'INJECTED' , $lastEmail [ 'html' ]);
$this -> assertStringContainsString ( '<h1>' , $lastEmail [ 'html' ]);
$this -> assertStringContainsString ( '</h1>' , $lastEmail [ 'html' ]);
$this -> assertStringContainsString ( '">' , $lastEmail [ 'html' ]);
$this -> assertStringContainsString ( '</a>' , $lastEmail [ 'html' ]);
$expectedUrl = $url . " ?userId= " . $userId . " &secret= " ;
$this -> assertStringContainsString ( $expectedUrl , $lastEmail [ 'html' ]);
}
2020-07-11 19:40:58 +00:00
}