Compare commits

...

12 Commits
main ... dev

@ -21,7 +21,8 @@
├── ... ├── ...
``` ```
## Dockerfile ## 配置信息
### Dockerfile
```bash ```bash
# generalai:v1是镜像名192.168.10.94:5000是镜像仓库docker registry本地地址 # generalai:v1是镜像名192.168.10.94:5000是镜像仓库docker registry本地地址
@ -87,7 +88,7 @@ docker build -t lemon:latest .
docker images 查看生成的镜像 lemon:latest docker images 查看生成的镜像 lemon:latest
``` ```
## docker-compose.yml ### docker-compose.yml
```shell ```shell
version: "3.3" version: "3.3"
@ -108,6 +109,8 @@ services:
# - /data/app/lemon:/app/lemon # 如果由相同的设置则会覆盖Dockfile中COPY的文件 # - /data/app/lemon:/app/lemon # 如果由相同的设置则会覆盖Dockfile中COPY的文件
- /data/app/log:/app/log - /data/app/log:/app/log
- /data/app/fileupload:/app/fileupload - /data/app/fileupload:/app/fileupload
- /usr/sbin/dmidecode:/usr/sbin/dmidecode # dmidecode命令需要root权限否则会报错
- /dev/mem:/dev/mem # /dev/mem需要root权限否则会报错
environment: environment:
- TZ=Asia/Shanghai - TZ=Asia/Shanghai
networks: # 配置网络 networks: # 配置网络
@ -167,7 +170,7 @@ networks:
driver: bridge # 如果不设置则默认使用bridge driver: bridge # 如果不设置则默认使用bridge
``` ```
## entrypoint.sh ### entrypoint.sh
```bash ```bash
#!/bin/bash #!/bin/bash
@ -236,14 +239,14 @@ function print_dir_structure() {
echo "启动完成" echo "启动完成"
``` ```
## mysql初始化 ### mysql初始化
``` ```
mysql_app.sql, 数据库的结构,以及默认账号的初始化 mysql_app.sql, 数据库的结构,以及默认账号的初始化
mysql_auth.sql 修改密码加密规格,修改密码 mysql_auth.sql 修改密码加密规格,修改密码
``` ```
## nginx ### nginx
``` ```
server { server {
@ -266,7 +269,7 @@ server {
} }
``` ```
## supervisor ### supervisor
``` ```
[program:lemon] [program:lemon]
@ -286,10 +289,43 @@ command 可以使用动态参数,例如:--port=88%(process_num)02d默认
多进程则修改numproc的值如numproc=2则第一个进程使用8800端口第二个进程使用8801端口。 多进程则修改numproc的值如numproc=2则第一个进程使用8800端口第二个进程使用8801端口。
``` ```
## 启动 ## 启动项目
### 本地编译启动
``` ```
1. 修改配置文件 1. 修改配置文件
2. 编译docker build -t lemon . 2. 编译docker build -t lemon .
3. docker-compose up -d 3. docker-compose up -d
```
### 镜像打包
```
Dockerfile中首行配置 FROM 192.168.10.94:5000/generalai:v1使用的是开发环境的docker registry镜像
这个image中包含工程运行需要的基础环境包括各种包supervisor
镜像制作:
docker build -t lemon .
镜像导出:
export:
docker export lemon_web lemon.tar # lemon_web是docker-compose.yml中的container name, 或者使用container id
或者save:
docker save -o lemon.tar lemon:latest # 导出为tar文件方便传输
```
### 导入docker镜像包
```
import: docker import lemon.tar lemon:latest
或者load: docker load < lemon.tar
docker-compose up -d
```
### 查看日志
```
docker logs -f lemon_web
``` ```

@ -16,8 +16,19 @@ services:
# - /data/app/lemon:/app/lemon # - /data/app/lemon:/app/lemon
- /data/app/log:/app/log - /data/app/log:/app/log
- /data/app/fileupload:/app/fileupload - /data/app/fileupload:/app/fileupload
- ./private_key.pem:/app/lemon/private_key.pem
- /usr/sbin/dmidecode:/usr/sbin/dmidecode
- /dev/mem:/dev/mem
environment: environment:
- TZ=Asia/Shanghai - TZ=Asia/Shanghai
- MYSQL_DATABASE=aiplatform
- MYSQL_USER=root
- MYSQL_PASSWORD=SghjdA887#
- MYSQL_HOST=lemon_mysql
- MYSQL_PORT=3306
- REDIS_HOST=lemon_redis
- REDIS_PORT=6379
- REDIS_PASSWORD=hgkiYY87
networks: networks:
- lemon_network - lemon_network
depends_on: depends_on:
@ -29,8 +40,11 @@ services:
image: nginx:latest image: nginx:latest
container_name: lemon_nginx container_name: lemon_nginx
ports: ports:
- "80:80" # - "80:80"
- "443:443" # - "443:443"
- "8989:8989"
environment:
TZ: Asia/Shanghai
volumes: volumes:
- ./nginx.conf:/etc/nginx/conf.d/lemon.conf - ./nginx.conf:/etc/nginx/conf.d/lemon.conf
- ./dist:/app/lemon/dist - ./dist:/app/lemon/dist
@ -47,6 +61,7 @@ services:
environment: environment:
MYSQL_ROOT_PASSWORD: SghjdA887# MYSQL_ROOT_PASSWORD: SghjdA887#
MYSQL_DATABASE: aiplatform MYSQL_DATABASE: aiplatform
TZ: Asia/Shanghai
volumes: volumes:
- /data/mysql_data:/var/lib/mysql - /data/mysql_data:/var/lib/mysql
- ./mysql_auth.sql:/docker-entrypoint-initdb.d/auth.sql - ./mysql_auth.sql:/docker-entrypoint-initdb.d/auth.sql

@ -22,15 +22,26 @@
if [ ! -f "/app/lemon/website/settings_local.py" ];then if [ ! -f "/app/lemon/website/settings_local.py" ];then
echo "@@init settings_local file" echo "@@init settings_local file"
cat > /app/lemon/website/settings_local.py << EOF cat > /app/lemon/website/settings_local.py << EOF
import os
mysql_app = { mysql_app = {
"host": "lemon_mysql:3306", "host": "{}:{}".format(os.environ.get("MYSQL_HOST"), os.environ.get("MYSQL_PORT")),
"database": "aiplatform", "database": os.environ.get("MYSQL_DATABASE"),
"user": "root", "user": os.environ.get("MYSQL_USER"),
"password": "SghjdA887#", "password": os.environ.get("MYSQL_PASSWORD"),
"time_zone": "+8:00" "time_zone": "+8:00"
} }
redis_app = ("lemon_redis", 6379, 0, "hgkiYY87")
redis_app = (
os.environ.get("REDIS_HOST"),
os.environ.get("REDIS_PORT"),
0,
os.environ.get("REDIS_PASSWORD"),
)
file_upload_dir = "/app/fileupload" file_upload_dir = "/app/fileupload"
rsa_private_file = "/app/lemon/private_key.pem"
rsa_license_file = "/app/lemon/license"
EOF EOF
fi fi

@ -48,7 +48,7 @@ CREATE TABLE `enterprise` (
`industry` int NOT NULL, `industry` int NOT NULL,
`contact` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, `contact` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`phone` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, `phone` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`summary` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, `summary` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL,
`logo` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL, `logo` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL,
`account` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, `account` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`pwd` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, `pwd` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,

@ -1,7 +1,8 @@
server { server {
listen 80; listen 8989;
server_name 192.168.10.94; server_name 192.168.10.94;
client_max_body_size 300M;
root /app/lemon/dist; root /app/lemon/dist;
location ^~ /api { location ^~ /api {

@ -0,0 +1,10 @@
aiofiles==24.1.0
M2Crypto==0.41.0
pandas==2.2.2
Pillow==10.4.0
pycryptodome==3.20.0
redis==5.0.7
requests==2.27.1
SQLAlchemy==2.0.31
tornado==6.4.1
xlwt==1.3.0

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""静态配置""" """静态配置"""
PAGE_NO = 1
PAGE_SIZE = 10 PAGE_SIZE = 10
# 行业分类 # 行业分类
@ -40,4 +41,36 @@ device_status_map = {
1002: u"离线", 1002: u"离线",
1003: u"运行中", 1003: u"运行中",
1004: u"故障", 1004: u"故障",
} }
# 系统状态
system_status_not_active = 9000 # 未激活
system_status_activated = 9001 # 已激活
system_status_expire_atall = 9003 # 完全过期
op_type_add = 1001 # 新增
op_type_add_str = u"新增"
op_type_edit = 1002 # 编辑
op_type_edit_str = u"编辑"
op_type_list = 1003 # 查询
op_type_list_str = u"查询"
op_type_delete = 1004 # 删除
op_type_delete_str = u"删除"
op_type_upload = 1005 # 上传
op_type_upload_str = u"上传"
op_type_login_logout = 1006
op_type_login_logout_str = u"登录/登出"
op_type_map = {
op_type_add: op_type_add_str,
op_type_edit: op_type_edit_str,
op_type_list: op_type_list_str,
op_type_delete: op_type_delete_str,
op_type_upload: op_type_upload_str,
op_type_login_logout: op_type_login_logout_str,
}

@ -97,4 +97,4 @@ class ModelRepositry(object):
def get_model_count(self) -> int: def get_model_count(self) -> int:
with get_session() as session: with get_session() as session:
return session.query(Model).count() return session.query(Model).filter(Model.delete == 0).count()

@ -1,13 +1,13 @@
from website.handler import BaseHandler import json
from sqlalchemy import text
from typing import Any from typing import Any
from sqlalchemy import text
from website.db_mysql import get_session, get_async_session, to_json, to_json_list from website.db_mysql import get_session, get_async_session, to_json, to_json_list
import json
# 获取企业模型数量 # 获取企业模型数量
def get_enterprise_model_count(id: int) -> int: def get_enterprise_model_count(id: int) -> int:
return 0 return 0
@ -19,7 +19,7 @@ def get_enterprise_device_count(id: int) -> int:
# 获取所有企业实体数量 # 获取所有企业实体数量
def get_enterprise_entity_count(engine: Any) -> int: def get_enterprise_entity_count(engine: Any) -> int:
with engine.connect() as conn: with engine.connect() as conn:
count_sql_text = "select count(*) from enterprise " count_sql_text = "select count(*) from enterprise where del=0 "
count = conn.execute(text(count_sql_text)).fetchone() count = conn.execute(text(count_sql_text)).fetchone()
if count: if count:
return count[0] return count[0]
@ -68,7 +68,7 @@ def get_enterprise_device_count(entity_id: int = 0, entity_suid: str = "") -> in
async def get_enterprise_model_and_device_count( async def get_enterprise_model_and_device_count(
entity_id: int = 0, entity_suid: str = "" entity_id: int = 0, entity_suid: str = ""
) -> (int, int): ) -> (int, int):
model_count = 0 model_count = 0
device_count = 0 device_count = 0
@ -103,8 +103,6 @@ async def get_enterprise_model_and_device_count(
# if res_device: # if res_device:
# device_count = res_device["device_count"] # device_count = res_device["device_count"]
sql_device_count = "SELECT COUNT(*) AS device_count FROM enterprise_device WHERE {where_clause} " sql_device_count = "SELECT COUNT(*) AS device_count FROM enterprise_device WHERE {where_clause} "
sql_base_model = "SELECT base_models FROM enterprise_busi_model WHERE {where_clause} " sql_base_model = "SELECT base_models FROM enterprise_busi_model WHERE {where_clause} "

@ -5,13 +5,13 @@ import logging
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from sqlalchemy import Column, Integer, String, DateTime, func from sqlalchemy import Column, Integer, String, DateTime, func
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import text from sqlalchemy import text
from sqlalchemy.ext.declarative import declarative_base
from website.db.alg_model import alg_model as DB_alg_model from website.db.alg_model import alg_model as DB_alg_model
from website.db.enterprise_entity.enterprise_entity import EnterpriseEntityRepository from website.db.enterprise_entity.enterprise_entity import EnterpriseEntityRepository
from website.db.enterprise_node import enterprise_node as DB_Node from website.db.enterprise_node import enterprise_node as DB_Node
from website.db_mysql import get_session, to_json_list, to_json, Row, dict_to_obj from website.db_mysql import get_session, to_json_list, Row, dict_to_obj
from website.util import shortuuid from website.util import shortuuid
Base = declarative_base() Base = declarative_base()
@ -73,6 +73,7 @@ class EnterpriseBusiModel(Base):
filtered_data = {key: value for key, value in kwargs.items() if key in valid_columns} filtered_data = {key: value for key, value in kwargs.items() if key in valid_columns}
super().__init__(**filtered_data) super().__init__(**filtered_data)
class EnterpriseBusiModelRepository(object): class EnterpriseBusiModelRepository(object):
def get_by_id(self, id: int) -> Optional[EnterpriseBusiModel]: def get_by_id(self, id: int) -> Optional[EnterpriseBusiModel]:
@ -161,7 +162,7 @@ class EnterpriseBusiModelRepository(object):
""" """
with get_session() as session: with get_session() as session:
total_count = session.query(func.count(EnterpriseBusiModel.id)).filter( total_count = session.query(func.count(EnterpriseBusiModel.id)).filter(
EnterpriseBusiModel.entity_id == entity_id).scalar() EnterpriseBusiModel.entity_id == entity_id).filter(EnterpriseBusiModel.delete == 0).scalar()
models = ( models = (
session.query( session.query(
@ -170,6 +171,7 @@ class EnterpriseBusiModelRepository(object):
EnterpriseBusiModel.create_time EnterpriseBusiModel.create_time
) )
.filter(EnterpriseBusiModel.entity_id == entity_id) .filter(EnterpriseBusiModel.entity_id == entity_id)
.filter(EnterpriseBusiModel.delete == 0)
.offset((page_no - 1) * page_size) .offset((page_no - 1) * page_size)
.limit(page_size) .limit(page_size)
.all() .all()
@ -204,6 +206,7 @@ class EnterpriseBusiModelRepository(object):
session.commit() session.commit()
return return
class EnterpriseBusiModelNode(Base): class EnterpriseBusiModelNode(Base):
__tablename__ = 'enterprise_busi_model_node' __tablename__ = 'enterprise_busi_model_node'
@ -277,19 +280,18 @@ class EnterpriseBusiModelNodeRepository(object):
.offset((page_no - 1) * page_size) .offset((page_no - 1) * page_size)
.limit(page_size) .limit(page_size)
.all() .all()
) )
total_count = session.query(func.count(EnterpriseBusiModelNode.id)).filter( total_count = session.query(func.count(EnterpriseBusiModelNode.id)).filter(
EnterpriseBusiModelNode.node_id == node_id).scalar() EnterpriseBusiModelNode.node_id == node_id).scalar()
return { return {
"count": total_count, "count": total_count,
"data": [ "data": [
{ {
"busi_model_id": model.busi_model_id, "busi_model_id": model.busi_model_id,
"busi_model_name": model.busi_model_name, "busi_model_name": model.busi_model_name,
"create_time": model.create_time.strftime("%Y-%m-%d %H:%M:%S"), "create_time": model.create_time.strftime("%Y-%m-%d %H:%M:%S"),
} for model in models } for model in models
] ]
} }

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
from typing import List, Dict, Any, Union from typing import List, Dict, Any, Union
from sqlalchemy import text from sqlalchemy import text
@ -71,15 +71,18 @@ class EnterpriseNodeRepository(object):
n.id, n.name, n.parent, p.name AS parent_name, n.suid n.id, n.name, n.parent, p.name AS parent_name, n.suid
FROM enterprise_node n FROM enterprise_node n
LEFT JOIN enterprise_node p ON n.parent = p.id LEFT JOIN enterprise_node p ON n.parent = p.id
WHERE n.entity_id=:entity_id AND n.del=0 and n.parent=0 WHERE n.entity_id=:entity_id AND n.del=0
""" """
) )
if name == "":
sql += " and n.parent=0"
param = {"entity_id": entity_id} param = {"entity_id": entity_id}
if name: if name:
sql += " and n.name like :name" sql += " and n.name like :name"
param["name"] = f"%{name}%" param["name"] = f"%{name}%"
# logging.info(f"############################# sql: {sql}, param: {param}")
res = session.execute(text(sql), param) res = session.execute(text(sql), param)
node_list = to_json_list(res) node_list = to_json_list(res)
node_list = node_list and node_list or [] node_list = node_list and node_list or []
@ -115,9 +118,9 @@ class EnterpriseNodeRepository(object):
param = {"parent": node["id"]} param = {"parent": node["id"]}
if name: # if name:
sql += " and n.name like :name" # sql += " and n.name like :name"
param["name"] = f"%{name}%" # param["name"] = f"%{name}%"
res = session.execute(text(sql), param) res = session.execute(text(sql), param)
node_list = to_json_list(res) node_list = to_json_list(res)

@ -53,7 +53,7 @@ class FileRepository(object):
for file in files: for file in files:
obj_dict = file.__dict__ obj_dict = file.__dict__
del obj_dict['_sa_instance_state'] del obj_dict['_sa_instance_state']
print(obj_dict) # print(obj_dict)
resp.append(dict_to_obj(obj_dict)) resp.append(dict_to_obj(obj_dict))
# return session.query(File).filter(File.md5_str.in_(md5_list)).all() # return session.query(File).filter(File.md5_str.in_(md5_list)).all()

@ -496,7 +496,7 @@ def authenticated_admin(method):
return wrapper return wrapper
def operation_log(primary_menu, sub_menu, ope_type, content, comment): def operation_log(primary_menu, sub_menu, ope_type, content, comment=""):
""" """
Add logging to a function. level is the logging Add logging to a function. level is the logging
level, name is the logger name, and message is the level, name is the logger name, and message is the
@ -507,22 +507,25 @@ def operation_log(primary_menu, sub_menu, ope_type, content, comment):
def decorate(func): def decorate(func):
@functools.wraps(func) @functools.wraps(func)
def wrapper(self, *args, **kwargs): def wrapper(self, *args, **kwargs):
with self.app_mysql.connect() as conn: try:
conn.execute(text( with self.app_mysql.connect() as conn:
"insert into sys_log(user, ip, primary_menu, sub_menu, op_type, content, comment) " conn.execute(text(
"values(:user, :ip, :primary_menu, :sub_menu, :op_type, :content, :comment)" "insert into sys_log(user, ip, primary_menu, sub_menu, op_type, content, comment) "
), "values(:user, :ip, :primary_menu, :sub_menu, :op_type, :content, :comment)"
{"user": self.current_user.name, ),
"ip": self.request.headers[ {"user": self.current_user.name,
"X-Forwarded-For"] if "X-Forwarded-For" in self.request.headers else self.request.remote_ip, "ip": self.request.headers[
"primary_menu": primary_menu, "X-Forwarded-For"] if "X-Forwarded-For" in self.request.headers else self.request.remote_ip,
"sub_menu": sub_menu, "primary_menu": primary_menu,
"op_type": ope_type, "sub_menu": sub_menu,
"content": content, "op_type": ope_type,
"comment": comment "content": content,
} "comment": comment
) }
conn.commit() )
conn.commit()
except Exception as e:
logging.info("operation log error: %s" % e)
return func(self, *args, **kwargs) return func(self, *args, **kwargs)

@ -8,7 +8,7 @@ from website import consts
from website import db_mysql from website import db_mysql
from website import errors from website import errors
from website import settings from website import settings
from website.handler import APIHandler, authenticated from website.handler import APIHandler, authenticated, operation_log
from website.util import md5, shortuuid from website.util import md5, shortuuid
@ -19,6 +19,7 @@ class ClassificationAddHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型列表", consts.op_type_add_str, "添加模型分类", "")
def post(self): def post(self):
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
if not name: if not name:
@ -53,6 +54,7 @@ class ClassificationEditHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型列表", consts.op_type_edit_str, "编辑模型分类", "")
def post(self): def post(self):
classification_id = self.get_int_argument("id") classification_id = self.get_int_argument("id")
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
@ -75,6 +77,7 @@ class ClassificationListHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型列表", consts.op_type_list_str, "查询模型分类", "")
def post(self): def post(self):
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
cur = conn.execute(text("""select id, name from model_classification""")) cur = conn.execute(text("""select id, name from model_classification"""))
@ -89,6 +92,7 @@ class ClassificationDeleteHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型列表", consts.op_type_delete_str, "删除模型分类", "")
def post(self): def post(self):
classification_id = self.get_int_argument("id") classification_id = self.get_int_argument("id")
if not classification_id: if not classification_id:
@ -104,12 +108,36 @@ class ClassificationDeleteHandler(APIHandler):
self.finish() self.finish()
class ClassificationEditHandler(APIHandler):
"""
编辑模型分类
"""
@authenticated
@operation_log("模型管理", "模型列表", consts.op_type_edit_str, "编辑模型分类", "")
def post(self):
classification_id = self.get_int_argument("id")
name = self.get_escaped_argument("name", "")
if not classification_id or not name:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "参数缺失")
with self.app_mysql.connect() as conn:
conn.execute(
text("""update model_classification set name=:name where id=:id"""),
{"name": name, "id": classification_id},
)
conn.commit()
self.finish()
class ListHandler(APIHandler): class ListHandler(APIHandler):
""" """
模型列表 模型列表
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型列表", consts.op_type_list_str, "查询模型列表", "")
def post(self): def post(self):
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
@ -124,7 +152,7 @@ class ListHandler(APIHandler):
param = {} param = {}
sql_count = "select count(id) from model where del=0 " sql_count = "select count(id) from model m where m.del=0 "
param_count = {} param_count = {}
if name: if name:
@ -161,6 +189,7 @@ class ListHandler(APIHandler):
class ListSimpleHandler(APIHandler): class ListSimpleHandler(APIHandler):
@authenticated @authenticated
@operation_log("模型管理", "模型列表", consts.op_type_list_str, "查询模型列表", "")
def post(self): def post(self):
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
sql = "select id, name from model where del=0" sql = "select id, name from model where del=0"
@ -176,6 +205,7 @@ class AddHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "添加模型", consts.op_type_add_str, "添加模型", "")
def post(self): def post(self):
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
model_type = self.get_int_argument( model_type = self.get_int_argument(
@ -218,6 +248,7 @@ class EditHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "编辑模型", consts.op_type_edit_str, "编辑模型", "")
def post(self): def post(self):
mid = self.get_int_argument("id") mid = self.get_int_argument("id")
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
@ -258,6 +289,7 @@ class InfoHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型信息", consts.op_type_list_str, "查询模型信息", "")
def post(self): def post(self):
mid = self.get_int_argument("id") mid = self.get_int_argument("id")
if not mid: if not mid:
@ -270,8 +302,10 @@ class InfoHandler(APIHandler):
select select
m.name, m.model_type, m.default_version, m.comment, m.update_time, m.name, m.model_type, m.default_version, m.comment, m.update_time,
mc.id as classification_id, mc.name as classification_name mc.id as classification_id, mc.name as classification_name
from model m, model_classification mc from model m
where m.id=:id and m.classification=mc.id left join model_classification mc
on m.classification=mc.id
where m.id=:id
""" """
), ),
{"id": mid}, {"id": mid},
@ -300,6 +334,7 @@ class DeleteHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型列表", consts.op_type_delete_str, "删除模型", "")
def post(self): def post(self):
mid = self.get_int_argument("id") mid = self.get_int_argument("id")
if not mid: if not mid:
@ -329,6 +364,7 @@ class VersionAddHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型版本", consts.op_type_add_str, "添加模型版本", "")
def post(self): def post(self):
mid = self.get_int_argument("model_id") mid = self.get_int_argument("model_id")
version = self.get_escaped_argument("version", "") version = self.get_escaped_argument("version", "")
@ -382,6 +418,7 @@ class VersionEditHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型版本", consts.op_type_edit_str, "编辑模型版本", "")
def post(self): def post(self):
version_id = self.get_int_argument("version_id") version_id = self.get_int_argument("version_id")
version = self.get_escaped_argument("version", "") version = self.get_escaped_argument("version", "")
@ -445,10 +482,11 @@ class VersionListHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型版本", consts.op_type_list_str, "模型版本列表", "")
def post(self): def post(self):
model_id = self.get_int_argument("model_id") model_id = self.get_int_argument("model_id")
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 20) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
if not model_id: if not model_id:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "参数缺失") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "参数缺失")
@ -524,6 +562,7 @@ class VersionInfoHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型版本", consts.op_type_list_str, "查询模型版本详情", "")
def post(self): def post(self):
version_id = self.get_int_argument("version_id") version_id = self.get_int_argument("version_id")
response = { response = {
@ -606,6 +645,7 @@ class VersionSetDefaultHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型版本", consts.op_type_edit_str, "设置模型版本为默认版本", "")
def post(self): def post(self):
version_id = self.get_int_argument("version_id") version_id = self.get_int_argument("version_id")
model_id = self.get_int_argument("model_id") model_id = self.get_int_argument("model_id")
@ -644,6 +684,7 @@ class VersionDeleteHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型版本", consts.op_type_delete_str, "删除模型版本", "")
def post(self): def post(self):
version_id = self.get_int_argument("version_id") version_id = self.get_int_argument("version_id")
if not version_id: if not version_id:

@ -5,6 +5,7 @@ handlers = [
("/model/classification/add", handler.ClassificationAddHandler), ("/model/classification/add", handler.ClassificationAddHandler),
("/model/classification/list", handler.ClassificationListHandler), ("/model/classification/list", handler.ClassificationListHandler),
("/model/classification/delete", handler.ClassificationDeleteHandler), ("/model/classification/delete", handler.ClassificationDeleteHandler),
("/model/classification/edit", handler.ClassificationEditHandler),
("/model/list", handler.ListHandler), ("/model/list", handler.ListHandler),
("/model/list/simple", handler.ListSimpleHandler), ("/model/list/simple", handler.ListSimpleHandler),

@ -9,7 +9,7 @@ from website import consts
from website import db_mysql from website import db_mysql
from website import errors from website import errors
from website import settings from website import settings
from website.handler import APIHandler, authenticated from website.handler import APIHandler, authenticated, operation_log
class ListHandler(APIHandler): class ListHandler(APIHandler):
@ -38,6 +38,7 @@ class ListHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型运行库", consts.op_type_list_str, "查询模型运行库列表", "")
def post(self): def post(self):
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
@ -104,6 +105,7 @@ class SyncHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型运行库", consts.op_type_list_str, "查询模型运行库镜像", "")
def post(self): def post(self):
host = self.get_escaped_argument("host", "") host = self.get_escaped_argument("host", "")
port = self.get_int_argument("port") port = self.get_int_argument("port")
@ -142,6 +144,7 @@ class AddHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型运行库", consts.op_type_add_str, "新建模型运行库", "")
def post(self): def post(self):
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
host = self.get_escaped_argument("host", "") host = self.get_escaped_argument("host", "")
@ -173,7 +176,7 @@ class AddHandler(APIHandler):
self.finish() self.finish()
class EditHandler(APIHandler): class EditHandler(APIHandler):
""" """
- 描述 编辑模型运行库 - 描述 编辑模型运行库
- 请求方式post - 请求方式post
@ -188,6 +191,7 @@ class EditHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型运行库", consts.op_type_edit_str, "编辑模型运行库", "")
def post(self): def post(self):
id = self.get_int_argument("id") id = self.get_int_argument("id")
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
@ -195,7 +199,7 @@ class EditHandler(APIHandler):
port = self.get_int_argument("port") port = self.get_int_argument("port")
path = self.get_escaped_argument("path", "") path = self.get_escaped_argument("path", "")
comment = self.get_escaped_argument("comment", "") comment = self.get_escaped_argument("comment", "")
if not id or not name or not host or not port or path: if not id or not name or not host or not port or not path:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "parameter error") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "parameter error")
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
conn.execute( conn.execute(
@ -235,6 +239,7 @@ class InfoHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型运行库", consts.op_type_list_str, "查询模型运行库信息", "")
def post(self): def post(self):
hid = self.get_int_argument("id") hid = self.get_int_argument("id")
if not id: if not id:
@ -266,6 +271,7 @@ class DeleteHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("模型管理", "模型运行库", consts.op_type_delete_str, "删除模型运行库", "")
def post(self): def post(self):
hid = self.get_int_argument("id") hid = self.get_int_argument("id")
if not id: if not id:

@ -3,8 +3,8 @@ import json
import logging import logging
from sqlalchemy import text from sqlalchemy import text
from website import db_mysql, errors from website import db_mysql, errors, consts
from website.handler import APIHandler, authenticated from website.handler import APIHandler, authenticated, operation_log
from website.util import shortuuid from website.util import shortuuid
from website.db.enterprise_busi_model import enterprise_busi_model as DB_BusiModel from website.db.enterprise_busi_model import enterprise_busi_model as DB_BusiModel
from website.db.enterprise_busi_model import enterprise_busi_model_node_device as DB_BusiModelNodeDevice from website.db.enterprise_busi_model import enterprise_busi_model_node_device as DB_BusiModelNodeDevice
@ -35,9 +35,10 @@ class ListHandler(APIHandler):
``` ```
""" """
@authenticated @authenticated
@operation_log("企业管理", "业务模型", consts.op_type_list_str, "查询企业部署的业务模型列表", "")
def post(self): def post(self):
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 10) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
entity_id = self.get_int_argument("entity_id") entity_id = self.get_int_argument("entity_id")
if not entity_id: if not entity_id:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "参数错误") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "参数错误")
@ -63,6 +64,7 @@ class AddHandler(APIHandler):
- 返回值 - 返回值
""" """
@authenticated @authenticated
@operation_log("企业管理", "业务模型", consts.op_type_add_str, "添加企业部署的业务模型", "")
def post(self): def post(self):
entity_id = self.get_int_argument("entity_id") entity_id = self.get_int_argument("entity_id")
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
@ -131,6 +133,7 @@ class InfoHandler(APIHandler):
``` ```
""" """
@authenticated @authenticated
@operation_log("企业管理", "业务模型", consts.op_type_list_str, "查询企业部署的业务模型详情")
def post(self): def post(self):
busimodel_id = self.get_int_argument("id") busimodel_id = self.get_int_argument("id")
@ -145,11 +148,14 @@ class InfoHandler(APIHandler):
db_file = DB_File.FileRepository() db_file = DB_File.FileRepository()
files = db_file.get_file_by_md5([busi_model_data.business_conf_file, busi_model_data.business_logic]) files = db_file.get_file_by_md5([busi_model_data.business_conf_file, busi_model_data.business_logic])
business_conf_name = files[0].filename business_logic_name = ""
business_logic_name = files[1].filename business_conf_name = ""
for item in files:
if item.md5_str == busi_model_data.business_logic:
business_logic_name = item.filename
else:
business_conf_name = item.filename
# business_conf_name = db_file.get_file_by_md5(busi_model_data.business_conf_file)
# business_logic_name = db_file.get_file_by_md5(busi_model_data.business_logic)
basemodel_list = json.loads(busi_model_data.base_models) basemodel_list = json.loads(busi_model_data.base_models)
entity_suid = busi_model_data.entity_suid entity_suid = busi_model_data.entity_suid
@ -189,6 +195,7 @@ class EditHandler(APIHandler):
- 返回值 - 返回值
""" """
@authenticated @authenticated
@operation_log("企业管理", "业务模型", consts.op_type_edit_str, "编辑企业部署的业务模型")
def post(self): def post(self):
busimodel_id = self.get_int_argument("id") busimodel_id = self.get_int_argument("id")
@ -255,6 +262,7 @@ class EditHandler(APIHandler):
class DeleteHandler(APIHandler): class DeleteHandler(APIHandler):
@authenticated @authenticated
@operation_log("企业管理", "业务模型", consts.op_type_delete_str, "删除企业部署的业务模型")
def post(self): def post(self):
busimodel_id = self.get_int_argument("id") busimodel_id = self.get_int_argument("id")
if not busimodel_id: if not busimodel_id:

@ -16,7 +16,7 @@ from website.db.enterprise_busi_model import enterprise_busi_model_node_device a
from website.db.enterprise_device import enterprise_device as DB_Device from website.db.enterprise_device import enterprise_device as DB_Device
from website.db.enterprise_node import enterprise_node as DB_Node from website.db.enterprise_node import enterprise_node as DB_Node
from website.db.enterprise_node import enterprise_node_base_model_conf as DB_NodeBaseModelConf from website.db.enterprise_node import enterprise_node_base_model_conf as DB_NodeBaseModelConf
from website.handler import APIHandler, authenticated from website.handler import APIHandler, authenticated, operation_log
from website.util import date_util from website.util import date_util
from website.util import shortuuid from website.util import shortuuid
@ -37,6 +37,7 @@ class DeviceClassificationAddHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "设备管理", consts.op_type_add_str, "添加设备分类")
def post(self): def post(self):
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
@ -82,11 +83,23 @@ class DeviceClassificationHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "设备管理", consts.op_type_list_str, "设备分类列表")
def post(self): def post(self):
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
cur = conn.execute( cur = conn.execute(
text( text(
"SELECT id, suid, name FROM device_classification where del=0 ORDER BY id DESC" """
SELECT id, suid, name,
CASE
WHEN EXISTS (
SELECT 1
FROM enterprise_device
WHERE classification = device_classification.suid
) THEN '1'
ELSE '0'
END AS used
FROM device_classification where del=0 ORDER BY id DESC
"""
) )
) )
res = db_mysql.to_json_list(cur) res = db_mysql.to_json_list(cur)
@ -105,6 +118,7 @@ class DeviceClassificationDeleteHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "设备管理", consts.op_type_delete_str, "删除设备分类")
def post(self): def post(self):
did = self.get_int_argument("id") did = self.get_int_argument("id")
@ -112,9 +126,9 @@ class DeviceClassificationDeleteHandler(APIHandler):
cur = conn.execute( cur = conn.execute(
text( text(
""" """
select d.id from enterprise_device d, device_classification c select d.id from enterprise_device d, device_classification c
where d.classification=c.suid and c.id=:id and c.del=0 where d.classification=c.suid and c.id=:id and c.del=0
""" """
), ),
{"id": did}, {"id": did},
) )
@ -131,6 +145,30 @@ class DeviceClassificationDeleteHandler(APIHandler):
self.finish() self.finish()
class DeviceClassificationEditHandler(APIHandler):
"""
- 描述编辑设备分类
- 请求方式post
- 请求参数
>- id
>- name
- 返回值
"""
@authenticated
@operation_log("企业管理", "设备管理", consts.op_type_edit_str, "编辑设备分类")
def post(self):
did = self.get_int_argument("id")
name = self.get_escaped_argument("name", "")
with self.app_mysql.connect() as conn:
conn.execute(
text("update device_classification set name=:name WHERE id=:id"),
{"id": did, "name": name},
)
conn.commit()
self.finish()
class DeviceAddHandler(APIHandler): class DeviceAddHandler(APIHandler):
""" """
- 描述企业节点添加设备 - 描述企业节点添加设备
@ -151,6 +189,7 @@ class DeviceAddHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "设备管理", consts.op_type_add_str, "企业节点,添加设备")
def post(self): def post(self):
entity_id = self.get_int_argument("entity_id") entity_id = self.get_int_argument("entity_id")
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
@ -204,6 +243,7 @@ class DeviceEditHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "设备管理", consts.op_type_edit_str, "企业节点,编辑设备")
def post(self): def post(self):
device_id = self.get_int_argument("device_id") device_id = self.get_int_argument("device_id")
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
@ -243,6 +283,7 @@ class DeviceDeleteHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "设备管理", consts.op_type_delete_str, "企业节点,删除设备")
def post(self): def post(self):
# node_id = self.get_int_argument('node_id') # node_id = self.get_int_argument('node_id')
device_id = self.get_int_argument("device_id") device_id = self.get_int_argument("device_id")
@ -281,10 +322,11 @@ class DeviceListHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "设备管理", consts.op_type_list_str, "企业节点,设备列表")
def post(self): def post(self):
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 20) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
if not node_id: if not node_id:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "企业节点不能为空") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "企业节点不能为空")
db_device = DB_Device.EnterpriseDeviceRepository() db_device = DB_Device.EnterpriseDeviceRepository()
@ -329,7 +371,8 @@ class DeviceInfoHandler(APIHandler):
} }
``` ```
""" """
@authenticated
@operation_log("企业管理", "设备管理", consts.op_type_list_str, "企业节点,设备信息")
def post(self): def post(self):
device_id = self.get_int_argument("device_id") device_id = self.get_int_argument("device_id")
if not device_id: if not device_id:
@ -374,6 +417,7 @@ class DeviceBasemodelListHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_list_str, "企业节点,节点信息 -> 设备列表 -> 基础模型配置 -> 模型列表")
def post(self): def post(self):
device_id = self.get_int_argument("device_id") device_id = self.get_int_argument("device_id")
if not device_id: if not device_id:
@ -381,7 +425,7 @@ class DeviceBasemodelListHandler(APIHandler):
errors.ERROR_BAD_REQUEST, "企业节点或设备不能为空" errors.ERROR_BAD_REQUEST, "企业节点或设备不能为空"
) )
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 10) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
db_busi_model = DB_BusiModelNodeDevice.EnterpriseBusiModelNodeDeviceRepository() db_busi_model = DB_BusiModelNodeDevice.EnterpriseBusiModelNodeDeviceRepository()
busi_models, count = db_busi_model.get_busi_model_by_device(device_id=device_id, pagination=True, busi_models, count = db_busi_model.get_busi_model_by_device(device_id=device_id, pagination=True,
page_no=pageNo, page_no=pageNo,
@ -395,9 +439,6 @@ class DeviceBasemodelListHandler(APIHandler):
busi_model_id = item["busi_model_id"] busi_model_id = item["busi_model_id"]
busi_model_name = item["name"] busi_model_name = item["name"]
base_model_list = json.loads(item["base_models"]) base_model_list = json.loads(item["base_models"])
logging.info("##############################################################")
logging.info(base_model_list)
logging.info("##############################################################")
base_models = [] base_models = []
for base_model in base_model_list: for base_model in base_model_list:
base_model_id = base_model["id"] base_model_id = base_model["id"]
@ -448,6 +489,8 @@ class DeviceBaseModelCustomConfigHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_add_str,
"企业节点,节点信息 -> 设备列表 -> 基础模型配置 -> 基础模型参数配置")
def post(self): def post(self):
device_id = self.get_int_argument("device_id") device_id = self.get_int_argument("device_id")
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
@ -533,13 +576,14 @@ class StatusListHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "设备状态", consts.op_type_list_str,"设备状态列表")
def post(self): def post(self):
entity_id = self.get_int_argument("entity_id") entity_id = self.get_int_argument("entity_id")
group = self.get_int_argument("group") group = self.get_int_argument("group")
classification = self.get_escaped_argument("classification", "") classification = self.get_escaped_argument("classification", "")
status = self.get_int_argument("status", 1000) status = self.get_int_argument("status", 1000)
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 20) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
if not entity_id: if not entity_id:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "企业节点不能为空") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "企业节点不能为空")
@ -599,6 +643,7 @@ class StatusInfoHandler(APIHandler):
""" """ """ """
@authenticated @authenticated
@operation_log("企业管理", "设备状态", consts.op_type_list_str, "设备信息")
def post(self): def post(self):
device_id = self.get_int_argument("id") device_id = self.get_int_argument("id")
if not device_id: if not device_id:
@ -698,7 +743,7 @@ class StatusLogHandler(APIHandler):
def post(self): def post(self):
entity_id = self.get_int_argument("entity_id") entity_id = self.get_int_argument("entity_id")
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 10) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
db_device = DB_Device.EnterpriseDeviceRepository() db_device = DB_Device.EnterpriseDeviceRepository()
res = db_device.list_entity_devices(entity_id=entity_id, pageno=pageNo, pagesize=pageSize) res = db_device.list_entity_devices(entity_id=entity_id, pageno=pageNo, pagesize=pageSize)

@ -5,10 +5,8 @@ from website.handlers.enterprise_device import handler
handlers = [ handlers = [
("/enterprise/device/classification/add", handler.DeviceClassificationAddHandler), ("/enterprise/device/classification/add", handler.DeviceClassificationAddHandler),
("/enterprise/device/classification", handler.DeviceClassificationHandler), ("/enterprise/device/classification", handler.DeviceClassificationHandler),
( ("/enterprise/device/classification/delete", handler.DeviceClassificationDeleteHandler),
"/enterprise/device/classification/delete", ("/enterprise/device/classification/edit", handler.DeviceClassificationEditHandler),
handler.DeviceClassificationDeleteHandler,
),
("/enterprise/entity/nodes/device/add", handler.DeviceAddHandler), ("/enterprise/entity/nodes/device/add", handler.DeviceAddHandler),
("/enterprise/entity/nodes/device/edit", handler.DeviceEditHandler), ("/enterprise/entity/nodes/device/edit", handler.DeviceEditHandler),
("/enterprise/entity/nodes/device/delete", handler.DeviceDeleteHandler), ("/enterprise/entity/nodes/device/delete", handler.DeviceDeleteHandler),

@ -12,7 +12,7 @@ from website import settings
from website.db.alg_model.alg_model import ModelRepositry from website.db.alg_model.alg_model import ModelRepositry
from website.db.enterprise import enterprise from website.db.enterprise import enterprise
from website.db.enterprise_device.enterprise_device import EnterpriseDeviceRepository from website.db.enterprise_device.enterprise_device import EnterpriseDeviceRepository
from website.handler import APIHandler, authenticated from website.handler import APIHandler, authenticated, operation_log
from website.util import shortuuid, aes from website.util import shortuuid, aes
@ -24,9 +24,10 @@ class EntityIndexHandler(APIHandler):
"""首页""" """首页"""
@authenticated @authenticated
@operation_log("首页", "企业列表", consts.op_type_list_str, "企业列表")
async def post(self): async def post(self):
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 10) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
name = self.tostr(self.get_escaped_argument("name", "")) name = self.tostr(self.get_escaped_argument("name", ""))
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
@ -104,7 +105,7 @@ class EntityIndexHandler(APIHandler):
"industry": consts.industry_map[item["industry"]], "industry": consts.industry_map[item["industry"]],
"modelCount": model_count, "modelCount": model_count,
"deviceCount": device_count, "deviceCount": device_count,
"logo": item["logo"], "logo": str(item["logo"]),
"createTime": str(item["create_time"]), "createTime": str(item["create_time"]),
} }
for item, model_count, device_count in zip( for item, model_count, device_count in zip(
@ -119,6 +120,7 @@ class EntityIndexBasecountHandler(APIHandler):
"""首页基础统计书记""" """首页基础统计书记"""
@authenticated @authenticated
@operation_log("首页", "企业列表", consts.op_type_list_str, "基础统计数据")
def post(self): def post(self):
entity_count = enterprise.get_enterprise_entity_count(self.app_mysql) entity_count = enterprise.get_enterprise_entity_count(self.app_mysql)
model_repository = ModelRepositry() model_repository = ModelRepositry()
@ -133,6 +135,7 @@ class EntityAddHandler(APIHandler):
"""添加企业""" """添加企业"""
@authenticated @authenticated
@operation_log("首页", "企业列表", consts.op_type_add_str, "添加企业项目")
def post(self): def post(self):
name = self.tostr(self.get_escaped_argument("name", "")) name = self.tostr(self.get_escaped_argument("name", ""))
province = self.get_escaped_argument("province", "") province = self.get_escaped_argument("province", "")
@ -203,6 +206,7 @@ class EntityEditHandler(APIHandler):
"""编辑企业""" """编辑企业"""
@authenticated @authenticated
@operation_log("首页", "企业列表", consts.op_type_edit_str, "编辑企业项目")
def post(self): def post(self):
eid = self.get_int_argument("id") eid = self.get_int_argument("id")
name = self.tostr(self.get_escaped_argument("name", "")) name = self.tostr(self.get_escaped_argument("name", ""))
@ -267,6 +271,7 @@ class EntityInfoHandler(APIHandler):
"""企业信息""" """企业信息"""
@authenticated @authenticated
@operation_log("企业管理", "企业信息", consts.op_type_list_str, "企业信息")
def post(self): def post(self):
eid = self.get_int_argument("id") eid = self.get_int_argument("id")
@ -293,12 +298,13 @@ class EntityInfoHandler(APIHandler):
"province": row["province"], "province": row["province"],
"city": row["city"], "city": row["city"],
"addr": row["addr"], "addr": row["addr"],
"industry": consts.industry_map[row["industry"]], "industry": row["industry"],
"industry_name": consts.industry_map[row["industry"]],
"expire_at": "", "expire_at": "",
"contact": row["contact"], "contact": row["contact"],
"phone": row["phone"], "phone": row["phone"],
"summary": row["summary"], "summary": row["summary"],
"logo": row["logo"], "logo": str(row["logo"]),
"createTime": str(row["create_time"]), "createTime": str(row["create_time"]),
"account": row["account"], # 企业账号 "account": row["account"], # 企业账号
} }
@ -310,42 +316,45 @@ class ModelsHandler(APIHandler):
"""企业模型""" """企业模型"""
@authenticated @authenticated
@operation_log("企业管理", "企业模型", consts.op_type_list_str, "企业模型")
def post(self): def post(self):
eid = self.get_int_argument("id") eid = self.get_int_argument("id")
model_ids = [] model_ids = []
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
cur = conn.execute( cur_modelid = conn.execute(
text("select base_models from enterprise_busi_model where entity_id=:eid"), {"eid": eid} text("select base_models from enterprise_busi_model where entity_id=:eid"), {"eid": eid}
) )
rows = db_mysql.to_json_list(cur) rows = db_mysql.to_json_list(cur_modelid)
for row in rows: for row in rows:
base_models = json.loads(row["base_models"]) base_models = json.loads(row["base_models"])
model_ids.extend([item["id"] for item in base_models]) model_ids.extend([item["id"] for item in base_models])
cur.close() cur_modelid.close()
model_ids = list(set(model_ids)) model_ids = list(set(model_ids))
cur = conn.execute(text(
"""
select m.name, m.model_type, mc.name as classification_name, m.default_version
from model m, model_classification mc
where m.classification=mc.id and m.id in :model_ids
"""
), {"model_ids": model_ids})
rows = db_mysql.to_json_list(cur)
cur.close()
data = [] data = []
for row in rows:
data.append({ if len(model_ids) > 0:
"name": row["name"], cur = conn.execute(text(
"model_type": consts.model_type_map[row["model_type"]], """
"classification_name": row["classification_name"], select m.name, m.model_type, mc.name as classification_name, m.default_version
"default_version": row["default_version"] from model m, model_classification mc
}) where m.classification=mc.id and m.id in :model_ids
"""
), {"model_ids": model_ids})
rows = db_mysql.to_json_list(cur)
cur.close()
for row in rows:
data.append({
"name": row["name"],
"model_type": consts.model_type_map[row["model_type"]],
"classification_name": row["classification_name"],
"default_version": row["default_version"]
})
self.finish({"count": len(model_ids), "data": data}) self.finish({"count": len(model_ids), "data": data})
@ -354,6 +363,7 @@ class EntityDeleteHandler(APIHandler):
"""删除企业""" """删除企业"""
@authenticated @authenticated
@operation_log("首页", "企业列表", consts.op_type_delete_str, "删除企业")
def post(self): def post(self):
eid = self.get_int_argument("id") eid = self.get_int_argument("id")
@ -369,6 +379,7 @@ class EntityPwdcheckHandler(APIHandler):
"""查看企业密码""" """查看企业密码"""
@authenticated @authenticated
@operation_log("企业管理", "企业信息", consts.op_type_list_str, "查看企业密码")
def post(self): def post(self):
eid = self.get_int_argument("id") eid = self.get_int_argument("id")

@ -1,7 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json import json
import logging
from website import errors from website import errors, consts
from website.db.enterprise_busi_model import enterprise_busi_model as DB_BusiModel from website.db.enterprise_busi_model import enterprise_busi_model as DB_BusiModel
from website.db.enterprise_busi_model import ( from website.db.enterprise_busi_model import (
enterprise_busi_model_node_device as DB_BusiModelNodeDevice, enterprise_busi_model_node_device as DB_BusiModelNodeDevice,
@ -10,7 +11,7 @@ from website.db.enterprise_device import enterprise_device as DB_Device
from website.db.enterprise_entity import enterprise_entity as DB_Entity from website.db.enterprise_entity import enterprise_entity as DB_Entity
from website.db.enterprise_node import enterprise_node as DB_Node from website.db.enterprise_node import enterprise_node as DB_Node
from website.db.enterprise_node import enterprise_node_alert as DB_NodeAlert from website.db.enterprise_node import enterprise_node_alert as DB_NodeAlert
from website.handler import APIHandler, authenticated from website.handler import APIHandler, authenticated, operation_log
from website.util import shortuuid from website.util import shortuuid
@ -30,7 +31,8 @@ class AddHandler(APIHandler):
- 返回值 - 返回值
""" """
# @authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_add_str, "添加企业节点")
def post(self): def post(self):
entity_id = self.get_int_argument("entity_id") entity_id = self.get_int_argument("entity_id")
entity_suid = self.get_escaped_argument("entity_suid", "") entity_suid = self.get_escaped_argument("entity_suid", "")
@ -83,7 +85,8 @@ class EditHandler(APIHandler):
- 返回值 - 返回值
""" """
# @authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_edit_str, "更新企业节点")
def post(self): def post(self):
node_id = self.get_int_argument("node_id", 0) node_id = self.get_int_argument("node_id", 0)
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
@ -151,9 +154,11 @@ class TreeHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_list_str, "企业节点树")
def post(self): def post(self):
entity_id = self.get_escaped_argument("entity_id", "") entity_id = self.get_escaped_argument("entity_id", "")
name = self.get_escaped_argument("name", "") name = self.get_escaped_argument("name", "")
# logging.info(f"name is {name}")
if not entity_id: if not entity_id:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "参数错误") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "参数错误")
@ -183,6 +188,7 @@ class InfoHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_list_str, "企业节点信息")
def post(self): def post(self):
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
@ -198,6 +204,7 @@ class InfoHandler(APIHandler):
class DeleteHandler(APIHandler): class DeleteHandler(APIHandler):
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_list_str, "删除节点")
def post(self): def post(self):
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
if not node_id: if not node_id:
@ -233,10 +240,11 @@ class BusimodelHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_list_str, "业务模型部署列表")
def post(self): def post(self):
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 20) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
if not node_id: if not node_id:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "企业节点不能为空") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "企业节点不能为空")
@ -284,6 +292,7 @@ class BusimodelInfoHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_list_str, "业务模型部署 -> 业务模型信息")
def post(self): def post(self):
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
busi_model_id = self.get_int_argument("busi_model_id") busi_model_id = self.get_int_argument("busi_model_id")
@ -332,6 +341,7 @@ class BusimodelDeployHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_add_str, "业务模型部署 -> 业务模型配置")
def post(self): def post(self):
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
busi_model_id = self.get_int_argument("busi_model_id") busi_model_id = self.get_int_argument("busi_model_id")
@ -403,6 +413,7 @@ class AlertHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_list_str, "节点信息 -> 设备列表 -> 告警设置信息")
def post(self): def post(self):
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
if not node_id: if not node_id:
@ -452,6 +463,7 @@ class AlertConfigHandler(APIHandler):
""" """
@authenticated @authenticated
@operation_log("企业管理", "节点设置", consts.op_type_edit_str, "节点信息 -> 设备列表 -> 告警设置,更新配置")
def post(self): def post(self):
node_id = self.get_int_argument("node_id") node_id = self.get_int_argument("node_id")
is_sms = self.get_int_argument("is_sms", 0) is_sms = self.get_int_argument("is_sms", 0)

@ -6,6 +6,7 @@ from sqlalchemy import text
from website import errors from website import errors
from website import settings from website import settings
from website import consts
from website.db.enterprise_device.enterprise_device import EnterpriseEntityRepository as EntRepo from website.db.enterprise_device.enterprise_device import EnterpriseEntityRepository as EntRepo
from website.db_mysql import to_json_list, to_json from website.db_mysql import to_json_list, to_json
from website.handler import APIHandler, authenticated, operation_log from website.handler import APIHandler, authenticated, operation_log
@ -131,7 +132,7 @@ class ListHandler(APIHandler):
entity_id = self.get_int_argument('entity_id') entity_id = self.get_int_argument('entity_id')
status = self.get_int_argument("status") status = self.get_int_argument("status")
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 10) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
if not entity_id: if not entity_id:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "entity_id is required") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "entity_id is required")
if status and status not in (1001, 1002): if status and status not in (1001, 1002):
@ -241,7 +242,7 @@ class LogHandler(APIHandler):
def post(self): def post(self):
entity_id = self.get_int_argument('entity_id') entity_id = self.get_int_argument('entity_id')
pageNo = self.get_int_argument('pageNo', 1) pageNo = self.get_int_argument('pageNo', 1)
pageSize = self.get_int_argument('pageSize', 10) pageSize = self.get_int_argument('pageSize', consts.PAGE_SIZE)
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
p = {} p = {}

@ -30,7 +30,7 @@ class UploadHandler(APIHandler):
logging.info("file_size: %s", file_size) logging.info("file_size: %s", file_size)
if file_size > 300 * 1024 * 1024: if file_size > 300 * 1024 * 1024:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, 'Exceed 300M size limit') raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, '超出300M限定大小')
filetype = filename.split(".") and filename.split(".")[-1] or "" filetype = filename.split(".") and filename.split(".")[-1] or ""

@ -1,21 +1,19 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""系统信息""" """系统信息"""
import datetime
import json
import logging import logging
import uuid
import time
import re import re
import os import time
import json
import hashlib
import datetime from sqlalchemy import text
from website import consts
from website import errors from website import errors
from website import settings from website import settings
from website.handler import APIHandler, WebHandler, authenticated, operation_log, permission
from website.db_mysql import to_json_list from website.db_mysql import to_json_list
from website.util import sysinfo, rsa from website.handler import APIHandler, authenticated
from sqlalchemy import text from website.util import sysinfo, rsa_oaep
class VersionHandler(APIHandler): class VersionHandler(APIHandler):
@ -24,8 +22,12 @@ class VersionHandler(APIHandler):
def post(self): def post(self):
self.finish() self.finish()
class IdentifycodeHandler(APIHandler): class IdentifycodeHandler(APIHandler):
@authenticated """系统识别码"""
# @authenticated
# @permission([100014, 100015]) # @permission([100014, 100015])
# @operation_log("资产管理中心", "系统激活", "查询", "查询本地识别码", "查询本地识别码") # @operation_log("资产管理中心", "系统激活", "查询", "查询本地识别码", "查询本地识别码")
def post(self): def post(self):
@ -33,6 +35,7 @@ class IdentifycodeHandler(APIHandler):
self.finish({"result": code}) self.finish({"result": code})
class LicenseUploadHandler(APIHandler): class LicenseUploadHandler(APIHandler):
@authenticated @authenticated
# @permission([100014, 100015]) # @permission([100014, 100015])
@ -55,45 +58,44 @@ class LicenseUploadHandler(APIHandler):
if file_size > 10 * 1024 * 1024: if file_size > 10 * 1024 * 1024:
raise errors.HTTPAPIError(errors.ERROR_METHOD_NOT_ALLOWED, 'Exceed 10M size limit') raise errors.HTTPAPIError(errors.ERROR_METHOD_NOT_ALLOWED, 'Exceed 10M size limit')
md5_str = hashlib.md5(file.body).hexdigest()
filepath = settings.rsa_license_file filepath = settings.rsa_license_file
try: try:
body = file['body'] body = file['body']
public_key = rsa.load_pub_key_string(open(settings.rsa_public_file).read().strip('\n').encode('utf-8')) plaintext = rsa_oaep.decrypt_message_pri(
plaintext = rsa.decrypt(public_key, body) open(settings.rsa_private_file).read().strip('\n').encode('utf-8'), body)
plaintext_json = json.loads(self.tostr(plaintext)) plaintext_json = json.loads(self.tostr(plaintext))
syscode = plaintext_json["syscode"] syscode = plaintext_json["sys_code"]
expireat = plaintext_json["expireat"] expireat = plaintext_json["expire_at"]
current_syscode = sysinfo.get_identify_code() current_syscode = sysinfo.get_idntify_code_v2()
if syscode != current_syscode: if syscode != current_syscode:
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "license激活失败请重新激活") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "license激活失败请重新激活")
row = self.db_app.get("select id from license where syscode=%s", syscode) with self.app_mysql.connect() as conn:
if row: conn.execute(text(
self.db_app.update( "update sys_license set syscode=:syscode, expireat=:expireat, status=:status",
"update license set expireat=%s where syscode=%s", str(expireat), syscode {
) "syscode": syscode,
else: "expireat": expireat,
self.db_app.insert( "status": consts.system_status_activated
"insert into license(syscode, expireat) values(%s, %s)", }
syscode, expireat ))
) conn.commit()
self.r_app.set("system:license", json.dumps({"syscode":syscode, "expireat":expireat}))
self.r_app.set("system:license", json.dumps({"syscode": syscode, "expireat": expireat}))
with open(filepath, 'wb') as f: with open(filepath, 'wb') as f:
f.write(file['body']) f.write(file['body'])
logging.info(plaintext_json)
except Exception as e: except Exception as e:
logging.info(e) logging.info(e)
raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "license激活失败请重新激活") raise errors.HTTPAPIError(errors.ERROR_BAD_REQUEST, "license激活失败请重新激活")
self.finish() self.finish()
class ActivateInfoHandler(APIHandler): class ActivateInfoHandler(APIHandler):
@authenticated @authenticated
# @permission([100014, 100015]) # @permission([100014, 100015])
@ -116,11 +118,11 @@ class ActivateInfoHandler(APIHandler):
date_remain = delta if delta > 0 else 0 date_remain = delta if delta > 0 else 0
data = { data = {
"system": settings.system_info[settings.system_type]["name"], # "system": settings.system_info[settings.system_type]["name"],
"license": license_str, # "license": license_str,
"activate_at": activate_at, # "activate_at": activate_at,
"expire_at": expire_at, # "expire_at": expire_at,
"date_remain": date_remain # "date_remain": date_remain
} }
self.finish(data) self.finish(data)
@ -128,7 +130,6 @@ class ActivateInfoHandler(APIHandler):
class InfoHandler(APIHandler): class InfoHandler(APIHandler):
def post(self): def post(self):
self.finish() self.finish()
@ -139,17 +140,17 @@ class LogHandler(APIHandler):
start = self.get_escaped_argument("startDate", "") start = self.get_escaped_argument("startDate", "")
end = self.get_escaped_argument("endDate", "") end = self.get_escaped_argument("endDate", "")
pageNo = self.get_int_argument("pageNo", 1) pageNo = self.get_int_argument("pageNo", 1)
pageSize = self.get_int_argument("pageSize", 20) pageSize = self.get_int_argument("pageSize", consts.PAGE_SIZE)
users = user.split(",") user_list = user.split(",") if user else []
with self.app_mysql.connect() as conn: with self.app_mysql.connect() as conn:
sql = "select user, ip, content, op_type, content from sys_log where 1=1" sql = "select user, ip, content, op_type, content, create_time from sys_log where 1=1"
sql_count = "select count(*) from sys_log where 1=1" sql_count = "select count(*) from sys_log where 1=1"
p = {} p = {}
if users: if user_list:
sql += " and user in :users" sql += " and user in :users"
sql_count += " and user in :users" sql_count += " and user in :users"
p["users"] = users p["users"] = user_list
if start: if start:
sql += " and date_format(create_time, '%Y-%m-%d') >= :start" sql += " and date_format(create_time, '%Y-%m-%d') >= :start"
sql_count += " and date_format(create_time, '%Y-%m-%d') >= :start" sql_count += " and date_format(create_time, '%Y-%m-%d') >= :start"
@ -166,5 +167,7 @@ class LogHandler(APIHandler):
p["pageSize"] = pageSize p["pageSize"] = pageSize
res = conn.execute(text(sql), p) res = conn.execute(text(sql), p)
data = to_json_list(res) data = to_json_list(res)
for item in data:
item["create_time"] = str(item["create_time"])
self.finish({"count": count, "data": data}) self.finish({"count": count, "data": data})

@ -8,7 +8,6 @@ handlers = [
("/system/license/upload", handler.LicenseUploadHandler), ("/system/license/upload", handler.LicenseUploadHandler),
("/system/activate/info", handler.ActivateInfoHandler), ("/system/activate/info", handler.ActivateInfoHandler),
("/system/info", handler.InfoHandler), ("/system/info", handler.InfoHandler),
("/system/log", handler.LogHandler), ("/system/log", handler.LogHandler),
] ]

@ -4,11 +4,13 @@ import json
import logging import logging
import uuid import uuid
from io import BytesIO from io import BytesIO
from typing import Optional, Awaitable
from sqlalchemy import text from sqlalchemy import text
from website import db_mysql from website import db_mysql
from website import errors from website import errors
from website import consts
from website import settings from website import settings
from website.handler import APIHandler, authenticated from website.handler import APIHandler, authenticated
from website.util import aes from website.util import aes
@ -17,6 +19,7 @@ from website.util.captcha import create_validate_code
class CaptchaHandler(APIHandler): class CaptchaHandler(APIHandler):
def get(self): def get(self):
self.set_header("Content-Type", "image/png") self.set_header("Content-Type", "image/png")
image, image_str = create_validate_code() image, image_str = create_validate_code()
@ -44,6 +47,23 @@ class LogoutHandler(APIHandler):
# self.current_user.name, self.request.remote_ip, "平台管理中心", "账号管理", "登出", "系统登出", "系统登出" # self.current_user.name, self.request.remote_ip, "平台管理中心", "账号管理", "登出", "系统登出", "系统登出"
# ) # )
with self.app_mysql.connect() as conn:
conn.execute(text(
"insert into sys_log(user, ip, primary_menu, sub_menu, op_type, content, comment) "
"values(:user, :ip, :primary_menu, :sub_menu, :op_type, :content, :comment)"
),
{"user": self.current_user.name,
"ip": self.request.headers[
"X-Forwarded-For"] if "X-Forwarded-For" in self.request.headers else self.request.remote_ip,
"primary_menu": "系统操作",
"sub_menu": "登录/登出",
"op_type": consts.op_type_login_logout_str,
"content": "退出登录",
"comment": ""
}
)
conn.commit()
self.r_app.delete(settings.session_key_prefix % self.current_user.uuid) self.r_app.delete(settings.session_key_prefix % self.current_user.uuid)
self.finish() self.finish()
@ -162,6 +182,23 @@ class LoginHandler(APIHandler):
# "system_status": system_status, # 9000/未激活, 9001/已激活, 9002/过期可查看, 9003/完全过期 # "system_status": system_status, # 9000/未激活, 9001/已激活, 9002/过期可查看, 9003/完全过期
} }
with self.app_mysql.connect() as conn:
conn.execute(text(
"insert into sys_log(user, ip, primary_menu, sub_menu, op_type, content, comment) "
"values(:user, :ip, :primary_menu, :sub_menu, :op_type, :content, :comment)"
),
{"user": username,
"ip": self.request.headers[
"X-Forwarded-For"] if "X-Forwarded-For" in self.request.headers else self.request.remote_ip,
"primary_menu": "系统操作",
"sub_menu": "登录/登出",
"op_type": consts.op_type_login_logout_str,
"content": "登录成功",
"comment": ""
}
)
conn.commit()
self.finish(render_data) self.finish(render_data)

