lthn.io/app/Mod/Names/Actions/UpdateDnsRecords.php

92 lines
2.5 KiB
PHP
Raw Permalink Normal View History

<?php
declare(strict_types=1);
namespace Mod\Names\Actions;
use Illuminate\Support\Facades\Cache;
use Illuminate\Validation\ValidationException;
use Mod\Chain\Services\DaemonRpc;
use Mod\Chain\Services\WalletRpc;
use Mod\Names\Models\DnsTicket;
use Mod\Names\Models\NameActivity;
/**
* Update DNS records for a .lthn name on the sidechain.
*
* $ticket = UpdateDnsRecords::run('mybrand', [
* ['type' => 'A', 'host' => '@', 'value' => '1.2.3.4'],
* ]);
*/
class UpdateDnsRecords
{
public function __construct(
private readonly DaemonRpc $rpc,
private readonly WalletRpc $wallet,
) {}
public function handle(string $name, array $records): DnsTicket
{
$name = strtolower(trim($name));
// Edit lock
$editLock = "dns_edit_lock:{$name}";
if (Cache::has($editLock)) {
throw ValidationException::withMessages([
'name' => 'A DNS update for this name is already pending.',
]);
}
$alias = $this->rpc->getAliasByName($name);
if (! $alias) {
throw ValidationException::withMessages([
'name' => 'Name not registered.',
]);
}
$address = $alias['address'] ?? '';
$comment = $this->buildComment($records);
$result = $this->wallet->updateAlias($name, $address, $comment);
if (isset($result['tx_id'])) {
Cache::put($editLock, true, 300);
$ticket = DnsTicket::open($name, $records, $result['tx_id'], $address, $comment);
} else {
$ticket = DnsTicket::open($name, $records, null, $address, $comment);
}
NameActivity::log($name, 'dns_updated', [
'ticket_id' => $ticket->ticket_id,
'records' => $records,
], request()?->ip());
return $ticket;
}
private function buildComment(array $records): string
{
$dnsEntries = [];
foreach ($records as $record) {
$type = $record['type'] ?? 'A';
$host = $record['host'] ?? '@';
$value = $record['value'] ?? '';
if ($value) {
$dnsEntries[] = "{$type}:{$host}:{$value}";
}
}
$comment = 'v=lthn1;type=user';
if ($dnsEntries) {
$comment .= ';dns=' . implode('|', $dnsEntries);
}
return $comment;
}
public static function run(string $name, array $records): DnsTicket
{
return app(static::class)->handle($name, $records);
}
}