mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
3caedbafe3
Browser extension IDs (e.g., chrome-extension://abcdefg) change every time an unpacked extension is reloaded during development, breaking origin validation. This moves extension schemes from hostname-based validation to scheme-only validation, consistent with how mobile/native platforms are handled. Extension schemes are now automatically included when a web platform is registered.
145 lines
7.5 KiB
PHP
145 lines
7.5 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Network\Validators;
|
|
|
|
use Appwrite\Network\Validator\Origin;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class OriginTest extends TestCase
|
|
{
|
|
public function testValues(): void
|
|
{
|
|
$validator = new Origin(
|
|
allowedHostnames: ['appwrite.io', 'appwrite.test', 'localhost', 'appwrite.flutter'],
|
|
allowedSchemes: ['exp', 'appwrite-callback-123']
|
|
);
|
|
|
|
$this->assertEquals(false, $validator->isValid(''));
|
|
$this->assertEquals(false, $validator->isValid('/'));
|
|
$this->assertEquals(false, $validator->isValid([]));
|
|
$this->assertEquals(false, $validator->isValid(['http://localhost']));
|
|
|
|
$this->assertEquals(true, $validator->isValid('https://localhost'));
|
|
$this->assertEquals(true, $validator->isValid('http://localhost'));
|
|
$this->assertEquals(true, $validator->isValid('http://localhost:80'));
|
|
|
|
$this->assertEquals(true, $validator->isValid('https://appwrite.io'));
|
|
$this->assertEquals(true, $validator->isValid('http://appwrite.io'));
|
|
$this->assertEquals(true, $validator->isValid('http://appwrite.io:80'));
|
|
|
|
$this->assertEquals(true, $validator->isValid('https://appwrite.test'));
|
|
$this->assertEquals(true, $validator->isValid('http://appwrite.test'));
|
|
$this->assertEquals(true, $validator->isValid('http://appwrite.test:80'));
|
|
|
|
$this->assertEquals(true, $validator->isValid('https://appwrite.flutter'));
|
|
$this->assertEquals(true, $validator->isValid('http://appwrite.flutter'));
|
|
$this->assertEquals(true, $validator->isValid('http://appwrite.flutter:80'));
|
|
|
|
$this->assertEquals(false, $validator->isValid('https://example.com'));
|
|
$this->assertEquals(false, $validator->isValid('http://example.com'));
|
|
$this->assertEquals(false, $validator->isValid('http://example.com:80'));
|
|
|
|
$this->assertEquals(true, $validator->isValid('exp://'));
|
|
$this->assertEquals(true, $validator->isValid('exp:///'));
|
|
$this->assertEquals(true, $validator->isValid('exp://index'));
|
|
|
|
$this->assertEquals(true, $validator->isValid('appwrite-callback-123://'));
|
|
$this->assertEquals(false, $validator->isValid('appwrite-callback-456://'));
|
|
|
|
$this->assertEquals(false, $validator->isValid('appwrite-ios://com.company.appname'));
|
|
$this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new iOS platform on your project console dashboard', $validator->getDescription());
|
|
|
|
$this->assertEquals(false, $validator->isValid('appwrite-android://com.company.appname'));
|
|
$this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new Android platform on your project console dashboard', $validator->getDescription());
|
|
|
|
$this->assertEquals(false, $validator->isValid('appwrite-macos://com.company.appname'));
|
|
$this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new macOS platform on your project console dashboard', $validator->getDescription());
|
|
|
|
$this->assertEquals(false, $validator->isValid('appwrite-linux://com.company.appname'));
|
|
$this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new Linux platform on your project console dashboard', $validator->getDescription());
|
|
|
|
$this->assertEquals(false, $validator->isValid('appwrite-windows://com.company.appname'));
|
|
$this->assertEquals('Invalid Origin. Register your new client (com.company.appname) as a new Windows platform on your project console dashboard', $validator->getDescription());
|
|
|
|
// Browser extensions are validated by scheme only, not hostname
|
|
$this->assertEquals(false, $validator->isValid('chrome-extension://com.company.appname'));
|
|
$this->assertEquals(false, $validator->isValid('moz-extension://com.company.appname'));
|
|
$this->assertEquals(false, $validator->isValid('safari-web-extension://com.company.appname'));
|
|
$this->assertEquals(false, $validator->isValid('ms-browser-extension://com.company.appname'));
|
|
|
|
// When extension schemes are in allowedSchemes, any extension ID is accepted
|
|
$validatorWithExtensions = new Origin(
|
|
allowedHostnames: ['appwrite.io'],
|
|
allowedSchemes: ['chrome-extension', 'moz-extension', 'safari-web-extension', 'ms-browser-extension']
|
|
);
|
|
$this->assertEquals(true, $validatorWithExtensions->isValid('chrome-extension://abcdefghijklmnop'));
|
|
$this->assertEquals(true, $validatorWithExtensions->isValid('chrome-extension://different-extension-id'));
|
|
$this->assertEquals(true, $validatorWithExtensions->isValid('moz-extension://some-uuid'));
|
|
$this->assertEquals(true, $validatorWithExtensions->isValid('safari-web-extension://some-id'));
|
|
$this->assertEquals(true, $validatorWithExtensions->isValid('ms-browser-extension://some-id'));
|
|
|
|
$this->assertEquals(true, $validator->isValid('tauri://localhost'));
|
|
$this->assertEquals(false, $validator->isValid('tauri://example.com'));
|
|
$this->assertEquals('Invalid Origin. Register your new client (example.com) as a new Web (Tauri) platform on your project console dashboard', $validator->getDescription());
|
|
|
|
$this->assertEquals(false, $validator->isValid('random-scheme://localhost'));
|
|
$this->assertEquals('Invalid Scheme. The scheme used (random-scheme) in the Origin (random-scheme://localhost) is not supported. If you are using a custom scheme, please change it to `appwrite-callback-<PROJECT_ID>`', $validator->getDescription());
|
|
}
|
|
|
|
public function testGetAllowedHostnames(): void
|
|
{
|
|
$validator = new Origin(
|
|
allowedHostnames: ['appwrite.io', 'localhost'],
|
|
allowedSchemes: ['exp']
|
|
);
|
|
|
|
$this->assertEquals(['appwrite.io', 'localhost'], $validator->getAllowedHostnames());
|
|
}
|
|
|
|
public function testGetAllowedSchemes(): void
|
|
{
|
|
$validator = new Origin(
|
|
allowedHostnames: ['appwrite.io'],
|
|
allowedSchemes: ['exp', 'appwrite-callback-123']
|
|
);
|
|
|
|
$this->assertEquals(['exp', 'appwrite-callback-123'], $validator->getAllowedSchemes());
|
|
}
|
|
|
|
public function testSetAllowedHostnames(): void
|
|
{
|
|
$validator = new Origin(
|
|
allowedHostnames: ['appwrite.io'],
|
|
allowedSchemes: ['exp']
|
|
);
|
|
|
|
$this->assertEquals(true, $validator->isValid('https://appwrite.io'));
|
|
$this->assertEquals(false, $validator->isValid('https://example.com'));
|
|
|
|
$result = $validator->setAllowedHostnames(['example.com']);
|
|
|
|
$this->assertSame($validator, $result);
|
|
$this->assertEquals(['example.com'], $validator->getAllowedHostnames());
|
|
$this->assertEquals(true, $validator->isValid('https://example.com'));
|
|
$this->assertEquals(false, $validator->isValid('https://appwrite.io'));
|
|
}
|
|
|
|
public function testSetAllowedSchemes(): void
|
|
{
|
|
$validator = new Origin(
|
|
allowedHostnames: ['appwrite.io'],
|
|
allowedSchemes: ['exp']
|
|
);
|
|
|
|
$this->assertEquals(true, $validator->isValid('exp://'));
|
|
$this->assertEquals(false, $validator->isValid('appwrite-callback-456://'));
|
|
|
|
$result = $validator->setAllowedSchemes(['appwrite-callback-456']);
|
|
|
|
$this->assertSame($validator, $result);
|
|
$this->assertEquals(['appwrite-callback-456'], $validator->getAllowedSchemes());
|
|
$this->assertEquals(true, $validator->isValid('appwrite-callback-456://'));
|
|
$this->assertEquals(false, $validator->isValid('exp://'));
|
|
}
|
|
}
|