mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
use Filter
This commit is contained in:
@@ -9,8 +9,8 @@ use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\MethodType;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Transformation\Adapter\BranchDomain;
|
||||
use Appwrite\Transformation\Transformation;
|
||||
use Appwrite\Filter\Filter;
|
||||
use Appwrite\Filter\Adapter\BranchDomain as FilterBranchDomain;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Installations;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
@@ -371,17 +371,16 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
||||
|
||||
// VCS branch preview
|
||||
if (!empty($providerBranch)) {
|
||||
$transformation = new Transformation([new BranchDomain()]);
|
||||
$transformation
|
||||
$filter = new Filter([new FilterBranchDomain()]);
|
||||
$filter
|
||||
->setInput([
|
||||
'branch' => $providerBranch,
|
||||
'resourceId' => $resource->getId(),
|
||||
'projectId' => $project->getId(),
|
||||
'sitesDomain' => $sitesDomain,
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformation->getOutput();
|
||||
->filter();
|
||||
$domain = $filter->getOutput();
|
||||
$ruleId = md5($domain);
|
||||
try {
|
||||
$authorization->skip(
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Filter;
|
||||
|
||||
abstract class Adapter
|
||||
{
|
||||
protected mixed $input;
|
||||
protected mixed $output;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function setInput(mixed $input): self
|
||||
{
|
||||
$this->input = $input;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOutput(): mixed
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
abstract public function isValid(mixed $input): bool;
|
||||
|
||||
abstract public function filter(): self;
|
||||
}
|
||||
+18
-11
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Transformation\Adapter;
|
||||
namespace Appwrite\Filter\Adapter;
|
||||
|
||||
use Appwrite\Transformation\Adapter;
|
||||
use Appwrite\Filter\Adapter;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class BranchDomain extends Adapter
|
||||
@@ -17,24 +17,30 @@ class BranchDomain extends Adapter
|
||||
*/
|
||||
public const HASH_SUFFIX_LENGTH = 7;
|
||||
|
||||
/**
|
||||
* @param array<mixed> $traits
|
||||
*/
|
||||
public function isValid(array $traits): bool
|
||||
public function isValid(mixed $input): bool
|
||||
{
|
||||
$branch = $input['branch'] ?? '';
|
||||
$resourceId = $input['resourceId'] ?? '';
|
||||
$projectId = $input['projectId'] ?? '';
|
||||
$sitesDomain = $input['sitesDomain'] ?? '';
|
||||
|
||||
if (empty($branch) || empty($resourceId) || empty($projectId) || empty($sitesDomain)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform branch name into a valid domain name.
|
||||
*
|
||||
* Pre-process branch name to a valid domain name.
|
||||
*
|
||||
* Input should be an array with:
|
||||
* - 'branch' (string): The branch name
|
||||
* - 'resourceId' (string): The resource ID (site or function)
|
||||
* - 'projectId' (string): The project ID
|
||||
* - 'sitesDomain' (string): The base sites domain
|
||||
*/
|
||||
public function transform(): void
|
||||
public function filter(): self
|
||||
{
|
||||
$branch = $this->input['branch'] ?? '';
|
||||
$resourceId = $this->input['resourceId'] ?? '';
|
||||
@@ -44,6 +50,7 @@ class BranchDomain extends Adapter
|
||||
$branchPrefix = $this->generateBranchPrefix($branch);
|
||||
$resourceProjectHash = substr(hash('sha256', $resourceId . $projectId), 0, self::HASH_SUFFIX_LENGTH);
|
||||
$this->output = strtolower("branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}");
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +99,7 @@ class BranchDomain extends Adapter
|
||||
if (isset($allowedCharsFlip[$char])) {
|
||||
$sanitized .= $char;
|
||||
} else {
|
||||
// Prevents two -- or more in row
|
||||
// Prevents two -- or more in a row
|
||||
if (strlen($sanitized) > 0 && $sanitized[strlen($sanitized) - 1] !== '-') {
|
||||
$sanitized .= '-';
|
||||
}
|
||||
@@ -101,4 +108,4 @@ class BranchDomain extends Adapter
|
||||
|
||||
return trim($sanitized, '-');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Filter;
|
||||
|
||||
class Filter
|
||||
{
|
||||
/**
|
||||
* @var array<mixed> $adapters
|
||||
*/
|
||||
protected array $adapters;
|
||||
|
||||
protected mixed $input;
|
||||
|
||||
protected mixed $output;
|
||||
|
||||
/**
|
||||
* @param array<Adapter> $adapters
|
||||
*/
|
||||
public function __construct(array $adapters = [])
|
||||
{
|
||||
$this->adapters = $adapters;
|
||||
}
|
||||
|
||||
public function setInput(mixed $input): self
|
||||
{
|
||||
$this->input = $input;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOutput(): mixed
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
public function addAdapter(Adapter $adapter): self
|
||||
{
|
||||
$this->adapters[] = $adapter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function filter(): bool
|
||||
{
|
||||
foreach ($this->adapters as $adapter) {
|
||||
if (!$adapter->isValid($this->input)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$output = $this->input;
|
||||
|
||||
foreach ($this->adapters as $adapter) {
|
||||
$output = $adapter
|
||||
->setInput($output)
|
||||
->filter()
|
||||
->getOutput();
|
||||
}
|
||||
|
||||
$this->output = $output;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ use Appwrite\Event\Build;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Action;
|
||||
use Appwrite\Platform\Modules\Compute\Validator\Specification as SpecificationValidator;
|
||||
use Appwrite\Transformation\Adapter\BranchDomain;
|
||||
use Appwrite\Transformation\Transformation;
|
||||
use Appwrite\Filter\Filter;
|
||||
use Appwrite\Filter\Adapter\BranchDomain as FilterBranchDomain;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
@@ -298,17 +298,16 @@ class Base extends Action
|
||||
|
||||
// VCS branch preview
|
||||
if (!empty($providerBranch)) {
|
||||
$transformation = new Transformation([new BranchDomain()]);
|
||||
$transformation
|
||||
$filter = new Filter([new FilterBranchDomain()]);
|
||||
$filter
|
||||
->setInput([
|
||||
'branch' => $providerBranch,
|
||||
'resourceId' => $site->getId(),
|
||||
'projectId' => $project->getId(),
|
||||
'sitesDomain' => $sitesDomain,
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformation->getOutput();
|
||||
->filter();
|
||||
$domain = $filter->getOutput();
|
||||
$ruleId = md5($domain);
|
||||
try {
|
||||
$authorization->skip(
|
||||
|
||||
@@ -9,8 +9,8 @@ use Appwrite\Event\Realtime;
|
||||
use Appwrite\Event\Screenshot;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Event\Webhook;
|
||||
use Appwrite\Transformation\Adapter\BranchDomain;
|
||||
use Appwrite\Transformation\Transformation;
|
||||
use Appwrite\Filter\Filter;
|
||||
use Appwrite\Filter\Adapter\BranchDomain as FilterBranchDomain;
|
||||
use Appwrite\Utopia\Response\Model\Deployment;
|
||||
use Appwrite\Vcs\Comment;
|
||||
use Exception;
|
||||
@@ -1039,17 +1039,16 @@ class Builds extends Action
|
||||
// VCS branch
|
||||
$branchName = $deployment->getAttribute('providerBranch');
|
||||
if (!empty($branchName)) {
|
||||
$transformation = new Transformation([new BranchDomain()]);
|
||||
$transformation
|
||||
$filter = new Filter([new FilterBranchDomain()]);
|
||||
$filter
|
||||
->setInput([
|
||||
'branch' => $branchName,
|
||||
'resourceId' => $resource->getId(),
|
||||
'projectId' => $project->getId(),
|
||||
'sitesDomain' => $platform['sitesDomain'],
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformation->getOutput();
|
||||
->filter();
|
||||
$domain = $filter->getOutput();
|
||||
$ruleId = md5($domain);
|
||||
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Filter;
|
||||
|
||||
use Appwrite\Filter\Filter;
|
||||
use Appwrite\Filter\Adapter\BranchDomain;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FilterTest extends TestCase
|
||||
{
|
||||
public function testBranchDomain(): void
|
||||
{
|
||||
$filter = new Filter([new BranchDomain()]);
|
||||
|
||||
// Branch name with slash
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain = $filter->getOutput();
|
||||
$this->assertStringNotContainsString('/', $domain);
|
||||
$this->assertStringStartsWith('branch-feature-test-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
// Branch domain consistency
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain2 = $filter->getOutput();
|
||||
$this->assertEquals($domain, $domain2);
|
||||
|
||||
// Different resources should produce different domains
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site789',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain2 = $filter->getOutput();
|
||||
$this->assertNotEquals($domain, $domain2);
|
||||
|
||||
// Different projects should produce different domains
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj789',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain2 = $filter->getOutput();
|
||||
$this->assertNotEquals($domain, $domain2);
|
||||
|
||||
// Some real-world branch names
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'feature/SER-1234',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain = $filter->getOutput();
|
||||
$this->assertStringStartsWith('branch-feature-ser-1234-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'bugfix/fix-login',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain = $filter->getOutput();
|
||||
$this->assertStringStartsWith('branch-bugfix-fix-login-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'hotfix/v1.2.3',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain = $filter->getOutput();
|
||||
$this->assertStringStartsWith('branch-hotfix-v1-2-3-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'release/2024.01',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain = $filter->getOutput();
|
||||
$this->assertStringStartsWith('branch-release-2024-01-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'user/john/experiment',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain = $filter->getOutput();
|
||||
$this->assertStringStartsWith('branch-user-john-experi-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'dependabot/npm_and_yarn/lodash-4.17.21',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertTrue($success);
|
||||
$domain = $filter->getOutput();
|
||||
$this->assertStringStartsWith('branch-dependabot-npm-a-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
// Invalid inputs
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => '',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertFalse($success);
|
||||
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => '',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertFalse($success);
|
||||
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => '',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->filter();
|
||||
$this->assertFalse($success);
|
||||
|
||||
$success = $filter
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => ''
|
||||
])
|
||||
->filter();
|
||||
$this->assertFalse($success);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Tests\Unit\Transformation;
|
||||
|
||||
use Appwrite\Transformation\Adapter\BranchDomain;
|
||||
use Appwrite\Transformation\Adapter\Mock;
|
||||
use Appwrite\Transformation\Adapter\Preview;
|
||||
use Appwrite\Transformation\Transformation;
|
||||
@@ -41,142 +40,4 @@ class TransformationTest extends TestCase
|
||||
$this->assertStringContainsString("Preview by", $transformer->getOutput());
|
||||
$this->assertStringContainsString("Mock:", $transformer->getOutput());
|
||||
}
|
||||
|
||||
public function testBranchDomain(): void
|
||||
{
|
||||
$transformer = new Transformation([new BranchDomain()]);
|
||||
|
||||
// Branch name with slash
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformer->getOutput();
|
||||
$this->assertStringNotContainsString('/', $domain);
|
||||
$this->assertStringStartsWith('branch-feature-test-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
// Branch domain consistency
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain2 = $transformer->getOutput();
|
||||
$this->assertEquals($domain, $domain2);
|
||||
|
||||
// Different resources should produce different domains
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site789',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain2 = $transformer->getOutput();
|
||||
$this->assertNotEquals($domain, $domain2);
|
||||
|
||||
// Different projects should produce different domains
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'feature/test',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj789',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain2 = $transformer->getOutput();
|
||||
$this->assertNotEquals($domain, $domain2);
|
||||
|
||||
// Some real-world branch names
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'feature/SER-1234',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformer->getOutput();
|
||||
$this->assertStringStartsWith('branch-feature-ser-1234-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'bugfix/fix-login',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformer->getOutput();
|
||||
$this->assertStringStartsWith('branch-bugfix-fix-login-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'hotfix/v1.2.3',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformer->getOutput();
|
||||
$this->assertStringStartsWith('branch-hotfix-v1-2-3-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'release/2024.01',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformer->getOutput();
|
||||
$this->assertStringStartsWith('branch-release-2024-01-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'user/john/experiment',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformer->getOutput();
|
||||
$this->assertStringStartsWith('branch-user-john-experi-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
|
||||
$transformer
|
||||
->setInput([
|
||||
'branch' => 'dependabot/npm_and_yarn/lodash-4.17.21',
|
||||
'resourceId' => 'site123',
|
||||
'projectId' => 'proj456',
|
||||
'sitesDomain' => 'appwrite.network'
|
||||
])
|
||||
->setTraits([])
|
||||
->transform();
|
||||
$domain = $transformer->getOutput();
|
||||
$this->assertStringStartsWith('branch-dependabot-npm-a-', $domain);
|
||||
$this->assertStringEndsWith('.appwrite.network', $domain);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user