pull/267/head
midoks 3 years ago
parent 9abe3ec166
commit 4f59d07416
  1. 52
      class/core/cert_request.py
  2. 2
      class/core/files_api.py
  3. 46
      class/core/site_api.py
  4. 43
      route/static/app/public.js
  5. 78
      route/static/app/site.js

@ -1046,12 +1046,12 @@ fullchain.pem 粘贴到证书输入框
self.saveCert(cert, index) self.saveCert(cert, index)
return cert return cert
def applyCert(self, domains, auth_type='dns', auth_to='Dns_com|None|None', args={}): def applyCert(self, domains, auth_type='http', auth_to='Dns_com|None|None', args={}):
writeLog("", "wb+") writeLog("", "wb+")
try: try:
self.getApis() self.getApis()
index = None index = None
if args.index: if 'index' in args and args.index:
index = args.index index = args.index
if not index: if not index:
# 判断是否只想验证域名 # 判断是否只想验证域名
@ -1084,7 +1084,11 @@ fullchain.pem 粘贴到证书输入框
else: else:
msg = ex msg = ex
writeLog(mw.getTracebackInfo()) writeLog(mw.getTracebackInfo())
return mw.returnJson(False, msg)
cert = {}
cert['status'] = False
cert['msg'] = msg
return cert
# 取根域名和记录值 # 取根域名和记录值
def extractZone(self, domain_name): def extractZone(self, domain_name):
@ -1218,47 +1222,13 @@ fullchain.pem 粘贴到证书输入框
except: except:
write_log("|-[{}]续签失败".format(siteName)) write_log("|-[{}]续签失败".format(siteName))
def apply_cert_api(self, args): # 外部API - START ----------------------------------------------------------
def applyCertApi(self, args):
''' '''
申请证书 - api 申请证书 - api
''' '''
if not 'id' in args: return self.applyCert(args['domains'], args['auth_type'], args['auth_to'])
return mw.returnJson(False, '网站id不能为空!') # 外部API - END ----------------------------------------------------------
# 是否为指定站点
if mw.M('sites').where('id=?', (args.id,)).count():
project_info = public.M('sites').where(
'id=?', (args.id,)).getField('project_config')
try:
project_info = json.loads(project_info)
if not os.path.exists(project_info['ssl_path']):
os.makedirs(project_info['ssl_path'])
path = project_info['ssl_path']
args.auth_to = path
if args.auto_wildcard == '1':
self._auto_wildcard = True
return self.applyCert(json.loads(args.domains), args.auth_type, args.auth_to)
except:
return mw.returnJson(False, '当前Java项目配置文件存在问题,请重新建立')
else:
if re.match(r"^\d+$", args.auth_to):
import panelSite
path = mw.M('sites').where(
'id=?', (args.id,)).getField('path')
args.auth_to = path + '/' + panelSite.panelSite().GetRunPath(args)
args.auth_to = args.auth_to.replace("//", "/")
if args.auth_to[-1] == '/':
args.auth_to = args.auth_to[:-1]
if not os.path.exists(args.auth_to):
return mw.returnJson(False, '无效的站点目录,请检查指定站点是否存在!')
check_result = self.checkAuthEnv(args)
if check_result:
return check_result
if args.auto_wildcard == '1':
self._auto_wildcard = True
return self.apply_cert(json.loads(args.domains), args.auth_type, args.auth_to)
def renewCert(self, index): def renewCert(self, index):
writeLog("", "wb+") writeLog("", "wb+")

@ -39,7 +39,7 @@ class files_api:
data = mw.getLastLine(path, int(line)) data = mw.getLastLine(path, int(line))
return mw.returnJson(True, 'OK', data) return mw.returnJson(True, 'OK', data)
except Exception as ex: except Exception as ex:
return mw.returnJson(False, u'无法正确读取文件!' + str(ex)) return mw.returnJson(False, '无法正确读取文件!' + str(ex))
def saveBodyApi(self): def saveBodyApi(self):
path = request.form.get('path', '') path = request.form.get('path', '')