@ -78,8 +78,11 @@ enterprise_aes_key = "FquMBlcVoIkTAmL7"
file_upload_dir = "/data/fileupload" file_upload_dir = "/data/fileupload"
rsa_public_file = "/home/app/public" system_salt = "5bVQmI0ATh+QITf75WgVchT6TPN1DEOasSmrtMcTsPQ="
# rsa_public_file = "/home/app/public"
rsa_license_file = "/home/app/license" rsa_license_file = "/home/app/license"
rsa_private_file = "/home/app/private_key.pem"
# hashlib.sha256(base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)).hexdigest() # hashlib.sha256(base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)).hexdigest()

@ -1,22 +1,60 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from M2Crypto import RSA
from M2Crypto import BIO
from binascii import a2b_hex, b2a_hex from binascii import a2b_hex, b2a_hex
from M2Crypto import BIO
from M2Crypto import RSA
def load_pub_key_string(string): def load_pub_key_string(string):
bio = BIO.MemoryBuffer(string) bio = BIO.MemoryBuffer(string)
return RSA.load_pub_key_bio(bio) return RSA.load_pub_key_bio(bio)
def block_data(texts, block_size): def block_data(texts, block_size):
for i in range(0, len(texts), block_size): for i in range(0, len(texts), block_size):
yield texts[i:i + block_size] yield texts[i:i + block_size]
def decrypt(publick_key, texts):
def encrypt(texts):
ciphertext = b""
block_size = 256 - 11
for text in block_data(texts.encode('utf-8'), block_size):
current_text = pri_key.private_encrypt(text, RSA.pkcs1_padding)
ciphertext += current_text
return b2a_hex(ciphertext)
def decrypt(texts):
plaintext = b"" plaintext = b""
block_size = 256 block_size = 256
for text in block_data(a2b_hex(texts), block_size): for text in block_data(a2b_hex(texts), block_size):
current_text = publick_key.public_decrypt(text, RSA.pkcs1_padding) current_text = pub_key.public_decrypt(text, RSA.pkcs1_padding)
plaintext += current_text plaintext += current_text
return plaintext return plaintext
if __name__ == '__main__':
# 2048代表生成密钥的位数65537代表公钥的指数
key = RSA.gen_key(2048, 65537)
key.save_key("private_key", None)
key.save_pub_key("public_key")
prikey = open("private_key").read()
pubkey = open("public_key").read()
pri_key = RSA.load_key_string(prikey.strip('\n').encode('utf-8'))
pub_key = load_pub_key_string(pubkey.strip('\n').encode('utf-8'))
texts = "hellohellohellohellohellohellohellohellohellohellohellohellohello" \
"hellohellohellohellohellohellohellohellohellohellohellohellohello" \
"hellohellohellohellohellohellohellohellohellohellohellohellohello" \
"hellohellohellohellohellohellohellohellohellohellohello"
ciphertext = encrypt(texts)
print(ciphertext)
plaintext = decrypt(ciphertext)
print(plaintext)

