Refactor Cloudflare DNS to add and remove A records for custom domains (#1905)

* Refactor Cloudflare DNS to add and remove A records for custom domains

* rebase
This commit is contained in:
David Bomba 2018-02-20 21:14:21 +11:00 committed by GitHub
parent 1d1d785174
commit 8e7b53fd26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 155 additions and 35 deletions

View File

@ -0,0 +1,21 @@
<?php
namespace App\Events;
use Illuminate\Queue\SerializesModels;
class SubdomainWasRemoved extends Event
{
use SerializesModels;
public $account;
/**
* Create a new event instance.
*
* @param $account
*/
public function __construct($account)
{
$this->account = $account;
}
}

View File

@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Events\SubdomainWasRemoved;
use App\Events\SubdomainWasUpdated;
use App\Events\UserSettingsChanged;
use App\Events\UserSignedUp;
@ -630,10 +631,10 @@ class AccountController extends BaseController
// sample invoice to help determine variables
$invoice = Invoice::scope()
->invoiceType(INVOICE_TYPE_STANDARD)
->with('client', 'account')
->where('is_recurring', '=', false)
->first();
->invoiceType(INVOICE_TYPE_STANDARD)
->with('client', 'account')
->where('is_recurring', '=', false)
->first();
if ($invoice) {
$invoice->hidePrivateFields();
@ -824,18 +825,27 @@ class AccountController extends BaseController
}
}
(bool) $fireUpdateSubdomainEvent = false;
if ($account->subdomain !== $request->subdomain) {
event(new SubdomainWasUpdated($account));
$fireUpdateSubdomainEvent = true;
event(new SubdomainWasRemoved($account));
}
$account->fill($request->all());
$account->client_view_css = $request->client_view_css;
$account->subdomain = $request->subdomain;
$account->subdomain = $request->subdomain;
$account->iframe_url = $request->iframe_url;
$account->save();
if ($fireUpdateSubdomainEvent) {
event(new SubdomainWasUpdated($account));
}
return redirect('settings/' . ACCOUNT_CLIENT_PORTAL)
->with('message', trans('texts.updated_settings'));
->with('message', trans('texts.updated_settings'));
}
/**
@ -852,7 +862,7 @@ class AccountController extends BaseController
$settings->save();
return redirect('settings/' . ACCOUNT_EMAIL_SETTINGS)
->with('message', trans('texts.updated_settings'));
->with('message', trans('texts.updated_settings'));
}
/**
@ -1007,8 +1017,8 @@ class AccountController extends BaseController
}
if (! $account->share_counter
&& $account->invoice_number_prefix == $account->quote_number_prefix
&& $account->invoice_number_pattern == $account->quote_number_pattern) {
&& $account->invoice_number_prefix == $account->quote_number_prefix
&& $account->invoice_number_pattern == $account->quote_number_pattern) {
Session::flash('error', trans('texts.invalid_counter'));
return Redirect::to('settings/'.ACCOUNT_INVOICE_SETTINGS)->withInput();
@ -1311,8 +1321,8 @@ class AccountController extends BaseController
}
$email = User::withTrashed()->where('email', '=', $email)
->where('id', '<>', $user->registered ? 0 : $user->id)
->first();
->where('id', '<>', $user->registered ? 0 : $user->id)
->first();
if ($email) {
return 'taken';
@ -1520,8 +1530,8 @@ class AccountController extends BaseController
{
$template = Input::get('template');
$invitation = \App\Models\Invitation::scope()
->with('invoice.client.contacts')
->first();
->with('invoice.client.contacts')
->first();
if (! $invitation) {
return trans('texts.create_invoice_for_sample');

View File

@ -2,6 +2,7 @@
namespace App\Listeners;
use App\Events\SubdomainWasRemoved;
use App\Events\SubdomainWasUpdated;
use App\Ninja\DNS\Cloudflare;
@ -19,4 +20,11 @@ class DNSListener
if(env("CLOUDFLARE_DNS_ENABLED"))
Cloudflare::addDNSRecord($event->account);
}
public function removeDNSRecord(SubdomainWasRemoved $event)
{
if(env("CLOUDFLARE_DNS_ENABLED"))
Cloudflare::removeDNSRecord($event->account);
}
}

View File

@ -18,31 +18,16 @@ class Cloudflare
if($account->subdomain != "")
{
$curl = curl_init();
$jsonEncodedData = json_encode(['type' => 'A', 'name' => $account->subdomain, 'content' => env('CLOUDFLARE_TARGET_IP_ADDRESS', ''), 'proxied' => true]);
$opts = [
CURLOPT_URL => 'https://api.cloudflare.com/client/v4/zones/' . $zone . '/dns_records',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $jsonEncodedData,
CURLOPT_HTTPHEADER => ['Content-Type: application/json',
'Content-Length: ' . strlen($jsonEncodedData),
'X-Auth-Email: ' . env('CLOUDFLARE_EMAIL', ''),
'X-Auth-Key: ' . env('CLOUDFLARE_API_KEY', '')
],
];
$requestType = 'POST';
curl_setopt_array($curl, $opts);
$url = 'https://api.cloudflare.com/client/v4/zones/' . $zone . '/dns_records';
$result = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$response = self::curlCloudFlare($requestType, $url, $jsonEncodedData);
curl_close($curl);
if ($status != 200)
Utils::logError('unable to update subdomain ' . $account->subdomain . ' @ Cloudflare - ' . $result);
if ($response['status'] != 200)
Utils::logError('Unable to update subdomain ' . $account->subdomain . ' @ Cloudflare - ' . $response['result']['result']);
}
@ -51,5 +36,96 @@ class Cloudflare
}
public static function removeDNSRecord(Account $account) {
$zones = json_decode(env('CLOUDFLARE_ZONE_IDS',''), true);
foreach($zones as $zone)
{
if($account->subdomain != "")
{
$dnsRecordId = self::getDNSRecord($zone, $account->subdomain);
$jsonEncodedData = json_encode([]);
$requestType = 'DELETE';
$url = 'https://api.cloudflare.com/client/v4/zones/' . $zone . '/dns_records/'. $dnsRecordId .'';
$response = self::curlCloudFlare($requestType, $url, $jsonEncodedData);
if ($response['status'] != 200)
Utils::logError('Unable to delete subdomain ' . $account->subdomain . ' @ Cloudflare - ' . $response['result']['result']);
}
}
}
public static function getDNSRecord($zone, $aRecord)
{
//harvest the zone_name
$url = 'https://api.cloudflare.com/client/v4/zones/'. $zone .'/dns_records?type=A&per_page=1';
$requestType = 'GET';
$jsonEncodedData = json_encode([]);
$response = self::curlCloudFlare($requestType, $url, $jsonEncodedData);
if ($response['status'] != 200)
Utils::logError('Unable to get the zone name for ' . $aRecord . ' @ Cloudflare - ' . $response['result']['result']);
$zoneName = $response['result']['result'][0]['zone_name'];
//get the A record
$url = 'https://api.cloudflare.com/client/v4/zones/'. $zone .'/dns_records?type=A&name='. $aRecord .'.'. $zoneName .' ';
$response = self::curlCloudFlare($requestType, $url, $jsonEncodedData);
if ($response['status'] != 200)
Utils::logError('Unable to get the record ID for ' . $aRecord . ' @ Cloudflare - ' . $response['result']['result']);
return $response['result']['result'][0]['id'];
}
private static function curlCloudFlare($requestType, $url, $jsonEncodedData)
{
$curl = curl_init();
$opts = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $requestType,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $jsonEncodedData,
CURLOPT_HTTPHEADER => ['Content-Type: application/json',
'Content-Length: ' . strlen($jsonEncodedData),
'X-Auth-Email: ' . env('CLOUDFLARE_EMAIL', ''),
'X-Auth-Key: ' . env('CLOUDFLARE_API_KEY', '')
],
];
curl_setopt_array($curl, $opts);
$result = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$data['status'] = $status;
$data['result'] = \json_decode($result, true);
curl_close($curl);
return $data;
}
}

View File

@ -225,9 +225,14 @@ class EventServiceProvider extends ServiceProvider
'App\Listeners\InvoiceListener@jobFailed'
],
//DNS
//DNS Add A record to Cloudflare
'App\Events\SubdomainWasUpdated' => [
'App\Listeners\DNSListener@addDNSRecord'
],
//DNS Remove A record from Cloudflare
'App\Events\SubdomainWasRemoved' => [
'App\Listeners\DNSListener@removeDNSRecord'
]
/*