add:域名管理

This commit is contained in:
JaguarJack 2020-09-28 09:55:30 +08:00
parent 5ec24ae9c9
commit 4b8d5aa507
17 changed files with 622 additions and 86 deletions

View File

@ -12,7 +12,9 @@
namespace catchAdmin\domain; namespace catchAdmin\domain;
use catchAdmin\domain\support\contract\DomainActionInterface; use catchAdmin\domain\support\contract\DomainActionInterface;
use catchAdmin\domain\support\contract\DomainRecordInterface;
use catchAdmin\domain\support\driver\aliyun\Domain; use catchAdmin\domain\support\driver\aliyun\Domain;
use catchAdmin\domain\support\driver\aliyun\DomainRecord;
use catcher\ModuleService; use catcher\ModuleService;
class DomainService extends ModuleService class DomainService extends ModuleService
@ -29,22 +31,23 @@ class DomainService extends ModuleService
return require __DIR__ . DIRECTORY_SEPARATOR . 'config.php'; return require __DIR__ . DIRECTORY_SEPARATOR . 'config.php';
} }
/**
* @return string
*/
public function loadRouteFrom() public function loadRouteFrom()
{ {
// TODO: Implement loadRouteFrom() method. // TODO: Implement loadRouteFrom() method.
return __DIR__ . DIRECTORY_SEPARATOR . 'route.php'; return __DIR__ . DIRECTORY_SEPARATOR . 'route.php';
} }
/**
*
*/
protected function registerInstance() protected function registerInstance()
{ {
$default = config('catch.domains.default'); $default = config('catch.domains.default');
switch ($default) { $this->app->instance(DomainActionInterface::class, $this->app->make(__NAMESPACE__ . '\\support\\driver\\' . $default . '\Domain'));
case 'aliyun': $this->app->instance(DomainRecordInterface::class, $this->app->make(__NAMESPACE__ . '\\support\\driver\\' . $default . '\DomainRecord'));
$this->app->instance(DomainActionInterface::class, new Domain);
break;
default:
break;
}
} }
} }

46
catch/domain/README.md Normal file
View File

@ -0,0 +1,46 @@
## 域名管理
- 阿里云(主支持)
- 腾讯云(需要做适配)
#### 配置
首先在 .env 文件设置
```
[ALIYUN]
ACCESS_KEY=
ACCESS_SECRET=
[QCLOUD]
ACCESS_KEY=
ACCESS_SECRET=
```
也可以在 config.php 文件配置
```
'domains' => [
// 默认阿里云
'default' => 'aliyun',
/**
* 阿里云配置
*
*/
'aliyun' => [
'api_domain' => 'http://alidns.aliyuncs.com',
'access_key' => Env::get('aliyun.access_key', ''),
'access_secret' => Env::get('aliyun.access_secret', ''),
],
/**
* 腾讯云配置
*
*/
'qcloud' => [
'api_domain' => 'cns.api.qcloud.com',
'access_key' => Env::get('qcloud.access_key', ''),
'access_secret' => Env::get('qcloud.access_secret', ''),
]
]
```

View File

@ -8,6 +8,9 @@
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ] // | Author: JaguarJack [ njphper@gmail.com ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
use think\facade\Env;
return [ return [
'domains' => [ 'domains' => [
// 默认阿里云 // 默认阿里云
@ -20,9 +23,9 @@ return [
'aliyun' => [ 'aliyun' => [
'api_domain' => 'http://alidns.aliyuncs.com', 'api_domain' => 'http://alidns.aliyuncs.com',
'access_key' => 'LTAI4G2JF2iiJEfnQYm4vhvr', 'access_key' => Env::get('aliyun.access_key', ''),
'access_secret' => 'YDe2sff7uDN1nRPdfvVAFCW6lLaOrC', 'access_secret' => Env::get('aliyun.access_secret', ''),
], ],
/** /**
@ -30,8 +33,11 @@ return [
* *
*/ */
'qcloud' => [ 'qcloud' => [
'access_key' => '', 'api_domain' => 'cns.api.qcloud.com',
'access_secret' => '',
'access_key' => Env::get('qcloud.access_key', ''),
'access_secret' => Env::get('qcloud.access_secret', ''),
] ]
] ]
]; ];

View File

@ -36,18 +36,6 @@ class Domain extends CatchController
return CatchResponse::paginate($this->domain->getList($request->param())); return CatchResponse::paginate($this->domain->getList($request->param()));
} }
/**
* 保存
*
* @time 2020/09/11 18:14
* @param Request Request
* @return \think\Response
*/
public function save(Request $request)
{
return CatchResponse::success($this->domain->add($request->post()));
}
/** /**
* 读取 * 读取
* *
@ -57,32 +45,6 @@ class Domain extends CatchController
*/ */
public function read($name) public function read($name)
{ {
return CatchResponse::success($this->domain->info($name)); return CatchResponse::success($this->domain->read(str_replace('-', '.', $name)));
} }
/**
* 更新
*
* @time 2020/09/11 18:14
* @param Request $request
* @return \think\Response
*/
public function update(Request $request, $name)
{
return CatchResponse::success($this->model->updateBy($id, $request->post()));
}
/**
* 删除
*
* @time 2020/09/11 18:14
* @param $name
* @return \think\Response
*/
public function delete($name)
{
return CatchResponse::success($this->domain->delete($name));
}
} }