@ -1,75 +0,0 @@
# -*- coding: utf-8 -*-
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
"""
RSA 加密中,有两种常见的填充方式:PKCS1_v1_5 PKCS1_OAEP这两种填充方式在安全性和性能方面都有一些差异
PKCS1_v1_5 填充方式:
这是较早的 RSA 填充方式,相对简单且性能较好
但是它存在一些安全隐患,比如可能会受到选择密文攻击(Chosen Ciphertext Attack, CCA)
PKCS1_OAEP 填充方式:
PKCS1_OAEP 是一种更加安全的填充方式,它使用了随机填充来提高安全性
PKCS1_OAEP 可以抵御选择密文攻击(CCA)和其他一些攻击方式,因此被认为更加安全
但是,PKCS1_OAEP 的性能略低于 PKCS1_v1_5,因为它需要进行更多的计算
"""
# 生成密钥对
def generate_keys():
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()
return private_key, public_key
# 加密消息message为bytes类型
def encrypt_message(public_key, message):
cipher = PKCS1_OAEP.new(RSA.import_key(public_key))
encrypted_message = base64.b64encode(cipher.encrypt(message))
print("Encrypted message:", encrypted_message.decode())
return encrypted_message
# 解密消息
def decrypt_message(private_key, encrypted_message):
decipher = PKCS1_OAEP.new(RSA.import_key(private_key))
decrypted_message = decipher.decrypt(base64.b64decode(encrypted_message))
print("Decrypted message:", decrypted_message.decode())
return decrypted_message.decode()
# 主程序
if __name__ == "__main__":
# 生成密钥对
private_key, public_key = generate_keys()
print(private_key)
print(public_key)
# 序列化公钥和私钥
# private_pem = private_key.private_bytes(
# encoding=serialization.Encoding.PEM,
# format=serialization.PrivateFormat.PKCS8,
# encryption_algorithm=serialization.NoEncryption()
# )
# public_pem = public_key.public_bytes(
# encoding=serialization.Encoding.PEM,
# format=serialization.PublicFormat.SubjectPublicKeyInfo
# )
# 打印公钥和私钥
print("Private Key:")
print(private_key.decode())
print("Public Key:")
print(public_key.decode())
# 待加密消息
message = b"Hello, RSA!"
# 加密消息
encrypted_message = encrypt_message(public_key, message)
print("Encrypted Message:")
print(encrypted_message)
# 解密消息
decrypted_message = decrypt_message(private_key, encrypted_message)
print("Decrypted Message:")
print(decrypted_message)

