Merge branch '1.8.x' into refactor-auth-single-instance

This commit is contained in:
Shimon Newman
2025-11-04 17:06:53 +02:00
committed by GitHub
15 changed files with 5158 additions and 179 deletions
+2
View File
@@ -5,3 +5,5 @@ src/** linguist-detectable=false
tests/** linguist-detectable=false
public/scripts/** linguist-detectable=false
public/dist/scripts/** linguist-detectable=false
.github/workflows/*.lock.yml linguist-generated=true merge=ours
+32
View File
@@ -0,0 +1,32 @@
name: AI Moderator
on:
issues:
types: [opened, edited]
issue_comment:
types: [created, edited]
pull_request:
types: [opened, edited]
pull_request_review:
types: [submitted, edited]
pull_request_review_comment:
types: [created, edited]
discussion:
types: [created, edited]
discussion_comment:
types: [created, edited]
permissions:
models: read
issues: write
pull-requests: write
discussions: write
jobs:
moderate:
runs-on: ubuntu-latest
steps:
- name: AI Moderator
uses: github/ai-moderator@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
+22
View File
@@ -0,0 +1,22 @@
name: Auto Label Issue
on:
issues:
types: [opened]
permissions:
issues: write
contents: read
jobs:
labeler:
runs-on: ubuntu-latest
steps:
- name: Issue Labeler
uses: github/issue-labeler@v3.4
with:
configuration-path: .github/labeler.yml
enable-versioned-regex: false
include-title: 1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
File diff suppressed because it is too large Load Diff
+78
View File
@@ -0,0 +1,78 @@
---
on:
issues:
types: [opened, reopened]
stop-after: +30d # workflow will no longer trigger after 30 days. Remove this and recompile to run indefinitely
reaction: eyes
permissions: read-all
network: defaults
safe-outputs:
add-labels:
max: 5
add-comment:
tools:
web-fetch:
web-search:
timeout_minutes: 10
source: githubnext/agentics/workflows/issue-triage.md@0837fb7b24c3b84ee77fb7c8cfa8735c48be347a
---
# Agentic Triage
<!-- Note - this file can be customized to your needs. Replace this section directly, or add further instructions here. After editing run 'gh aw compile' -->
You're a triage assistant for GitHub issues. Your task is to analyze issue #${{ github.event.issue.number }} and perform some initial triage tasks related to that issue.
1. Select appropriate labels for the issue from the provided list.
2. Retrieve the issue content using the `get_issue` tool. If the issue is obviously spam, or generated by bot, or something else that is not an actual issue to be worked on, then add an issue comment to the issue with a one sentence analysis and exit the workflow.
3. Next, use the GitHub tools to gather additional context about the issue:
- Fetch the list of labels available in this repository. Use 'gh label list' bash command to fetch the labels. This will give you the labels you can use for triaging issues.
- Fetch any comments on the issue using the `get_issue_comments` tool
- Find similar issues if needed using the `search_issues` tool
- List the issues to see other open issues in the repository using the `list_issues` tool
4. Analyze the issue content, considering:
- The issue title and description
- The type of issue (bug report, feature request, question, etc.)
- Technical areas mentioned
- Severity or priority indicators
- User impact
- Components affected
5. Write notes, ideas, nudges, resource links, debugging strategies and/or reproduction steps for the team to consider relevant to the issue.
6. Select appropriate labels from the available labels list provided above:
- Choose labels that accurately reflect the issue's nature
- Be specific but comprehensive
- Select priority labels if you can determine urgency (high-priority, med-priority, or low-priority)
- Consider platform labels (android, ios) if applicable
- Search for similar issues, and if you find similar issues consider using a "duplicate" label if appropriate. Only do so if the issue is a duplicate of another OPEN issue.
- Only select labels from the provided list above
- It's okay to not add any labels if none are clearly applicable
7. Apply the selected labels:
- Use the `update_issue` tool to apply the labels to the issue
- DO NOT communicate directly with users
- If no labels are clearly applicable, do not apply any labels
8. Add an issue comment to the issue with your analysis:
- Start with "🎯 Agentic Issue Triage"
- Provide a brief summary of the issue
- Mention any relevant details that might help the team understand the issue better
- Include any debugging strategies or reproduction steps if applicable
- Suggest resources or links that might be helpful for resolving the issue or learning skills related to the issue or the particular area of the codebase affected by it
- Mention any nudges or ideas that could help the team in addressing the issue
- If you have possible reproduction steps, include them in the comment
- If you have any debugging strategies, include them in the comment
- If appropriate break the issue down to sub-tasks and write a checklist of things to do.
- Use collapsed-by-default sections in the GitHub markdown to keep the comment tidy. Collapse all sections except the short main summary at the top.
+1 -1
View File
@@ -55,7 +55,7 @@
"utopia-php/detector": "0.2.*",
"utopia-php/domains": "0.9.*",
"utopia-php/emails": "0.6.*",
"utopia-php/dns": "0.3.*",
"utopia-php/dns": "1.1.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
"utopia-php/fetch": "0.4.*",
Generated
+15 -16
View File
@@ -3457,7 +3457,7 @@
"reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828"
},
"dist": {
"type": "zip",
"type": "zip",\
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/611fa66a97e87c0dbbc133a717d970da7a5ca828",
"reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828",
"shasum": ""
@@ -3974,29 +3974,28 @@
},
{
"name": "utopia-php/dns",
"version": "0.3.0",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/dns.git",
"reference": "8fd4161bc3a8021a670c1101b40f6b09a97f1a54"
"reference": "d6eca184883262bdcb4261e57491c91b16079b9a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/dns/zipball/8fd4161bc3a8021a670c1101b40f6b09a97f1a54",
"reference": "8fd4161bc3a8021a670c1101b40f6b09a97f1a54",
"url": "https://api.github.com/repos/utopia-php/dns/zipball/d6eca184883262bdcb4261e57491c91b16079b9a",
"reference": "d6eca184883262bdcb4261e57491c91b16079b9a",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/cli": "0.15.*",
"utopia-php/telemetry": "^0.1.1"
"php": ">=8.3",
"utopia-php/console": "0.0.*",
"utopia-php/telemetry": "0.1.*"
},
"require-dev": {
"laravel/pint": "1.2.*",
"phpstan/phpstan": "1.8.*",
"phpunit/phpunit": "^9.3",
"rregeer/phpunit-coverage-check": "^0.3.1",
"swoole/ide-helper": "4.6.6"
"laravel/pint": "1.25.*",
"phpstan/phpstan": "2.0.*",
"phpunit/phpunit": "12.4.*",
"swoole/ide-helper": "5.1.8"
},
"type": "library",
"autoload": {
@@ -4024,9 +4023,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/dns/issues",
"source": "https://github.com/utopia-php/dns/tree/0.3.0"
"source": "https://github.com/utopia-php/dns/tree/1.1.0"
},
"time": "2025-08-04T11:05:53+00:00"
"time": "2025-11-03T22:49:02+00:00"
},
{
"name": "utopia-php/domains",
@@ -8982,7 +8981,7 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
+63 -95
View File
@@ -3,118 +3,65 @@
namespace Appwrite\Network\Validator;
use Utopia\DNS\Client;
use Utopia\DNS\Message;
use Utopia\DNS\Message\Question;
use Utopia\DNS\Message\Record;
use Utopia\Domains\Domain;
use Utopia\System\System;
use Utopia\Validator;
class DNS extends Validator
{
public const RECORD_A = 'A';
public const RECORD_AAAA = 'AAAA';
public const RECORD_CNAME = 'CNAME';
public const RECORD_CAA = 'CAA'; // You can provide domain only (as $target) for CAA validation
/**
* @var mixed
*/
protected mixed $logs;
/**
* @var string
*/
protected string $dnsServer;
/**
* @param string $target
*/
public function __construct(protected string $target, protected string $type = self::RECORD_CNAME, string $dnsServer = '')
{
if (empty($dnsServer)) {
$dnsServer = System::getEnv('_APP_DNS', '8.8.8.8');
}
$this->dnsServer = $dnsServer;
public function __construct(
protected string $target,
protected int $type = Record::TYPE_CNAME,
protected string $server = ''
) {
$this->server = $server ?: System::getEnv('_APP_DNS', '8.8.8.8');
}
/**
* @return string
*/
public function getDescription(): string
{
return 'Invalid DNS record';
return 'Invalid DNS record.';
}
/**
* @return mixed
*/
public function getLogs(): mixed
{
return $this->logs;
}
/**
* Check if DNS record value matches specific value
*
* @param mixed $domain
* @return bool
*/
public function isValid($value): bool
{
if (!is_string($value)) {
if (!is_string($value) || trim($value) === '') {
return false;
}
$dns = new Client($this->dnsServer);
$client = new Client($this->server);
try {
$rawQuery = $dns->query($value, $this->type);
// Some DNS servers return all records, not only type that's asked for
// Likely occurs when no records of specific type are found
$query = array_filter($rawQuery, function ($record) {
return $record->getTypeName() === $this->type;
});
$this->logs = $query;
} catch (\Exception $e) {
$this->logs = ['error' => $e->getMessage()];
$response = $client->query(Message::query(
new Question($value, $this->type)
));
} catch (\Throwable) {
return false;
}
if (empty($query)) {
// CAA records inherit from parent (custom CAA behaviour)
if ($this->type === self::RECORD_CAA) {
$domain = new Domain($value);
if ($domain->get() === $domain->getApex()) {
return true; // No CAA on apex domain means anyone can issue certificate
}
$typeMatches = array_filter(
$response->answers,
fn (Record $record) => $record->type === $this->type
);
// Recursive validation by parent domain
$parts = \explode('.', $value);
\array_shift($parts);
$parentDomain = \implode('.', $parts);
$validator = new DNS($this->target, DNS::RECORD_CAA, $this->dnsServer);
return $validator->isValid($parentDomain);
if (empty($typeMatches)) {
if ($this->type === Record::TYPE_CAA) {
return $this->validateParentCAA($value);
}
return false;
}
foreach ($query as $record) {
// CAA validation only needs to ensure domain
if ($this->type === self::RECORD_CAA) {
// Extract domain; comments showcase extraction steps in most complex scenario
$rdata = $record->getRdata(); // 255 issuewild "certainly.com;validationmethods=tls-alpn-01;retrytimeout=3600"
$rdata = \explode(' ', $rdata, 3)[2] ?? ''; // "certainly.com;validationmethods=tls-alpn-01;retrytimeout=3600"
$rdata = \trim($rdata, '"'); // certainly.com;validationmethods=tls-alpn-01;retrytimeout=3600
$rdata = \explode(';', $rdata, 2)[0] ?? ''; // certainly.com
if ($rdata === $this->target) {
foreach ($typeMatches as $record) {
if ($this->type === Record::TYPE_CAA) {
$valuePart = $this->extractCAAValue($record->rdata);
if ($valuePart !== '' && $valuePart === $this->target) {
return true;
}
}
if ($record->getRdata() === $this->target) {
if ($record->rdata === $this->target) {
return true;
}
}
@@ -122,25 +69,46 @@ class DNS extends Validator
return false;
}
/**
* Is array
*
* Function will return true if object is array.
*
* @return bool
*/
private function validateParentCAA(string $domain): bool
{
try {
$domainInfo = new Domain($domain);
} catch (\Throwable) {
return false;
}
if ($domainInfo->get() === $domainInfo->getApex()) {
return true;
}
$parts = explode('.', $domainInfo->get());
array_shift($parts);
$parent = implode('.', $parts);
if ($parent === '') {
return false;
}
$validator = new self($this->target, Record::TYPE_CAA, $this->server);
return $validator->isValid($parent);
}
private function extractCAAValue(string $rdata): string
{
$parts = explode(' ', $rdata, 3);
if (count($parts) < 3) {
return '';
}
$value = trim($parts[2], '"');
return explode(';', $value)[0] ?? '';
}
public function isArray(): bool
{
return false;
}
/**
* Get Type
*
* Returns validator type.
*
* @return string
*/
public function getType(): string
{
return self::TYPE_STRING;
@@ -14,6 +14,7 @@ use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Helpers\ID;
use Utopia\DNS\Message\Record;
use Utopia\Domains\Domain;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@@ -135,13 +136,13 @@ class Create extends Action
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
}
if (empty($validators)) {
@@ -15,6 +15,7 @@ use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\UID;
use Utopia\DNS\Message\Record;
use Utopia\Domains\Domain;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@@ -147,13 +148,13 @@ class Create extends Action
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
}
if (empty($validators)) {
@@ -15,6 +15,7 @@ use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\UID;
use Utopia\DNS\Message\Record;
use Utopia\Domains\Domain;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@@ -152,13 +153,13 @@ class Create extends Action
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
}
if (empty($validators)) {
@@ -15,6 +15,7 @@ use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\UID;
use Utopia\DNS\Message\Record;
use Utopia\Domains\Domain;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@@ -147,13 +148,13 @@ class Create extends Action
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
}
if (empty($validators)) {
@@ -13,6 +13,7 @@ use Appwrite\Utopia\Response;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Validator\UID;
use Utopia\DNS\Message\Record;
use Utopia\Domains\Domain;
use Utopia\Logger\Log;
use Utopia\Platform\Action;
@@ -113,15 +114,15 @@ class Update extends Action
if (!is_null($targetCNAME)) {
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
}
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
}
if (empty($validators)) {
@@ -139,24 +140,13 @@ class Update extends Action
if (!$validator->isValid($domain->get())) {
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
$log->addTag('dnsDomain', $domain->get());
$errors = [];
foreach ($validators as $validator) {
if (!empty($validator->getLogs())) {
$errors[] = $validator->getLogs();
}
}
$error = \implode("\n", $errors);
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
throw new Exception(Exception::RULE_VERIFICATION_FAILED);
}
// Ensure CAA won't block certificate issuance
if (!empty(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''))) {
$validationStart = \microtime(true);
$validator = new DNS(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''), DNS::RECORD_CAA);
$validator = new DNS(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''), Record::TYPE_CAA);
if (!$validator->isValid($domain->get())) {
$log->addExtra('dnsTimingCaa', \strval(\microtime(true) - $validationStart));
$log->addTag('dnsDomain', $domain->get());
+5 -15
View File
@@ -22,6 +22,7 @@ use Utopia\Database\Exception\Conflict;
use Utopia\Database\Exception\Structure;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\DNS\Message\Record;
use Utopia\Domains\Domain;
use Utopia\Locale\Locale;
use Utopia\Logger\Log;
@@ -313,13 +314,13 @@ class Certificates extends Action
$validators = [];
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) {
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
$validators[] = new DNS($targetCNAME->get(), Record::TYPE_CNAME);
}
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), Record::TYPE_A);
}
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), Record::TYPE_AAAA);
}
// Validate if domain target is properly configured
@@ -332,24 +333,13 @@ class Certificates extends Action
if (!$validator->isValid($domain->get())) {
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
$log->addTag('dnsDomain', $domain->get());
$errors = [];
foreach ($validators as $validator) {
if (!empty($validator->getLogs())) {
$errors[] = $validator->getLogs();
}
}
$error = \implode("\n", $errors);
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
throw new Exception('Failed to verify domain DNS records.');
}
// Ensure CAA won't block certificate issuance
if (!empty(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''))) {
$validationStart = \microtime(true);
$validator = new DNS(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''), DNS::RECORD_CAA);
$validator = new DNS(System::getEnv('_APP_DOMAIN_TARGET_CAA', ''), Record::TYPE_CAA);
if (!$validator->isValid($domain->get())) {
$log->addExtra('dnsTimingCaa', \strval(\microtime(true) - $validationStart));
$log->addTag('dnsDomain', $domain->get());
+15 -25
View File
@@ -5,30 +5,20 @@ namespace Tests\Unit\Network\Validators;
use Appwrite\Network\Validator\DNS;
use Appwrite\Tests\Retry;
use PHPUnit\Framework\TestCase;
use Utopia\DNS\Message\Record;
/*
DNS Setup (on Appwrite Labs digital ocean team, network tab):
certainly.caa.appwrite.org: CAA 0 issue "certainly.com"
certainly-full.caa.appwrite.org: CAA 128 issuewild "certainly.com;account=123456;validationmethods=dns-01"
letsencrypt.certainly.caa.appwrite.org: CAA 0 issue "letsencrypt.org"
*/
/**
* DNS Setup (on Appwrite Labs digital ocean team, network tab):
*
* certainly.caa.appwrite.org: CAA 0 issue "certainly.com"
* certainly-full.caa.appwrite.org: CAA 128 issuewild "certainly.com;account=123456;validationmethods=dns-01"
* letsencrypt.certainly.caa.appwrite.org: CAA 0 issue "letsencrypt.org"
*/
class DNSTest extends TestCase
{
public function setUp(): void
{
}
public function tearDown(): void
{
}
public function testCNAME(): void
{
$validator = new DNS('appwrite.io', DNS::RECORD_CNAME);
$validator = new DNS('appwrite.io', Record::TYPE_CNAME);
$this->assertEquals($validator->isValid(''), false);
$this->assertEquals($validator->isValid(null), false);
$this->assertEquals($validator->isValid(false), false);
@@ -39,7 +29,7 @@ class DNSTest extends TestCase
public function testA(): void
{
// IPv4 for documentation purposes
$validator = new DNS('203.0.113.1', DNS::RECORD_A);
$validator = new DNS('203.0.113.1', Record::TYPE_A);
$this->assertEquals($validator->isValid(''), false);
$this->assertEquals($validator->isValid(null), false);
$this->assertEquals($validator->isValid(false), false);
@@ -50,7 +40,7 @@ class DNSTest extends TestCase
public function testAAAA(): void
{
// IPv6 for documentation purposes
$validator = new DNS('2001:db8::1', DNS::RECORD_AAAA);
$validator = new DNS('2001:db8::1', Record::TYPE_AAAA);
$this->assertEquals($validator->isValid(''), false);
$this->assertEquals($validator->isValid(null), false);
$this->assertEquals($validator->isValid(false), false);
@@ -61,8 +51,8 @@ class DNSTest extends TestCase
#[Retry(count: 5)]
public function testCAA(): void
{
$certainly = new DNS('certainly.com', DNS::RECORD_CAA, 'ns1.digitalocean.com');
$letsencrypt = new DNS('letsencrypt.org', DNS::RECORD_CAA, 'ns1.digitalocean.com');
$certainly = new DNS('certainly.com', Record::TYPE_CAA, 'ns1.digitalocean.com');
$letsencrypt = new DNS('letsencrypt.org', Record::TYPE_CAA, 'ns1.digitalocean.com');
// No CAA record succeeds on main domain & subdomains for any issuer
$this->assertEquals($certainly->isValid('caa.appwrite.org'), true);
@@ -78,11 +68,11 @@ class DNSTest extends TestCase
$this->assertEquals($letsencrypt->isValid('certainly-full.caa.appwrite.org'), false);
// Custom flags&tag are not allowed if validator includes specific flags&tag
$certainlyFull = new DNS('0 issue "certainly.com"', DNS::RECORD_CAA);
$certainlyFull = new DNS('0 issue "certainly.com"', Record::TYPE_CAA);
$this->assertEquals($certainlyFull->isValid('certainly-full.caa.appwrite.org'), false);
// Custom flags&tag still allows if they match exactly
$certainlyFull = new DNS('128 issuewild "certainly.com;account=123456;validationmethods=dns-01"', DNS::RECORD_CAA);
$certainlyFull = new DNS('128 issuewild "certainly.com;account=123456;validationmethods=dns-01"', Record::TYPE_CAA);
$this->assertEquals($certainlyFull->isValid('certainly-full.caa.appwrite.org'), true);
// Certainly CAA allows Certainly, but not LetsEncrypt; Same for subdomains