Merge branch '1.8.x' into documents-db-api

This commit is contained in:
ArnabChatterjee20k
2026-02-09 17:27:09 +05:30
6990 changed files with 52733 additions and 8283 deletions
@@ -1875,12 +1875,13 @@ class ProjectsConsoleClientTest extends Scope
return $data;
}
/**
* @depends testUpdateProjectAuthLimit
*/
public function testUpdateProjectAuthSessionsLimit($data): array
public function testUpdateProjectAuthSessionsLimit(): void
{
$id = $data['projectId'] ?? '';
$id = $this->setupProject([
'projectId' => ID::unique(),
'name' => 'testUpdateProjectAuthSessionsLimit',
'region' => System::getEnv('_APP_REGION', 'default')
]);
/**
* Test for failure
@@ -1991,10 +1992,9 @@ class ProjectsConsoleClientTest extends Scope
'limit' => 10,
]);
return $data;
$this->assertEquals(200, $response['headers']['status-code']);
}
/**
* @depends testUpdateProjectAuthLimit
*/
@@ -5202,6 +5202,31 @@ class ProjectsConsoleClientTest extends Scope
]);
$this->assertEquals(200, $response['headers']['status-code']);
/** 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']);
$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']);
/** Test hostname in Magic URL */
$response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', [
'content-type' => 'application/json',
@@ -5226,6 +5251,95 @@ class ProjectsConsoleClientTest extends Scope
$this->assertEquals(201, $response['headers']['status-code']);
}
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,
'origin' => '',
], [
'success' => 'https://domain-without-rule.com',
'failure' => 'https://domain-without-rule.com'
], followRedirects: false);
$this->assertEquals(400, $response['headers']['status-code']);
// 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,
'origin' => '',
], [
'success' => 'https://' . $domain,
'failure' => 'https://' . $domain
], followRedirects: false);
$this->assertEquals(301, $response['headers']['status-code']);
// 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,
'origin' => '',
], [
'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,
'origin' => '',
], [
'userId' => ID::unique(),
'email' => 'user@appwrite.io',
'url' => 'https://' . $domain,
]);
$this->assertEquals(201, $response['headers']['status-code']);
}
/**
* @group abuseEnabled
*/
@@ -5283,6 +5397,68 @@ class ProjectsConsoleClientTest extends Scope
$this->assertEquals($origin, $response['headers']['access-control-allow-origin'] ?? null);
}
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
$this->assertEquals(200, $currencies['headers']['status-code']);
$this->assertSame('http://' . $domain, $currencies['headers']['access-control-allow-origin']);
} else {
// Untrusted projects cannot
$this->assertEquals(403, $currencies['headers']['status-code']);
$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']);
}
}
}
/**
* @group abuseEnabled
*/