@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
import argparse
import base64
import json
import sys
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
"""
RSA 加密中,有两种常见的填充方式:PKCS1_v1_5 PKCS1_OAEP这两种填充方式在安全性和性能方面都有一些差异
PKCS1_v1_5 填充方式:
这是较早的 RSA 填充方式,相对简单且性能较好
但是它存在一些安全隐患,比如可能会受到选择密文攻击(Chosen Ciphertext Attack, CCA)
PKCS1_OAEP 填充方式:
PKCS1_OAEP 是一种更加安全的填充方式,它使用了随机填充来提高安全性
PKCS1_OAEP 可以抵御选择密文攻击(CCA)和其他一些攻击方式,因此被认为更加安全
但是,PKCS1_OAEP 的性能略低于 PKCS1_v1_5,因为它需要进行更多的计算
"""
# 生成密钥对
def generate_keys():
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()
return private_key, public_key
# 公钥加密消息message为bytes类型
def encrypt_message_pub(public_key, message):
cipher = PKCS1_OAEP.new(RSA.import_key(public_key))
encrypted_message = base64.b64encode(cipher.encrypt(message))
# print("Encrypted message:", encrypted_message.decode())
return encrypted_message
# 私钥解密消息
def decrypt_message_pri(private_key, encrypted_message):
decipher = PKCS1_OAEP.new(RSA.import_key(private_key))
decrypted_message = decipher.decrypt(base64.b64decode(encrypted_message))
# print("Decrypted message:", decrypted_message.decode())
return decrypted_message.decode()
def test():
# 生成密钥对
private_key, public_key = generate_keys()
print(private_key)
print(public_key)
# 打印公钥和私钥
print("Private Key:")
print(private_key.decode())
print("Public Key:")
print(public_key.decode())
# 待加密消息
# message = b"Hello, RSA!"
message = "Hello, RSA!".encode()
# 加密消息
encrypted_message = encrypt_message_pub(public_key, message)
print("Encrypted Message:")
print(encrypted_message)
# 解密消息
decrypted_message = decrypt_message_pri(private_key, encrypted_message)
print("Decrypted Message:")
print(decrypted_message)
def save_keys():
private_key, public_key = generate_keys()
with open("private_key.pem", "wb") as f:
f.write(private_key)
with open("public_key.pem", "wb") as f:
f.write(public_key)
# 主程序
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='manual to sign enterprise license')
parser.add_argument("-o", type=str,
help="operation type, "
"'t' is for function test, "
"'s' is to sign and save license, "
"'g' is to generate keys and save them, "
"'d' is to decrypt license",
required=True) # name, t/test, s/sign, g/generate key, d/decrypt
parser.add_argument("-c", type=str, help="enterprise's sys code, its something code like MD5") # code
parser.add_argument("-e", type=str, help="expire date, eg: 2035-01-01") # expire
args = parser.parse_args()
operation = args.o
if operation == "t": # test
test()
elif operation == "g": # generate keys and save
save_keys()
elif operation == "s": # sign and save license
code = args.c
expire = args.e
if not code or not expire:
print("sys code and expire date are required")
sys.exit(1)
pub_key = open("public_key.pem", "r").read()
license = encrypt_message_pub(pub_key.strip('\n').encode('utf-8'),
json.dumps({"sys_code": code, "expire_at": expire}).encode("utf-8"))
with open("license", "wb") as f:
f.write(license)
elif operation == "d": # decrypt license
private_key = open("private_key.pem", "r").read()
with open("license", "rb") as f:
license = f.read()
# 解密消息
body = decrypt_message_pri(private_key.strip('\n').encode('utf-8'), license)
json_body = json.loads(body)
print(json_body)

