Application create is possible via EPP too

This commit is contained in:
Pinga 2025-02-17 16:20:57 +02:00
parent f2326a92e0
commit c5b2783fbf
3 changed files with 629 additions and 343 deletions

View file

@ -9,6 +9,7 @@
"namingo/rately": "^0.1.0",
"moneyphp/money": "^4.6",
"phpmailer/phpmailer": "^6.9",
"filips123/monolog-phpmailer": "^2.0"
"filips123/monolog-phpmailer": "^2.0",
"ramsey/uuid": "^4.7"
}
}

View file

@ -633,6 +633,8 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m
// If all validations pass, continue
} elseif ($launch_phase === 'landrush') {
// Continue
} elseif ($launch_phase === 'custom') {
// Continue
} else {
// Mixed or unsupported form
sendEppError($conn, $db, 2101, 'unsupported launch phase or mixed form', $clTRID, $trans);
@ -669,11 +671,8 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m
return;
}
if ($launch_extension_enabled && isset($launch_create)) {
$stmt = $db->prepare("SELECT value FROM settings WHERE name = 'launch_phases' LIMIT 1");
$stmt->execute();
$launch_phases = $stmt->fetchColumn();
$launch_phases = $db->query("SELECT value FROM settings WHERE name = 'launch_phases' LIMIT 1")->fetchColumn();
if ($launch_phases) {
$currentDateTime = new \DateTime();
$currentDate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp
@ -689,7 +688,29 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m
$phase_details = $stmt->fetchColumn();
// Check if the phase requires application submission
if ($phase_details && $phase_details === 'Application') {
if (empty($launch_phase) && $launch_phase !== 'custom' && $phase_details === 'Application') {
sendEppError($conn, $db, 2304, 'Domain registration is not allowed for this TLD. You must submit a new application instead.', $clTRID, $trans);
return;
}
}
if ($launch_extension_enabled && isset($launch_create)) {
$currentDateTime = new \DateTime();
$currentDate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp
$stmt = $db->prepare("
SELECT phase_category
FROM launch_phases
WHERE tld_id = ?
AND start_date <= ?
AND (end_date >= ? OR end_date IS NULL OR end_date = '')
LIMIT 1
");
$stmt->execute([$tld_id, $currentDate, $currentDate]);
$phase_details = $stmt->fetchColumn();
// Check if the phase requires application submission
if (empty($launch_phase) && $launch_phase !== 'custom' && $phase_details === 'Application') {
sendEppError($conn, $db, 2304, 'Domain registration is not allowed for this TLD. You must submit a new application instead.', $clTRID, $trans);
return;
}
@ -1253,6 +1274,252 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m
return;
}
if (isset($phase_details) && $phase_details === 'Application') {
try {
$db->beginTransaction();
$currentDateTime = new \DateTime();
$crdate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp
$response = [];
$domainSql = "INSERT INTO application (
name, tldid, registrant, crdate, clid, crid, authtype, authinfo, tm_phase, phase_type
) VALUES (
:name, :tldid, :registrant, :crdate, :clid, :crid, :authtype, :authinfo, :tm_phase, :phase_type
)";
$domainStmt = $db->prepare($domainSql);
$domainStmt->execute([
':name' => $domainName,
':tldid' => $tld_id,
':registrant' => $registrant_id,
':crdate' => $crdate,
':clid' => $clid,
':crid' => $clid,
':authtype' => 'pw',
':authinfo' => $authInfo_pw ?? null,
':tm_phase' => $launch_phase_name ?? null,
':phase_type' => $launch_phase ?? null,
]);
$domain_id = $db->lastInsertId();
$uuid = createUuidFromId($domain_id);
// Update application_id in the application table
$updateStmt = $db->prepare("UPDATE application SET application_id = :uuid WHERE id = :domain_id");
$updateStmt->execute([
':uuid' => $uuid,
':domain_id' => $domain_id
]);
// Insert into application_status table
$insertStmt = $db->prepare("INSERT INTO application_status (domain_id, status) VALUES (:domain_id, :status)");
$insertStmt->execute([
':domain_id' => $domain_id,
':status' => 'pendingValidation'
]);
$updateRegistrarStmt = $db->prepare("UPDATE registrar SET accountBalance = (accountBalance - :price) WHERE id = :registrar_id");
$updateRegistrarStmt->execute([
':price' => $price,
':registrar_id' => $clid
]);
$paymentHistoryStmt = $db->prepare("INSERT INTO payment_history (registrar_id,date,description,amount) VALUES(:registrar_id,CURRENT_TIMESTAMP(3),:description,:amount)");
$paymentHistoryStmt->execute([
':registrar_id' => $clid,
':description' => "create application $domainName for period $date_add MONTH",
':amount' => "-$price"
]);
$selectDomainDatesStmt = $db->prepare("SELECT crdate,exdate FROM application WHERE name = :name LIMIT 1");
$selectDomainDatesStmt->execute([':name' => $domainName]);
[$from, $to] = $selectDomainDatesStmt->fetch(PDO::FETCH_NUM);
$statementStmt = $db->prepare("INSERT INTO statement (registrar_id,date,command,domain_name,length_in_months,fromS,toS,amount) VALUES(:registrar_id,CURRENT_TIMESTAMP(3),:cmd,:name,:date_add,:from,:to,:price)");
$statementStmt->execute([
':registrar_id' => $clid,
':cmd' => 'create',
':name' => $domainName,
':date_add' => $date_add,
':from' => $from,
':to' => $from,
':price' => $price
]);
if (!empty($hostObj_list) && is_array($hostObj_list)) {
foreach ($hostObj_list as $node) {
$hostObj = strtoupper((string)$node);
$hostExistStmt = $db->prepare("SELECT id FROM host WHERE name = :hostObj LIMIT 1");
$hostExistStmt->execute([':hostObj' => $hostObj]);
$hostObj_already_exist = $hostExistStmt->fetchColumn();
if ($hostObj_already_exist) {
$domainHostMapStmt = $db->prepare("SELECT domain_id FROM application_host_map WHERE domain_id = :domain_id AND host_id = :host_id LIMIT 1");
$domainHostMapStmt->execute([':domain_id' => $domain_id, ':host_id' => $hostObj_already_exist]);
$domain_host_map_id = $domainHostMapStmt->fetchColumn();
if (!$domain_host_map_id) {
$insertDomainHostMapStmt = $db->prepare("INSERT INTO application_host_map (domain_id,host_id) VALUES(:domain_id,:host_id)");
$insertDomainHostMapStmt->execute([':domain_id' => $domain_id, ':host_id' => $hostObj_already_exist]);
} else {
$errorLogStmt = $db->prepare("INSERT INTO error_log
(channel, level, level_name, message, context, extra, created_at)
VALUES ('epp', 3, 'warning', :log, :context, '{}', CURRENT_TIMESTAMP)");
$errorLogStmt->execute([
':log' => "Domain: $domainName; hostObj: $hostObj - is duplicated",
':context' => json_encode(['registrar_id' => $clid, 'domain' => $domainName, 'host' => $hostObj])
]);
}
} else {
$internal_host = false;
$stmt = $db->prepare("SELECT tld FROM domain_tld");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$tld = strtoupper($row['tld']);
$tld = str_replace('.', '\\.', $tld); // Escape the dot for regex pattern matching
if (preg_match("/$tld$/i", $hostObj)) {
$internal_host = true;
break;
}
}
$stmt->closeCursor();
if ($internal_host) {
if (preg_match("/\.$domainName$/i", $hostObj)) {
$stmt = $db->prepare("INSERT INTO host (name,domain_id,clid,crid,crdate) VALUES(?, ?, ?, ?, CURRENT_TIMESTAMP(3))");
$stmt->execute([$hostObj, $domain_id, $clid, $clid]);
$host_id = $db->lastInsertId();
$stmt = $db->prepare("INSERT INTO application_host_map (domain_id,host_id) VALUES(?, ?)");
$stmt->execute([$domain_id, $host_id]);
}
} else {
$stmt = $db->prepare("INSERT INTO host (name,clid,crid,crdate) VALUES(?, ?, ?, CURRENT_TIMESTAMP(3))");
$stmt->execute([$hostObj, $clid, $clid]);
$host_id = $db->lastInsertId();
$stmt = $db->prepare("INSERT INTO application_host_map (domain_id,host_id) VALUES(?, ?)");
$stmt->execute([$domain_id, $host_id]);
}
}
}
}
if (!empty($hostAttr_list) && is_array($hostAttr_list)) {
foreach ($hostAttr_list as $node) {
// Extract the hostName
$hostName = strtoupper((string)$node->xpath('./domain:hostName')[0] ?? '');
if (empty($hostName)) {
continue; // Skip if no hostName found
}
// Check if the host already exists
$stmt = $db->prepare("SELECT id FROM host WHERE name = ? LIMIT 1");
$stmt->execute([$hostName]);
$hostName_already_exist = $stmt->fetchColumn();
if ($hostName_already_exist) {
// Check if the host is already mapped to this domain
$stmt = $db->prepare("SELECT domain_id FROM application_host_map WHERE domain_id = ? AND host_id = ? LIMIT 1");
$stmt->execute([$domain_id, $hostName_already_exist]);
$domain_host_map_id = $stmt->fetchColumn();
if (!$domain_host_map_id) {
// Map the host to the domain
$stmt = $db->prepare("INSERT INTO application_host_map (domain_id,host_id) VALUES (?, ?)");
$stmt->execute([$domain_id, $hostName_already_exist]);
} else {
// Log duplicate mapping error
$stmt = $db->prepare("INSERT INTO error_log
(channel, level, level_name, message, context, extra, created_at)
VALUES ('epp', 3, 'warning', ?, ?, '{}', CURRENT_TIMESTAMP)");
$stmt->execute([
"Domain: $domainName; hostName: $hostName - duplicate mapping",
json_encode(['registrar_id' => $clid, 'domain' => $domainName, 'host' => $hostName])
]);
}
} else {
// Insert a new host
$stmt = $db->prepare("INSERT INTO host (name, domain_id, clid, crid, crdate) VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP(3))");
$stmt->execute([$hostName, $domain_id, $clid, $clid]);
$host_id = $db->lastInsertId();
// Map the new host to the domain
$stmt = $db->prepare("INSERT INTO application_host_map (domain_id, host_id) VALUES (?, ?)");
$stmt->execute([$domain_id, $host_id]);
// Process and insert host addresses
foreach ($node->xpath('./domain:hostAddr') as $nodeAddr) {
$hostAddr = (string)$nodeAddr;
$addr_type = (string)($nodeAddr->attributes()->ip ?? 'v4');
// Normalize the address
if ($addr_type === 'v6') {
$hostAddr = normalize_v6_address($hostAddr);
} else {
$hostAddr = normalize_v4_address($hostAddr);
}
// Insert the address into host_addr table
$stmt = $db->prepare("INSERT INTO host_addr (host_id, addr, ip) VALUES (?, ?, ?)");
$stmt->execute([$host_id, $hostAddr, $addr_type]);
}
}
}
}
$contact_admin_list = $xml->xpath("//domain:contact[@type='admin']");
$contact_billing_list = $xml->xpath("//domain:contact[@type='billing']");
$contact_tech_list = $xml->xpath("//domain:contact[@type='tech']");
$contactTypes = [
'admin' => $contact_admin_list,
'billing' => $contact_billing_list,
'tech' => $contact_tech_list
];
foreach ($contactTypes as $type => $contact_list) {
foreach ($contact_list as $element) {
$contact = (string)$element;
$stmt = $db->prepare("SELECT id FROM contact WHERE identifier = ? LIMIT 1");
$stmt->execute([$contact]);
$contact_id = $stmt->fetchColumn();
$stmt = $db->prepare("INSERT INTO application_contact_map (domain_id,contact_id,type) VALUES(?,?,?)");
$stmt->execute([$domain_id, $contact_id, $type]);
}
}
$stmt = $db->prepare("SELECT crdate,exdate FROM domain WHERE name = ? LIMIT 1");
$stmt->execute([$domainName]);
[$crdate, $exdate] = $stmt->fetch(PDO::FETCH_NUM);
$db->commit();
} catch (Exception $e) {
$db->rollBack();
sendEppError($conn, $db, 2400, "Database failure: " . $e->getMessage(), $clTRID, $trans);
}
$svTRID = generateSvTRID();
$response['command'] = 'create_domain';
$response['resultCode'] = 1000;
$response['lang'] = 'en-US';
$response['message'] = 'Command completed successfully';
$response['name'] = $domainName;
$response['crDate'] = $crdate;
$response['exDate'] = null;
$response['clTRID'] = $clTRID;
$response['svTRID'] = $svTRID;
$epp = new EPP\EppWriter();
$xml = $epp->epp_writer($response);
updateTransaction($db, 'create', 'domain', $domainName, 1000, 'Command completed successfully', $svTRID, $xml, $trans);
sendEppResponse($conn, $xml);
} else {
try {
$db->beginTransaction();
@ -1630,4 +1897,5 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m
$xml = $epp->epp_writer($response);
updateTransaction($db, 'create', 'domain', $domainName, 1000, 'Command completed successfully', $svTRID, $xml, $trans);
sendEppResponse($conn, $xml);
}
}

View file

@ -23,6 +23,9 @@ use Money\Currency;
use Money\Converter;
use Money\Currencies\ISOCurrencies;
use Money\Exchange\FixedExchange;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\Guid\Guid;
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
/**
* Sets up and returns a Logger instance.
@ -859,6 +862,20 @@ function formatMoney(Money $money) {
return number_format($money->getAmount() / 100, 2, '.', '');
}
function createUuidFromId($id) {
// Define a namespace UUID; this should be a UUID that is unique to your application
$namespace = '123e4567-e89b-12d3-a456-426614174000';
// Generate a UUIDv5 based on the namespace and a name (in this case, the $id)
try {
$uuid5 = Uuid::uuid5($namespace, (string)$id);
return $uuid5->toString();
} catch (UnsatisfiedDependencyException $e) {
// Handle exception
return null;
}
}
/**
* Fetch a single value from the database using PDO.
*/