array( 'friendlyName' => 'Config Content', 'type' => 'textarea', 'validators' => array( 'required' => 'required', ) ), ); public $availableTypes = array('A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'TXT', 'SPF', 'SRV'); public function testConnection() { try { $domainRelations = new GoogleCloud\DomainRelations(); $domainRelations->createTableIfNotExists(); $this->apiTestConnection(); return true; } catch (\Exception $e) { throw new exceptions\DNSSubmoduleException($e->getMessage(), dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM); } } public function getRecords($recordType = false) { try { $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $results = $service->resourceRecordSets->listResourceRecordSets($this->getProjectID(), $this->getDomainName()); $return = []; if (!empty($results->rrsets)) { foreach ($results->rrsets as $key => $r) { $i = 0; foreach ($r->rrdatas as $rdata) { $record = new dns\record\Record(); $record->line = $key . '-' . $i++; $record->name = $r->name; $record->type = $r->type; $record->ttl = $r->ttl; $record->createRDATAObject(); if( $record->type === 'TXT' ) { $record->rdata->txtdata = $rdata; } else { $record->rdata = $this->assignValuesToFields($record->rdata, $rdata); } $return[] = $record; } } } return $return; } catch (\Exception $ex) { throw new exceptions\DNSSubmoduleException($ex->getMessage(), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } public function addRecord(dns\record\Record $record) { try { $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); if( $record->type === 'TXT' ) { $record->rdata->txtdata = htmlspecialchars_decode($record->rdata->txtdata); } $model = new \Google_Service_Dns_ResourceRecordSet(); $model->setName($record->nameToAbsolute($this->domain)); $model->setType($record->type); $model->setTtl($record->ttl); $model->setRrdatas([implode(' ', $this->preapareArray($record->rdata))]); $additions = new \Google_Service_Dns_Change(); $additions->setAdditions([$model]); $service->changes->create($this->getProjectID(), $this->getDomainName(), $additions); return true; } catch (\Exception $ex) { throw new exceptions\DNSSubmoduleException($this->getErrorMessage($ex), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } public function editRecord(dns\record\Record $record) { try { $lines = $this->getLines($record); $newLines = $this->getNewLines($record); if( $record->type === 'TXT' ) { $record->rdata->txtdata = htmlspecialchars_decode($record->rdata->txtdata); } if (count($lines) > 1) { $rData = $this->getRDataForLines($lines); $newRData = $this->getRDataForLines($newLines); } else { $rData = [implode(' ', $this->preapareArray($lines[0]->rdata))]; $newRData = [implode(' ', $this->preapareArray($record->rdata))]; } $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $removeModel = new \Google_Service_Dns_ResourceRecordSet(); $removeModel->setName($lines[0]->name); $removeModel->setType($lines[0]->type); $removeModel->setTtl($lines[0]->ttl); $removeModel->setRrdatas(array_values($rData)); $addModel = new \Google_Service_Dns_ResourceRecordSet(); $addModel->setName($record->nameToAbsolute($this->domain)); $addModel->setType($record->type); $addModel->setTtl($record->ttl); $addModel->setRrdatas(array_values($newRData)); $additions = new \Google_Service_Dns_Change(); $additions->setDeletions([$removeModel]); $additions->setAdditions([$addModel]); $service->changes->create($this->getProjectID(), $this->getDomainName(), $additions); return true; } catch (\Exception $ex) { throw new exceptions\DNSSubmoduleException($this->getErrorMessage($ex), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } public function getNewLines(dns\record\Record $record) { $lines = $this->getLines($record); foreach ($lines as $line) { if ($line->line == $record->line) { $line->rdata = $record->rdata; } } return $lines; } public function customDeleteRecord($records, $toRemove) { try { $newRData = $this->getRDataForLines($records); $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $removeModel = new \Google_Service_Dns_ResourceRecordSet(); $removeModel->setName($toRemove->nameToAbsolute($this->domain)); $removeModel->setType($toRemove->type); $removeModel->setTtl($toRemove->ttl); $removeModel->setRrdatas(array_values($newRData)); unset($newRData[$this->preapareArray($toRemove->rdata)[0]]); $addModel = new \Google_Service_Dns_ResourceRecordSet(); $addModel->setName($toRemove->nameToAbsolute($this->domain)); $addModel->setType($toRemove->type); $addModel->setTtl($toRemove->ttl); $addModel->setRrdatas(array_values($newRData)); $additions = new \Google_Service_Dns_Change(); $additions->setDeletions([$removeModel]); $additions->setAdditions([$addModel]); $service->changes->create($this->getProjectID(), $this->getDomainName(), $additions); return true; } catch (\Exception $ex) { throw new exceptions\DNSSubmoduleException($this->getErrorMessage($ex), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } public function getRDataForLines($lines) { $newRData = []; foreach ($lines as $row) { $rData = $this->preapareArray($row->rdata)[0]; $newRData[$rData] = $rData; } return $newRData; } public function deleteRecord(dns\record\Record $record) { try { $lines = $this->getLines($record); if( $record->type === 'TXT' ) { $record->rdata->txtdata = htmlspecialchars_decode($record->rdata->txtdata); } if (count($lines) > 1) { $this->customDeleteRecord($lines, $record); } else { $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $model = new \Google_Service_Dns_ResourceRecordSet(); $model->setName($record->nameToAbsolute($this->domain)); $model->setType($record->type); $model->setTtl($record->ttl); $model->setRrdatas([implode(' ', $this->preapareArray($record->rdata))]); $additions = new \Google_Service_Dns_Change(); $additions->setDeletions([$model]); $service->changes->create($this->getProjectID(), $this->getDomainName(), $additions); } } catch (\Exception $ex) { throw new exceptions\DNSSubmoduleException($this->getErrorMessage($ex), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } public function getLines(dns\record\Record $record) { $records = $this->getRecords(); if (empty($records)) { return false; } $lines = []; foreach ($records as $r) { if (explode('-', $r->line)[0] == explode('-', $record->line)[0]) { $lines[] = $r; } } return $lines; } public function zoneExists() { try { $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $service->managedZones->get($this->getProjectID(), $this->getDomainName()); return true; } catch( \Exception $ex ) { if( $ex->getErrors() && $ex->getErrors()[0]['reason'] === 'notFound' ) { return false; } throw $ex; } } public function activateZone() { if ($this->ip != '') { if (!filter_var($this->ip, FILTER_VALIDATE_IP)) { throw new exceptions\DNSSubmoduleException('IP is not valid!', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } try { $model = new \Google_Service_Dns_ManagedZone(); $model->setName($this->getDomainName()); $model->setDnsName($this->getDNSName()); $model->setDescription($this->ip); $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $service->managedZones->create($this->getProjectID(), $model); } catch (\Exception $ex) { throw new exceptions\DNSSubmoduleException($this->getErrorMessage($ex), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } public function terminateZone() { try { $this->clearRecords(); $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $service->managedZones->delete($this->getProjectID(), $this->getDomainName()); return true; } catch (\Exception $ex) { throw new exceptions\DNSSubmoduleException($this->getErrorMessage($ex), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } private function clearRecords(){ foreach ($this->getRecords() as $record) { try{ $this->deleteRecord($record); } catch(\Exception $e) { continue; } } } public function getZones() { try { $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $results = $service->managedZones->listManagedZones($this->getProjectID()); $out = []; foreach ($results->managedZones as $zone) { $domainName = rtrim($zone->dnsName, "."); $domainRelations = GoogleCloud\DomainRelations::WhereName($domainName)->first(); if (is_null($domainRelations)) { $model = new GoogleCloud\DomainRelations([ 'domain' => $domainName, 'name' => $zone->name ]); $model->save(); } $out[$domainName] = ''; } } catch (\Exception $ex) { throw new exceptions\DNSSubmoduleException($this->getErrorMessage($ex), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } return $out; } /* * Google API * */ private function apiTestConnection() { $client = $this->getGoogleClient(); $service = new \Google_Service_Dns($client); $results = $service->managedZones->listManagedZones($this->getProjectID()); return $results; } private function assignValuesToFields($object, $values) { $fields = get_object_vars($object); $values = explode(' ', $values); $i = 0; foreach ($fields as $field => $v) { $object->{$field} = $values[$i++]; } return $object; } private function preapareArray($object) { $return = []; foreach ($object as $option) { $return[] = $option; } return $return; } private function getDomainName() { $domainRelations = GoogleCloud\DomainRelations::WhereDomain($this->domain)->first(); if ($domainRelations->name) { return $domainRelations->name; } $name = str_replace('.', '-', strtolower($this->domain)) . time(); $model = new GoogleCloud\DomainRelations([ 'domain' => $this->domain, 'name' => $name ]); $model->save(); return $name; } private function getDNSName() { return $this->domain . '.'; } private function getConfigArray() { if (!$config = json_decode(htmlspecialchars_decode($this->config['configContent']), true)) { throw new \Exception('Invalid json for auth config'); } return $config; } private function getProjectID() { return $this->getConfigArray()['project_id']; } private function getErrorMessage(\Exception $ex) { $object = \json_decode($ex->getMessage(), true); return $object['error']['message']; } private function getGoogleClient() { $googleClient = new \Google_Client(); $googleClient->setAuthConfig($this->getConfigArray()); $googleClient->addScope(\Google_Service_Dns::CLOUD_PLATFORM); return $googleClient; } }