From 044cad1e64ac2297d03e84a9ac11aee3f5696c82 Mon Sep 17 00:00:00 2001
From: midoks
Date: Sun, 27 Nov 2022 00:28:09 +0800
Subject: [PATCH] =?UTF-8?q?API=E6=8E=A5=E5=8F=A3=20=E5=90=8E=E5=8F=B0ui=20?=
=?UTF-8?q?=E5=AE=8C=E6=88=90=E3=80=82=20=E5=8A=9F=E8=83=BD50%?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 1 +
class/core/config_api.py | 76 +++++++++++++++++++++++++++++
class/core/mw.py | 28 +++++++++++
route/static/app/config.js | 71 ++++++++++++++++++++++++++-
route/templates/default/config.html | 8 +++
5 files changed, 183 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 751331556..2b2442516 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/class/core/config_api.py b/class/core/config_api.py
index 71af6f938..afc69c542 100755
--- a/class/core/config_api.py
+++ b/class/core/config_api.py
@@ -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(
diff --git a/class/core/mw.py b/class/core/mw.py
index 029192ff2..f6851bdd3 100755
--- a/class/core/mw.py
+++ b/class/core/mw.py
@@ -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):
'''
建立软连接
diff --git a/route/static/app/config.js b/route/static/app/config.js
index 238a27b9e..fb8584152 100755
--- a/route/static/app/config.js
+++ b/route/static/app/config.js
@@ -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: '',
+ 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('您确定要重置当前密钥吗?
重置密钥后,已关联密钥产品,将失效,请重新添加新密钥至产品。',{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');
+}
+
diff --git a/route/templates/default/config.html b/route/templates/default/config.html
index fc5d8cb49..8a7534bc9 100755
--- a/route/templates/default/config.html
+++ b/route/templates/default/config.html
@@ -138,6 +138,14 @@
为面板增加一道基于BasicAuth的认证服务,有效防止面板被扫描
+
+ API接口
+
+
+
+ 提供面板API接口访问的支持
+
+
临时访问授权