@ -4,10 +4,10 @@ import os
import socket import socket
import subprocess import subprocess
import uuid import uuid
from website import settings
def get_cpu_id(): def get_cpu_id():
p = subprocess.Popen(["dmidecode -t 4 | grep ID"], p = subprocess.Popen(["dmidecode -t 4 | grep ID | tail -1"],
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data = p.stdout data = p.stdout
lines = [] lines = []
@ -23,6 +23,75 @@ def get_cpu_id():
return lines return lines
def get_system_uuid():
p = subprocess.Popen(["dmidecode -s system-uuid"],
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data = p.stdout
lines = []
while True:
line = str(data.readline(), encoding="utf-8")
if line == '\n':
break
if line:
lines.append(line)
else:
break
print("system uuid {}".format(lines))
return lines
def get_system_manufacture():
p = subprocess.Popen(["dmidecode -s processor-manufacturer | tail -1"],
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data = p.stdout
lines = []
while True:
line = str(data.readline(), encoding="utf-8")
if line == '\n':
break
if line:
lines.append(line)
else:
break
return lines
def get_board_manufacturer():
p = subprocess.Popen(["dmidecode -s baseboard-manufacturer"],
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data = p.stdout
lines = []
while True:
line = str(data.readline(), encoding="utf-8")
if line == '\n':
break
if line:
lines.append(line)
else:
break
return lines
def get_board_serial_number():
p = subprocess.Popen(["dmidecode -s baseboard-serial-number"],
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data = p.stdout
lines = []
while True:
line = str(data.readline(), encoding="utf-8")
if line == '\n':
break
if line:
lines.append(line)
else:
break
return lines
def get_board_serialnumber(): def get_board_serialnumber():
p = subprocess.Popen(["dmidecode -t 2 | grep Serial"], p = subprocess.Popen(["dmidecode -t 2 | grep Serial"],
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -40,6 +109,37 @@ def get_board_serialnumber():
return lines return lines
def get_idntify_code_v2():
cpuid = get_cpu_id()
system_uuid = get_system_uuid()
system_manufacture = get_system_manufacture()
board_manufacturer = get_board_manufacturer()
board_serial_number = get_board_serial_number()
s = ""
if cpuid:
s += cpuid[0]["ID"]
print("cpuid: ", cpuid[0]["ID"])
if system_uuid:
print(system_uuid)
s += system_uuid[0].strip()
if system_manufacture:
print(system_manufacture)
s += system_manufacture[0].strip()
if board_manufacturer:
print(board_manufacturer)
s += board_manufacturer[0].strip()
if board_serial_number:
print(board_serial_number)
s += board_serial_number[0].strip()
s += settings.system_salt
# system_salt = "5bVQmI0ATh+QITf75WgVchT6TPN1DEOasSmrtMcTsPQ="
# s += system_salt
code = hashlib.sha256(s.encode("utf8")).hexdigest()
return code
def get_identify_code(): def get_identify_code():
mac = uuid.UUID(int=uuid.getnode()).hex[-12:] mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
mac_addr = ":".join([mac[e:e + 2] for e in range(0, 11, 2)]) mac_addr = ":".join([mac[e:e + 2] for e in range(0, 11, 2)])
@ -65,14 +165,6 @@ def get_identify_code():
return code return code
def get_system_uuid():
# 获取系统uuid
# 这个 UUID 是与硬件相关的,因此即使在 Docker 容器中,它也应该是唯一的,可以用来标识宿主机,而不是容器本身。
with open("/sys/class/dmi/id/product_uuid", "r") as f:
host_uuid = f.read().strip()
return host_uuid
def get_docker_container_id(): def get_docker_container_id():
# 获取当前 Docker 容器的 ID # 获取当前 Docker 容器的 ID
cmd = "cat /proc/self/cgroup" cmd = "cat /proc/self/cgroup"
@ -84,3 +176,7 @@ def get_docker_container_id():
else: else:
container_id = container_message.strip().split("docker/")[-1] container_id = container_message.strip().split("docker/")[-1]
return container_id return container_id
if __name__ == "__main__":
print(get_idntify_code_v2())
Loading…
Cancel
Save