DomainInfoLogic.php 8.7 KB
<?php

namespace App\Http\Logic\Aside\Domain;


use App\Http\Logic\Aside\BaseLogic;
use App\Models\Devops\ServerConfig;
use App\Models\Domain\DomainInfo;
use App\Models\Project\DeployOptimize;
use App\Models\Project\Project;
use App\Utils\HttpUtils;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Carbon;
use Symfony\Component\Process\Process;

class DomainInfoLogic extends BaseLogic
{

    public function __construct()
    {
        parent::__construct();
        $this->model = new DomainInfo();
        $this->param = $this->requestAll;

    }

    /**
     * @remark :保存域名
     * @name   :createDomain
     * @author :lyh
     * @method :post
     * @time   :2023/8/1 14:52
     */
    public function saveDomain()
    {
        $domain = parse_url($this->param['domain'], PHP_URL_HOST);
        if(!empty($domain)){
            $this->param['domain'] = trim($domain['host']);
        }
        //验证域名
        $this->verifyDomain($this->param['domain'],isset($this->param['id']) ?? '');
        if(isset($this->param['id']) && !empty($this->param['id'])){
            $rs = $this->model->edit($this->param,['id'=>$this->param['id']]);
        }else{
            $rs = $this->model->add($this->param);
        }
        if($rs === false){
            $this->fail('error');
        }
        return $this->success();
    }


    /**
     * @remark :验证域名是否存在
     * @name   :verifyDomain
     * @author :lyh
     * @method :post
     * @time   :2023/8/1 14:59
     */
    public function verifyDomain($domain,$id = ''){
        if(!empty($id)){
            $info = $this->model->read(['domain'=>$domain,'id'=>['!=',$id]]);
            if ($info !== false) {
                $this->fail('当前域名已存在');
            }
        }else{
            $info = $this->model->read(['domain'=>$domain]);
            if ($info !== false) {
                $this->fail('当前域名已存在');
            }
        }
        return $this->success();
    }

    /**
     * @remark :修改当前域名状态
     * @name   :editStatus
     * @author :lyh
     * @method :post
     * @time   :2023/8/1 15:43
     */
    public function editDomainStatus(){
        //查看当前域名是否有项目在使用
        if($this->param['status'] != $this->model::STATUS_ONE){
            $info = $this->model->read(['id'=>$this->param['id']]);
            if($info === false){
                $this->fail('当前域名有项目正在使用中');
            }
        }
        $rs = $this->model->edit(['status'=>$this->param['status']],['id'=>$this->param['id']]);
        if($rs === false){
            $this->fail('error');
        }
        return $this->success();
    }

    /**
     * @remark :获取所有项目列表
     * @name   :getProjectList
     * @author :lyh
     * @method :post
     * @time   :2023/8/1 16:10
     */
    public function getProjectList($map){
        $projectModel = new Project();
        $lists = $projectModel->list($map,'id',['id','title']);
        return $this->success($lists);
    }

    /**
     * @remark :删除域名
     * @name   :delDomain
     * @author :lyh
     * @method :post
     * @time   :2023/8/1 15:41
     */
    public function delDomain(){
        $ids = $this->param['id'];
        foreach ($ids as $k => $v){
            $info = $this->model->read(['id'=>$v]);
            $deployOptimizeModel = new DeployOptimize();
            $domainInfo = $deployOptimizeModel->read(['domain'=>$info['domain']]);
            if($domainInfo !== false){
                $this->fail('当前域名正在使用中');
            }
        }
        $this->param['id'] = ['in',$ids];
        $rs = $this->model->del($this->param);
        if($rs === false){
            $this->fail('error');
        }
        return $this->success();
    }


    public function infoDomain(){
        $info = $this->model->read(['id'=>$this->param['id']]);
        if($info === false){
            $this->fail('当前数据不存在或者已被删除');
        }
        if(!empty($info['project_id'])){
            $info['company'] = (new Project())->read(['id'=>$info['project_id']],['title'])['title'];
        }
        return $this->success($info);
    }

