mirror of
https://github.com/netcccyun/dnsmgr.git
synced 2026-05-09 23:16:27 +02:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44790639cd | ||
|
|
5b12a368fc | ||
|
|
36622e6642 | ||
|
|
12d8017df5 | ||
|
|
70f2e0d487 | ||
|
|
521275ee33 | ||
|
|
c06bf2d34c | ||
|
|
39dc789ac3 | ||
|
|
0877674efb | ||
|
|
fe9a50469d | ||
|
|
d9f8cc18eb | ||
|
|
48d5ad7569 |
@@ -456,4 +456,19 @@ function curl_set_proxy(&$ch)
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
|
||||
}
|
||||
|
||||
function convertDomainToAscii($domain) {
|
||||
if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $domain)) {
|
||||
return idn_to_ascii($domain);
|
||||
} else {
|
||||
return $domain;
|
||||
}
|
||||
}
|
||||
function convertDomainToUtf8($domain) {
|
||||
if (preg_match('/^xn--/', $domain)) {
|
||||
return idn_to_utf8($domain);
|
||||
} else {
|
||||
return $domain;
|
||||
}
|
||||
}
|
||||
@@ -203,6 +203,7 @@ class Cert extends BaseController
|
||||
$domain = $this->request->post('domain', null, 'trim');
|
||||
$id = input('post.id');
|
||||
$type = input('post.type', null, 'trim');
|
||||
$status = input('post.status', null, 'trim');
|
||||
$offset = input('post.offset/d');
|
||||
$limit = input('post.limit/d');
|
||||
|
||||
@@ -216,6 +217,17 @@ class Cert extends BaseController
|
||||
if (!empty($type)) {
|
||||
$select->where('B.type', $type);
|
||||
}
|
||||
if (!isNullOrEmpty($status)) {
|
||||
if ($status == '5') {
|
||||
$select->where('A.status', '<', 0);
|
||||
} elseif ($status == '6') {
|
||||
$select->where('A.expiretime', '<', date('Y-m-d H:i:s', time() + 86400 * 7))->where('A.expiretime', '>=', date('Y-m-d H:i:s'));
|
||||
} elseif ($status == '7') {
|
||||
$select->where('A.expiretime', '<', date('Y-m-d H:i:s'));
|
||||
} else {
|
||||
$select->where('A.status', $status);
|
||||
}
|
||||
}
|
||||
$total = $select->count();
|
||||
$rows = $select->fieldRaw('A.*,B.type,B.remark aremark')->order('id', 'desc')->limit($offset, $limit)->select();
|
||||
|
||||
@@ -272,7 +284,7 @@ class Cert extends BaseController
|
||||
foreach($domains as $domain){
|
||||
$domainList[] = [
|
||||
'oid' => $id,
|
||||
'domain' => $domain,
|
||||
'domain' => convertDomainToAscii($domain),
|
||||
'sort' => $i++,
|
||||
];
|
||||
}
|
||||
@@ -310,7 +322,7 @@ class Cert extends BaseController
|
||||
foreach($domains as $domain){
|
||||
$domainList[] = [
|
||||
'oid' => $id,
|
||||
'domain' => $domain,
|
||||
'domain' => convertDomainToAscii($domain),
|
||||
'sort' => $i++,
|
||||
];
|
||||
}
|
||||
@@ -441,7 +453,8 @@ class Cert extends BaseController
|
||||
}
|
||||
|
||||
foreach($domains as $domain){
|
||||
if(!$wildcard && strpos($domain, '*') !== false) return ['code' => -1, 'msg' => '该证书账户类型不支持泛域名'];
|
||||
if (!$wildcard && strpos($domain, '*') !== false) return ['code' => -1, 'msg' => '该证书账户类型不支持泛域名'];
|
||||
if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $domain) && !function_exists('idn_to_ascii')) return ['code' => -1, 'msg' => '域名包含中文,请开启intl扩展'];
|
||||
$mainDomain = getMainDomain($domain);
|
||||
$drow = Db::name('domain')->where('name', $mainDomain)->find();
|
||||
if (!$drow) {
|
||||
@@ -477,7 +490,7 @@ class Cert extends BaseController
|
||||
return json(['code' => 0, 'msg' => '添加DNS记录成功!请等待DNS生效后点击验证']);
|
||||
}
|
||||
}catch(Exception $e){
|
||||
return json(['code' => -1, 'msg' => $e->getMessage()]);
|
||||
return json(['code' => -1, 'msg' => $e->getMessage(), 'trace' => $e->getTrace()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,6 +553,7 @@ class Cert extends BaseController
|
||||
$domain = $this->request->post('domain', null, 'trim');
|
||||
$oid = input('post.oid');
|
||||
$type = input('post.type', null, 'trim');
|
||||
$status = input('post.status', null, 'trim');
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
$offset = input('post.offset/d');
|
||||
$limit = input('post.limit/d');
|
||||
@@ -554,6 +568,9 @@ class Cert extends BaseController
|
||||
if (!empty($type)) {
|
||||
$select->where('B.type', $type);
|
||||
}
|
||||
if (!isNullOrEmpty($status)) {
|
||||
$select->where('A.status', $status);
|
||||
}
|
||||
if (!empty($remark)) {
|
||||
$select->where('A.remark', $remark);
|
||||
}
|
||||
@@ -651,7 +668,7 @@ class Cert extends BaseController
|
||||
$service->process(true);
|
||||
return json(['code' => 0, 'msg' => 'SSL证书部署任务执行成功!']);
|
||||
}catch(Exception $e){
|
||||
return json(['code' => -1, 'msg' => $e->getMessage()]);
|
||||
return json(['code' => -1, 'msg' => $e->getMessage(), 'trace' => $e->getTrace()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ class Dmonitor extends BaseController
|
||||
'cycle' => input('post.cycle/d'),
|
||||
'timeout' => input('post.timeout/d'),
|
||||
'proxy' => input('post.proxy/d'),
|
||||
'cdn' => input('post.cdn') == 'true' || input('post.cdn') == '1' ? 1 : 0,
|
||||
'remark' => input('post.remark', null, 'trim'),
|
||||
'recordinfo' => input('post.recordinfo', null, 'trim'),
|
||||
'addtime' => time(),
|
||||
@@ -123,6 +124,7 @@ class Dmonitor extends BaseController
|
||||
'cycle' => input('post.cycle/d'),
|
||||
'timeout' => input('post.timeout/d'),
|
||||
'proxy' => input('post.proxy/d'),
|
||||
'cdn' => input('post.cdn') == 'true' || input('post.cdn') == '1' ? 1 : 0,
|
||||
'remark' => input('post.remark', null, 'trim'),
|
||||
'recordinfo' => input('post.recordinfo', null, 'trim'),
|
||||
];
|
||||
@@ -163,8 +165,9 @@ class Dmonitor extends BaseController
|
||||
}
|
||||
|
||||
$domains = [];
|
||||
foreach (Db::name('domain')->select() as $row) {
|
||||
$domains[$row['id']] = $row['name'];
|
||||
$domainList = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->field('A.id,A.name,B.type')->select();
|
||||
foreach ($domainList as $row) {
|
||||
$domains[] = ['id'=>$row['id'], 'name'=>$row['name'], 'type'=>$row['type']];
|
||||
}
|
||||
View::assign('domains', $domains);
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@ class Domain extends BaseController
|
||||
$is_hide = input('post.is_hide/d');
|
||||
$is_sso = input('post.is_sso/d');
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
if (empty($remark)) $remark = null;
|
||||
Db::name('domain')->where('id', $id)->update([
|
||||
'is_hide' => $is_hide,
|
||||
'is_sso' => $is_sso,
|
||||
@@ -273,6 +274,22 @@ class Domain extends BaseController
|
||||
}
|
||||
Db::name('domain')->insertAll($data);
|
||||
return json(['code' => 0, 'msg' => '成功添加' . count($data) . '个域名!']);
|
||||
} elseif ($act == 'batchedit') {
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
$ids = input('post.ids');
|
||||
if (empty($ids)) return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
if (empty($remark)) $remark = null;
|
||||
Db::name('domain')->where('id', 'in', $ids)->update(['remark' => $remark]);
|
||||
return json(['code' => 0, 'msg' => '成功修改' . count($ids) . '个域名!']);
|
||||
} elseif ($act == 'batchdel') {
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
$ids = input('post.ids');
|
||||
if (empty($ids)) return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
Db::name('domain')->where('id', 'in', $ids)->delete();
|
||||
Db::name('dmtask')->where('did', 'in', $ids)->delete();
|
||||
Db::name('optimizeip')->where('did', 'in', $ids)->delete();
|
||||
return json(['code' => 0, 'msg' => '成功删除' . count($ids) . '个域名!']);
|
||||
}
|
||||
return json(['code' => -3]);
|
||||
}
|
||||
@@ -413,7 +430,7 @@ class Domain extends BaseController
|
||||
}
|
||||
|
||||
$dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
|
||||
if ($dnstype == 'baidu' || $dnstype == 'namesilo') {
|
||||
if (DnsHelper::$dns_config[$dnstype]['page']) {
|
||||
return json($domainRecords['list']);
|
||||
}
|
||||
|
||||
@@ -470,7 +487,7 @@ class Domain extends BaseController
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
$recordid = $dns->addDomainRecord($name, $type, $value, $line, $ttl, $mx, $weight, $remark);
|
||||
if ($recordid) {
|
||||
$this->add_log($drow['name'], '添加解析', $type . '记录 ' . $name . ' ' . $value . ' (线路:' . $line . ' TTL:' . $ttl . ')');
|
||||
$this->add_log($drow['name'], '添加解析', $name.' ['.$type.'] '.$value.' (线路:'.$line.' TTL:'.$ttl.')');
|
||||
return json(['code' => 0, 'msg' => '添加解析记录成功!']);
|
||||
} else {
|
||||
return json(['code' => -1, 'msg' => '添加解析记录失败,' . $dns->getError()]);
|
||||
@@ -496,6 +513,9 @@ class Domain extends BaseController
|
||||
$mx = input('post.mx/d', 1);
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
|
||||
$recordinfo = input('post.recordinfo', null, 'trim');
|
||||
$recordinfo = json_decode($recordinfo, true);
|
||||
|
||||
if (empty($recordid) || empty($name) || empty($type) || empty($value)) {
|
||||
return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
}
|
||||
@@ -503,7 +523,11 @@ class Domain extends BaseController
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
$recordid = $dns->updateDomainRecord($recordid, $name, $type, $value, $line, $ttl, $mx, $weight, $remark);
|
||||
if ($recordid) {
|
||||
$this->add_log($drow['name'], '修改解析', $type . '记录 ' . $name . ' ' . $value . ' (线路:' . $line . ' TTL:' . $ttl . ')');
|
||||
if ($recordinfo['Name'] != $name || $recordinfo['Type'] != $type || $recordinfo['Value'] != $value) {
|
||||
$this->add_log($drow['name'], '修改解析', $recordinfo['Name'].' ['.$recordinfo['Type'].'] '.$recordinfo['Value'].' → '.$name.' ['.$type.'] '.$value.' (线路:'.$line.' TTL:'.$ttl.')');
|
||||
} elseif($recordinfo['Line'] != $line || $recordinfo['TTL'] != $ttl) {
|
||||
$this->add_log($drow['name'], '修改解析', $name.' ['.$type.'] '.$value.' (线路:'.$line.' TTL:'.$ttl.')');
|
||||
}
|
||||
return json(['code' => 0, 'msg' => '修改解析记录成功!']);
|
||||
} else {
|
||||
return json(['code' => -1, 'msg' => '修改解析记录失败,' . $dns->getError()]);
|
||||
@@ -520,6 +544,8 @@ class Domain extends BaseController
|
||||
if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
|
||||
|
||||
$recordid = input('post.recordid', null, 'trim');
|
||||
$recordinfo = input('post.recordinfo', null, 'trim');
|
||||
$recordinfo = json_decode($recordinfo, true);
|
||||
|
||||
if (empty($recordid)) {
|
||||
return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
@@ -527,7 +553,11 @@ class Domain extends BaseController
|
||||
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
if ($dns->deleteDomainRecord($recordid)) {
|
||||
$this->add_log($drow['name'], '删除解析', '记录ID:' . $recordid);
|
||||
if ($recordinfo) {
|
||||
$this->add_log($drow['name'], '删除解析', $recordinfo['Name'].' ['.$recordinfo['Type'].'] '.$recordinfo['Value'].' (线路:'.$recordinfo['Line'].' TTL:'.$recordinfo['TTL'].')');
|
||||
} else {
|
||||
$this->add_log($drow['name'], '删除解析', '记录ID:'.$recordid);
|
||||
}
|
||||
return json(['code' => 0, 'msg' => '删除解析记录成功!']);
|
||||
} else {
|
||||
return json(['code' => -1, 'msg' => '删除解析记录失败,' . $dns->getError()]);
|
||||
@@ -545,6 +575,8 @@ class Domain extends BaseController
|
||||
|
||||
$recordid = input('post.recordid', null, 'trim');
|
||||
$status = input('post.status', null, 'trim');
|
||||
$recordinfo = input('post.recordinfo', null, 'trim');
|
||||
$recordinfo = json_decode($recordinfo, true);
|
||||
|
||||
if (empty($recordid)) {
|
||||
return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
@@ -553,7 +585,11 @@ class Domain extends BaseController
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
if ($dns->setDomainRecordStatus($recordid, $status)) {
|
||||
$action = $status == '1' ? '启用解析' : '暂停解析';
|
||||
$this->add_log($drow['name'], $action, '记录ID:' . $recordid);
|
||||
if ($recordinfo) {
|
||||
$this->add_log($drow['name'], $action, $recordinfo['Name'].' ['.$recordinfo['Type'].'] '.$recordinfo['Value'].' (线路:'.$recordinfo['Line'].' TTL:'.$recordinfo['TTL'].')');
|
||||
} else {
|
||||
$this->add_log($drow['name'], $action, '记录ID:'.$recordid);
|
||||
}
|
||||
return json(['code' => 0, 'msg' => '操作成功!']);
|
||||
} else {
|
||||
return json(['code' => -1, 'msg' => '操作失败,' . $dns->getError()]);
|
||||
@@ -594,10 +630,11 @@ class Domain extends BaseController
|
||||
}
|
||||
if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
|
||||
|
||||
$recordids = input('post.recordids', null, 'trim');
|
||||
$action = input('post.action', null, 'trim');
|
||||
$recordinfo = input('post.recordinfo', null, 'trim');
|
||||
$recordinfo = json_decode($recordinfo, true);
|
||||
|
||||
if (empty($recordids) || empty($action)) {
|
||||
if (empty($recordinfo) || empty($action)) {
|
||||
return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
}
|
||||
|
||||
@@ -605,25 +642,25 @@ class Domain extends BaseController
|
||||
$fail = 0;
|
||||
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
|
||||
if ($action == 'open') {
|
||||
foreach ($recordids as $recordid) {
|
||||
if ($dns->setDomainRecordStatus($recordid, '1')) {
|
||||
$this->add_log($drow['name'], '启用解析', '记录ID:' . $recordid);
|
||||
foreach ($recordinfo as $record) {
|
||||
if ($dns->setDomainRecordStatus($record['RecordId'], '1')) {
|
||||
$this->add_log($drow['name'], '启用解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
|
||||
$success++;
|
||||
}
|
||||
}
|
||||
$msg = '成功启用' . $success . '条解析记录';
|
||||
} else if ($action == 'pause') {
|
||||
foreach ($recordids as $recordid) {
|
||||
if ($dns->setDomainRecordStatus($recordid, '0')) {
|
||||
$this->add_log($drow['name'], '暂停解析', '记录ID:' . $recordid);
|
||||
foreach ($recordinfo as $record) {
|
||||
if ($dns->setDomainRecordStatus($record['RecordId'], '0')) {
|
||||
$this->add_log($drow['name'], '暂停解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
|
||||
$success++;
|
||||
}
|
||||
}
|
||||
$msg = '成功暂停' . $success . '条解析记录';
|
||||
} else if ($action == 'delete') {
|
||||
foreach ($recordids as $recordid) {
|
||||
if ($dns->deleteDomainRecord($recordid)) {
|
||||
$this->add_log($drow['name'], '删除解析', '记录ID:' . $recordid);
|
||||
foreach ($recordinfo as $record) {
|
||||
if ($dns->deleteDomainRecord($record['RecordId'])) {
|
||||
$this->add_log($drow['name'], '删除解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
|
||||
$success++;
|
||||
}
|
||||
}
|
||||
@@ -631,8 +668,8 @@ class Domain extends BaseController
|
||||
} else if ($action == 'remark') {
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
if (empty($remark)) $remark = null;
|
||||
foreach ($recordids as $recordid) {
|
||||
if ($dns->updateDomainRecordRemark($recordid, $remark)) {
|
||||
foreach ($recordinfo as $record) {
|
||||
if ($dns->updateDomainRecordRemark($record['RecordId'], $remark)) {
|
||||
$success++;
|
||||
} else {
|
||||
$fail++;
|
||||
@@ -669,9 +706,9 @@ class Domain extends BaseController
|
||||
$success = 0;
|
||||
$fail = 0;
|
||||
foreach ($recordinfo as $record) {
|
||||
$recordid = $dns->updateDomainRecord($record['recordid'], $record['name'], $type, $value, $record['line'], $record['ttl'], $record['mx'], $record['weight'], $record['remark']);
|
||||
$recordid = $dns->updateDomainRecord($record['RecordId'], $record['Name'], $type, $value, $record['Line'], $record['TTL'], $record['MX'], $record['Weight'], $record['Remark']);
|
||||
if ($recordid) {
|
||||
$this->add_log($drow['name'], '修改解析', $type . '记录 ' . $record['name'] . ' ' . $value . ' (线路:' . $record['line'] . ' TTL:' . $record['ttl'] . ')');
|
||||
$this->add_log($drow['name'], '修改解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' → '.$record['Name'].' ['.$type.'] '.$value.' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
|
||||
$success++;
|
||||
} else {
|
||||
$fail++;
|
||||
@@ -690,9 +727,9 @@ class Domain extends BaseController
|
||||
$success = 0;
|
||||
$fail = 0;
|
||||
foreach ($recordinfo as $record) {
|
||||
$recordid = $dns->updateDomainRecord($record['recordid'], $record['name'], $record['type'], $record['value'], $line, $record['ttl'], $record['mx'], $record['weight'], $record['remark']);
|
||||
$recordid = $dns->updateDomainRecord($record['RecordId'], $record['Name'], $record['Type'], $record['Value'], $line, $record['TTL'], $record['MX'], $record['Weight'], $record['Remark']);
|
||||
if ($recordid) {
|
||||
$this->add_log($drow['name'], '修改解析', $record['type'] . '记录 ' . $record['name'] . ' ' . $record['value'] . ' (线路:' . $line . ' TTL:' . $record['ttl'] . ')');
|
||||
$this->add_log($drow['name'], '修改解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$line.' TTL:'.$record['TTL'].')');
|
||||
$success++;
|
||||
} else {
|
||||
$fail++;
|
||||
@@ -735,7 +772,7 @@ class Domain extends BaseController
|
||||
$thistype = empty($type) ? getDnsType($arr[1]) : $type;
|
||||
$recordid = $dns->addDomainRecord($arr[0], $thistype, $arr[1], $line, $ttl, $mx);
|
||||
if ($recordid) {
|
||||
$this->add_log($drow['name'], '添加解析', $thistype . '记录 ' . $arr[0] . ' ' . $arr[1] . ' (线路:' . $line . ' TTL:' . $ttl . ')');
|
||||
$this->add_log($drow['name'], '添加解析', $arr[0].' ['.$thistype.'] '.$arr[1].' (线路:'.$line.' TTL:'.$ttl.')');
|
||||
$success++;
|
||||
} else {
|
||||
$fail++;
|
||||
|
||||
@@ -19,15 +19,17 @@ class Index extends BaseController
|
||||
}
|
||||
if ($this->request->isAjax()) {
|
||||
if (input('post.do') == 'stat') {
|
||||
$stat = ['domains' => 0, 'users' => 0, 'records' => 0, 'types' => count(DnsHelper::$dns_config)];
|
||||
$stat = ['domains' => 0, 'tasks' => 0, 'certs' => 0, 'deploys' => 0];
|
||||
if ($this->request->user['level'] == 2) {
|
||||
$stat['domains'] = Db::name('domain')->count();
|
||||
$stat['users'] = Db::name('user')->count();
|
||||
$stat['records'] = Db::name('domain')->sum('recordcount');
|
||||
$stat['tasks'] = Db::name('dmtask')->count();
|
||||
$stat['certs'] = Db::name('cert_order')->count();
|
||||
$stat['deploys'] = Db::name('cert_deploy')->count();
|
||||
} else {
|
||||
$stat['domains'] = Db::name('domain')->where('name', 'in', $this->request->user['permission'])->count();
|
||||
$stat['users'] = 1;
|
||||
$stat['records'] = Db::name('domain')->where('name', 'in', $this->request->user['permission'])->sum('recordcount');
|
||||
$stat['tasks'] = Db::name('dmtask')->count();
|
||||
$stat['certs'] = Db::name('cert_order')->count();
|
||||
$stat['deploys'] = Db::name('cert_deploy')->count();
|
||||
}
|
||||
return json($stat);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ class DeployHelper
|
||||
'options' => [
|
||||
'0' => '宝塔面板站点的证书',
|
||||
'1' => '宝塔面板本身的证书',
|
||||
'2' => '宝塔邮局域名的证书',
|
||||
],
|
||||
'value' => '0',
|
||||
'required' => true,
|
||||
@@ -51,14 +52,14 @@ class DeployHelper
|
||||
'name' => '网站名称列表',
|
||||
'type' => 'textarea',
|
||||
'placeholder' => '填写要部署证书的网站名称,每行一个',
|
||||
'note' => 'PHP项目和反代项目填写创建时绑定的第一个域名,Java/Node/Go等其他项目填写项目名称',
|
||||
'show' => 'type==0',
|
||||
'note' => 'PHP项目和反代项目填写创建时绑定的第一个域名,Java/Node/Go等其他项目填写项目名称,邮局填写域名',
|
||||
'show' => 'type==0||type==2',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'kangle' => [
|
||||
'name' => 'Kangle',
|
||||
'name' => 'Kangle用户',
|
||||
'class' => 1,
|
||||
'icon' => 'host.png',
|
||||
'note' => '以上登录信息为Easypanel用户面板的,非管理员面板。如选网站密码认证类型,则用户面板登录不能开启验证码。',
|
||||
@@ -130,6 +131,72 @@ class DeployHelper
|
||||
],
|
||||
],
|
||||
],
|
||||
'kangleadmin' => [
|
||||
'name' => 'Kangle管理员',
|
||||
'class' => 1,
|
||||
'icon' => 'host.png',
|
||||
'note' => '以上登录地址需填写Easypanel管理员面板地址,非用户面板。',
|
||||
'inputs' => [
|
||||
'url' => [
|
||||
'name' => '面板地址',
|
||||
'type' => 'input',
|
||||
'placeholder' => 'Easypanel管理员面板地址',
|
||||
'note' => '填写规则如:http://192.168.1.100:3312 ,不要带其他后缀',
|
||||
'required' => true,
|
||||
],
|
||||
'path' => [
|
||||
'name' => '管理员面板路径',
|
||||
'type' => 'input',
|
||||
'placeholder' => '留空默认为/admin',
|
||||
],
|
||||
'username' => [
|
||||
'name' => '管理员用户名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'skey' => [
|
||||
'name' => '面板安全码',
|
||||
'type' => 'input',
|
||||
'placeholder' => '管理员面板->服务器设置->面板通信安全码',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'name' => [
|
||||
'name' => '网站用户名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'type' => [
|
||||
'name' => '部署类型',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '网站SSL证书',
|
||||
'1' => '单域名SSL证书(仅CDN支持)',
|
||||
],
|
||||
'value' => '0',
|
||||
'required' => true,
|
||||
],
|
||||
'domains' => [
|
||||
'name' => 'CDN域名列表',
|
||||
'type' => 'textarea',
|
||||
'placeholder' => '填写要部署证书的域名,每行一个',
|
||||
'show' => 'type==1',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'safeline' => [
|
||||
'name' => '雷池WAF',
|
||||
'class' => 1,
|
||||
@@ -399,6 +466,106 @@ class DeployHelper
|
||||
],
|
||||
],
|
||||
],
|
||||
'synology' => [
|
||||
'name' => '群辉面板',
|
||||
'class' => 1,
|
||||
'icon' => 'synology.png',
|
||||
'note' => null,
|
||||
'tasknote' => '',
|
||||
'inputs' => [
|
||||
'url' => [
|
||||
'name' => '面板地址',
|
||||
'type' => 'input',
|
||||
'placeholder' => '群辉面板地址',
|
||||
'note' => '填写规则如:http://192.168.1.100:5000 ,不要带其他后缀',
|
||||
'required' => true,
|
||||
],
|
||||
'username' => [
|
||||
'name' => '登录账号',
|
||||
'type' => 'input',
|
||||
'placeholder' => '必须是处于管理员用户组,不能开启双重认证',
|
||||
'required' => true,
|
||||
],
|
||||
'password' => [
|
||||
'name' => '登录密码',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'version' => [
|
||||
'name' => '群辉版本',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '7.x',
|
||||
'1' => '6.x',
|
||||
],
|
||||
'value' => '0',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'desc' => [
|
||||
'name' => '群晖证书描述',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'note' => '根据证书描述匹配替换对应证书,留空则根据证书通用名匹配',
|
||||
],
|
||||
],
|
||||
],
|
||||
'proxmox' => [
|
||||
'name' => 'Proxmox VE',
|
||||
'class' => 1,
|
||||
'icon' => 'proxmox.ico',
|
||||
'note' => '在“权限->API令牌”添加令牌,不要选特权分离',
|
||||
'tasknote' => '',
|
||||
'inputs' => [
|
||||
'url' => [
|
||||
'name' => '面板地址',
|
||||
'type' => 'input',
|
||||
'placeholder' => 'Proxmox VE 面板地址',
|
||||
'note' => '填写规则如:https://192.168.1.100:8006 ,不要带其他后缀',
|
||||
'required' => true,
|
||||
],
|
||||
'api_user' => [
|
||||
'name' => 'API令牌ID',
|
||||
'type' => 'input',
|
||||
'placeholder' => '用户!令牌名称',
|
||||
'required' => true,
|
||||
],
|
||||
'api_key' => [
|
||||
'name' => 'API令牌密钥',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'node' => [
|
||||
'name' => '节点名称',
|
||||
'type' => 'input',
|
||||
'placeholder' => '要部署证书的节点',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'aliyun' => [
|
||||
'name' => '阿里云',
|
||||
'class' => 2,
|
||||
@@ -1082,18 +1249,63 @@ class DeployHelper
|
||||
],
|
||||
'taskinputs' => [
|
||||
'product' => [
|
||||
'name' => '产品',
|
||||
'type' => 'hidden',
|
||||
'name' => '要部署的产品',
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
['value'=>'cdn', 'label'=>'CDN加速'],
|
||||
['value'=>'icdn', 'label'=>'全站加速'],
|
||||
['value'=>'accessone', 'label'=>'边缘安全加速平台'],
|
||||
],
|
||||
'value' => 'cdn',
|
||||
'required' => true,
|
||||
],
|
||||
'domain' => [
|
||||
'name' => 'CDN域名',
|
||||
'name' => '绑定的域名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'kuocai' => [
|
||||
'name' => '括彩云',
|
||||
'class' => 2,
|
||||
'icon' => 'kuocai.jpg',
|
||||
'note' => '支持括彩云及其代理商,填写控制台登录账号及密码',
|
||||
'inputs' => [
|
||||
'username' => [
|
||||
'name' => '账号',
|
||||
'type' => 'input',
|
||||
'placeholder' => '控制台账号',
|
||||
'note' => '填写手机号或邮箱',
|
||||
'required' => true,
|
||||
],
|
||||
'password' => [
|
||||
'name' => '密码',
|
||||
'type' => 'input',
|
||||
'placeholder' => '控制台密码',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'id' => [
|
||||
'name' => '域名ID',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'note' => '在控制台->我的域名->配置复制浏览器地址栏显示的域名ID(19位数字),注意域名是否与证书匹配',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'allwaf' => [
|
||||
'name' => 'AllWAF',
|
||||
'class' => 2,
|
||||
|
||||
@@ -18,6 +18,7 @@ class DnsHelper
|
||||
'redirect' => true, //是否支持域名转发
|
||||
'log' => true, //是否支持查看日志
|
||||
'weight' => false, //是否支持权重
|
||||
'page' => false, //是否客户端分页
|
||||
],
|
||||
'dnspod' => [
|
||||
'name' => '腾讯云',
|
||||
@@ -30,6 +31,7 @@ class DnsHelper
|
||||
'redirect' => true,
|
||||
'log' => true,
|
||||
'weight' => true,
|
||||
'page' => false,
|
||||
],
|
||||
'huawei' => [
|
||||
'name' => '华为云',
|
||||
@@ -42,6 +44,7 @@ class DnsHelper
|
||||
'redirect' => false,
|
||||
'log' => false,
|
||||
'weight' => true,
|
||||
'page' => false,
|
||||
],
|
||||
'baidu' => [
|
||||
'name' => '百度云',
|
||||
@@ -54,6 +57,7 @@ class DnsHelper
|
||||
'redirect' => false,
|
||||
'log' => false,
|
||||
'weight' => false,
|
||||
'page' => true,
|
||||
],
|
||||
'west' => [
|
||||
'name' => '西部数码',
|
||||
@@ -66,6 +70,7 @@ class DnsHelper
|
||||
'redirect' => false,
|
||||
'log' => false,
|
||||
'weight' => false,
|
||||
'page' => false,
|
||||
],
|
||||
'huoshan' => [
|
||||
'name' => '火山引擎',
|
||||
@@ -78,6 +83,7 @@ class DnsHelper
|
||||
'redirect' => false,
|
||||
'log' => false,
|
||||
'weight' => true,
|
||||
'page' => false,
|
||||
],
|
||||
'dnsla' => [
|
||||
'name' => 'DNSLA',
|
||||
@@ -90,6 +96,7 @@ class DnsHelper
|
||||
'redirect' => true,
|
||||
'log' => false,
|
||||
'weight' => true,
|
||||
'page' => false,
|
||||
],
|
||||
'cloudflare' => [
|
||||
'name' => 'Cloudflare',
|
||||
@@ -102,6 +109,7 @@ class DnsHelper
|
||||
'redirect' => false,
|
||||
'log' => false,
|
||||
'weight' => false,
|
||||
'page' => false,
|
||||
],
|
||||
'namesilo' => [
|
||||
'name' => 'NameSilo',
|
||||
@@ -114,6 +122,21 @@ class DnsHelper
|
||||
'redirect' => false,
|
||||
'log' => false,
|
||||
'weight' => false,
|
||||
'page' => true,
|
||||
],
|
||||
'powerdns' => [
|
||||
'name' => 'PowerDNS',
|
||||
'config' => [
|
||||
'ak' => 'IP地址',
|
||||
'sk' => '端口',
|
||||
'ext' => 'API KEY',
|
||||
],
|
||||
'remark' => 2,
|
||||
'status' => true,
|
||||
'redirect' => false,
|
||||
'log' => false,
|
||||
'weight' => false,
|
||||
'page' => true,
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
@@ -46,13 +46,24 @@ class btpanel implements DeployInterface
|
||||
foreach ($sites as $site) {
|
||||
$siteName = trim($site);
|
||||
if (empty($siteName)) continue;
|
||||
try {
|
||||
$this->deploySite($siteName, $fullchain, $privatekey);
|
||||
$this->log("网站 {$siteName} 证书部署成功");
|
||||
$success++;
|
||||
} catch (Exception $e) {
|
||||
$errmsg = $e->getMessage();
|
||||
$this->log("网站 {$siteName} 证书部署失败:" . $errmsg);
|
||||
if ($config['type'] == '2') {
|
||||
try {
|
||||
$this->deployMailSys($siteName, $fullchain, $privatekey);
|
||||
$this->log("邮局域名 {$siteName} 证书部署成功");
|
||||
$success++;
|
||||
} catch (Exception $e) {
|
||||
$errmsg = $e->getMessage();
|
||||
$this->log("邮局域名 {$siteName} 证书部署失败:" . $errmsg);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
$this->deploySite($siteName, $fullchain, $privatekey);
|
||||
$this->log("网站 {$siteName} 证书部署成功");
|
||||
$success++;
|
||||
} catch (Exception $e) {
|
||||
$errmsg = $e->getMessage();
|
||||
$this->log("网站 {$siteName} 证书部署失败:" . $errmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($success == 0) {
|
||||
@@ -98,6 +109,26 @@ class btpanel implements DeployInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function deployMailSys($domain, $fullchain, $privatekey)
|
||||
{
|
||||
$path = '/plugin?action=a&name=mail_sys&s=set_mail_certificate_multiple';
|
||||
$data = [
|
||||
'domain' => $domain,
|
||||
'key' => $privatekey,
|
||||
'csr' => $fullchain,
|
||||
'act' => 'add',
|
||||
];
|
||||
$response = $this->request($path, $data);
|
||||
$result = json_decode($response, true);
|
||||
if (isset($result['status']) && $result['status']) {
|
||||
return true;
|
||||
} elseif (isset($result['msg'])) {
|
||||
throw new Exception($result['msg']);
|
||||
} else {
|
||||
throw new Exception($response ? $response : '返回数据解析失败');
|
||||
}
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
|
||||
@@ -12,20 +12,19 @@ class ctyun implements DeployInterface
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $proxy;
|
||||
private $client;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->SecretAccessKey = $config['SecretAccessKey'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new CtyunClient($this->AccessKeyId, $this->SecretAccessKey, 'ctcdn-global.ctapi.ctyun.cn', $this->proxy);
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->AccessKeyId) || empty($this->SecretAccessKey)) throw new Exception('必填参数不能为空');
|
||||
$this->client->request('GET', '/v1/cert/query-cert-list');
|
||||
$client = new CtyunClient($this->AccessKeyId, $this->SecretAccessKey, 'ctcdn-global.ctapi.ctyun.cn', $this->proxy);
|
||||
$client->request('GET', '/v1/cert/query-cert-list');
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,31 +32,42 @@ class ctyun implements DeployInterface
|
||||
{
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
$config['cert_name'] = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
if ($config['product'] == 'cdn') {
|
||||
$this->deploy_cdn($fullchain, $privatekey, $config);
|
||||
} elseif ($config['product'] == 'icdn') {
|
||||
$this->deploy_icdn($fullchain, $privatekey, $config);
|
||||
} elseif ($config['product'] == 'accessone') {
|
||||
$this->deploy_accessone($fullchain, $privatekey, $config);
|
||||
}
|
||||
}
|
||||
|
||||
private function deploy_cdn($fullchain, $privatekey, $config)
|
||||
{
|
||||
$client = new CtyunClient($this->AccessKeyId, $this->SecretAccessKey, 'ctcdn-global.ctapi.ctyun.cn', $this->proxy);
|
||||
$param = [
|
||||
'name' => $cert_name,
|
||||
'name' => $config['cert_name'],
|
||||
'key' => $privatekey,
|
||||
'certs' => $fullchain,
|
||||
];
|
||||
try {
|
||||
$this->client->request('POST', '/v1/cert/creat-cert', null, $param);
|
||||
$client->request('POST', '/v1/cert/creat-cert', null, $param);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '已存在重名的证书') !== false) {
|
||||
$this->log('已存在重名的证书 cert_name=' . $cert_name);
|
||||
$this->log('已存在重名的证书 cert_name=' . $config['cert_name']);
|
||||
} else {
|
||||
throw new Exception('上传证书失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
$this->log('上传证书成功 cert_name=' . $cert_name);
|
||||
$this->log('上传证书成功 cert_name=' . $config['cert_name']);
|
||||
|
||||
$param = [
|
||||
'domain' => $config['domain'],
|
||||
'https_status' => 'on',
|
||||
'cert_name' => $cert_name,
|
||||
'cert_name' => $config['cert_name'],
|
||||
];
|
||||
try {
|
||||
$this->client->request('POST', '/v1/domain/update-domain', null, $param);
|
||||
$client->request('POST', '/v1/domain/update-domain', null, $param);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '请求已提交,请勿重复操作!') === false) {
|
||||
throw new Exception($e->getMessage());
|
||||
@@ -67,6 +77,99 @@ class ctyun implements DeployInterface
|
||||
$this->log('CDN域名 ' . $config['domain'] . ' 部署证书成功!');
|
||||
}
|
||||
|
||||
private function deploy_icdn($fullchain, $privatekey, $config)
|
||||
{
|
||||
$client = new CtyunClient($this->AccessKeyId, $this->SecretAccessKey, 'icdn-global.ctapi.ctyun.cn', $this->proxy);
|
||||
$param = [
|
||||
'name' => $config['cert_name'],
|
||||
'key' => $privatekey,
|
||||
'certs' => $fullchain,
|
||||
];
|
||||
try {
|
||||
$client->request('POST', '/v1/cert/creat-cert', null, $param);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '已存在重名的证书') !== false) {
|
||||
$this->log('已存在重名的证书 cert_name=' . $config['cert_name']);
|
||||
} else {
|
||||
throw new Exception('上传证书失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
$this->log('上传证书成功 cert_name=' . $config['cert_name']);
|
||||
|
||||
$param = [
|
||||
'domain' => $config['domain'],
|
||||
'https_status' => 'on',
|
||||
'cert_name' => $config['cert_name'],
|
||||
];
|
||||
try {
|
||||
$client->request('POST', '/v1/domain/update-domain', null, $param);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '请求已提交,请勿重复操作!') === false) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$this->log('CDN域名 ' . $config['domain'] . ' 部署证书成功!');
|
||||
}
|
||||
|
||||
private function deploy_accessone($fullchain, $privatekey, $config)
|
||||
{
|
||||
$client = new CtyunClient($this->AccessKeyId, $this->SecretAccessKey, 'accessone-global.ctapi.ctyun.cn', $this->proxy);
|
||||
$param = [
|
||||
'name' => $config['cert_name'],
|
||||
'key' => $privatekey,
|
||||
'certs' => $fullchain,
|
||||
];
|
||||
try {
|
||||
$client->request('POST', '/ctapi/v1/accessone/cert/create', null, $param);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '已存在重名的证书') !== false) {
|
||||
$this->log('已存在重名的证书 cert_name=' . $config['cert_name']);
|
||||
} else {
|
||||
throw new Exception('上传证书失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
$this->log('上传证书成功 cert_name=' . $config['cert_name']);
|
||||
|
||||
$param = [
|
||||
'domain' => $config['domain'],
|
||||
'product_code' => '020',
|
||||
];
|
||||
try {
|
||||
$result = $client->request('POST', '/ctapi/v1/accessone/domain/config', null, $param);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('查询域名配置失败:' . $e->getMessage());
|
||||
}
|
||||
|
||||
if ($result['https_status'] == 'on' && $result['cert_name'] == $config['cert_name']) {
|
||||
$this->log('边缘安全加速域名 ' . $config['domain'] . ' 证书已部署,无需重复操作!');
|
||||
return;
|
||||
}
|
||||
|
||||
$result['https_status'] = 'on';
|
||||
$result['cert_name'] = $config['cert_name'];
|
||||
$exclude_keys = ['status', 'area_scope', 'cname', 'insert_date', 'status_date', 'record_status', 'record_num', 'customer_name', 'outlink_replace_filter', 'website_ipv6_access_mark', 'websocket_speed', 'dynamic_config', 'dynamic_ability'];
|
||||
foreach ($result as $key => $value) {
|
||||
if (in_array($key, $exclude_keys) || is_array($value) && empty($value)) {
|
||||
unset($result[$key]);
|
||||
}
|
||||
}
|
||||
if (isset($result['origin'])) {
|
||||
foreach ($result['origin'] as &$origin) {
|
||||
$origin['weight'] = strval($origin['weight']);
|
||||
}
|
||||
}
|
||||
try {
|
||||
$client->request('POST', '/ctapi/v1/accessone/domain/modify_config', null, $result);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '请求已提交,请勿重复操作!') === false) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$this->log('边缘安全加速域名 ' . $config['domain'] . ' 部署证书成功!');
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
|
||||
173
app/lib/deploy/kangleadmin.php
Normal file
173
app/lib/deploy/kangleadmin.php
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\deploy;
|
||||
|
||||
use app\lib\DeployInterface;
|
||||
use Exception;
|
||||
|
||||
class kangleadmin implements DeployInterface
|
||||
{
|
||||
private $logger;
|
||||
private $url;
|
||||
private $path;
|
||||
private $username;
|
||||
private $skey;
|
||||
private $proxy;
|
||||
private $cookie;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->url = rtrim($config['url'], '/');
|
||||
if (empty($config['path'])) $config['path'] = '/admin';
|
||||
$this->path = rtrim($config['path'], '/');
|
||||
$this->username = $config['username'];
|
||||
$this->skey = $config['skey'];
|
||||
$this->proxy = $config['proxy'] == 1;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->username) || empty($this->skey)) throw new Exception('必填参数不能为空');
|
||||
$this->login();
|
||||
}
|
||||
|
||||
public function deploy($fullchain, $privatekey, $config, &$info)
|
||||
{
|
||||
if (empty($config['name'])) throw new Exception('网站用户名不能为空');
|
||||
$this->login();
|
||||
$this->log('登录成功 cookie:' . $this->cookie);
|
||||
$this->loginVhost($config['name']);
|
||||
|
||||
if ($config['type'] == '1' && !empty($config['domains'])) {
|
||||
$domains = explode("\n", $config['domains']);
|
||||
$success = 0;
|
||||
$errmsg = null;
|
||||
foreach ($domains as $domain) {
|
||||
$domain = trim($domain);
|
||||
if (empty($domain)) continue;
|
||||
try {
|
||||
$this->deployDomain($domain, $fullchain, $privatekey);
|
||||
$this->log("域名 {$domain} 证书部署成功");
|
||||
$success++;
|
||||
} catch (Exception $e) {
|
||||
$errmsg = $e->getMessage();
|
||||
$this->log("域名 {$domain} 证书部署失败:" . $errmsg);
|
||||
}
|
||||
}
|
||||
if ($success == 0) {
|
||||
throw new Exception($errmsg ? $errmsg : '要部署的域名不存在');
|
||||
}
|
||||
} else {
|
||||
$this->deployAccount($fullchain, $privatekey);
|
||||
$this->log("账号级SSL证书部署成功");
|
||||
}
|
||||
}
|
||||
|
||||
private function deployDomain($domain, $fullchain, $privatekey)
|
||||
{
|
||||
$path = '/vhost/?c=ssl&a=domainSsl';
|
||||
$post = [
|
||||
'domain' => $domain,
|
||||
'certificate' => $fullchain,
|
||||
'certificate_key' => $privatekey,
|
||||
];
|
||||
$response = curl_client($this->url . $path, http_build_query($post), null, $this->cookie, null, $this->proxy);
|
||||
if (strpos($response['body'], '成功')) {
|
||||
return true;
|
||||
} elseif (preg_match('/alert\(\'(.*?)\'\)/i', $response['body'], $match)) {
|
||||
throw new Exception(htmlspecialchars($match[1]));
|
||||
} elseif (strlen($response['body']) > 3 && strlen($response['body']) < 50) {
|
||||
throw new Exception(htmlspecialchars($response['body']));
|
||||
} else {
|
||||
throw new Exception('原因未知(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
|
||||
private function deployAccount($fullchain, $privatekey)
|
||||
{
|
||||
$path = '/vhost/?c=ssl&a=ssl';
|
||||
$post = [
|
||||
'certificate' => $fullchain,
|
||||
'certificate_key' => $privatekey,
|
||||
];
|
||||
$response = curl_client($this->url . $path, http_build_query($post), null, $this->cookie, null, $this->proxy);
|
||||
if (strpos($response['body'], '成功')) {
|
||||
return true;
|
||||
} elseif (preg_match('/alert\(\'(.*?)\'\)/i', $response['body'], $match)) {
|
||||
throw new Exception(htmlspecialchars($match[1]));
|
||||
} elseif (strlen($response['body']) > 3 && strlen($response['body']) < 50) {
|
||||
throw new Exception(htmlspecialchars($response['body']));
|
||||
} else {
|
||||
throw new Exception('原因未知(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
|
||||
private function login()
|
||||
{
|
||||
$url = $this->url . $this->path . '/index.php?c=sso&a=hello&url=' . urlencode($this->url . $this->path . '/index.php?');
|
||||
$response = curl_client($url, null, null, null, null, $this->proxy);
|
||||
if ($response['code'] == 302 && !empty($response['redirect_url'])) {
|
||||
$cookie = '';
|
||||
if (preg_match_all('/Set-Cookie: (.*);/iU', $response['header'], $matchs)) {
|
||||
foreach ($matchs[1] as $val) {
|
||||
$arr = explode('=', $val);
|
||||
if ($arr[1] == '' || $arr[1] == 'deleted') continue;
|
||||
$cookie .= $val . '; ';
|
||||
}
|
||||
$query = parse_url($response['redirect_url'], PHP_URL_QUERY);
|
||||
parse_str($query, $params);
|
||||
if (isset($params['r'])) {
|
||||
$sess_key = $params['r'];
|
||||
$this->login2($cookie, $sess_key);
|
||||
$this->cookie = $cookie;
|
||||
return true;
|
||||
} else {
|
||||
throw new Exception('获取SSO凭据失败,sess_key获取失败');
|
||||
}
|
||||
} else {
|
||||
throw new Exception('获取SSO凭据失败,获取cookie失败');
|
||||
}
|
||||
} elseif (strlen($response['body']) > 3 && strlen($response['body']) < 50) {
|
||||
throw new Exception('获取SSO凭据失败 (' . htmlspecialchars($response['body']) . ')');
|
||||
} else {
|
||||
throw new Exception('获取SSO凭据失败 (httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
|
||||
private function login2($cookie, $sess_key)
|
||||
{
|
||||
$s = md5($sess_key . $this->username . $sess_key . $this->skey);
|
||||
$url = $this->url . $this->path . '/index.php?c=sso&a=login&name=' . $this->username . '&r=' . $sess_key . '&s=' . $s;
|
||||
$response = curl_client($url, null, null, $cookie, null, $this->proxy);
|
||||
if ($response['code'] == 302) {
|
||||
return true;
|
||||
} elseif (strlen($response['body']) > 3 && strlen($response['body']) < 50) {
|
||||
throw new Exception('SSO登录失败 (' . htmlspecialchars($response['body']) . ')');
|
||||
} else {
|
||||
throw new Exception('SSO登录失败 (httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
|
||||
private function loginVhost($name)
|
||||
{
|
||||
$url = $this->url . $this->path . '/index.php?c=vhost&a=impLogin&name=' . $name;
|
||||
$response = curl_client($url, null, null, $this->cookie, null, $this->proxy);
|
||||
if ($response['code'] == 302) {
|
||||
curl_client($this->url . '/vhost/', null, null, $this->cookie, null, $this->proxy);
|
||||
} else {
|
||||
throw new Exception('用户面板登录失败 (httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
}
|
||||
|
||||
private function log($txt)
|
||||
{
|
||||
if ($this->logger) {
|
||||
call_user_func($this->logger, $txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
94
app/lib/deploy/kuocai.php
Normal file
94
app/lib/deploy/kuocai.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\deploy;
|
||||
|
||||
use app\lib\DeployInterface;
|
||||
use Exception;
|
||||
|
||||
class kuocai implements DeployInterface
|
||||
{
|
||||
private $logger;
|
||||
private $username;
|
||||
private $password;
|
||||
private $proxy;
|
||||
private $token = null;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->username = $config['username'];
|
||||
$this->password = $config['password'];
|
||||
$this->proxy = $config['proxy'] == 1;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->username) || empty($this->password)) {
|
||||
throw new Exception('请填写控制台账号和密码');
|
||||
}
|
||||
$this->request('/login/loginUser', [
|
||||
'userAccount' => $this->username,
|
||||
'userPwd' => $this->password,
|
||||
'remember' => 'true'
|
||||
]);
|
||||
}
|
||||
|
||||
public function deploy($fullchain, $privatekey, $config, &$info)
|
||||
{
|
||||
$id = $config['id'];
|
||||
if (empty($id)) {
|
||||
throw new Exception('域名ID不能为空');
|
||||
}
|
||||
$this->token = $this->request('/login/loginUser', [
|
||||
'userAccount' => $this->username,
|
||||
'userPwd' => $this->password,
|
||||
'remember' => 'true'
|
||||
]);
|
||||
$this->request('/CdnDomainHttps/httpsConfiguration', [
|
||||
'doMainId' => $id,
|
||||
'https' => [
|
||||
'certificate_name' => uniqid('cert_'),
|
||||
'certificate_source' => '0',
|
||||
'certificate_value' => $fullchain,
|
||||
'https_status' => 'on',
|
||||
'private_key' => $privatekey,
|
||||
]
|
||||
], true);
|
||||
$this->log("域名ID:{$id}更新成功!");
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
}
|
||||
|
||||
private function log($txt)
|
||||
{
|
||||
if ($this->logger) {
|
||||
call_user_func($this->logger, $txt);
|
||||
}
|
||||
}
|
||||
|
||||
private function request($path, $params = null, $json = false)
|
||||
{
|
||||
$url = 'https://kuocai.cn' . $path;
|
||||
$body = $json ? json_encode($params) : $params;
|
||||
$headers = [];
|
||||
if ($json) $headers[] = 'Content-Type: application/json';
|
||||
$response = curl_client(
|
||||
$url,
|
||||
$body,
|
||||
null,
|
||||
$this->token ? "kuocai_cdn_token={$this->token}" : null,
|
||||
$headers,
|
||||
$this->proxy
|
||||
);
|
||||
$result = json_decode($response['body'], true);
|
||||
if (isset($result['code']) && $result['code'] == 'SUCCESS') {
|
||||
return isset($result['data']) ? $result['data'] : null;
|
||||
} elseif (isset($result['message'])) {
|
||||
throw new Exception($result['message']);
|
||||
} else {
|
||||
throw new Exception('请求失败(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
98
app/lib/deploy/proxmox.php
Normal file
98
app/lib/deploy/proxmox.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\deploy;
|
||||
|
||||
use app\lib\DeployInterface;
|
||||
use Exception;
|
||||
|
||||
class proxmox implements DeployInterface
|
||||
{
|
||||
private $logger;
|
||||
private $url;
|
||||
private $api_user;
|
||||
private $api_key;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->url = rtrim($config['url'], '/');
|
||||
$this->api_user = $config['api_user'];
|
||||
$this->api_key = $config['api_key'];
|
||||
$this->proxy = $config['proxy'] == 1;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->api_user) || empty($this->api_key)) throw new Exception('必填内容不能为空');
|
||||
|
||||
$path = '/api2/json/access';
|
||||
$this->send_request($path);
|
||||
}
|
||||
|
||||
public function deploy($fullchain, $privatekey, $config, &$info)
|
||||
{
|
||||
if (empty($config['node'])) throw new Exception('节点名称不能为空');
|
||||
$cert_hash = openssl_x509_fingerprint($fullchain, 'sha256');
|
||||
if (!$cert_hash) throw new Exception('证书解析失败');
|
||||
|
||||
$path = '/api2/json/nodes/' . $config['node'] . '/certificates/info';
|
||||
$list = $this->send_request($path);
|
||||
foreach ($list as $item) {
|
||||
$fingerprint = strtolower(str_replace(':', '', $item['fingerprint']));
|
||||
if ($fingerprint == $cert_hash) {
|
||||
$this->log('节点:' . $config['node'] . ' 证书已存在');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$path = '/api2/json/nodes/' . $config['node'] . '/certificates/custom';
|
||||
$params = [
|
||||
'certificates' => $fullchain,
|
||||
'key' => $privatekey,
|
||||
'force' => 1,
|
||||
'restart' => 1,
|
||||
];
|
||||
$this->send_request($path, $params);
|
||||
$this->log('节点:' . $config['node'] . ' 证书部署成功!');
|
||||
}
|
||||
|
||||
private function send_request($path, $params = null)
|
||||
{
|
||||
$url = $this->url . $path;
|
||||
$headers = ['Authorization: PVEAPIToken=' . $this->api_user . '=' . $this->api_key];
|
||||
$post = $params ? http_build_query($params) : null;
|
||||
$response = curl_client($url, $post, null, null, $headers, $this->proxy);
|
||||
if ($response['code'] == 200) {
|
||||
$result = json_decode($response['body'], true);
|
||||
if (isset($result['data'])) {
|
||||
return $result['data'];
|
||||
} elseif (isset($result['errors'])) {
|
||||
if (is_array($result['errors'])) {
|
||||
$result['errors'] = implode(';', $result['errors']);
|
||||
}
|
||||
throw new Exception($result['errors']);
|
||||
} else {
|
||||
throw new Exception('返回数据解析失败');
|
||||
}
|
||||
} else {
|
||||
$header = getSubstr($response['header'], ' ', "\r\n");
|
||||
if ($header) {
|
||||
throw new Exception($header);
|
||||
} else {
|
||||
throw new Exception('请求失败(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
}
|
||||
|
||||
private function log($txt)
|
||||
{
|
||||
if ($this->logger) {
|
||||
call_user_func($this->logger, $txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
156
app/lib/deploy/synology.php
Normal file
156
app/lib/deploy/synology.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\deploy;
|
||||
|
||||
use app\lib\DeployInterface;
|
||||
use Exception;
|
||||
|
||||
class synology implements DeployInterface
|
||||
{
|
||||
private $logger;
|
||||
private $url;
|
||||
private $username;
|
||||
private $password;
|
||||
private $version;
|
||||
private $token;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->url = rtrim($config['url'], '/');
|
||||
$this->username = $config['username'];
|
||||
$this->password = $config['password'];
|
||||
$this->version = $config['version'];
|
||||
$this->proxy = $config['proxy'] == 1;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->username) || empty($this->password)) throw new Exception('必填内容不能为空');
|
||||
$this->login();
|
||||
}
|
||||
|
||||
private function login()
|
||||
{
|
||||
$url = $this->url . '/webapi/' . ($this->version == '1' ? 'auth.cgi' : 'entry.cgi');
|
||||
$params = [
|
||||
'api' => 'SYNO.API.Auth',
|
||||
'version' => 6,
|
||||
'method' => 'login',
|
||||
'session' => 'webui',
|
||||
'account' => $this->username,
|
||||
'passwd' => $this->password,
|
||||
'format' => 'sid',
|
||||
'enable_syno_token' => 'yes',
|
||||
];
|
||||
$response = curl_client($url, http_build_query($params), null, null, null, $this->proxy);
|
||||
$result = json_decode($response['body'], true);
|
||||
if (isset($result['success']) && $result['success']) {
|
||||
$this->token = $result['data'];
|
||||
} elseif (isset($result['error'])) {
|
||||
throw new Exception('登录失败:' . $result['error']);
|
||||
} else {
|
||||
throw new Exception('请求失败(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
|
||||
public function deploy($fullchain, $privatekey, $config, &$info)
|
||||
{
|
||||
$this->login();
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
$certInfo['validFrom_time_t'];
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
|
||||
$url = $this->url . '/webapi/entry.cgi';
|
||||
$params = [
|
||||
'api' => 'SYNO.Core.Certificate.CRT',
|
||||
'version' => 1,
|
||||
'method' => 'list',
|
||||
'_sid' => $this->token['sid'],
|
||||
'SynoToken' => $this->token['synotoken'],
|
||||
];
|
||||
$response = curl_client($url . '?' . http_build_query($params), null, null, $this->proxy);
|
||||
$result = json_decode($response['body'], true);
|
||||
if (isset($result['success']) && $result['success']) {
|
||||
$this->log('获取证书列表成功');
|
||||
} elseif (isset($result['error'])) {
|
||||
throw new Exception('获取证书列表失败:' . json_encode($result['error']));
|
||||
} else {
|
||||
throw new Exception('获取证书列表失败(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
|
||||
$id = null;
|
||||
$validFrom = 0;
|
||||
foreach ($result['data']['certificates'] as $certificate) {
|
||||
if ($certificate['subject']['common_name'] == $certInfo['subject']['CN'] || $certificate['desc'] == $config['desc']) {
|
||||
$id = $certificate['id'];
|
||||
$validFrom = \DateTime::createFromFormat('M d H:i:s Y T', $certificate['valid_from'])->getTimestamp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($id) {
|
||||
if ($validFrom == $certInfo['validFrom_time_t']) {
|
||||
$this->log('证书ID:' . $id . '已存在,无需更新');
|
||||
return;
|
||||
}
|
||||
$this->import($fullchain, $privatekey, $config, $id);
|
||||
} else {
|
||||
$this->import($fullchain, $privatekey, $config);
|
||||
}
|
||||
}
|
||||
|
||||
private function import($fullchain, $privatekey, $config, $id = null)
|
||||
{
|
||||
$url = $this->url . '/webapi/entry.cgi';
|
||||
$params = [
|
||||
'api' => 'SYNO.Core.Certificate',
|
||||
'version' => 1,
|
||||
'method' => 'import',
|
||||
'_sid' => $this->token['sid'],
|
||||
'SynoToken' => $this->token['synotoken'],
|
||||
];
|
||||
$privatekey_file = tempnam(sys_get_temp_dir(), 'privatekey');
|
||||
file_put_contents($privatekey_file, $privatekey);
|
||||
$fullchain_file = tempnam(sys_get_temp_dir(), 'fullchain');
|
||||
file_put_contents($fullchain_file, $fullchain);
|
||||
$post = [
|
||||
'key' => new \CURLFile($privatekey_file),
|
||||
'cert' => new \CURLFile($fullchain_file),
|
||||
'id' => $id,
|
||||
'desc' => $config['desc'],
|
||||
];
|
||||
$response = curl_client($url . '?' . http_build_query($params), $post, null, null, null, $this->proxy, null, 15);
|
||||
unlink($privatekey_file);
|
||||
unlink($fullchain_file);
|
||||
$result = json_decode($response['body'], true);
|
||||
if ($id) {
|
||||
if (isset($result['success']) && $result['success']) {
|
||||
$this->log('证书ID:' . $id . '更新成功!');
|
||||
} elseif (isset($result['error'])) {
|
||||
throw new Exception('证书ID:' . $id . '更新失败:' . json_encode($result['error']));
|
||||
} else {
|
||||
throw new Exception('证书ID:' . $id . '更新失败(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
} else {
|
||||
if (isset($result['success']) && $result['success']) {
|
||||
$this->log('证书上传成功!');
|
||||
} elseif (isset($result['error'])) {
|
||||
throw new Exception('证书上传失败:' . json_encode($result['error']));
|
||||
} else {
|
||||
throw new Exception('证书上传失败(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
}
|
||||
|
||||
private function log($txt)
|
||||
{
|
||||
if ($this->logger) {
|
||||
call_user_func($this->logger, $txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,22 +79,22 @@ class namesilo implements DnsInterface
|
||||
'UpdateTime' => null,
|
||||
];
|
||||
}
|
||||
if(!empty($SubDomain)){
|
||||
if(!isNullOrEmpty($SubDomain)){
|
||||
$list = array_values(array_filter($list, function($v) use ($SubDomain){
|
||||
return $v['Name'] == $SubDomain;
|
||||
}));
|
||||
}else{
|
||||
if(!empty($KeyWord)){
|
||||
if(!isNullOrEmpty($KeyWord)){
|
||||
$list = array_values(array_filter($list, function($v) use ($KeyWord){
|
||||
return strpos($v['Name'], $KeyWord) !== false || strpos($v['Value'], $KeyWord) !== false;
|
||||
}));
|
||||
}
|
||||
if(!empty($Value)){
|
||||
if(!isNullOrEmpty($Value)){
|
||||
$list = array_values(array_filter($list, function($v) use ($Value){
|
||||
return $v['Value'] == $Value;
|
||||
}));
|
||||
}
|
||||
if(!empty($Type)){
|
||||
if(!isNullOrEmpty($Type)){
|
||||
$list = array_values(array_filter($list, function($v) use ($Type){
|
||||
return $v['Type'] == $Type;
|
||||
}));
|
||||
@@ -118,7 +118,7 @@ class namesilo implements DnsInterface
|
||||
}
|
||||
|
||||
//添加解析记录
|
||||
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
|
||||
public function addDomainRecord($Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
|
||||
{
|
||||
$param = ['domain' => $this->domain, 'rrtype' => $Type, 'rrhost' => $Name, 'rrvalue' => $Value, 'rrttl' => $TTL];
|
||||
if ($Type == 'MX') $param['rrdistance'] = intval($MX);
|
||||
@@ -127,7 +127,7 @@ class namesilo implements DnsInterface
|
||||
}
|
||||
|
||||
//修改解析记录
|
||||
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
|
||||
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
|
||||
{
|
||||
$param = ['domain' => $this->domain, 'rrid' => $RecordId, 'rrtype' => $Type, 'rrhost' => $Name, 'rrvalue' => $Value, 'rrttl' => $TTL];
|
||||
if ($Type == 'MX') $param['rrdistance'] = intval($MX);
|
||||
|
||||
409
app/lib/dns/powerdns.php
Normal file
409
app/lib/dns/powerdns.php
Normal file
@@ -0,0 +1,409 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\dns;
|
||||
|
||||
use app\lib\DnsInterface;
|
||||
use Exception;
|
||||
|
||||
class powerdns implements DnsInterface
|
||||
{
|
||||
private $url;
|
||||
private $apikey;
|
||||
private $server_id = 'localhost';
|
||||
private $error;
|
||||
private $domain;
|
||||
private $domainid;
|
||||
private $proxy;
|
||||
|
||||
function __construct($config)
|
||||
{
|
||||
$this->url = 'http://' . $config['ak'] . ':' . $config['sk'] . '/api/v1';
|
||||
$this->apikey = $config['ext'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->domain = $config['domain'];
|
||||
$this->domainid = $config['domainid'];
|
||||
}
|
||||
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if ($this->getDomainList() !== false) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取域名列表
|
||||
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20)
|
||||
{
|
||||
$data = $this->send_reuqest('GET', '/servers/' . $this->server_id . '/zones');
|
||||
if ($data) {
|
||||
$list = [];
|
||||
foreach ($data as $row) {
|
||||
$list[] = [
|
||||
'DomainId' => $row['id'],
|
||||
'Domain' => rtrim($row['name'], '.'),
|
||||
'RecordCount' => 0,
|
||||
];
|
||||
}
|
||||
return ['total' => count($list), 'list' => $list];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取解析记录列表
|
||||
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null)
|
||||
{
|
||||
$data = $this->send_reuqest('GET', '/servers/' . $this->server_id . '/zones/' . $this->domainid);
|
||||
if ($data) {
|
||||
$list = [];
|
||||
$rrset_id = 0;
|
||||
foreach ($data['rrsets'] as &$row) {
|
||||
$rrset_id++;
|
||||
$name = $row['name'] == $this->domainid ? '@' : str_replace('.' . $this->domainid, '', $row['name']);
|
||||
$row['host'] = $name;
|
||||
$row['id'] = $rrset_id;
|
||||
$record_id = 0;
|
||||
foreach ($row['records'] as &$record) {
|
||||
$record_id++;
|
||||
$record['id'] = $record_id;
|
||||
$remark = !empty($row['comments']) ? $row['comments'][0]['content'] : null;
|
||||
$value = $record['content'];
|
||||
if ($row['type'] == 'MX') list($record['mx'], $value) = explode(' ', $record['content']);
|
||||
$list[] = [
|
||||
'RecordId' => $rrset_id . '_' . $record_id,
|
||||
'Domain' => $this->domain,
|
||||
'Name' => $name,
|
||||
'Type' => $row['type'],
|
||||
'Value' => $value,
|
||||
'Line' => 'default',
|
||||
'TTL' => $row['ttl'],
|
||||
'MX' => isset($record['mx']) ? $record['mx'] : null,
|
||||
'Status' => $record['disabled'] ? '0' : '1',
|
||||
'Weight' => null,
|
||||
'Remark' => $remark,
|
||||
'UpdateTime' => null,
|
||||
];
|
||||
}
|
||||
}
|
||||
cache('powerdns_' . $this->domainid, $data['rrsets'], 86400);
|
||||
if (!isNullOrEmpty($SubDomain)) {
|
||||
$list = array_values(array_filter($list, function ($v) use ($SubDomain) {
|
||||
return $v['Name'] == $SubDomain;
|
||||
}));
|
||||
} else {
|
||||
if (!isNullOrEmpty($KeyWord)) {
|
||||
$list = array_values(array_filter($list, function ($v) use ($KeyWord) {
|
||||
return strpos($v['Name'], $KeyWord) !== false || strpos($v['Value'], $KeyWord) !== false;
|
||||
}));
|
||||
}
|
||||
if (!isNullOrEmpty($Value)) {
|
||||
$list = array_values(array_filter($list, function ($v) use ($Value) {
|
||||
return $v['Value'] == $Value;
|
||||
}));
|
||||
}
|
||||
if (!isNullOrEmpty($Type)) {
|
||||
$list = array_values(array_filter($list, function ($v) use ($Type) {
|
||||
return $v['Type'] == $Type;
|
||||
}));
|
||||
}
|
||||
if (!isNullOrEmpty($Status)) {
|
||||
$list = array_values(array_filter($list, function ($v) use ($Status) {
|
||||
return $v['Status'] == $Status;
|
||||
}));
|
||||
}
|
||||
}
|
||||
return ['total' => count($list), 'list' => $list];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取子域名解析记录列表
|
||||
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null)
|
||||
{
|
||||
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
|
||||
}
|
||||
|
||||
//获取解析记录详细信息
|
||||
public function getDomainRecordInfo($RecordId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//添加解析记录
|
||||
public function addDomainRecord($Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
|
||||
{
|
||||
if ($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"' . $Value . '"';
|
||||
if ($Type == 'CNAME' && substr($Value, -1) != '.') $Value .= '.';
|
||||
if ($Type == 'MX') $Value = intval($MX) . ' ' . $Value;
|
||||
$records = [];
|
||||
$rrsets = cache('powerdns_' . $this->domainid);
|
||||
if ($rrsets) {
|
||||
$rrsets_filter = array_filter($rrsets, function ($row) use ($Name, $Type) {
|
||||
return $row['host'] == $Name && $row['type'] == $Type;
|
||||
});
|
||||
if (!empty($rrsets_filter)) {
|
||||
$rrset = $rrsets_filter[array_key_first($rrsets_filter)];
|
||||
$records = $rrset['records'];
|
||||
$records_filter = array_filter($records, function ($record) use ($Value) {
|
||||
return $record['content'] == $Value;
|
||||
});
|
||||
if (!empty($records_filter)) {
|
||||
$this->setError('已存在相同记录');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
$records[] = ['content' => $Value, 'disabled' => false];
|
||||
return $this->rrset_replace($Name, $Type, $TTL, $records, $Remark);
|
||||
}
|
||||
|
||||
//修改解析记录
|
||||
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
|
||||
{
|
||||
if ($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"' . $Value . '"';
|
||||
if ($Type == 'CNAME' && substr($Value, -1) != '.') $Value .= '.';
|
||||
if ($Type == 'MX') $Value = intval($MX) . ' ' . $Value;
|
||||
$rrsets = cache('powerdns_' . $this->domainid);
|
||||
$add = false;
|
||||
$res = false;
|
||||
if ($rrsets) {
|
||||
[$rrset_id, $record_id] = explode('_', $RecordId);
|
||||
$exist = false;
|
||||
foreach ($rrsets as &$rrset) {
|
||||
if ($rrset['id'] == $rrset_id) {
|
||||
$records = $rrset['records'];
|
||||
$records_filter = array_filter($records, function ($record) use ($Value, $record_id) {
|
||||
return $record['content'] == $Value && $record['id'] != $record_id;
|
||||
});
|
||||
if (!empty($records_filter)) {
|
||||
$this->setError('已存在相同记录');
|
||||
return false;
|
||||
}
|
||||
foreach ($records as $i => &$record) {
|
||||
if ($record['id'] == $record_id) {
|
||||
$exist = true;
|
||||
if ($rrset['host'] == $Name && $rrset['type'] == $Type) {
|
||||
$record['content'] = $Value;
|
||||
} else {
|
||||
unset($records[$i]);
|
||||
$add = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$exist) break;
|
||||
$records = array_values($records);
|
||||
if (!empty($records)) {
|
||||
$res = $this->rrset_replace($rrset['host'], $rrset['type'], $TTL, $records, $Remark);
|
||||
} else {
|
||||
$res = $this->rrset_delete($rrset['host'], $rrset['type']);
|
||||
}
|
||||
$rrset['records'] = $records;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$exist) {
|
||||
$this->setError('记录不存在,请刷新页面重试');
|
||||
return false;
|
||||
}
|
||||
cache('powerdns_' . $this->domainid, $rrsets, 86400);
|
||||
if ($res && $add) {
|
||||
$res = $this->addDomainRecord($Name, $Type, $Value, $Line, $TTL, $MX, $Weight, $Remark);
|
||||
}
|
||||
return $res;
|
||||
} else {
|
||||
$records[] = ['content' => $Value, 'disabled' => false];
|
||||
return $this->addDomainRecord($Name, $Type, $Value, $Line, $TTL, $MX, $Weight, $Remark);
|
||||
}
|
||||
}
|
||||
|
||||
//修改解析记录备注
|
||||
public function updateDomainRecordRemark($RecordId, $Remark)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//删除解析记录
|
||||
public function deleteDomainRecord($RecordId)
|
||||
{
|
||||
$rrsets = cache('powerdns_' . $this->domainid);
|
||||
if (!$rrsets) {
|
||||
$this->setError('记录不存在,请刷新页面重试');
|
||||
return false;
|
||||
}
|
||||
[$rrset_id, $record_id] = explode('_', $RecordId);
|
||||
$exist = false;
|
||||
$res = false;
|
||||
foreach ($rrsets as &$rrset) {
|
||||
if ($rrset['id'] == $rrset_id) {
|
||||
$records = $rrset['records'];
|
||||
foreach ($records as $i => &$record) {
|
||||
if ($record['id'] == $record_id) {
|
||||
$exist = true;
|
||||
unset($records[$i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$exist) break;
|
||||
$records = array_values($records);
|
||||
if (!empty($records)) {
|
||||
$res = $this->rrset_replace($rrset['host'], $rrset['type'], $rrset['ttl'], $records);
|
||||
} else {
|
||||
$res = $this->rrset_delete($rrset['host'], $rrset['type']);
|
||||
}
|
||||
$rrset['records'] = $records;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$exist) {
|
||||
$this->setError('记录不存在,请刷新页面重试');
|
||||
return false;
|
||||
}
|
||||
cache('powerdns_' . $this->domainid, $rrsets, 86400);
|
||||
return $res;
|
||||
}
|
||||
|
||||
//设置解析记录状态
|
||||
public function setDomainRecordStatus($RecordId, $Status)
|
||||
{
|
||||
$rrsets = cache('powerdns_' . $this->domainid);
|
||||
if (!$rrsets) {
|
||||
$this->setError('记录不存在,请刷新页面重试');
|
||||
return false;
|
||||
}
|
||||
[$rrset_id, $record_id] = explode('_', $RecordId);
|
||||
$exist = false;
|
||||
$res = false;
|
||||
foreach ($rrsets as &$rrset) {
|
||||
if ($rrset['id'] == $rrset_id) {
|
||||
$records = $rrset['records'];
|
||||
foreach ($records as &$record) {
|
||||
if ($record['id'] == $record_id) {
|
||||
$exist = true;
|
||||
$record['disabled'] = $Status == '0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$exist) break;
|
||||
$res = $this->rrset_replace($rrset['host'], $rrset['type'], $rrset['ttl'], $records);
|
||||
$rrset['records'] = $records;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$exist) {
|
||||
$this->setError('记录不存在,请刷新页面重试');
|
||||
return false;
|
||||
}
|
||||
cache('powerdns_' . $this->domainid, $rrsets, 86400);
|
||||
return $res;
|
||||
}
|
||||
|
||||
//获取解析记录操作日志
|
||||
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取解析线路列表
|
||||
public function getRecordLine()
|
||||
{
|
||||
return ['default' => ['name' => '默认', 'parent' => null]];
|
||||
}
|
||||
|
||||
//获取域名信息
|
||||
public function getDomainInfo()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取域名最低TTL
|
||||
public function getMinTTL()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private function rrset_replace($host, $type, $ttl, $records, $remark = null)
|
||||
{
|
||||
$name = $host == '@' ? $this->domainid : $host . '.' . $this->domainid;
|
||||
$rrset = [
|
||||
'name' => $name,
|
||||
'type' => $type,
|
||||
'ttl' => intval($ttl),
|
||||
'changetype' => 'REPLACE',
|
||||
'records' => $records,
|
||||
'comments' => [],
|
||||
];
|
||||
if (!empty($remark)) {
|
||||
$rrset['comments'] = [
|
||||
['account' => '', 'content' => $remark]
|
||||
];
|
||||
}
|
||||
$param = [
|
||||
'rrsets' => [
|
||||
$rrset
|
||||
],
|
||||
];
|
||||
return $this->send_reuqest('PATCH', '/servers/' . $this->server_id . '/zones/' . $this->domainid, $param);
|
||||
}
|
||||
|
||||
private function rrset_delete($host, $type)
|
||||
{
|
||||
$name = $host == '@' ? $this->domainid : $host . '.' . $this->domainid;
|
||||
$param = [
|
||||
'rrsets' => [
|
||||
[
|
||||
'name' => $name,
|
||||
'type' => $type,
|
||||
'changetype' => 'DELETE',
|
||||
]
|
||||
],
|
||||
];
|
||||
return $this->send_reuqest('PATCH', '/servers/' . $this->server_id . '/zones/' . $this->domainid, $param);
|
||||
}
|
||||
|
||||
private function send_reuqest($method, $path, $params = null)
|
||||
{
|
||||
$url = $this->url . $path;
|
||||
$headers[] = 'X-API-Key: ' . $this->apikey;
|
||||
$body = null;
|
||||
if ($method == 'GET' || $method == 'DELETE') {
|
||||
if ($params) {
|
||||
$url .= '?' . http_build_query($params);
|
||||
}
|
||||
} else {
|
||||
$body = json_encode($params);
|
||||
$headers[] = 'Content-Type: application/json';
|
||||
}
|
||||
try {
|
||||
$response = curl_client($url, $body, null, null, $headers, $this->proxy, $method);
|
||||
} catch (Exception $e) {
|
||||
$this->setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
$arr = json_decode($response['body'], true);
|
||||
if ($response['code'] < 400) {
|
||||
return is_array($arr) ? $arr : true;
|
||||
} elseif (isset($arr['error'])) {
|
||||
$this->setError($arr['error']);
|
||||
return false;
|
||||
} elseif (isset($arr['errors'])) {
|
||||
$this->setError(implode(',', $arr['errors']));
|
||||
return false;
|
||||
} else {
|
||||
$this->setError($response['body']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function setError($message)
|
||||
{
|
||||
$this->error = $message;
|
||||
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ class CertDeployService
|
||||
//重置任务
|
||||
public function reset()
|
||||
{
|
||||
Db::name('cert_deploy')->where('id', $this->task['id'])->data(['status' => 0, 'retry' => 0, 'retrytime' => null, 'issend' => 0])->update();
|
||||
Db::name('cert_deploy')->where('id', $this->task['id'])->data(['status' => 0, 'retry' => 0, 'retrytime' => null, 'issend' => 0, 'islock' => 0])->update();
|
||||
//$file_name = app()->getRuntimePath().'log/'.$this->task['processid'].'.log';
|
||||
//if (file_exists($file_name)) unlink($file_name);
|
||||
$this->task['status'] = 0;
|
||||
|
||||
@@ -68,7 +68,11 @@ class CertOrderService
|
||||
$cname = CertHelper::$cert_config[$this->atype]['cname'];
|
||||
foreach($this->domainList as $domain){
|
||||
$mainDomain = getMainDomain($domain);
|
||||
if (!Db::name('domain')->where('name', $mainDomain)->find()) {
|
||||
$drow = Db::name('domain')->where('name', $mainDomain)->find();
|
||||
if (!$drow && preg_match('/^xn--/', $mainDomain)) {
|
||||
$drow = Db::name('domain')->where('name', idn_to_utf8($mainDomain))->find();
|
||||
}
|
||||
if (!$drow) {
|
||||
if (substr($domain, 0, 2) == '*.') $domain = substr($domain, 2);
|
||||
$cname_row = Db::name('cert_cname')->where('domain', $domain)->where('status', 1)->find();
|
||||
if (!$cname || !$cname_row) {
|
||||
@@ -205,7 +209,7 @@ class CertOrderService
|
||||
//重置订单
|
||||
public function reset()
|
||||
{
|
||||
Db::name('cert_order')->where('id', $this->order['id'])->data(['status' => 0, 'retry' => 0, 'retry2' => 0, 'retrytime' => null, 'processid' => null, 'updatetime' => date('Y-m-d H:i:s'), 'issend' => 0])->update();
|
||||
Db::name('cert_order')->where('id', $this->order['id'])->data(['status' => 0, 'retry' => 0, 'retry2' => 0, 'retrytime' => null, 'processid' => null, 'updatetime' => date('Y-m-d H:i:s'), 'issend' => 0, 'islock' => 0])->update();
|
||||
$file_name = app()->getRuntimePath().'log/'.$this->order['processid'].'.log';
|
||||
if (file_exists($file_name)) unlink($file_name);
|
||||
$this->order['status'] = 0;
|
||||
|
||||
@@ -146,17 +146,19 @@ class OptimizeService
|
||||
if (empty($iplist)) {
|
||||
continue;
|
||||
}
|
||||
$record_num = $row['recordnum'];
|
||||
$get_ips = array_column($iplist, 'ip');
|
||||
if ($drow['type'] == 'huawei') {
|
||||
sort($get_ips);
|
||||
$get_ips = array_slice($get_ips, 0, $row['recordnum']);
|
||||
$get_ips = [implode(',', $get_ips)];
|
||||
$row['recordnum'] = 1;
|
||||
$record_num = 1;
|
||||
}
|
||||
if ($row['type'] == 1 && $line == 'CT') {
|
||||
$line = 'DEF';
|
||||
}
|
||||
$line_name = DnsHelper::$line_name[$drow['type']][$line];
|
||||
$this->process_dns_line($dns, $row, $domainRecords['list'], $get_ips, $line_name, $ip_type);
|
||||
$this->process_dns_line($dns, $row, $domainRecords['list'], $record_num, $get_ips, $line_name, $ip_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,9 +166,8 @@ class OptimizeService
|
||||
}
|
||||
|
||||
//处理单个线路的解析记录
|
||||
private function process_dns_line($dns, $row, $record_list, $get_ips, $line_name, $ip_type)
|
||||
private function process_dns_line($dns, $row, $record_list, $record_num, $get_ips, $line_name, $ip_type)
|
||||
{
|
||||
$record_num = $row['recordnum'];
|
||||
$records = array_filter($record_list, function ($v) use ($line_name) {
|
||||
return $v['Line'] == $line_name;
|
||||
});
|
||||
|
||||
@@ -83,6 +83,9 @@ class TaskRunner
|
||||
if ($row['type'] == 2) {
|
||||
$dns = DnsHelper::getModel2($drow);
|
||||
$recordinfo = json_decode($row['recordinfo'], true);
|
||||
if ($drow['type'] == 'cloudflare' && $row['cdn'] == 1) {
|
||||
$recordinfo['Line'] = '1';
|
||||
}
|
||||
$res = $dns->updateDomainRecord($row['recordid'], $row['rr'], getDnsType($row['backup_value']), $row['backup_value'], $recordinfo['Line'], $recordinfo['TTL']);
|
||||
if (!$res) {
|
||||
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '修改解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
|
||||
@@ -98,6 +101,9 @@ class TaskRunner
|
||||
if ($row['type'] == 2) {
|
||||
$dns = DnsHelper::getModel2($drow);
|
||||
$recordinfo = json_decode($row['recordinfo'], true);
|
||||
if ($drow['type'] == 'cloudflare' && $row['cdn'] == 1) {
|
||||
$recordinfo['Line'] = '0';
|
||||
}
|
||||
$res = $dns->updateDomainRecord($row['recordid'], $row['rr'], getDnsType($row['main_value']), $row['main_value'], $recordinfo['Line'], $recordinfo['TTL']);
|
||||
if (!$res) {
|
||||
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '修改解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
|
||||
|
||||
@@ -5,7 +5,7 @@ CREATE TABLE `dnsmgr_config` (
|
||||
PRIMARY KEY (`key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO `dnsmgr_config` VALUES ('version', '1021');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('version', '1028');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('notice_mail', '0');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('notice_wxtpl', '0');
|
||||
INSERT INTO `dnsmgr_config` VALUES ('mail_smtp', 'smtp.qq.com');
|
||||
@@ -96,6 +96,7 @@ CREATE TABLE `dnsmgr_dmtask` (
|
||||
`timeout` tinyint(5) NOT NULL DEFAULT 2,
|
||||
`remark` varchar(100) DEFAULT NULL,
|
||||
`proxy` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`cdn` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`addtime` int(11) NOT NULL DEFAULT 0,
|
||||
`checktime` int(11) NOT NULL DEFAULT 0,
|
||||
`checknexttime` int(11) NOT NULL DEFAULT 0,
|
||||
|
||||
@@ -152,4 +152,7 @@ CREATE TABLE IF NOT EXISTS `dnsmgr_cert_cname` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE `dnsmgr_account`
|
||||
ADD COLUMN `proxy` tinyint(1) NOT NULL DEFAULT '0';
|
||||
ADD COLUMN `proxy` tinyint(1) NOT NULL DEFAULT '0';
|
||||
|
||||
ALTER TABLE `dnsmgr_dmtask`
|
||||
ADD COLUMN `cdn` tinyint(1) NOT NULL DEFAULT 0;
|
||||
@@ -13,6 +13,9 @@ class CertDnsUtils
|
||||
$cnameDomainList = [];
|
||||
foreach ($dnsList as $mainDomain => $list) {
|
||||
$drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.name', $mainDomain)->field('A.*,B.type')->find();
|
||||
if (!$drow && preg_match('/^xn--/', $mainDomain)) {
|
||||
$drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.name', idn_to_utf8($mainDomain))->field('A.*,B.type')->find();
|
||||
}
|
||||
if (!$drow) {
|
||||
if ($cname) {
|
||||
foreach ($list as $key => $row) {
|
||||
@@ -102,6 +105,9 @@ class CertDnsUtils
|
||||
$cnameDomainList = [];
|
||||
foreach ($dnsList as $mainDomain => $list) {
|
||||
$drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.name', $mainDomain)->field('A.*,B.type')->find();
|
||||
if (!$drow && preg_match('/^xn--/', $mainDomain)) {
|
||||
$drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.name', idn_to_utf8($mainDomain))->field('A.*,B.type')->find();
|
||||
}
|
||||
if (!$drow) {
|
||||
if ($cname) {
|
||||
foreach ($list as $key => $row) {
|
||||
|
||||
@@ -197,7 +197,14 @@ class MsgNotice
|
||||
$tgbot_token = config_get('tgbot_token');
|
||||
$tgbot_chatid = config_get('tgbot_chatid');
|
||||
if (!$tgbot_token || !$tgbot_chatid) return false;
|
||||
$url = 'https://api.telegram.org/bot'.$tgbot_token.'/sendMessage';
|
||||
$tgbot_url = 'https://api.telegram.org';
|
||||
if (config_get('tgbot_proxy') == 2) {
|
||||
$tgbot_url_n = config_get('tgbot_url');
|
||||
if (!empty($tgbot_url_n)) {
|
||||
$tgbot_url = rtrim($tgbot_url_n, '/');
|
||||
}
|
||||
}
|
||||
$url = $tgbot_url.'/bot'.$tgbot_token.'/sendMessage';
|
||||
$post = ['chat_id' => $tgbot_chatid, 'text' => $content, 'parse_mode' => 'HTML'];
|
||||
$result = self::telegram_curl($url, http_build_query($post));
|
||||
$arr = json_decode($result, true);
|
||||
|
||||
@@ -27,6 +27,9 @@ pre.pre-log{height: 330px;overflow-y: auto;width: 100%;background-color: rgba(51
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/foreach}</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="status" class="form-control"><option value="">所有状态</option><option value="0">待提交</option><option value="1">待验证</option><option value="2">正在验证</option><option value="5">失败</option><option value="3">已签发</option><option value="4">已吊销</option><option value="6">即将过期</option><option value="7">已过期</option></select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa fa-search"></i> 搜索</button>
|
||||
<a href="javascript:searchClear()" class="btn btn-default" title="刷新订单列表"><i class="fa fa-refresh"></i> 刷新</a>
|
||||
<div class="btn-group">
|
||||
@@ -137,6 +140,16 @@ $(document).ready(function(){
|
||||
} else if(value == 3) {
|
||||
return '<span class="label label-success">已签发</span>';
|
||||
} else if(value == 2) {
|
||||
if(row.retrytime != null){
|
||||
var now = new Date().getTime();
|
||||
var retry = new Date(row.retrytime).getTime();
|
||||
var diff = retry - now;
|
||||
if(diff > 0){
|
||||
var min = Math.floor(diff / 60000);
|
||||
var sec = Math.floor((diff - min * 60000) / 1000);
|
||||
return '<span title="'+min+'分'+sec+'秒后自动验证" data-toggle="tooltip" data-placement="top" class="label" style="background-color: #3e76fb;">正在验证</span>';
|
||||
}
|
||||
}
|
||||
return '<span class="label" style="background-color: #3e76fb;">正在验证</span>';
|
||||
} else if(value == 1) {
|
||||
if(row.retrytime != null){
|
||||
|
||||
@@ -29,6 +29,9 @@ pre.pre-log{height: 330px;overflow-y: auto;width: 100%;background-color: rgba(51
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/foreach}</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="status" class="form-control"><option value="">所有状态</option><option value="0">待处理</option><option value="1">已完成</option><option value="-1">处理失败</option></select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa fa-search"></i> 搜索</button>
|
||||
<a href="javascript:searchClear()" class="btn btn-default" title="刷新任务列表"><i class="fa fa-refresh"></i> 刷新</a>
|
||||
<a href="/cert/deploy/add" class="btn btn-success"><i class="fa fa-plus"></i> 添加</a>
|
||||
|
||||
@@ -119,8 +119,8 @@
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li><a href="/dmonitor/overview"><i class="fa fa-circle-o"></i> 运行概览</a></li>
|
||||
<li><a href="/dmonitor/task"><i class="fa fa-circle-o"></i> 切换策略</a></li>
|
||||
<li class="{:checkIfActive('overview')}"><a href="/dmonitor/overview"><i class="fa fa-circle-o"></i> 运行概览</a></li>
|
||||
<li class="{:checkIfActive('task,taskform')}"><a href="/dmonitor/task"><i class="fa fa-circle-o"></i> 切换策略</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="treeview {:checkIfActive('opipset,opiplist,opipform')}">
|
||||
@@ -132,8 +132,8 @@
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li><a href="/optimizeip/opipset"><i class="fa fa-circle-o"></i> 优选设置</a></li>
|
||||
<li><a href="/optimizeip/opiplist"><i class="fa fa-circle-o"></i> 任务管理</a></li>
|
||||
<li class="{:checkIfActive('opipset')}"><a href="/optimizeip/opipset"><i class="fa fa-circle-o"></i> 优选设置</a></li>
|
||||
<li class="{:checkIfActive('opiplist,opipform')}"><a href="/optimizeip/opiplist"><i class="fa fa-circle-o"></i> 任务管理</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="treeview {:checkIfActive('certaccount,account_form,certorder,order_form,order_import,deployaccount,deploytask,deploy_form,certset,cname')}">
|
||||
@@ -145,12 +145,12 @@
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li><a href="/cert/certaccount"><i class="fa fa-circle-o"></i> SSL证书账户</a></li>
|
||||
<li><a href="/cert/certorder"><i class="fa fa-circle-o"></i> SSL证书订单</a></li>
|
||||
<li><a href="/cert/deployaccount"><i class="fa fa-circle-o"></i> 自动部署账户</a></li>
|
||||
<li><a href="/cert/deploytask"><i class="fa fa-circle-o"></i> 自动部署任务</a></li>
|
||||
<li><a href="/cert/cname"><i class="fa fa-circle-o"></i> CNAME代理</a></li>
|
||||
<li><a href="/cert/certset"><i class="fa fa-circle-o"></i> 计划任务设置</a></li>
|
||||
<li class="{:checkIfActive('certaccount')}"><a href="/cert/certaccount"><i class="fa fa-circle-o"></i> SSL证书账户</a></li>
|
||||
<li class="{:checkIfActive('certorder,order_form,order_import')}"><a href="/cert/certorder"><i class="fa fa-circle-o"></i> SSL证书订单</a></li>
|
||||
<li class="{:checkIfActive('deployaccount')}"><a href="/cert/deployaccount"><i class="fa fa-circle-o"></i> 自动部署账户</a></li>
|
||||
<li class="{:checkIfActive('deploytask,deploy_form')}"><a href="/cert/deploytask"><i class="fa fa-circle-o"></i> 自动部署任务</a></li>
|
||||
<li class="{:checkIfActive('cname')}"><a href="/cert/cname"><i class="fa fa-circle-o"></i> CNAME代理</a></li>
|
||||
<li class="{:checkIfActive('certset')}"><a href="/cert/certset"><i class="fa fa-circle-o"></i> 计划任务设置</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="treeview {:checkIfActive('noticeset,proxyset')}">
|
||||
@@ -162,8 +162,8 @@
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li><a href="/system/noticeset"><i class="fa fa-circle-o"></i> 通知设置</a></li>
|
||||
<li><a href="/system/proxyset"><i class="fa fa-circle-o"></i> 代理设置</a></li>
|
||||
<li class="{:checkIfActive('noticeset')}"><a href="/system/noticeset"><i class="fa fa-circle-o"></i> 通知设置</a></li>
|
||||
<li class="{:checkIfActive('proxyset')}"><a href="/system/proxyset"><i class="fa fa-circle-o"></i> 代理设置</a></li>
|
||||
<li><a href="https://www.showdoc.com.cn/dnsmgr/11058996709621562" target="_blank" rel="noreferrer"><i class="fa fa-circle-o"></i> <span>接口文档</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -20,9 +20,7 @@
|
||||
<div class="col-sm-3 col-xs-5"><input type="text" name="rr" v-model="set.rr" placeholder="主机记录" class="form-control" required></div>
|
||||
<div class="col-sm-3 col-xs-7 dselect"><select name="did" v-model="set.did" class="form-control" required>
|
||||
<option value="">--主域名--</option>
|
||||
{foreach $domains as $k=>$v}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/foreach}
|
||||
<option v-for="option in domainList" :value="option.id">{{option.name}}</option>
|
||||
</select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -50,6 +48,15 @@
|
||||
<input type="text" name="backup_value" v-model="set.backup_value" placeholder="支持填写IPv4或CNAME地址" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" v-show="set.type==2&&dnstype=='cloudflare'">
|
||||
<div class="col-sm-offset-3 col-sm-7">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="name" v-model="set.cdn"> 切换时同时开启Cloudflare代理模式
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" v-show="set.type<=2">
|
||||
<label class="col-sm-3 control-label no-padding-right">检测协议</label>
|
||||
<div class="col-sm-6">
|
||||
@@ -131,6 +138,7 @@
|
||||
<script>
|
||||
var action = '{$action}';
|
||||
var info = {$info|json_encode|raw};
|
||||
var domainList = {$domains|json_encode|raw};
|
||||
var support_ping = '{$support_ping}';
|
||||
new Vue({
|
||||
el: '#app',
|
||||
@@ -153,7 +161,10 @@ new Vue({
|
||||
timeout: 2,
|
||||
cycle: 3,
|
||||
proxy: 0,
|
||||
cdn: 0,
|
||||
},
|
||||
dnstype: null,
|
||||
domainList: domainList,
|
||||
recordList: [],
|
||||
typeList: [
|
||||
{value:0, label:'无操作'},
|
||||
@@ -176,6 +187,10 @@ new Vue({
|
||||
if(typeof record.Value == 'object') this.set.main_value = record.Value[0];
|
||||
else this.set.main_value = record.Value;
|
||||
}
|
||||
},
|
||||
'set.did': function(val){
|
||||
if(val == '') return;
|
||||
this.dnstype = this.domainList.find(item => item.id == val).type;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<div class="form-group" id="ext_name_div" style="display:none;">
|
||||
<label class="col-sm-3 control-label no-padding-right" id="ext_name">扩展字段</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" name="ext" placeholder="没有请勿填写">
|
||||
<input type="text" class="form-control" name="ext" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
<label class="col-sm-3 control-label">选择域名</label>
|
||||
<div class="col-sm-9">
|
||||
<select name="domain" id="domainList" class="form-control"></select>
|
||||
<span class="pull-right"><a href="/domain/add">批量添加</a></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -107,7 +106,11 @@
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa fa-search"></i> 搜索</button>
|
||||
<a href="javascript:searchClear()" class="btn btn-default" title="刷新域名列表"><i class="fa fa-refresh"></i> 刷新</a>
|
||||
{if request()->user['level'] eq 2}<a href="javascript:addframe()" class="btn btn-success"><i class="fa fa-plus"></i> 添加</a>{/if}
|
||||
{if request()->user['level'] eq 2}<a href="javascript:addframe()" class="btn btn-success"><i class="fa fa-plus"></i> 添加</a>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">批量操作 <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu"><li><a href="/domain/add">添加</a></li><li><a href="javascript:operation('editremark')">修改备注</a></li><li><a href="javascript:operation('delete')">删除</a></li></ul>
|
||||
</div>{/if}
|
||||
</form>
|
||||
|
||||
<table id="listTable">
|
||||
@@ -137,7 +140,12 @@ $(document).ready(function(){
|
||||
pageNumber: pageNumber,
|
||||
pageSize: pageSize,
|
||||
classes: 'table table-striped table-hover table-bordered',
|
||||
uniqueId: 'id',
|
||||
columns: [
|
||||
{
|
||||
field: '',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'id',
|
||||
title: 'ID'
|
||||
@@ -246,25 +254,12 @@ function saveAdd(){
|
||||
});
|
||||
}
|
||||
function editframe(id){
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/domain/op/act/get',
|
||||
data : {id: id},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
$("#modal-store2").modal('show');
|
||||
$("#form-store2 input[name=id]").val(data.data.id);
|
||||
$("#form-store2 select[name=is_hide]").val(data.data.is_hide);
|
||||
$("#form-store2 select[name=is_sso]").val(data.data.is_sso);
|
||||
$("#form-store2 input[name=remark]").val(data.data.remark);
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2})
|
||||
}
|
||||
}
|
||||
});
|
||||
var row = $("#listTable").bootstrapTable('getRowByUniqueId', id);
|
||||
$("#modal-store2").modal('show');
|
||||
$("#form-store2 input[name=id]").val(row.id);
|
||||
$("#form-store2 select[name=is_hide]").val(row.is_hide);
|
||||
$("#form-store2 select[name=is_sso]").val(row.is_sso);
|
||||
$("#form-store2 input[name=remark]").val(row.remark);
|
||||
}
|
||||
function saveEdit(){
|
||||
var ii = layer.load(2);
|
||||
@@ -276,14 +271,9 @@ function saveEdit(){
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg,{
|
||||
icon: 1,
|
||||
closeBtn: false
|
||||
}, function(){
|
||||
layer.closeAll();
|
||||
$("#modal-store2").modal('hide');
|
||||
searchRefresh();
|
||||
});
|
||||
layer.msg(data.msg, {icon:1, time:800});
|
||||
$("#modal-store2").modal('hide');
|
||||
searchRefresh();
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2})
|
||||
}
|
||||
@@ -358,6 +348,78 @@ function getDomainList(){
|
||||
cache:false
|
||||
});
|
||||
}
|
||||
function operation(action){
|
||||
var rows = $("#listTable").bootstrapTable('getSelections');
|
||||
if(rows.length == 0){
|
||||
layer.msg('请选择要操作的记录');
|
||||
return;
|
||||
}
|
||||
var ids = [];
|
||||
$.each(rows, function(index, item){
|
||||
ids.push(item.id);
|
||||
})
|
||||
if(action == 'editremark'){
|
||||
batch_edit_remark(ids)
|
||||
return;
|
||||
}
|
||||
var confirmobj = layer.confirm('确定要删除所选记录吗?', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/domain/op/act/batchdel',
|
||||
data : {ids: ids},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.closeAll();
|
||||
layer.alert(data.msg, {icon: 1});
|
||||
searchRefresh();
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
layer.close(confirmobj);
|
||||
});
|
||||
}
|
||||
function batch_edit_remark(ids) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: ['350px'],
|
||||
closeBtn: 2,
|
||||
title: '批量修改备注',
|
||||
content: '<div style="padding:15px"><div class="form-group"><input class="form-control" type="text" name="remark2" value="" autocomplete="off" placeholder="备注信息"></div></div>',
|
||||
btn: ['确认', '取消'],
|
||||
yes: function(){
|
||||
var remark = $("input[name='remark2']").val();
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/domain/op/act/batchedit',
|
||||
data : {ids:ids, remark:remark},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
layer.alert(data.msg,{
|
||||
icon: 1,
|
||||
closeBtn: false
|
||||
}, function(){
|
||||
layer.closeAll();
|
||||
searchRefresh();
|
||||
});
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii);
|
||||
layer.msg('服务器错误');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function loading(){
|
||||
layer.load(2);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
|
||||
<form class="form-horizontal" id="form-store">
|
||||
<input type="hidden" name="action"/>
|
||||
<input type="hidden" name="recordid"/>
|
||||
<input type="hidden" name="recordinfo"/>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">主机记录</label>
|
||||
<div class="col-sm-9">
|
||||
@@ -210,9 +211,6 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="value" placeholder="输入记录值">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="status" class="form-control"><option value="">所有状态</option><option value="1">启用</option><option value="0">暂停</option></select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa fa-search"></i> 搜索</button>
|
||||
<a href="javascript:searchClear()" class="btn btn-default" title="刷新解析记录列表"><i class="fa fa-refresh"></i> 刷新</a>
|
||||
<a href="javascript:advanceSearch()" class="btn"><i class="fa fa-angle-up"></i> 收起</a>
|
||||
@@ -236,7 +234,7 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:360px;
|
||||
var recordLine = {$recordLine|json_encode|raw};
|
||||
var dnsconfig = {$dnsconfig|json_encode|raw};
|
||||
var defaultLine = recordLine[0].id;
|
||||
var sidePagination = dnsconfig.type == 'baidu' || dnsconfig.type == 'namesilo' ? 'client' : 'server';
|
||||
var sidePagination = dnsconfig.page ? 'client' : 'server';
|
||||
var showWeight = dnsconfig.weight;
|
||||
$(document).ready(function(){
|
||||
updateToolbar();
|
||||
@@ -423,6 +421,7 @@ function editframe(recordid){
|
||||
$("#modal-title").html("修改记录");
|
||||
$("#form-store input[name=action]").val("update");
|
||||
$("#form-store input[name=recordid]").val(recordid);
|
||||
$("#form-store input[name=recordinfo]").val(JSON.stringify(row));
|
||||
$("#form-store input[name=name]").val(row.Name);
|
||||
$("#form-store select[name=type]").val(row.Type);
|
||||
$("#form-store select[name=type]").change();
|
||||
@@ -470,11 +469,12 @@ function save(){
|
||||
});
|
||||
}
|
||||
function setStatus(recordid, status){
|
||||
var row = $("#listTable").bootstrapTable('getRowByUniqueId', recordid);
|
||||
var ii = layer.load(2);
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/record/status/{$domainId}',
|
||||
data : {recordid: recordid, status: status},
|
||||
data : {recordid: recordid, status: status, recordinfo: JSON.stringify(row)},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
@@ -489,6 +489,7 @@ function setStatus(recordid, status){
|
||||
});
|
||||
}
|
||||
function delItem(recordid) {
|
||||
var row = $("#listTable").bootstrapTable('getRowByUniqueId', recordid);
|
||||
var confirmobj = layer.confirm('确定要删除此解析记录吗?', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
@@ -496,7 +497,7 @@ function delItem(recordid) {
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/record/delete/{$domainId}',
|
||||
data : {recordid: recordid},
|
||||
data : {recordid: recordid, recordinfo: JSON.stringify(row)},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
@@ -555,32 +556,16 @@ function operation(action){
|
||||
return;
|
||||
}
|
||||
if(action == 'edit'){
|
||||
var records = [];
|
||||
$.each(rows, function(index, item){
|
||||
records.push({recordid:item.RecordId, name:item.Name, line:item.Line, mx:item.MX, ttl:item.TTL, weight:item.Weight, remark:item.Remark});
|
||||
})
|
||||
batch_edit(records)
|
||||
batch_edit(rows)
|
||||
return;
|
||||
}else if(action == 'editline'){
|
||||
var records = [];
|
||||
$.each(rows, function(index, item){
|
||||
records.push({recordid:item.RecordId, name:item.Name, type:item.Type, value:item.Value, mx:item.MX, ttl:item.TTL, weight:item.Weight, remark:item.Remark});
|
||||
})
|
||||
batch_edit_line(records)
|
||||
batch_edit_line(rows)
|
||||
return;
|
||||
}else if(action == 'editremark'){
|
||||
var ids = [];
|
||||
$.each(rows, function(index, item){
|
||||
ids.push(item.RecordId);
|
||||
})
|
||||
batch_edit_remark(ids)
|
||||
batch_edit_remark(rows)
|
||||
return;
|
||||
}
|
||||
|
||||
var ids = [];
|
||||
$.each(rows, function(index, item){
|
||||
ids.push(item.RecordId);
|
||||
})
|
||||
var confirmobj = layer.confirm('确定要'+(action=='open'?'启用':(action=='pause'?'暂停':'删除'))+'所选记录吗?', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
@@ -588,7 +573,7 @@ function operation(action){
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/record/batch/{$domainId}',
|
||||
data : {action: action, recordids: ids},
|
||||
data : {action: action, recordinfo: JSON.stringify(rows)},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
@@ -645,10 +630,10 @@ function batch_save(){
|
||||
}
|
||||
});
|
||||
}
|
||||
function batch_edit_line(records){
|
||||
$("#batch_num").text(records.length);
|
||||
function batch_edit_line(rows){
|
||||
$("#batch_num").text(rows.length);
|
||||
$("#modal-store3").modal('show');
|
||||
$("#form-store3 input[name=recordinfo]").val(JSON.stringify(records));
|
||||
$("#form-store3 input[name=recordinfo]").val(JSON.stringify(rows));
|
||||
initLine('', 'line_list3');
|
||||
}
|
||||
function batch_save_line(){
|
||||
@@ -675,7 +660,7 @@ function batch_save_line(){
|
||||
}
|
||||
});
|
||||
}
|
||||
function batch_edit_remark(recordids) {
|
||||
function batch_edit_remark(rows) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: ['350px'],
|
||||
@@ -689,7 +674,7 @@ function batch_edit_remark(recordids) {
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/record/batch/{$domainId}',
|
||||
data : {action:'remark', recordids:recordids, remark:remark},
|
||||
data : {action:'remark', recordinfo: JSON.stringify(rows), remark:remark},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
<div class="small-box bg-green">
|
||||
<div class="inner">
|
||||
<h3 id="count2">0</h3>
|
||||
<p>用户数量</p>
|
||||
<p>容灾切换策略</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="fa fa-users"></i>
|
||||
<i class="fa fa-heartbeat"></i>
|
||||
</div>
|
||||
<a href="/user" class="small-box-footer">More info <i class="fa fa-arrow-circle-right"></i></a>
|
||||
<a href="/dmonitor/task" class="small-box-footer">More info <i class="fa fa-arrow-circle-right"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ./col -->
|
||||
@@ -45,12 +45,12 @@
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="inner">
|
||||
<h3 id="count3">0</h3>
|
||||
<p>解析数量</p>
|
||||
<p>SSL证书订单</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="fa fa-globe"></i>
|
||||
<i class="fa fa-expeditedssl"></i>
|
||||
</div>
|
||||
<a href="#" class="small-box-footer">More info <i class="fa fa-arrow-circle-right"></i></a>
|
||||
<a href="/cert/certorder" class="small-box-footer">More info <i class="fa fa-arrow-circle-right"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ./col -->
|
||||
@@ -59,12 +59,12 @@
|
||||
<div class="small-box bg-red">
|
||||
<div class="inner">
|
||||
<h3 id="count4">0</h3>
|
||||
<p>DNS平台数量</p>
|
||||
<p>SSL部署任务</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="fa fa-connectdevelop"></i>
|
||||
</div>
|
||||
<a href="#" class="small-box-footer">More info <i class="fa fa-arrow-circle-right"></i></a>
|
||||
<a href="/cert/deploytask" class="small-box-footer">More info <i class="fa fa-arrow-circle-right"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ./col -->
|
||||
@@ -131,9 +131,9 @@ $(document).ready(function(){
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
$('#count1').html(data.domains);
|
||||
$('#count2').html(data.users);
|
||||
$('#count3').html(data.records);
|
||||
$('#count4').html(data.types);
|
||||
$('#count2').html(data.tasks);
|
||||
$('#count3').html(data.certs);
|
||||
$('#count4').html(data.deploys);
|
||||
$.ajax({
|
||||
url: '{$checkupdate}',
|
||||
type: 'get',
|
||||
|
||||
@@ -94,9 +94,13 @@
|
||||
<div class="col-sm-9"><input type="text" name="tgbot_chatid" value="{:config_get('tgbot_chatid')}" class="form-control"/></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">使用代理服务器</label>
|
||||
<div class="col-sm-9"><select class="form-control" name="tgbot_proxy" default="{:config_get('tgbot_proxy')}"><option value="0">否</option><option value="1">是</option></select></div>
|
||||
</div>
|
||||
<label class="col-sm-3 control-label">使用代理服务器</label>
|
||||
<div class="col-sm-9"><select class="form-control" name="tgbot_proxy" default="{:config_get('tgbot_proxy')}"><option value="0">否</option><option value="1">是</option><option value="2">自定义反代URL</option></select></div>
|
||||
</div>
|
||||
<div class="form-group" id="tgbot_url_div" style="display:none;">
|
||||
<label class="col-sm-3 control-label">自定义反代URL</label>
|
||||
<div class="col-sm-9"><input type="text" name="tgbot_url" value="{:config_get('tgbot_url')}" class="form-control" placeholder="默认为:https://api.telegram.org"/></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<input type="submit" name="submit" value="保存" class="btn btn-primary btn-block"/>
|
||||
@@ -148,7 +152,15 @@ $("select[name='mail_type']").change(function(){
|
||||
$("#frame_set2").show();
|
||||
}
|
||||
});
|
||||
$("select[name='tgbot_proxy']").change(function(){
|
||||
if($(this).val() == 2){
|
||||
$("#tgbot_url_div").show();
|
||||
}else{
|
||||
$("#tgbot_url_div").hide();
|
||||
}
|
||||
});
|
||||
$("select[name='mail_type']").change();
|
||||
$("select[name='tgbot_proxy']").change();
|
||||
function saveSetting(obj){
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
$.ajax({
|
||||
|
||||
@@ -31,7 +31,7 @@ return [
|
||||
'show_error_msg' => true,
|
||||
'exception_tmpl' => \think\facade\App::getAppPath() . 'view/exception.tpl',
|
||||
|
||||
'version' => '1028',
|
||||
'version' => '1029',
|
||||
|
||||
'dbversion' => '1023'
|
||||
'dbversion' => '1028'
|
||||
];
|
||||
|
||||
BIN
public/static/images/ctyun.ico
Normal file
BIN
public/static/images/ctyun.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
public/static/images/kuocai.jpg
Normal file
BIN
public/static/images/kuocai.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
public/static/images/powerdns.ico
Normal file
BIN
public/static/images/powerdns.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/static/images/proxmox.ico
Normal file
BIN
public/static/images/proxmox.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/static/images/synology.png
Normal file
BIN
public/static/images/synology.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Reference in New Issue
Block a user