Commit 54432ee6 authored by wanli's avatar wanli

update

parent b4570cc6
{
"appList": [
{
"uuid": "001",
"img": "alipay.png",
"title": "支付宝",
"arrow": "setup.png",
"download": 120,
"like": 76,
"category": "1016",
"details": {
"version": "1.0.1",
"update": "2021-04-01",
"size": 20,
"log": "优化性能,提高稳定性和安全性",
"desc": "生活好,支付宝"
}
},
{
"uuid": "123",
"img": "qq.png",
"title": "腾讯QQ",
"arrow": "setup.png",
"download": 111,
"like": 70,
"category": "1016",
"details": {
"version": "0.0.2",
"update": "2021-04-02",
"size": 22,
"log": "修复若干已知问题",
"desc": "QQ,乐在沟通"
}
},
{
"uuid": "456",
"img": "qq_music.png",
"title": "QQ音乐",
"arrow": "setup.png",
"download": 100,
"like": 71,
"category": "1012",
"details": {
"version": "0.0.3",
"update": "2021-04-03",
"size": 32,
"log": "优化性能,提高稳定性和安全性",
"desc": "十五年的陪伴,国民音乐平台"
}
},
{
"uuid": "789",
"img": "360kids.png",
"title": "360儿童卫士",
"arrow": "setup.png",
"download": 100,
"like": 56,
"category": "1016",
"details": {
"version": "0.0.5",
"update": "2021-04-05",
"size": 36,
"log": "优化性能,提高稳定性和安全性",
"desc": "千万家长信任的育学助手"
}
},
{
"uuid": "1011",
"img": "baidutieba.png",
"title": "百度贴吧",
"arrow": "setup.png",
"download": 100,
"like": 78,
"category": "1016",
"details": {
"version": "0.0.4",
"update": "2021-04-04",
"size": 25,
"log": "优化性能,提高稳定性和安全性",
"desc": "聊兴趣,上贴吧"
}
},
{
"uuid": "1012",
"img": "aiqiyi.png",
"title": "爱奇艺",
"arrow": "setup.png",
"download": 79,
"like": 76,
"category": "1013",
"details": {
"version": "0.0.3",
"update": "2021-04-03",
"size": 41,
"log": "优化性能,提高稳定性和安全性",
"desc": "欧洲杯免费直播"
}
},
{
"uuid": "1013",
"img": "yy.png",
"title": "YY语音",
"arrow": "setup.png",
"download": 120,
"like": 45,
"category": "1015",
"details": {
"version": "0.0.3",
"update": "2021-04-03",
"size": 32,
"log": "优化性能,提高稳定性和安全性",
"desc": "和附近的聊天看直播"
}
},
{
"uuid": "1014",
"img": "didi.png",
"title": "滴滴打车",
"arrow": "setup.png",
"download": 34,
"like": 55,
"category": "1016",
"details": {
"version": "0.0.3",
"update": "2021-04-03",
"size": 32,
"log": "优化性能,提高稳定性和安全性",
"desc": "滴滴一下,美好出行"
}
},
{
"uuid": "1015",
"img": "gaode.png",
"title": "高德地图",
"arrow": "setup.png",
"download": 29,
"like": 59,
"category": "1016",
"details": {
"version": "0.0.3",
"update": "2021-04-03",
"size": 32,
"log": "优化性能,提高稳定性和安全性",
"desc": "专享88元打车礼包"
}
}
],
"categoryList": [
{
"uuid": "1012",
"img": "music.png",
"title": "音乐"
},
{
"uuid": "1013",
"img": "movie.png",
"title": "视频"
},
{
"uuid": "1014",
"img": "camera.png",
"title": "相机"
},
{
"uuid": "1015",
"img": "voice.png",
"title": "语音"
},
{
"uuid": "1016",
"img": "tool.png",
"title": "工具"
}
],
"downloadList": [
{
"icon": "360kids.png",
"time": 1625648308210,
"iconUrl": "http://store.evmiot.com/application/360kids.png",
"apkId": "789",
"version": "v1.0",
"homePage": "evue_album",
"apkDownloadUrl": "evue_album",
"fileList": "360kids"
},
{
"icon": "qq_music.png",
"time": 1625648308210,
"iconUrl": "http://store.evmiot.com/application/qq_music.png",
"apkId": "456",
"version": "v1.0",
"homePage": "evue_music",
"apkDownloadUrl": "evue_music",
"fileList": "qq_music"
},
{
"icon": "gaode.png",
"time": 1625648308210,
"iconUrl": "http://store.evmiot.com/application/gaode.png",
"apkId": "1015",
"version": "v1.0",
"homePage": "evue_dial",
"apkDownloadUrl": "evue_dial",
"fileList": "gaode"
},
{
"icon": "didi.png",
"time": 1625648308210,
"iconUrl": "http://store.evmiot.com/application/didi.png",
"apkId": "1014",
"version": "v1.0",
"homePage": "evue_setting",
"apkDownloadUrl": "evue_setting",
"fileList": "didi"
},
{
"icon": "alipay.png",
"time": 1625648308210,
"iconUrl": "http://store.evmiot.com/application/zhifubao.png",
"apkId": "001",
"version": "v1.0",
"homePage": "evue_calculator",
"apkDownloadUrl": "evue_calculator",
"fileList": "alipay"
}
]
}
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import json
from .signal_manager import signalManager
from .setting import config
import logging
from controller import initConnect
logger = logging.getLogger("ApplicationManager")
def loadSettings(path=None):
global config
projectFile = os.sep.join([os.path.dirname(os.getcwd()), "project.json"])
if os.path.exists(projectFile):
with open(projectFile, "rb") as f:
obj = json.loads(f.read())
config['PORT'] = obj['port']
for key in config:
lowerKey = key.lower()
if lowerKey in obj:
config[key] = obj[lowerKey]
if lowerKey in obj["server"]:
config[key] = obj["server"][lowerKey]
if key == "PONY":
config["PONY"]= obj["server"]["db"]
return config
def initApp():
global config
config = loadSettings()
return config
config = initApp()
'''
Author: your name
Date: 2021-04-14 14:12:18
LastEditTime: 2021-06-30 22:50:10
LastEditors: your name
Description: In User Settings Edit
FilePath: \evm-store\backend\app\setting.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import configparser
conf = configparser.ConfigParser()
conf.read(os.path.join(os.getcwd(), "config.ini"))
config = dict(
NAME='evm_store',
DEBUG=True,
HOST=conf.get('application', 'host'),
PORT=int(conf.get('application', 'port')),
LOGIN_DISABLED=False,
MD5_SALT="EhuqUkwV",
SECRET_KEY='secret_key_EhuqUkwV',
DATABASE=conf.get('database', 'filename'),
DATABASE_FILE=conf.get('scheduler', 'db'),
PONY={
'provider': conf.get('database', 'provider'),
'filename': "../{}".format(conf.get('database', 'filename')),
'create_db': True,
},
TABLE_PREFIX='evm_store_',
BACKUP_DIR=conf.get('application', 'backup_dir'),
UPLOAD_SERVER="{}://{}:{}/".format(conf.get('uploads', 'protocol'), conf.get('uploads', 'host'), conf.get('uploads', 'port')),
EPK_DIR=conf.get('uploads', 'epk_dir'),
TEMP_DIR=conf.get('uploads', 'temp_dir'),
UPLOAD_PATH=os.path.abspath(conf.get('uploads', 'upload_path')),
UPLOAD_DIR=conf.get('uploads', 'upload_dir'),
TEMPLATE_PATH=os.path.join(os.getcwd(), "static"),
STATIC_PATH=os.path.join(os.getcwd(), "static"),
LOGO=r'''
______ _____
___ _________ /_ ________________________ __ /______________
__ | /| / / _ \_ __ \ _ ___/_ ___/ _ \ __ `/ __/ __ \_ ___/
__ |/ |/ // __/ /_/ / / /__ _ / / __/ /_/ // /_ / /_/ / /
____/|__/ \___//_.___/ \___/ /_/ \___/\__,_/ \__/ \____//_/
Power by EVM Team
'''
)
\ No newline at end of file
'''
Author: your name
Date: 2021-04-14 14:12:18
LastEditTime: 2021-07-03 11:53:43
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\backend\app\signal_manager.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
from fullstack.event import PySignal
class SignalManager(object):
# 接口模块
actionUpdatePassword = PySignal()
actionBackupDatabase = PySignal()
actionApplicationBuild = PySignal()
actionGetConvertString = PySignal()
actionOpqcp = PySignal()
# 登录模块
actionLogin = PySignal()
actionLogout = PySignal()
actionRegister = PySignal()
# 应用管理
actionAddApp = PySignal()
actionGetApp = PySignal()
actionGetAppList = PySignal()
actionUpdateApp = PySignal()
actionDeleteApp = PySignal()
# 应用打包记录
actionAddBuildLog = PySignal()
actionGetBuildLog = PySignal()
actionGetBuildLogList = PySignal()
actionUpdateBuildLog = PySignal()
actionDeleteBuildLog = PySignal()
# 用户模块
actionCheckUser = PySignal()
actionAddUser = PySignal()
actionDeleteUser = PySignal()
actionGetUser = PySignal()
actionGetUserList = PySignal()
actionUpdateUser = PySignal()
# 系统框架模块
actionAddDevice = PySignal()
actionDeleteDevice = PySignal()
actionGetDevice = PySignal()
actionGetDeviceList = PySignal()
actionUpdateDevice = PySignal()
# 应用下载统计模块
actionAddDownload = PySignal()
actionDeleteDownload = PySignal()
actionGetDownload = PySignal()
actionGetDownloadList = PySignal()
actionUpdateDownload = PySignal()
# 应用打包日志
actionAddAppLogs = PySignal()
actionDeleteAppLogs = PySignal()
actionGetAppLogs = PySignal()
actionGetAppLogsList = PySignal()
actionUpdateAppLogs = PySignal()
# 用户登录日志
actionAddLoginLogs = PySignal()
actionDeleteLoginLogs = PySignal()
actionGetLoginLogs = PySignal()
actionGetLoginLogsList = PySignal()
actionUpdateLoginLogs = PySignal()
def __init__(self):
super(SignalManager, self).__init__()
signalManager = SignalManager()
{"lastModifyDateTime": 1625808079}
\ No newline at end of file
[uploads]
port = 80
host = store.evmiot.com
protocol = http
upload_path = ../../evm_app_store_files
temp_dir = tmp
epk_dir = epks
db_dir = epkdb
upload_dir = uploads
[database]
provider = sqlite
filename = app-store.db
[scheduler]
db = scheduler.db
[application]
name = evm_store
backup_dir = backup
evueapps_dir = evueapps
launcher_dir = launcher
host = 127.0.0.1
port = 5001
'''
Author: your name
Date: 2021-04-14 14:12:18
LastEditTime: 2021-07-03 11:53:04
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\backend\controller\__init__.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import logging
from app import signalManager
from .api_manager import apiManager
from .user_manager import userManager
from .login_manager import loginManager
from .apps_manager import appsManager
from .device_manager import deviceManager
from .download_manager import downloadManager
from .login_logs_manager import loginLogsManager
from .app_logs_manager import appLogsManager
from .build_logs_manager import buildLogsManager
logger = logging.getLogger(__name__)
def initConnect():
# 系统模块
signalManager.actionApplicationBuild.connect(appsManager.build)
signalManager.actionGetConvertString.connect(apiManager.get_escape_text)
signalManager.actionUpdatePassword.connect(apiManager.update_user_password)
signalManager.actionOpqcp.connect(apiManager.opqcp)
# 登录模块
signalManager.actionLogin.connect(loginManager.login)
signalManager.actionLogout.connect(loginManager.logout)
signalManager.actionRegister.connect(loginManager.register)
# 应用管理
signalManager.actionAddApp.connect(appsManager.add)
signalManager.actionDeleteApp.connect(appsManager.delete)
signalManager.actionGetApp.connect(appsManager.get)
signalManager.actionGetAppList.connect(appsManager.getList)
signalManager.actionUpdateApp.connect(appsManager.update)
# 设备管理
signalManager.actionAddDevice.connect(deviceManager.add)
signalManager.actionDeleteDevice.connect(deviceManager.delete)
signalManager.actionGetDevice.connect(deviceManager.get)
signalManager.actionGetDeviceList.connect(deviceManager.getList)
signalManager.actionUpdateDevice.connect(deviceManager.update)
# 打包记录
signalManager.actionAddBuildLog.connect(buildLogsManager.add)
signalManager.actionDeleteBuildLog.connect(buildLogsManager.delete)
signalManager.actionGetBuildLog.connect(buildLogsManager.get)
signalManager.actionGetBuildLogList.connect(buildLogsManager.getList)
signalManager.actionUpdateBuildLog.connect(buildLogsManager.update)
# 用户登录记录
signalManager.actionAddLoginLogs.connect(loginLogsManager.add)
signalManager.actionDeleteLoginLogs.connect(loginLogsManager.delete)
signalManager.actionGetLoginLogs.connect(loginLogsManager.get)
signalManager.actionGetLoginLogsList.connect(loginLogsManager.getList)
signalManager.actionUpdateLoginLogs.connect(loginLogsManager.update)
# 用户模块
signalManager.actionCheckUser.connect(userManager.check)
signalManager.actionAddUser.connect(userManager.add)
signalManager.actionDeleteUser.connect(userManager.delete)
signalManager.actionGetUser.connect(userManager.get)
signalManager.actionGetUserList.connect(userManager.getList)
signalManager.actionUpdateUser.connect(userManager.update)
# 应用下载统计模块
signalManager.actionAddDownload.connect(downloadManager.add)
signalManager.actionDeleteDownload.connect(downloadManager.delete)
signalManager.actionGetDownload.connect(downloadManager.get)
signalManager.actionGetDownloadList.connect(downloadManager.getList)
signalManager.actionUpdateDownload.connect(downloadManager.update)
# 应用打包日志
signalManager.actionAddAppLogs.connect(appLogsManager.add)
signalManager.actionDeleteAppLogs.connect(appLogsManager.delete)
signalManager.actionGetAppLogs.connect(appLogsManager.get)
signalManager.actionGetAppLogsList.connect(appLogsManager.getList)
signalManager.actionUpdateAppLogs.connect(appLogsManager.update)
initConnect()
\ No newline at end of file
'''
Author: your name
Date: 2021-04-14 14:12:18
LastEditTime: 2021-07-01 11:39:27
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\backend\controller\api_manager.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import logging
import shutil
from datetime import datetime
from pony.orm import *
from app.setting import config
from model.user import User
from utils import md5_salt
from utils.ccode import convert_string
logger = logging.getLogger(__name__)
class ApiManager(object):
def __init__(self):
super(ApiManager, self).__init__()
def update_user_password(self, user, data):
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = User.get(uuid=data.get("uuid"), password=md5_salt(data['password']))
if not result:
return None, "user does not exists"
data.pop("uuid")
data['password'] = md5_salt(data['newPassword'])
data.pop('newPassword')
data.update({
"create_by": editor.id,
"create_at": datetime.now(),
"update_by": editor.id,
"update_at": datetime.now()
})
result = result.set(**data)
commit()
return True, "success"
def get_escape_text(self, data):
# fname = "./a.c"
# target = os.sep.join(["out", fname])
# if os.path.exists(fname):
# os.remove(fname)
# if os.path.exists(target):
# os.remove(target)
# with open(fname, "w+") as f:
# f.write(data['string'])
# result = os.system("./opqcp {i} ./out".format(i=fname))
# print(result)
# with open(target) as f:
# result = f.read()
# return result
return convert_string(data['string'])
def opqcp(self, params):
target_file = os.path.normpath(os.sep.join([config.get("UPLOAD_PATH"), params.get("filename")]))
shutil.copy(target_file, os.getcwd())
# dtNowString = datetime.now().strftime("%Y%m%d%H%M%S%f")
# fn, ex = os.path.splitext(params.get("filename"))
output_path = os.sep.join([os.path.dirname(target_file), "out"])
if not os.path.exists(output_path):
os.makedirs(output_path)
print("#######", output_path)
# print(os.path.dirname(os.getcwd()), os.path.abspath("../opqcp/opqcp"))
result = os.system("./opqcp {i} ./out".format(i=os.path.basename(target_file)))
print(result)
# command = ["./opqcp", os.path.basename(target_file), "./"]
fname = os.sep.join([os.getcwd(), "out", os.path.basename(target_file)])
shutil.copy(fname, output_path)
os.remove(fname)
# ret = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8", timeout=5)
# if ret.returncode == 0:
# print("success:", ret)
# else:
# print("error:", ret)
# ret = target_file
return True, os.sep.join([output_path.replace(config.get("UPLOAD_PATH"), ""), params.get("filename")])
apiManager = ApiManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import logging
from datetime import datetime
from pony.orm import *
from model import fullStackDB
from model.app_logs import AppLogs
from model.user import User
logger = logging.getLogger(__name__)
class AppLogsManager(object):
def __init__(self):
super(AppLogsManager, self).__init__()
def add(self, user, data):
# 判断角色名是否存在
result = AppLogs.get(name=data.get("name"))
if result:
return False, "app logs name has been exists."
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
})
result = fullStackDB.add(AppLogs, **data)
return result, "add app logs {}.".format("success" if result else "fail")
def delete(self, user, uuid):
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = AppLogs.get(uuid=uuid)
if result:
result.delete()
return result, "delete app logs {}.".format("success" if result else "fail")
def get(self, data):
result = AppLogs.get(**data)
if result:
result = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "name", "create_at", "update_at", "delete_at"])
return result, "get app logs {}.".format("success" if result else "fail")
def getList(self, user, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null"
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
if editor.role != "administrator":
temp.update({ 'create_by': editor })
if "scope_type" in data and data.get("scope_type") == "list":
result = AppLogs.select().where(**temp).order_by(desc(AppLogs.create_at))
temp = []
for item in result:
temp.append(item.to_dict(only=["uuid", "app_name"]))
return temp, len(temp), "get select {}.".format("success" if temp else "no data")
result = AppLogs.select().where(**temp).order_by(desc(AppLogs.create_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = AppLogs.select().where(**temp).count()
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True)
t.update({
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
})
temp.append(t)
result = temp
return result, count, "get app logs {}.".format("success" if result else "no data")
def update(self, user, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
return True, "update app logs {}.".format("success" if True else "fail")
appLogsManager = AppLogsManager()
This diff is collapsed.
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import re
import copy
import shutil
import logging
from datetime import datetime
from pony.orm import *
from app.setting import config
from model import fullStackDB
from model.apps import Apps
from model.annex import Annex
from model.app_logs import AppLogs
from model.build_logs import BuildLogs
from model.user import User
from utils.epk import EpkApp
logger = logging.getLogger(__name__)
class BuildLogsManager(object):
def __init__(self):
super(BuildLogsManager, self).__init__()
def add(self, user, app):
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
# 根据app查询应用,获取应用有哪些文件
# 按格式创建文件夹,将这些文件移动到这个文件夹
# 将这些零散文件进行打包
# 更新数据库对应文件的路径
app = Apps.get(uuid=app)
if not app:
return None, "app not found"
source_files = Annex.select().filter(app=app)
if not source_files:
return None, "apps file not found"
dir_format = "{}-{}-{}".format(app.app_name, app.app_version, datetime.now().strftime("%Y%m%d%H%M%S"))
upload_dir = os.sep.join([config.get("UPLOAD_PATH"), config.get("UPLOAD_DIR"), "evueapps"])
target_dir = os.sep.join([upload_dir, editor.account, dir_format])
dest_dir = os.sep.join([target_dir, "src"])
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
app_files = []
for sf in source_files:
target_file = os.sep.join([config.get("UPLOAD_PATH"), sf.path])
filename = os.path.basename(target_file)
name, suffix = os.path.splitext(filename)
name = re.sub(r"_\d{14}$", "", name)
dst_file = os.path.normpath(os.sep.join([dest_dir, name + suffix]))
shutil.move(os.path.normpath(target_file), dst_file)
app_files.append([sf.id, dst_file])
# 打包成EPK文件
app_info = {}
params = { 'appName': app.app_name, 'appDir': dest_dir, 'appVersion': app.app_version, 'output': target_dir }
if editor.role == "administrator" or editor.role == "community":
params['algorithm'] = "h"
epk = EpkApp(**params)
app_info = epk.pack()
if app_info:
app_info['md5'] = str(app_info['md5'])
# 更新数据库对应文件路径
for sf in source_files:
for af in app_files:
if sf.id == af[0]:
t = os.path.normpath(af[1].replace(config.get("UPLOAD_PATH"), "")).replace('\\', '/')
sf.set(path=t)
flush()
commit()
epk_path = os.sep.join([target_dir.replace(config.get("UPLOAD_PATH"), ""), "{}.epk".format(app.app_name)]).replace('\\', '/')
# 新增一条BuildLogs
result = BuildLogs(app=app, app_path=epk_path, app_info=app_info, create_by=editor, create_at=datetime.now(), update_by=editor, update_at=datetime.now())
commit()
# 新增一条AppLogs
AppLogs(app_name=app.app_name, app_path=epk_path, app_version=app.app_version, app_info=app_info, create_by=editor, create_at=datetime.now())
commit()
return epk_path, "add build_logs {}.".format("success" if result else "fail")
def delete(self, user, uuid):
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(BuildLogs, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete build_logs {}.".format("success" if result else "fail")
def get(self, user, app_id):
with db_session:
app = Apps.get(uuid=app_id)
if not app:
return False, "app not found"
result = BuildLogs.select().where(app=app).order_by(desc(BuildLogs.create_at)).first()
if result:
result = result.to_dict(only=["uuid", "app_path"])
result.update({ "app_name": app.app_name })
return result, "get build logs {}.".format("success" if result else "no data")
def getList(self, user, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
if editor.role == "administrator":
temp.update({"is_delete": False})
else:
temp.update({ "create_by": editor, "is_delete": False })
if "scope_type" in data and data.get("scope_type") == "list":
result = BuildLogs.select().where(**temp).order_by(desc(BuildLogs.create_at))
temp = []
for item in result:
temp.append({ "name": item.app.app_name, "uuid": str(item.uuid) })
return temp, len(temp), "get build_logs {}.".format("success" if temp else "fail")
result = BuildLogs.select().where(**temp).order_by(desc(BuildLogs.create_at)).page(data.get("pagenum", 1), pagesize=data.get("pagesize", 10))
count = BuildLogs.select().where(**temp).count()
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, exclude=["is_delete", "delete_by", "delete_at"])
t.update({
"app": item.app.to_dict(exclude=["is_delete", "delete_by", "delete_at"]),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
"update_by": item.update_by.to_dict(only=["uuid", "username"]),
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S") if item.create_at else None,
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S") if item.update_at else None,
})
temp.append(t)
result = temp
return result, count, "get build_logs {}.".format("success" if result else "no data")
def update(self, user, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(BuildLogs, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
return result, "update build log {}.".format("success" if result else "fail")
buildLogsManager = BuildLogsManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import logging
from datetime import datetime
from pony.orm import *
from model import fullStackDB
from model.device import Device
from model.user import User
logger = logging.getLogger(__name__)
class DeviceManager(object):
def __init__(self):
super(DeviceManager, self).__init__()
def add(self, user, data):
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
device = Device.select().where(imei=data.get("imei")).first()
if device:
return False, "device has been exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = Device(**data)
commit()
return result, "add Device {}.".format("success" if result else "fail")
def delete(self, user, uuid):
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Device, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete Device {}.".format("success" if result else "fail")
def get(self, user, data):
result = Device.get(**data)
if result:
result = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "create_at", "update_at", "delete_at"])
return result, "get Device {}.".format("success" if result else "fail")
def getList(self, user, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
if editor.role == "administrator":
temp.update({ "is_delete": False })
else:
temp.update({"create_by": editor, "is_delete": False})
if "scope_type" in data and data.get("scope_type") == "list":
result = Device.select().where(**temp).order_by(desc(Device.create_at))
temp = []
for item in result:
temp.append(item.to_dict(only=["uuid", "name"]))
return temp, len(temp), "get select {}.".format("success" if temp else "no data")
result = Device.select().where(**temp).order_by(desc(Device.create_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = Device.select().where(**temp).count()
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, exclude=["is_delete", "delete_at", "delete_by"])
t.update({
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S"),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
"update_by": item.update_by.to_dict(only=["uuid", "username"])
})
temp.append(t)
result = temp
return result, count, "get Device {}.".format("success" if result else "no data")
def update(self, user, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
with db_session:
# 查询请求者是否存在
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
if data.get("imei"):
device = Device.select().where(imei=data.get("imei")).first()
if device:
return False, "device has been exists"
result = Device.get(uuid=uuid)
if result:
result.set(update_at=datetime.now(), update_by=editor, **data)
commit()
return result, "update role {}.".format("success" if result else "fail")
deviceManager = DeviceManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import logging
from datetime import datetime
from pony.orm import select, desc
from flask import request
from model import fullStackDB
from model.dictionary import Dict
from model.user import User
logger = logging.getLogger(__name__)
class DictManager(object):
def __init__(self):
super(DictManager, self).__init__()
def add(self, data):
# 判断相同的类别和标签是否存在
result = Dict.get(label=data.get("label"), value=data.get("value"), category=data.get("category"))
if result:
return False, "dictionary has been exists."
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = fullStackDB.add(Dict, **data)
return result, "add dictionary {}.".format("success" if result else "fail")
def delete(self, uuid):
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = Dict.get(uuid=uuid)
if not result:
return False, "dict does not exists"
else:
if result.is_system:
return False, "dict can not delete"
result = fullStackDB.update(Dict, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete dictionary {}.".format("success" if result else "fail")
def get(self, data):
result = Dict.get(**data)
if result:
result = result.to_dict(only=["uuid", "label", "create_at", "update_at"])
return result, "get dictionary {}.".format("success" if result else "no data")
def getList(self, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
if 'is_category' in temp:
temp.pop('is_category')
if 'category' in temp and isinstance(data.get("category"), list):
temp.pop("category")
temp.setdefault("is_delete", False)
if "scope_type" in data and data.get("scope_type") == "list":
result = Dict.select().where(**temp).order_by(Dict.sort)
temp = []
for item in result:
if item.category in data.get("category"):
temp.append(item.to_dict(only=["uuid", "label", "value", "category"]))
return temp, len(temp), "get dictionary list {}.".format("success" if temp else "no data")
elif "is_category" in data and data.get("is_category") == 1:
result = select(d.category for d in Dict)
# result = Dict.select_by_sql("SELECT DISTINCT(`category`) FROM `{}`".format(Dict._table_))
return list(result), len(result), "get select {}.".format("success" if result else "fail")
result = Dict.select().where(**temp).order_by(desc(Dict.create_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = Dict.select().where(**temp).count()
if result:
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True,)
t.update({
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S"),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
"update_by": item.update_by.to_dict(only=["uuid", "username"])
})
temp.append(t)
result = temp
return result, count, "get dictionary {}.".format("success" if result else "fail")
def update(self, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Dict, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
return result, "update dictionary {}.".format("success" if result else "fail")
dictManager = DictManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import copy
import json
import logging
import urllib
from pathlib import Path
from urllib import parse, request
from urllib.parse import urlparse
from datetime import datetime
from pony.orm import *
from app.setting import config
from model.download import AppDownload
from model.device import Device
from model.apps import Apps
from model.user import User
from utils import ThreadMaker
logger = logging.getLogger(__name__)
@ThreadMaker
def update_download_information(ip, id):
params = { 'ak': 'aZEAgYG8wKuLd6DS9BmCloGtfnGGkRMn', 'coor': 'bd09ll' }
parameters = urllib.parse.urlencode(params)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko'
}
if ip != '127.0.0.1':
params.update({'ip': ip})
parameters = urllib.parse.urlencode(params)
url = 'http://api.map.baidu.com/location/ip'
req = request.Request(url='%s%s%s' % (url, '?', parameters), headers=headers)
ret = request.urlopen(req).read()
jsonData = json.loads(ret)
logger.info(jsonData)
if (0 != jsonData['status']):
return None
with db_session:
down = AppDownload.get(id=id)
if down:
down.set(address=jsonData['address'], ip=ip, remarks=json.dumps(jsonData['content'], ensure_ascii=False))
commit()
def convert_url_to_local_path(url):
parsed_result = urlparse(url)
target_file = os.sep.join([config.get("UPLOAD_PATH").replace('\\', '/'), parsed_result.path])
target_file = os.path.normpath(target_file)
return target_file
class DownloadManager(object):
def __init__(self):
super(DownloadManager, self).__init__()
def add(self, user, data):
with db_session:
app = Apps.get(id=data.get("app"), is_delete=False)
if not app:
return False, "app does not found"
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = AppDownload(app=app, imei=data.get("imei"), **data)
commit()
return result, "add dictionary {}.".format("success" if result else "fail")
def delete(self, user, uuid):
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = AppDownload.get(uuid=uuid)
if not result:
return False, "dict does not exists"
result.set(is_delete=True, delete_at=datetime.now(), delete_by=editor)
commit()
return result, "delete dictionary {}.".format("success" if result else "fail")
def get(self, data):
# 流程如下:
# 获取前端传来的应用UUID和IMEI
# 根据应用UUID查找应用信息,找不到返回失败信息
# 如果应用ID是evue_launcher,则进行如下处理
# 遍历系统所有应用,将相关应用根据4个一组拼接到一个数组里面去
# 最后将这些信息导出为一个JSON文件
# 将evue_launcher.evue和evue_dock.evue以及相关资源文件进行打包
# 以上文件全部是复制处理,最后根据格式生成文件夹,将epk文件写入到这里
# 读取这个epk文件,以encoding='utf8'格式返回字节流
# 否则就是普通应用
# 查找出这个应用路径以及依赖文件
# 将这些文件进行打包
# 读取这个epk文件,以encoding='utf8'格式返回字节流
# 此次下载将生成一次下载记录
# 当前还没有校验前端传来的IMEI是否是合法的
# 根据IMEI查找设备,根据设备查找用户,根据用户查找应用
app = None
with db_session:
# 根据IMEI查找设备
# device = Device.select().where(imei=data.get("imei")).first()
# logger.info(data)
# if not device:
# return False, "device not found"
# if not device.create_by:
# return False, "create user is null"
app = Apps.select(app_name=data.get("id")).order_by(desc(Apps.create_at))
if len(app) > 1:
app = Apps.select(lambda p: p.app_name == data.get("id") and p.create_by.account == 'evm').order_by(desc(Apps.create_at))
if not app:
return False, "app not found"
app = app[:]
epk_path = ""
if app[0].app_build_log:
epk_path = os.path.normpath(os.sep.join([config.get("UPLOAD_PATH"), app[0].app_build_log.app_path]))
epk_path = Path(epk_path)
if not epk_path.exists():
return False, "epk file not found"
down = AppDownload(app=app[0], imei=data.get("imei"))
commit()
if down:
update_download_information(data.get('real_ip', '127.0.0.1'), down.id)
return epk_path, "get dictionary {}.".format("success" if epk_path else "no data")
def getList(self, user, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
temp.setdefault("is_delete", False)
with db_session:
if "scope_type" in data and data.get("scope_type") == "list":
result = AppDownload.select().where(**temp).order_by(AppDownload.sort)
temp = []
for item in result:
temp.append(item.to_dict(only=["uuid"]))
return temp, len(temp), "get dictionary list {}.".format("success" if temp else "no data")
result = AppDownload.select().where(**temp).order_by(desc(AppDownload.download_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = AppDownload.select().where(**temp).count()
if result:
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True)
t.update({
"app": item.app.to_dict(exclude=["create_by", "update_by", "delete_by", "is_delete"]),
"download_at": item.download_at.strftime("%Y-%m-%d %H:%M:%S")
})
temp.append(t)
result = temp
return result, count, "get dictionary {}.".format("success" if result else "fail")
def update(self, user, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
with db_session:
# 查询请求者是否存在
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = AppDownload.get(uuid=uuid)
if not result:
return False, "app does not found"
result.set(update_at=datetime.now(), update_by=editor, **data)
commit()
return result, "update dictionary {}.".format("success" if result else "fail")
downloadManager = DownloadManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import logging
from datetime import datetime
from pony.orm import *
from model import fullStackDB
from model.login_logs import LoginLogs
from model.user import User
logger = logging.getLogger(__name__)
class LoginLogsManager(object):
def __init__(self):
super(LoginLogsManager, self).__init__()
def add(self, user, data):
# 判断角色名是否存在
result = LoginLogs.get(name=data.get("name"))
if result:
return False, "app logs name has been exists."
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
})
result = fullStackDB.add(LoginLogs, **data)
return result, "add app logs {}.".format("success" if result else "fail")
def delete(self, user, uuid):
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = LoginLogs.get(uuid=uuid)
if result:
result.delete()
return result, "delete app logs {}.".format("success" if result else "fail")
def get(self, data):
result = LoginLogs.get(**data)
if result:
result = result.to_dict(with_collections=True, related_objects=True)
return result, "get app logs {}.".format("success" if result else "fail")
def getList(self, user, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null"
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
temp.update({ 'create_by': editor })
if "scope_type" in data and data.get("scope_type") == "list":
result = LoginLogs.select().where(**temp).order_by(desc(LoginLogs.create_at))
temp = []
for item in result:
temp.append(item.to_dict(only=["uuid"]))
return temp, len(temp), "get select {}.".format("success" if temp else "no data")
result = LoginLogs.select().where(**temp).order_by(desc(LoginLogs.create_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = LoginLogs.select().where(**temp).count()
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True)
t.update({
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
})
temp.append(t)
result = temp
return result, count, "get app logs {}.".format("success" if result else "no data")
def update(self, user, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
return True, "update app logs {}.".format("success" if True else "fail")
loginLogsManager = LoginLogsManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import json
import logging
import urllib
from urllib import parse, request
from datetime import datetime
from threading import Thread
from werkzeug.security import check_password_hash
from flask import request as flask_request
from pony.orm import *
from model.user import User
from model.login_logs import LoginLogs
from fullstack.login import Auth
from fullstack.response import ResponseCode
from utils import md5_salt, ThreadMaker
logger = logging.getLogger(__name__)
@ThreadMaker
def update_login_information(ip, user_id):
params = { 'ak': 'aZEAgYG8wKuLd6DS9BmCloGtfnGGkRMn', 'coor': 'bd09ll' }
parameters = urllib.parse.urlencode(params)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko'
}
if ip != '127.0.0.1':
params.update({'ip': ip})
parameters = urllib.parse.urlencode(params)
url = 'http://api.map.baidu.com/location/ip'
req = request.Request(url='%s%s%s' % (url, '?', parameters), headers=headers)
ret = request.urlopen(req).read()
jsonData = json.loads(ret)
logger.info(jsonData)
if (0 != jsonData['status']):
return None
with db_session:
user = User.get(id=user_id)
if not user:
return
LoginLogs(username=user.username, ip=ip, address=jsonData['address'], create_by=user, remarks=json.dumps(jsonData['content'], ensure_ascii=False))
commit()
class LoginManager(object):
'''
用户管理的单例类
'''
def __init__(self):
super(LoginManager, self).__init__()
# Thread(target=self.dashboard).start()
def login(self, data):
'''
用户登录
:param data:登录的用户信息json如 { "account": "xx", "password": "xx" }
:return ret: dict类型的登录相关信息
'''
with db_session:
# 判断用户名是否存在
result = User.get(account=data.get("account"))
if not result:
return False, ResponseCode.NO_DATA_FOUND
# 判断密码是否正确
result = User.get(account=data.get("account"), password=md5_salt(data.get("password")))
if not result:
return False, ResponseCode.PASSWORD_ERROR
# 判断用户是否禁用
if result.is_delete:
return False, ResponseCode.ACCOUNT_DISABLED
real_ip = flask_request.headers['X-Forwarded-For']
update_login_information(real_ip, result.id)
# 返回token
token = Auth.encode_auth_token(result.id, result.username, str(result.uuid)) # 生成 token
# setattr(result, 'token', token)
return { 'token': token, 'id': result.id, 'username': result.username }, ResponseCode.OK
def logout(self):
'''
用户登出
'''
return True, "user logout success."
def register(self, data):
'''
用户注册
'''
with db_session:
# 判断账号是否存在
editor = User.get(account=data.get("account"))
if editor:
return False, "user already exists"
data.update({
"password": md5_salt(data['password']),
"create_by": 0,
"create_at": datetime.now(),
"update_by": 0,
"update_at": datetime.now()
})
result = User(**data)
commit()
result.create_by = result.id
result.update_by = result.id
commit()
return result, "user register {}.".format("success" if result else "fail")
loginManager = LoginManager()
'''
Author: your name
Date: 2021-06-29 19:24:32
LastEditTime: 2021-07-14 21:25:39
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\backend\controller\monitor.py
'''
from model.monitor import session, System, Lvgl, Evm, Image, Device, Request, User
class SystemResource(object):
def get(self):
result = session.query(System).all()
print(result)
return result
def post(self, params):
result = System(**params)
session.add(result)
return session.commit()
def put(self):
pass
def delete(self):
pass
class LvglResource(object):
def get(self):
result = session.query(Lvgl).all()
print(result)
return result
def post(self, params):
result = Lvgl(**params)
session.add(result)
return session.commit()
def put(self):
pass
def delete(self):
pass
class EvmResource(object):
def get(self):
result = session.query(Evm).all()
print(result)
return result
def post(self, params):
result = Evm(**params)
session.add(result)
return session.commit()
def put(self):
pass
def delete(self):
pass
class ImageResource(object):
def get(self):
result = session.query(Image).all()
print(result)
return result
def post(self, params):
result = Image(**params)
session.add(result)
return session.commit()
def post_array(self, array, watch):
t = []
for a in array:
a.update({ "watch": watch })
t.append(Image(**a))
session.add_all(t)
return session.commit()
def put(self):
pass
def delete(self):
pass
systemResource = SystemResource()
lvglResource = LvglResource()
evmResource = EvmResource()
imageResource = ImageResource()
def insert_data(msg):
# 先判断手表imei是否存在,不存在则先注册手表IMEI
watch_id = -1
if msg.get("imei"):
result = session.query(Device).filter_by(imei=msg.get("imei")).first()
if result:
watch_id = result.id
else:
user = session.query(User).filter(User.account=="evm").first()
result = Device(imei=msg.get("imei"), name="watch_{}".format(msg.get("imei")), type="watch", create_by=user.id, update_by=user.id)
session.add(result)
session.flush()
session.commit()
result = session.query(Device).filter_by(imei=msg.get("imei")).first()
if result:
watch_id = result.id
if msg.get("request"):
msg.get("request").update({ "watch": watch_id })
result = Request(**msg.get("request"))
session.add(result)
session.flush()
session.commit()
if msg.get("system"):
msg.get("system").update({ "watch": watch_id })
systemResource.post(msg.get("system"))
if msg.get("lvgl"):
msg.get("lvgl").update({ "watch": watch_id })
lvglResource.post(msg.get("lvgl"))
if msg.get("evm"):
msg.get("evm").update({ "watch": watch_id })
evmResource.post(msg.get("evm"))
if msg.get("image"):
imageResource.post_array(msg.get("image"), watch_id)
def get_watch_list():
result = session.query(Device).all()
tmp = []
for item in result:
tmp.append({
'id': item.id,
'imei': item.imei
})
return tmp
def evm_data(watch, start, end):
filters = [Evm.watch==watch]
if start:
filters.append(Evm.timestamp >= start)
if end:
filters.append(Evm.timestamp <= end)
result = session.query(Evm).filter(*filters).order_by(Evm.timestamp).all()
temp = []
for item in result:
t = item.to_dict()
if t.get("timestamp"):
t.update({ 'timestamp': t.get("timestamp").strftime("%Y-%m-%d %H:%M:%S") })
temp.append(t)
return temp
def lvgl_data(watch, start, end):
filters = [Lvgl.watch==watch]
if start:
filters.append(Lvgl.timestamp>=start)
if end:
filters.append(Lvgl.timestamp<=end)
result = session.query(Lvgl).filter(*filters).order_by(Lvgl.timestamp).all()
temp = []
for item in result:
t = item.to_dict()
if t.get("timestamp"):
t.update({ 'timestamp': t.get("timestamp").strftime("%Y-%m-%d %H:%M:%S") })
temp.append(t)
return temp
def image_data(watch, start, end):
filters = [Image.watch==watch]
if start:
filters.append(Image.timestamp>=start)
if end:
filters.append(Image.timestamp<=end)
result = session.query(Image).filter(*filters).order_by(Image.timestamp).all()
temp = []
for item in result:
t = item.to_dict()
if t.get("timestamp"):
t.update({ 'timestamp': t.get("timestamp").strftime("%Y-%m-%d %H:%M:%S") })
temp.append(t)
return temp
def get_monitor_list(watch, category, start, end):
# 判断watch是否存在
w = session.query(Device).filter(Device.id==watch).first()
if not w:
return []
if category == "system":
return []
elif category == "image":
return image_data(watch, start, end)
elif category == "lvgl":
return lvgl_data(watch, start, end)
elif category == "evm":
return evm_data(watch, start, end)
else:
return {
'evm': evm_data(watch, start, end),
'lvgl': lvgl_data(watch, start, end),
'image': image_data(watch, start, end)
}
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import json
import logging
import traceback
import tempfile
import base64
from hashlib import md5 as fmd5
from werkzeug.security import check_password_hash
logger = logging.getLogger(__name__)
FileStoragePath = os.getcwd()
# 判断目录是否存在,不存在则创建
# if not os.path.exists(os.path.join(FileStoragePath, config.get("UPLOAD_DIR"))):
# os.makedirs(os.path.join(FileStoragePath, config.get("UPLOAD_DIR")))
def ajaxCheckAccess(path):
realpath = os.path.realpath(path)
if not realpath.startswith(FileStoragePath):
return False
return True
def checkPath(path):
if not path:
return False, {"code": -1, "data": None, "message": "[%s] arg missed!" % path}
fpath = os.path.abspath(os.sep.join(
[os.path.abspath(FileStoragePath), path]))
if not ajaxCheckAccess(fpath):
return False, {"code": -1, "data": None, "message": "You have no access to [%s]!" % fpath}
if not os.path.exists(fpath):
return False, {"code": -1, "data": None, "message": "[%s] is not existed!" % fpath}
return True, os.path.abspath(fpath)
def saveToFile(saveFile, content):
try:
tfn = tempfile.mktemp()
tf = open(tfn, 'w+b')
tf.write(content)
tf.close()
os.rename(tfn, saveFile)
return True
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return False
def getFileInfo(infofile):
info = dict()
info.update({
"isfile": os.path.isfile(infofile),
"isdir": os.path.isdir(infofile),
"size": os.path.getsize(infofile),
"atime": os.path.getatime(infofile),
"mtime": os.path.getmtime(infofile),
"ctime": os.path.getctime(infofile),
"name": os.path.basename(infofile)
})
return info
class UploadManager(object):
def __init__(self):
super(UploadManager, self).__init__()
def download(self, data):
obj = json.loads(data)
isAccessed, path = checkPath(obj["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
if not os.path.isfile(path):
return {"code": -1, "data": None, "message": "Path [%s] is not a valid file!" % path}
try:
with open(path, "rb") as f:
content = base64.b64encode(f.read())
md5code = fmd5(content).hexdigest()
return {
"data": {
"content": content,
"md5": md5code,
"filename": os.path.basename(path)
},
"code": 0,
"message": "download file [%s] successfully!" % obj['path']
}
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return {
"data": None,
"code": -1,
"message": "upload file [%s] failed!\n %s" % (obj['path'], repr(e))
}
def delete(self, data):
try:
isAccessed, path = checkPath(data["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
if os.path.isfile(path):
os.remove(path)
return {"code": 0, "data": None, "message": "delete file [%s] successfully!" % path}
elif os.path.isdir(path):
os.rmdir(path)
return {"code": 0, "data": None, "message": "delete dir [%s] successfully!" % path}
else:
return {"code": 0, "data": None, "message": "Path [%s] is not a valid file or path!" % path}
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return {"code": -1, "data": None, "message": repr(e)}
def dirlist(self, data):
obj = json.loads(data)
isAccessed, path = checkPath(obj["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
result = []
for p in os.listdir(path):
result.append(getFileInfo(os.path.join(FileStoragePath, p)))
return {"code": 0, "result": result, "message": "Get [%s] successfully!" % path}
def filemd5(self, data):
obj = json.loads(data)
isAccessed, path = checkPath(obj["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
if not os.path.isfile(path):
return {"code": -1, "data": None, "message": "Path [%s] is not a valid file!" % path}
with open(path, "rb") as f:
filemd5 = fmd5(f.read()).hexdigest()
return {"code": 0, "result": filemd5, "message": "Get md5 of [%s] successfully!" % path}
def fileinfo(self, data):
obj = json.loads(data)
isAccessed, path = checkPath(obj["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
if not os.path.isfile(path):
return {"code": -1, "data": None, "message": "Path [%s] is not a valid file!" % path}
return {"code": 0, "result": getFileInfo(path), "message": "Get md5 of [%s] successfully!" % path}
uploadManager = UploadManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import logging
import copy
from datetime import datetime
from pony.orm import *
from model import fullStackDB
from model.user import User
from utils import md5_salt
logger = logging.getLogger(__name__)
class UserManager(object):
'''
用户管理的单例类
'''
def __init__(self):
super(UserManager, self).__init__()
def check(self, data):
with db_session:
user = User.get(uuid=data.get("uuid"))
if not user:
return False
return True
def add(self, uuid, data):
'''
添加用户
'''
# 判断账号是否存在
isExists = select(u for u in User if u.account == data['account'] and u.is_delete == False).exists()
if isExists:
return False, "user already exists"
editor = User.get(id=uuid)
if not editor:
return False, "current user is not exists"
if "username" not in data or not data.get("username"):
data.update({ "username": data.get("account") })
# 密码加密
data['password'] = md5_salt(data['password'])
data.update({
"create_by": editor.id,
"create_at": datetime.now(),
"update_by": editor.id,
"update_at": datetime.now()
})
# 添加用户时,是否考虑将该用户的过期时间加入预警
result = fullStackDB.add(User, **data)
return result, "add user {}.".format("success" if result else "fail")
def delete(self, uuid):
'''
删除用户
'''
with db_session:
editor = User.get(uuid=uuid)
if not editor:
return False, "current user is not exists"
result = User.get(uuid=uuid)
if result:
result.delete()
commit()
result = True
return result, "delete user {}.".format("success" if result else "fail")
def update(self, uuid, data):
'''
更新用户
'''
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
with db_session:
# 查询请求者是否存在
editor = User.get(uuid=uuid)
if not editor:
return False, "current user is not exists"
if "password" in data:
data["password"] = md5_salt(data['password'])
user = User.get(uuid=uuid)
if user:
user.set(update_at=datetime.now(), update_by=editor.id, **data)
result = user.to_dict(only=["account", "gender", "birthday", "phone", "email",])
if result.get("birthday"):
result.update({ "birthday": result.get("birthday").strftime("%Y-%m-%d") })
return result, "update user success"
else:
return None, "user does not exists"
def get(self, user):
'''
查询单用户
'''
result = User.get(id=user, is_delete=False)
if result:
temp = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "username", "account", "role", "phone", "email", "gender", "create_at", "update_at"])
temp.update({
"create_at": result.create_at.strftime("%Y-%m-%d %H:%M:%S") if result.create_at else None,
"update_at": result.update_at.strftime("%Y-%m-%d %H:%M:%S") if result.update_at else None,
})
result = temp
return result, "get user {}.".format("success" if result else "not found")
def getList(self, data):
'''
查询多用户
'''
# 当参数为空时,直接返回错误
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
temp.setdefault("is_delete", False)
if "scope_type" in data and data.get("scope_type") == "list":
result = User.select().where(**temp).order_by(desc(User.create_at))
temp = []
for item in result:
t = item.to_dict(only=["id", "uuid", "username", "account"])
temp.append(t)
return temp, len(temp), "get select {}.".format("success" if temp else "no data")
result = User.select().where(**temp).order_by(desc(User.create_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = User.select().where(**temp).count()
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, only=["uuid", "username", "account", "phone", "email", "gender", "create_at", "update_at", "remarks"])
t.update({
"email": "" if item.email == "user@example.com" else item.email,
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S"),
})
temp.append(t)
result = temp
return result, count, "get users {}.".format("success" if result else "no data")
userManager = UserManager()
'''
Author: your name
Date: 2021-04-14 14:12:18
LastEditTime: 2021-07-01 14:46:22
LastEditors: your name
Description: In User Settings Edit
FilePath: \evm-store\backend\deploy.py
'''
import os
import json
import shutil
import configparser
from datetime import datetime
from operator import itemgetter
# 应用和数据分离
# 数据库文件备份在evm_app_store_files/epkdb
# 探测文件变化,定时备份到 epkdb
config = configparser.ConfigParser()
config.read(os.path.join(os.getcwd(), "config.ini"))
# 根据文件最后修改时间排序文件
def getSortDir(path):
lists = os.listdir(path)
print(lists)
lists.sort(key=lambda fn: os.path.getmtime(os.sep.join([path, fn])))
filepath = os.path.join(path, lists[-1])
print(filepath)
return lists
def isFileChange(dt):
f = os.sep.join([os.getcwd(), config.get("database", "filename")])
if dt:
return dt != int(os.path.getmtime(f))
else:
return int(os.path.getctime(f)) != int(os.path.getmtime(f))
def backupDatabase():
src = config.get("database", "filename")
dst = os.path.abspath(config.get("uploads", "upload_path"))
dst = os.path.normpath(os.sep.join([dst, config.get("uploads", "db_dir")]))
if not os.path.exists(dst):
os.makedirs(dst)
# 判断文件创建时间和修改时间是否一致,不一致则备份
shutil.copy(src, dst)
src = os.sep.join([dst, src])
dst = os.sep.join([dst, f"{datetime.now().strftime('%Y%m%d%H%M%S')}-{config.get('database', 'filename')}"])
os.rename(src, dst)
def removeExpiredFiles():
path = os.path.abspath(config.get("uploads", "upload_path"))
path = os.path.normpath(os.sep.join([path, config.get("uploads", "db_dir")]))
if not os.path.exists(path):
os.makedirs(path)
file_count = len(os.listdir(path))
if file_count > 10:
file_list = getSortDir(path)[:-10]
for f in file_list:
os.remove(os.sep.join([path, f]))
def getModifyTime():
result = {}
with open("./backupData.json", "r+") as f:
result = json.loads(f.read())
return result
def saveMofidyTime(result):
db = config.get("database", "filename")
result["lastModifyDateTime"] = int(os.path.getmtime(db))
with open("./backupData.json", "w+") as f:
f.write(json.dumps(result))
return result
def main():
removeExpiredFiles()
result = getModifyTime()
if isFileChange(result["lastModifyDateTime"]):
saveMofidyTime(result)
backupDatabase()
if __name__ == "__main__":
main()
\ No newline at end of file
#!/usr/bin/env bash
Cur_Dir=$(pwd)
rm -rf ${Cur_Dir}/release
mkdir -p ${Cur_Dir}/release
cxfreeze ${Cur_Dir}/start.py --install-dir=${Cur_Dir}/release
cp -fi ${Cur_Dir}/config.ini ${Cur_Dir}/release/
cp -fi ${Cur_Dir}/backupData.json ${Cur_Dir}/release/
cp -fi ${Cur_Dir}/app-store.db ${Cur_Dir}/release/
\ No newline at end of file
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['deploy.py'],
pathex=['F:\\Wanli\\projects\\kxpms\\backend'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='deploy',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False )
#!/usr/bin/env python
# -*- coding: utf_8 -*-
class PySignal(object):
"""
Simple event class used to provide hooks for different types of events in Locust.
Here's how to use the EventHook class::
my_event = PySignal()
def on_my_event(a, b, **kw):
print "Event was fired with arguments: %s, %s" % (a, b)
my_event += on_my_event
my_event.fire(a="foo", b="bar")
my_event.emit(a="foo", b="bar")
"""
def __init__(self):
self._handlers = []
def __iadd__(self, handler):
return self.connect(handler)
def __isub__(self, handler):
return self.disconnect(handler)
def connect(self, handler):
self._handlers.append(handler)
return self
def disconnect(self, handler):
self._handlers.remove(handler)
return self
def fire(self, *args, **kwargs):
return self.emit(*args, **kwargs)
def emit(self, *args, **kwargs):
rets = {}
for handler in self._handlers:
ret = handler(*args, **kwargs)
rets[handler.__name__] = ret
if len(rets) == 1:
return list(rets.values())[0] # list()用来兼容python3
return rets
if __name__ == '__main__':
my_event = PySignal()
def on_my_event(a, b, **kw):
print(a, b)
print(kw)
my_event.connect(on_my_event)
my_event.fire(1, 2, c="foo", d="bar")
my_event.emit(3, 4, e="foo", f="bar")
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import logging
from logging.handlers import RotatingFileHandler
import os
logPath = os.getcwd() + os.path.sep + "logs"
if not os.path.exists(logPath):
os.makedirs(logPath)
fh = RotatingFileHandler("logs/webapiscraper.log",
maxBytes=10 * 1024 * 1024, backupCount=100)
fh.setLevel(logging.DEBUG)
# log write in console
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# log formatter
formatter = logging.Formatter(
'[%(asctime)s][%(levelname)7s] [%(filename)15s%(funcName)15s%(lineno)06s] %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger = logging.root
logger.setLevel(logging.DEBUG)
logger.addHandler(fh)
logger.addHandler(ch)
from .auth import Auth
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import logging
import traceback
from datetime import datetime, timedelta
from functools import wraps
import jwt
from flask import current_app, request
logger = logging.getLogger(__name__)
class Auth(object):
def __init__(self):
super(Auth, self).__init__()
@staticmethod
def auth_required(func):
'''
api接口的登录鉴权装饰器
包括cookie和jwt_token鉴权
'''
@wraps(func)
def inner(*args, **kwargs):
if current_app.config.get('LOGIN_DISABLED'):
return func(*args, **kwargs)
auth = Auth()
isSuccess, message = auth.identify(request)
if isSuccess:
return func(*args, **kwargs)
return current_app.unauthorized(message)
return inner
@staticmethod
def encode_auth_token(user_id, username, uuid):
"""
生成认证Token
:param user_id: int
:param username: str
:return: bytes
"""
payload = {
'iat': datetime.now(),
'exp': datetime.now() + timedelta(hours=2), # 两个小时后过期
'iss': 'bytecode', # token签发者
'aud': 'bytecode', # token接收者
'sub': user_id, # token所属者
'data': { # payload
'id': user_id,
'uuid': uuid,
'username': username
}
}
token = jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256')
if isinstance(token, bytes): # dict 转成json传输时, value中为byte类型会报错
token = str(token, 'utf8')
return token
@staticmethod
def decode_auth_token(auth_token):
"""
验证Token
:param auth_token:
:return: dict|string
"""
try:
# result = re.match(r'[+-/*\w]+\.[+-/*\w]+\.[+/*-\w]+', auth_token, re.I)
# if not result or not result.group():
# return False, "token invaild"
payload = jwt.decode(auth_token, current_app.config['SECRET_KEY'], verify=True, algorithms=['HS256'], options={'require': ['exp', 'iss', 'sub', 'aud', 'iat', 'data']}, audience="bytecode")
if payload:
return True, payload
else:
return False, "payload invaild"
# except jwt.ExpiredSignatureError:
# return 'token expire'
# except jwt.InvalidTokenError:
# return 'token invaild'
except Exception as e:
traceback.print_exc()
return False, str(e)
def identify(self, request):
"""
用户鉴权
:param request: flask的requst全局对象
:return: bool
"""
try:
auth_token = request.headers.get('Authorization')
if auth_token:
isSuccess, result = self.decode_auth_token(auth_token)
print(result)
if isSuccess:
if "data" in result and "id" in result["data"] and "username" in result["data"]:
setattr(request, 'current_user', result['data'])
return True, result['data']
return False, "data invaild"
else:
return False, result
return False, "authorization token can not be none"
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return False, str(e)
class ResponseCode(object):
OK = (200, 'OK')
NO_DATA = (204, 'No data')
NO_DATA_FOUND = (404, 'No data found')
NOTHING_CHANGE = (304, 'Nothing change')
REQUEST_ERROR = (400, 'Request error')
PARAMETER_ERROR = (4001, 'Parameter error')
PARAMETER_NULL = (4002, 'Parameter is null')
PASSWORD_ERROR = (4003, 'Password error')
EXISTS_ERROR = (4004, 'Record already exists')
INVAILD_ROLE_ERROR = (4005, 'Invaild role error')
ACCOUNT_DISABLED = (4006, 'Account is disabled')
AUTHORIZATION_ERROR = (401, 'Authentication error')
INVAILD_REQUEST = (403, 'Invaild request')
DB_ERROR = (5001, 'Database error')
SERVER_ERROR = (5002, 'Server error')
UNKNOWN_ERROR = (5003, 'Unknown error')
def response_result(code, msg=None, data=None, **kwargs):
if msg is None:
msg = code[1]
result = { 'code': code[0], 'message': msg, 'data': data }
result.update(kwargs)
return result
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
from app import config
from apscheduler.schedulers.background import BackgroundScheduler
# from apscheduler.jobstores.mongodb import MongoDBJobStore
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
jobstores = {
# 'mongo': MongoDBJobStore(),
'default': SQLAlchemyJobStore(url='sqlite:///{}'.format("scheduler.db", engine_options={ 'connect_args': { 'timeout': 15 } })
}
executors = {
'default': ThreadPoolExecutor(20),
'processpool': ProcessPoolExecutor(1)
}
job_defaults = {
'coalesce': False,
'max_instances': 1
}
scheduler = BackgroundScheduler(executors=executors, job_defaults=job_defaults,)
scheduler.start()
\ No newline at end of file
import functools
import json
from flask import request
from marshmallow import Schema, ValidationError
from fullstack.response import ResponseCode, response_result
from app.setting import config
def validate_schema(schema_class: Schema):
def decorator(view_func):
@functools.wraps(view_func)
def inner(*args, **kwargs):
try:
if request.method == "GET":
form_data = request.args
elif request.method == "POST":
if request.content_type and request.content_type.startswith('application/json'):
form_data = request.json
elif request.content_type and request.content_type.startswith('application/x-www-form-urlencoded'):
form_data = request.values
elif request.content_type and request.content_type.startswith('multipart/form-data'):
form_data = request.form
else:
form_data = json.loads(request.data)
data = schema_class().load(form_data)
request.schema_data = data
print(request.schema_data)
except ValidationError as e:
if config['DEBUG']:
return response_result(ResponseCode.PARAMETER_ERROR, e.messages if config['DEBUG'] else None)
return view_func(*args, **kwargs)
return inner
return decorator
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import traceback
import logging
from pony.orm import *
from pony.orm.serialization import to_json
from pony.flask import Pony
logger = logging.getLogger(__name__)
class FullStackDB(object):
def __init__(self):
super(FullStackDB, self).__init__()
self._db = Database()
@property
def db(self):
return self._db
def __call__(self, app=None, drop_tables=[]):
if app:
Pony(app)
self.db.bind(**app.config['PONY'])
for name in drop_tables:
# 删除表,演示实体声明时用于快速清除旧表
self.db.drop_table(name, if_exists=True, with_all_data=True)
self.db.generate_mapping(create_tables=True)
def get(self, table, **kwargs):
'''
得到条目
'''
with db_session():
item = table.get(**kwargs)
return item
def add(self, table, **kwargs):
'''
增加条目
:param table: 操作的数据表
:param **kwargs: 新增条目的属性和值
'''
with db_session():
item = table(**kwargs)
commit()
return item
def delete(self, table, **kwargs):
'''
删除条目
:param table: 操作的数据表
:param **kwargs: 删除条目的属性和值
'''
with db_session():
target = table.get(**kwargs)
if target:
target.delete()
commit()
return True
else:
return False
def update(self, table, filters, **kwargs):
'''
:param item: 需要更新的条目,如 User[1]
:param **kwargs: 更新后条目的属性和值
'''
with db_session():
item = table.get(**filters)
if item:
for key, value in kwargs.items():
if value != None and hasattr(item, key):
setattr(item, key, value)
commit()
return item
else:
return False
def display(self, table):
'''
展示表格的所有条目信息
:param table: 操作的数据表
:return 成功则返回一个包含所有条目的列表 | 失败返回False
'''
with db_session():
items = select(item for item in table)[:]
items.show()
return items
def select(self, table, **kwargs):
with db_session():
return table.select(**kwargs)
def pagination(self, table, order, pagenum=1, pagesize=10, **kwargs):
if not isinstance(pagenum, int):
pagenum = int(pagenum)
if not isinstance(pagesize, int):
pagesize = int(pagesize)
with db_session():
return table.select().where(**kwargs).order_by(desc(order)).page(pagenum, pagesize)
def pagination_dict(self, table, order, pagenum=1, pagesize=10, **kwargs):
if not isinstance(pagenum, int):
pagenum = int(pagenum)
if not isinstance(pagesize, int):
pagesize = int(pagesize)
with db_session():
result = table.select().where(**kwargs).order_by(desc(order)).page(pagenum, pagesize)
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True)
for key in t:
if isinstance(t[key], self.db.Entity):
t[key] = t[key].to_dict()
temp.append(t)
return temp
def count(self, table, **kwargs):
with db_session():
return table.select().where(**kwargs).count()
fullStackDB = FullStackDB()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, LongStr
from app import config
from . import fullStackDB
db = fullStackDB.db
class Annex(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "annex"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app = Optional("Apps", reverse="app_annex")
title = Required(str, max_len=200) # 文件名
path = Required(LongStr) # 文件路径
type = Required(int, default=0) # 文件类型 PNG/JPG/GIF/MP3/MP4/DOCX/XLSX/PPT/PDF...
size = Required(float, default=0) # 文件大小
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse="annex_creator") # Annex与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse="annex_updater") # Annex与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse="annex_deleter") # Annex与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Json
from app import config
from . import fullStackDB
db = fullStackDB.db
class AppLogs(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "app_logs"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app_name = Optional(str)
app_path = Optional(str, default="")
app_version = Optional(str, default="")
app_info = Optional(Json, default={})
create_at = Required(datetime, default=datetime.now)
create_by = Optional("User", reverse='app_logs_creater')
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional
from app import config
from . import fullStackDB
db = fullStackDB.db
# 当前用户拥有哪些APP
class AppUser(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "app_user"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app = Required("Apps", reverse="app_user")
device = Required("Device", reverse="app_user")
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='app_users_creator')
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='app_users_updater')
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='app_users_deleter')
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Set
from app import config
from . import fullStackDB
# ********************************
from .app_users import AppUser
# ********************************
db = fullStackDB.db
class Apps(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "apps"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app_name = Required(str, max_len=200)
app_version = Optional(str, default="")
app_url = Optional(str, default="")
category = Optional(str, default="")
app_icon = Optional(str)
app_desc = Optional(str, default="")
app_annex = Set("Annex", reverse="app", cascade_delete=True)
app_user = Optional("AppUser", reverse="app", cascade_delete=True)
app_build_log = Optional("BuildLogs", reverse="app", cascade_delete=True)
app_download = Set("AppDownload", reverse="app", cascade_delete=True)
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='apps_creator') # BuildLogs与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='apps_updater') # BuildLogs与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='apps_deleter') # BuildLogs与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Json
from app import config
from . import fullStackDB
db = fullStackDB.db
class BuildLogs(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "build_logs"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app = Required("Apps", reverse="app_build_log")
app_path = Optional(str, default="")
app_info = Optional(Json, default={})
source = Optional(int, default=0) # 打包来源 1管理中心 2后端接口
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='build_logs_creator') # BuildLogs与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='build_logs_updater') # BuildLogs与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='build_logs_deleter') # BuildLogs与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Set
from app import config
from . import fullStackDB
db = fullStackDB.db
class Device(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "device"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
name = Required(str) # 名称
imei = Required(str) # IMEI
desc = Optional(str) # 描述信息
type = Optional(str) # 设备类型
app_user = Set("AppUser", reverse="device")
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='device_creator')
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='device_updater')
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='device_deleter')
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional
from app import config
from . import fullStackDB
db = fullStackDB.db
class Dict(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "dictionary"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
label = Required(str)
value = Required(str)
category = Required(str)
is_system = Required(bool, default=False) # 能否删除
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='dict_creator') # Dict与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='dict_updater') # Dict与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='dict_deleter') # Dict与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional
from app import config
from . import fullStackDB
db = fullStackDB.db
class AppDownload(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "download"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app = Optional("Apps", reverse="app_download")
imei = Required(str)
ip = Optional(str)
address = Optional(str)
download_at = Required(datetime, default=datetime.now)
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional
from app import config
from . import fullStackDB
db = fullStackDB.db
class LoginLogs(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "login_logs"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
username = Optional(str)
ip = Optional(str)
address = Optional(str)
create_at = Required(datetime, default=datetime.now)
create_by = Optional("User", reverse='login_logs_creater')
sort = Optional(int, size=32, default=0)
remarks = Optional(str, default="", nullable=True)
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import json
import uuid
from app.setting import config
from datetime import datetime
from sqlalchemy import create_engine
from sqlalchemy import func, Column, Integer, String, DateTime, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, class_mapper
engine = create_engine('sqlite:///{}?check_same_thread=False'.format(config.get("DATABASE")), echo=False)
Base = declarative_base()
def get_current_datetime():
return datetime.now()
def gen_id():
return uuid.uuid4().hex
def object_to_dict(obj):
columns = [column.key for column in class_mapper(obj.__class__).columns]
get_key_value = lambda c: (c, getattr(obj, c).isoformat()) if isinstance(getattr(obj, c), datetime) else (c, getattr(obj, c))
return dict(map(get_key_value, columns))
class WatchTest(Base):
__tablename__ = 'monitor_watch_test'
id = Column(Integer, primary_key=True, autoincrement=True)
imei = Column(String)
create_at = Column(DateTime(timezone=True), default=get_current_datetime, server_default=func.now(), onupdate=func.now())
class Watch(Base):
__tablename__ = 'monitor_watch'
id = Column(Integer, primary_key=True, autoincrement=True)
imei = Column(String)
create_at = Column(DateTime(timezone=True), default=get_current_datetime, server_default=func.now(), onupdate=func.now())
def to_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
class Request(Base):
__tablename__ = 'monitor_request'
id = Column(Integer, primary_key=True, autoincrement=True)
watch = Column(Integer) # 手表ID
host = Column(String)
path = Column(String)
protocol = Column(String)
create_at = Column(DateTime(timezone=True), default=get_current_datetime, server_default=func.now(), onupdate=func.now())
def to_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
class System(Base):
__tablename__ = 'monitor_system'
id = Column(Integer, primary_key=True, autoincrement=True)
watch = Column(Integer) # 手表ID
free_size = Column(Integer) # 单位:字节
timestamp = Column(DateTime(timezone=True), default=get_current_datetime, server_default=func.now(), onupdate=func.now())
def to_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
class Lvgl(Base):
__tablename__ = 'monitor_lvgl'
id = Column(Integer, primary_key=True, autoincrement=True)
watch = Column(Integer) # 手表ID
total_size = Column(Integer) # 单位:字节
free_cnt = Column(Integer)
free_size = Column(Integer)
free_biggest_size = Column(Integer)
used_cnt = Column(Integer)
used_pct = Column(Integer)
frag_pct = Column(Integer)
timestamp = Column(DateTime(timezone=True), default=get_current_datetime, server_default=func.now(), onupdate=func.now())
def to_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
class Evm(Base):
__tablename__ = 'monitor_evm'
id = Column(Integer, primary_key=True, autoincrement=True)
watch = Column(Integer) # 手表ID
# total_size = Column(Integer) # 单位:字节
# free_size = Column(Integer)
# gc_usage = Column(Integer)
heap_map_size = Column(Integer)
heap_total_size = Column(Integer)
heap_used_size = Column(Integer)
stack_total_size = Column(Integer)
stack_used_size = Column(Integer)
timestamp = Column(DateTime(timezone=True), default=get_current_datetime, server_default=func.now(), onupdate=func.now())
def to_dict(self):
# def convert_datetime(value):
# if value:
# return value.strftime("%Y-%m-%d %H:%M:%S")
# else:
# return ""
# for col in self.__table__.columns:
# if isinstance(col.type, DateTime):
# value = convert_datetime(getattr(self, col.name))
# elif isinstance(col.type, Numeric):
# value = float(getattr(self, col.name))
# else:
# value = getattr(self, col.name)
# yield {col.name: value}
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
def to_json(self):
d = dict(self.__todict__())
return json.dumps(d)
class Image(Base):
__tablename__ = 'monitor_image'
id = Column(Integer, primary_key=True, autoincrement=True)
watch = Column(Integer) # 手表ID
uri = Column(String(50))
length = Column(Integer)
png_uncompressed_size = Column(Integer)
png_total_count = Column(Integer)
png_file_size = Column(Integer)
timestamp = Column(DateTime(timezone=True), default=get_current_datetime, server_default=func.now(), onupdate=func.now())
def to_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
class User(Base):
__tablename__ = "{}".format(config['TABLE_PREFIX']) + "user"
id = Column(Integer, primary_key=True, autoincrement=True)
uuid = Column(String(64), default=gen_id, index=True)
account = Column(String(256))
class Device(Base):
__tablename__ = "{}".format(config['TABLE_PREFIX']) + "device"
id = Column(Integer, primary_key=True, autoincrement=True)
uuid = Column(String(64), default=gen_id, index=True)
name = Column(String, default="")
imei = Column(String)
desc = Column(String, default="")
type = Column(String, default="watch")
create_at = Column(DateTime(timezone=True), default=get_current_datetime, onupdate=func.now())
create_by = Column(Integer, default=None, nullable=True)
update_at = Column(DateTime(timezone=True), default=get_current_datetime, onupdate=func.now())
update_by = Column(Integer, default=None)
delete_at = Column(DateTime(timezone=True), default=get_current_datetime, onupdate=func.now())
delete_by = Column(Integer, default=None)
is_delete = Column(Boolean, default=False)
sort = Column(Integer, default=1)
remarks = Column(String, default="")
def to_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
Base.metadata.create_all(engine, checkfirst=True)
# engine是2.2中创建的连接
Session = sessionmaker(bind=engine)
# 创建Session类实例
session = Session()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime, date
from pony.orm import PrimaryKey, Required, Optional, Set
from app import config
from . import fullStackDB
db = fullStackDB.db
class User(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "user"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
role = Required(str, default="community") # 角色,管理员[administrator]、企业用户[enterprise]、社区用户[community]
account = Required(str, unique=True) # 账号
username = Required(str, max_len=100) # 用户名
password = Required(str, max_len=64) # 密码
gender = Optional(int, size=8, default=1) # 性别,未知0 男1 女2
birthday = Optional(date, default=date.today()) # 使用age会带来age无法随时间变化问题
phone = Optional(str, max_len=11, default="") # 联系方式
email = Optional(str, max_len=100, default="") # 邮箱
create_at = Required(datetime, default=datetime.now)
create_by = Required(int)
update_at = Required(datetime, default=datetime.now)
update_by = Required(int)
delete_at = Optional(datetime)
delete_by = Optional(int)
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
app_logs_creater = Set('AppLogs', reverse='create_by')
login_logs_creater = Set('LoginLogs', reverse='create_by')
annex_creator = Set('Annex', reverse='create_by')
annex_updater = Set('Annex', reverse='update_by')
annex_deleter = Set('Annex', reverse='delete_by')
apps_creator = Set('Apps', reverse='create_by')
apps_updater = Set('Apps', reverse='update_by')
apps_deleter = Set('Apps', reverse='delete_by')
app_users_creator = Set('AppUser', reverse='create_by')
app_users_updater = Set('AppUser', reverse='update_by')
app_users_deleter = Set('AppUser', reverse='delete_by')
build_logs_creator = Set('BuildLogs', reverse='create_by')
build_logs_updater = Set('BuildLogs', reverse='update_by')
build_logs_deleter = Set('BuildLogs', reverse='delete_by')
device_creator = Set('Device', reverse='create_by')
device_updater = Set('Device', reverse='update_by')
device_deleter = Set('Device', reverse='delete_by')
appdirs==1.4.4
certifi==2020.12.5
chardet==4.0.0
click==7.1.2
cx-Freeze==6.6
cx-Logging==3.0
Flask==1.1.2
Flask-Cors==3.0.10
Flask-Login==0.5.0
fs==2.4.12
idna==2.10
importlib-metadata==4.0.1
itsdangerous==1.1.0
Jinja2==2.11.3
MarkupSafe==1.1.1
marshmallow==3.10.0
pony==0.7.14
PyJWT==2.0.1
pytz==2021.1
requests==2.25.1
six==1.15.0
tornado==6.1
urllib3==1.26.4
Werkzeug==1.0.1
zipp==3.4.1
{
"count": 84
}
\ No newline at end of file
#!/usr/bin/env bash
# 获取当前路径
Cur_Dir=$(pwd)
# 关闭evm_store
supervisorctl stop evm_store
# 切换到release分支
git checkout release
# 拉取最新代码
git pull
# 启动evm_store
supervisorctl start evm_store
# 启动一个定时任务
# cd $Cur_Dir
# source venv/bin/activate
# 0 */1 * * * "${Cur_Dir}/venv/bin/python deploy.py"
# ps -def | grep "run.sh"
# ps -aux | grep start.py
Cur_Dir=$(pwd)
source venv/bin/activate
nohup ${Cur_Dir}/venv/bin/python3 ${Cur_Dir}/start.py > runoob.log 2>&1 &
This diff is collapsed.
from marshmallow import Schema
class BaseSchema(Schema):
pass
\ No newline at end of file
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
title = fields.String(required=True)
path = fields.String(required=True)
size = fields.Float(required=True)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
path = fields.String(required=False)
type = fields.Int(required=False)
size = fields.Float(required=False)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
title = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=False)
title = fields.String(required=False)
path = fields.String(required=False)
type = fields.Int(required=False)
size = fields.Float(required=False)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
name = fields.String(required=True, validate=validate.Length(min=2, max=50))
class Meta:
unknown = EXCLUDE
class UpdatePasswordSchema(BaseSchema):
uuid = fields.UUID(required=True)
password = fields.String(required=True, validate=validate.Length(min=6, max=50))
newPassword = fields.String(required=True, validate=validate.Length(min=6, max=50))
class Meta:
unknown = EXCLUDE
class ApplicationBuildSchema(BaseSchema):
access_key = fields.UUID(required=True)
app_name = fields.String(required=True)
app_version = fields.String(required=True)
category = fields.String(required=True)
app_desc = fields.String(required=False)
class Meta:
unknown = INCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
name = fields.String(required=False, validate=validate.Length(min=2, max=20))
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
name = fields.String(required=True, validate=validate.Length(min=2, max=50))
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
class GetRoleUser(BaseSchema):
roles = fields.List(fields.String, required=True)
class Meta:
unknown = EXCLUDE
class ConvertString(BaseSchema):
string = fields.String(required=True)
class Meta:
unknown = EXCLUDE
class ExportProject(BaseSchema):
project = fields.List(fields.String, required=True)
production = fields.List(fields.String, required=True)
condition = fields.Dict(required=False)
class Meta:
unknown = EXCLUDE
\ No newline at end of file
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
app_name = fields.String(required=True)
app_version = fields.String(required=False)
app_desc = fields.String(required=False)
category = fields.String(required=False)
logo = fields.Raw(required=False)
fileList = fields.List(fields.Raw, required=False)
sort = fields.Int(required=False, default=0)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
app_name = fields.String(required=False)
app_version = fields.String(required=False)
app_desc = fields.String(required=False)
category = fields.String(required=False)
sort = fields.Int(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
app_name = fields.String(required=False)
category = fields.String(required=False)
scope_type = fields.String(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
name = fields.String(required=True)
imei = fields.String(required=True)
desc = fields.String(required=False)
type = fields.String(required=False)
sort = fields.Integer(required=False, default=0, allow_none=True)
remarks = fields.String(required=False, default="", allow_none=True)
is_system = fields.Boolean(required=False, default=False, allow_none=True)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
name = fields.String(required=False)
imei = fields.String(required=False)
desc = fields.String(required=False)
type = fields.String(required=False)
sort = fields.Integer(required=False)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
type = fields.Integer(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=False)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
label = fields.String(required=True, validate=validate.Length(min=1, max=50))
value = fields.String(required=True, validate=validate.Length(min=1, max=50))
category = fields.String(required=True, validate=validate.Length(min=1, max=50))
sort = fields.Integer(required=False, default=0, allow_none=True)
remarks = fields.String(required=False, default=" ", allow_none=True)
is_system = fields.Boolean(required=False, default=False, allow_none=True)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
label = fields.String(required=False, validate=validate.Length(min=1, max=50))
value = fields.String(required=False, validate=validate.Length(min=1, max=50))
category = fields.String(required=False, validate=validate.Length(min=1, max=50))
sort = fields.Integer(required=False)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
is_category = fields.Integer(required=False)
label = fields.String(required=False, validate=validate.Length(min=1, max=20))
value = fields.String(required=False, validate=validate.Length(min=1, max=20))
category = fields.List(fields.String(validate=validate.Length(min=1, max=50)), required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=False)
enabld_delete = fields.Boolean(required=True,)
label = fields.String(required=False, validate=validate.Length(min=1, max=50))
value = fields.String(required=False, validate=validate.Length(min=1, max=50))
category = fields.String(required=False, validate=validate.Length(min=1, max=50))
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
app = fields.String(required=True)
imei = fields.String(required=True)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
app = fields.String(required=False)
imei = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class DownloadSchema(BaseSchema):
id = fields.String(required=True)
imei = fields.String(required=True)
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=False)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class LoginSchema(BaseSchema):
account = fields.String(required=True)
password = fields.String(required=True)
class Meta:
unknown = EXCLUDE
class RegisterSchema(BaseSchema):
account = fields.String(required=True)
username = fields.String(required=True)
password = fields.String(required=True)
class Meta:
unknown = EXCLUDE
\ No newline at end of file
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
name = fields.String(required=False)
parent_dir = fields.String(required=False)
file_type = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
name = fields.String(required=True)
parent_dir = fields.String(required=False)
file_type = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
uuids = fields.List(fields.UUID, required=True)
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
name = fields.String(required=False)
parent_dir = fields.String(required=False)
file_type = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
name = fields.String(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
title = fields.String(required=True, validate=validate.Length(min=2, max=50))
funds = fields.Float(required=True)
type = fields.Int(required=True)
status = fields.Int(required=True, default=1)
project = fields.UUID(required=False)
plan_time = fields.DateTime(required=False)
real_time = fields.DateTime(required=True)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
title = fields.String(required=False, validate=validate.Length(min=2, max=50))
funds = fields.Float(required=False)
type = fields.Int(required=False)
status = fields.Int(required=False) # 回款状态
plan_time = fields.DateTime(required=False)
real_time = fields.DateTime(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
title = fields.String(required=False, validate=validate.Length(min=2, max=20))
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=False)
funds = fields.Float(required=True)
type = fields.Int(required=False)
project = fields.Int(required=False)
title = fields.String(required=True, validate=validate.Length(min=2, max=50))
plan_time = fields.DateTime(required=True)
real_time = fields.DateTime(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class QuerySchema(BaseSchema):
project = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class QueryPaybackSchema(BaseSchema):
project = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class DeleteProjectUserSchema(BaseSchema):
uuid = fields.UUID(required=True)
project = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class ModifyProjectUserSchema(BaseSchema):
users = fields.List(fields.UUID, required=True)
project = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class UpdateFlowSchema(BaseSchema):
flow = fields.List(fields.Dict(required=True), required=True)
uuid = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class UpdatePaybackSchema(BaseSchema):
payback = fields.List(fields.Dict(required=True), required=True)
uuid = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class UpdateProductionSchema(BaseSchema):
production = fields.Dict(required=True)
uuid = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
\ No newline at end of file
from . import BaseSchema
class TokenSchema(BaseSchema):
pass
\ No newline at end of file
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
'''
默认情况下,如果在架构中遇到不匹配的键,load将引发a 。ValidationErrorField
可以使用unknown选项修改此行为,该选项接受以下之一:
RAISE(默认):ValidationError 如果存在未知字段,则引发
EXCLUDE:排除未知字段
INCLUDE:接受并包含未知字段
您可以unknown在类的Meta中指定Schema
'''
class AddSchema(BaseSchema):
account = fields.String(required=True)
username = fields.String(required=False)
password = fields.String(required=True)
email = fields.Email(required=False, default="")
phone = fields.String(required=False, default="")
gender = fields.Int(required=False, default=1)
birthday = fields.Date(required=False, default=None)
role = fields.String(required=False)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
uuid = fields.UUID(required=False)
account = fields.String(required=False)
username = fields.String(required=False)
email = fields.Email(required=False)
phone = fields.String(required=False)
gender = fields.Int(required=False)
birthday = fields.Date(required=False)
role = fields.String(required=False)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
account = fields.String(required=True)
username = fields.String(required=True)
password = fields.String(required=True)
email = fields.Email(required=False)
phone = fields.String(required=True)
gender = fields.Int(required=True)
birthday = fields.Date(required=False)
remarks = fields.String(required=True)
class Meta:
unknown = INCLUDE
\ No newline at end of file
# -*- coding: utf-8 -*-
from cx_Freeze import setup, Executable
executables = [
Executable("./start.py")
]
setup(
name="kxpms",
version="1.0",
description="a project manager system",
executables=executables
)
\ No newline at end of file
'''
Author: your name
Date: 2021-04-14 14:12:18
LastEditTime: 2021-07-14 21:37:53
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\backend\start.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import sys
import os
import signal
# import tornado.autoreload
from tornado.wsgi import WSGIContainer
from tornado.web import Application, RequestHandler, FallbackHandler
from tornado.ioloop import IOLoop
from tornado.autoreload import watch
from view import app
from view.monitor import DeviceMessageHandler, NotifyHandler, WatchHandler
from app import config
class GracefulExit(SystemExit):
code = 1
class VueHandler(RequestHandler):
def get(self):
self.write(json.dumps({ 'code': 200, 'msg': 'success', 'data': self.request.remote_ip }))
def raise_graceful_exit(*args):
IOLoop.current().stop()
print("Gracefully shutdown", args)
raise GracefulExit()
def start():
settings = {
'debug': config['DEBUG'],
# 'template_path': config['TEMPLATE_PATH'],
# 'static_path': config['STATIC_PATH'],
'static_url_path': '',
}
watch(os.sep.join([os.getcwd(), "restart.json"]))
wsgi_app = WSGIContainer(app)
application = Application([
(r'/', VueHandler),
(r"/api/v1/evm_store/monitor", DeviceMessageHandler),
(r"/api/v1/evm_store/watch", WatchHandler),
(r"/ws/v1/notify", NotifyHandler),
(r'.*', FallbackHandler, dict(fallback=wsgi_app))
], **settings)
if len(sys.argv) == 2:
port = int(sys.argv[1])
application.listen(port, address=config['HOST'], xheaders=True)
else:
port = config['PORT']
application.listen(port, address=config['HOST'], xheaders=True)
print(config['LOGO'])
print("server running at %s:%d" % (config['HOST'], port))
# 主进程退出信号
signal.signal(signal.SIGINT, raise_graceful_exit)
signal.signal(signal.SIGTERM, raise_graceful_exit)
# instance = tornado.ioloop.IOLoop.instance()
# tornado.autoreload.start(instance)
# instance.start()
IOLoop.instance().start()
if __name__ == '__main__':
start()
\ No newline at end of file
#!/usr/bin/env bash
Cur_Dir=$(pwd)
source venv/bin/activate
nohup ${Cur_Dir}/venv/bin/python3 ${Cur_Dir}/start.py > runoob.log 2>&1 &
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['start.py'],
pathex=['F:\\Wanli\\projects\\kxpms\\backend'],
binaries=[],
datas=[],
hiddenimports=['pony', 'pony.orm.dbproviders', 'pony.orm.dbproviders.sqlite'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='start',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True )
import os
import requests
if __name__ == "__main__":
url = "http://store.evmiot.com/api/v1/evm_store/application/build"
datas = {
"access_key": "69b80cc6-4ea0-11eb-904e-a85e459dc84f",
"app_name": "test",
"app_version": "v1.0",
"category": "test",
}
# upload_files = [
# ("field1" , ("filename1", open("filePath1", "rb"))),
# ("field1" , ("filename2", open("filePath2", "rb"), "image/png")),
# ("field1" , open("filePath3", "rb")),
# ("field1" , open("filePath4", "rb").read())
# ]
upload_files = []
for root, dirs, files in os.walk("./watch_launcher"):
for f in files:
upload_files.append(("binfiles", (f, open(os.sep.join([root, f]), "rb"))))
# print(upload_files)
res = requests.post(url, datas, files = upload_files)
result = res.json()
print(result)
if result['code'] == 200:
down_res = requests.get(url=result['data']['app_url'])
with open(result['data']['app_file'], "wb") as fd:
fd.write(down_res.content)
\ No newline at end of file
{"appName": "Launcher", "appVersion": "1.0", "files": [{"path": "C:/Launcher.json", "name": "Launcher.json", "size": 723, "basename": "Launcher", "ext": "json"}, {"path": "C:/app.js", "name": "app.js", "size": 126, "basename": "app", "ext": "js"}, {"path": "C:/evue_launcher.evue", "name": "evue_launcher.evue", "size": 2371, "basename": "evue_launcher", "ext": "evue"}, {"path": "C:/evue_launcher.md5", "name": "evue_launcher.md5", "size": 16, "basename": "evue_launcher", "ext": "md5"}, {"path": "C:/evue_logo.bin", "name": "evue_logo.bin", "size": 67504, "basename": "evue_logo", "ext": "bin"}, {"path": "C:/watch_launcher.json", "name": "watch_launcher.json", "size": 622, "basename": "watch_launcher", "ext": "json"}]}
\ No newline at end of file
function onCreate() {
print("Application onCreate");
}
function onDestroy() {
print("Application onDestroy");
}
\ No newline at end of file
<html>
<div class="container">
<image src="evue_logo.bin" style="top: 20px;left: 40px;"></image>
<text style="top:190px;background-color: transparent; color: white;font-size: 20px;width: 240px;height: 25px;text-align: center;">{{ title }}</text>
</div>
</html>
<script>
router = require("@system.router")
http = require("@system.http")
fs = require("@system.fs")
watch = require("@system.watch")
os = require("@system.os")
export default {
data: {
title: 'Power by EVM!',
epk_remote_url: 'http://store.evmiot.com/api/v1/evm_store/download/apps',
path_prefix: '',
epk_name: 'evue_launcher.epk',
fpath: '',
url_dock: 'evue_dock',
url_404: 'evue_404',
appId: "evue_launcher"
},
onInit: function() {},
onReady: function() {
this.fpath = this.epk_name;
},
onShow: function() {
setTimeout(function() {
this.install();
}, 10)
},
install: function() {
this.installLauncherEpk(this.appId, this.epk_remote_url)
router.push({
path: this.url_dock
})
},
onHide: function() {},
onDestroy: function() {},
installLauncherEpk: function(appId, epk_remote_url) {
headers = [
"Accept: application/json",
"Content-Type: application/json",
"charsets: utf-8"
]
var res = http.request({
method: "POST",
url: epk_remote_url,
headers: headers,
data: JSON.stringify({
"id": appId,
"imei": watch.imei()
}),
timeout: 10000,
responseType: "epk",
callback: function(res, len) {},
error: function(code) {}
});
}
}
</script>
<style>
.container {
width: 240px;
height: 240px;
border-width: 0px;
border-radius: 0px;
margin: 0px;
padding: 0px;
opacity: 0;
background-color: transparent;
align-items: off;
}
</style>
\ No newline at end of file
q
TMC
\ No newline at end of file
{"appName": "watch_launcher", "appVersion": "1.0", "files": [{"path": "C:/watch_launcher.json", "name": "watch_launcher.json", "size": 622, "basename": "watch_launcher", "ext": "json"}, {"path": "C:/app.js", "name": "app.js", "size": 126, "basename": "app", "ext": "js"}, {"path": "C:/evue_launcher.evue", "name": "evue_launcher.evue", "size": 2371, "basename": "evue_launcher", "ext": "evue"}, {"path": "C:/evue_launcher.md5", "name": "evue_launcher.md5", "size": 16, "basename": "evue_launcher", "ext": "md5"}, {"path": "C:/evue_logo.bin", "name": "evue_logo.bin", "size": 67504, "basename": "evue_logo", "ext": "bin"}]}
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import shutil
import time
import re
import os
import json
import functools
import hashlib
import random
import string
import datetime
import threading
import decimal
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return float(o)
super(DecimalEncoder, self).default(o)
class ObjectDict(dict):
"""Makes a dictionary behave like an object, with attribute-style access.
"""
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError(name)
def __setattr__(self, name, value):
self[name] = value
def ThreadMaker(f):
def runner(*args, **argv):
t = threading.Thread(target=f, args=args, kwargs=argv)
t.start()
return t
return runner
def copytree(src, dst, symlinks=False, ignore=None):
names = os.listdir(src)
if ignore is not None:
ignored_names = ignore
else:
ignored_names = set()
if not os.path.exists(dst):
os.makedirs(dst)
errors = []
for name in names:
if name in ignored_names:
continue
if re.match(r'.*?.pyc$', name):
continue
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if symlinks and os.path.islink(srcname):
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
copytree(srcname, dstname, symlinks, ignore)
else:
shutil.copy2(srcname, dstname)
# XXX What about devices, sockets etc.?
except (IOError, os.error) as why:
errors.append((srcname, dstname, str(why)))
# catch the Error from the recursive copytree so that we can
# continue with other files
except Exception as e:
errors.extend(e.args[0])
try:
shutil.copystat(src, dst)
except WindowsError:
# can't copy file access times on Windows
pass
except OSError as why:
errors.extend((src, dst, str(why)))
if errors:
raise Exception(errors)
def timing(f):
@functools.wraps(f)
def inner(*args, **kwargs):
startTime = time.time()
f(*args, **kwargs)
print("[function]: %s [finished in]: %fs" %
(f.__name__, time.time()-startTime))
return inner
def timeToSeconds(t, sep=":"):
if t == "":
t = "0:0:0"
ts = [int(i) for i in t.split(sep)]
return ts[0] * 60 * 60 + ts[1] * 60 + ts[2]
def secondsToTime(seconds, sep=":"):
h = seconds / 3600
m = seconds % 3600 / 60
s = (seconds - h * 3600 - m * 60) % 60
return sep.join([str(i) for i in [h, m, s]])
def md5_salt(s):
md5 = hashlib.md5("EhuqUkwV".encode("utf-8"))
md5.update(s.encode('utf-8'))
return md5.hexdigest()
def filter_dict(source: dict, rules_list: list):
# 如果source中的词典数量过多,请使用itertools模块的ifilter。 它会返回一个迭代器,而不是立即用整个列表填充系统的内存
result = dict()
# res = [d for d in source.keys() if d in rules_list]
# res = list(filter(lambda d: d in rules_list, source.keys()))
for k in source.keys():
if k in rules_list:
result.update(k, source[k])
return result
def sql_filter(sql):
return re.sub(r"[\"\\/*\'=\-#;<>+%$()!@]", "", sql)
def random_string(length=32):
return ''.join(random.sample(string.ascii_letters + string.digits, length))
def get_days_before_datetime(dt, dayAgo):
if not isinstance(dt, datetime.datetime):
dt = datetime.datetime.strptime(dt, "%Y-%m-%d %H:%M:%S")
# 先获得时间数组格式的日期
dayAgo = (dt - datetime.timedelta(days = dayAgo))
# 转换为其他字符串格式
return dayAgo.strftime("%Y-%m-%d %H:%M:%S")
if __name__ == "__main__":
print(os.path.abspath(__file__))
print(random_string(7))
\ No newline at end of file
'''
Author: your name
Date: 2021-04-29 12:12:01
LastEditTime: 2021-07-14 21:26:39
LastEditors: your name
Description: In User Settings Edit
FilePath: \evm-store\backend\utils\ccode.py
'''
# -*- coding: utf-8 -*-
import sys
header = \
u'''
/****************************************************************************
**
** Copyright (C) 2021 @scriptiot
**
** EVM是一款通用化设计的虚拟机引擎,拥有语法解析前端接口、编译器、虚拟机和虚拟机扩展接口框架。
** 支持js、python、qml、lua等多种脚本语言,纯C开发,零依赖,支持主流 ROM > 50KB, RAM > 2KB的MCU;
** 自带垃圾回收(GC)先进的内存管理,采用最复杂的压缩算法,无内存碎片(大部分解释器都存在内存碎片)
** Version : 3.0
** Email : scriptiot@aliyun.com
** Website : https://github.com/scriptiot
** Licence: MIT Licence
****************************************************************************/
'''
def cstr_encode(text, splitLines=True, escapePercent=False):
output = "\""
count = len(text)
for i in range(count):
if text[i] == '\f':
output += "\\f"
elif text[i] == '\n':
if splitLines:
output += "\\n\"\n\""
else:
output += "\\n";
elif text[i] == '\r':
output += "\\r"
elif text[i] == '\t':
output += "\\t"
elif text[i] == '\"':
output += "\\\""
elif text[i] == '\\':
output += "\\\\"
elif text[i] == '%':
if escapePercent:
output += "%%"
else:
output += "%"
else:
output += text[i]
output += "\""
return output
def convert(fpath):
with open(fpath, "r") as f:
content = f.read()
ret = cstr_encode(content)
ccode = "%s\nconst char * appjs_content=\\\n%s;" % (header, ret)
with open("appjs.c", "w", encoding="utf-8") as f:
f.write(ccode)
return ccode
def convert_string(string):
return "%s\nconst char * appjs_content=\\\n%s;" % (header, cstr_encode(string))
if __name__ == '__main__':
ret = convert(sys.argv[1])
print(ret)
#-*- coding: UTF-8 -*-
#!/usr/bin/python
import os
import sys
import fs
import struct
import json
from collections import OrderedDict
import zlib
import pprint
import hashlib
from ctypes import *
import platform
lib_path = os.path.dirname(os.path.abspath(__file__))
if platform.system() == 'Windows':
pDll = CDLL(os.sep.join([lib_path, "lib", "eheatshrink.dll"]))
elif platform.system() == 'Linux':
pDll = CDLL(os.sep.join([lib_path, "lib", "libeheatshrink.so"]))
pDll.ecompress_size.restype = c_uint32
pDll.ecompress_size.argtypes = [c_void_p, c_uint32]
pDll.ecompress.restype = POINTER(c_uint8)
pDll.ecompress.argtypes = [c_void_p, c_uint32]
def heatshrink_compress(buf:bytes, level:int):
count = len(buf)
size = pDll.ecompress_size(buf, count)
pDll.ecompress.restype = POINTER(c_uint8)
pDll.ecompress.argtypes = [c_void_p, c_uint32]
ret = pDll.ecompress(buf, count)
arr = bytearray(size)
i = 0
while i < size:
arr[i] = ret[i]
i = i+1
return arr
def str_to_hex(s):
return ' '.join([hex(ord(c)).replace('0x', '') for c in s])
def hex_to_str(s):
return ''.join([chr(i) for i in [int(b, 16) for b in s.split(' ')]])
def str_to_bin(s):
return ' '.join([bin(ord(c)).replace('0b', '') for c in s])
def bin_to_str(s):
return ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]])
def eprint(*args, **kwargs):
# print(*args, **kwargs)
pass
class EpkApp(object):
def __init__(self, appName, appDir, algorithm='zlib',appVersion="1.0", output="epks"):
super(EpkApp, self).__init__()
self._appName = appName
self._appDir = os.path.abspath(appDir)
self.algorithm = algorithm
eprint(sys.argv)
eprint(appName)
eprint(appDir)
eprint(self._appDir)
self._appVersion = appVersion
self._appCRCCode = None
self._files = []
self._infoPath = os.sep.join([self._appDir, "%s.json" % self._appName])
self._epksDir = output
if not os.path.exists(self._epksDir):
fs.open_fs(os.getcwd()).makedirs(output)
self._epkName = os.sep.join([self._epksDir, "%s.epk" % self._appName])
def compress(self):
if self.algorithm == 'h':
return heatshrink_compress
return zlib.compress
def epkInfo(self):
epkInfo = OrderedDict({
"appName": self._appName,
"appVersion": self._appVersion,
"files": self.fileinfos(self._appDir),
})
infocontent = json.dumps(epkInfo)
with open(self._infoPath, "w", encoding='utf-8') as f:
f.write(infocontent)
return epkInfo
def fileinfos(self, path):
path = os.path.abspath(path)
home_fs = fs.open_fs(path)
files = []
for jspath in home_fs.glob('*', namespaces=['details']):
fpath = "C:/%s" % jspath.info.name
fname = jspath.info.name
fsize = jspath.info.size
fbasename, fext = os.path.splitext(jspath.info.name)
if fext in ["", ".exe", ".dll", ".nv", ".conf"]:
continue
finfo = {
"path": fpath,
"name": fname,
"size": fsize,
"basename": fbasename,
"ext": fext
}
if self._infoPath == os.sep.join([path, fname]):
eprint(finfo)
files.insert(0, finfo)
else:
files.append(finfo)
if fext == ".evue":
self.fileMD5(finfo)
return files
def header(self, epk_start=0xAA, md5_offset=0, file_count=0):
if self.algorithm == 'zlib':
bytes_header = struct.pack("<BBLH", epk_start, 1 ,md5_offset, file_count)
else:
bytes_header = struct.pack("<BBLH", epk_start, 2 ,md5_offset, file_count)
return bytes_header
def fileMD5(self, info):
md5path = os.sep.join([self._appDir, "%s.md5" % info["basename"]])
fpath = os.sep.join([self._appDir, info["name"]])
with open(fpath, "rb") as f:
filecontent = f.read()
newmd5 = self.md5(filecontent)
with open(md5path, "wb") as f:
f.write(newmd5)
return newmd5
def sign(self, content):
ret = b""
for i in range(int(len(content) / 2 )):
ret += struct.pack("<B", int("0x%s" % (content[i*2:i*2+2]), 16))
ret = ret + b'EVM is NB ++!'
return ret
def md5(self, filecontent):
newmd5 = ''
content = filecontent
for i in range(3):
md5 = hashlib.md5() #获取一个md5加密算法对象
md5.update(content) #指定需要加密的字符串
newmd5 = md5.hexdigest() #获取加密后的16进制字符串
eprint("md5 == ",newmd5)
content = self.sign(newmd5)
ret = b""
for i in range(int(len(newmd5) / 2 )):
ret += struct.pack("<B", int("0x%s" % (newmd5[i*2:i*2+2]), 16))
return ret
def packFile(self, info, level=9):
fname = info["name"]
fpath = os.sep.join([self._appDir, fname])
fext = info["ext"]
fileBytes = b""
if fext == "md5":
fileBytes += struct.pack("<B", 1)
else:
fileBytes += struct.pack("<B", 2)
_name = fname + "\0"
fileBytes += struct.pack("<B", len(_name))
fileBytes += struct.pack("<%ds" % len(_name), fname.encode("utf-8"))
with open(fpath, "rb") as fc:
fileContentBytes = fc.read()
eprint(info["name"])
eprint(len(fileContentBytes))
fileBytes += struct.pack("<L", len(fileContentBytes))
if fext == "md5":
fileCompressBytes = fileContentBytes
else:
fileCompressBytes = self.compress()(fileContentBytes, level)
eprint("===",fileCompressBytes[0])
eprint(fileCompressBytes)
fileBytes += struct.pack("<L", len(fileCompressBytes))
eprint(fileBytes)
fileBytes += fileCompressBytes
return fileBytes
def pack(self, level=9):
for i in range(10):
infos = self.epkInfo()
# infos = self.epkInfo()
# infos = self.epkInfo()
epkFileBytes = b""
ret = None
epkFileContentBytes = b""
file_count = len(infos["files"])
with open(self._epkName, "wb") as f:
for info in infos["files"]:
epkFileContentBytes += self.packFile(info)
epkFileContentLength = len(epkFileContentBytes)
epkFileBytes += self.header(md5_offset= 8 + epkFileContentLength, file_count=file_count)
epkFileBytes += epkFileContentBytes
epkmd5Bytes = self.md5(epkFileBytes)
epkFileBytes += struct.pack("<H", len(epkmd5Bytes))
epkFileBytes += epkmd5Bytes
crcBytes = zlib.crc32(epkFileBytes)
epkFileBytes += struct.pack("<L", crcBytes)
f.write(epkFileBytes)
ret = {
"epkfile": self._epkName,
"epk_filecontent_size": epkFileContentLength,
"md5_offset": 10 + epkFileContentLength,
"file_count": file_count,
"md5_length": len(epkmd5Bytes),
"md5": epkmd5Bytes,
"raw_crc": hex(crcBytes),
"compress_level": level,
"buff_length": len(epkFileBytes)
}
pprint.pprint(ret)
return ret
def main(path, appName, algorithm):
epk = EpkApp(appName, path, algorithm)
epk.pack()
if __name__ == '__main__':
main(sys.argv[1], sys.argv[2], sys.argv[3])
This diff is collapsed.
This diff is collapsed.
'''
Author: your name
Date: 2021-04-14 14:12:18
LastEditTime: 2021-07-03 11:43:10
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\backend\view\__init__.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import logging
import traceback
from flask import Flask, Response, jsonify
from flask_cors import CORS
from werkzeug.exceptions import HTTPException, InternalServerError
from .api import api
from .files import file_api
from .login import login_api
from .user import user_api
from .apps import apps_api
from .device import device_api
from .download import download_api
from .app_logs import appLogs_api
from model import fullStackDB
from fullstack.response import ResponseCode, response_result
from app import config
logger = logging.getLogger(__name__)
class JsonResponse(Response):
@classmethod
def force_type(cls, response, environ=None):
if isinstance(response, (list, dict)):
response = jsonify(response)
return super(cls, Response).force_type(response, environ)
class FlaskAPP(Flask):
response_class = JsonResponse
def unauthorized(self, message):
return response_result(ResponseCode.AUTHORIZATION_ERROR, msg=message)
def create_app():
app = FlaskAPP(__name__)
app.register_blueprint(api)
app.register_blueprint(login_api)
app.register_blueprint(file_api)
app.register_blueprint(user_api)
app.register_blueprint(apps_api)
app.register_blueprint(download_api)
app.register_blueprint(device_api)
app.register_blueprint(appLogs_api)
@app.errorhandler(InternalServerError)
def handle_500(e):
logger.error(str(e))
traceback.print_exc()
return response_result(ResponseCode.SERVER_ERROR, msg=str(e))
@app.errorhandler(HTTPException)
def handle_http_exception(e):
logger.error(str(e))
traceback.print_exc()
return response_result(ResponseCode.SERVER_ERROR, msg=str(e))
@app.errorhandler(Exception)
def handle_exception(e):
logger.error(str(e))
traceback.print_exc()
return response_result(ResponseCode.SERVER_ERROR, msg=str(e))
CORS(app, supports_credentials=True, origins='*')
app.config.update(config)
fullStackDB(app, drop_tables=[])
return app
app = create_app()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# vuedemo
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This image diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment