Compare commits

...

8 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] f099bd8e05 Remove unreachable code and ensure consistent escaping for both Debian and Alpine
Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
2025-12-22 14:53:59 +00:00
copilot-swe-agent[bot] 6f7a54a614 Fix incomplete sanitization - properly escape backslashes in URL escaping
Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
2025-12-22 14:50:31 +00:00
copilot-swe-agent[bot] 6397415d7f Address code review feedback - improve distribution detection and error handling
Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
2025-12-22 14:47:23 +00:00
copilot-swe-agent[bot] 8dc98a6c0e Add Debian/Armbian support to Linux mirror update functionality
Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
2025-12-22 14:43:15 +00:00
copilot-swe-agent[bot] 5c151f93c5 Initial plan 2025-12-22 14:37:23 +00:00
Copilot c61d1aa828 Fix enum value 0 causing type filter to fail for NodeJS dependencies (#2869)
* Initial plan

* Fix: Prevent Python3 dependencies from appearing in NodeJs tab

Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
2025-12-15 18:21:14 +08:00
whyour 33fa3aca99 更新版本 2.20.0 2025-12-11 01:53:17 +08:00
whyour c772fc9527 修复脚本调试保存文件错误 2025-12-11 01:52:47 +08:00
6 changed files with 147 additions and 29 deletions
+1 -1
View File
@@ -164,7 +164,7 @@ jobs:
flavor: |
latest=false
tags: |
type=ref,event=branch,enable=${{ github.ref != format('refs/heads/{0}', 'master') }}
type=ref,event=branch,enable=${{ github.ref == format('refs/heads/{0}', 'develop') }}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }}
type=raw,value=${{ steps.version.outputs.version }},enable=${{ github.ref == format('refs/heads/{0}', 'master') }}
type=semver,pattern={{version}}
+1
View File
@@ -176,6 +176,7 @@ export default (app: Router) => {
path,
`${originFilename.replace(/\//g, '')}`,
);
await fs.mkdir(path, { recursive: true });
const filePath = join(path, `${filename.replace(/\//g, '')}`);
const fileExists = await fileExist(filePath);
if (fileExists) {
+1 -1
View File
@@ -107,7 +107,7 @@ export default class DependenceService {
query: any = {},
): Promise<Dependence[]> {
let condition = query;
if (DependenceTypes[type]) {
if (type && DependenceTypes[type] !== undefined) {
condition.type = DependenceTypes[type];
}
if (status) {
+97 -17
View File
@@ -218,28 +218,108 @@ export default class SystemService {
...oDoc,
info: { ...oDoc.info, ...info },
});
let defaultDomain = 'https://dl-cdn.alpinelinux.org';
let targetDomain = 'https://dl-cdn.alpinelinux.org';
if (os.platform() !== 'linux') {
return;
}
const content = await fs.promises.readFile('/etc/apk/repositories', {
encoding: 'utf-8',
});
const domainMatch = content.match(/(http.*)\/alpine\/.*/);
if (domainMatch) {
defaultDomain = domainMatch[1];
let command = '';
// Check if this is a Debian-based system (including Armbian)
// Check for both sources.list and debian_version for more reliable detection
const hasAptSourcesList = await fs.promises.access('/etc/apt/sources.list')
.then(() => true)
.catch(() => false);
const hasDebianVersion = await fs.promises.access('/etc/debian_version')
.then(() => true)
.catch(() => false);
const isDebianBased = hasAptSourcesList || hasDebianVersion;
if (isDebianBased) {
// Handle Debian/Ubuntu/Armbian systems
let defaultDomain = '';
let targetDomain = info.linuxMirror || '';
try {
// Read the current sources.list
const content = await fs.promises.readFile('/etc/apt/sources.list', {
encoding: 'utf-8',
});
// Match the first deb line to extract the current mirror
// Note: This assumes all mirrors in sources.list use the same base URL
// If multiple different mirrors are configured, only the first one will be replaced
const debMatch = content.match(/^deb\s+(https?:\/\/[^\s]+)/m);
if (debMatch) {
defaultDomain = debMatch[1];
}
if (defaultDomain && targetDomain) {
// Sanitize and escape special characters for sed
// Escape backslashes first, then other special characters
const escapedDefault = defaultDomain
.replace(/\\/g, '\\\\') // Escape backslashes first
.replace(/\//g, '\\/') // Escape forward slashes
.replace(/\./g, '\\.'); // Escape dots
const escapedTarget = targetDomain
.replace(/\\/g, '\\\\') // Escape backslashes first
.replace(/\//g, '\\/'); // Escape forward slashes
// Replace mirror URL in main sources.list
command = `sed -i 's/${escapedDefault}/${escapedTarget}/g' /etc/apt/sources.list`;
// Also update sources.list.d if it exists
command += ` && if [ -d /etc/apt/sources.list.d ]; then find /etc/apt/sources.list.d -type f \\( -name "*.list" -o -name "*.sources" \\) -exec sed -i 's/${escapedDefault}/${escapedTarget}/g' {} \\;; fi`;
// Update package lists
command += ` && apt-get update`;
} else if (!defaultDomain && targetDomain) {
// Cannot detect current mirror, log warning
this.logger.warn('Unable to detect current mirror from /etc/apt/sources.list. Mirror update skipped.');
this.sockService.sendMessage({
type: 'updateLinuxMirror',
message: 'Warning: Unable to detect current mirror. Please manually configure /etc/apt/sources.list',
});
}
} catch (error) {
this.logger.error('Failed to read /etc/apt/sources.list', error);
}
} else {
// Handle Alpine Linux systems
let defaultDomain = 'https://dl-cdn.alpinelinux.org';
let targetDomain = 'https://dl-cdn.alpinelinux.org';
try {
const content = await fs.promises.readFile('/etc/apk/repositories', {
encoding: 'utf-8',
});
const domainMatch = content.match(/(http.*)\/alpine\/.*/);
if (domainMatch) {
defaultDomain = domainMatch[1];
}
if (info.linuxMirror) {
targetDomain = info.linuxMirror;
}
// Sanitize and escape special characters for sed
// Escape backslashes first, then other special characters
command = `sed -i 's/${defaultDomain
.replace(/\\/g, '\\\\') // Escape backslashes first
.replace(/\//g, '\\/') // Escape forward slashes
.replace(/\./g, '\\.')}/${targetDomain
.replace(/\\/g, '\\\\') // Escape backslashes first
.replace(/\//g, '\\/')}/g' /etc/apk/repositories && apk update -f`;
} catch (error) {
this.logger.error('Failed to read /etc/apk/repositories', error);
}
}
if (info.linuxMirror) {
targetDomain = info.linuxMirror;
if (!command) {
this.sockService.sendMessage({
type: 'updateLinuxMirror',
message: 'No supported package manager found or mirror not configured',
});
return;
}
const command = `sed -i 's/${defaultDomain.replace(
/\//g,
'\\/',
)}/${targetDomain.replace(
/\//g,
'\\/',
)}/g' /etc/apk/repositories && apk update -f`;
this.scheduleService.runTask(
command,
+1 -1
View File
@@ -16,7 +16,7 @@ const SaveModal = ({
const handleOk = async (values: any) => {
setLoading(true);
const payload = { ...file, ...values, originFilename: file.title };
const payload = { ...values, originFilename: file.title, content: file.content };
request
.post(`${config.apiPrefix}scripts`, payload)
.then(({ code, data }) => {
+46 -9
View File
@@ -1,10 +1,47 @@
version: 2.19.2
changeLogLink: https://t.me/jiao_long/431
publishTime: 2025-06-27 23:59
version: 2.20.0
changeLogLink: https://t.me/jiao_long/432
publishTime: 2025-12-10 01:05
changeLog: |
1. 备份数据支持选择模块,支持清除依赖缓存
2. QLAPI 和 openapi 的 systemNotify 支持自定义通知类型和参数
3. ntfy 增加可选的认证与用户动作,感谢 https://github.com/liheji
4. 修复取消安装依赖
5. 修复环境变量过大解析报错
6. 修改服务启动方式
1. 定时任务(cron / task)相关的大量修复 & 增强
修复 cron 解析错误(修复 parse cron / 升级 cron-parser
修复集群模式下定时任务可能不执行(race condition
定时任务支持订阅筛选
定时任务支持排序调整
定时任务支持自定义日志文件或无日志
修复任务实例默认值
任务支持单实例 / 多实例模式
修复 task 命令软链可能失败问题
2. 日志系统相关的大更新
修复日志目录逻辑
修复 pm2 日志目录
优化日志写入(stream pooling
3. 环境变量(env)系统的改进与修复
修复环境变量复制到剪贴板时可能失败
添加环境变量“置顶”功能
修复 QlPort 与 QlGrpcPort 环境变量在 host network 模式下被忽略
增加全局 SSH 私钥配置
4. Docker / 非 root 用户 / Alpine 兼容性增强
新增非 root Docker 用户支持,自动初始化命令
修复 Alpine 容器 DNS 解析失败(设置 ndots:0
修复 PM2 在 ARM 路由器(Node.js 不兼容)上的启动失败
移除 nginx(可能是考虑更轻量的镜像运行)
5. API 安全与校验增强
Dependencies GET endpoint 增加校验
Script API routes 增加输入校验
修复 JWT 认证问题
Feishu 机器人通知增加签名校验
QLAPI 增加 cron task 管理功能
修复 URIError(错误 cookie 导致白屏)
6. 系统设置
新增多终端/多平台的并发登录会话支持