fix: harden upload cancellation and audit logging

Preserve pre-start and batch cancellation requests, reject late upload success after cancellation, and wait for cancellation acknowledgements before removing queue entries.

Separate formatted link logs from privacy-safe source cleanup and upload plan audits, persist audit fallback paths, redact support bundles, and expose audit diagnostics safely.

Improve queue selection and destructive-action clarity, show the Settings save action only while changes are pending, and add regression coverage for all updated behavior.
This commit is contained in:
Sucukdeluxe
2026-08-13 14:31:46 +02:00
parent 59cead80c6
commit bfb3a39fed
20 changed files with 733 additions and 101 deletions
+46 -1
View File
@@ -28,7 +28,52 @@
return { hoster, fileName, ts };
}
const api = { formatUploadLogLine, parseUploadLogLine };
function summarizeBatchPlan(payload) {
const source = payload && typeof payload === 'object' ? payload : {};
const jobs = Array.isArray(source.jobs) ? source.jobs : [];
if (jobs.length > 0) {
const files = new Set();
const destinations = new Set();
let plannedUploadCount = 0;
for (const job of jobs) {
if (!job || typeof job !== 'object') continue;
const file = typeof job.file === 'string' ? job.file.trim() : '';
const hoster = typeof job.hoster === 'string' ? job.hoster.trim() : '';
if (!file || !hoster) continue;
files.add(file);
destinations.add(hoster);
plannedUploadCount++;
}
return {
fileCount: files.size,
destinationCount: destinations.size,
plannedUploadCount
};
}
const files = new Set((Array.isArray(source.files) ? source.files : []).filter(value => typeof value === 'string' && value.trim()));
const destinations = new Set((Array.isArray(source.hosters) ? source.hosters : []).filter(value => typeof value === 'string' && value.trim()));
return {
fileCount: files.size,
destinationCount: destinations.size,
plannedUploadCount: files.size * destinations.size
};
}
function formatUploadPlanLogLine(date, plan, mode) {
const inputDate = date instanceof Date && !Number.isNaN(date.getTime()) ? date : new Date();
const source = plan && typeof plan === 'object' ? plan : {};
const count = value => Number.isFinite(Number(value)) ? Math.max(0, Math.floor(Number(value))) : 0;
return `# UPLOAD-PLAN ${JSON.stringify({
timestamp: inputDate.toISOString(),
mode: mode === 'add' ? 'add' : 'start',
fileCount: count(source.fileCount),
destinationCount: count(source.destinationCount),
plannedUploadCount: count(source.plannedUploadCount)
})}\r\n`;
}
const api = { formatUploadLogLine, parseUploadLogLine, summarizeBatchPlan, formatUploadPlanLogLine };
if (typeof module !== 'undefined' && module.exports) module.exports = api;
else if (root) root.UploadLog = api;
})(typeof window !== 'undefined' ? window : this);