    /**
     * 编辑网站证书
     * @return array
     * @throws \App\Exceptions\AsideGlobalException
     * @throws \App\Exceptions\BsideGlobalException
     * @author Akun
     * @date 2023/10/17 11:52
     */
    public function setDomainSsl($initDomain,$domain,$rewrite,$other_domain)
    {
        if($this->param['type'] == 2){
            if(empty($this->param['key'])){
                $this->fail('证书KEY值不能为空');
            }
            if(empty($this->param['cert'])){
                $this->fail('证书cert值不能为空');
            }
            $api_url = 'http://'.$initDomain.'/api/setSsl';
            $api_param = [
                'domain' => $domain,
                'private_key' => $this->param['key'],
                'cert' => $this->param['cert'],
                'rewrite'=>$rewrite,
                'other_domain'=>$other_domain
            ];
        }else{
            $api_url = 'http://'.$initDomain.'/api/applySsl';
            $api_param = ['domain' => $domain,'rewrite'=>$rewrite,'other_domain'=>$other_domain];
        }
        try {
            $rs = HttpUtils::get($api_url, $api_param);
            $rs = json_decode($rs, true);
            if(isset($rs['status']) && $rs['status'] == 200){
                return $this->success();
            }else{
                $this->fail($rs['message']??'');
            }
        } catch (\Exception | GuzzleException $e) {
            errorLog('创建站点', $api_param, $e);
            $this->fail('编辑证书失败');
        }
        return $this->success();
    }

    /**
     * @remark :保存证书相关配置
     * @name   :sslSave
     * @author :lyh
     * @method :post
     * @time   :2023/11/6 10:50
     */
    public function sslSave(){
        $info = $this->model->read(['id'=>$this->param['id']]);
        if($info === false){
            $this->fail('当前数据不存在或者已被删除');
        }
        //获取项目数据
        $project_model = new Project();
        $project_info = $project_model->read(['id'=>$info['project_id']],'serve_id');
        if($project_info === false){
            $this->fail('获取项目数据失败');
        }
        $server_model = new ServerConfig();
        $server_info = $server_model->read(['id'=>$project_info['serve_id']],['init_domain', 'host']);
        if($server_info === false){
            $this->fail('获取服务器数据失败');
        }

        //域名是否都已经解析
        if($info['domain'] && !$this->check_cname($info['domain'], $server_info)){
            $this->fail('域名' . $info['domain'] . '未解析至目标服务器');
        }
        foreach ($this->param['other_domain']??[] as $other_domain){
            if($other_domain && !$this->check_cname($other_domain, $server_info)){
                $this->fail('域名' . $other_domain . '未解析至目标服务器');
            }
        }

        //保存301跳转数据+其他域名
        $data = [
            'other_domain'=>json_encode($this->param['other_domain'] ?? []),
            'extend_config'=>json_encode($this->param['extend_config'] ?? []),
            'type'=>$this->param['type'],
            'private_key' => $this->param['key'] ?? '',
            'private_cert' => $this->param['cert'] ?? '',
        ];
        $this->model->edit($data,['id'=>$this->param['id']]);
        //生成证书
        $this->setDomainSsl($server_info['init_domain'],$info['domain'],$this->param['extend_config'] ?? [],$this->param['other_domain'] ?? []);
        return $this->success();
    }


    /**
     * 验证是否cname或者A记录解析到目标服务器
     * @param $domain
     * @param $server_info
     * @return mixed
     * @author zbj
     * @date 2023/11/13
     */
    public function check_cname($domain, $server_info){
        $checkA = false;
        $checkCname = false;

        $process = new Process(['nslookup', '-qt=a', $domain]);
        $process->run();
        $output = explode(PHP_EOL, $process->getOutput());
        foreach ($output as $line){
            if($line){
                $checkA = strpos($line, $server_info['host']) !== false;
            }
        }
        if($checkA){
            return $domain;
        }

        //是否cname
        $process = new Process(['nslookup', '-qt=cname', $domain]);
        $process->run();
        $output = explode(PHP_EOL, $process->getOutput());
        foreach ($output as $line){
            if($line){
                $checkCname = (strpos($line, $server_info['init_domain']) !== false);
            }
        }
        if($checkCname){
            return $domain;

        }
        return false;
    }
}