API接口 后台ui 完成。 功能50%

pull/278/head
midoks 2 years ago
parent c0d0efb756
commit 044cad1e64
  1. 1
      .gitignore
  2. 76
      class/core/config_api.py
  3. 28
      class/core/mw.py
  4. 71
      route/static/app/config.js
  5. 8
      route/templates/default/config.html

1
.gitignore vendored

@ -148,6 +148,7 @@ data/system.db-journal
data/hook_*.json
data/letsencrypt.json
data/basic_auth.json
data/api.json
plugins/l2tp
plugins/openlitespeed

@ -489,6 +489,73 @@ class config_api:
'id,type,uid,log,addtime').select()
return mw.returnJson(False, 'ok', data)
def getPanelTokenApi(self):
api_file = 'data/api.json'
tmp = mw.readFile(api_file)
if not os.path.exists(api_file):
ready_data = {"open": False, "token": "", "limit_addr": []}
mw.writeFile(api_file, json.dumps(ready_data))
mw.execShell("chmod 600 " + api_file)
tmp = mw.readFile(api_file)
data = json.loads(tmp)
if not 'key' in data:
data['key'] = mw.getRandomString(16)
mw.writeFile(api_file, json.dumps(data))
if 'token_crypt' in data:
data['token'] = mw.deCrypt(data['token'], data['token_crypt'])
else:
token = mw.getRandomString(32)
data['token'] = mw.md5(token)
data['token_crypt'] = mw.enCrypt(
data['token'], token).decode('utf-8')
mw.writeFile(api_file, json.dumps(data))
data['token'] = "***********************************"
data['limit_addr'] = '\n'.join(data['limit_addr'])
del(data['key'])
return mw.returnJson(True, 'ok', data)
def setPanelTokenApi(self):
op_type = request.form.get('op_type', '').strip()
api_file = 'data/api.json'
tmp = mw.readFile(api_file)
data = json.loads(tmp)
if op_type == '1':
token = mw.getRandomString(32)
data['token'] = mw.md5(token)
data['token_crypt'] = mw.enCrypt(
data['token'], token).decode('utf-8')
mw.writeLog('API配置', '重新生成API-Token')
mw.writeFile(api_file, json.dumps(data))
return mw.returnJson(True, 'ok', token)
elif op_type == '2':
data['open'] = not data['open']
stats = {True: '开启', False: '关闭'}
if not 'token_crypt' in data:
token = mw.getRandomString(32)
data['token'] = mw.md5(token)
data['token_crypt'] = mw.enCrypt(
data['token'], token).decode('utf-8')
token = stats[data['open']] + '成功!'
mw.writeLog('API配置', '%sAPI接口' % stats[data['open']])
mw.writeFile(api_file, json.dumps(data))
return mw.returnJson(not not data['open'], token)
elif op_type == '3':
limit_addr = request.form.get('limit_addr', '').strip()
data['limit_addr'] = limit_addr.split('\n')
mw.writeLog('API配置', '变更IP限制为[%s]' % limit_addr)
mw.writeFile(api_file, json.dumps(data))
return mw.returnJson(True, '保存成功!')
def get(self):
data = {}
@ -534,6 +601,15 @@ class config_api:
else:
data['basic_auth'] = ''
api_token = 'data/api.json'
if os.path.exists(api_token):
bac = mw.readFile(api_token)
bac = json.loads(bac)
if bac['open']:
data['api_token'] = 'checked'
else:
data['api_token'] = ''
data['site_count'] = mw.M('sites').count()
data['username'] = mw.M('users').where(

@ -541,6 +541,34 @@ def dePunycode(domain):
return newdomain[0:-1]
def enCrypt(key, strings):
# 加密字符串
try:
if type(strings) != bytes:
strings = strings.encode('utf-8')
from cryptography.fernet import Fernet
f = Fernet(key)
result = f.encrypt(strings)
return result.decode('utf-8')
except:
# print(get_error_info())
return strings
def deCrypt(key, strings):
# 解密字符串
try:
if type(strings) != bytes:
strings = strings.decode('utf-8')
from cryptography.fernet import Fernet
f = Fernet(key)
result = f.decrypt(strings).decode('utf-8')
return result
except:
# print(get_error_info())
return strings
def buildSoftLink(src, dst, force=False):
'''
建立软连接

@ -665,4 +665,73 @@ function setBasicAuth(){
}
}
} else{
function showPanelApi(){
$.post('/config/get_panel_token', '', function(rdata){
var tip = layer.open({
area: ['500px', '355px'],
title: '配置面板API',
closeBtn:1,
shift: 0,
type: 1,
content: '<div class="bt-form pd20">\
<div class="line">\
<span class="tname">接口密钥</span>\
<div class="info-r">\
<input class="bt-input-text mr5" name="token" type="text" style="width: 310px;" disabled>\
<button class="btn btn-success btn-xs reset_token" style="margin-left: -50px;">重置</button>\
</div>\
</div>\
<div class="line">\
<span class="tname" style="width: 90px; overflow: initial; height: 20px; line-height: 20px;">IP白名单<br/>(每行1个)</span>\
<div class="info-r"><textarea class="bt-input-text" name="api_limit_addr" style="width: 310px; height: 80px; line-height: 20px; padding: 5px 8px;"></textarea></div>\
</div>\
<div class="line">\
<span class="tname"></span>\
<div class="info-r"><button class="btn btn-success btn-sm save_api">保存配置</button></div>\
</div>\
<ul class="help-info-text c7">\
<li>开启API后必需在IP白名单列表中的IP才能访问面板API接口</li>\
<li style="color: red;">请不要在生产环境开启这可能增加服务器安全风险</li>\
</ul>\
</div>',
success:function(layero,index){
$('input[name="token"]').val(rdata.data.token);
$('textarea[name="api_limit_addr"]').val(rdata.data.limit_addr);
$('.reset_token').click(function(){
layer.confirm('您确定要重置当前密钥吗?<br/><span style="color: red; ">重置密钥后,已关联密钥产品,将失效,请重新添加新密钥至产品。</span>',{title:'重置密钥',closeBtn:2,icon:13,cancel:function(){
}}, function() {
$.post('/config/set_panel_token', {'op_type':"1"},function(rdata){
showMsg("接口密钥已生成,重置密钥后,已关联密钥产品,将失效,请重新添加新密钥至产品。", function(){
$('input[name="token"]').val(rdata.data);
} ,{icon:1}, 2000);
},'json');
});
});
$('.save_api').click(function(){
var limit_addr = $('textarea[name="api_limit_addr"]').val();
$.post('/config/set_panel_token', {'op_type':"3",'limit_addr':limit_addr},function(rdata){
showMsg(rdata.msg, function(){
} ,{icon:rdata.status?1:2}, 2000);
},'json');
});
},
});
},'json');
}
function setPanelApi(){
var cfg_panel_api = $('#cfg_panel_api').prop("checked");
$.post('/config/set_panel_token', {'op_type':"2"},function(rdata){
showMsg(rdata.msg, function(){
if (rdata.status){
showPanelApi();
}
} ,{icon:rdata.status?1:2}, 1000);
},'json');
}

@ -138,6 +138,14 @@
<span class="set-info c7">为面板增加一道基于BasicAuth的认证服务,有效防止面板被扫描</span>
</p>
<p class="mtb15">
<span class="set-tit text-right" title="API接口" style="float: left;">API接口</span>
<input class="btswitch btswitch-ios" id="cfg_panel_api" type="checkbox" {{data['api_token']}}/>
<label class="btswitch-btn ml5" for="cfg_panel_api" style="float: left;margin-top:4px;" onclick="setPanelApi()"></label>
<button ype="button" class="btn btn-default btn-xs panel_api_btn" style="vertical-align: middle; margin-left: 10px" onclick="showPanelApi();">API接口配置</button>
<span class="set-info c7">提供面板API接口访问的支持</span>
</p>
<p class="mtb15">
<span class="set-tit text-right" title="临时访问授权">临时访问授权</span>
<button type="button" class="btn btn-success btn-sm ml5" onclick="setTempAccess()">临时访问授权管理</button>

Loading…
Cancel
Save