@ -611,6 +611,12 @@ class site_api:
mw.restartWeb() mw.restartWeb()
return mw.returnJson(True, 'SSL已关闭!') return mw.returnJson(True, 'SSL已关闭!')
def getLetLogsApi(self):
log_file = mw.getRunDir() + '/logs/letsencrypt.log'
if not os.path.exists(log_file):
mw.execShell('touch ' + log_file)
return mw.returnJson(True, 'OK', log_file)
def createLetApi(self): def createLetApi(self):
siteName = request.form.get('siteName', '') siteName = request.form.get('siteName', '')
updateOf = request.form.get('updateOf', '') updateOf = request.form.get('updateOf', '')
@ -648,28 +654,30 @@ class site_api:
if os.path.exists(proxy_dir_file): if os.path.exists(proxy_dir_file):
return mw.returnJson(False, '检测到您的站点做了反向代理设置,请先关闭反向代理!') return mw.returnJson(False, '检测到您的站点做了反向代理设置,请先关闭反向代理!')
letpath = self.sslDir + siteName auth_to = self.getSitePath(siteName)
csrpath = letpath + "/fullchain.pem" # 生成证书路径 to_args = {
keypath = letpath + "/privkey.pem" # 密钥文件路径 'domains': domains,
'auth_type': 'http',
'auth_to': auth_to,
}
siteInfo = mw.M('sites').where( # print(to_args)
'name=?', (siteName,)).field('id,name,path').find() import cert_request
path = self.getSitePath(siteName) data = cert_request.cert_request().applyCertApi(to_args)
srcPath = siteInfo['path']
# print(domains) # letpath = self.sslDir + siteName
# print(cmd) # csrpath = letpath + "/fullchain.pem" # 生成证书路径
result = mw.execShell(cmd) # keypath = letpath + "/privkey.pem" # 密钥文件路径
# 写入配置文件 # # 写入配置文件
result = self.setSslConf(siteName) # result = self.setSslConf(siteName)
if not result['status']: # if not result['status']:
return mw.getJson(result) # return mw.getJson(result)
result['csr'] = mw.readFile(csrpath) # result['csr'] = mw.readFile(csrpath)
result['key'] = mw.readFile(keypath) # result['key'] = mw.readFile(keypath)
mw.restartWeb()
return mw.returnJson(True, 'OK', result) # mw.restartWeb()
return mw.returnJson(data['status'], '', data['msg'])
def createAcmeApi(self): def createAcmeApi(self):
siteName = request.form.get('siteName', '') siteName = request.form.get('siteName', '')
@ -1092,10 +1100,10 @@ class site_api:
mw.M('binding').add('pid,domain,port,path,addtime', mw.M('binding').add('pid,domain,port,path,addtime',
(pid, domain, port, dirName, mw.getDate())) (pid, domain, port, dirName, mw.getDate()))
mw.restartWeb()
msg = mw.getInfo('网站[{1}]子目录[{2}]绑定到[{3}]', msg = mw.getInfo('网站[{1}]子目录[{2}]绑定到[{3}]',
(siteInfo['name'], dirName, domain)) (siteInfo['name'], dirName, domain))
mw.writeLog('网站管理', msg) mw.writeLog('网站管理', msg)
mw.restartWeb()
return mw.returnJson(True, '添加成功!') return mw.returnJson(True, '添加成功!')
def delDirBindApi(self): def delDirBindApi(self):

@ -1607,6 +1607,49 @@ function remove_ssh_menu() {
$(".contextmenu").remove(); $(".contextmenu").remove();
} }
//显示进度
function showSpeed(filename) {
$.post('/files/get_last_body', { num: 10,path: filename}, function (rdata) {
if ($("#speed_log_lst").text() == ''){
return;
}
if (rdata.status) {
$("#speed_log_lst").text(rdata.data);
$("#speed_log_lst").scrollTop($("#speed_log_lst")[0].scrollHeight);
}
setTimeout(function () { showSpeed(filename); }, 1000);
},'json');
}
/**
* 显示进度窗口
*/
function showSpeedWindow(msg, speed_log_func_name, callback){
var speed_msg = "<pre style='margin-bottom: 0px;height:250px;text-align: left;background-color: #000;color: #fff;white-space: pre-wrap;' id='speed_log_lst'>[MSG]</pre>";
var showSpeedKey = layer.open({
title: false,
type: 1,
closeBtn: 0,
shade: 0.3,
area: "500px",
offset: "30%",
content: speed_msg.replace('[MSG]', msg),
success: function (layers, index) {
var url = speed_log_func_name.replace('.','/');
$.post('/'+url, {}, function(rdata){
if (rdata.status){
setTimeout(function () {
showSpeed(rdata.data);
}, 1000);
} else {
layer.msg("缺少指定文件!");
}
},'json');
if (callback) {callback(layers,index,showSpeedKey);}
}
});
}
/*** 其中功能,针对插件通过库使用 start ***/ /*** 其中功能,针对插件通过库使用 start ***/
//字符串转数组对象 //字符串转数组对象