View File

@ -0,0 +1,99 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\controller;
use catchAdmin\domain\support\contract\DomainRecordInterface;
use catcher\base\CatchRequest as Request;
use catcher\CatchResponse;
use catcher\base\CatchController;
class DomainRecord extends CatchController
{
protected $domainRecord;
public function __construct(DomainRecordInterface $record)
{
$this->domainRecord = $record;
}
/**
* 列表
*
* @time 2020/09/11 18:14
* @param Request $request
* @return \think\Response
*/
public function index(Request $request): \think\Response
{
return CatchResponse::paginate($this->domainRecord->getList($request->param()));
}
/**
* 保存
*
* @time 2020/09/11 18:14
* @param Request Request
* @return \think\Response
*/
public function save(Request $request): \think\Response
{
return CatchResponse::success($this->domainRecord->store($request->post()));
}
/**
* 读取
*
* @time 2020/09/11 18:14
* @param $name
* @return \think\Response
*/
public function read($name): \think\Response
{
return CatchResponse::success($this->domainRecord->read($name));
}
/**
* 更新
*
* @time 2020/09/11 18:14
* @param Request $request
* @param $id
* @return \think\Response
*/
public function update($id, Request $request): \think\Response
{
return CatchResponse::success($this->domainRecord->update($id, $request->post()));
}
/**
* 删除
*
* @time 2020/09/11 18:14
* @param $id
* @return \think\Response
*/
public function delete($id): \think\Response
{
return CatchResponse::success($this->domainRecord->delete($id));
}
/**
* 设置状态
*
* @param $id
* @param $status
* @return \think\response\Json
*/
public function enable($id, $status)
{
return CatchResponse::success($this->domainRecord->enable($id, $status));
}
}

View File

@ -11,5 +11,5 @@
"aliases": {}, "aliases": {},
"files": [], "files": [],
"requires": [], "requires": [],
"enable": true "enable": false
} }

View File

@ -10,9 +10,14 @@
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// you should use `$router` // you should use `$router`
use catchAdmin\domain\controller\DomainRecord;
$router->group(function () use ($router){ $router->group(function () use ($router){
// 域名管理 // 域名管理
$router->resource('domain', '\catchAdmin\domain\controller\Domain'); $router->get('domain', '\catchAdmin\domain\controller\Domain@index');
$router->get('domain/<name>', '\catchAdmin\domain\controller\Domain@read');
// 域名解析管理 // 域名解析管理
$router->resource('record/domain', DomainRecord::class);
$router->put('record/domain/<id>/<status>', '\catchAdmin\domain\controller\DomainRecord@enable');
})->middleware('auth'); })->middleware('auth');

View File

@ -11,6 +11,7 @@
namespace catchAdmin\domain\support; namespace catchAdmin\domain\support;
use catchAdmin\domain\support\signature\Aliyun; use catchAdmin\domain\support\signature\Aliyun;
use catchAdmin\domain\support\signature\Qcloud;
/** /**
* 公共参数 * 公共参数
@ -20,6 +21,13 @@ use catchAdmin\domain\support\signature\Aliyun;
*/ */
class CommonParams class CommonParams
{ {
/**
* 阿里云公共参数
*
* @param array $params
* @param string $method
* @return array
*/
public static function aliyun(array $params, $method = 'GET') public static function aliyun(array $params, $method = 'GET')
{ {
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
@ -38,4 +46,25 @@ class CommonParams
return $params; return $params;
} }
/**
* 腾讯云公共参数
*
* @param array $params
* @param string $method
* @return array
*/
public static function qcloud(array $params, $method = 'GET')
{
$params = array_merge($params, [
'SecretId' => config('catch.domains.qcloud.access_key'),
'SignatureMethod' => 'HmacSHA1',
'Timestamp' => time(),
'Nonce' => uniqid()
]);
$params['Signature'] = (new Qcloud($params))->signature($method);
return $params;
}
} }

