mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 19:10:47 +02:00
Policies: enforce on upload or export (#6614)
Follow-up to #6604 (merged). Builds the Security policy out so it actually enforces, driven from the editor. ## What it does - **Run on upload or export** — a single choice in the wizard: enforce when a file is uploaded, or just before it's exported. - **Output** — enforced result is a **new version** of the file (default) or a **new file**, with optional filename prefix/suffix/auto-number ("Output filename" subsection; auto-number only for new files). - **Export enforcement** — exporting an export-mode file runs the policy first and downloads the enforced result; never hard-blocks (on failure the original downloads). For new-version policies the in-editor file is versioned too. Covers every export path incl. multi-file ZIP. A toast (glowing in the policy's accent while it runs) reports progress and fades after ~10s. - **Affordances** — a freshly enforced file briefly glows its policy accent and carries a shield badge. - **Config tidy-up** — removed the unwired Security setting fields + the wizard's review step; "Upgrade to enterprise" on locked categories; category accent in the detail/wizard headers. ## Notes - Builds on the manual-only (client-driven) policy model from #6587 (`trigger: null`, metadata in `output.options`), adding the `runOn` field + export-time enforcement. - The page-editor merge-export (no single source file) enforces + downloads but doesn't version in place. ## Verification typecheck (core + proprietary), eslint, prettier; proprietary suite (105) green; flows checked in-app.
This commit is contained in:
@@ -2,6 +2,8 @@ import { StirlingFileStub } from "@app/types/fileContext";
|
||||
import { fileStorage } from "@app/services/fileStorage";
|
||||
import { zipFileService } from "@app/services/zipFileService";
|
||||
import { downloadFile } from "@app/services/downloadService";
|
||||
import { downloadFileWithPolicy } from "@app/services/exportWithPolicy";
|
||||
import { enforceExportPolicies } from "@app/services/policyExport";
|
||||
|
||||
/**
|
||||
* Downloads a blob as a file using browser download API
|
||||
@@ -27,10 +29,11 @@ export async function downloadFileFromStorage(
|
||||
throw new Error(`File "${file.name}" not found in storage`);
|
||||
}
|
||||
|
||||
await downloadFile({
|
||||
await downloadFileWithPolicy({
|
||||
data: stirlingFile,
|
||||
filename: stirlingFile.name,
|
||||
localPath: file.localFilePath,
|
||||
fileId: file.id,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -59,15 +62,15 @@ export async function downloadFilesAsZip(
|
||||
throw new Error("No files provided for ZIP download");
|
||||
}
|
||||
|
||||
// Convert stored files to File objects
|
||||
// Convert stored files to File objects (tracking ids so export policies can
|
||||
// version the in-editor file).
|
||||
const filesToZip: File[] = [];
|
||||
const fileIds: (string | undefined)[] = [];
|
||||
for (const fileWithUrl of files) {
|
||||
const lookupKey = fileWithUrl.id;
|
||||
const stirlingFile = await fileStorage.getStirlingFile(lookupKey);
|
||||
|
||||
const stirlingFile = await fileStorage.getStirlingFile(fileWithUrl.id);
|
||||
if (stirlingFile) {
|
||||
// StirlingFile is already a File object!
|
||||
filesToZip.push(stirlingFile);
|
||||
fileIds.push(fileWithUrl.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +78,9 @@ export async function downloadFilesAsZip(
|
||||
throw new Error("No valid files found in storage for ZIP download");
|
||||
}
|
||||
|
||||
// Enforce any export-triggered policy on each PDF before they're zipped.
|
||||
const enforced = await enforceExportPolicies(filesToZip, fileIds);
|
||||
|
||||
// Generate default filename if not provided
|
||||
const finalZipFilename =
|
||||
zipFilename ||
|
||||
@@ -82,7 +88,7 @@ export async function downloadFilesAsZip(
|
||||
|
||||
// Create and download ZIP
|
||||
const { zipFile } = await zipFileService.createZipFromFiles(
|
||||
filesToZip,
|
||||
enforced,
|
||||
finalZipFilename,
|
||||
);
|
||||
await downloadFile({ data: zipFile, filename: finalZipFilename });
|
||||
@@ -125,7 +131,7 @@ export async function downloadFiles(
|
||||
* @param filename - Optional custom filename
|
||||
*/
|
||||
export function downloadFileObject(file: File, filename?: string): void {
|
||||
void downloadFile({ data: file, filename: filename || file.name });
|
||||
void downloadFileWithPolicy({ data: file, filename: filename || file.name });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user