diff --git a/.example.env b/.example.env index 95e1469..037c165 100644 --- a/.example.env +++ b/.example.env @@ -1,18 +1,18 @@ -APP_DEBUG = false - -[APP] -DEFAULT_TIMEZONE = Asia/Shanghai - -[DATABASE] -TYPE = mysql -HOSTNAME = {dbhost} -DATABASE = {dbname} -USERNAME = {dbuser} -PASSWORD = {dbpwd} -HOSTPORT = {dbport} -CHARSET = utf8mb4 -PREFIX = {dbprefix} -DEBUG = false - -[LANG] +APP_DEBUG = false + +[APP] +DEFAULT_TIMEZONE = Asia/Shanghai + +[DATABASE] +TYPE = mysql +HOSTNAME = {dbhost} +DATABASE = {dbname} +USERNAME = {dbuser} +PASSWORD = {dbpwd} +HOSTPORT = {dbport} +CHARSET = utf8mb4 +PREFIX = {dbprefix} +DEBUG = false + +[LANG] default_lang = zh-cn \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/README.md b/README.md index 9f895cd..8cf8abd 100644 --- a/README.md +++ b/README.md @@ -1,209 +1,209 @@ -# 彩虹聚合DNS管理系统 - -
-
-### 其他推荐
-
-- [彩虹云主机 - 免备案CDN/虚拟主机](https://www.cccyun.net/)
-- [小白云高防云服务器](https://www.xiaobaiyun.cn/aff/GMLPMFOV)
-
+# 彩虹聚合DNS管理系统
+
+
+
+### 其他推荐
+
+- [彩虹云主机 - 免备案CDN/虚拟主机](https://www.cccyun.net/)
+- [小白云高防云服务器](https://www.xiaobaiyun.cn/aff/GMLPMFOV)
+
diff --git a/app/command/Certtask.php b/app/command/Certtask.php
index d75f8e4..7023698 100644
--- a/app/command/Certtask.php
+++ b/app/command/Certtask.php
@@ -1,42 +1,42 @@
-setName('certtask')
- ->setDescription('SSL证书续签与部署、域名到期提醒、定时切换解析、CF优选IP更新');
- }
-
- protected function execute(Input $input, Output $output)
- {
- $res = Db::name('config')->cache('configs', 0)->column('value', 'key');
- Config::set($res, 'sys');
-
- (new ScheduleService())->execute();
- $res = (new OptimizeService())->execute();
- if (!$res) {
- (new CertTaskService())->execute();
- (new ExpireNoticeService())->task();
- }
- echo 'done'.PHP_EOL;
- }
-}
+setName('certtask')
+ ->setDescription('SSL证书续签与部署、域名到期提醒、定时切换解析、CF优选IP更新');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $res = Db::name('config')->cache('configs', 0)->column('value', 'key');
+ Config::set($res, 'sys');
+
+ (new ScheduleService())->execute();
+ $res = (new OptimizeService())->execute();
+ if (!$res) {
+ (new CertTaskService())->execute();
+ (new ExpireNoticeService())->task();
+ }
+ echo 'done'.PHP_EOL;
+ }
+}
diff --git a/app/command/Dmtask.php b/app/command/Dmtask.php
index f69eb53..0c46140 100644
--- a/app/command/Dmtask.php
+++ b/app/command/Dmtask.php
@@ -1,82 +1,82 @@
-setName('dmtask')
- ->setDescription('容灾切换任务');
- }
-
- protected function execute(Input $input, Output $output)
- {
- $res = Db::name('config')->cache('configs', 0)->column('value', 'key');
- Config::set($res, 'sys');
-
- config_set('run_error', '');
- if (!extension_loaded('swoole')) {
- $output->writeln('[Error] 未安装Swoole扩展');
- config_set('run_error', '未安装Swoole扩展');
- return;
- }
- try {
- $output->writeln('进程启动成功.');
- $this->runtask();
- } catch (Exception $e) {
- $output->writeln('[Error] ' . $e->getMessage());
- config_set('run_error', $e->getMessage());
- }
- }
-
- private function runtask()
- {
- \Co::set(['hook_flags' => SWOOLE_HOOK_ALL]);
- \Co\run(function () {
- $date = date("Ymd");
- $count = config_get('run_count', null, true) ?? 0;
- while (true) {
- sleep(1);
- if ($date != date("Ymd")) {
- $count = 0;
- $date = date("Ymd");
- }
-
- $rows = Db::name('dmtask')->where('checknexttime', '<=', time())->where('active', 1)->order('id', 'ASC')->select();
- foreach ($rows as $row) {
- \go(function () use ($row) {
- try {
- (new TaskRunner())->execute($row);
- } catch (\Swoole\ExitException $e) {
- echo $e->getStatus() . "\n";
- } catch (Exception $e) {
- echo $e->__toString() . "\n";
- }
- });
- Db::name('dmtask')->where('id', $row['id'])->update([
- 'checktime' => time(),
- 'checknexttime' => time() + $row['frequency']
- ]);
- $count++;
- }
-
- config_set('run_time', date("Y-m-d H:i:s"));
- config_set('run_count', $count);
- }
- });
- }
-}
+setName('dmtask')
+ ->setDescription('容灾切换任务');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $res = Db::name('config')->cache('configs', 0)->column('value', 'key');
+ Config::set($res, 'sys');
+
+ config_set('run_error', '');
+ if (!extension_loaded('swoole')) {
+ $output->writeln('[Error] 未安装Swoole扩展');
+ config_set('run_error', '未安装Swoole扩展');
+ return;
+ }
+ try {
+ $output->writeln('进程启动成功.');
+ $this->runtask();
+ } catch (Exception $e) {
+ $output->writeln('[Error] ' . $e->getMessage());
+ config_set('run_error', $e->getMessage());
+ }
+ }
+
+ private function runtask()
+ {
+ \Co::set(['hook_flags' => SWOOLE_HOOK_ALL]);
+ \Co\run(function () {
+ $date = date("Ymd");
+ $count = config_get('run_count', null, true) ?? 0;
+ while (true) {
+ sleep(1);
+ if ($date != date("Ymd")) {
+ $count = 0;
+ $date = date("Ymd");
+ }
+
+ $rows = Db::name('dmtask')->where('checknexttime', '<=', time())->where('active', 1)->order('id', 'ASC')->select();
+ foreach ($rows as $row) {
+ \go(function () use ($row) {
+ try {
+ (new TaskRunner())->execute($row);
+ } catch (\Swoole\ExitException $e) {
+ echo $e->getStatus() . "\n";
+ } catch (Exception $e) {
+ echo $e->__toString() . "\n";
+ }
+ });
+ Db::name('dmtask')->where('id', $row['id'])->update([
+ 'checktime' => time(),
+ 'checknexttime' => time() + $row['frequency']
+ ]);
+ $count++;
+ }
+
+ config_set('run_time', date("Y-m-d H:i:s"));
+ config_set('run_count', $count);
+ }
+ });
+ }
+}
diff --git a/app/command/Reset.php b/app/command/Reset.php
index 019387f..d968d62 100644
--- a/app/command/Reset.php
+++ b/app/command/Reset.php
@@ -1,47 +1,47 @@
-setName('reset')
- ->addArgument('type', Argument::REQUIRED, '操作类型,pwd:重置密码,totp:关闭TOTP')
- ->addArgument('username', Argument::REQUIRED, '用户名')
- ->addArgument('password', Argument::OPTIONAL, '密码')
- ->setDescription('重置密码');
- }
-
- protected function execute(Input $input, Output $output)
- {
- $type = trim($input->getArgument('type'));
- $username = trim($input->getArgument('username'));
- $user = Db::name('user')->where('username', $username)->find();
- if (!$user) {
- $output->writeln('用户 ' . $username . ' 不存在');
- return;
- }
- if ($type == 'pwd') {
- $password = $input->getArgument('password');
- if (empty($password)) $password = '123456';
- Db::name('user')->where('id', $user['id'])->update(['password' => password_hash($password, PASSWORD_DEFAULT)]);
- $output->writeln('用户 ' . $username . ' 密码重置成功');
- } elseif ($type == 'totp') {
- Db::name('user')->where('id', $user['id'])->update(['totp_open' => 0, 'totp_secret' => null]);
- $output->writeln('用户 ' . $username . ' TOTP关闭成功');
- }
- }
-}
+setName('reset')
+ ->addArgument('type', Argument::REQUIRED, '操作类型,pwd:重置密码,totp:关闭TOTP')
+ ->addArgument('username', Argument::REQUIRED, '用户名')
+ ->addArgument('password', Argument::OPTIONAL, '密码')
+ ->setDescription('重置密码');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $type = trim($input->getArgument('type'));
+ $username = trim($input->getArgument('username'));
+ $user = Db::name('user')->where('username', $username)->find();
+ if (!$user) {
+ $output->writeln('用户 ' . $username . ' 不存在');
+ return;
+ }
+ if ($type == 'pwd') {
+ $password = $input->getArgument('password');
+ if (empty($password)) $password = '123456';
+ Db::name('user')->where('id', $user['id'])->update(['password' => password_hash($password, PASSWORD_DEFAULT)]);
+ $output->writeln('用户 ' . $username . ' 密码重置成功');
+ } elseif ($type == 'totp') {
+ Db::name('user')->where('id', $user['id'])->update(['totp_open' => 0, 'totp_secret' => null]);
+ $output->writeln('用户 ' . $username . ' TOTP关闭成功');
+ }
+ }
+}
diff --git a/app/controller/Cert.php b/app/controller/Cert.php
index 28f9437..1693395 100644
--- a/app/controller/Cert.php
+++ b/app/controller/Cert.php
@@ -1,962 +1,962 @@
-alert('error', '无权限');
- return view();
- }
-
- public function deployaccount()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- return view();
- }
-
- public function account_data()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $deploy = input('get.deploy/d', 0);
- $kw = $this->request->post('kw', null, 'trim');
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
-
- $select = Db::name('cert_account')->where('deploy', $deploy);
- if (!empty($kw)) {
- $select->whereLike('name|remark', '%' . $kw . '%')->whereOr('id', $kw);
- }
- $total = $select->count();
- $rows = $select->order('id', 'desc')->limit($offset, $limit)->select();
-
- $list = [];
- foreach ($rows as $row) {
- if ($deploy == 1) {
- if (!empty($row['type']) && isset(DeployHelper::$deploy_config[$row['type']])) {
- $row['typename'] = DeployHelper::$deploy_config[$row['type']]['name'];
- $row['icon'] = DeployHelper::$deploy_config[$row['type']]['icon'];
- }
- } else {
- if (!empty($row['type']) && isset(CertHelper::$cert_config[$row['type']])) {
- $row['typename'] = CertHelper::$cert_config[$row['type']]['name'];
- $row['icon'] = CertHelper::$cert_config[$row['type']]['icon'];
- }
- }
- $list[] = $row;
- }
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function account_op()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
- $deploy = input('post.deploy/d', 0);
- $title = $deploy == 1 ? '自动部署账户' : 'SSL证书账户';
-
- if ($action == 'add') {
- $type = input('post.type');
- $name = input('post.name', null, 'trim');
- $config = input('post.config', null, 'trim');
- $remark = input('post.remark', null, 'trim');
- if ($type == 'local') $name = '复制到本机';
- if (empty($name) || empty($config)) return json(['code' => -1, 'msg' => '必填参数不能为空']);
- if (Db::name('cert_account')->where('type', $type)->where('config', $config)->find()) {
- return json(['code' => -1, 'msg' => $title . '已存在']);
- }
- Db::startTrans();
- $id = Db::name('cert_account')->insertGetId([
- 'type' => $type,
- 'name' => $name,
- 'config' => $config,
- 'remark' => $remark,
- 'deploy' => $deploy,
- 'addtime' => date('Y-m-d H:i:s'),
- ]);
- try {
- $this->checkAccount($id, $type, $deploy);
- Db::commit();
- return json(['code' => 0, 'msg' => '添加' . $title . '成功!']);
- } catch (Exception $e) {
- Db::rollback();
- return json(['code' => -1, 'msg' => $e->getMessage()]);
- }
- } elseif ($action == 'edit') {
- $id = input('post.id/d');
- $row = Db::name('cert_account')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => $title . '不存在']);
- $type = input('post.type');
- $name = input('post.name', null, 'trim');
- $config = input('post.config', null, 'trim');
- $remark = input('post.remark', null, 'trim');
- if ($type == 'local') $name = '复制到本机';
- if (empty($name) || empty($config)) return json(['code' => -1, 'msg' => '必填参数不能为空']);
- if (Db::name('cert_account')->where('type', $type)->where('config', $config)->where('id', '<>', $id)->find()) {
- return json(['code' => -1, 'msg' => $title . '已存在']);
- }
- Db::startTrans();
- Db::name('cert_account')->where('id', $id)->update([
- 'type' => $type,
- 'name' => $name,
- 'config' => $config,
- 'remark' => $remark,
- ]);
- try {
- $this->checkAccount($id, $type, $deploy);
- Db::commit();
- return json(['code' => 0, 'msg' => '修改' . $title . '成功!']);
- } catch (Exception $e) {
- Db::rollback();
- return json(['code' => -1, 'msg' => $e->getMessage()]);
- }
- } elseif ($action == 'del') {
- $id = input('post.id/d');
- if ($deploy == 0) {
- $dcount = DB::name('cert_order')->where('aid', $id)->count();
- if ($dcount > 0) return json(['code' => -1, 'msg' => '该' . $title . '下存在证书订单,无法删除']);
- } else {
- $dcount = DB::name('cert_deploy')->where('aid', $id)->count();
- if ($dcount > 0) return json(['code' => -1, 'msg' => '该' . $title . '下存在自动部署任务,无法删除']);
- }
- Db::name('cert_account')->where('id', $id)->delete();
- return json(['code' => 0]);
- }
- return json(['code' => -3]);
- }
-
- public function account_form()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
- $deploy = input('get.deploy/d', 0);
- $title = $deploy == 1 ? '自动部署账户' : 'SSL证书账户';
-
- $account = null;
- if ($action == 'edit') {
- $id = input('get.id/d');
- $account = Db::name('cert_account')->where('id', $id)->find();
- if (empty($account)) return $this->alert('error', $title . '不存在');
- }
-
- $typeList = $deploy == 1 ? DeployHelper::getList() : CertHelper::getList();
- $classList = $deploy == 1 ? DeployHelper::$class_config : CertHelper::$class_config;
-
- View::assign('title', $title);
- View::assign('info', $account);
- View::assign('typeList', $typeList);
- View::assign('classList', $classList);
- View::assign('action', $action);
- View::assign('deploy', $deploy);
- return View::fetch();
- }
-
- private function checkAccount($id, $type, $deploy)
- {
- if ($deploy == 0) {
- $mod = CertHelper::getModel($id);
- if ($mod) {
- try {
- $ext = $mod->register();
- if (is_array($ext)) {
- Db::name('cert_account')->where('id', $id)->update(['ext' => json_encode($ext)]);
- }
- return true;
- } catch (Exception $e) {
- throw new Exception('验证SSL证书账户失败,' . $e->getMessage());
- }
- } else {
- throw new Exception('SSL证书申请模块' . $type . '不存在');
- }
- } else {
- $mod = DeployHelper::getModel($id);
- if ($mod) {
- try {
- $mod->check();
- return true;
- } catch (Exception $e) {
- throw new Exception('验证自动部署账户失败,' . $e->getMessage());
- }
- } else {
- throw new Exception('SSL证书申请模块' . $type . '不存在');
- }
- }
- }
-
- public function certorder()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $types = [];
- foreach (CertHelper::$cert_config as $key => $value) {
- $types[$key] = $value['name'];
- }
- View::assign('types', $types);
- return view();
- }
-
- public function order_data()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $domain = $this->request->post('domain', null, 'trim');
- $id = input('post.id');
- $aid = input('post.aid', null, 'trim');
- $type = input('post.type', null, 'trim');
- $status = input('post.status', null, 'trim');
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
-
- $select = Db::name('cert_order')->alias('A')->leftJoin('cert_account B', 'A.aid = B.id');
- if (!empty($id)) {
- $select->where('A.id', $id);
- } elseif (!empty($domain)) {
- $oids = Db::name('cert_domain')->where('domain', 'like', '%' . $domain . '%')->column('oid');
- $select->whereIn('A.id', $oids);
- }
- if (!empty($aid)) {
- $select->where('A.aid', $aid);
- }
- 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();
-
- $list = [];
- foreach ($rows as $row) {
- if (!empty($row['type']) && isset(CertHelper::$cert_config[$row['type']])) {
- $row['typename'] = CertHelper::$cert_config[$row['type']]['name'];
- $row['icon'] = CertHelper::$cert_config[$row['type']]['icon'];
- } else {
- $row['typename'] = null;
- }
- $row['domains'] = Db::name('cert_domain')->where('oid', $row['id'])->order('sort', 'ASC')->column('domain');
- $row['end_day'] = $row['expiretime'] ? ceil((strtotime($row['expiretime']) - time()) / 86400) : null;
- if ($row['error']) $row['error'] = htmlspecialchars(str_replace("'", "\\'", $row['error']));
- $list[] = $row;
- }
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function order_info()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $id = input('post.id/d');
- $row = Db::name('cert_order')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => '证书订单不存在']);
- $pfx = CertHelper::getPfx($row['fullchain'], $row['privatekey']);
- $row['pfx'] = base64_encode($pfx);
- return json(['code' => 0, 'data' => ['id' => $row['id'], 'crt' => $row['fullchain'], 'key' => $row['privatekey'], 'pfx' => $row['pfx'], 'issuetime' => $row['issuetime'], 'expiretime' => $row['expiretime'], 'domains' => Db::name('cert_domain')->where('oid', $row['id'])->order('sort', 'ASC')->column('domain')]]);
- }
-
- public function order_op()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
-
- if ($action == 'get') {
- $id = input('post.id/d');
- $row = Db::name('cert_order')->where('id', $id)->field('fullchain,privatekey')->find();
- if (!$row) return $this->alert('error', '证书订单不存在');
- $pfx = CertHelper::getPfx($row['fullchain'], $row['privatekey']);
- $row['pfx'] = base64_encode($pfx);
- return json(['code' => 0, 'data' => $row]);
- } elseif ($action == 'add') {
- $aid = input('post.aid/d');
-
- if ($aid == -1) {
- $fullchain = input('post.fullchain', null, 'trim');
- $privatekey = input('post.privatekey', null, 'trim');
- $certInfo = $this->parse_cert_key($fullchain, $privatekey);
- if ($certInfo['code'] == -1) return json($certInfo);
- $domains = $certInfo['domains'];
-
- $order_ids = Db::name('cert_order')->where('issuetime', $certInfo['issuetime'])->column('id');
- if (!empty($order_ids)) {
- foreach ($order_ids as $order_id) {
- $domains2 = Db::name('cert_domain')->where('oid', $order_id)->column('domain');
- if (arrays_are_equal($domains2, $domains)) {
- return json(['code' => -1, 'msg' => '该证书已存在,无需重复添加']);
- }
- }
- }
-
- $order = [
- 'aid' => 0,
- 'keytype' => $certInfo['keytype'],
- 'keysize' => $certInfo['keysize'],
- 'addtime' => date('Y-m-d H:i:s'),
- 'updatetime' => date('Y-m-d H:i:s'),
- 'issuetime' => $certInfo['issuetime'],
- 'expiretime' => $certInfo['expiretime'],
- 'issuer' => $certInfo['issuer'],
- 'status' => 3,
- 'isauto' => 1,
- 'fullchain' => $fullchain,
- 'privatekey' => $privatekey,
- ];
- } else {
- $order = [
- 'aid' => $aid,
- 'keytype' => input('post.keytype'),
- 'keysize' => input('post.keysize'),
- 'addtime' => date('Y-m-d H:i:s'),
- 'issuer' => '',
- 'status' => 0,
- 'isauto' => 1,
- ];
- $domains = input('post.domains', [], 'trim');
- $domains = array_map('trim', $domains);
- $domains = array_filter($domains, function ($v) {
- return !empty($v);
- });
- $domains = array_unique($domains);
- if (empty($domains)) return json(['code' => -1, 'msg' => '绑定域名不能为空']);
- $res = $this->check_order($order, $domains);
- if (is_array($res)) return json($res);
- }
- if (empty($order['keytype']) || empty($order['keysize'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
-
- Db::startTrans();
- $id = Db::name('cert_order')->insertGetId($order);
- $domainList = [];
- $i = 1;
- foreach ($domains as $domain) {
- $domainList[] = [
- 'oid' => $id,
- 'domain' => convertDomainToAscii($domain),
- 'sort' => $i++,
- ];
- }
- Db::name('cert_domain')->insertAll($domainList);
- Db::commit();
- return json(['code' => 0, 'msg' => '添加证书订单成功!']);
- } elseif ($action == 'edit') {
- $id = input('post.id/d');
- $row = Db::name('cert_order')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => '证书订单不存在']);
-
- $aid = input('post.aid/d');
- if ($aid == -1) {
- $fullchain = input('post.fullchain', null, 'trim');
- $privatekey = input('post.privatekey', null, 'trim');
- $certInfo = $this->parse_cert_key($fullchain, $privatekey);
- if ($certInfo['code'] == -1) return json($certInfo);
- $domains = $certInfo['domains'];
-
- $order = [
- 'aid' => 0,
- 'keytype' => $certInfo['keytype'],
- 'keysize' => $certInfo['keysize'],
- 'updatetime' => date('Y-m-d H:i:s'),
- 'issuetime' => $certInfo['issuetime'],
- 'expiretime' => $certInfo['expiretime'],
- 'issuer' => $certInfo['issuer'],
- 'status' => 3,
- 'issend' => 0,
- 'fullchain' => $fullchain,
- 'privatekey' => $privatekey,
- ];
- } else {
- $domains = input('post.domains', [], 'trim');
- $order = [
- 'aid' => $aid,
- 'keytype' => input('post.keytype'),
- 'keysize' => input('post.keysize'),
- 'updatetime' => date('Y-m-d H:i:s'),
- ];
- $domains = array_map('trim', $domains);
- $domains = array_filter($domains, function ($v) {
- return !empty($v);
- });
- $domains = array_unique($domains);
- if (empty($domains)) return json(['code' => -1, 'msg' => '绑定域名不能为空']);
- $res = $this->check_order($order, $domains);
- if (is_array($res)) return json($res);
- }
- if (empty($order['keytype']) || empty($order['keysize'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
-
- Db::startTrans();
- Db::name('cert_order')->where('id', $id)->update($order);
- Db::name('cert_domain')->where('oid', $id)->delete();
- $domainList = [];
- $i = 1;
- foreach ($domains as $domain) {
- $domainList[] = [
- 'oid' => $id,
- 'domain' => convertDomainToAscii($domain),
- 'sort' => $i++,
- ];
- }
- Db::name('cert_domain')->insertAll($domainList);
- Db::commit();
- return json(['code' => 0, 'msg' => '修改证书订单成功!']);
- } elseif ($action == 'del') {
- $id = input('post.id/d');
- $dcount = DB::name('cert_deploy')->where('oid', $id)->count();
- if ($dcount > 0) return json(['code' => -1, 'msg' => '该证书关联了自动部署任务,无法删除']);
- try {
- (new CertOrderService($id))->cancel();
- } catch (Exception $e) {
- }
- Db::name('cert_order')->where('id', $id)->delete();
- Db::name('cert_domain')->where('oid', $id)->delete();
- return json(['code' => 0]);
- } elseif ($action == 'setauto') {
- $id = input('post.id/d');
- $isauto = input('post.isauto/d');
- Db::name('cert_order')->where('id', $id)->update(['isauto' => $isauto]);
- return json(['code' => 0]);
- } elseif ($action == 'reset') {
- $id = input('post.id/d');
- try {
- $service = new CertOrderService($id);
- $service->cancel();
- $service->reset();
- return json(['code' => 0]);
- } catch (Exception $e) {
- return json(['code' => -1, 'msg' => $e->getMessage()]);
- }
- } elseif ($action == 'revoke') {
- $id = input('post.id/d');
- try {
- $service = new CertOrderService($id);
- $service->revoke();
- return json(['code' => 0]);
- } catch (Exception $e) {
- return json(['code' => -1, 'msg' => $e->getMessage()]);
- }
- } elseif ($action == 'show_log') {
- $processid = input('post.processid');
- $file = app()->getRuntimePath() . 'log/' . $processid . '.log';
- if (!file_exists($file)) return json(['code' => -1, 'msg' => '日志文件不存在']);
- return json(['code' => 0, 'data' => file_get_contents($file), 'time' => filemtime($file)]);
- } elseif ($action == 'operation') {
- $ids = input('post.ids');
- $success = 0;
- foreach ($ids as $id) {
- if (input('post.act') == 'delete') {
- $dcount = DB::name('cert_deploy')->where('oid', $id)->count();
- if ($dcount > 0) continue;
- try {
- (new CertOrderService($id))->cancel();
- } catch (Exception $e) {
- }
- Db::name('cert_order')->where('id', $id)->delete();
- Db::name('cert_domain')->where('oid', $id)->delete();
- $success++;
- } elseif (input('post.act') == 'reset') {
- try {
- $service = new CertOrderService($id);
- $service->cancel();
- $service->reset();
- $success++;
- } catch (Exception $e) {
- }
- } elseif (input('post.act') == 'open' || input('post.act') == 'close') {
- $isauto = input('post.act') == 'open' ? 1 : 0;
- Db::name('cert_order')->where('id', $id)->update(['isauto' => $isauto]);
- $success++;
- }
- }
- return json(['code' => 0, 'msg' => '成功操作' . $success . '个证书订单']);
- }
- return json(['code' => -3]);
- }
-
- private function check_order($order, $domains)
- {
- $account = Db::name('cert_account')->where('id', $order['aid'])->find();
- if (!$account) return ['code' => -1, 'msg' => 'SSL证书账户不存在'];
- $max_domains = CertHelper::$cert_config[$account['type']]['max_domains'];
- $wildcard = CertHelper::$cert_config[$account['type']]['wildcard'];
- $cname = CertHelper::$cert_config[$account['type']]['cname'];
- if (count($domains) > $max_domains) {
- if (!(count($domains) == 2 && $max_domains == 1 && ltrim($domains[0], 'www.') == ltrim($domains[1], 'www.'))) {
- return ['code' => -1, 'msg' => '域名数量不能超过' . $max_domains . '个'];
- }
- }
-
- foreach ($domains as $domain) {
- if (!$wildcard && strpos($domain, '*') !== false) return ['code' => -1, 'msg' => '该证书账户类型不支持泛域名'];
- $mainDomain = getMainDomain($domain);
- $drow = Db::name('domain')->where('name', $mainDomain)->find();
- if (!$drow) {
- if (substr($domain, 0, 2) == '*.') $domain = substr($domain, 2);
- if (!$cname || !Db::name('cert_cname')->where('domain', $domain)->where('status', 1)->find()) {
- return ['code' => -1, 'msg' => '域名' . $domain . '未在本系统添加'];
- }
- }
- }
- return true;
- }
-
- private function parse_cert_key($fullchain, $privatekey)
- {
- if (!openssl_x509_read($fullchain)) return ['code' => -1, 'msg' => '证书内容填写错误'];
- if (!openssl_get_privatekey($privatekey)) return ['code' => -1, 'msg' => '私钥内容填写错误'];
- if (!openssl_x509_check_private_key($fullchain, $privatekey)) return ['code' => -1, 'msg' => 'SSL证书与私钥不匹配'];
- $certInfo = openssl_x509_parse($fullchain, true);
- if (!$certInfo || !isset($certInfo['extensions']['subjectAltName'])) return ['code' => -1, 'msg' => '证书内容解析失败'];
-
- $pubKey = openssl_pkey_get_public($fullchain);
- if (!$pubKey) return ['code' => -1, 'msg' => '证书公钥解析失败'];
- $keyDetails = openssl_pkey_get_details($pubKey);
- $keytype = null;
- $keysize = 0;
- switch ($keyDetails['type']) {
- case OPENSSL_KEYTYPE_RSA:
- $keytype = 'RSA';
- $keysize = $keyDetails['bits'];
- break;
- case OPENSSL_KEYTYPE_EC:
- $keytype = 'ECC';
- $keysize = $keyDetails['bits'];
- break;
- case OPENSSL_KEYTYPE_DSA:
- $keytype = 'DSA';
- $keysize = $keyDetails['bits'];
- break;
- default:
- $keytype = 'Unknown';
- }
-
- $domains = [];
- $subjectAltName = explode(',', $certInfo['extensions']['subjectAltName']);
- foreach ($subjectAltName as $domain) {
- $domain = trim($domain);
- if (strpos($domain, 'DNS:') === 0) $domain = substr($domain, 4);
- if (!empty($domain)) {
- $domains[] = $domain;
- }
- }
- $domains = array_unique($domains);
- if (empty($domains)) return ['code' => -1, 'msg' => '证书绑定域名不能为空'];
- $issuetime = date('Y-m-d H:i:s', $certInfo['validFrom_time_t']);
- $expiretime = date('Y-m-d H:i:s', $certInfo['validTo_time_t']);
- $issuer = $certInfo['issuer']['CN'];
- return [
- 'code' => 0,
- 'keytype' => $keytype,
- 'keysize' => $keysize,
- 'issuetime' => $issuetime,
- 'expiretime' => $expiretime,
- 'issuer' => $issuer,
- 'domains' => $domains,
- ];
- }
-
- public function order_process()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- if (function_exists("set_time_limit")) {
- @set_time_limit(0);
- }
- if (function_exists("ignore_user_abort")) {
- @ignore_user_abort(true);
- }
- $id = input('post.id/d');
- $reset = input('post.reset/d', 0);
- try {
- $service = new CertOrderService($id);
- if ($reset == 1) {
- $service->reset();
- }
- $retcode = $service->process(true);
- if ($retcode == 3) {
- return json(['code' => 0, 'msg' => '证书已签发成功!']);
- } elseif ($retcode == 1) {
- return json(['code' => 0, 'msg' => '添加DNS记录成功!请等待DNS生效后点击验证']);
- }
- } catch (Exception $e) {
- return json(['code' => -1, 'msg' => $e->getMessage(), 'trace' => $e->getTrace()]);
- }
- }
-
- public function order_form()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
-
- $order = null;
- if ($action == 'edit') {
- $id = input('get.id/d');
- $order = Db::name('cert_order')->where('id', $id)->fieldRaw('id,aid,keytype,keysize,status,fullchain,privatekey')->find();
- if (empty($order)) return $this->alert('error', '证书订单不存在');
- $order['domains'] = Db::name('cert_domain')->where('oid', $order['id'])->order('sort', 'ASC')->column('domain');
- if ($order['aid'] == 0) $order['aid'] = -1;
- }
-
- $accounts = [];
- foreach (Db::name('cert_account')->where('deploy', 0)->select() as $row) {
- if (empty($row['type']) || !isset(CertHelper::$cert_config[$row['type']])) continue;
- $accounts[$row['id']] = ['name' => $row['id'] . '_' . CertHelper::$cert_config[$row['type']]['name'], 'type' => $row['type']];
- if (!empty($row['remark'])) {
- $accounts[$row['id']]['name'] .= '(' . $row['remark'] . ')';
- }
- }
- View::assign('accounts', $accounts);
-
- View::assign('info', $order);
- View::assign('action', $action);
- return View::fetch();
- }
-
- public function deploytask()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $types = [];
- foreach (DeployHelper::$deploy_config as $key => $value) {
- $types[$key] = $value['name'];
- }
- View::assign('types', $types);
- return view();
- }
-
- public function deploy_data()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $domain = $this->request->post('domain', null, 'trim');
- $oid = input('post.oid');
- $aid = input('post.aid', null, 'trim');
- $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');
-
- $select = Db::name('cert_deploy')->alias('A')->leftJoin('cert_account B', 'A.aid = B.id')->leftJoin('cert_order C', 'A.oid = C.id')->leftJoin('cert_account D', 'C.aid = D.id');
- if (!empty($oid)) {
- $select->where('A.oid', $oid);
- } elseif (!empty($domain)) {
- $oids = Db::name('cert_domain')->where('domain', 'like', '%' . $domain . '%')->column('oid');
- $select->whereIn('oid', $oids);
- }
- if (!empty($aid)) {
- $select->where('A.aid', $aid);
- }
- if (!empty($type)) {
- $select->where('B.type', $type);
- }
- if (!isNullOrEmpty($status)) {
- $select->where('A.status', $status);
- }
- if (!empty($remark)) {
- $select->where('A.remark', $remark);
- }
- $total = $select->count();
- $rows = $select->fieldRaw('A.*,B.type,B.remark aremark,B.name aname,D.type certtype,D.id certaid')->order('id', 'desc')->limit($offset, $limit)->select();
-
- $list = [];
- foreach ($rows as $row) {
- if (!empty($row['type']) && isset(DeployHelper::$deploy_config[$row['type']])) {
- $row['typename'] = DeployHelper::$deploy_config[$row['type']]['name'];
- $row['icon'] = DeployHelper::$deploy_config[$row['type']]['icon'];
- }
- if (!empty($row['certtype']) && isset(CertHelper::$cert_config[$row['certtype']])) {
- $row['certtypename'] = CertHelper::$cert_config[$row['certtype']]['name'];
- } else {
- $row['certtypename'] = '手动续期';
- }
- $row['domains'] = Db::name('cert_domain')->where('oid', $row['oid'])->order('sort', 'ASC')->column('domain');
- if ($row['error']) $row['error'] = htmlspecialchars(str_replace("'", "\\'", $row['error']));
- $list[] = $row;
- }
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function deploy_op()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
-
- if ($action == 'add') {
- $task = [
- 'aid' => input('post.aid/d'),
- 'oid' => input('post.oid/d'),
- 'config' => input('post.config', null, 'trim'),
- 'remark' => input('post.remark', null, 'trim'),
- 'addtime' => date('Y-m-d H:i:s'),
- 'status' => 0,
- 'active' => 1
- ];
- if (empty($task['aid']) || empty($task['oid']) || empty($task['config'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
- Db::name('cert_deploy')->insert($task);
- return json(['code' => 0, 'msg' => '添加自动部署任务成功!']);
- } elseif ($action == 'edit') {
- $id = input('post.id/d');
- $row = Db::name('cert_deploy')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => '自动部署任务不存在']);
-
- $task = [
- 'aid' => input('post.aid/d'),
- 'oid' => input('post.oid/d'),
- 'config' => input('post.config', null, 'trim'),
- 'remark' => input('post.remark', null, 'trim'),
- ];
- if (empty($task['aid']) || empty($task['oid']) || empty($task['config'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
- Db::name('cert_deploy')->where('id', $id)->update($task);
- return json(['code' => 0, 'msg' => '修改自动部署任务成功!']);
- } elseif ($action == 'del') {
- $id = input('post.id/d');
- Db::name('cert_deploy')->where('id', $id)->delete();
- return json(['code' => 0]);
- } elseif ($action == 'setactive') {
- $id = input('post.id/d');
- $active = input('post.active/d');
- Db::name('cert_deploy')->where('id', $id)->update(['active' => $active]);
- return json(['code' => 0]);
- } elseif ($action == 'reset') {
- $id = input('post.id/d');
- try {
- $service = new CertDeployService($id);
- $service->reset();
- return json(['code' => 0]);
- } catch (Exception $e) {
- return json(['code' => -1, 'msg' => $e->getMessage()]);
- }
- } elseif ($action == 'show_log') {
- $processid = input('post.processid');
- $file = app()->getRuntimePath() . 'log/' . $processid . '.log';
- if (!file_exists($file)) return json(['code' => -1, 'msg' => '日志文件不存在']);
- return json(['code' => 0, 'data' => file_get_contents($file), 'time' => filemtime($file)]);
- } elseif ($action == 'operation') {
- $ids = input('post.ids');
- $success = 0;
- $certid = 0;
- if (input('post.action') == 'cert') {
- $certid = input('post.certid/d');
- $cert = Db::name('cert_order')->where('id', $certid)->find();
- if (!$cert) return json(['code' => -1, 'msg' => '证书订单不存在']);
- }
- foreach ($ids as $id) {
- if (input('post.act') == 'delete') {
- Db::name('cert_deploy')->where('id', $id)->delete();
- $success++;
- } elseif (input('post.act') == 'reset') {
- try {
- $service = new CertDeployService($id);
- $service->reset();
- $success++;
- } catch (Exception $e) {
- }
- } elseif (input('post.act') == 'open' || input('post.act') == 'close') {
- $active = input('post.act') == 'open' ? 1 : 0;
- Db::name('cert_deploy')->where('id', $id)->update(['active' => $active]);
- $success++;
- } elseif (input('post.act') == 'cert') {
- Db::name('cert_deploy')->where('id', $id)->update(['oid' => $certid]);
- $success++;
- }
- }
- return json(['code' => 0, 'msg' => '成功操作' . $success . '个任务']);
- }
- return json(['code' => -3]);
- }
-
- public function deploy_process()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- if (function_exists("set_time_limit")) {
- @set_time_limit(0);
- }
- if (function_exists("ignore_user_abort")) {
- @ignore_user_abort(true);
- }
- $id = input('post.id/d');
- $reset = input('post.reset/d', 0);
- try {
- $service = new CertDeployService($id);
- if ($reset == 1) {
- $service->reset();
- }
- $service->process(true);
- return json(['code' => 0, 'msg' => 'SSL证书部署任务执行成功!']);
- } catch (Exception $e) {
- return json(['code' => -1, 'msg' => $e->getMessage(), 'trace' => $e->getTrace()]);
- }
- }
-
- public function deploy_form()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
-
- $task = null;
- if ($action == 'edit') {
- $id = input('get.id/d');
- $task = Db::name('cert_deploy')->alias('A')->join('cert_account B', 'A.aid = B.id')->where('A.id', $id)->fieldRaw('A.id,A.aid,A.oid,A.config,A.remark,B.type')->find();
- if (empty($task)) return $this->alert('error', '自动部署任务不存在');
- }
-
- $accounts = [];
- foreach (Db::name('cert_account')->where('deploy', 1)->select() as $row) {
- if (empty($row['type']) || !isset(DeployHelper::$deploy_config[$row['type']])) continue;
- $accounts[$row['id']] = ['name' => $row['id'] . '_' . DeployHelper::$deploy_config[$row['type']]['name'], 'type' => $row['type']];
- if (!empty($row['remark'])) {
- $accounts[$row['id']]['name'] .= '(' . $row['remark'] . ')';
- }
- }
- View::assign('accounts', $accounts);
-
- $orders = [];
- foreach (Db::name('cert_order')->alias('A')->leftJoin('cert_account B', 'A.aid = B.id')->where('status', '<>', 4)->fieldRaw('A.id,A.aid,B.type,B.remark aremark')->order('id', 'desc')->select() as $row) {
- $domains = Db::name('cert_domain')->where('oid', $row['id'])->order('sort', 'ASC')->column('domain');
- $domainstr = count($domains) > 2 ? implode('、', array_slice($domains, 0, 2)) . '等' . count($domains) . '个域名' : implode('、', $domains);
- if ($row['aid'] == 0) {
- $name = $row['id'] . '_' . $domainstr . '(手动续期)';
- } else {
- $name = $row['id'] . '_' . $domainstr . '(' . CertHelper::$cert_config[$row['type']]['name'] . ')';
- }
- $orders[$row['id']] = ['name' => $name];
- }
- View::assign('orders', $orders);
-
- View::assign('info', $task);
- View::assign('action', $action);
- View::assign('typeList', DeployHelper::getList());
- return View::fetch();
- }
-
- public function cname()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $domains = [];
- foreach (Db::name('domain')->field('id,name')->select() as $row) {
- $domains[$row['id']] = $row['name'];
- }
- View::assign('domains', $domains);
- return view();
- }
-
- public function cname_data()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $kw = $this->request->post('kw', null, 'trim');
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
-
- $select = Db::name('cert_cname')->alias('A')->leftJoin('domain B', 'A.did = B.id');
- if (!empty($kw)) {
- $select->whereLike('A.domain', '%' . $kw . '%');
- }
- $total = $select->count();
- $rows = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name cnamedomain')->select();
-
- $list = [];
- foreach ($rows as $row) {
- $row['host'] = $this->getCnameHost($row['domain']);
- $row['record'] = $row['rr'] . '.' . $row['cnamedomain'];
- $list[] = $row;
- }
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- private function getCnameHost($domain)
- {
- $main = getMainDomain($domain);
- if ($main == $domain) {
- return '_acme-challenge';
- } else {
- return '_acme-challenge.' . substr($domain, 0, -strlen($main) - 1);
- }
- }
-
- public function cname_op()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
-
- if ($action == 'add') {
- $data = [
- 'domain' => input('post.domain', null, 'trim'),
- 'rr' => input('post.rr', null, 'trim'),
- 'did' => input('post.did/d'),
- 'addtime' => date('Y-m-d H:i:s'),
- 'status' => 0
- ];
- if (empty($data['domain']) || empty($data['rr']) || empty($data['did'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
- if (!checkDomain($data['domain'])) return json(['code' => -1, 'msg' => '域名格式不正确']);
- if (Db::name('cert_cname')->where('domain', $data['domain'])->find()) {
- return json(['code' => -1, 'msg' => '域名' . $data['domain'] . '已存在']);
- }
- if (Db::name('cert_cname')->where('rr', $data['rr'])->where('did', $data['did'])->find()) {
- return json(['code' => -1, 'msg' => '已存在相同CNAME记录值']);
- }
- Db::name('cert_cname')->insert($data);
- return json(['code' => 0, 'msg' => '添加CMAME代理成功!']);
- } elseif ($action == 'edit') {
- $id = input('post.id/d');
- $row = Db::name('cert_cname')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => 'CMAME代理不存在']);
-
- $data = [
- 'rr' => input('post.rr', null, 'trim'),
- 'did' => input('post.did/d'),
- ];
- if ($row['rr'] != $data['rr'] || $row['did'] != $data['did']) {
- $data['status'] = 0;
- }
- if (empty($data['rr']) || empty($data['did'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
- if (Db::name('cert_cname')->where('rr', $data['rr'])->where('did', $data['did'])->where('id', '<>', $id)->find()) {
- return json(['code' => -1, 'msg' => '已存在相同CNAME记录值']);
- }
- Db::name('cert_cname')->where('id', $id)->update($data);
- return json(['code' => 0, 'msg' => '修改CMAME代理成功!']);
- } elseif ($action == 'del') {
- $id = input('post.id/d');
- Db::name('cert_cname')->where('id', $id)->delete();
- return json(['code' => 0]);
- } elseif ($action == 'check') {
- $id = input('post.id/d');
- $row = Db::name('cert_cname')->alias('A')->join('domain B', 'A.did = B.id')->where('A.id', $id)->field('A.*,B.name cnamedomain')->find();
- if (!$row) return json(['code' => -1, 'msg' => '自动部署任务不存在']);
-
- $status = 1;
- $domain = '_acme-challenge.' . $row['domain'];
- $record = $row['rr'] . '.' . $row['cnamedomain'];
- $result = \app\utils\DnsQueryUtils::get_dns_records($domain, 'CNAME');
- if (!$result || !in_array($record, $result)) {
- $result = \app\utils\DnsQueryUtils::query_dns_doh($domain, 'CNAME');
- if (!$result || !in_array($record, $result)) {
- $status = 0;
- }
- }
- if ($status != $row['status']) {
- Db::name('cert_cname')->where('id', $id)->update(['status' => $status]);
- }
- return json(['code' => 0, 'status' => $status]);
- }
- }
-
- public function certset()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- return View::fetch();
- }
-}
+alert('error', '无权限');
+ return view();
+ }
+
+ public function deployaccount()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ return view();
+ }
+
+ public function account_data()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $deploy = input('get.deploy/d', 0);
+ $kw = $this->request->post('kw', null, 'trim');
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+
+ $select = Db::name('cert_account')->where('deploy', $deploy);
+ if (!empty($kw)) {
+ $select->whereLike('name|remark', '%' . $kw . '%')->whereOr('id', $kw);
+ }
+ $total = $select->count();
+ $rows = $select->order('id', 'desc')->limit($offset, $limit)->select();
+
+ $list = [];
+ foreach ($rows as $row) {
+ if ($deploy == 1) {
+ if (!empty($row['type']) && isset(DeployHelper::$deploy_config[$row['type']])) {
+ $row['typename'] = DeployHelper::$deploy_config[$row['type']]['name'];
+ $row['icon'] = DeployHelper::$deploy_config[$row['type']]['icon'];
+ }
+ } else {
+ if (!empty($row['type']) && isset(CertHelper::$cert_config[$row['type']])) {
+ $row['typename'] = CertHelper::$cert_config[$row['type']]['name'];
+ $row['icon'] = CertHelper::$cert_config[$row['type']]['icon'];
+ }
+ }
+ $list[] = $row;
+ }
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function account_op()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+ $deploy = input('post.deploy/d', 0);
+ $title = $deploy == 1 ? '自动部署账户' : 'SSL证书账户';
+
+ if ($action == 'add') {
+ $type = input('post.type');
+ $name = input('post.name', null, 'trim');
+ $config = input('post.config', null, 'trim');
+ $remark = input('post.remark', null, 'trim');
+ if ($type == 'local') $name = '复制到本机';
+ if (empty($name) || empty($config)) return json(['code' => -1, 'msg' => '必填参数不能为空']);
+ if (Db::name('cert_account')->where('type', $type)->where('config', $config)->find()) {
+ return json(['code' => -1, 'msg' => $title . '已存在']);
+ }
+ Db::startTrans();
+ $id = Db::name('cert_account')->insertGetId([
+ 'type' => $type,
+ 'name' => $name,
+ 'config' => $config,
+ 'remark' => $remark,
+ 'deploy' => $deploy,
+ 'addtime' => date('Y-m-d H:i:s'),
+ ]);
+ try {
+ $this->checkAccount($id, $type, $deploy);
+ Db::commit();
+ return json(['code' => 0, 'msg' => '添加' . $title . '成功!']);
+ } catch (Exception $e) {
+ Db::rollback();
+ return json(['code' => -1, 'msg' => $e->getMessage()]);
+ }
+ } elseif ($action == 'edit') {
+ $id = input('post.id/d');
+ $row = Db::name('cert_account')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => $title . '不存在']);
+ $type = input('post.type');
+ $name = input('post.name', null, 'trim');
+ $config = input('post.config', null, 'trim');
+ $remark = input('post.remark', null, 'trim');
+ if ($type == 'local') $name = '复制到本机';
+ if (empty($name) || empty($config)) return json(['code' => -1, 'msg' => '必填参数不能为空']);
+ if (Db::name('cert_account')->where('type', $type)->where('config', $config)->where('id', '<>', $id)->find()) {
+ return json(['code' => -1, 'msg' => $title . '已存在']);
+ }
+ Db::startTrans();
+ Db::name('cert_account')->where('id', $id)->update([
+ 'type' => $type,
+ 'name' => $name,
+ 'config' => $config,
+ 'remark' => $remark,
+ ]);
+ try {
+ $this->checkAccount($id, $type, $deploy);
+ Db::commit();
+ return json(['code' => 0, 'msg' => '修改' . $title . '成功!']);
+ } catch (Exception $e) {
+ Db::rollback();
+ return json(['code' => -1, 'msg' => $e->getMessage()]);
+ }
+ } elseif ($action == 'del') {
+ $id = input('post.id/d');
+ if ($deploy == 0) {
+ $dcount = DB::name('cert_order')->where('aid', $id)->count();
+ if ($dcount > 0) return json(['code' => -1, 'msg' => '该' . $title . '下存在证书订单,无法删除']);
+ } else {
+ $dcount = DB::name('cert_deploy')->where('aid', $id)->count();
+ if ($dcount > 0) return json(['code' => -1, 'msg' => '该' . $title . '下存在自动部署任务,无法删除']);
+ }
+ Db::name('cert_account')->where('id', $id)->delete();
+ return json(['code' => 0]);
+ }
+ return json(['code' => -3]);
+ }
+
+ public function account_form()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+ $deploy = input('get.deploy/d', 0);
+ $title = $deploy == 1 ? '自动部署账户' : 'SSL证书账户';
+
+ $account = null;
+ if ($action == 'edit') {
+ $id = input('get.id/d');
+ $account = Db::name('cert_account')->where('id', $id)->find();
+ if (empty($account)) return $this->alert('error', $title . '不存在');
+ }
+
+ $typeList = $deploy == 1 ? DeployHelper::getList() : CertHelper::getList();
+ $classList = $deploy == 1 ? DeployHelper::$class_config : CertHelper::$class_config;
+
+ View::assign('title', $title);
+ View::assign('info', $account);
+ View::assign('typeList', $typeList);
+ View::assign('classList', $classList);
+ View::assign('action', $action);
+ View::assign('deploy', $deploy);
+ return View::fetch();
+ }
+
+ private function checkAccount($id, $type, $deploy)
+ {
+ if ($deploy == 0) {
+ $mod = CertHelper::getModel($id);
+ if ($mod) {
+ try {
+ $ext = $mod->register();
+ if (is_array($ext)) {
+ Db::name('cert_account')->where('id', $id)->update(['ext' => json_encode($ext)]);
+ }
+ return true;
+ } catch (Exception $e) {
+ throw new Exception('验证SSL证书账户失败,' . $e->getMessage());
+ }
+ } else {
+ throw new Exception('SSL证书申请模块' . $type . '不存在');
+ }
+ } else {
+ $mod = DeployHelper::getModel($id);
+ if ($mod) {
+ try {
+ $mod->check();
+ return true;
+ } catch (Exception $e) {
+ throw new Exception('验证自动部署账户失败,' . $e->getMessage());
+ }
+ } else {
+ throw new Exception('SSL证书申请模块' . $type . '不存在');
+ }
+ }
+ }
+
+ public function certorder()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $types = [];
+ foreach (CertHelper::$cert_config as $key => $value) {
+ $types[$key] = $value['name'];
+ }
+ View::assign('types', $types);
+ return view();
+ }
+
+ public function order_data()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $domain = $this->request->post('domain', null, 'trim');
+ $id = input('post.id');
+ $aid = input('post.aid', null, 'trim');
+ $type = input('post.type', null, 'trim');
+ $status = input('post.status', null, 'trim');
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+
+ $select = Db::name('cert_order')->alias('A')->leftJoin('cert_account B', 'A.aid = B.id');
+ if (!empty($id)) {
+ $select->where('A.id', $id);
+ } elseif (!empty($domain)) {
+ $oids = Db::name('cert_domain')->where('domain', 'like', '%' . $domain . '%')->column('oid');
+ $select->whereIn('A.id', $oids);
+ }
+ if (!empty($aid)) {
+ $select->where('A.aid', $aid);
+ }
+ 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();
+
+ $list = [];
+ foreach ($rows as $row) {
+ if (!empty($row['type']) && isset(CertHelper::$cert_config[$row['type']])) {
+ $row['typename'] = CertHelper::$cert_config[$row['type']]['name'];
+ $row['icon'] = CertHelper::$cert_config[$row['type']]['icon'];
+ } else {
+ $row['typename'] = null;
+ }
+ $row['domains'] = Db::name('cert_domain')->where('oid', $row['id'])->order('sort', 'ASC')->column('domain');
+ $row['end_day'] = $row['expiretime'] ? ceil((strtotime($row['expiretime']) - time()) / 86400) : null;
+ if ($row['error']) $row['error'] = htmlspecialchars(str_replace("'", "\\'", $row['error']));
+ $list[] = $row;
+ }
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function order_info()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $id = input('post.id/d');
+ $row = Db::name('cert_order')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => '证书订单不存在']);
+ $pfx = CertHelper::getPfx($row['fullchain'], $row['privatekey']);
+ $row['pfx'] = base64_encode($pfx);
+ return json(['code' => 0, 'data' => ['id' => $row['id'], 'crt' => $row['fullchain'], 'key' => $row['privatekey'], 'pfx' => $row['pfx'], 'issuetime' => $row['issuetime'], 'expiretime' => $row['expiretime'], 'domains' => Db::name('cert_domain')->where('oid', $row['id'])->order('sort', 'ASC')->column('domain')]]);
+ }
+
+ public function order_op()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+
+ if ($action == 'get') {
+ $id = input('post.id/d');
+ $row = Db::name('cert_order')->where('id', $id)->field('fullchain,privatekey')->find();
+ if (!$row) return $this->alert('error', '证书订单不存在');
+ $pfx = CertHelper::getPfx($row['fullchain'], $row['privatekey']);
+ $row['pfx'] = base64_encode($pfx);
+ return json(['code' => 0, 'data' => $row]);
+ } elseif ($action == 'add') {
+ $aid = input('post.aid/d');
+
+ if ($aid == -1) {
+ $fullchain = input('post.fullchain', null, 'trim');
+ $privatekey = input('post.privatekey', null, 'trim');
+ $certInfo = $this->parse_cert_key($fullchain, $privatekey);
+ if ($certInfo['code'] == -1) return json($certInfo);
+ $domains = $certInfo['domains'];
+
+ $order_ids = Db::name('cert_order')->where('issuetime', $certInfo['issuetime'])->column('id');
+ if (!empty($order_ids)) {
+ foreach ($order_ids as $order_id) {
+ $domains2 = Db::name('cert_domain')->where('oid', $order_id)->column('domain');
+ if (arrays_are_equal($domains2, $domains)) {
+ return json(['code' => -1, 'msg' => '该证书已存在,无需重复添加']);
+ }
+ }
+ }
+
+ $order = [
+ 'aid' => 0,
+ 'keytype' => $certInfo['keytype'],
+ 'keysize' => $certInfo['keysize'],
+ 'addtime' => date('Y-m-d H:i:s'),
+ 'updatetime' => date('Y-m-d H:i:s'),
+ 'issuetime' => $certInfo['issuetime'],
+ 'expiretime' => $certInfo['expiretime'],
+ 'issuer' => $certInfo['issuer'],
+ 'status' => 3,
+ 'isauto' => 1,
+ 'fullchain' => $fullchain,
+ 'privatekey' => $privatekey,
+ ];
+ } else {
+ $order = [
+ 'aid' => $aid,
+ 'keytype' => input('post.keytype'),
+ 'keysize' => input('post.keysize'),
+ 'addtime' => date('Y-m-d H:i:s'),
+ 'issuer' => '',
+ 'status' => 0,
+ 'isauto' => 1,
+ ];
+ $domains = input('post.domains', [], 'trim');
+ $domains = array_map('trim', $domains);
+ $domains = array_filter($domains, function ($v) {
+ return !empty($v);
+ });
+ $domains = array_unique($domains);
+ if (empty($domains)) return json(['code' => -1, 'msg' => '绑定域名不能为空']);
+ $res = $this->check_order($order, $domains);
+ if (is_array($res)) return json($res);
+ }
+ if (empty($order['keytype']) || empty($order['keysize'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
+
+ Db::startTrans();
+ $id = Db::name('cert_order')->insertGetId($order);
+ $domainList = [];
+ $i = 1;
+ foreach ($domains as $domain) {
+ $domainList[] = [
+ 'oid' => $id,
+ 'domain' => convertDomainToAscii($domain),
+ 'sort' => $i++,
+ ];
+ }
+ Db::name('cert_domain')->insertAll($domainList);
+ Db::commit();
+ return json(['code' => 0, 'msg' => '添加证书订单成功!']);
+ } elseif ($action == 'edit') {
+ $id = input('post.id/d');
+ $row = Db::name('cert_order')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => '证书订单不存在']);
+
+ $aid = input('post.aid/d');
+ if ($aid == -1) {
+ $fullchain = input('post.fullchain', null, 'trim');
+ $privatekey = input('post.privatekey', null, 'trim');
+ $certInfo = $this->parse_cert_key($fullchain, $privatekey);
+ if ($certInfo['code'] == -1) return json($certInfo);
+ $domains = $certInfo['domains'];
+
+ $order = [
+ 'aid' => 0,
+ 'keytype' => $certInfo['keytype'],
+ 'keysize' => $certInfo['keysize'],
+ 'updatetime' => date('Y-m-d H:i:s'),
+ 'issuetime' => $certInfo['issuetime'],
+ 'expiretime' => $certInfo['expiretime'],
+ 'issuer' => $certInfo['issuer'],
+ 'status' => 3,
+ 'issend' => 0,
+ 'fullchain' => $fullchain,
+ 'privatekey' => $privatekey,
+ ];
+ } else {
+ $domains = input('post.domains', [], 'trim');
+ $order = [
+ 'aid' => $aid,
+ 'keytype' => input('post.keytype'),
+ 'keysize' => input('post.keysize'),
+ 'updatetime' => date('Y-m-d H:i:s'),
+ ];
+ $domains = array_map('trim', $domains);
+ $domains = array_filter($domains, function ($v) {
+ return !empty($v);
+ });
+ $domains = array_unique($domains);
+ if (empty($domains)) return json(['code' => -1, 'msg' => '绑定域名不能为空']);
+ $res = $this->check_order($order, $domains);
+ if (is_array($res)) return json($res);
+ }
+ if (empty($order['keytype']) || empty($order['keysize'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
+
+ Db::startTrans();
+ Db::name('cert_order')->where('id', $id)->update($order);
+ Db::name('cert_domain')->where('oid', $id)->delete();
+ $domainList = [];
+ $i = 1;
+ foreach ($domains as $domain) {
+ $domainList[] = [
+ 'oid' => $id,
+ 'domain' => convertDomainToAscii($domain),
+ 'sort' => $i++,
+ ];
+ }
+ Db::name('cert_domain')->insertAll($domainList);
+ Db::commit();
+ return json(['code' => 0, 'msg' => '修改证书订单成功!']);
+ } elseif ($action == 'del') {
+ $id = input('post.id/d');
+ $dcount = DB::name('cert_deploy')->where('oid', $id)->count();
+ if ($dcount > 0) return json(['code' => -1, 'msg' => '该证书关联了自动部署任务,无法删除']);
+ try {
+ (new CertOrderService($id))->cancel();
+ } catch (Exception $e) {
+ }
+ Db::name('cert_order')->where('id', $id)->delete();
+ Db::name('cert_domain')->where('oid', $id)->delete();
+ return json(['code' => 0]);
+ } elseif ($action == 'setauto') {
+ $id = input('post.id/d');
+ $isauto = input('post.isauto/d');
+ Db::name('cert_order')->where('id', $id)->update(['isauto' => $isauto]);
+ return json(['code' => 0]);
+ } elseif ($action == 'reset') {
+ $id = input('post.id/d');
+ try {
+ $service = new CertOrderService($id);
+ $service->cancel();
+ $service->reset();
+ return json(['code' => 0]);
+ } catch (Exception $e) {
+ return json(['code' => -1, 'msg' => $e->getMessage()]);
+ }
+ } elseif ($action == 'revoke') {
+ $id = input('post.id/d');
+ try {
+ $service = new CertOrderService($id);
+ $service->revoke();
+ return json(['code' => 0]);
+ } catch (Exception $e) {
+ return json(['code' => -1, 'msg' => $e->getMessage()]);
+ }
+ } elseif ($action == 'show_log') {
+ $processid = input('post.processid');
+ $file = app()->getRuntimePath() . 'log/' . $processid . '.log';
+ if (!file_exists($file)) return json(['code' => -1, 'msg' => '日志文件不存在']);
+ return json(['code' => 0, 'data' => file_get_contents($file), 'time' => filemtime($file)]);
+ } elseif ($action == 'operation') {
+ $ids = input('post.ids');
+ $success = 0;
+ foreach ($ids as $id) {
+ if (input('post.act') == 'delete') {
+ $dcount = DB::name('cert_deploy')->where('oid', $id)->count();
+ if ($dcount > 0) continue;
+ try {
+ (new CertOrderService($id))->cancel();
+ } catch (Exception $e) {
+ }
+ Db::name('cert_order')->where('id', $id)->delete();
+ Db::name('cert_domain')->where('oid', $id)->delete();
+ $success++;
+ } elseif (input('post.act') == 'reset') {
+ try {
+ $service = new CertOrderService($id);
+ $service->cancel();
+ $service->reset();
+ $success++;
+ } catch (Exception $e) {
+ }
+ } elseif (input('post.act') == 'open' || input('post.act') == 'close') {
+ $isauto = input('post.act') == 'open' ? 1 : 0;
+ Db::name('cert_order')->where('id', $id)->update(['isauto' => $isauto]);
+ $success++;
+ }
+ }
+ return json(['code' => 0, 'msg' => '成功操作' . $success . '个证书订单']);
+ }
+ return json(['code' => -3]);
+ }
+
+ private function check_order($order, $domains)
+ {
+ $account = Db::name('cert_account')->where('id', $order['aid'])->find();
+ if (!$account) return ['code' => -1, 'msg' => 'SSL证书账户不存在'];
+ $max_domains = CertHelper::$cert_config[$account['type']]['max_domains'];
+ $wildcard = CertHelper::$cert_config[$account['type']]['wildcard'];
+ $cname = CertHelper::$cert_config[$account['type']]['cname'];
+ if (count($domains) > $max_domains) {
+ if (!(count($domains) == 2 && $max_domains == 1 && ltrim($domains[0], 'www.') == ltrim($domains[1], 'www.'))) {
+ return ['code' => -1, 'msg' => '域名数量不能超过' . $max_domains . '个'];
+ }
+ }
+
+ foreach ($domains as $domain) {
+ if (!$wildcard && strpos($domain, '*') !== false) return ['code' => -1, 'msg' => '该证书账户类型不支持泛域名'];
+ $mainDomain = getMainDomain($domain);
+ $drow = Db::name('domain')->where('name', $mainDomain)->find();
+ if (!$drow) {
+ if (substr($domain, 0, 2) == '*.') $domain = substr($domain, 2);
+ if (!$cname || !Db::name('cert_cname')->where('domain', $domain)->where('status', 1)->find()) {
+ return ['code' => -1, 'msg' => '域名' . $domain . '未在本系统添加'];
+ }
+ }
+ }
+ return true;
+ }
+
+ private function parse_cert_key($fullchain, $privatekey)
+ {
+ if (!openssl_x509_read($fullchain)) return ['code' => -1, 'msg' => '证书内容填写错误'];
+ if (!openssl_get_privatekey($privatekey)) return ['code' => -1, 'msg' => '私钥内容填写错误'];
+ if (!openssl_x509_check_private_key($fullchain, $privatekey)) return ['code' => -1, 'msg' => 'SSL证书与私钥不匹配'];
+ $certInfo = openssl_x509_parse($fullchain, true);
+ if (!$certInfo || !isset($certInfo['extensions']['subjectAltName'])) return ['code' => -1, 'msg' => '证书内容解析失败'];
+
+ $pubKey = openssl_pkey_get_public($fullchain);
+ if (!$pubKey) return ['code' => -1, 'msg' => '证书公钥解析失败'];
+ $keyDetails = openssl_pkey_get_details($pubKey);
+ $keytype = null;
+ $keysize = 0;
+ switch ($keyDetails['type']) {
+ case OPENSSL_KEYTYPE_RSA:
+ $keytype = 'RSA';
+ $keysize = $keyDetails['bits'];
+ break;
+ case OPENSSL_KEYTYPE_EC:
+ $keytype = 'ECC';
+ $keysize = $keyDetails['bits'];
+ break;
+ case OPENSSL_KEYTYPE_DSA:
+ $keytype = 'DSA';
+ $keysize = $keyDetails['bits'];
+ break;
+ default:
+ $keytype = 'Unknown';
+ }
+
+ $domains = [];
+ $subjectAltName = explode(',', $certInfo['extensions']['subjectAltName']);
+ foreach ($subjectAltName as $domain) {
+ $domain = trim($domain);
+ if (strpos($domain, 'DNS:') === 0) $domain = substr($domain, 4);
+ if (!empty($domain)) {
+ $domains[] = $domain;
+ }
+ }
+ $domains = array_unique($domains);
+ if (empty($domains)) return ['code' => -1, 'msg' => '证书绑定域名不能为空'];
+ $issuetime = date('Y-m-d H:i:s', $certInfo['validFrom_time_t']);
+ $expiretime = date('Y-m-d H:i:s', $certInfo['validTo_time_t']);
+ $issuer = $certInfo['issuer']['CN'];
+ return [
+ 'code' => 0,
+ 'keytype' => $keytype,
+ 'keysize' => $keysize,
+ 'issuetime' => $issuetime,
+ 'expiretime' => $expiretime,
+ 'issuer' => $issuer,
+ 'domains' => $domains,
+ ];
+ }
+
+ public function order_process()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ if (function_exists("set_time_limit")) {
+ @set_time_limit(0);
+ }
+ if (function_exists("ignore_user_abort")) {
+ @ignore_user_abort(true);
+ }
+ $id = input('post.id/d');
+ $reset = input('post.reset/d', 0);
+ try {
+ $service = new CertOrderService($id);
+ if ($reset == 1) {
+ $service->reset();
+ }
+ $retcode = $service->process(true);
+ if ($retcode == 3) {
+ return json(['code' => 0, 'msg' => '证书已签发成功!']);
+ } elseif ($retcode == 1) {
+ return json(['code' => 0, 'msg' => '添加DNS记录成功!请等待DNS生效后点击验证']);
+ }
+ } catch (Exception $e) {
+ return json(['code' => -1, 'msg' => $e->getMessage(), 'trace' => $e->getTrace()]);
+ }
+ }
+
+ public function order_form()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+
+ $order = null;
+ if ($action == 'edit') {
+ $id = input('get.id/d');
+ $order = Db::name('cert_order')->where('id', $id)->fieldRaw('id,aid,keytype,keysize,status,fullchain,privatekey')->find();
+ if (empty($order)) return $this->alert('error', '证书订单不存在');
+ $order['domains'] = Db::name('cert_domain')->where('oid', $order['id'])->order('sort', 'ASC')->column('domain');
+ if ($order['aid'] == 0) $order['aid'] = -1;
+ }
+
+ $accounts = [];
+ foreach (Db::name('cert_account')->where('deploy', 0)->select() as $row) {
+ if (empty($row['type']) || !isset(CertHelper::$cert_config[$row['type']])) continue;
+ $accounts[$row['id']] = ['name' => $row['id'] . '_' . CertHelper::$cert_config[$row['type']]['name'], 'type' => $row['type']];
+ if (!empty($row['remark'])) {
+ $accounts[$row['id']]['name'] .= '(' . $row['remark'] . ')';
+ }
+ }
+ View::assign('accounts', $accounts);
+
+ View::assign('info', $order);
+ View::assign('action', $action);
+ return View::fetch();
+ }
+
+ public function deploytask()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $types = [];
+ foreach (DeployHelper::$deploy_config as $key => $value) {
+ $types[$key] = $value['name'];
+ }
+ View::assign('types', $types);
+ return view();
+ }
+
+ public function deploy_data()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $domain = $this->request->post('domain', null, 'trim');
+ $oid = input('post.oid');
+ $aid = input('post.aid', null, 'trim');
+ $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');
+
+ $select = Db::name('cert_deploy')->alias('A')->leftJoin('cert_account B', 'A.aid = B.id')->leftJoin('cert_order C', 'A.oid = C.id')->leftJoin('cert_account D', 'C.aid = D.id');
+ if (!empty($oid)) {
+ $select->where('A.oid', $oid);
+ } elseif (!empty($domain)) {
+ $oids = Db::name('cert_domain')->where('domain', 'like', '%' . $domain . '%')->column('oid');
+ $select->whereIn('oid', $oids);
+ }
+ if (!empty($aid)) {
+ $select->where('A.aid', $aid);
+ }
+ if (!empty($type)) {
+ $select->where('B.type', $type);
+ }
+ if (!isNullOrEmpty($status)) {
+ $select->where('A.status', $status);
+ }
+ if (!empty($remark)) {
+ $select->where('A.remark', $remark);
+ }
+ $total = $select->count();
+ $rows = $select->fieldRaw('A.*,B.type,B.remark aremark,B.name aname,D.type certtype,D.id certaid')->order('id', 'desc')->limit($offset, $limit)->select();
+
+ $list = [];
+ foreach ($rows as $row) {
+ if (!empty($row['type']) && isset(DeployHelper::$deploy_config[$row['type']])) {
+ $row['typename'] = DeployHelper::$deploy_config[$row['type']]['name'];
+ $row['icon'] = DeployHelper::$deploy_config[$row['type']]['icon'];
+ }
+ if (!empty($row['certtype']) && isset(CertHelper::$cert_config[$row['certtype']])) {
+ $row['certtypename'] = CertHelper::$cert_config[$row['certtype']]['name'];
+ } else {
+ $row['certtypename'] = '手动续期';
+ }
+ $row['domains'] = Db::name('cert_domain')->where('oid', $row['oid'])->order('sort', 'ASC')->column('domain');
+ if ($row['error']) $row['error'] = htmlspecialchars(str_replace("'", "\\'", $row['error']));
+ $list[] = $row;
+ }
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function deploy_op()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+
+ if ($action == 'add') {
+ $task = [
+ 'aid' => input('post.aid/d'),
+ 'oid' => input('post.oid/d'),
+ 'config' => input('post.config', null, 'trim'),
+ 'remark' => input('post.remark', null, 'trim'),
+ 'addtime' => date('Y-m-d H:i:s'),
+ 'status' => 0,
+ 'active' => 1
+ ];
+ if (empty($task['aid']) || empty($task['oid']) || empty($task['config'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
+ Db::name('cert_deploy')->insert($task);
+ return json(['code' => 0, 'msg' => '添加自动部署任务成功!']);
+ } elseif ($action == 'edit') {
+ $id = input('post.id/d');
+ $row = Db::name('cert_deploy')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => '自动部署任务不存在']);
+
+ $task = [
+ 'aid' => input('post.aid/d'),
+ 'oid' => input('post.oid/d'),
+ 'config' => input('post.config', null, 'trim'),
+ 'remark' => input('post.remark', null, 'trim'),
+ ];
+ if (empty($task['aid']) || empty($task['oid']) || empty($task['config'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
+ Db::name('cert_deploy')->where('id', $id)->update($task);
+ return json(['code' => 0, 'msg' => '修改自动部署任务成功!']);
+ } elseif ($action == 'del') {
+ $id = input('post.id/d');
+ Db::name('cert_deploy')->where('id', $id)->delete();
+ return json(['code' => 0]);
+ } elseif ($action == 'setactive') {
+ $id = input('post.id/d');
+ $active = input('post.active/d');
+ Db::name('cert_deploy')->where('id', $id)->update(['active' => $active]);
+ return json(['code' => 0]);
+ } elseif ($action == 'reset') {
+ $id = input('post.id/d');
+ try {
+ $service = new CertDeployService($id);
+ $service->reset();
+ return json(['code' => 0]);
+ } catch (Exception $e) {
+ return json(['code' => -1, 'msg' => $e->getMessage()]);
+ }
+ } elseif ($action == 'show_log') {
+ $processid = input('post.processid');
+ $file = app()->getRuntimePath() . 'log/' . $processid . '.log';
+ if (!file_exists($file)) return json(['code' => -1, 'msg' => '日志文件不存在']);
+ return json(['code' => 0, 'data' => file_get_contents($file), 'time' => filemtime($file)]);
+ } elseif ($action == 'operation') {
+ $ids = input('post.ids');
+ $success = 0;
+ $certid = 0;
+ if (input('post.action') == 'cert') {
+ $certid = input('post.certid/d');
+ $cert = Db::name('cert_order')->where('id', $certid)->find();
+ if (!$cert) return json(['code' => -1, 'msg' => '证书订单不存在']);
+ }
+ foreach ($ids as $id) {
+ if (input('post.act') == 'delete') {
+ Db::name('cert_deploy')->where('id', $id)->delete();
+ $success++;
+ } elseif (input('post.act') == 'reset') {
+ try {
+ $service = new CertDeployService($id);
+ $service->reset();
+ $success++;
+ } catch (Exception $e) {
+ }
+ } elseif (input('post.act') == 'open' || input('post.act') == 'close') {
+ $active = input('post.act') == 'open' ? 1 : 0;
+ Db::name('cert_deploy')->where('id', $id)->update(['active' => $active]);
+ $success++;
+ } elseif (input('post.act') == 'cert') {
+ Db::name('cert_deploy')->where('id', $id)->update(['oid' => $certid]);
+ $success++;
+ }
+ }
+ return json(['code' => 0, 'msg' => '成功操作' . $success . '个任务']);
+ }
+ return json(['code' => -3]);
+ }
+
+ public function deploy_process()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ if (function_exists("set_time_limit")) {
+ @set_time_limit(0);
+ }
+ if (function_exists("ignore_user_abort")) {
+ @ignore_user_abort(true);
+ }
+ $id = input('post.id/d');
+ $reset = input('post.reset/d', 0);
+ try {
+ $service = new CertDeployService($id);
+ if ($reset == 1) {
+ $service->reset();
+ }
+ $service->process(true);
+ return json(['code' => 0, 'msg' => 'SSL证书部署任务执行成功!']);
+ } catch (Exception $e) {
+ return json(['code' => -1, 'msg' => $e->getMessage(), 'trace' => $e->getTrace()]);
+ }
+ }
+
+ public function deploy_form()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+
+ $task = null;
+ if ($action == 'edit') {
+ $id = input('get.id/d');
+ $task = Db::name('cert_deploy')->alias('A')->join('cert_account B', 'A.aid = B.id')->where('A.id', $id)->fieldRaw('A.id,A.aid,A.oid,A.config,A.remark,B.type')->find();
+ if (empty($task)) return $this->alert('error', '自动部署任务不存在');
+ }
+
+ $accounts = [];
+ foreach (Db::name('cert_account')->where('deploy', 1)->select() as $row) {
+ if (empty($row['type']) || !isset(DeployHelper::$deploy_config[$row['type']])) continue;
+ $accounts[$row['id']] = ['name' => $row['id'] . '_' . DeployHelper::$deploy_config[$row['type']]['name'], 'type' => $row['type']];
+ if (!empty($row['remark'])) {
+ $accounts[$row['id']]['name'] .= '(' . $row['remark'] . ')';
+ }
+ }
+ View::assign('accounts', $accounts);
+
+ $orders = [];
+ foreach (Db::name('cert_order')->alias('A')->leftJoin('cert_account B', 'A.aid = B.id')->where('status', '<>', 4)->fieldRaw('A.id,A.aid,B.type,B.remark aremark')->order('id', 'desc')->select() as $row) {
+ $domains = Db::name('cert_domain')->where('oid', $row['id'])->order('sort', 'ASC')->column('domain');
+ $domainstr = count($domains) > 2 ? implode('、', array_slice($domains, 0, 2)) . '等' . count($domains) . '个域名' : implode('、', $domains);
+ if ($row['aid'] == 0) {
+ $name = $row['id'] . '_' . $domainstr . '(手动续期)';
+ } else {
+ $name = $row['id'] . '_' . $domainstr . '(' . CertHelper::$cert_config[$row['type']]['name'] . ')';
+ }
+ $orders[$row['id']] = ['name' => $name];
+ }
+ View::assign('orders', $orders);
+
+ View::assign('info', $task);
+ View::assign('action', $action);
+ View::assign('typeList', DeployHelper::getList());
+ return View::fetch();
+ }
+
+ public function cname()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $domains = [];
+ foreach (Db::name('domain')->field('id,name')->select() as $row) {
+ $domains[$row['id']] = $row['name'];
+ }
+ View::assign('domains', $domains);
+ return view();
+ }
+
+ public function cname_data()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $kw = $this->request->post('kw', null, 'trim');
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+
+ $select = Db::name('cert_cname')->alias('A')->leftJoin('domain B', 'A.did = B.id');
+ if (!empty($kw)) {
+ $select->whereLike('A.domain', '%' . $kw . '%');
+ }
+ $total = $select->count();
+ $rows = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name cnamedomain')->select();
+
+ $list = [];
+ foreach ($rows as $row) {
+ $row['host'] = $this->getCnameHost($row['domain']);
+ $row['record'] = $row['rr'] . '.' . $row['cnamedomain'];
+ $list[] = $row;
+ }
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ private function getCnameHost($domain)
+ {
+ $main = getMainDomain($domain);
+ if ($main == $domain) {
+ return '_acme-challenge';
+ } else {
+ return '_acme-challenge.' . substr($domain, 0, -strlen($main) - 1);
+ }
+ }
+
+ public function cname_op()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+
+ if ($action == 'add') {
+ $data = [
+ 'domain' => input('post.domain', null, 'trim'),
+ 'rr' => input('post.rr', null, 'trim'),
+ 'did' => input('post.did/d'),
+ 'addtime' => date('Y-m-d H:i:s'),
+ 'status' => 0
+ ];
+ if (empty($data['domain']) || empty($data['rr']) || empty($data['did'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
+ if (!checkDomain($data['domain'])) return json(['code' => -1, 'msg' => '域名格式不正确']);
+ if (Db::name('cert_cname')->where('domain', $data['domain'])->find()) {
+ return json(['code' => -1, 'msg' => '域名' . $data['domain'] . '已存在']);
+ }
+ if (Db::name('cert_cname')->where('rr', $data['rr'])->where('did', $data['did'])->find()) {
+ return json(['code' => -1, 'msg' => '已存在相同CNAME记录值']);
+ }
+ Db::name('cert_cname')->insert($data);
+ return json(['code' => 0, 'msg' => '添加CMAME代理成功!']);
+ } elseif ($action == 'edit') {
+ $id = input('post.id/d');
+ $row = Db::name('cert_cname')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => 'CMAME代理不存在']);
+
+ $data = [
+ 'rr' => input('post.rr', null, 'trim'),
+ 'did' => input('post.did/d'),
+ ];
+ if ($row['rr'] != $data['rr'] || $row['did'] != $data['did']) {
+ $data['status'] = 0;
+ }
+ if (empty($data['rr']) || empty($data['did'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
+ if (Db::name('cert_cname')->where('rr', $data['rr'])->where('did', $data['did'])->where('id', '<>', $id)->find()) {
+ return json(['code' => -1, 'msg' => '已存在相同CNAME记录值']);
+ }
+ Db::name('cert_cname')->where('id', $id)->update($data);
+ return json(['code' => 0, 'msg' => '修改CMAME代理成功!']);
+ } elseif ($action == 'del') {
+ $id = input('post.id/d');
+ Db::name('cert_cname')->where('id', $id)->delete();
+ return json(['code' => 0]);
+ } elseif ($action == 'check') {
+ $id = input('post.id/d');
+ $row = Db::name('cert_cname')->alias('A')->join('domain B', 'A.did = B.id')->where('A.id', $id)->field('A.*,B.name cnamedomain')->find();
+ if (!$row) return json(['code' => -1, 'msg' => '自动部署任务不存在']);
+
+ $status = 1;
+ $domain = '_acme-challenge.' . $row['domain'];
+ $record = $row['rr'] . '.' . $row['cnamedomain'];
+ $result = \app\utils\DnsQueryUtils::get_dns_records($domain, 'CNAME');
+ if (!$result || !in_array($record, $result)) {
+ $result = \app\utils\DnsQueryUtils::query_dns_doh($domain, 'CNAME');
+ if (!$result || !in_array($record, $result)) {
+ $status = 0;
+ }
+ }
+ if ($status != $row['status']) {
+ Db::name('cert_cname')->where('id', $id)->update(['status' => $status]);
+ }
+ return json(['code' => 0, 'status' => $status]);
+ }
+ }
+
+ public function certset()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ return View::fetch();
+ }
+}
diff --git a/app/controller/Dmonitor.php b/app/controller/Dmonitor.php
index c69b0a7..8b0b617 100644
--- a/app/controller/Dmonitor.php
+++ b/app/controller/Dmonitor.php
@@ -1,266 +1,266 @@
-alert('error', '无权限');
- $switch_count = Db::name('dmlog')->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->count();
- $fail_count = Db::name('dmlog')->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->where('action', 1)->count();
-
- $run_time = config_get('run_time', null, true);
- $run_state = $run_time ? (time() - strtotime($run_time) > 10 ? 0 : 1) : 0;
- View::assign('info', [
- 'run_count' => config_get('run_count', null, true) ?? 0,
- 'run_time' => $run_time ?? '无',
- 'run_state' => $run_state,
- 'run_error' => config_get('run_error', null, true),
- 'switch_count' => $switch_count,
- 'fail_count' => $fail_count,
- 'swoole' => extension_loaded('swoole') ? '已安装' : '未安装',
- ]);
- return View::fetch();
- }
-
- public function task()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- return View::fetch();
- }
-
- public function task_data()
- {
- if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
- $type = input('post.type/d', 1);
- $status = input('post.status', null);
- $kw = input('post.kw', null, 'trim');
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
-
- $select = Db::name('dmtask')->alias('A')->join('domain B', 'A.did = B.id');
- if (!empty($kw)) {
- if ($type == 1) {
- $select->whereLike('rr|B.name', '%' . $kw . '%');
- } elseif ($type == 2) {
- $select->where('recordid', $kw);
- } elseif ($type == 3) {
- $select->where('main_value', $kw);
- } elseif ($type == 4) {
- $select->where('backup_value', $kw);
- } elseif ($type == 5) {
- $select->whereLike('remark', '%' . $kw . '%');
- }
- }
- if (!isNullOrEmpty($status)) {
- $select->where('status', intval($status));
- }
- $total = $select->count();
- $list = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name domain')->select()->toArray();
-
- foreach ($list as &$row) {
- $row['addtimestr'] = date('Y-m-d H:i:s', $row['addtime']);
- $row['checktimestr'] = $row['checktime'] > 0 ? date('Y-m-d H:i:s', $row['checktime']) : '未运行';
- }
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function task_op()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
- if ($action == 'add') {
- $task = [
- 'did' => input('post.did/d'),
- 'rr' => input('post.rr', null, 'trim'),
- 'recordid' => input('post.recordid', null, 'trim'),
- 'type' => input('post.type/d'),
- 'main_value' => input('post.main_value', null, 'trim'),
- 'backup_value' => input('post.backup_value', null, 'trim'),
- 'checktype' => input('post.checktype/d'),
- 'checkurl' => input('post.checkurl', null, 'trim'),
- 'tcpport' => !empty(input('post.tcpport')) ? input('post.tcpport/d') : null,
- 'frequency' => input('post.frequency/d'),
- '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(),
- 'active' => 1
- ];
-
- if (empty($task['did']) || empty($task['rr']) || empty($task['recordid']) || empty($task['main_value']) || empty($task['frequency']) || empty($task['cycle'])) {
- return json(['code' => -1, 'msg' => '必填项不能为空']);
- }
- if ($task['checktype'] > 0 && $task['timeout'] > $task['frequency']) {
- return json(['code' => -1, 'msg' => '为保障容灾切换任务正常运行,最大超时时间不能大于检测间隔']);
- }
- if ($task['type'] == 2 && $task['backup_value'] == $task['main_value']) {
- return json(['code' => -1, 'msg' => '主备地址不能相同']);
- }
- if (Db::name('dmtask')->where('recordid', $task['recordid'])->find()) {
- return json(['code' => -1, 'msg' => '当前容灾切换策略已存在']);
- }
- Db::name('dmtask')->insert($task);
- return json(['code' => 0, 'msg' => '添加成功']);
- } elseif ($action == 'edit') {
- $id = input('post.id/d');
- $task = [
- 'did' => input('post.did/d'),
- 'rr' => input('post.rr', null, 'trim'),
- 'recordid' => input('post.recordid', null, 'trim'),
- 'type' => input('post.type/d'),
- 'main_value' => input('post.main_value', null, 'trim'),
- 'backup_value' => input('post.backup_value', null, 'trim'),
- 'checktype' => input('post.checktype/d'),
- 'checkurl' => input('post.checkurl', null, 'trim'),
- 'tcpport' => !empty(input('post.tcpport')) ? input('post.tcpport/d') : null,
- 'frequency' => input('post.frequency/d'),
- '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'),
- ];
-
- if (empty($task['did']) || empty($task['rr']) || empty($task['recordid']) || empty($task['main_value']) || empty($task['frequency']) || empty($task['cycle'])) {
- return json(['code' => -1, 'msg' => '必填项不能为空']);
- }
- if ($task['checktype'] > 0 && $task['timeout'] > $task['frequency']) {
- return json(['code' => -1, 'msg' => '为保障容灾切换任务正常运行,最大超时时间不能大于检测间隔']);
- }
- if ($task['type'] == 2 && $task['backup_value'] == $task['main_value']) {
- return json(['code' => -1, 'msg' => '主备地址不能相同']);
- }
- if (Db::name('dmtask')->where('recordid', $task['recordid'])->where('id', '<>', $id)->find()) {
- return json(['code' => -1, 'msg' => '当前容灾切换策略已存在']);
- }
- Db::name('dmtask')->where('id', $id)->update($task);
- return json(['code' => 0, 'msg' => '修改成功']);
- } elseif ($action == 'setactive') {
- $id = input('post.id/d');
- $active = input('post.active/d');
- Db::name('dmtask')->where('id', $id)->update(['active' => $active]);
- return json(['code' => 0, 'msg' => '设置成功']);
- } elseif ($action == 'del') {
- $id = input('post.id/d');
- Db::name('dmtask')->where('id', $id)->delete();
- Db::name('dmlog')->where('taskid', $id)->delete();
- return json(['code' => 0, 'msg' => '删除成功']);
- } elseif ($action == 'operation') {
- $ids = input('post.ids');
- $success = 0;
- foreach ($ids as $id) {
- if (input('post.act') == 'delete') {
- Db::name('dmtask')->where('id', $id)->delete();
- Db::name('dmlog')->where('taskid', $id)->delete();
- $success++;
- } elseif (input('post.act') == 'retry') {
- Db::name('dmtask')->where('id', $id)->update(['checknexttime' => time()]);
- $success++;
- } elseif (input('post.act') == 'open' || input('post.act') == 'close') {
- $isauto = input('post.act') == 'open' ? 1 : 0;
- Db::name('dmtask')->where('id', $id)->update(['active' => $isauto]);
- $success++;
- }
- }
- return json(['code' => 0, 'msg' => '成功操作' . $success . '个容灾切换策略']);
- } else {
- return json(['code' => -1, 'msg' => '参数错误']);
- }
- }
-
- public function taskform()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
- $task = null;
- if ($action == 'edit') {
- $id = input('get.id/d');
- $task = Db::name('dmtask')->where('id', $id)->find();
- if (empty($task)) return $this->alert('error', '切换策略不存在');
- }
-
- $domains = [];
- $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);
-
- View::assign('info', $task);
- View::assign('action', $action);
- View::assign('support_ping', function_exists('exec') ? '1' : '0');
- return View::fetch();
- }
-
- public function taskinfo()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $id = input('param.id/d');
- $task = Db::name('dmtask')->where('id', $id)->find();
- if (empty($task)) return $this->alert('error', '切换策略不存在');
-
- $switch_count = Db::name('dmlog')->where('taskid', $id)->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->count();
- $fail_count = Db::name('dmlog')->where('taskid', $id)->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->where('action', 1)->count();
-
- $task['switch_count'] = $switch_count;
- $task['fail_count'] = $fail_count;
- if ($task['type'] == 3) {
- $task['action_name'] = ['未知', '开启解析', '暂停解析'];
- } elseif ($task['type'] == 2) {
- $task['action_name'] = ['未知', '切换备用解析记录', '恢复主解析记录'];
- } else {
- $task['action_name'] = ['未知', '暂停解析', '启用解析'];
- }
- View::assign('info', $task);
- return View::fetch();
- }
-
- public function tasklog_data()
- {
- if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
- $taskid = input('param.id/d');
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
- $action = input('post.action/d', 0);
-
- $select = Db::name('dmlog')->where('taskid', $taskid);
- if ($action > 0) {
- $select->where('action', $action);
- }
- $total = $select->count();
- $list = $select->order('id', 'desc')->limit($offset, $limit)->select();
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function clean()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- if ($this->request->isPost()) {
- $days = input('post.days/d');
- if (!$days || $days < 0) return json(['code' => -1, 'msg' => '参数错误']);
- Db::execute("DELETE FROM `" . config('database.connections.mysql.prefix') . "dmlog` WHERE `date`<'" . date("Y-m-d H:i:s", strtotime("-" . $days . " days")) . "'");
- Db::execute("OPTIMIZE TABLE `" . config('database.connections.mysql.prefix') . "dmlog`");
- return json(['code' => 0, 'msg' => '清理成功']);
- }
- }
-
- public function status()
- {
- $run_time = config_get('run_time', null, true);
- $run_state = $run_time ? (time() - strtotime($run_time) > 10 ? 0 : 1) : 0;
- return $run_state == 1 ? 'ok' : 'error';
- }
-}
+alert('error', '无权限');
+ $switch_count = Db::name('dmlog')->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->count();
+ $fail_count = Db::name('dmlog')->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->where('action', 1)->count();
+
+ $run_time = config_get('run_time', null, true);
+ $run_state = $run_time ? (time() - strtotime($run_time) > 10 ? 0 : 1) : 0;
+ View::assign('info', [
+ 'run_count' => config_get('run_count', null, true) ?? 0,
+ 'run_time' => $run_time ?? '无',
+ 'run_state' => $run_state,
+ 'run_error' => config_get('run_error', null, true),
+ 'switch_count' => $switch_count,
+ 'fail_count' => $fail_count,
+ 'swoole' => extension_loaded('swoole') ? '已安装' : '未安装',
+ ]);
+ return View::fetch();
+ }
+
+ public function task()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ return View::fetch();
+ }
+
+ public function task_data()
+ {
+ if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
+ $type = input('post.type/d', 1);
+ $status = input('post.status', null);
+ $kw = input('post.kw', null, 'trim');
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+
+ $select = Db::name('dmtask')->alias('A')->join('domain B', 'A.did = B.id');
+ if (!empty($kw)) {
+ if ($type == 1) {
+ $select->whereLike('rr|B.name', '%' . $kw . '%');
+ } elseif ($type == 2) {
+ $select->where('recordid', $kw);
+ } elseif ($type == 3) {
+ $select->where('main_value', $kw);
+ } elseif ($type == 4) {
+ $select->where('backup_value', $kw);
+ } elseif ($type == 5) {
+ $select->whereLike('remark', '%' . $kw . '%');
+ }
+ }
+ if (!isNullOrEmpty($status)) {
+ $select->where('status', intval($status));
+ }
+ $total = $select->count();
+ $list = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name domain')->select()->toArray();
+
+ foreach ($list as &$row) {
+ $row['addtimestr'] = date('Y-m-d H:i:s', $row['addtime']);
+ $row['checktimestr'] = $row['checktime'] > 0 ? date('Y-m-d H:i:s', $row['checktime']) : '未运行';
+ }
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function task_op()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+ if ($action == 'add') {
+ $task = [
+ 'did' => input('post.did/d'),
+ 'rr' => input('post.rr', null, 'trim'),
+ 'recordid' => input('post.recordid', null, 'trim'),
+ 'type' => input('post.type/d'),
+ 'main_value' => input('post.main_value', null, 'trim'),
+ 'backup_value' => input('post.backup_value', null, 'trim'),
+ 'checktype' => input('post.checktype/d'),
+ 'checkurl' => input('post.checkurl', null, 'trim'),
+ 'tcpport' => !empty(input('post.tcpport')) ? input('post.tcpport/d') : null,
+ 'frequency' => input('post.frequency/d'),
+ '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(),
+ 'active' => 1
+ ];
+
+ if (empty($task['did']) || empty($task['rr']) || empty($task['recordid']) || empty($task['main_value']) || empty($task['frequency']) || empty($task['cycle'])) {
+ return json(['code' => -1, 'msg' => '必填项不能为空']);
+ }
+ if ($task['checktype'] > 0 && $task['timeout'] > $task['frequency']) {
+ return json(['code' => -1, 'msg' => '为保障容灾切换任务正常运行,最大超时时间不能大于检测间隔']);
+ }
+ if ($task['type'] == 2 && $task['backup_value'] == $task['main_value']) {
+ return json(['code' => -1, 'msg' => '主备地址不能相同']);
+ }
+ if (Db::name('dmtask')->where('recordid', $task['recordid'])->find()) {
+ return json(['code' => -1, 'msg' => '当前容灾切换策略已存在']);
+ }
+ Db::name('dmtask')->insert($task);
+ return json(['code' => 0, 'msg' => '添加成功']);
+ } elseif ($action == 'edit') {
+ $id = input('post.id/d');
+ $task = [
+ 'did' => input('post.did/d'),
+ 'rr' => input('post.rr', null, 'trim'),
+ 'recordid' => input('post.recordid', null, 'trim'),
+ 'type' => input('post.type/d'),
+ 'main_value' => input('post.main_value', null, 'trim'),
+ 'backup_value' => input('post.backup_value', null, 'trim'),
+ 'checktype' => input('post.checktype/d'),
+ 'checkurl' => input('post.checkurl', null, 'trim'),
+ 'tcpport' => !empty(input('post.tcpport')) ? input('post.tcpport/d') : null,
+ 'frequency' => input('post.frequency/d'),
+ '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'),
+ ];
+
+ if (empty($task['did']) || empty($task['rr']) || empty($task['recordid']) || empty($task['main_value']) || empty($task['frequency']) || empty($task['cycle'])) {
+ return json(['code' => -1, 'msg' => '必填项不能为空']);
+ }
+ if ($task['checktype'] > 0 && $task['timeout'] > $task['frequency']) {
+ return json(['code' => -1, 'msg' => '为保障容灾切换任务正常运行,最大超时时间不能大于检测间隔']);
+ }
+ if ($task['type'] == 2 && $task['backup_value'] == $task['main_value']) {
+ return json(['code' => -1, 'msg' => '主备地址不能相同']);
+ }
+ if (Db::name('dmtask')->where('recordid', $task['recordid'])->where('id', '<>', $id)->find()) {
+ return json(['code' => -1, 'msg' => '当前容灾切换策略已存在']);
+ }
+ Db::name('dmtask')->where('id', $id)->update($task);
+ return json(['code' => 0, 'msg' => '修改成功']);
+ } elseif ($action == 'setactive') {
+ $id = input('post.id/d');
+ $active = input('post.active/d');
+ Db::name('dmtask')->where('id', $id)->update(['active' => $active]);
+ return json(['code' => 0, 'msg' => '设置成功']);
+ } elseif ($action == 'del') {
+ $id = input('post.id/d');
+ Db::name('dmtask')->where('id', $id)->delete();
+ Db::name('dmlog')->where('taskid', $id)->delete();
+ return json(['code' => 0, 'msg' => '删除成功']);
+ } elseif ($action == 'operation') {
+ $ids = input('post.ids');
+ $success = 0;
+ foreach ($ids as $id) {
+ if (input('post.act') == 'delete') {
+ Db::name('dmtask')->where('id', $id)->delete();
+ Db::name('dmlog')->where('taskid', $id)->delete();
+ $success++;
+ } elseif (input('post.act') == 'retry') {
+ Db::name('dmtask')->where('id', $id)->update(['checknexttime' => time()]);
+ $success++;
+ } elseif (input('post.act') == 'open' || input('post.act') == 'close') {
+ $isauto = input('post.act') == 'open' ? 1 : 0;
+ Db::name('dmtask')->where('id', $id)->update(['active' => $isauto]);
+ $success++;
+ }
+ }
+ return json(['code' => 0, 'msg' => '成功操作' . $success . '个容灾切换策略']);
+ } else {
+ return json(['code' => -1, 'msg' => '参数错误']);
+ }
+ }
+
+ public function taskform()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+ $task = null;
+ if ($action == 'edit') {
+ $id = input('get.id/d');
+ $task = Db::name('dmtask')->where('id', $id)->find();
+ if (empty($task)) return $this->alert('error', '切换策略不存在');
+ }
+
+ $domains = [];
+ $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);
+
+ View::assign('info', $task);
+ View::assign('action', $action);
+ View::assign('support_ping', function_exists('exec') ? '1' : '0');
+ return View::fetch();
+ }
+
+ public function taskinfo()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $id = input('param.id/d');
+ $task = Db::name('dmtask')->where('id', $id)->find();
+ if (empty($task)) return $this->alert('error', '切换策略不存在');
+
+ $switch_count = Db::name('dmlog')->where('taskid', $id)->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->count();
+ $fail_count = Db::name('dmlog')->where('taskid', $id)->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->where('action', 1)->count();
+
+ $task['switch_count'] = $switch_count;
+ $task['fail_count'] = $fail_count;
+ if ($task['type'] == 3) {
+ $task['action_name'] = ['未知', '开启解析', '暂停解析'];
+ } elseif ($task['type'] == 2) {
+ $task['action_name'] = ['未知', '切换备用解析记录', '恢复主解析记录'];
+ } else {
+ $task['action_name'] = ['未知', '暂停解析', '启用解析'];
+ }
+ View::assign('info', $task);
+ return View::fetch();
+ }
+
+ public function tasklog_data()
+ {
+ if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
+ $taskid = input('param.id/d');
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+ $action = input('post.action/d', 0);
+
+ $select = Db::name('dmlog')->where('taskid', $taskid);
+ if ($action > 0) {
+ $select->where('action', $action);
+ }
+ $total = $select->count();
+ $list = $select->order('id', 'desc')->limit($offset, $limit)->select();
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function clean()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ if ($this->request->isPost()) {
+ $days = input('post.days/d');
+ if (!$days || $days < 0) return json(['code' => -1, 'msg' => '参数错误']);
+ Db::execute("DELETE FROM `" . config('database.connections.mysql.prefix') . "dmlog` WHERE `date`<'" . date("Y-m-d H:i:s", strtotime("-" . $days . " days")) . "'");
+ Db::execute("OPTIMIZE TABLE `" . config('database.connections.mysql.prefix') . "dmlog`");
+ return json(['code' => 0, 'msg' => '清理成功']);
+ }
+ }
+
+ public function status()
+ {
+ $run_time = config_get('run_time', null, true);
+ $run_state = $run_time ? (time() - strtotime($run_time) > 10 ? 0 : 1) : 0;
+ return $run_state == 1 ? 'ok' : 'error';
+ }
+}
diff --git a/app/controller/Domain.php b/app/controller/Domain.php
index 85c7df4..03e04a0 100644
--- a/app/controller/Domain.php
+++ b/app/controller/Domain.php
@@ -1,1099 +1,1099 @@
-alert('error', '无权限');
- View::assign('dnsconfig', DnsHelper::$dns_config);
- return view();
- }
-
- public function account_data()
- {
- if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
- $kw = $this->request->post('kw', null, 'trim');
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
-
- $select = Db::name('account');
- if (!empty($kw)) {
- $select->whereLike('ak|remark', '%' . $kw . '%');
- }
- $total = $select->count();
- $rows = $select->order('id', 'desc')->limit($offset, $limit)->select();
-
- $list = [];
- foreach ($rows as $row) {
- $row['typename'] = DnsHelper::$dns_config[$row['type']]['name'];
- $list[] = $row;
- }
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function account_op()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $act = input('param.act');
- if ($act == 'get') {
- $id = input('post.id/d');
- $row = Db::name('account')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => '域名账户不存在']);
- return json(['code' => 0, 'data' => $row]);
- } elseif ($act == 'add') {
- $type = input('post.type');
- $ak = input('post.ak', null, 'trim');
- $sk = input('post.sk', null, 'trim');
- $ext = input('post.ext', null, 'trim');
- $remark = input('post.remark', null, 'trim');
- $proxy = input('post.proxy/d', 0);
- if (empty($ak) || empty($sk)) return json(['code' => -1, 'msg' => 'AccessKey和SecretKey不能为空']);
- if (Db::name('account')->where('type', $type)->where('ak', $ak)->find()) {
- return json(['code' => -1, 'msg' => '域名账户已存在']);
- }
- Db::startTrans();
- $id = Db::name('account')->insertGetId([
- 'type' => $type,
- 'ak' => $ak,
- 'sk' => $sk,
- 'ext' => $ext,
- 'proxy' => $proxy,
- 'remark' => $remark,
- 'addtime' => date('Y-m-d H:i:s'),
- ]);
- $dns = DnsHelper::getModel($id);
- if ($dns) {
- if ($dns->check()) {
- Db::commit();
- return json(['code' => 0, 'msg' => '添加域名账户成功!']);
- } else {
- Db::rollback();
- return json(['code' => -1, 'msg' => '验证域名账户失败,' . $dns->getError()]);
- }
- } else {
- Db::rollback();
- return json(['code' => -1, 'msg' => 'DNS模块(' . $type . ')不存在']);
- }
- } elseif ($act == 'edit') {
- $id = input('post.id/d');
- $row = Db::name('account')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => '域名账户不存在']);
- $type = input('post.type');
- $ak = input('post.ak', null, 'trim');
- $sk = input('post.sk', null, 'trim');
- $ext = input('post.ext', null, 'trim');
- $remark = input('post.remark', null, 'trim');
- $proxy = input('post.proxy/d', 0);
- if (empty($ak) || empty($sk)) return json(['code' => -1, 'msg' => 'AccessKey和SecretKey不能为空']);
- if (Db::name('account')->where('type', $type)->where('ak', $ak)->where('id', '<>', $id)->find()) {
- return json(['code' => -1, 'msg' => '域名账户已存在']);
- }
- Db::startTrans();
- Db::name('account')->where('id', $id)->update([
- 'type' => $type,
- 'ak' => $ak,
- 'sk' => $sk,
- 'ext' => $ext,
- 'proxy' => $proxy,
- 'remark' => $remark,
- ]);
- $dns = DnsHelper::getModel($id);
- if ($dns) {
- if ($dns->check()) {
- Db::commit();
- return json(['code' => 0, 'msg' => '修改域名账户成功!']);
- } else {
- Db::rollback();
- return json(['code' => -1, 'msg' => '验证域名账户失败,' . $dns->getError()]);
- }
- } else {
- Db::rollback();
- return json(['code' => -1, 'msg' => 'DNS模块(' . $type . ')不存在']);
- }
- } elseif ($act == 'del') {
- $id = input('post.id/d');
- $dcount = DB::name('domain')->where('aid', $id)->count();
- if ($dcount > 0) return json(['code' => -1, 'msg' => '该域名账户下存在域名,无法删除']);
- Db::name('account')->where('id', $id)->delete();
- return json(['code' => 0]);
- }
- return json(['code' => -3]);
- }
-
-
- public function domain()
- {
- if (request()->user['type'] == 'domain') {
- return redirect('/record/' . request()->user['id']);
- }
- $list = Db::name('account')->select();
- $accounts = [];
- $types = [];
- foreach ($list as $row) {
- $name = $row['id'] . '_' . DnsHelper::$dns_config[$row['type']]['name'];
- if (!array_key_exists($row['type'], $types)) {
- $types[$row['type']] = DnsHelper::$dns_config[$row['type']]['name'];
- }
- if (!empty($row['remark'])) {
- $name .= '(' . $row['remark'] . ')';
- }
- $accounts[] = ['id' => $row['id'], 'name' => $name, 'type' => DnsHelper::$dns_config[$row['type']]['name'], 'add' => DnsHelper::$dns_config[$row['type']]['add']];
- }
- View::assign('accounts', $accounts);
- View::assign('types', $types);
- return view();
- }
-
- public function domain_add()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $list = Db::name('account')->select();
- $accounts = [];
- $types = [];
- foreach ($list as $row) {
- $accounts[$row['id']] = $row['id'] . '_' . DnsHelper::$dns_config[$row['type']]['name'];
- if (!array_key_exists($row['type'], $types)) {
- $types[$row['type']] = DnsHelper::$dns_config[$row['type']]['name'];
- }
- if (!empty($row['remark'])) {
- $accounts[$row['id']] .= '(' . $row['remark'] . ')';
- }
- }
- View::assign('accounts', $accounts);
- View::assign('types', $types);
- return view();
- }
-
- public function domain_data()
- {
- if (!checkPermission(1)) return json(['total' => 0, 'rows' => []]);
- $kw = input('post.kw', null, 'trim');
- $type = input('post.type', null, 'trim');
- $status = input('post.status', null, 'trim');
- $offset = input('post.offset/d', 0);
- $limit = input('post.limit/d', 10);
-
- $select = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id');
- if (!empty($kw)) {
- $select->whereLike('name|A.remark', '%' . $kw . '%');
- }
- if (!empty($type)) {
- $select->whereLike('B.type', $type);
- }
- if (request()->user['level'] == 1) {
- $select->where('is_hide', 0)->where('A.name', 'in', request()->user['permission']);
- }
- if (!isNullOrEmpty($status)) {
- if ($status == '2') {
- $select->where('A.expiretime', '<=', date('Y-m-d H:i:s'));
- } elseif ($status == '1') {
- $select->where('A.expiretime', '<=', date('Y-m-d H:i:s', time() + 86400 * 30))->where('A.expiretime', '>', date('Y-m-d H:i:s'));
- }
- }
- $total = $select->count();
- $rows = $select->fieldRaw('A.*,B.type,B.remark aremark')->order('A.id', 'desc')->limit($offset, $limit)->select();
-
- $list = [];
- foreach ($rows as $row) {
- $row['typename'] = DnsHelper::$dns_config[$row['type']]['name'];
- $list[] = $row;
- }
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function domain_op()
- {
- if (!checkPermission(1)) return $this->alert('error', '无权限');
- $act = input('param.act');
- if ($act == 'get') {
- $id = input('post.id/d');
- $row = Db::name('domain')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => '域名不存在']);
- return json(['code' => 0, 'data' => $row]);
- } elseif ($act == 'add') {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $aid = input('post.aid/d');
- $method = input('post.method/d', 0);
- $name = input('post.name', null, 'trim');
- $thirdid = input('post.thirdid', null, 'trim');
- $recordcount = input('post.recordcount/d', 0);
- if ($method == 1 && empty($name) || $method == 0 && (empty($name) || empty($thirdid))) return json(['code' => -1, 'msg' => '参数不能为空']);
- if (Db::name('domain')->where('aid', $aid)->where('name', $name)->find()) {
- return json(['code' => -1, 'msg' => '域名已存在']);
- }
- if ($method == 1) {
- $dns = DnsHelper::getModel($aid);
- $result = $dns->addDomain($name);
- if (!$result) return json(['code' => -1, 'msg' => '添加域名失败,' . $dns->getError()]);
- $name = $result['name'];
- $thirdid = $result['id'];
- }
- Db::name('domain')->insert([
- 'aid' => $aid,
- 'name' => $name,
- 'thirdid' => $thirdid,
- 'addtime' => date('Y-m-d H:i:s'),
- 'is_hide' => 0,
- 'is_sso' => 1,
- 'recordcount' => $recordcount,
- ]);
- return json(['code' => 0, 'msg' => '添加域名成功!']);
- } elseif ($act == 'edit') {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $id = input('post.id/d');
- $row = Db::name('domain')->where('id', $id)->find();
- if (!$row) return json(['code' => -1, 'msg' => '域名不存在']);
- $is_hide = input('post.is_hide/d');
- $is_sso = input('post.is_sso/d');
- $is_notice = input('post.is_notice/d');
- $expiretime = input('post.expiretime', null, 'trim');
- $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,
- 'is_notice' => $is_notice,
- 'expiretime' => $expiretime ? $expiretime : null,
- 'remark' => $remark,
- ]);
- return json(['code' => 0, 'msg' => '修改域名配置成功!']);
- } elseif ($act == 'del') {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $id = input('post.id/d');
- Db::name('domain')->where('id', $id)->delete();
- Db::name('dmtask')->where('did', $id)->delete();
- Db::name('optimizeip')->where('did', $id)->delete();
- Db::name('sctask')->where('did', $id)->delete();
- return json(['code' => 0]);
- } elseif ($act == 'batchadd') {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $aid = input('post.aid/d');
- $domains = input('post.domains');
- if (empty($domains)) return json(['code' => -1, 'msg' => '参数不能为空']);
- $data = [];
- foreach ($domains as $row) {
- $data[] = [
- 'aid' => $aid,
- 'name' => $row['name'],
- 'thirdid' => $row['id'],
- 'addtime' => date('Y-m-d H:i:s'),
- 'is_hide' => 0,
- 'is_sso' => 1,
- 'recordcount' => $row['recordcount'],
- ];
- }
- 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;
- $count = Db::name('domain')->where('id', 'in', $ids)->update(['remark' => $remark]);
- return json(['code' => 0, 'msg' => '成功修改' . $count . '个域名!']);
- } elseif ($act == 'batchsetnotice') {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $ids = input('post.ids');
- $is_notice = input('post.is_notice/d', 0);
- if (empty($ids)) return json(['code' => -1, 'msg' => '参数不能为空']);
- $count = Db::name('domain')->where('id', 'in', $ids)->update(['is_notice' => $is_notice]);
- return json(['code' => 0, 'msg' => '成功修改' . $count . '个域名!']);
- } 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();
- Db::name('sctask')->where('did', 'in', $ids)->delete();
- return json(['code' => 0, 'msg' => '成功删除' . count($ids) . '个域名!']);
- }
- return json(['code' => -3]);
- }
-
- public function domain_list()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $aid = input('post.aid/d');
- $kw = input('post.kw', null, 'trim');
- $page = input('?post.page') ? input('post.page/d') : 1;
- $pagesize = input('?post.pagesize') ? input('post.pagesize/d') : 10;
- $dns = DnsHelper::getModel($aid);
- $result = $dns->getDomainList($kw, $page, $pagesize);
- if (!$result) return json(['code' => -1, 'msg' => '获取域名列表失败,' . $dns->getError()]);
-
- foreach ($result['list'] as &$row) {
- $row['disabled'] = Db::name('domain')->where('aid', $aid)->where('name', $row['Domain'])->find() != null;
- }
- return json(['code' => 0, 'data' => ['total' => $result['total'], 'list' => $result['list']]]);
- }
-
- //获取解析线路和最小TTL
- private function get_line_and_ttl($drow)
- {
- $recordLine = cache('record_line_' . $drow['id']);
- $minTTL = cache('min_ttl_' . $drow['id']);
- if (empty($recordLine)) {
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- if (!$dns) throw new Exception('DNS模块不存在');
- $recordLine = $dns->getRecordLine();
- if (!$recordLine) throw new Exception('获取解析线路列表失败,' . $dns->getError());
- cache('record_line_' . $drow['id'], $recordLine, 604800);
- $minTTL = $dns->getMinTTL();
- if ($minTTL) {
- cache('min_ttl_' . $drow['id'], $minTTL, 604800);
- }
- }
- return [$recordLine, $minTTL];
- }
-
- public function domain_info()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return $this->alert('error', '域名不存在');
- }
- $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
-
- $recordLineArr = [];
- foreach ($recordLine as $key => $item) {
- $recordLineArr[] = ['id' => strval($key), 'name' => $item['name'], 'parent' => $item['parent']];
- }
-
- $dnsconfig = DnsHelper::$dns_config[$dnstype];
- $dnsconfig['type'] = $dnstype;
-
- $drow['config'] = $dnsconfig;
- $drow['recordLine'] = $recordLineArr;
- $drow['minTTL'] = $minTTL ? $minTTL : 1;
- if (input('?post.loginurl') && input('post.loginurl') == '1') {
- $token = getSid();
- cache('quicklogin_' . $drow['name'], $token, 3600);
- $timestamp = time();
- $sign = md5(config_get('sys_key') . $drow['name'] . $timestamp . $token . config_get('sys_key'));
- $drow['loginurl'] = request()->root(true) . '/quicklogin?domain=' . $drow['name'] . '×tamp=' . $timestamp . '&token=' . $token . '&sign=' . $sign;
- }
-
- return json(['code' => 0, 'data' => $drow]);
- }
-
- public function record()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return $this->alert('error', '域名不存在');
- }
- $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
-
- $recordLineArr = [];
- foreach ($recordLine as $key => $item) {
- $recordLineArr[] = ['id' => strval($key), 'name' => $item['name'], 'parent' => $item['parent']];
- }
-
- $dnsconfig = DnsHelper::$dns_config[$dnstype];
- $dnsconfig['type'] = $dnstype;
-
- View::assign('domainId', $id);
- View::assign('domainName', $drow['name']);
- View::assign('recordLine', $recordLineArr);
- View::assign('minTTL', $minTTL ? $minTTL : 1);
- View::assign('dnsconfig', $dnsconfig);
- return view();
- }
-
- public function record_data()
- {
- $id = input('param.id/d');
- $keyword = input('post.keyword', null, 'trim');
- $subdomain = input('post.subdomain', null, 'trim');
- $value = input('post.value', null, 'trim');
- $type = input('post.type', null, 'trim');
- $line = input('post.line', null, 'trim');
- $status = input('post.status', null, 'trim');
- $offset = input('post.offset/d', 0);
- $limit = input('post.limit/d', 10);
- if ($limit == 0) {
- $page = 1;
- } else {
- $page = $offset / $limit + 1;
- }
-
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['total' => 0, 'rows' => []]);
- }
- if (!checkPermission(0, $drow['name'])) return json(['total' => 0, 'rows' => []]);
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- $domainRecords = $dns->getDomainRecords($page, $limit, $keyword, $subdomain, $value, $type, $line, $status);
- if (!$domainRecords) return json(['total' => 0, 'rows' => []]);
-
- if (empty($keyword) && empty($subdomain) && empty($type) && isNullOrEmpty($line) && empty($status) && empty($value) && $domainRecords['total'] != $drow['recordcount']) {
- Db::name('domain')->where('id', $id)->update(['recordcount' => $domainRecords['total']]);
- }
-
- $recordLine = cache('record_line_' . $id);
-
- foreach ($domainRecords['list'] as &$row) {
- $row['LineName'] = isset($recordLine[$row['Line']]) ? $recordLine[$row['Line']]['name'] : $row['Line'];
- }
-
- $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
- if (DnsHelper::$dns_config[$dnstype]['page']) {
- return json($domainRecords['list']);
- }
-
- return json(['total' => $domainRecords['total'], 'rows' => $domainRecords['list']]);
- }
-
- public function record_list()
- {
- $id = input('post.id/d');
- $rr = input('post.rr', null, 'trim');
-
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return json(['code' => -1, 'msg' => '无权限']);
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- $domainRecords = $dns->getSubDomainRecords($rr, 1, 100);
- if (!$domainRecords) return json(['code' => -1, 'msg' => '获取记录列表失败,' . $dns->getError()]);
-
- list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
-
- $list = [];
- foreach ($domainRecords['list'] as &$row) {
- if ($rr == '@' && ($row['Type'] == 'NS' || $row['Type'] == 'SOA')) continue;
- $row['LineName'] = isset($recordLine[$row['Line']]) ? $recordLine[$row['Line']]['name'] : $row['Line'];
- $list[] = $row;
- }
-
- return json(['code' => 0, 'data' => $list]);
- }
-
- public function record_add()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- $name = input('post.name', null, 'trim');
- $type = input('post.type', null, 'trim');
- $value = input('post.value', null, 'trim');
- $line = input('post.line', null, 'trim');
- $ttl = input('post.ttl/d', 600);
- $weight = input('post.weight/d', 0);
- $mx = input('post.mx/d', 1);
- $remark = input('post.remark', null, 'trim');
-
- if (empty($name) || empty($type) || empty($value)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
-
- $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'], '添加解析', $name.' ['.$type.'] '.$value.' (线路:'.$line.' TTL:'.$ttl.')');
- return json(['code' => 0, 'msg' => '添加解析记录成功!']);
- } else {
- return json(['code' => -1, 'msg' => '添加解析记录失败,' . $dns->getError()]);
- }
- }
-
- public function record_update()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- $recordid = input('post.recordid', null, 'trim');
- $name = input('post.name', null, 'trim');
- $type = input('post.type', null, 'trim');
- $value = input('post.value', null, 'trim');
- $line = input('post.line', null, 'trim');
- $ttl = input('post.ttl/d', 600);
- $weight = input('post.weight/d', 0);
- $mx = input('post.mx/d', 1);
- $remark = input('post.remark', null, 'trim');
-
- $recordinfo = input('post.recordinfo', null, 'trim');
-
- if (empty($recordid) || empty($name) || empty($type) || empty($value)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- $recordid = $dns->updateDomainRecord($recordid, $name, $type, $value, $line, $ttl, $mx, $weight, $remark);
- if ($recordid) {
- if ($recordinfo) {
- $recordinfo = json_decode($recordinfo, true);
- if (is_array($recordinfo['Value'])) $recordinfo['Value'] = implode(',', $recordinfo['Value']);
- 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.')');
- }
- } else {
- $this->add_log($drow['name'], '修改解析', $name.' ['.$type.'] '.$value.' (线路:'.$line.' TTL:'.$ttl.')');
- }
- return json(['code' => 0, 'msg' => '修改解析记录成功!']);
- } else {
- return json(['code' => -1, 'msg' => '修改解析记录失败,' . $dns->getError()]);
- }
- }
-
- public function record_delete()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- $recordid = input('post.recordid', null, 'trim');
- $recordinfo = input('post.recordinfo', null, 'trim');
-
- if (empty($recordid)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- if ($dns->deleteDomainRecord($recordid)) {
- if ($recordinfo) {
- $recordinfo = json_decode($recordinfo, true);
- if (is_array($recordinfo['Value'])) $recordinfo['Value'] = implode(',', $recordinfo['Value']);
- $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()]);
- }
- }
-
- public function record_status()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- $recordid = input('post.recordid', null, 'trim');
- $status = input('post.status', null, 'trim');
- $recordinfo = input('post.recordinfo', null, 'trim');
-
- if (empty($recordid)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- if ($dns->setDomainRecordStatus($recordid, $status)) {
- $action = $status == '1' ? '启用解析' : '暂停解析';
- if ($recordinfo) {
- $recordinfo = json_decode($recordinfo, true);
- if (is_array($recordinfo['Value'])) $recordinfo['Value'] = implode(',', $recordinfo['Value']);
- $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()]);
- }
- }
-
- public function record_remark()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- $recordid = input('post.recordid', null, 'trim');
- $remark = input('post.remark', null, 'trim');
-
- if (empty($recordid)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
- if (empty($remark)) $remark = null;
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- if ($dns->updateDomainRecordRemark($recordid, $remark)) {
- return json(['code' => 0, 'msg' => '操作成功!']);
- } else {
- return json(['code' => -1, 'msg' => '操作失败,' . $dns->getError()]);
- }
- }
-
- public function record_batch()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- $action = input('post.action', null, 'trim');
- $recordinfo = input('post.recordinfo', null, 'trim');
- $recordinfo = json_decode($recordinfo, true);
-
- if (empty($recordinfo) || empty($action)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
-
- $success = 0;
- $fail = 0;
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- if ($action == 'open') {
- foreach ($recordinfo as $record) {
- if ($dns->setDomainRecordStatus($record['RecordId'], '1')) {
- if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
- $this->add_log($drow['name'], '启用解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
- $success++;
- }
- }
- $msg = '成功启用' . $success . '条解析记录';
- } else if ($action == 'pause') {
- foreach ($recordinfo as $record) {
- if ($dns->setDomainRecordStatus($record['RecordId'], '0')) {
- if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
- $this->add_log($drow['name'], '暂停解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
- $success++;
- }
- }
- $msg = '成功暂停' . $success . '条解析记录';
- } else if ($action == 'delete') {
- foreach ($recordinfo as $record) {
- if ($dns->deleteDomainRecord($record['RecordId'])) {
- if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
- $this->add_log($drow['name'], '删除解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
- $success++;
- }
- }
- $msg = '成功删除' . $success . '条解析记录';
- } else if ($action == 'remark') {
- $remark = input('post.remark', null, 'trim');
- if (empty($remark)) $remark = null;
- foreach ($recordinfo as $record) {
- if ($dns->updateDomainRecordRemark($record['RecordId'], $remark)) {
- $success++;
- } else {
- $fail++;
- }
- }
- $msg = '批量修改备注,成功' . $success . '条,失败' . $fail . '条';
- }
- return json(['code' => 0, 'msg' => $msg]);
- }
-
- public function record_batch_edit()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- $action = input('post.action', null, 'trim');
- $recordinfo = input('post.recordinfo', null, 'trim');
- $recordinfo = json_decode($recordinfo, true);
-
- if ($action == 'value') {
- $type = input('post.type', null, 'trim');
- $value = input('post.value', null, 'trim');
-
- if (empty($recordinfo) || empty($type) || empty($value)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
-
- $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']);
- if ($recordid) {
- if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
- $this->add_log($drow['name'], '修改解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' → '.$record['Name'].' ['.$type.'] '.$value.' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
- $success++;
- } else {
- $fail++;
- }
- }
- return json(['code' => 0, 'msg' => '批量修改解析记录,成功' . $success . '条,失败' . $fail . '条']);
- } else if ($action == 'line') {
- $line = input('post.line', null, 'trim');
-
- if (empty($recordinfo) || isNullOrEmpty($line)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
-
- $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']);
- if ($recordid) {
- if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
- $this->add_log($drow['name'], '修改解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$line.' TTL:'.$record['TTL'].')');
- $success++;
- } else {
- $fail++;
- }
- }
- return json(['code' => 0, 'msg' => '批量修改解析线路,成功' . $success . '条,失败' . $fail . '条']);
- }
- }
-
- public function record_batch_add()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return $this->alert('error', '域名不存在');
- }
- $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- if (request()->isAjax()) {
- $record = input('post.record', null, 'trim');
- $type = input('post.type', null, 'trim');
- $line = input('post.line', null, 'trim');
- $ttl = input('post.ttl/d', 600);
- $mx = input('post.mx/d', 1);
- $recordlist = explode("\n", $record);
-
- if (empty($record) || empty($recordlist)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
- if (is_null($line)) {
- $line = DnsHelper::$line_name[$dnstype]['DEF'];
- if ($dnstype == 'cloudflare' && input('post.proxy/d', 0) == 1) {
- $line = '1';
- }
- }
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
-
- $success = 0;
- $fail = 0;
- foreach ($recordlist as $record) {
- $record = trim($record);
- $arr = explode(' ', $record);
- if (empty($record) || empty($arr[0]) || empty($arr[1])) continue;
- $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'], '添加解析', $arr[0].' ['.$thistype.'] '.$arr[1].' (线路:'.$line.' TTL:'.$ttl.')');
- $success++;
- } else {
- $fail++;
- }
- }
- if ($success > 0) {
- return json(['code' => 0, 'msg' => '批量添加解析,成功' . $success . '条,失败' . $fail . '条']);
- } elseif($fail > 0) {
- return json(['code' => -1, 'msg' => '批量添加解析失败,' . $dns->getError()]);
- } else {
- return json(['code' => -1, 'msg' => '批量添加解析失败,没有可添加的记录']);
- }
- }
-
- list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
-
- $recordLineArr = [];
- foreach ($recordLine as $key => $item) {
- $recordLineArr[] = ['id' => strval($key), 'name' => $item['name'], 'parent' => $item['parent']];
- }
-
- $dnsconfig = DnsHelper::$dns_config[$dnstype];
- $dnsconfig['type'] = $dnstype;
-
- View::assign('domainId', $id);
- View::assign('domainName', $drow['name']);
- View::assign('recordLine', $recordLineArr);
- View::assign('minTTL', $minTTL ? $minTTL : 1);
- View::assign('dnsconfig', $dnsconfig);
- return view('batchadd');
- }
-
- public function record_batch_add2()
- {
- return view('batchadd2');
- }
-
- public function record_batch_edit2()
- {
- if (request()->isAjax()) {
- $id = input('post.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
- if (!checkPermission(0, $drow['name'])) return json(['code' => -1, 'msg' => '无权限']);
-
- $name = input('post.name', null, 'trim');
- $type = input('post.type', null, 'trim');
- $value = input('post.value', null, 'trim');
- $ttl = input('post.ttl/d', 0);
- $mx = input('post.mx/d', 0);
-
- if (empty($name) || empty($type) || empty($value)) {
- return json(['code' => -1, 'msg' => '必填参数不能为空']);
- }
- $line = DnsHelper::$line_name[$dnstype]['DEF'];
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- $domainRecords = $dns->getSubDomainRecords($name, 1, 100);
- if (!$domainRecords) return json(['code' => -1, 'msg' => '获取记录列表失败,' . $dns->getError()]);
- if (empty($domainRecords['list'])) return json(['code' => -1, 'msg' => '没有可修改的记录']);
-
- if ($type == 'A' || $type == 'AAAA' || $type == 'CNAME') {
- $list2 = array_filter($domainRecords['list'], function ($item) use ($type) {
- return $item['Type'] == $type;
- });
- if (!empty($list2)) {
- $list = $list2;
- } else {
- $list = array_filter($domainRecords['list'], function ($item) {
- return $item['Type'] == 'A' || $item['Type'] == 'AAAA' || $item['Type'] == 'CNAME';
- });
- }
- } else {
- $list = array_filter($domainRecords['list'], function ($item) use ($type) {
- return $item['Type'] == $type;
- });
- }
- if (empty($list)) return json(['code' => -1, 'msg' => '没有可修改的'.$type.'记录']);
-
- $list2 = array_filter($domainRecords['list'], function ($item) use ($line) {
- return $item['Line'] == $line;
- });
- if (!empty($list2)) $list = $list2;
-
- $success = 0;
- $fail = 0;
- foreach ($list as $record) {
- if ($name == '@' && ($record['Type'] == 'NS' || $record['Type'] == 'SOA')) continue;
-
- if ($ttl > 0) $record['TTL'] = $ttl;
- if ($mx > 0) $record['MX'] = $mx;
- $recordid = $dns->updateDomainRecord($record['RecordId'], $record['Name'], $type, $value, $record['Line'], $record['TTL'], $record['MX'], $record['Weight'], $record['Remark']);
- if ($recordid) {
- if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
- $this->add_log($drow['name'], '修改解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' → '.$record['Name'].' ['.$type.'] '.$value.' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
- $success++;
- } else {
- $fail++;
- }
- }
- if ($success > 0) {
- return json(['code' => 0, 'msg' => '成功修改' . $success . '条解析记录']);
- } elseif($fail > 0) {
- return json(['code' => -1, 'msg' => $dns->getError()]);
- } else {
- return json(['code' => -1, 'msg' => '没有可修改的记录']);
- }
- }
-
- return view('batchedit');
- }
-
- public function record_log()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return $this->alert('error', '域名不存在');
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
-
- if (request()->isPost()) {
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
- $page = $offset / $limit + 1;
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- $domainRecords = $dns->getDomainRecordLog($page, $limit);
- if (!$domainRecords) return json(['total' => 0, 'rows' => []]);
- return json(['total' => $domainRecords['total'], 'rows' => $domainRecords['list']]);
- }
-
- View::assign('domainId', $id);
- View::assign('domainName', $drow['name']);
- return view('log');
- }
-
- private function add_log($domain, $action, $data)
- {
- if (strlen($data) > 500) $data = substr($data, 0, 500);
- Db::name('log')->insert(['uid' => request()->user['id'], 'domain' => $domain, 'action' => $action, 'data' => $data, 'addtime' => date("Y-m-d H:i:s")]);
- }
-
-
- public function weight()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return $this->alert('error', '域名不存在');
- }
- if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
- if (request()->isAjax()) {
- $act = input('param.act');
- if ($act == 'status') {
- $subdomain = input('post.subdomain', null, 'trim');
- $status = input('post.status', null, 'trim');
- $type = input('post.type', null, 'trim');
- $line = input('post.line', null, 'trim');
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- if ($dns->setWeightStatus($subdomain, $status, $type, $line)) {
- return json(['code' => 0, 'msg' => '操作成功']);
- } else {
- return json(['code' => -1, 'msg' => '操作失败,' . $dns->getError()]);
- }
- } elseif ($act == 'update') {
- $subdomain = input('post.subdomain', null, 'trim');
- $status = input('post.status', '0', 'trim');
- $type = input('post.type', null, 'trim');
- $line = input('post.line', null, 'trim');
- $weight = input('post.weight');
- if (empty($subdomain) || empty($type) || empty($line) || $status == '1' && empty($weight)) {
- return json(['code' => -1, 'msg' => '参数不能为空']);
- }
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- if ($type == 'CNAME' || $dns->setWeightStatus($subdomain, $status, $type, $line)) {
- if ($status == '1') {
- $success = 0;
- foreach($weight as $recordid => $weight) {
- if ($dns->updateRecordWeight($recordid, $weight)) {
- $success++;
- }
- }
- if ($success > 0) {
- return json(['code' => 0, 'msg' => '成功修改' . $success . '条解析记录权重']);
- } else {
- return json(['code' => -1, 'msg' => '修改权重失败,' . $dns->getError()]);
- }
- }
- return json(['code' => 0, 'msg' => '修改成功']);
- } else {
- return json(['code' => -1, 'msg' => '修改失败,' . $dns->getError()]);
- }
- } else {
- return json(['code' => -1, 'msg' => '参数错误']);
- }
- }
-
- $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
- if ($dnstype != 'aliyun') {
- return $this->alert('error', '仅支持阿里云解析的域名');
- }
- list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
-
- $recordLineArr = [];
- foreach ($recordLine as $key => $item) {
- $recordLineArr[] = ['id' => strval($key), 'name' => $item['name'], 'parent' => $item['parent']];
- }
-
- $dnsconfig = DnsHelper::$dns_config[$dnstype];
- $dnsconfig['type'] = $dnstype;
-
- View::assign('domainId', $id);
- View::assign('domainName', $drow['name']);
- View::assign('recordLine', $recordLineArr);
- View::assign('dnsconfig', $dnsconfig);
- return view();
- }
-
- public function weight_data()
- {
- $id = input('param.id/d');
- $keyword = input('post.keyword', null, 'trim');
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
- if ($limit == 0) {
- $page = 1;
- } else {
- $page = $offset / $limit + 1;
- }
-
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['total' => 0, 'rows' => []]);
- }
- if (!checkPermission(0, $drow['name'])) return json(['total' => 0, 'rows' => []]);
-
- $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
- $domainRecords = $dns->getWeightSubDomains($page, $limit, $keyword);
- return json(['total' => $domainRecords['total'], 'rows' => $domainRecords['list']]);
- }
-
- public function expire_notice()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- if ($this->request->isPost()) {
- $params = input('post.');
- foreach ($params as $key => $value) {
- if (empty($key)) {
- continue;
- }
- config_set($key, $value);
- Cache::delete('configs');
- }
- return json(['code' => 0, 'msg' => 'succ']);
- }
- return View::fetch();
- }
-
- public function update_date()
- {
- $id = input('param.id/d');
- $drow = Db::name('domain')->where('id', $id)->find();
- if (!$drow) {
- return json(['code' => -1, 'msg' => '域名不存在']);
- }
- if (!checkPermission(0, $drow['name'])) return json(['code' => -1, 'msg' => '无权限']);
- $result = (new ExpireNoticeService())->updateDomainDate($id, $drow['name']);
- return json($result);
- }
-}
+alert('error', '无权限');
+ View::assign('dnsconfig', DnsHelper::$dns_config);
+ return view();
+ }
+
+ public function account_data()
+ {
+ if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
+ $kw = $this->request->post('kw', null, 'trim');
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+
+ $select = Db::name('account');
+ if (!empty($kw)) {
+ $select->whereLike('ak|remark', '%' . $kw . '%');
+ }
+ $total = $select->count();
+ $rows = $select->order('id', 'desc')->limit($offset, $limit)->select();
+
+ $list = [];
+ foreach ($rows as $row) {
+ $row['typename'] = DnsHelper::$dns_config[$row['type']]['name'];
+ $list[] = $row;
+ }
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function account_op()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $act = input('param.act');
+ if ($act == 'get') {
+ $id = input('post.id/d');
+ $row = Db::name('account')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => '域名账户不存在']);
+ return json(['code' => 0, 'data' => $row]);
+ } elseif ($act == 'add') {
+ $type = input('post.type');
+ $ak = input('post.ak', null, 'trim');
+ $sk = input('post.sk', null, 'trim');
+ $ext = input('post.ext', null, 'trim');
+ $remark = input('post.remark', null, 'trim');
+ $proxy = input('post.proxy/d', 0);
+ if (empty($ak) || empty($sk)) return json(['code' => -1, 'msg' => 'AccessKey和SecretKey不能为空']);
+ if (Db::name('account')->where('type', $type)->where('ak', $ak)->find()) {
+ return json(['code' => -1, 'msg' => '域名账户已存在']);
+ }
+ Db::startTrans();
+ $id = Db::name('account')->insertGetId([
+ 'type' => $type,
+ 'ak' => $ak,
+ 'sk' => $sk,
+ 'ext' => $ext,
+ 'proxy' => $proxy,
+ 'remark' => $remark,
+ 'addtime' => date('Y-m-d H:i:s'),
+ ]);
+ $dns = DnsHelper::getModel($id);
+ if ($dns) {
+ if ($dns->check()) {
+ Db::commit();
+ return json(['code' => 0, 'msg' => '添加域名账户成功!']);
+ } else {
+ Db::rollback();
+ return json(['code' => -1, 'msg' => '验证域名账户失败,' . $dns->getError()]);
+ }
+ } else {
+ Db::rollback();
+ return json(['code' => -1, 'msg' => 'DNS模块(' . $type . ')不存在']);
+ }
+ } elseif ($act == 'edit') {
+ $id = input('post.id/d');
+ $row = Db::name('account')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => '域名账户不存在']);
+ $type = input('post.type');
+ $ak = input('post.ak', null, 'trim');
+ $sk = input('post.sk', null, 'trim');
+ $ext = input('post.ext', null, 'trim');
+ $remark = input('post.remark', null, 'trim');
+ $proxy = input('post.proxy/d', 0);
+ if (empty($ak) || empty($sk)) return json(['code' => -1, 'msg' => 'AccessKey和SecretKey不能为空']);
+ if (Db::name('account')->where('type', $type)->where('ak', $ak)->where('id', '<>', $id)->find()) {
+ return json(['code' => -1, 'msg' => '域名账户已存在']);
+ }
+ Db::startTrans();
+ Db::name('account')->where('id', $id)->update([
+ 'type' => $type,
+ 'ak' => $ak,
+ 'sk' => $sk,
+ 'ext' => $ext,
+ 'proxy' => $proxy,
+ 'remark' => $remark,
+ ]);
+ $dns = DnsHelper::getModel($id);
+ if ($dns) {
+ if ($dns->check()) {
+ Db::commit();
+ return json(['code' => 0, 'msg' => '修改域名账户成功!']);
+ } else {
+ Db::rollback();
+ return json(['code' => -1, 'msg' => '验证域名账户失败,' . $dns->getError()]);
+ }
+ } else {
+ Db::rollback();
+ return json(['code' => -1, 'msg' => 'DNS模块(' . $type . ')不存在']);
+ }
+ } elseif ($act == 'del') {
+ $id = input('post.id/d');
+ $dcount = DB::name('domain')->where('aid', $id)->count();
+ if ($dcount > 0) return json(['code' => -1, 'msg' => '该域名账户下存在域名,无法删除']);
+ Db::name('account')->where('id', $id)->delete();
+ return json(['code' => 0]);
+ }
+ return json(['code' => -3]);
+ }
+
+
+ public function domain()
+ {
+ if (request()->user['type'] == 'domain') {
+ return redirect('/record/' . request()->user['id']);
+ }
+ $list = Db::name('account')->select();
+ $accounts = [];
+ $types = [];
+ foreach ($list as $row) {
+ $name = $row['id'] . '_' . DnsHelper::$dns_config[$row['type']]['name'];
+ if (!array_key_exists($row['type'], $types)) {
+ $types[$row['type']] = DnsHelper::$dns_config[$row['type']]['name'];
+ }
+ if (!empty($row['remark'])) {
+ $name .= '(' . $row['remark'] . ')';
+ }
+ $accounts[] = ['id' => $row['id'], 'name' => $name, 'type' => DnsHelper::$dns_config[$row['type']]['name'], 'add' => DnsHelper::$dns_config[$row['type']]['add']];
+ }
+ View::assign('accounts', $accounts);
+ View::assign('types', $types);
+ return view();
+ }
+
+ public function domain_add()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $list = Db::name('account')->select();
+ $accounts = [];
+ $types = [];
+ foreach ($list as $row) {
+ $accounts[$row['id']] = $row['id'] . '_' . DnsHelper::$dns_config[$row['type']]['name'];
+ if (!array_key_exists($row['type'], $types)) {
+ $types[$row['type']] = DnsHelper::$dns_config[$row['type']]['name'];
+ }
+ if (!empty($row['remark'])) {
+ $accounts[$row['id']] .= '(' . $row['remark'] . ')';
+ }
+ }
+ View::assign('accounts', $accounts);
+ View::assign('types', $types);
+ return view();
+ }
+
+ public function domain_data()
+ {
+ if (!checkPermission(1)) return json(['total' => 0, 'rows' => []]);
+ $kw = input('post.kw', null, 'trim');
+ $type = input('post.type', null, 'trim');
+ $status = input('post.status', null, 'trim');
+ $offset = input('post.offset/d', 0);
+ $limit = input('post.limit/d', 10);
+
+ $select = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id');
+ if (!empty($kw)) {
+ $select->whereLike('name|A.remark', '%' . $kw . '%');
+ }
+ if (!empty($type)) {
+ $select->whereLike('B.type', $type);
+ }
+ if (request()->user['level'] == 1) {
+ $select->where('is_hide', 0)->where('A.name', 'in', request()->user['permission']);
+ }
+ if (!isNullOrEmpty($status)) {
+ if ($status == '2') {
+ $select->where('A.expiretime', '<=', date('Y-m-d H:i:s'));
+ } elseif ($status == '1') {
+ $select->where('A.expiretime', '<=', date('Y-m-d H:i:s', time() + 86400 * 30))->where('A.expiretime', '>', date('Y-m-d H:i:s'));
+ }
+ }
+ $total = $select->count();
+ $rows = $select->fieldRaw('A.*,B.type,B.remark aremark')->order('A.id', 'desc')->limit($offset, $limit)->select();
+
+ $list = [];
+ foreach ($rows as $row) {
+ $row['typename'] = DnsHelper::$dns_config[$row['type']]['name'];
+ $list[] = $row;
+ }
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function domain_op()
+ {
+ if (!checkPermission(1)) return $this->alert('error', '无权限');
+ $act = input('param.act');
+ if ($act == 'get') {
+ $id = input('post.id/d');
+ $row = Db::name('domain')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => '域名不存在']);
+ return json(['code' => 0, 'data' => $row]);
+ } elseif ($act == 'add') {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $aid = input('post.aid/d');
+ $method = input('post.method/d', 0);
+ $name = input('post.name', null, 'trim');
+ $thirdid = input('post.thirdid', null, 'trim');
+ $recordcount = input('post.recordcount/d', 0);
+ if ($method == 1 && empty($name) || $method == 0 && (empty($name) || empty($thirdid))) return json(['code' => -1, 'msg' => '参数不能为空']);
+ if (Db::name('domain')->where('aid', $aid)->where('name', $name)->find()) {
+ return json(['code' => -1, 'msg' => '域名已存在']);
+ }
+ if ($method == 1) {
+ $dns = DnsHelper::getModel($aid);
+ $result = $dns->addDomain($name);
+ if (!$result) return json(['code' => -1, 'msg' => '添加域名失败,' . $dns->getError()]);
+ $name = $result['name'];
+ $thirdid = $result['id'];
+ }
+ Db::name('domain')->insert([
+ 'aid' => $aid,
+ 'name' => $name,
+ 'thirdid' => $thirdid,
+ 'addtime' => date('Y-m-d H:i:s'),
+ 'is_hide' => 0,
+ 'is_sso' => 1,
+ 'recordcount' => $recordcount,
+ ]);
+ return json(['code' => 0, 'msg' => '添加域名成功!']);
+ } elseif ($act == 'edit') {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $id = input('post.id/d');
+ $row = Db::name('domain')->where('id', $id)->find();
+ if (!$row) return json(['code' => -1, 'msg' => '域名不存在']);
+ $is_hide = input('post.is_hide/d');
+ $is_sso = input('post.is_sso/d');
+ $is_notice = input('post.is_notice/d');
+ $expiretime = input('post.expiretime', null, 'trim');
+ $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,
+ 'is_notice' => $is_notice,
+ 'expiretime' => $expiretime ? $expiretime : null,
+ 'remark' => $remark,
+ ]);
+ return json(['code' => 0, 'msg' => '修改域名配置成功!']);
+ } elseif ($act == 'del') {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $id = input('post.id/d');
+ Db::name('domain')->where('id', $id)->delete();
+ Db::name('dmtask')->where('did', $id)->delete();
+ Db::name('optimizeip')->where('did', $id)->delete();
+ Db::name('sctask')->where('did', $id)->delete();
+ return json(['code' => 0]);
+ } elseif ($act == 'batchadd') {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $aid = input('post.aid/d');
+ $domains = input('post.domains');
+ if (empty($domains)) return json(['code' => -1, 'msg' => '参数不能为空']);
+ $data = [];
+ foreach ($domains as $row) {
+ $data[] = [
+ 'aid' => $aid,
+ 'name' => $row['name'],
+ 'thirdid' => $row['id'],
+ 'addtime' => date('Y-m-d H:i:s'),
+ 'is_hide' => 0,
+ 'is_sso' => 1,
+ 'recordcount' => $row['recordcount'],
+ ];
+ }
+ 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;
+ $count = Db::name('domain')->where('id', 'in', $ids)->update(['remark' => $remark]);
+ return json(['code' => 0, 'msg' => '成功修改' . $count . '个域名!']);
+ } elseif ($act == 'batchsetnotice') {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $ids = input('post.ids');
+ $is_notice = input('post.is_notice/d', 0);
+ if (empty($ids)) return json(['code' => -1, 'msg' => '参数不能为空']);
+ $count = Db::name('domain')->where('id', 'in', $ids)->update(['is_notice' => $is_notice]);
+ return json(['code' => 0, 'msg' => '成功修改' . $count . '个域名!']);
+ } 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();
+ Db::name('sctask')->where('did', 'in', $ids)->delete();
+ return json(['code' => 0, 'msg' => '成功删除' . count($ids) . '个域名!']);
+ }
+ return json(['code' => -3]);
+ }
+
+ public function domain_list()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $aid = input('post.aid/d');
+ $kw = input('post.kw', null, 'trim');
+ $page = input('?post.page') ? input('post.page/d') : 1;
+ $pagesize = input('?post.pagesize') ? input('post.pagesize/d') : 10;
+ $dns = DnsHelper::getModel($aid);
+ $result = $dns->getDomainList($kw, $page, $pagesize);
+ if (!$result) return json(['code' => -1, 'msg' => '获取域名列表失败,' . $dns->getError()]);
+
+ foreach ($result['list'] as &$row) {
+ $row['disabled'] = Db::name('domain')->where('aid', $aid)->where('name', $row['Domain'])->find() != null;
+ }
+ return json(['code' => 0, 'data' => ['total' => $result['total'], 'list' => $result['list']]]);
+ }
+
+ //获取解析线路和最小TTL
+ private function get_line_and_ttl($drow)
+ {
+ $recordLine = cache('record_line_' . $drow['id']);
+ $minTTL = cache('min_ttl_' . $drow['id']);
+ if (empty($recordLine)) {
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ if (!$dns) throw new Exception('DNS模块不存在');
+ $recordLine = $dns->getRecordLine();
+ if (!$recordLine) throw new Exception('获取解析线路列表失败,' . $dns->getError());
+ cache('record_line_' . $drow['id'], $recordLine, 604800);
+ $minTTL = $dns->getMinTTL();
+ if ($minTTL) {
+ cache('min_ttl_' . $drow['id'], $minTTL, 604800);
+ }
+ }
+ return [$recordLine, $minTTL];
+ }
+
+ public function domain_info()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return $this->alert('error', '域名不存在');
+ }
+ $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
+
+ $recordLineArr = [];
+ foreach ($recordLine as $key => $item) {
+ $recordLineArr[] = ['id' => strval($key), 'name' => $item['name'], 'parent' => $item['parent']];
+ }
+
+ $dnsconfig = DnsHelper::$dns_config[$dnstype];
+ $dnsconfig['type'] = $dnstype;
+
+ $drow['config'] = $dnsconfig;
+ $drow['recordLine'] = $recordLineArr;
+ $drow['minTTL'] = $minTTL ? $minTTL : 1;
+ if (input('?post.loginurl') && input('post.loginurl') == '1') {
+ $token = getSid();
+ cache('quicklogin_' . $drow['name'], $token, 3600);
+ $timestamp = time();
+ $sign = md5(config_get('sys_key') . $drow['name'] . $timestamp . $token . config_get('sys_key'));
+ $drow['loginurl'] = request()->root(true) . '/quicklogin?domain=' . $drow['name'] . '×tamp=' . $timestamp . '&token=' . $token . '&sign=' . $sign;
+ }
+
+ return json(['code' => 0, 'data' => $drow]);
+ }
+
+ public function record()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return $this->alert('error', '域名不存在');
+ }
+ $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
+
+ $recordLineArr = [];
+ foreach ($recordLine as $key => $item) {
+ $recordLineArr[] = ['id' => strval($key), 'name' => $item['name'], 'parent' => $item['parent']];
+ }
+
+ $dnsconfig = DnsHelper::$dns_config[$dnstype];
+ $dnsconfig['type'] = $dnstype;
+
+ View::assign('domainId', $id);
+ View::assign('domainName', $drow['name']);
+ View::assign('recordLine', $recordLineArr);
+ View::assign('minTTL', $minTTL ? $minTTL : 1);
+ View::assign('dnsconfig', $dnsconfig);
+ return view();
+ }
+
+ public function record_data()
+ {
+ $id = input('param.id/d');
+ $keyword = input('post.keyword', null, 'trim');
+ $subdomain = input('post.subdomain', null, 'trim');
+ $value = input('post.value', null, 'trim');
+ $type = input('post.type', null, 'trim');
+ $line = input('post.line', null, 'trim');
+ $status = input('post.status', null, 'trim');
+ $offset = input('post.offset/d', 0);
+ $limit = input('post.limit/d', 10);
+ if ($limit == 0) {
+ $page = 1;
+ } else {
+ $page = $offset / $limit + 1;
+ }
+
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['total' => 0, 'rows' => []]);
+ }
+ if (!checkPermission(0, $drow['name'])) return json(['total' => 0, 'rows' => []]);
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ $domainRecords = $dns->getDomainRecords($page, $limit, $keyword, $subdomain, $value, $type, $line, $status);
+ if (!$domainRecords) return json(['total' => 0, 'rows' => []]);
+
+ if (empty($keyword) && empty($subdomain) && empty($type) && isNullOrEmpty($line) && empty($status) && empty($value) && $domainRecords['total'] != $drow['recordcount']) {
+ Db::name('domain')->where('id', $id)->update(['recordcount' => $domainRecords['total']]);
+ }
+
+ $recordLine = cache('record_line_' . $id);
+
+ foreach ($domainRecords['list'] as &$row) {
+ $row['LineName'] = isset($recordLine[$row['Line']]) ? $recordLine[$row['Line']]['name'] : $row['Line'];
+ }
+
+ $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
+ if (DnsHelper::$dns_config[$dnstype]['page']) {
+ return json($domainRecords['list']);
+ }
+
+ return json(['total' => $domainRecords['total'], 'rows' => $domainRecords['list']]);
+ }
+
+ public function record_list()
+ {
+ $id = input('post.id/d');
+ $rr = input('post.rr', null, 'trim');
+
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return json(['code' => -1, 'msg' => '无权限']);
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ $domainRecords = $dns->getSubDomainRecords($rr, 1, 100);
+ if (!$domainRecords) return json(['code' => -1, 'msg' => '获取记录列表失败,' . $dns->getError()]);
+
+ list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
+
+ $list = [];
+ foreach ($domainRecords['list'] as &$row) {
+ if ($rr == '@' && ($row['Type'] == 'NS' || $row['Type'] == 'SOA')) continue;
+ $row['LineName'] = isset($recordLine[$row['Line']]) ? $recordLine[$row['Line']]['name'] : $row['Line'];
+ $list[] = $row;
+ }
+
+ return json(['code' => 0, 'data' => $list]);
+ }
+
+ public function record_add()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ $name = input('post.name', null, 'trim');
+ $type = input('post.type', null, 'trim');
+ $value = input('post.value', null, 'trim');
+ $line = input('post.line', null, 'trim');
+ $ttl = input('post.ttl/d', 600);
+ $weight = input('post.weight/d', 0);
+ $mx = input('post.mx/d', 1);
+ $remark = input('post.remark', null, 'trim');
+
+ if (empty($name) || empty($type) || empty($value)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+
+ $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'], '添加解析', $name.' ['.$type.'] '.$value.' (线路:'.$line.' TTL:'.$ttl.')');
+ return json(['code' => 0, 'msg' => '添加解析记录成功!']);
+ } else {
+ return json(['code' => -1, 'msg' => '添加解析记录失败,' . $dns->getError()]);
+ }
+ }
+
+ public function record_update()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ $recordid = input('post.recordid', null, 'trim');
+ $name = input('post.name', null, 'trim');
+ $type = input('post.type', null, 'trim');
+ $value = input('post.value', null, 'trim');
+ $line = input('post.line', null, 'trim');
+ $ttl = input('post.ttl/d', 600);
+ $weight = input('post.weight/d', 0);
+ $mx = input('post.mx/d', 1);
+ $remark = input('post.remark', null, 'trim');
+
+ $recordinfo = input('post.recordinfo', null, 'trim');
+
+ if (empty($recordid) || empty($name) || empty($type) || empty($value)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ $recordid = $dns->updateDomainRecord($recordid, $name, $type, $value, $line, $ttl, $mx, $weight, $remark);
+ if ($recordid) {
+ if ($recordinfo) {
+ $recordinfo = json_decode($recordinfo, true);
+ if (is_array($recordinfo['Value'])) $recordinfo['Value'] = implode(',', $recordinfo['Value']);
+ 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.')');
+ }
+ } else {
+ $this->add_log($drow['name'], '修改解析', $name.' ['.$type.'] '.$value.' (线路:'.$line.' TTL:'.$ttl.')');
+ }
+ return json(['code' => 0, 'msg' => '修改解析记录成功!']);
+ } else {
+ return json(['code' => -1, 'msg' => '修改解析记录失败,' . $dns->getError()]);
+ }
+ }
+
+ public function record_delete()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ $recordid = input('post.recordid', null, 'trim');
+ $recordinfo = input('post.recordinfo', null, 'trim');
+
+ if (empty($recordid)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ if ($dns->deleteDomainRecord($recordid)) {
+ if ($recordinfo) {
+ $recordinfo = json_decode($recordinfo, true);
+ if (is_array($recordinfo['Value'])) $recordinfo['Value'] = implode(',', $recordinfo['Value']);
+ $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()]);
+ }
+ }
+
+ public function record_status()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ $recordid = input('post.recordid', null, 'trim');
+ $status = input('post.status', null, 'trim');
+ $recordinfo = input('post.recordinfo', null, 'trim');
+
+ if (empty($recordid)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ if ($dns->setDomainRecordStatus($recordid, $status)) {
+ $action = $status == '1' ? '启用解析' : '暂停解析';
+ if ($recordinfo) {
+ $recordinfo = json_decode($recordinfo, true);
+ if (is_array($recordinfo['Value'])) $recordinfo['Value'] = implode(',', $recordinfo['Value']);
+ $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()]);
+ }
+ }
+
+ public function record_remark()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ $recordid = input('post.recordid', null, 'trim');
+ $remark = input('post.remark', null, 'trim');
+
+ if (empty($recordid)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+ if (empty($remark)) $remark = null;
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ if ($dns->updateDomainRecordRemark($recordid, $remark)) {
+ return json(['code' => 0, 'msg' => '操作成功!']);
+ } else {
+ return json(['code' => -1, 'msg' => '操作失败,' . $dns->getError()]);
+ }
+ }
+
+ public function record_batch()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ $action = input('post.action', null, 'trim');
+ $recordinfo = input('post.recordinfo', null, 'trim');
+ $recordinfo = json_decode($recordinfo, true);
+
+ if (empty($recordinfo) || empty($action)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+
+ $success = 0;
+ $fail = 0;
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ if ($action == 'open') {
+ foreach ($recordinfo as $record) {
+ if ($dns->setDomainRecordStatus($record['RecordId'], '1')) {
+ if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
+ $this->add_log($drow['name'], '启用解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
+ $success++;
+ }
+ }
+ $msg = '成功启用' . $success . '条解析记录';
+ } else if ($action == 'pause') {
+ foreach ($recordinfo as $record) {
+ if ($dns->setDomainRecordStatus($record['RecordId'], '0')) {
+ if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
+ $this->add_log($drow['name'], '暂停解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
+ $success++;
+ }
+ }
+ $msg = '成功暂停' . $success . '条解析记录';
+ } else if ($action == 'delete') {
+ foreach ($recordinfo as $record) {
+ if ($dns->deleteDomainRecord($record['RecordId'])) {
+ if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
+ $this->add_log($drow['name'], '删除解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
+ $success++;
+ }
+ }
+ $msg = '成功删除' . $success . '条解析记录';
+ } else if ($action == 'remark') {
+ $remark = input('post.remark', null, 'trim');
+ if (empty($remark)) $remark = null;
+ foreach ($recordinfo as $record) {
+ if ($dns->updateDomainRecordRemark($record['RecordId'], $remark)) {
+ $success++;
+ } else {
+ $fail++;
+ }
+ }
+ $msg = '批量修改备注,成功' . $success . '条,失败' . $fail . '条';
+ }
+ return json(['code' => 0, 'msg' => $msg]);
+ }
+
+ public function record_batch_edit()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ $action = input('post.action', null, 'trim');
+ $recordinfo = input('post.recordinfo', null, 'trim');
+ $recordinfo = json_decode($recordinfo, true);
+
+ if ($action == 'value') {
+ $type = input('post.type', null, 'trim');
+ $value = input('post.value', null, 'trim');
+
+ if (empty($recordinfo) || empty($type) || empty($value)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+
+ $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']);
+ if ($recordid) {
+ if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
+ $this->add_log($drow['name'], '修改解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' → '.$record['Name'].' ['.$type.'] '.$value.' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
+ $success++;
+ } else {
+ $fail++;
+ }
+ }
+ return json(['code' => 0, 'msg' => '批量修改解析记录,成功' . $success . '条,失败' . $fail . '条']);
+ } else if ($action == 'line') {
+ $line = input('post.line', null, 'trim');
+
+ if (empty($recordinfo) || isNullOrEmpty($line)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+
+ $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']);
+ if ($recordid) {
+ if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
+ $this->add_log($drow['name'], '修改解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' (线路:'.$line.' TTL:'.$record['TTL'].')');
+ $success++;
+ } else {
+ $fail++;
+ }
+ }
+ return json(['code' => 0, 'msg' => '批量修改解析线路,成功' . $success . '条,失败' . $fail . '条']);
+ }
+ }
+
+ public function record_batch_add()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return $this->alert('error', '域名不存在');
+ }
+ $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ if (request()->isAjax()) {
+ $record = input('post.record', null, 'trim');
+ $type = input('post.type', null, 'trim');
+ $line = input('post.line', null, 'trim');
+ $ttl = input('post.ttl/d', 600);
+ $mx = input('post.mx/d', 1);
+ $recordlist = explode("\n", $record);
+
+ if (empty($record) || empty($recordlist)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+ if (is_null($line)) {
+ $line = DnsHelper::$line_name[$dnstype]['DEF'];
+ if ($dnstype == 'cloudflare' && input('post.proxy/d', 0) == 1) {
+ $line = '1';
+ }
+ }
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+
+ $success = 0;
+ $fail = 0;
+ foreach ($recordlist as $record) {
+ $record = trim($record);
+ $arr = explode(' ', $record);
+ if (empty($record) || empty($arr[0]) || empty($arr[1])) continue;
+ $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'], '添加解析', $arr[0].' ['.$thistype.'] '.$arr[1].' (线路:'.$line.' TTL:'.$ttl.')');
+ $success++;
+ } else {
+ $fail++;
+ }
+ }
+ if ($success > 0) {
+ return json(['code' => 0, 'msg' => '批量添加解析,成功' . $success . '条,失败' . $fail . '条']);
+ } elseif($fail > 0) {
+ return json(['code' => -1, 'msg' => '批量添加解析失败,' . $dns->getError()]);
+ } else {
+ return json(['code' => -1, 'msg' => '批量添加解析失败,没有可添加的记录']);
+ }
+ }
+
+ list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
+
+ $recordLineArr = [];
+ foreach ($recordLine as $key => $item) {
+ $recordLineArr[] = ['id' => strval($key), 'name' => $item['name'], 'parent' => $item['parent']];
+ }
+
+ $dnsconfig = DnsHelper::$dns_config[$dnstype];
+ $dnsconfig['type'] = $dnstype;
+
+ View::assign('domainId', $id);
+ View::assign('domainName', $drow['name']);
+ View::assign('recordLine', $recordLineArr);
+ View::assign('minTTL', $minTTL ? $minTTL : 1);
+ View::assign('dnsconfig', $dnsconfig);
+ return view('batchadd');
+ }
+
+ public function record_batch_add2()
+ {
+ return view('batchadd2');
+ }
+
+ public function record_batch_edit2()
+ {
+ if (request()->isAjax()) {
+ $id = input('post.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
+ if (!checkPermission(0, $drow['name'])) return json(['code' => -1, 'msg' => '无权限']);
+
+ $name = input('post.name', null, 'trim');
+ $type = input('post.type', null, 'trim');
+ $value = input('post.value', null, 'trim');
+ $ttl = input('post.ttl/d', 0);
+ $mx = input('post.mx/d', 0);
+
+ if (empty($name) || empty($type) || empty($value)) {
+ return json(['code' => -1, 'msg' => '必填参数不能为空']);
+ }
+ $line = DnsHelper::$line_name[$dnstype]['DEF'];
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ $domainRecords = $dns->getSubDomainRecords($name, 1, 100);
+ if (!$domainRecords) return json(['code' => -1, 'msg' => '获取记录列表失败,' . $dns->getError()]);
+ if (empty($domainRecords['list'])) return json(['code' => -1, 'msg' => '没有可修改的记录']);
+
+ if ($type == 'A' || $type == 'AAAA' || $type == 'CNAME') {
+ $list2 = array_filter($domainRecords['list'], function ($item) use ($type) {
+ return $item['Type'] == $type;
+ });
+ if (!empty($list2)) {
+ $list = $list2;
+ } else {
+ $list = array_filter($domainRecords['list'], function ($item) {
+ return $item['Type'] == 'A' || $item['Type'] == 'AAAA' || $item['Type'] == 'CNAME';
+ });
+ }
+ } else {
+ $list = array_filter($domainRecords['list'], function ($item) use ($type) {
+ return $item['Type'] == $type;
+ });
+ }
+ if (empty($list)) return json(['code' => -1, 'msg' => '没有可修改的'.$type.'记录']);
+
+ $list2 = array_filter($domainRecords['list'], function ($item) use ($line) {
+ return $item['Line'] == $line;
+ });
+ if (!empty($list2)) $list = $list2;
+
+ $success = 0;
+ $fail = 0;
+ foreach ($list as $record) {
+ if ($name == '@' && ($record['Type'] == 'NS' || $record['Type'] == 'SOA')) continue;
+
+ if ($ttl > 0) $record['TTL'] = $ttl;
+ if ($mx > 0) $record['MX'] = $mx;
+ $recordid = $dns->updateDomainRecord($record['RecordId'], $record['Name'], $type, $value, $record['Line'], $record['TTL'], $record['MX'], $record['Weight'], $record['Remark']);
+ if ($recordid) {
+ if (is_array($record['Value'])) $record['Value'] = implode(',', $record['Value']);
+ $this->add_log($drow['name'], '修改解析', $record['Name'].' ['.$record['Type'].'] '.$record['Value'].' → '.$record['Name'].' ['.$type.'] '.$value.' (线路:'.$record['Line'].' TTL:'.$record['TTL'].')');
+ $success++;
+ } else {
+ $fail++;
+ }
+ }
+ if ($success > 0) {
+ return json(['code' => 0, 'msg' => '成功修改' . $success . '条解析记录']);
+ } elseif($fail > 0) {
+ return json(['code' => -1, 'msg' => $dns->getError()]);
+ } else {
+ return json(['code' => -1, 'msg' => '没有可修改的记录']);
+ }
+ }
+
+ return view('batchedit');
+ }
+
+ public function record_log()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return $this->alert('error', '域名不存在');
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+
+ if (request()->isPost()) {
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+ $page = $offset / $limit + 1;
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ $domainRecords = $dns->getDomainRecordLog($page, $limit);
+ if (!$domainRecords) return json(['total' => 0, 'rows' => []]);
+ return json(['total' => $domainRecords['total'], 'rows' => $domainRecords['list']]);
+ }
+
+ View::assign('domainId', $id);
+ View::assign('domainName', $drow['name']);
+ return view('log');
+ }
+
+ private function add_log($domain, $action, $data)
+ {
+ if (strlen($data) > 500) $data = substr($data, 0, 500);
+ Db::name('log')->insert(['uid' => request()->user['id'], 'domain' => $domain, 'action' => $action, 'data' => $data, 'addtime' => date("Y-m-d H:i:s")]);
+ }
+
+
+ public function weight()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return $this->alert('error', '域名不存在');
+ }
+ if (!checkPermission(0, $drow['name'])) return $this->alert('error', '无权限');
+ if (request()->isAjax()) {
+ $act = input('param.act');
+ if ($act == 'status') {
+ $subdomain = input('post.subdomain', null, 'trim');
+ $status = input('post.status', null, 'trim');
+ $type = input('post.type', null, 'trim');
+ $line = input('post.line', null, 'trim');
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ if ($dns->setWeightStatus($subdomain, $status, $type, $line)) {
+ return json(['code' => 0, 'msg' => '操作成功']);
+ } else {
+ return json(['code' => -1, 'msg' => '操作失败,' . $dns->getError()]);
+ }
+ } elseif ($act == 'update') {
+ $subdomain = input('post.subdomain', null, 'trim');
+ $status = input('post.status', '0', 'trim');
+ $type = input('post.type', null, 'trim');
+ $line = input('post.line', null, 'trim');
+ $weight = input('post.weight');
+ if (empty($subdomain) || empty($type) || empty($line) || $status == '1' && empty($weight)) {
+ return json(['code' => -1, 'msg' => '参数不能为空']);
+ }
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ if ($type == 'CNAME' || $dns->setWeightStatus($subdomain, $status, $type, $line)) {
+ if ($status == '1') {
+ $success = 0;
+ foreach($weight as $recordid => $weight) {
+ if ($dns->updateRecordWeight($recordid, $weight)) {
+ $success++;
+ }
+ }
+ if ($success > 0) {
+ return json(['code' => 0, 'msg' => '成功修改' . $success . '条解析记录权重']);
+ } else {
+ return json(['code' => -1, 'msg' => '修改权重失败,' . $dns->getError()]);
+ }
+ }
+ return json(['code' => 0, 'msg' => '修改成功']);
+ } else {
+ return json(['code' => -1, 'msg' => '修改失败,' . $dns->getError()]);
+ }
+ } else {
+ return json(['code' => -1, 'msg' => '参数错误']);
+ }
+ }
+
+ $dnstype = Db::name('account')->where('id', $drow['aid'])->value('type');
+ if ($dnstype != 'aliyun') {
+ return $this->alert('error', '仅支持阿里云解析的域名');
+ }
+ list($recordLine, $minTTL) = $this->get_line_and_ttl($drow);
+
+ $recordLineArr = [];
+ foreach ($recordLine as $key => $item) {
+ $recordLineArr[] = ['id' => strval($key), 'name' => $item['name'], 'parent' => $item['parent']];
+ }
+
+ $dnsconfig = DnsHelper::$dns_config[$dnstype];
+ $dnsconfig['type'] = $dnstype;
+
+ View::assign('domainId', $id);
+ View::assign('domainName', $drow['name']);
+ View::assign('recordLine', $recordLineArr);
+ View::assign('dnsconfig', $dnsconfig);
+ return view();
+ }
+
+ public function weight_data()
+ {
+ $id = input('param.id/d');
+ $keyword = input('post.keyword', null, 'trim');
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+ if ($limit == 0) {
+ $page = 1;
+ } else {
+ $page = $offset / $limit + 1;
+ }
+
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['total' => 0, 'rows' => []]);
+ }
+ if (!checkPermission(0, $drow['name'])) return json(['total' => 0, 'rows' => []]);
+
+ $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
+ $domainRecords = $dns->getWeightSubDomains($page, $limit, $keyword);
+ return json(['total' => $domainRecords['total'], 'rows' => $domainRecords['list']]);
+ }
+
+ public function expire_notice()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ if ($this->request->isPost()) {
+ $params = input('post.');
+ foreach ($params as $key => $value) {
+ if (empty($key)) {
+ continue;
+ }
+ config_set($key, $value);
+ Cache::delete('configs');
+ }
+ return json(['code' => 0, 'msg' => 'succ']);
+ }
+ return View::fetch();
+ }
+
+ public function update_date()
+ {
+ $id = input('param.id/d');
+ $drow = Db::name('domain')->where('id', $id)->find();
+ if (!$drow) {
+ return json(['code' => -1, 'msg' => '域名不存在']);
+ }
+ if (!checkPermission(0, $drow['name'])) return json(['code' => -1, 'msg' => '无权限']);
+ $result = (new ExpireNoticeService())->updateDomainDate($id, $drow['name']);
+ return json($result);
+ }
+}
diff --git a/app/controller/Optimizeip.php b/app/controller/Optimizeip.php
index 3b33cd4..d7b8f9f 100644
--- a/app/controller/Optimizeip.php
+++ b/app/controller/Optimizeip.php
@@ -1,183 +1,183 @@
-alert('error', '无权限');
- if ($this->request->isPost()) {
- $params = input('post.');
- foreach ($params as $key => $value) {
- if (empty($key)) {
- continue;
- }
- if ($key == 'optimize_ip_min' && intval($value) < 10) {
- return json(['code' => -1, 'msg' => '自动更新时间间隔不能小于10分钟']);
- }
- config_set($key, $value);
- Cache::delete('configs');
- }
- return json(['code' => 0, 'msg' => 'succ']);
- }
- return View::fetch();
- }
-
- public function opiplist()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- return View::fetch();
- }
-
- public function opiplist_data()
- {
- if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
- $type = input('post.type/d', 1);
- $kw = input('post.kw', null, 'trim');
- $status = input('post.status', null);
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
-
- $select = Db::name('optimizeip')->alias('A')->join('domain B', 'A.did = B.id');
- if (!empty($kw)) {
- if ($type == 1) {
- $select->whereLike('rr|B.name', '%' . $kw . '%');
- } elseif ($type == 2) {
- $select->whereLike('remark', '%' . $kw . '%');
- }
- }
- if (!isNullOrEmpty($status)) {
- $select->where('status', intval($status));
- }
- $total = $select->count();
- $list = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name domain')->select();
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function opipform()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
- if ($this->request->isPost()) {
- if ($action == 'add') {
- $task = [
- 'did' => input('post.did/d'),
- 'rr' => input('post.rr', null, 'trim'),
- 'type' => input('post.type/d'),
- 'ip_type' => input('post.ip_type', null, 'trim'),
- 'cdn_type' => input('post.cdn_type/d'),
- 'recordnum' => input('post.recordnum/d'),
- 'ttl' => input('post.ttl/d'),
- 'remark' => input('post.remark', null, 'trim'),
- 'addtime' => date('Y-m-d H:i:s'),
- 'active' => 1
- ];
-
- if (empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])) {
- return json(['code' => -1, 'msg' => '必填项不能为空']);
- }
- if ($task['recordnum'] > 5) {
- return json(['code' => -1, 'msg' => '解析数量不能超过5个']);
- }
- if (Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->find()) {
- return json(['code' => -1, 'msg' => '当前域名的优选IP任务已存在']);
- }
- Db::name('optimizeip')->insert($task);
- return json(['code' => 0, 'msg' => '添加成功']);
- } elseif ($action == 'edit') {
- $id = input('post.id/d');
- $task = [
- 'did' => input('post.did/d'),
- 'rr' => input('post.rr', null, 'trim'),
- 'type' => input('post.type/d'),
- 'ip_type' => input('post.ip_type', null, 'trim'),
- 'cdn_type' => input('post.cdn_type/d'),
- 'recordnum' => input('post.recordnum/d'),
- 'ttl' => input('post.ttl/d'),
- 'remark' => input('post.remark', null, 'trim'),
- ];
-
- if (empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])) {
- return json(['code' => -1, 'msg' => '必填项不能为空']);
- }
- if ($task['recordnum'] > 5) {
- return json(['code' => -1, 'msg' => '解析数量不能超过5个']);
- }
- if (Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->where('id', '<>', $id)->find()) {
- return json(['code' => -1, 'msg' => '当前域名的优选IP任务已存在']);
- }
- Db::name('optimizeip')->where('id', $id)->update($task);
- return json(['code' => 0, 'msg' => '修改成功']);
- } elseif ($action == 'setactive') {
- $id = input('post.id/d');
- $active = input('post.active/d');
- Db::name('optimizeip')->where('id', $id)->update(['active' => $active]);
- return json(['code' => 0, 'msg' => '设置成功']);
- } elseif ($action == 'del') {
- $id = input('post.id/d');
- Db::name('optimizeip')->where('id', $id)->delete();
- return json(['code' => 0, 'msg' => '删除成功']);
- } elseif ($action == 'run') {
- $id = input('post.id/d');
- $task = Db::name('optimizeip')->where('id', $id)->find();
- if (empty($task)) return json(['code' => -1, 'msg' => '任务不存在']);
- try {
- $result = (new OptimizeService())->execute_one($task);
- Db::name('optimizeip')->where('id', $id)->update(['status' => 1, 'errmsg' => null, 'updatetime' => date('Y-m-d H:i:s')]);
- return json(['code' => 0, 'msg' => '优选任务执行成功:' . $result]);
- } catch (Exception $e) {
- Db::name('optimizeip')->where('id', $id)->update(['status' => 2, 'errmsg' => $e->getMessage(), 'updatetime' => date('Y-m-d H:i:s')]);
- return json(['code' => -1, 'msg' => '优选任务执行失败:' . $e->getMessage(), 'stack' => $e->__toString()]);
- }
- } else {
- return json(['code' => -1, 'msg' => '参数错误']);
- }
- }
- $task = null;
- if ($action == 'edit') {
- $id = input('get.id/d');
- $task = Db::name('optimizeip')->where('id', $id)->find();
- if (empty($task)) return $this->alert('error', '任务不存在');
- }
-
- $domains = [];
- foreach (Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->field('A.*')->where('B.type', '<>', 'cloudflare')->select() as $row) {
- $domains[$row['id']] = $row['name'];
- }
- View::assign('domains', $domains);
-
- View::assign('info', $task);
- View::assign('action', $action);
- return View::fetch();
- }
-
- public function queryapi()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $optimize_ip_api = input('post.optimize_ip_api/d');
- $optimize_ip_key = input('post.optimize_ip_key', null, 'trim');
- if (empty($optimize_ip_key)) return json(['code' => -1, 'msg' => '参数不能为空']);
- try {
- $result = (new OptimizeService())->get_license($optimize_ip_api, $optimize_ip_key);
- return json(['code' => 0, 'msg' => '当前积分余额:' . $result]);
- } catch (Exception $e) {
- return json(['code' => -1, 'msg' => $e->getMessage()]);
- }
- }
-
- public function status()
- {
- $run_time = Db::name('optimizeip')->where('active', 1)->order('updatetime', 'desc')->value('updatetime');
- $run_state = $run_time ? (time() - strtotime($run_time) > 3600 ? 0 : 1) : 0;
- return $run_state == 1 ? 'ok' : 'error';
- }
-}
+alert('error', '无权限');
+ if ($this->request->isPost()) {
+ $params = input('post.');
+ foreach ($params as $key => $value) {
+ if (empty($key)) {
+ continue;
+ }
+ if ($key == 'optimize_ip_min' && intval($value) < 10) {
+ return json(['code' => -1, 'msg' => '自动更新时间间隔不能小于10分钟']);
+ }
+ config_set($key, $value);
+ Cache::delete('configs');
+ }
+ return json(['code' => 0, 'msg' => 'succ']);
+ }
+ return View::fetch();
+ }
+
+ public function opiplist()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ return View::fetch();
+ }
+
+ public function opiplist_data()
+ {
+ if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
+ $type = input('post.type/d', 1);
+ $kw = input('post.kw', null, 'trim');
+ $status = input('post.status', null);
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+
+ $select = Db::name('optimizeip')->alias('A')->join('domain B', 'A.did = B.id');
+ if (!empty($kw)) {
+ if ($type == 1) {
+ $select->whereLike('rr|B.name', '%' . $kw . '%');
+ } elseif ($type == 2) {
+ $select->whereLike('remark', '%' . $kw . '%');
+ }
+ }
+ if (!isNullOrEmpty($status)) {
+ $select->where('status', intval($status));
+ }
+ $total = $select->count();
+ $list = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name domain')->select();
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function opipform()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+ if ($this->request->isPost()) {
+ if ($action == 'add') {
+ $task = [
+ 'did' => input('post.did/d'),
+ 'rr' => input('post.rr', null, 'trim'),
+ 'type' => input('post.type/d'),
+ 'ip_type' => input('post.ip_type', null, 'trim'),
+ 'cdn_type' => input('post.cdn_type/d'),
+ 'recordnum' => input('post.recordnum/d'),
+ 'ttl' => input('post.ttl/d'),
+ 'remark' => input('post.remark', null, 'trim'),
+ 'addtime' => date('Y-m-d H:i:s'),
+ 'active' => 1
+ ];
+
+ if (empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])) {
+ return json(['code' => -1, 'msg' => '必填项不能为空']);
+ }
+ if ($task['recordnum'] > 5) {
+ return json(['code' => -1, 'msg' => '解析数量不能超过5个']);
+ }
+ if (Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->find()) {
+ return json(['code' => -1, 'msg' => '当前域名的优选IP任务已存在']);
+ }
+ Db::name('optimizeip')->insert($task);
+ return json(['code' => 0, 'msg' => '添加成功']);
+ } elseif ($action == 'edit') {
+ $id = input('post.id/d');
+ $task = [
+ 'did' => input('post.did/d'),
+ 'rr' => input('post.rr', null, 'trim'),
+ 'type' => input('post.type/d'),
+ 'ip_type' => input('post.ip_type', null, 'trim'),
+ 'cdn_type' => input('post.cdn_type/d'),
+ 'recordnum' => input('post.recordnum/d'),
+ 'ttl' => input('post.ttl/d'),
+ 'remark' => input('post.remark', null, 'trim'),
+ ];
+
+ if (empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])) {
+ return json(['code' => -1, 'msg' => '必填项不能为空']);
+ }
+ if ($task['recordnum'] > 5) {
+ return json(['code' => -1, 'msg' => '解析数量不能超过5个']);
+ }
+ if (Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->where('id', '<>', $id)->find()) {
+ return json(['code' => -1, 'msg' => '当前域名的优选IP任务已存在']);
+ }
+ Db::name('optimizeip')->where('id', $id)->update($task);
+ return json(['code' => 0, 'msg' => '修改成功']);
+ } elseif ($action == 'setactive') {
+ $id = input('post.id/d');
+ $active = input('post.active/d');
+ Db::name('optimizeip')->where('id', $id)->update(['active' => $active]);
+ return json(['code' => 0, 'msg' => '设置成功']);
+ } elseif ($action == 'del') {
+ $id = input('post.id/d');
+ Db::name('optimizeip')->where('id', $id)->delete();
+ return json(['code' => 0, 'msg' => '删除成功']);
+ } elseif ($action == 'run') {
+ $id = input('post.id/d');
+ $task = Db::name('optimizeip')->where('id', $id)->find();
+ if (empty($task)) return json(['code' => -1, 'msg' => '任务不存在']);
+ try {
+ $result = (new OptimizeService())->execute_one($task);
+ Db::name('optimizeip')->where('id', $id)->update(['status' => 1, 'errmsg' => null, 'updatetime' => date('Y-m-d H:i:s')]);
+ return json(['code' => 0, 'msg' => '优选任务执行成功:' . $result]);
+ } catch (Exception $e) {
+ Db::name('optimizeip')->where('id', $id)->update(['status' => 2, 'errmsg' => $e->getMessage(), 'updatetime' => date('Y-m-d H:i:s')]);
+ return json(['code' => -1, 'msg' => '优选任务执行失败:' . $e->getMessage(), 'stack' => $e->__toString()]);
+ }
+ } else {
+ return json(['code' => -1, 'msg' => '参数错误']);
+ }
+ }
+ $task = null;
+ if ($action == 'edit') {
+ $id = input('get.id/d');
+ $task = Db::name('optimizeip')->where('id', $id)->find();
+ if (empty($task)) return $this->alert('error', '任务不存在');
+ }
+
+ $domains = [];
+ foreach (Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->field('A.*')->where('B.type', '<>', 'cloudflare')->select() as $row) {
+ $domains[$row['id']] = $row['name'];
+ }
+ View::assign('domains', $domains);
+
+ View::assign('info', $task);
+ View::assign('action', $action);
+ return View::fetch();
+ }
+
+ public function queryapi()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $optimize_ip_api = input('post.optimize_ip_api/d');
+ $optimize_ip_key = input('post.optimize_ip_key', null, 'trim');
+ if (empty($optimize_ip_key)) return json(['code' => -1, 'msg' => '参数不能为空']);
+ try {
+ $result = (new OptimizeService())->get_license($optimize_ip_api, $optimize_ip_key);
+ return json(['code' => 0, 'msg' => '当前积分余额:' . $result]);
+ } catch (Exception $e) {
+ return json(['code' => -1, 'msg' => $e->getMessage()]);
+ }
+ }
+
+ public function status()
+ {
+ $run_time = Db::name('optimizeip')->where('active', 1)->order('updatetime', 'desc')->value('updatetime');
+ $run_state = $run_time ? (time() - strtotime($run_time) > 3600 ? 0 : 1) : 0;
+ return $run_state == 1 ? 'ok' : 'error';
+ }
+}
diff --git a/app/controller/Schedule.php b/app/controller/Schedule.php
index dace308..8350be4 100644
--- a/app/controller/Schedule.php
+++ b/app/controller/Schedule.php
@@ -1,165 +1,165 @@
-alert('error', '无权限');
- return View::fetch();
- }
-
- public function stask_data()
- {
- if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
- $type = input('post.type/d', 1);
- $kw = input('post.kw', null, 'trim');
- $stype = input('post.stype', null);
- $offset = input('post.offset/d');
- $limit = input('post.limit/d');
-
- $select = Db::name('sctask')->alias('A')->join('domain B', 'A.did = B.id');
- if (!empty($kw)) {
- if ($type == 1) {
- $select->whereLike('rr|B.name', '%' . $kw . '%');
- } elseif ($type == 2) {
- $select->where('recordid', $kw);
- } elseif ($type == 3) {
- $select->where('value', $kw);
- } elseif ($type == 4) {
- $select->whereLike('remark', '%' . $kw . '%');
- }
- }
- if (!isNullOrEmpty($stype)) {
- $select->where('type', $stype);
- }
- $total = $select->count();
- $list = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name domain')->select()->toArray();
-
- foreach ($list as &$row) {
- $row['addtimestr'] = date('Y-m-d H:i:s', $row['addtime']);
- $row['updatetimestr'] = $row['updatetime'] > 0 ? date('Y-m-d H:i:s', $row['updatetime']) : '未运行';
- $row['nexttimestr'] = $row['nexttime'] > 0 ? date('Y-m-d H:i:s', $row['nexttime']) : '无';
- }
-
- return json(['total' => $total, 'rows' => $list]);
- }
-
- public function stask_op()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
- if ($action == 'add') {
- $task = [
- 'did' => input('post.did/d'),
- 'rr' => input('post.rr', null, 'trim'),
- 'recordid' => input('post.recordid', null, 'trim'),
- 'type' => input('post.type/d'),
- 'cycle' => input('post.cycle/d'),
- 'switchtype' => input('post.switchtype/d'),
- 'switchdate' => input('post.switchdate', null, 'trim'),
- 'switchtime' => input('post.switchtime', null, 'trim'),
- 'value' => input('post.value', null, 'trim'),
- 'line' => input('post.line', null, 'trim'),
- 'remark' => input('post.remark', null, 'trim'),
- 'recordinfo' => input('post.recordinfo', null, 'trim'),
- 'addtime' => time(),
- 'active' => 1
- ];
-
- if (empty($task['did']) || empty($task['rr']) || empty($task['recordid'])) {
- return json(['code' => -1, 'msg' => '必填项不能为空']);
- }
- if (Db::name('sctask')->where('recordid', $task['recordid'])->where('switchtype', $task['switchtype'])->where('switchtime', $task['switchtime'])->find()) {
- return json(['code' => -1, 'msg' => '当前定时切换策略已存在']);
- }
- $id = Db::name('sctask')->insertGetId($task);
- $row = Db::name('sctask')->where('id', $id)->find();
- (new ScheduleService())->update_nexttime($row);
- return json(['code' => 0, 'msg' => '添加成功']);
- } elseif ($action == 'edit') {
- $id = input('post.id/d');
- $task = [
- 'did' => input('post.did/d'),
- 'rr' => input('post.rr', null, 'trim'),
- 'recordid' => input('post.recordid', null, 'trim'),
- 'type' => input('post.type/d'),
- 'cycle' => input('post.cycle/d'),
- 'switchtype' => input('post.switchtype/d'),
- 'switchdate' => input('post.switchdate', null, 'trim'),
- 'switchtime' => input('post.switchtime', null, 'trim'),
- 'value' => input('post.value', null, 'trim'),
- 'line' => input('post.line', null, 'trim'),
- 'remark' => input('post.remark', null, 'trim'),
- 'recordinfo' => input('post.recordinfo', null, 'trim'),
- ];
-
- if (empty($task['did']) || empty($task['rr']) || empty($task['recordid'])) {
- return json(['code' => -1, 'msg' => '必填项不能为空']);
- }
- if (Db::name('sctask')->where('recordid', $task['recordid'])->where('switchtype', $task['switchtype'])->where('switchtime', $task['switchtime'])->where('id', '<>', $id)->find()) {
- return json(['code' => -1, 'msg' => '当前定时切换策略已存在']);
- }
- Db::name('sctask')->where('id', $id)->update($task);
- $row = Db::name('sctask')->where('id', $id)->find();
- (new ScheduleService())->update_nexttime($row);
- return json(['code' => 0, 'msg' => '修改成功']);
- } elseif ($action == 'setactive') {
- $id = input('post.id/d');
- $active = input('post.active/d');
- Db::name('sctask')->where('id', $id)->update(['active' => $active]);
- return json(['code' => 0, 'msg' => '设置成功']);
- } elseif ($action == 'del') {
- $id = input('post.id/d');
- Db::name('sctask')->where('id', $id)->delete();
- return json(['code' => 0, 'msg' => '删除成功']);
- } elseif ($action == 'operation') {
- $ids = input('post.ids');
- $success = 0;
- foreach ($ids as $id) {
- if (input('post.act') == 'delete') {
- Db::name('sctask')->where('id', $id)->delete();
- $success++;
- } elseif (input('post.act') == 'open' || input('post.act') == 'close') {
- $isauto = input('post.act') == 'open' ? 1 : 0;
- Db::name('sctask')->where('id', $id)->update(['active' => $isauto]);
- $success++;
- }
- }
- return json(['code' => 0, 'msg' => '成功操作' . $success . '个定时切换策略']);
- } else {
- return json(['code' => -1, 'msg' => '参数错误']);
- }
- }
-
- public function staskform()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $action = input('param.action');
- $task = null;
- if ($action == 'edit') {
- $id = input('get.id/d');
- $task = Db::name('sctask')->where('id', $id)->find();
- if (empty($task)) return $this->alert('error', '切换策略不存在');
- }
-
- $domains = [];
- $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);
-
- View::assign('info', $task);
- View::assign('action', $action);
- return View::fetch();
- }
-
-}
+alert('error', '无权限');
+ return View::fetch();
+ }
+
+ public function stask_data()
+ {
+ if (!checkPermission(2)) return json(['total' => 0, 'rows' => []]);
+ $type = input('post.type/d', 1);
+ $kw = input('post.kw', null, 'trim');
+ $stype = input('post.stype', null);
+ $offset = input('post.offset/d');
+ $limit = input('post.limit/d');
+
+ $select = Db::name('sctask')->alias('A')->join('domain B', 'A.did = B.id');
+ if (!empty($kw)) {
+ if ($type == 1) {
+ $select->whereLike('rr|B.name', '%' . $kw . '%');
+ } elseif ($type == 2) {
+ $select->where('recordid', $kw);
+ } elseif ($type == 3) {
+ $select->where('value', $kw);
+ } elseif ($type == 4) {
+ $select->whereLike('remark', '%' . $kw . '%');
+ }
+ }
+ if (!isNullOrEmpty($stype)) {
+ $select->where('type', $stype);
+ }
+ $total = $select->count();
+ $list = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name domain')->select()->toArray();
+
+ foreach ($list as &$row) {
+ $row['addtimestr'] = date('Y-m-d H:i:s', $row['addtime']);
+ $row['updatetimestr'] = $row['updatetime'] > 0 ? date('Y-m-d H:i:s', $row['updatetime']) : '未运行';
+ $row['nexttimestr'] = $row['nexttime'] > 0 ? date('Y-m-d H:i:s', $row['nexttime']) : '无';
+ }
+
+ return json(['total' => $total, 'rows' => $list]);
+ }
+
+ public function stask_op()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+ if ($action == 'add') {
+ $task = [
+ 'did' => input('post.did/d'),
+ 'rr' => input('post.rr', null, 'trim'),
+ 'recordid' => input('post.recordid', null, 'trim'),
+ 'type' => input('post.type/d'),
+ 'cycle' => input('post.cycle/d'),
+ 'switchtype' => input('post.switchtype/d'),
+ 'switchdate' => input('post.switchdate', null, 'trim'),
+ 'switchtime' => input('post.switchtime', null, 'trim'),
+ 'value' => input('post.value', null, 'trim'),
+ 'line' => input('post.line', null, 'trim'),
+ 'remark' => input('post.remark', null, 'trim'),
+ 'recordinfo' => input('post.recordinfo', null, 'trim'),
+ 'addtime' => time(),
+ 'active' => 1
+ ];
+
+ if (empty($task['did']) || empty($task['rr']) || empty($task['recordid'])) {
+ return json(['code' => -1, 'msg' => '必填项不能为空']);
+ }
+ if (Db::name('sctask')->where('recordid', $task['recordid'])->where('switchtype', $task['switchtype'])->where('switchtime', $task['switchtime'])->find()) {
+ return json(['code' => -1, 'msg' => '当前定时切换策略已存在']);
+ }
+ $id = Db::name('sctask')->insertGetId($task);
+ $row = Db::name('sctask')->where('id', $id)->find();
+ (new ScheduleService())->update_nexttime($row);
+ return json(['code' => 0, 'msg' => '添加成功']);
+ } elseif ($action == 'edit') {
+ $id = input('post.id/d');
+ $task = [
+ 'did' => input('post.did/d'),
+ 'rr' => input('post.rr', null, 'trim'),
+ 'recordid' => input('post.recordid', null, 'trim'),
+ 'type' => input('post.type/d'),
+ 'cycle' => input('post.cycle/d'),
+ 'switchtype' => input('post.switchtype/d'),
+ 'switchdate' => input('post.switchdate', null, 'trim'),
+ 'switchtime' => input('post.switchtime', null, 'trim'),
+ 'value' => input('post.value', null, 'trim'),
+ 'line' => input('post.line', null, 'trim'),
+ 'remark' => input('post.remark', null, 'trim'),
+ 'recordinfo' => input('post.recordinfo', null, 'trim'),
+ ];
+
+ if (empty($task['did']) || empty($task['rr']) || empty($task['recordid'])) {
+ return json(['code' => -1, 'msg' => '必填项不能为空']);
+ }
+ if (Db::name('sctask')->where('recordid', $task['recordid'])->where('switchtype', $task['switchtype'])->where('switchtime', $task['switchtime'])->where('id', '<>', $id)->find()) {
+ return json(['code' => -1, 'msg' => '当前定时切换策略已存在']);
+ }
+ Db::name('sctask')->where('id', $id)->update($task);
+ $row = Db::name('sctask')->where('id', $id)->find();
+ (new ScheduleService())->update_nexttime($row);
+ return json(['code' => 0, 'msg' => '修改成功']);
+ } elseif ($action == 'setactive') {
+ $id = input('post.id/d');
+ $active = input('post.active/d');
+ Db::name('sctask')->where('id', $id)->update(['active' => $active]);
+ return json(['code' => 0, 'msg' => '设置成功']);
+ } elseif ($action == 'del') {
+ $id = input('post.id/d');
+ Db::name('sctask')->where('id', $id)->delete();
+ return json(['code' => 0, 'msg' => '删除成功']);
+ } elseif ($action == 'operation') {
+ $ids = input('post.ids');
+ $success = 0;
+ foreach ($ids as $id) {
+ if (input('post.act') == 'delete') {
+ Db::name('sctask')->where('id', $id)->delete();
+ $success++;
+ } elseif (input('post.act') == 'open' || input('post.act') == 'close') {
+ $isauto = input('post.act') == 'open' ? 1 : 0;
+ Db::name('sctask')->where('id', $id)->update(['active' => $isauto]);
+ $success++;
+ }
+ }
+ return json(['code' => 0, 'msg' => '成功操作' . $success . '个定时切换策略']);
+ } else {
+ return json(['code' => -1, 'msg' => '参数错误']);
+ }
+ }
+
+ public function staskform()
+ {
+ if (!checkPermission(2)) return $this->alert('error', '无权限');
+ $action = input('param.action');
+ $task = null;
+ if ($action == 'edit') {
+ $id = input('get.id/d');
+ $task = Db::name('sctask')->where('id', $id)->find();
+ if (empty($task)) return $this->alert('error', '切换策略不存在');
+ }
+
+ $domains = [];
+ $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);
+
+ View::assign('info', $task);
+ View::assign('action', $action);
+ return View::fetch();
+ }
+
+}
diff --git a/app/controller/System.php b/app/controller/System.php
index fd5dbd7..0e2ebf3 100644
--- a/app/controller/System.php
+++ b/app/controller/System.php
@@ -1,149 +1,149 @@
-alert('error', '无权限');
- $params = input('post.');
- if (isset($params['mail_type']) && isset($params['mail_name2']) && $params['mail_type'] > 0) {
- $params['mail_name'] = $params['mail_name2'];
- unset($params['mail_name2']);
- }
- foreach ($params as $key => $value) {
- if (empty($key)) {
- continue;
- }
- config_set($key, $value);
- }
- Cache::delete('configs');
- return json(['code' => 0, 'msg' => 'succ']);
- }
-
- public function loginset()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- return View::fetch();
- }
-
- public function noticeset()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- return View::fetch();
- }
-
- public function proxyset()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- return View::fetch();
- }
-
- public function mailtest()
- {
- if (!checkPermission(2)) return $this->alert('error', '无权限');
- $mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name');
- if (empty($mail_name)) return json(['code' => -1, 'msg' => '您还未设置邮箱!']);
- $result = \app\utils\MsgNotice::send_mail($mail_name, '邮件发送测试。', '这是一封测试邮件!
-
-
-
-
-
+
+
+
+
+ CNAME代理可以让未在本系统添加的域名自动申请SSL证书,支持所有DNS服务商。
注:仅支持基于ACME的证书类型,不支持腾讯云等云厂商SSL证书。
CNAME代理可以让未在本系统添加的域名自动申请SSL证书,支持所有DNS服务商。
注:仅支持基于ACME的证书类型,不支持腾讯云等云厂商SSL证书。
1、php需要安装swoole组件
-2、在命令行执行以下命令启动进程:
-cd {:app()->getRootPath()} && php think dmtask
3、也可以使用进程守护管理器,添加守护进程。
运行目录:{:app()->getRootPath()}
启动命令:php think dmtask
1、php需要安装swoole组件
+2、在命令行执行以下命令启动进程:
+cd {:app()->getRootPath()} && php think dmtask
3、也可以使用进程守护管理器,添加守护进程。
运行目录:{:app()->getRootPath()}
启动命令:php think dmtask
| ID | -域名 | -添加结果 | -
|---|---|---|
| {{item.id}} | -- |
| ID | +域名 | +添加结果 | +
|---|---|---|
| {{item.id}} | ++ |
| ID | -域名 | -修改结果 | -
|---|---|---|
| {{item.id}} | -- |
| ID | +域名 | +修改结果 | +
|---|---|---|
| {{item.id}} | ++ |
| 框架版本 | -{$info.framework_version} | -
| PHP版本 | -{$info.php_version} | -
| 数据库版本 | -{$info.mysql_version} | -
| Web服务器 | -{$info.software} | -
| 服务器时间 | -{$info.date} | -
| 框架版本 | +{$info.framework_version} | +
| PHP版本 | +{$info.php_version} | +
| 数据库版本 | +{$info.mysql_version} | +
| Web服务器 | +{$info.software} | +
| 服务器时间 | +{$info.date} | +
由于CloudFlare官方IP是泛播路由,同一个IP在不同地区不同运营商所链接的机房是不同的,速度或延迟也会有区别。目前网上也有很多CF优选CNAME服务,然而公共的CNAME可能无法满足稳定性和安全性的需要。
-本功能可以获取CloudFlare最新的优选IP地址(分为电信/联通/移动线路),并自动更新到域名解析记录。
-由于CloudFlare官方IP是泛播路由,同一个IP在不同地区不同运营商所链接的机房是不同的,速度或延迟也会有区别。目前网上也有很多CF优选CNAME服务,然而公共的CNAME可能无法满足稳定性和安全性的需要。
+本功能可以获取CloudFlare最新的优选IP地址(分为电信/联通/移动线路),并自动更新到域名解析记录。
+