View File

@ -14,7 +14,13 @@ use think\Paginator;
class Transformer class Transformer
{ {
public static function aliyunDomainPaginate($data) /**
* 分页展示
*
* @param array $data
* @return mixed
*/
public static function aliyunDomainPaginate(array $data)
{ {
$list = []; $list = [];
@ -24,31 +30,83 @@ class Transformer
'created_at' => date('Y-m-d', $item['CreateTimestamp']/1000), 'created_at' => date('Y-m-d', $item['CreateTimestamp']/1000),
'dns_server' => $item['DnsServers']['DnsServer'], 'dns_server' => $item['DnsServers']['DnsServer'],
'from' => $item['VersionName'], 'from' => $item['VersionName'],
'expired_at' => substr($item['InstanceEndTime'], 0, 10), 'free' => $item['VersionCode'] === 'mianfei',
'record_count' => $item['RecordCount'], 'record_count' => $item['RecordCount'],
'registrant_email' => $item['RegistrantEmail'],
'tags' => $item['Tags']['Tag'], 'tags' => $item['Tags']['Tag'],
'id' => $item['DomainId'] 'id' => $item['DomainId']
]; ];
} }
var_dump($list);
return Paginator::make($list, $data['PageSize'], $data['PageNumber'], $data['TotalCount']); return Paginator::make($list, $data['PageSize'], $data['PageNumber'], $data['TotalCount']);
} }
public static function aliyunDomainRecordPaginate($data) /**
* 腾讯云域名列表
*
* @param array $data
* @param $page
* @param $limit
* @return Paginator|\think\paginator\driver\Bootstrap
*/
public static function qcloudDomainPaginate(array $data, $page, $limit)
{ {
$info = $data['data']['info'];
$domains = $data['data']['domains'];
$list = []; $list = [];
foreach ($data['Domains']['Domain'] as $item) { foreach ($domains as $item) {
$list[] = [ $list[] = [
'name' => $item['DomainName'], 'name' => $item['name'],
'created_at' => date('Y-m-d', $item['CreateTimestamp']/1000), 'created_at' => $item['created_on'],
'dns_server' => $item['DnsServers']['DnsServer'], 'dns_server' => [],
'from' => $item['VersionName'], 'from' => 'qcloud',
'tags' => $item['Tags']['Tag'], 'free' => $item['grade'] === 'DP_Free',
'record_count' => $item['records'],
'tags' => [],
'id' => $item['id']
]; ];
} }
return Paginator::make($list, $limit, $page + 1,$info['domain_total']);
}
/**
* 阿里云域名解析
*
* @param array $data
* @return mixed
*/
public static function aliyunDomainRecordPaginate(array $data)
{
$list = [];
foreach ($data['DomainRecords']['Record'] as &$item) {
$list[] = array_change_key_case($item);
}
return Paginator::make($list, $data['PageSize'], $data['PageNumber'], $data['TotalCount']); return Paginator::make($list, $data['PageSize'], $data['PageNumber'], $data['TotalCount']);
} }
/**
* DNS 记录
*
* @param array $data
* @param $page
* @param $limit
* @return Paginator|\think\paginator\driver\Bootstrap
*/
public static function qcloudDomainRecordPaginate(array $data, $page, $limit)
{
$list = [];
foreach ($data['data']['records'] as &$item) {
$item['status'] = $item['status'] === 'enabled' ? 'ENABLE' : 'DISABLE';
$item['rr'] = $item['name'];
$item['recordid'] = $item['id'];
$list[] = array_change_key_case($item);
}
return Paginator::make($list, $limit, $page + 1, $data['data']['info']['record_total']);
}
} }

View File

@ -18,5 +18,5 @@ interface DomainActionInterface
public function delete(array $params); public function delete(array $params);
public function read(array $params); public function read($name);
} }

View File

@ -16,9 +16,12 @@ interface DomainRecordInterface
public function store(array $params); public function store(array $params);
public function delete(array $params); public function delete($recordId);
public function read(array $params); public function read(array $params);
public function update(array $params); public function update($recordId, array $params);
public function enable($recordId, $status);
} }

View File

