fix server - agent

This commit is contained in:
2026-05-27 08:37:47 +07:00
parent 13765e58d2
commit b0443d5950
13 changed files with 170 additions and 11 deletions

View File

@@ -844,6 +844,24 @@ function normalizeApplicationStatus(value) {
return ['Draft', 'Released', 'Archived'].includes(value) ? value : 'Draft';
}
function normalizeApplicationOpenUrl(value) {
const text = String(value || '').trim();
if (!text) return '';
const candidate = /^https?:\/\//i.test(text) ? text : `http://${text}`;
try {
const parsed = new URL(candidate);
if (!['http:', 'https:'].includes(parsed.protocol) || !parsed.hostname) {
return null;
}
return parsed.href.replace(/\/+$/, '');
} catch {
return null;
}
}
function isInstallerIdentifier(value) {
return installerIdentifierPattern.test(String(value || '').trim());
}
@@ -1297,7 +1315,8 @@ app.get('/api/apps', asyncRoute(async (req, res) => {
appName: application.name,
version: application.version,
status: application.status,
packageCount: application.packageCount
packageCount: application.packageCount,
openUrl: application.openUrl
}))
});
}));
@@ -1316,6 +1335,7 @@ app.get('/api/apps/:appCode', asyncRoute(async (req, res) => {
version: application.version,
status: application.status,
packageCount: application.packageCount,
openUrl: application.openUrl,
packages: application.packages
});
}));
@@ -1839,7 +1859,7 @@ app.get('/applications', asyncRoute(async (req, res) => {
app.get('/applications/export.csv', asyncRoute(async (req, res) => {
const applications = await repository.listApplications();
const rows = [
['AppCode', 'AppName', 'AppVersion', 'Status', 'CreatedAt', 'CreatedBy', 'PackageCount', 'Packages', 'Notes'],
['AppCode', 'AppName', 'AppVersion', 'Status', 'CreatedAt', 'CreatedBy', 'PackageCount', 'Packages', 'OpenUrl', 'Notes'],
...applications.map((application) => [
application.code,
application.name,
@@ -1849,6 +1869,7 @@ app.get('/applications/export.csv', asyncRoute(async (req, res) => {
application.createdBy,
application.packageCount,
application.packages.map((packageItem) => `${packageItem.code}@${packageItem.selectedVersion}`).join('; '),
application.openUrl,
application.notes
])
];
@@ -1860,12 +1881,18 @@ app.post('/applications', asyncRoute(async (req, res) => {
const appCode = String(req.body.appCode || '').trim();
const appName = String(req.body.appName || '').trim();
const appVersion = String(req.body.appVersion || '').trim();
const openUrl = normalizeApplicationOpenUrl(req.body.openUrl);
if (!appCode || !appName || !appVersion) {
redirectWithNotice(res, '/builder', 'warning', 'Vui lòng nhập App code, App name và App version.');
return;
}
if (openUrl === null) {
redirectWithNotice(res, '/builder', 'warning', 'Open URL khong hop le. Hay nhap URL http/https, vi du http://127.0.0.1:5000.');
return;
}
if (!isInstallerIdentifier(appCode)) {
redirectWithNotice(res, '/builder', 'warning', `App code khong hop le. ${installerIdentifierHint}`);
return;
@@ -1882,6 +1909,7 @@ app.post('/applications', asyncRoute(async (req, res) => {
appName,
appVersion,
notes: req.body.notes,
openUrl,
status: normalizeApplicationStatus(req.body.status),
createdByUserId: req.currentUser.id,
packages: getSelectedApplicationPackages(req.body)
@@ -1904,12 +1932,18 @@ app.post('/applications/:id/edit', asyncRoute(async (req, res) => {
const appCode = String(req.body.appCode || '').trim();
const appName = String(req.body.appName || '').trim();
const appVersion = String(req.body.appVersion || '').trim();
const openUrl = normalizeApplicationOpenUrl(req.body.openUrl);
if (!appCode || !appName || !appVersion) {
redirectWithNotice(res, returnTo, 'warning', 'Vui lòng nhập App code, App name và App version.');
return;
}
if (openUrl === null) {
redirectWithNotice(res, returnTo, 'warning', 'Open URL khong hop le. Hay nhap URL http/https, vi du http://127.0.0.1:5000.');
return;
}
if (!isInstallerIdentifier(appCode)) {
redirectWithNotice(res, returnTo, 'warning', `App code khong hop le. ${installerIdentifierHint}`);
return;
@@ -1927,6 +1961,7 @@ app.post('/applications/:id/edit', asyncRoute(async (req, res) => {
appName,
appVersion,
notes: req.body.notes,
openUrl,
status: normalizeApplicationStatus(req.body.status),
packages: getSelectedApplicationPackages(req.body)
});