Compare commits

..

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] faa38294d6 Upgrade multer from 1.4.5-lts.1 to 2.1.1 to fix security vulnerabilities
Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
2026-03-07 13:40:32 +00:00
copilot-swe-agent[bot] e8abaeb83c Fix Python relative path issue: correct CWD for subdirectory scripts
Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
2026-03-07 13:35:25 +00:00
copilot-swe-agent[bot] bf7350f10b Initial plan 2026-03-07 13:27:02 +00:00
11 changed files with 251 additions and 742 deletions
-13
View File
@@ -374,19 +374,6 @@ export default (app: Router) => {
},
);
route.get(
'/notify-log',
async (req: Request, res: Response, next: NextFunction) => {
try {
const systemService = Container.get(SystemService);
const data = await systemService.getNotifyLog();
res.send({ code: 200, data });
} catch (e) {
return next(e);
}
},
);
route.delete(
'/log',
async (req: Request, res: Response, next: NextFunction) => {
-15
View File
@@ -28,12 +28,6 @@ export enum AuthDataType {
'removeLogFrequency' = 'removeLogFrequency',
'systemConfig' = 'systemConfig',
'authConfig' = 'authConfig',
'notifyLog' = 'notifyLog',
}
export enum NotifyStatus {
'success',
'fail',
}
export interface SystemConfigInfo {
@@ -55,14 +49,6 @@ export interface LoginLogInfo {
status?: LoginStatus;
}
export interface NotifyLogInfo {
timestamp?: number;
title?: string;
content?: string;
status?: NotifyStatus;
notifyType?: string;
}
export interface TokenInfo {
value: string;
timestamp: number;
@@ -95,7 +81,6 @@ export interface AuthInfo {
export type SystemModelInfo = SystemConfigInfo &
Partial<NotificationInfo> &
LoginLogInfo &
Partial<NotifyLogInfo> &
Partial<AuthInfo>;
export interface SystemInstance
-37
View File
@@ -30,8 +30,6 @@ import {
SystemInstance,
SystemModel,
SystemModelInfo,
NotifyStatus,
NotifyLogInfo,
} from '../data/system';
import taskLimit from '../shared/pLimit';
import NotificationService from './notify';
@@ -391,34 +389,11 @@ export default class SystemService {
if (notificationInfo && typeString) {
notificationInfo.type = typeString;
}
let notifyType: string | undefined;
if (notificationInfo?.type) {
notifyType = typeString || (notificationInfo.type as string);
} else {
try {
const notifConfig = await this.getDb({ type: AuthDataType.notification });
notifyType = notifConfig.info?.type as string | undefined;
} catch (e) {}
}
const isSuccess = await this.notificationService.notify(
title,
content,
notificationInfo,
);
await SystemModel.create({
type: AuthDataType.notifyLog,
info: {
timestamp: Date.now(),
title,
content,
status: isSuccess ? NotifyStatus.success : NotifyStatus.fail,
notifyType,
},
});
if (isSuccess) {
return { code: 200, message: '通知发送成功' };
} else {
@@ -426,18 +401,6 @@ export default class SystemService {
}
}
public async getNotifyLog(): Promise<Array<NotifyLogInfo>> {
const docs = await SystemModel.findAll({
where: { type: AuthDataType.notifyLog },
order: [['id', 'DESC']],
});
if (docs.length > 200) {
const ids = docs.slice(200).map((x) => x.id!);
await SystemModel.destroy({ where: { id: ids } });
}
return docs.slice(0, 200).map((x) => ({ ...x.info, id: x.id }));
}
public async run({ command, logPath }: { command: string; logPath?: string }, callback: TaskCallbacks) {
if (!command.startsWith(TASK_COMMAND)) {
command = `${TASK_COMMAND} ${command}`;
+1 -1
View File
@@ -84,6 +84,6 @@ COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
WORKDIR ${QL_DIR}
HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
CMD curl -sf --noproxy '*' http://127.0.0.1:${QlPort:-5700}/api/health || exit 1
CMD curl -sf --noproxy '*' http://127.0.0.1:5700/api/health || exit 1
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
+1 -1
View File
@@ -84,6 +84,6 @@ COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
WORKDIR ${QL_DIR}
HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
CMD curl -sf --noproxy '*' http://127.0.0.1:${QlPort:-5700}/api/health || exit 1
CMD curl -sf --noproxy '*' http://127.0.0.1:5700/api/health || exit 1
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
+2 -2
View File
@@ -79,7 +79,7 @@
"lodash": "^4.17.21",
"multer": "2.1.1",
"node-schedule": "^2.1.0",
"nodemailer": "^8.0.1",
"nodemailer": "^6.9.16",
"p-queue-cjs": "7.3.4",
"@bufbuild/protobuf": "^2.10.0",
"ps-tree": "^1.2.0",
@@ -118,7 +118,7 @@
"@types/js-yaml": "^4.0.5",
"@types/jsonwebtoken": "^8.5.8",
"@types/lodash": "^4.14.185",
"@types/multer": "^1.4.7",
"@types/multer": "^2.0.0",
"@types/node": "^17.0.21",
"@types/node-schedule": "^1.3.2",
"@types/nodemailer": "^6.4.4",
+245 -546
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -92,7 +92,7 @@ run_normal() {
cd $dir_scripts
local relative_path="${file_param%/*}"
if [[ ${file_param} != /* ]] && [[ ! -z ${relative_path} ]] && [[ ${file_param} =~ "/" ]]; then
if [[ ! -z ${relative_path} ]] && [[ ${file_param} =~ "/" ]]; then
cd ${relative_path}
file_param=${file_param/$relative_path\//}
fi
+1 -1
View File
@@ -42,7 +42,7 @@ def run():
os.environ["PYTHONPATH"] = prev_pythonpath
split_str = "__sitecustomize__"
file_name = sys.argv[0].replace(f"{os.getenv('dir_scripts')}/", "")
file_name = os.path.abspath(sys.argv[0]).replace(f"{os.getenv('dir_scripts')}/", "")
# 创建临时文件路径
temp_file = f"/tmp/env_{os.getpid()}.json"
-22
View File
@@ -26,7 +26,6 @@ import {
} from '@ant-design/icons';
import SecuritySettings from './security';
import LoginLog from './loginLog';
import NotifyLog from './notifyLog';
import NotificationSetting from './notification';
import Other from './other';
import About from './about';
@@ -126,7 +125,6 @@ const Setting = () => {
const [editedApp, setEditedApp] = useState<any>();
const [tabActiveKey, setTabActiveKey] = useState('security');
const [loginLogData, setLoginLogData] = useState<any[]>([]);
const [notifyLogData, setNotifyLogData] = useState<any[]>([]);
const [notificationInfo, setNotificationInfo] = useState<any>();
const containergRef = useRef<HTMLDivElement>(null);
const [height, setHeight] = useState<number>(0);
@@ -255,8 +253,6 @@ const Setting = () => {
getApps();
} else if (activeKey === 'login') {
getLoginLog();
} else if (activeKey === 'notifylog') {
getNotifyLog();
} else if (activeKey === 'notification') {
getNotification();
}
@@ -275,19 +271,6 @@ const Setting = () => {
});
};
const getNotifyLog = () => {
request
.get(`${config.apiPrefix}system/notify-log`)
.then(({ code, data }) => {
if (code === 200) {
setNotifyLogData(data);
}
})
.catch((error: any) => {
console.log(error);
});
};
useEffect(() => {
if (isDemoEnv) {
getApps();
@@ -361,11 +344,6 @@ const Setting = () => {
label: intl.get('登录日志'),
children: <LoginLog height={height} data={loginLogData} />,
},
{
key: 'notifylog',
label: intl.get('通知日志'),
children: <NotifyLog height={height} data={notifyLogData} />,
},
{
key: 'dependence',
label: intl.get('依赖设置'),
-103
View File
@@ -1,103 +0,0 @@
import intl from 'react-intl-universal';
import React from 'react';
import { Table, Tag } from 'antd';
import dayjs from 'dayjs';
interface NotifyLogItem {
id?: number;
timestamp?: number;
title?: string;
content?: string;
status?: number;
notifyType?: string;
}
const NotifyStatusLabel: Record<number, string> = {
0: '成功',
1: '失败',
};
const NotifyStatusColor: Record<number, string> = {
0: 'success',
1: 'error',
};
const columns = [
{
title: intl.get('序号'),
width: 50,
render: (text: string, record: any, index: number) => {
return index + 1;
},
},
{
title: intl.get('发送时间'),
dataIndex: 'timestamp',
key: 'timestamp',
width: 160,
render: (text: string, record: any) => {
return dayjs(record.timestamp).format('YYYY-MM-DD HH:mm:ss');
},
},
{
title: intl.get('标题'),
dataIndex: 'title',
key: 'title',
width: 200,
},
{
title: intl.get('内容'),
dataIndex: 'content',
key: 'content',
render: (text: string) => {
if (!text) return '';
return text.length > 100 ? text.slice(0, 100) + '...' : text;
},
},
{
title: intl.get('推送渠道'),
dataIndex: 'notifyType',
key: 'notifyType',
width: 120,
},
{
title: intl.get('发送状态'),
dataIndex: 'status',
key: 'status',
width: 90,
render: (text: string, record: NotifyLogItem) => {
const statusKey = record.status ?? 1;
return (
<Tag
color={NotifyStatusColor[statusKey]}
style={{ marginRight: 0 }}
>
{intl.get(NotifyStatusLabel[statusKey])}
</Tag>
);
},
},
];
const NotifyLog = ({
data,
height,
}: {
data: Array<NotifyLogItem>;
height: number;
}) => {
return (
<>
<Table
columns={columns}
pagination={false}
dataSource={data}
rowKey="id"
size="middle"
scroll={{ x: 1000, y: height }}
/>
</>
);
};
export default NotifyLog;