@ -19,7 +19,14 @@ trait ApiTrait
{ {
$name = config('catch.domains.default'); $name = config('catch.domains.default');
return Http::query(CommonParams::{$name}($params)) $apiDomain = config('catch.domains.' . $name . '.api_domain');
->get(config('catch.domains.' . $name . '.api_domain'))->json();
if (strpos($apiDomain, 'https') === false &&
strpos($apiDomain, 'http') === false) {
$apiDomain = 'https://' . $apiDomain . '/v2/index.php';
}
return Http::ignoreSsl()->query(CommonParams::{$name}($params))
->get($apiDomain)->json();
} }
} }

View File

@ -44,12 +44,12 @@ class Domain implements DomainActionInterface
]); ]);
} }
public function read(array $params) public function read($name)
{ {
// TODO: Implement info() method. // TODO: Implement info() method.
return $this->get([ return $this->get([
'Action' => 'DescribeDomainInfo', 'Action' => 'DescribeDomainInfo',
'DomainName' => $params['name'] 'DomainName' => $name
]); ]);
} }
} }

View File

@ -12,44 +12,93 @@ namespace catchAdmin\domain\support\driver\aliyun;
use catchAdmin\domain\support\contract\DomainRecordInterface; use catchAdmin\domain\support\contract\DomainRecordInterface;
use catchAdmin\domain\support\driver\ApiTrait; use catchAdmin\domain\support\driver\ApiTrait;
use catchAdmin\domain\support\Transformer;
class DomainRecord implements DomainRecordInterface class DomainRecord implements DomainRecordInterface
{ {
use ApiTrait; use ApiTrait;
/**
* 列表
*
* @param array $params
* @return mixed
*/
public function getList(array $params) public function getList(array $params)
{ {
// TODO: Implement getList() method. $data = [
return $this->get([
'Action' => 'DescribeDomainRecords', 'Action' => 'DescribeDomainRecords',
'DomainName' => $params['name'], 'DomainName' => $params['name'],
'PageNumber' => $params['page'] ?? 1, 'PageNumber' => $params['page'] ?? 1,
'PageSize' => $params['limit'] ?? 20, 'PageSize' => $params['limit'] ?? 20,
'' ];
]);
if ($params['rr']) {
$data['RRKeyWord'] = $params['rr'];
} }
if ($params['type']) {
$data['TypeKeyWord'] = $params['type'];
}
if ($params['value']) {
$data['ValueKeyWord'] = $params['value'];
}
if ($params['line']) {
$data['Line'] = $params['line'];
}
if ($params['status']) {
$data['Status'] = $params['status'];
}
// TODO: Implement getList() method.
return Transformer::aliyunDomainRecordPaginate($this->get($data));
}
/**
* 新增解析
*
* @param array $params
* @return array
*
*/
public function store(array $params) public function store(array $params)
{ {
// TODO: Implement add() method. // TODO: Implement add() method.
return $this->get([ return $this->get([
'Action' => 'AddDomainRecord', 'Action' => 'AddDomainRecord',
'DomainName' => $params['name'], 'DomainName' => $params['name'],
'RR' => $params['record'], 'RR' => $params['rr'],
'Type' => $params['type'], 'Type' => $params['type'],
'Value' => $params['ip'] 'Value' => $params['value'],
'Line' => $params['line'],
'TTL' => $params['ttl'],
]); ]);
} }
public function delete(array $params) /**
* 删除解析
*
* @param $recordId
* @return array
*/
public function delete($recordId)
{ {
// TODO: Implement delete() method. // TODO: Implement delete() method.
return $this->get([ return $this->get([
'Action' => 'DeleteDomainRecord', 'Action' => 'DeleteDomainRecord',
'RecordId' => $params['record_id'] 'RecordId' => $recordId
]); ]);
} }
/**
* 获取解析记录
*
* @param array $params
* @return array
*/
public function read(array $params) public function read(array $params)
{ {
// TODO: Implement info() method. // TODO: Implement info() method.
@ -59,15 +108,40 @@ class DomainRecord implements DomainRecordInterface
]); ]);
} }
public function update(array $params) /**
* 更新解析
*
* @param array $params
* @param $recordId
* @return array
*/
public function update($recordId, array $params)
{ {
// TODO: Implement update() method. // TODO: Implement update() method.
return $this->get([ return $this->get([
'Action' => 'UpdateDomainRecord', 'Action' => 'UpdateDomainRecord',
'RecordId' => $params['record_id'], 'RecordId' => $recordId,
'RR' => $params['record'], 'RR' => $params['rr'],
'Type' => $params['type'], 'Type' => $params['type'],
'Value' => $params['ip'] 'Value' => $params['value'],
'Line' => $params['line'],
'TTL' => $params['ttl'],
]);
}
/**
* 设置状态
*
* @param $recordId
* @param $status
* @return array
*/
public function enable($recordId, $status)
{
return $this->get([
'Action' => 'SetDomainRecordStatus',
'RecordId' => $recordId,
'Status' => ucfirst(strtolower($status))
]); ]);
} }
} }

