Adding and cleaning up domains/registrars

This commit is contained in:
wess
2023-04-18 10:36:17 -04:00
parent 62bdc77b93
commit ca4ba65291
9 changed files with 902 additions and 54 deletions
+3 -1
View File
@@ -86,4 +86,6 @@ _APP_GRAPHQL_MAX_COMPLEXITY=250
_APP_GRAPHQL_MAX_DEPTH=3
DOCKERHUB_PULL_USERNAME=
DOCKERHUB_PULL_PASSWORD=
DOCKERHUB_PULL_EMAIL=
DOCKERHUB_PULL_EMAIL=
OPENSRS_KEY=95e4dc58cafc3623f8188d7f1aecbb2259cff4b003b96cfb4ac93d25b5f96e6749c6febfb838fd56e1bcd1026635c0c38e9f40bef0e39585
OPENSRS_USERNAME=eldadfux
+1
View File
@@ -13,3 +13,4 @@ debug/
app/sdks
dev/yasd_init.php
.phpunit.result.cache
Makefile
+516
View File
@@ -0,0 +1,516 @@
<?php
use Appwrite\Auth\Validator\Phone;
use Appwrite\Extend\Exception;
use Appwrite\Network\Validator\Email;
use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\Database\Validator\UID;
use Utopia\Domains\Contact;
use Utopia\Domains\Domain;
use Utopia\Domains\Registrar;
use Utopia\Validator\Domain as DomainValidator;
use Utopia\Validator\Text;
App::init()
->groups(['projects'])
->inject('project')
->action(function (Document $project) {
if ($project->getId() !== 'console') {
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN);
}
});
App::post('/v1/domains/suggest')
->desc('Suggest domain names')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'create')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('domain', null, new DomainValidator(), 'Domain name')
->inject('response')
->inject('registrar')
->action(function (string $domain, $response, $registrar) {
$domain = new Domain($domain);
$suggestions = $registrar->suggest([$domain->getName()], [$domain->getTLD()]);
$response->dynamic(new Document(['domains' => $suggestions]), Response::MODEL_DOMAIN_LIST);
});
App::post('/v1/domains/available')
->desc('Checks if a domain is available for registration')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'create')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('domain', null, new DomainValidator(), 'Domain name')
->inject('response')
->inject('registrar')
->action(function (string $domain, $response, $registrar) {
$domain = [
'domain' => $domain,
'available' => $registrar->available($domain),
];
$response->dynamic(new Document(['domain' => $domain]), Response::MODEL_DOMAIN);
});
App::post('/v1/domains')
->desc('Create a domain for 3rd party registrar, prompt to assign nameservers')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'create')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', '', new UID(), 'Project unique ID')
->param('domain', null, new DomainValidator(), 'Domain name')
->inject('response')
->inject('dbForConsole')
->inject('registrar')
->action(function (
string $projectId,
string $domain,
Response $response,
Database $dbForConsole,
Registrar $registrar
) {
if (! $registrar->available($domain)) {
throw new Exception(Exception::DOMAIN_ALREADY_EXISTS);
}
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$document = $dbForConsole->findOne('domains', [
Query::equal('domain', [$domain]),
Query::equal('projectInternalId', [$project->getInternalId()]),
]);
if ($document && ! $document->isEmpty()) {
throw new Exception(Exception::DOMAIN_ALREADY_EXISTS);
}
$domain = new Domain($domain);
$domain = new Document([
'$id' => ID::unique(),
'$permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'projectInternalId' => $project->getInternalId(),
'projectId' => $project->getId(),
'domain' => $domain->get(),
'tld' => $domain->getSuffix(),
'registerable' => $domain->getRegisterable(),
'verification' => false,
'certificateId' => null,
'registered' => false,
]);
$domain = $dbForConsole->createDocument('domains', $domain);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($domain, Response::MODEL_DOMAIN);
});
App::post('/v1/domains/purchase')
->desc('Purchase, create and domain assign nameservers')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'create')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', '', new UID(), 'Project unique ID')
->param('domain', null, new DomainValidator(), 'Domain name')
->param('firstname', '', new Text(128), 'First name')
->param('lastname', '', new Text(128), 'Last name')
->param('phone', '', new Phone(), 'Phone number')
->param('email', '', new Email(), 'Email address')
->param('address1', '', new Text(128), 'Address')
->param('address2', '', new Text(128), 'Address 2')
->param('address3', '', new Text(128), 'Address 3')
->param('city', '', new Text(128), 'City')
->param('state', '', new Text(128), 'State')
->param('country', '', new Text(128), 'Country')
->param('postalcode', '', new Text(128), 'Postal code')
->param('org', '', new Text(128), 'Organization')
->inject('response')
->inject('dbForConsole')
->inject('registrar')
->action(function (
string $projectId,
string $domain,
string $firstname,
string $lastname,
string $phone,
string $email,
string $address1,
string $address2,
string $address3,
string $city,
string $state,
string $country,
string $postalcode,
string $org,
Response $response,
Database $dbForConsole,
Registrar $registrar
) {
if (! $registrar->available($domain)) {
throw new Exception();
}
$contact = new Contact(
$firstname,
$lastname,
$phone,
$email,
$address1,
$address2,
$address3,
$city,
$state,
$country,
$postalcode,
$org,
''
);
try {
$registrar->purchase($domain, [$contact]);
} catch (Exception $e) {
throw new Exception();
}
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$document = $dbForConsole->findOne('domains', [
Query::equal('domain', [$domain]),
Query::equal('projectInternalId', [$project->getInternalId()]),
]);
if ($document && ! $document->isEmpty()) {
throw new Exception(Exception::DOMAIN_ALREADY_EXISTS);
}
$domain = new Domain($domain);
$domain = new Document([
'$id' => ID::unique(),
'$permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'projectInternalId' => $project->getInternalId(),
'projectId' => $project->getId(),
'domain' => $domain->get(),
'tld' => $domain->getSuffix(),
'registerable' => $domain->getRegisterable(),
'verification' => false,
'certificateId' => null,
'registered' => true,
]);
$domain = $dbForConsole->createDocument('domains', $domain);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($domain, Response::MODEL_DOMAIN);
});
App::post('/v1/domains/transfer/in')
->desc('Transfer existing domain to Appwrite, and assign nameservers')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'create')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', '', new UID(), 'Project unique ID')
->param('domain', null, new DomainValidator(), 'Domain name')
->param('firstname', '', new Text(128), 'First name')
->param('lastname', '', new Text(128), 'Last name')
->param('phone', '', new Phone(), 'Phone number')
->param('email', '', new Email(), 'Email address')
->param('address1', '', new Text(128), 'Address')
->param('address2', '', new Text(128), 'Address 2')
->param('address3', '', new Text(128), 'Address 3')
->param('city', '', new Text(128), 'City')
->param('state', '', new Text(128), 'State')
->param('country', '', new Text(128), 'Country')
->param('postalcode', '', new Text(128), 'Postal code')
->param('org', '', new Text(128), 'Organization')
->inject('response')
->inject('dbForConsole')
->inject('registrar')
->action(function (
string $projectId,
string $domain,
string $firstname,
string $lastname,
string $phone,
string $email,
string $address1,
string $address2,
string $address3,
string $city,
string $state,
string $country,
string $postalcode,
string $org,
Response $response,
Database $dbForConsole,
Registrar $registrar
) {
$contact = new Contact(
$firstname,
$lastname,
$phone,
$email,
$address1,
$address2,
$address3,
$city,
$state,
$country,
$postalcode,
$org,
''
);
try {
$registrar->transfer($domain, [$contact]);
} catch (Exception $e) {
throw new Exception();
}
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$document = $dbForConsole->findOne('domains', [
Query::equal('domain', [$domain]),
Query::equal('projectInternalId', [$project->getInternalId()]),
]);
if ($document && ! $document->isEmpty()) {
throw new Exception(Exception::DOMAIN_ALREADY_EXISTS);
}
$domain = new Domain($domain);
$domain = new Document([
'$id' => ID::unique(),
'$permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'projectInternalId' => $project->getInternalId(),
'projectId' => $project->getId(),
'domain' => $domain->get(),
'tld' => $domain->getSuffix(),
'registerable' => $domain->getRegisterable(),
'verification' => false,
'certificateId' => null,
'registered' => true,
]);
$domain = $dbForConsole->createDocument('domains', $domain);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($domain, Response::MODEL_DOMAIN);
});
App::post('/v1/domains/transfer/out')
->desc('Start transfer process for domain and generate code for transfer to 3rd party registrar')
->groups(['api', 'domains'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'transferOut')
->label('sdk.method', 'create')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->inject('response')
->inject('user')
->action(function () {
///TODO
});
App::get('/v1/domains')
->desc('List domains')
->groups(['api', 'domains'])
->label('scope', 'projects.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'list')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', '', new UID(), 'Project unique ID')
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$domains = $dbForConsole->find('domains', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::limit(5000),
]);
$response->dynamic(new Document([
'domains' => $domains,
'total' => count($domains),
]), Response::MODEL_DOMAIN_LIST);
});
App::get('/v1/domains/:domainId')
->desc('Get domain')
->groups(['api', 'domains'])
->label('scope', 'projects.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'list')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', '', new UID(), 'Project unique ID')
->param('domainId', '', new UID(), 'Domain unique ID')
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $domainId, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$domain = $dbForConsole->findOne('domains', [
Query::equal('_uid', [$domainId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
]);
if ($domain === false || $domain->isEmpty()) {
throw new Exception(Exception::DOMAIN_NOT_FOUND);
}
$response->dynamic($domain, Response::MODEL_DOMAIN);
});
App::patch('/v1/domains/:domainId/nameservers')
->desc('Check namserver records and update them if needed')
->groups(['api', 'domains'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'updateNameservers')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('domainId', '', new UID(), 'Domain unique ID')
->inject('response')
->inject('user')
->action(function () {
///Do we need/want?
});
App::patch('/v1/domains/:domainId/project')
->desc('Move domain to a different project')
->groups(['api', 'domains'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'updateProject')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('domainId', '', new UID(), 'Domain unique ID')
->inject('response')
->inject('user')
->action(function () {
/// WAIT FOR TRANSFER SERVICE.
});
App::delete('/v1/domains/:domainId')
->desc('Remove a domain')
->groups(['api', 'domains'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'domains')
->label('sdk.method', 'list')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOMAIN)
->param('projectId', '', new UID(), 'Project unique ID')
->param('domainId', '', new UID(), 'Domain unique ID')
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $domainId, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$domain = $dbForConsole->findOne('domains', [
Query::equal('_uid', [$domainId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
]);
if ($domain === false || $domain->isEmpty()) {
throw new Exception(Exception::DOMAIN_NOT_FOUND);
}
if ($domain['registered'] === true) {
throw new Exception();
}
$response->noContent();
});
+18
View File
@@ -75,6 +75,9 @@ use Utopia\Validator\Range;
use Utopia\Validator\IP;
use Utopia\Validator\URL;
use Utopia\Validator\WhiteList;
use Utopia\Domains\Registrar;
use Utopia\Domains\Registrar\OpenSRS;
const APP_NAME = 'Appwrite';
const APP_DOMAIN = 'appwrite.io';
@@ -758,6 +761,21 @@ App::setResource('register', fn() => $register);
App::setResource('locale', fn() => new Locale(App::getEnv('_APP_LOCALE', 'en')));
App::setResource('registrar', function () {
$opensrs = new OpenSRS(
App::getEnv('OPENSRS_KEY'),
App::getEnv('OPENSRS_USERNAME'),
'appwrite',
'0p3n5R5@Appwrite',
[
'ns1.appwrite.io',
'ns2.appwrite.io',
]
);
return new Registrar($opensrs);
});
// Queues
App::setResource('events', fn() => new Event('', ''));
App::setResource('audits', fn() => new Audit());
+1 -1
View File
@@ -50,7 +50,7 @@
"utopia-php/cli": "0.13.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.35.*",
"utopia-php/domains": "1.1.*",
"utopia-php/domains": "0.3.*",
"utopia-php/framework": "0.28.*",
"utopia-php/image": "0.5.*",
"utopia-php/locale": "0.4.*",
Generated
+55 -52
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "87de4ea3130e576470a63b21628e30fb",
"content-hash": "528e1300e9a6b017072d039cdee9fee7",
"packages": [
{
"name": "adhocore/jwt",
@@ -481,22 +481,22 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "7.5.0",
"version": "7.5.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba"
"reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba",
"reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/b964ca597e86b752cd994f27293e9fa6b6a95ed9",
"reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.5",
"guzzlehttp/psr7": "^1.9 || ^2.4",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
@@ -589,7 +589,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.5.0"
"source": "https://github.com/guzzle/guzzle/tree/7.5.1"
},
"funding": [
{
@@ -605,7 +605,7 @@
"type": "tidelift"
}
],
"time": "2022-08-28T15:39:27+00:00"
"time": "2023-04-17T16:30:08+00:00"
},
{
"name": "guzzlehttp/promises",
@@ -693,22 +693,22 @@
},
{
"name": "guzzlehttp/psr7",
"version": "2.4.4",
"version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf"
"reference": "b635f279edd83fc275f822a1188157ffea568ff6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf",
"reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6",
"reference": "b635f279edd83fc275f822a1188157ffea568ff6",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0",
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0"
},
"provide": {
@@ -728,9 +728,6 @@
"bamarni-bin": {
"bin-links": true,
"forward-command": false
},
"branch-alias": {
"dev-master": "2.4-dev"
}
},
"autoload": {
@@ -792,7 +789,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.4.4"
"source": "https://github.com/guzzle/psr7/tree/2.5.0"
},
"funding": [
{
@@ -808,7 +805,7 @@
"type": "tidelift"
}
],
"time": "2023-03-09T13:19:02+00:00"
"time": "2023-04-17T16:11:26+00:00"
},
{
"name": "influxdb/influxdb-php",
@@ -1372,16 +1369,16 @@
},
{
"name": "psr/http-message",
"version": "1.1",
"version": "2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba"
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"shasum": ""
},
"require": {
@@ -1390,7 +1387,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
"dev-master": "2.0.x-dev"
}
},
"autoload": {
@@ -1405,7 +1402,7 @@
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
@@ -1419,9 +1416,9 @@
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/1.1"
"source": "https://github.com/php-fig/http-message/tree/2.0"
},
"time": "2023-04-04T09:50:52+00:00"
"time": "2023-04-04T09:54:51+00:00"
},
{
"name": "psr/log",
@@ -2112,16 +2109,16 @@
},
{
"name": "utopia-php/database",
"version": "0.35.0",
"version": "0.35.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "f162c142fd61753c4b413b15c3c4041f3cd00bb2"
"reference": "b5ac84e0c77145bd0a7f38718ad915729c64fa93"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/f162c142fd61753c4b413b15c3c4041f3cd00bb2",
"reference": "f162c142fd61753c4b413b15c3c4041f3cd00bb2",
"url": "https://api.github.com/repos/utopia-php/database/zipball/b5ac84e0c77145bd0a7f38718ad915729c64fa93",
"reference": "b5ac84e0c77145bd0a7f38718ad915729c64fa93",
"shasum": ""
},
"require": {
@@ -2164,29 +2161,31 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.35.0"
"source": "https://github.com/utopia-php/database/tree/0.35.1"
},
"time": "2023-04-11T04:02:22+00:00"
"time": "2023-04-13T04:30:08+00:00"
},
{
"name": "utopia-php/domains",
"version": "v1.1.0",
"version": "0.3.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/domains.git",
"reference": "1665e1d9932afa3be63b5c1e0dcfe01fe77d8e73"
"reference": "7ea655feea3476be96308003cf44a9f49ceb1aea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/domains/zipball/1665e1d9932afa3be63b5c1e0dcfe01fe77d8e73",
"reference": "1665e1d9932afa3be63b5c1e0dcfe01fe77d8e73",
"url": "https://api.github.com/repos/utopia-php/domains/zipball/7ea655feea3476be96308003cf44a9f49ceb1aea",
"reference": "7ea655feea3476be96308003cf44a9f49ceb1aea",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": ">=8.0",
"utopia-php/framework": "0.*.*"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
"laravel/pint": "1.2.*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"autoload": {
@@ -2202,6 +2201,10 @@
{
"name": "Eldad Fux",
"email": "eldad@appwrite.io"
},
{
"name": "Wess Cope",
"email": "wess@appwrite.io"
}
],
"description": "Utopia Domains library is simple and lite library for parsing web domains. This library is aiming to be as simple and easy to learn and use.",
@@ -2218,9 +2221,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/domains/issues",
"source": "https://github.com/utopia-php/domains/tree/master"
"source": "https://github.com/utopia-php/domains/tree/0.3.1"
},
"time": "2020-02-23T07:40:02+00:00"
"time": "2023-03-30T12:17:50+00:00"
},
{
"name": "utopia-php/framework",
@@ -3037,16 +3040,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "0.32.1",
"version": "0.32.2",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "ba1d7afd57e3baef06c04ce6abc26f79310146df"
"reference": "cdec289bcf38c99d0074414d2438e9967d0c9699"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/ba1d7afd57e3baef06c04ce6abc26f79310146df",
"reference": "ba1d7afd57e3baef06c04ce6abc26f79310146df",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/cdec289bcf38c99d0074414d2438e9967d0c9699",
"reference": "cdec289bcf38c99d0074414d2438e9967d0c9699",
"shasum": ""
},
"require": {
@@ -3082,9 +3085,9 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/0.32.1"
"source": "https://github.com/appwrite/sdk-generator/tree/0.32.2"
},
"time": "2023-04-12T04:43:07+00:00"
"time": "2023-04-12T21:06:57+00:00"
},
{
"name": "doctrine/deprecations",
@@ -3787,16 +3790,16 @@
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.18.1",
"version": "1.19.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f"
"reference": "f545fc30978190a056832aa7ed995e36a66267f3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/22dcdfd725ddf99583bfe398fc624ad6c5004a0f",
"reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/f545fc30978190a056832aa7ed995e36a66267f3",
"reference": "f545fc30978190a056832aa7ed995e36a66267f3",
"shasum": ""
},
"require": {
@@ -3826,9 +3829,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.18.1"
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.19.1"
},
"time": "2023-04-07T11:51:11+00:00"
"time": "2023-04-18T11:30:56+00:00"
},
{
"name": "phpunit/php-code-coverage",
+2
View File
@@ -177,6 +177,8 @@ services:
- _APP_GRAPHQL_MAX_BATCH_SIZE
- _APP_GRAPHQL_MAX_COMPLEXITY
- _APP_GRAPHQL_MAX_DEPTH
- OPENSRS_KEY
- OPENSRS_USERNAME
appwrite-realtime:
entrypoint: realtime
@@ -0,0 +1,7 @@
<?php
namespace Tests\E2E\Services\Domains;
trait DomainsBase
{
}
@@ -0,0 +1,299 @@
<?php
namespace Tests\E2E\Services\Projects;
use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectConsole;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideClient;
use Tests\E2E\Services\Domains\DomainsBase;
use Utopia\Database\Helpers\ID;
class DomainsRegistrarClientTest extends Scope
{
use DomainsBase;
use ProjectConsole;
use SideClient;
public function testCreateProject(): array
{
/**
* 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(),
'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()), [
'projectId' => ID::unique(),
'name' => 'Project Test',
'teamId' => $team['body']['$id'],
'region' => 'default',
]);
$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']);
$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_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']);
$this->assertArrayHasKey('platforms', $response['body']);
$this->assertArrayHasKey('webhooks', $response['body']);
$this->assertArrayHasKey('keys', $response['body']);
return ['projectId' => $projectId];
}
/**
* @depends testCreateProject
*/
public function testSuggestDomain($data): void
{
$id = $data['projectId'] ?? '';
$response = $this->client->call(Client::METHOD_POST, '/domains/suggest', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => $id,
'domain' => 'kittens.com',
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['domains']);
}
/**
* @depends testCreateProject
*/
public function testAvailableDomain($data): void
{
$id = $data['projectId'] ?? '';
$response = $this->client->call(Client::METHOD_POST, '/domains/available', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => $id,
'domain' => 'google.com',
]);
$available = $response['body']['domain']['available'];
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['domain']);
$this->assertFalse($available);
}
/**
* @depends testCreateProject
*/
public function testCreate3rdPartyDomain($data): array
{
$id = $data['projectId'] ?? '';
$domain = $this->generateRandomString().'.net';
$response = $this->client->call(Client::METHOD_POST, '/domains', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => $id,
'domain' => $domain,
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals($domain, $response['body']['domain']);
$this->assertEquals(false, $response['body']['verification']);
/**
* Test for FAILURE
*/
$response = $response = $this->client->call(Client::METHOD_POST, '/domains', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => $id,
'domain' => 'sdkljgfhsdflkjghsdflkgjsh.com',
]);
return [];
}
/**
* @depends testCreateProject
*/
public function testPurchaseDomain($data): array
{
$id = $data['projectId'] ?? '';
$domain = $this->generateRandomString().'.net';
$response = $this->client->call(Client::METHOD_POST, '/domains/purchase', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => $id,
'domain' => $domain,
'firstname' => 'firstname',
'lastname' => 'lastname',
'phone' => '+18037889693',
'email' => 'email@email.com',
'address1' => 'address1 st',
'address2' => 'unit address2',
'address3' => 'apt. address3',
'city' => 'city',
'state' => 'state',
'country' => 'us',
'postalcode' => '29223',
'org' => 'myorg',
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertTrue($response['body']['registered']);
return [
'projectId' => $id,
'domain' => $domain,
];
}
public function testTransferInDomain(): void
{
// This will always fail mainly because it's a test env,
// but also because:
// - we use random domains to test
// - transfer lock is default
// - unable to unlock transfer because domains (in tests) are new.
// ** Even when testing against my own live domains, it failed.
// So we test for a proper formatted response,
// with "successful" being "false".
$this->markTestSkipped('Transfer test skipped because it always fails.');
}
public function testTransferOutDomain(): void
{
// This will always fail mainly because it's a test env,
// but also because:
// - we use random domains to test
// - transfer lock is default
// - unable to unlock transfer because domains (in tests) are new.
// ** Even when testing against my own live domains, it failed.
// So we test for a proper formatted response,
// with "successful" being "false".
$this->markTestSkipped('Transfer test skipped because it always fails.');
}
/**
* @depends testCreateProject
*/
public function testDomainList($data): array
{
$id = $data['projectId'] ?? '';
$response = $this->client->call(Client::METHOD_GET, '/domains', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => $id,
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertTrue($response['body']['total'] > 0);
$this->assertTrue(count($response['body']['domains']) > 0);
return [
'projectId' => $id,
'domains' => $response['body']['domains'],
];
}
/**
* @depends testDomainList
*/
public function testDomainGet($data): array
{
$id = $data['projectId'] ?? '';
$domains = $data['domains'] ?? [];
$domain = $domains[0];
$domainId = $domain['$id'];
$response = $this->client->call(Client::METHOD_GET, '/domains/'.$domainId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => $id,
'domainId' => $domains[0]['$id'],
]);
$this->assertEquals(200, $response['headers']['status-code']);
return [
'projectId' => $id,
'domainId' => $domainId,
];
}
/**
* @depends testDomainGet
*/
public function testDomainDelete($data): string
{
$id = $data['projectId'] ?? '';
$domainId = $data['domainId'] ?? '';
$response = $this->client->call(Client::METHOD_DELETE, '/domains/'.$domainId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => $id,
'domainId' => $domainId,
]);
$this->assertEquals(204, $response['headers']['status-code']);
return $domainId;
}
private function generateRandomString(int $length = 10): string
{
$characters = 'abcdefghijklmnopqrstuvwxyz';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[random_int(0, $charactersLength - 1)];
}
return $randomString;
}
}