Initial YakPanel commit
This commit is contained in:
255
class/panelApi.py
Normal file
255
class/panelApi.py
Normal file
@@ -0,0 +1,255 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | YakPanel
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2017 YakPanel(www.yakpanel.com) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@yakpanel.com>
|
||||
# +-------------------------------------------------------------------
|
||||
import public,os,json,time
|
||||
class panelApi:
|
||||
save_path = '/www/server/panel/config/api.json'
|
||||
timeout = 600
|
||||
max_bind = 5
|
||||
def get_token(self,get):
|
||||
data = self.get_api_config()
|
||||
if not 'key' in data:
|
||||
data['key'] = public.GetRandomString(16)
|
||||
public.writeFile(self.save_path,json.dumps(data))
|
||||
|
||||
if 'token_crypt' in data:
|
||||
data['token'] = public.de_crypt(data['token'],data['token_crypt'])
|
||||
else:
|
||||
data['token'] = "***********************************"
|
||||
|
||||
data['limit_addr'] = '\n'.join(data['limit_addr'])
|
||||
data['bind'] = self.get_bind_token()
|
||||
qrcode = (public.getPanelAddr() + "|" + data['token'] + "|" + data['key'] + '|' + data['bind']['token']+'|yakpanel').encode('utf-8')
|
||||
data['qrcode'] = public.base64.b64encode(qrcode).decode('utf-8')
|
||||
data['apps'] = sorted(data['apps'],key=lambda x: x['time'],reverse=True)
|
||||
del(data['key'])
|
||||
return data
|
||||
|
||||
|
||||
def login_for_app(self,get):
|
||||
from YakPanel import cache
|
||||
import uuid
|
||||
tid = get.tid
|
||||
if(len(tid) != 32): return public.return_msg_gettext(False, public.lang("Invalid login key1"))
|
||||
session_id = cache.get(tid)
|
||||
if not session_id: return public.return_msg_gettext(False, public.lang("The specified key does not exist or has expired1"))
|
||||
if(len(session_id) != 64): return public.return_msg_gettext(False, public.lang("Invalid login key2"))
|
||||
try:
|
||||
if not os.path.exists('/www/server/panel/data/app_login_check.pl'):return public.returnMsg(False, public.lang("Invalid login key3"))
|
||||
key, init_time, tid2, status = public.readFile('/www/server/panel/data/app_login_check.pl').split(':')
|
||||
if session_id!=key:return public.returnMsg(False, public.lang("Invalid login key4"))
|
||||
if tid != tid2: return public.returnMsg(False, public.lang("The specified key does not exist or has expired5"))
|
||||
if time.time() - float(init_time) > 60:
|
||||
return public.returnMsg(False, public.lang("QR code validity time expired6"))
|
||||
cache.set(session_id,public.md5(uuid.UUID(int=uuid.getnode()).hex),120)
|
||||
import uuid
|
||||
data = key + ':' + init_time + ':' + tid2 + ':' + uuid.UUID(int=uuid.getnode()).hex[-12:]
|
||||
public.writeFile("/www/server/panel/data/app_login_check.pl", data)
|
||||
return public.return_msg_gettext(True, public.lang("Scan code successfully, log in!"))
|
||||
except:
|
||||
os.remove("/www/server/panel/data/app_login_check.pl")
|
||||
return public.return_msg_gettext(False, public.lang("Invalid login key"))
|
||||
|
||||
def get_api_config(self):
|
||||
tmp = public.ReadFile(self.save_path)
|
||||
if not tmp or not os.path.exists(self.save_path):
|
||||
data = { "open":False, "token":"", "limit_addr":[] }
|
||||
public.WriteFile(self.save_path,json.dumps(data))
|
||||
public.ExecShell("chmod 600 " + self.save_path)
|
||||
tmp = public.ReadFile(self.save_path)
|
||||
try:
|
||||
data = json.loads(tmp)
|
||||
except json.JSONDecodeError:
|
||||
default_config = {"open": False, "token": "", "limit_addr": []}
|
||||
return default_config
|
||||
is_save = False
|
||||
if not 'binds' in data:
|
||||
data['binds'] = []
|
||||
is_save = True
|
||||
|
||||
if not 'apps' in data:
|
||||
data['apps'] = []
|
||||
is_save = True
|
||||
|
||||
data['binds'] = sorted(data['binds'],key=lambda x: x['time'],reverse=True)
|
||||
if len(data['binds']) > 5:
|
||||
data['binds'] = data['binds'][:5]
|
||||
is_save = True
|
||||
|
||||
if is_save:
|
||||
self.save_api_config(data)
|
||||
return data
|
||||
|
||||
def save_api_config(self,data):
|
||||
public.WriteFile(self.save_path,json.dumps(data))
|
||||
public.set_mode(self.save_path,'600')
|
||||
return True
|
||||
|
||||
def check_bind(self,args):
|
||||
if not 'bind_token' in args or not 'client_brand' in args or not 'client_model' in args:
|
||||
return 0
|
||||
if not args.client_brand or not args.client_model:
|
||||
return 'Invalid device'
|
||||
|
||||
bind = self.get_bind_token(args.bind_token)
|
||||
if bind['token'] != args.bind_token:
|
||||
return public.lang("The current QR code has expired, please refresh the page and rescan the code!")
|
||||
|
||||
apps = self.get_apps()
|
||||
if len(apps) >= self.max_bind:
|
||||
return public.lang('This server is bound to a maximum of {} devices, which has reached the limit!',self.max_bind)
|
||||
|
||||
bind['status'] = 1
|
||||
bind['brand'] = args.client_brand
|
||||
bind['model'] = args.client_model
|
||||
self.set_bind_token(bind)
|
||||
return 1
|
||||
|
||||
def get_bind_status(self,args):
|
||||
if not public.cache_get(public.Md5(os.uname().version)):
|
||||
public.cache_set(public.Md5(os.uname().version),1,60)
|
||||
bind = self.get_bind_token(args.bind_token)
|
||||
return bind
|
||||
|
||||
def get_app_bind_status(self,args):
|
||||
if not 'bind_token' in args:
|
||||
return 0
|
||||
if self.get_app_find(args.bind_token):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def set_bind_token(self,bind):
|
||||
data = self.get_api_config()
|
||||
is_save = False
|
||||
for i in range(len(data['binds'])):
|
||||
if data['binds'][i]['token'] == bind['token']:
|
||||
data['binds'][i] = bind
|
||||
is_save = True
|
||||
break
|
||||
if is_save:
|
||||
self.save_api_config(data)
|
||||
return True
|
||||
|
||||
|
||||
def get_apps(self,args = None):
|
||||
data = self.get_api_config()
|
||||
return data['apps']
|
||||
|
||||
def get_app_find(self,bind_token):
|
||||
apps = self.get_apps()
|
||||
for s_app in apps:
|
||||
if s_app['token'] == bind_token:
|
||||
return s_app
|
||||
return None
|
||||
|
||||
def add_bind_app(self,args):
|
||||
bind = self.get_bind_token(args.bind_token)
|
||||
if bind['status'] == 0:
|
||||
return public.return_msg_gettext(False, public.lang("Failed verification!"))
|
||||
apps = self.get_apps()
|
||||
if len(apps) >= self.max_bind:
|
||||
return public.return_msg_gettext(False, public.lang("A server allows up to {} device bindings!", self.max_bind))
|
||||
|
||||
args.bind_app = args.bind_token
|
||||
self.remove_bind_app(args)
|
||||
data = self.get_api_config()
|
||||
data['apps'].append(bind)
|
||||
self.save_api_config(data)
|
||||
self.remove_bind_token(args.bind_token)
|
||||
return public.return_msg_gettext(True, public.lang("Bind successfully!"))
|
||||
|
||||
def remove_bind_token(self,bind_token):
|
||||
data = self.get_api_config()
|
||||
tmp_binds = []
|
||||
for s_bind in data['binds']:
|
||||
if bind_token == s_bind['token']:
|
||||
continue
|
||||
tmp_binds.append(s_bind)
|
||||
data['binds'] = tmp_binds
|
||||
self.save_api_config(data)
|
||||
|
||||
def remove_bind_app(self,args):
|
||||
data = self.get_api_config()
|
||||
tmp_apps = []
|
||||
for s_app in data['apps']:
|
||||
if args.bind_app == s_app['token']:
|
||||
continue
|
||||
tmp_apps.append(s_app)
|
||||
data['apps'] = tmp_apps
|
||||
self.save_api_config(data)
|
||||
s_file = '/dev/shm/{}'.format(args.bind_app)
|
||||
if os.path.exists(s_file):
|
||||
os.remove(s_file)
|
||||
return public.return_msg_gettext(True, public.lang("Successfully deleted!"))
|
||||
|
||||
def get_bind_token(self,token = None):
|
||||
data = self.get_api_config()
|
||||
s_time = time.time()
|
||||
binds = []
|
||||
bind = None
|
||||
is_write = False
|
||||
for i in range(len(data['binds'])):
|
||||
if s_time - data['binds'][i]['time'] > self.timeout:
|
||||
is_write = True
|
||||
continue
|
||||
binds.append(data['binds'][i])
|
||||
if token:
|
||||
if token == data['binds'][i]['token']:
|
||||
bind = data['binds'][i]
|
||||
else:
|
||||
if not bind:
|
||||
bind = data['binds'][i]
|
||||
if not bind:
|
||||
if len(binds) > 0:
|
||||
binds = sorted(binds,key=lambda x: x['time'],reverse=True)
|
||||
bind = binds[0]
|
||||
else:
|
||||
bind = {"time":s_time,"token":public.GetRandomString(18),'status':0}
|
||||
binds.append(bind)
|
||||
is_write = True
|
||||
|
||||
if is_write:
|
||||
data['binds'] = binds
|
||||
self.save_api_config(data)
|
||||
return bind
|
||||
|
||||
|
||||
def set_token(self,get):
|
||||
if 'request_token' in get: return public.return_msg_gettext(False, public.lang("Cannot configure API through API interface"))
|
||||
data = self.get_api_config()
|
||||
if get.t_type == '1':
|
||||
token = public.GetRandomString(32)
|
||||
data['token'] = public.md5(token)
|
||||
data['token_crypt'] = public.en_crypt(data['token'],token).decode('utf-8')
|
||||
public.write_log_gettext('API configuration','Regenerate API-Token')
|
||||
public.add_security_logs('API configuration','Regenerate API-Token')
|
||||
elif get.t_type == '2':
|
||||
data['open'] = not data['open']
|
||||
stats = {True:'Open',False:'Close'}
|
||||
if not 'token_crypt' in data:
|
||||
token = public.GetRandomString(32)
|
||||
data['token'] = public.md5(token)
|
||||
data['token_crypt'] = public.en_crypt(data['token'],token).decode('utf-8')
|
||||
public.write_log_gettext('API configuration','{} API interface',(stats[data['open']],))
|
||||
public.add_security_logs('API configuration', '{} API interface', (stats[data['open']],))
|
||||
token = stats[data['open']] + ' success!'
|
||||
elif get.t_type == '3':
|
||||
data['limit_addr'] = get.limit_addr.split('\n')
|
||||
public.write_log_gettext('API configuration','Change IP limit to [{}]',(get.limit_addr,))
|
||||
public.add_security_logs('API configuration', 'Change IP limit to [{}]', (get.limit_addr,))
|
||||
token ='Saved successfully!'
|
||||
self.save_api_config(data)
|
||||
return public.return_msg_gettext(True,token)
|
||||
|
||||
def get_tmp_token(self,get):
|
||||
if not 'request_token' in get: return public.return_msg_gettext(False, public.lang("Temporary keys can only be obtained through the API interface"))
|
||||
data = self.get_api_config()
|
||||
data['tmp_token'] = public.GetRandomString(64)
|
||||
data['tmp_time'] = time.time()
|
||||
self.save_api_config(data)
|
||||
return public.return_msg_gettext(True,data['tmp_token'])
|
||||
Reference in New Issue
Block a user