@ -1031,9 +1031,9 @@ function webEdit(id,website,endTime,addtime){
+" "+eMenu+"" +" "+eMenu+""
+"</div>" +"</div>"
+"<div id='webedit-con' class='bt-w-con webedit-con pd15'></div>" +"<div id='webedit-con' class='bt-w-con webedit-con pd15'></div>"
+"</div>" +"</div>",
});
domainEdit(id,website); success:function(){
//域名输入提示 //域名输入提示
var placeholder = "<div class='placeholder'>每行填写一个域名,默认为80端口<br>泛解析添加方法 *.domain.com<br>如另加端口格式为 www.domain.com:88</div>"; var placeholder = "<div class='placeholder'>每行填写一个域名,默认为80端口<br>泛解析添加方法 *.domain.com<br>如另加端口格式为 www.domain.com:88</div>";
$('#newdomain').after(placeholder); $('#newdomain').after(placeholder);
@ -1056,6 +1056,10 @@ function webEdit(id,website,endTime,addtime){
$(".bt-w-menu p").click(function(){ $(".bt-w-menu p").click(function(){
$(this).addClass("bgw").siblings().removeClass("bgw"); $(this).addClass("bgw").siblings().removeClass("bgw");
}); });
domainEdit(id,website);
}
});
} }
//取网站日志 //取网站日志
@ -1685,7 +1689,6 @@ function toProxy(siteName, type, obj) {
layer.msg(res.msg, {icon: 2}); layer.msg(res.msg, {icon: 2});
} }
},'json'); },'json');
} }
}); });
} }
@ -1983,7 +1986,7 @@ function opSSL(type, id, siteName, callback){
<li>如果浏览器提示证书链不完整,请检查是否正确拼接PEM证书</li><li>PEM = .crt + (root_bundle).crt</li>\ <li>如果浏览器提示证书链不完整,请检查是否正确拼接PEM证书</li><li>PEM = .crt + (root_bundle).crt</li>\
<li>在未指定SSL默认站点时,未开启SSL的站点使用HTTPS会直接访问到已开启SSL的站点</li></ul>'; <li>在未指定SSL默认站点时,未开启SSL的站点使用HTTPS会直接访问到已开启SSL的站点</li></ul>';
var lets = '<div class="btssl"><div class="label-input-group">' var lets = '<div class="apply_ssl"><div class="label-input-group">'
+ '<div class="line mtb10"><form><span class="tname text-center">验证方式</span><div style="margin-top:7px;display:inline-block"><input type="radio" name="c_type" onclick="file_check()" id="check_file" checked="checked" />\ + '<div class="line mtb10"><form><span class="tname text-center">验证方式</span><div style="margin-top:7px;display:inline-block"><input type="radio" name="c_type" onclick="file_check()" id="check_file" checked="checked" />\
<label class="mr20" for="check_file" style="font-weight:normal">文件验证</label></label></div></form></div>' <label class="mr20" for="check_file" style="font-weight:normal">文件验证</label></label></div></form></div>'
+ '<div class="check_message line"><div style="margin-left:100px"><input type="checkbox" name="checkDomain" id="checkDomain" checked=""><label class="mr20" for="checkDomain" style="font-weight:normal">提前校验域名(提前发现问题,减少失败率)</label></div></div>' + '<div class="check_message line"><div style="margin-left:100px"><input type="checkbox" name="checkDomain" id="checkDomain" checked=""><label class="mr20" for="checkDomain" style="font-weight:normal">提前校验域名(提前发现问题,减少失败率)</label></div></div>'
@ -1996,7 +1999,7 @@ function opSSL(type, id, siteName, callback){
<li>在未指定SSL默认站点时,未开启SSL的站点使用HTTPS会直接访问到已开启SSL的站点</li></ul>' <li>在未指定SSL默认站点时,未开启SSL的站点使用HTTPS会直接访问到已开启SSL的站点</li></ul>'
+ '</div>'; + '</div>';
var acme = '<div class="btssl"><div class="label-input-group">' var acme = '<div class="apply_ssl"><div class="label-input-group">'
+ '<div class="line mtb10"><form><span class="tname text-center">验证方式</span><div style="margin-top:7px;display:inline-block"><input type="radio" name="c_type" onclick="file_check()" id="check_file" checked="checked" />\ + '<div class="line mtb10"><form><span class="tname text-center">验证方式</span><div style="margin-top:7px;display:inline-block"><input type="radio" name="c_type" onclick="file_check()" id="check_file" checked="checked" />\
<label class="mr20" for="check_file" style="font-weight:normal">文件验证</label></label></div></form></div>' <label class="mr20" for="check_file" style="font-weight:normal">文件验证</label></label></div></form></div>'
+ '<div class="check_message line"><div style="margin-left:100px"><input type="checkbox" name="checkDomain" id="checkDomain" checked=""><label class="mr20" for="checkDomain" style="font-weight:normal">提前校验域名(提前发现问题,减少失败率)</label></div></div>' + '<div class="check_message line"><div style="margin-left:100px"><input type="checkbox" name="checkDomain" id="checkDomain" checked=""><label class="mr20" for="checkDomain" style="font-weight:normal">提前校验域名(提前发现问题,减少失败率)</label></div></div>'
@ -2137,7 +2140,7 @@ function opSSL(type, id, siteName, callback){
},'json'); },'json');
break; break;
case 'now': case 'now':
$(".tab-con").html(other); $(".tab-con").html(now);
var key = ''; var key = '';
var csr = ''; var csr = '';
var loadT = layer.msg('正在提交任务...',{icon:16,time:0,shade: [0.3, '#000']}); var loadT = layer.msg('正在提交任务...',{icon:16,time:0,shade: [0.3, '#000']});
@ -2166,35 +2169,6 @@ function opSSL(type, id, siteName, callback){
} }
//一键部署证书
function onekeySSl(partnerOrderId,siteName){
var loadT = layer.msg(lan.site.ssl_apply_3,{icon:16,time:0,shade:0.3});
$.post("/ssl?action=GetSSLInfo","partnerOrderId="+partnerOrderId+"&siteName="+siteName,function(zdata){
layer.close(loadT);
layer.msg(zdata.msg,{icon:zdata.status?1:2});
getSSLlist(siteName);
})
}
//验证域名
function verifyDomain(partnerOrderId,siteName){
var loadT = layer.msg(lan.site.ssl_apply_2,{icon:16,time:0,shade:0.3});
$.post("/ssl?action=Completed","partnerOrderId="+partnerOrderId+'&siteName='+siteName,function(ydata){
layer.close(loadT);
if(!ydata.status){
layer.msg(ydata.msg,{icon:2});
return;
}
//第三步
var loadT = layer.msg(lan.site.ssl_apply_3,{icon:16,time:0,shade:0.3});
$.post("/ssl?action=GetSSLInfo","partnerOrderId="+partnerOrderId+"&siteName="+siteName,function(zdata){
layer.close(loadT);
if(zdata.status) getSSLlist();
layer.msg(zdata.msg,{icon:zdata.status?1:2});
});
});
}
//开启与关闭SSL //开启与关闭SSL
function ocSSL(action,siteName){ function ocSSL(action,siteName){
var loadT = layer.msg('正在获取证书列表,请稍后..',{icon:16,time:0,shade: [0.3, '#000']}); var loadT = layer.msg('正在获取证书列表,请稍后..',{icon:16,time:0,shade: [0.3, '#000']});
@ -2228,29 +2202,29 @@ function ocSSL(action,siteName){
} }
//生成SSL //生成SSL
function newSSL(siteName,domains){ function newSSL(siteName, domains){
var loadT = layer.msg('正在校验域名,请稍后...',{icon:16,time:0,shade: [0.3, '#000']}); showSpeedWindow('正在申请...', 'site.get_let_logs', function(layers,index){
var force = ''; var force = '';
if($("#checkDomain").prop("checked")) force = '&force=true'; if ($("#checkDomain").prop("checked")) force = '&force=true';
var email = $("input[name='admin_email']").val(); var email = $("input[name='admin_email']").val();
$.post('/site/create_let','siteName='+siteName+'&domains='+domains+'&updateOf=1&email='+email + force,function(rdata){ $.post('/site/create_let','siteName='+siteName+'&domains='+domains+'&updateOf=1&email='+email + force,function(rdata){
layer.close(loadT); layer.close(index);
if(rdata.status){ if(rdata.status){
var mykeyhtml = '<div class="myKeyCon ptb15"><div class="ssl-con-key pull-left mr20">密钥(KEY)<br><textarea id="key" class="bt-input-text" readonly="" style="background-color:#f6f6f6">'+rdata.data.key+'</textarea></div>' var key = '<div class="myKeyCon ptb15">\
+ '<div class="ssl-con-key pull-left">证书(PEM格式)<br><textarea id="csr" class="bt-input-text" readonly="" style="background-color:#f6f6f6">'+rdata.data.csr+'</textarea></div>' <div class="ssl-con-key pull-left mr20">密钥(KEY)<br><textarea id="key" class="bt-input-text" readonly="" style="background-color:#f6f6f6">'+rdata.data.key+'</textarea></div>\
+ '</div>' <div class="ssl-con-key pull-left">证书(PEM格式)<br><textarea id="csr" class="bt-input-text" readonly="" style="background-color:#f6f6f6">'+rdata.data.csr+'</textarea></div>\
+ '<ul class="help-info-text c7 pull-left"><li>已为您自动生成Let\'s Encrypt免费证书</li>\ </div>\
<li>如需使用其他SSL,请切换其他证书后粘贴您的KEY以及PEM内容然后保存即可</li></ul>'; <ul class="help-info-text c7 pull-left"><li>已为您自动生成Let\'s Encrypt免费证书</li>\
$(".btssl").html(mykeyhtml); <li>如需使用其他SSL,请切换其他证书后粘贴您的KEY以及PEM内容然后保存即可</li>\
</ul>';
$(".apply_ssl").html(key);
layer.msg(rdata.data.msg,{icon:rdata.status?1:2}); layer.msg(rdata.data.msg,{icon:rdata.status?1:2});
setCookie('letssl',1);
return; return;
} }
layer.msg(rdata.data[0],{icon:2,area:'500px',time:0,shade:0.3,shadeClose:true});
setCookie('letssl',0);
layer.msg(rdata.msg,{icon:2,area:'500px',time:0,shade:0.3,shadeClose:true});
},'json'); },'json');
});
} }
function newAcmeSSL(siteName,domains){ function newAcmeSSL(siteName,domains){
@ -2266,7 +2240,7 @@ function newAcmeSSL(siteName,domains){
+ '</div>' + '</div>'
+ '<ul class="help-info-text c7 pull-left"><li>已为您自动生成Let\'s Encrypt免费证书</li>\ + '<ul class="help-info-text c7 pull-left"><li>已为您自动生成Let\'s Encrypt免费证书</li>\
<li>如需使用其他SSL,请切换其他证书后粘贴您的KEY以及PEM内容然后保存即可</li></ul>'; <li>如需使用其他SSL,请切换其他证书后粘贴您的KEY以及PEM内容然后保存即可</li></ul>';
$(".btssl").html(mykeyhtml); $(".apply_ssl").html(mykeyhtml);
layer.msg(rdata.data.msg,{icon:rdata.status?1:2}); layer.msg(rdata.data.msg,{icon:rdata.status?1:2});
setCookie('letssl',1); setCookie('letssl',1);
return; return;

Loading…
Cancel
Save