View File

@ -0,0 +1,56 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\driver\qcloud;
use catchAdmin\domain\support\contract\DomainActionInterface;
use catchAdmin\domain\support\driver\ApiTrait;
use catchAdmin\domain\support\Transformer;
class Domain implements DomainActionInterface
{
use ApiTrait;
public function getList(array $params)
{
$offset = ($params['page'] ?? 1) - 1;
$length = $params['limit'] ?? 10;
// TODO: Implement getList() method.
return Transformer::qcloudDomainPaginate($this->get([
'Action' => 'DomainList',
'offset' => $offset,
'length' => $length
]), $offset, $length);
}
public function store(array $params)
{
// TODO: Implement add() method.
}
public function delete(array $params)
{
// TODO: Implement delete() method.
return $this->get([
'Action' => 'DeleteDomain',
'DomainName' => $params['name'],
]);
}
public function read($name)
{
// TODO: Implement info() method.
return $this->get([
'Action' => 'DescribeDomainInfo',
'DomainName' => $name
]);
}
}

View File

@ -0,0 +1,125 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\driver\qcloud;
use catchAdmin\domain\support\contract\DomainRecordInterface;
use catchAdmin\domain\support\driver\ApiTrait;
use catchAdmin\domain\support\Transformer;
class DomainRecord implements DomainRecordInterface
{
use ApiTrait;
/**
* 列表
*
* @param array $params
* @return mixed
*/
public function getList(array $params)
{
$data = [
'Action' => 'RecordList',
'domain' => $params['name'],
'offset' => ($params['page'] ?? 1) - 1,
'length' => $params['limit'] ?? 10,
];
if ($params['rr']) {
$data['subDomain'] = $params['rr'];
}
if ($params['type']) {
$data['recordType'] = $params['type'];
}
// TODO: Implement getList() method.
return Transformer::qcloudDomainRecordPaginate($this->get($data), $data['offset'], $data['length']);
}
/**
* 新增解析
*
* @param array $params
* @return array
*
*/
public function store(array $params)
{
// TODO: Implement add() method.
return $this->get([
'Action' => 'RecordCreate',
'domain' => $params['name'],
'subDomain' => $params['rr'],
'recordType' => $params['type'],
'value' => $params['value'],
'recordLine' => $params['line'],
'ttl' => $params['ttl'],
]);
}
/**
* 删除解析
*
* @param $recordId
* @return array
*/
public function delete($recordId)
{
// TODO: Implement delete() method.
return $this->get([
'Action' => 'RecordDelete',
'recordId' => $recordId
]);
}
/**
* 更新解析
*
* @param array $params
* @param $recordId
* @return array
*/
public function update($recordId, array $params)
{
// TODO: Implement update() method.
return $this->get([
'Action' => 'RecordModify',
'recordId' => $recordId,
'subDomain' => $params['rr'],
'recordType' => $params['type'],
'value' => $params['value'],
'recordLine' => $params['line'],
'ttl' => $params['ttl'],
]);
}
/**
* 设置状态
*
* @param $recordId
* @param $status
* @return array
*/
public function enable($recordId, $status)
{
return $this->get([
'Action' => 'RecordStatus',
'recordId' => $recordId,
'Status' => strtolower($status)
]);
}
public function read(array $params)
{
// TODO: Implement read() method.
}
}

View File

@ -0,0 +1,63 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catchAdmin\domain\support\signature;
class Qcloud
{
/**
* @var array
*/
protected $params;
/**
* Qcloud constructor.
* @param $params
*/
public function __construct(array $params)
{
$this->params = $params;
}
/**
* key 替换
*
* @param $key
* @return mixed|string|string[]
*/
protected function replaceKey($key)
{
return strpos($key, '_') === false ?
$key : str_replace('_', '.', $key);
}
/**
* 签名
*
* @time 2020年09月25日
* @param $method
* @return string
*/
public function signature(string $method)
{
ksort($this->params);
$queryString = '';
foreach ($this->params as $key => $param) {
$queryString .= '&' . $this->replaceKey($key) . '=' . $param;
}
$signString = $method . config('catch.domains.qcloud.api_domain') . '/v2/index.php?'
. substr($queryString, 1);
return base64_encode(hash_hmac('sha1', $signString, config('catch.domains.qcloud.access_secret'), true));
}
}