mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-09-04 16:58:05 +02:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3cb8d575c | ||
|
|
0c295961c3 | ||
|
|
5fbd1fc6f2 | ||
|
|
3f4007d564 |
+23
-32
@@ -39,27 +39,9 @@ const mime = {
|
||||
};
|
||||
|
||||
function contentType(filePath) {
|
||||
// Files under /.well-known/ are JSON by convention (WebAuthn, apple-app-site-association, etc.)
|
||||
// and are extensionless, so explicitly set application/json there.
|
||||
const rel = path.relative(root, filePath).split(path.sep).join("/");
|
||||
if (rel.startsWith(".well-known/")) {
|
||||
return "application/json; charset=utf-8";
|
||||
}
|
||||
return mime[path.extname(filePath).toLowerCase()] || "application/octet-stream";
|
||||
}
|
||||
|
||||
function applyWellKnownCors(req, res, filePath) {
|
||||
const rel = path.relative(root, filePath).split(path.sep).join("/");
|
||||
if (!rel.startsWith(".well-known/")) return;
|
||||
// .well-known/* must be readable cross-origin (e.g. WebAuthn related-origins
|
||||
// requests come from any RP host). Echo the request origin when present so
|
||||
// credentialed fetches still work; otherwise allow all.
|
||||
const origin = req.headers.origin;
|
||||
res.setHeader("Access-Control-Allow-Origin", origin || "*");
|
||||
res.setHeader("Vary", "Origin");
|
||||
res.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
|
||||
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
||||
}
|
||||
|
||||
function safeJoin(reqPath) {
|
||||
let decoded;
|
||||
@@ -96,23 +78,25 @@ function streamFile(req, res, filePath, stats) {
|
||||
"Last-Modified": stats.mtime.toUTCString(),
|
||||
"Cache-Control": cacheControl(filePath)
|
||||
};
|
||||
applyWellKnownCors(req, res, filePath);
|
||||
if (req.method === "HEAD") {
|
||||
res.writeHead(200, headers);
|
||||
return res.end();
|
||||
}
|
||||
const stream = fs.createReadStream(filePath);
|
||||
stream.on("error", () => {
|
||||
stream.on("error", (err) => {
|
||||
console.error("Stream error:", err);
|
||||
if (!res.headersSent) {
|
||||
res.writeHead(500, { "Content-Type": "text/plain" });
|
||||
return res.end("Internal Server Error");
|
||||
res.end("Internal Server Error");
|
||||
} else {
|
||||
res.destroy();
|
||||
}
|
||||
res.destroy();
|
||||
});
|
||||
res.on("close", () => {
|
||||
if (!stream.destroyed) stream.destroy();
|
||||
});
|
||||
res.on("error", () => {
|
||||
res.on("error", (err) => {
|
||||
console.error("Response error:", err);
|
||||
if (!stream.destroyed) stream.destroy();
|
||||
});
|
||||
res.writeHead(200, headers);
|
||||
@@ -122,7 +106,7 @@ function streamFile(req, res, filePath, stats) {
|
||||
function sendIndex(req, res) {
|
||||
const indexPath = path.join(root, "index.html");
|
||||
fs.stat(indexPath, (err, stats) => {
|
||||
if (err || !stats.isFile()) {
|
||||
if (err || !stats || !stats.isFile()) {
|
||||
res.writeHead(500, { "Content-Type": "text/plain" });
|
||||
return res.end("index.html not found");
|
||||
}
|
||||
@@ -133,14 +117,15 @@ function sendIndex(req, res) {
|
||||
const server = http.createServer((req, res) => {
|
||||
if (req.method === "OPTIONS") {
|
||||
const filePath = safeJoin(req.url || "/");
|
||||
if (filePath) applyWellKnownCors(req, res, filePath);
|
||||
res.writeHead(204);
|
||||
return res.end();
|
||||
}
|
||||
|
||||
if (req.method !== "GET" && req.method !== "HEAD") {
|
||||
res.writeHead(405, { Allow: "GET, HEAD, OPTIONS" });
|
||||
return res.end();
|
||||
}
|
||||
|
||||
const reqUrl = req.url || "/";
|
||||
const filePath = safeJoin(reqUrl);
|
||||
if (!filePath) {
|
||||
@@ -149,21 +134,27 @@ const server = http.createServer((req, res) => {
|
||||
}
|
||||
|
||||
fs.stat(filePath, (err, stats) => {
|
||||
if (!err && stats.isFile()) {
|
||||
if (err) {
|
||||
// No file at this path → SPA fallback to index.html
|
||||
return sendIndex(req, res);
|
||||
}
|
||||
if (stats.isFile()) {
|
||||
return streamFile(req, res, filePath, stats);
|
||||
}
|
||||
if (!err && stats.isDirectory()) {
|
||||
if (stats.isDirectory()) {
|
||||
const indexInDir = path.join(filePath, "index.html");
|
||||
return fs.stat(indexInDir, (e, s) => {
|
||||
if (!e && s.isFile()) return streamFile(req, res, indexInDir, s);
|
||||
return fs.stat(indexInDir, (dirErr, dirStats) => {
|
||||
if (!dirErr && dirStats && dirStats.isFile()) {
|
||||
return streamFile(req, res, indexInDir, dirStats);
|
||||
}
|
||||
return sendIndex(req, res);
|
||||
});
|
||||
}
|
||||
// No file at this path → SPA fallback to index.html
|
||||
sendIndex(req, res);
|
||||
// Path exists but is neither file nor directory → SPA fallback
|
||||
return sendIndex(req, res);
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(port, host, () => {
|
||||
console.log(`Serving ${root} on http://${host}:${port}`);
|
||||
});
|
||||
});
|
||||
@@ -32,7 +32,12 @@ const PrefillWidgets = ({ prefills = [], setPrefills, onNext }) => {
|
||||
>
|
||||
<div className="py-3 px-[10px] op-card border-[1px] border-gray-400">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-10 gap-y-4 w-full">
|
||||
{prefills.map((widget, index) => (
|
||||
{[...prefills]
|
||||
.sort((a, b) =>
|
||||
a.pageNumber !== b.pageNumber
|
||||
? a.pageNumber - b.pageNumber
|
||||
: (a.yPosition ?? 0) - (b.yPosition ?? 0)
|
||||
).map((widget, index) => (
|
||||
<RenderWidgets
|
||||
key={widget.key}
|
||||
showLabel
|
||||
|
||||
@@ -148,15 +148,25 @@ function PrefillWidgetModal(props) {
|
||||
return true;
|
||||
})
|
||||
}));
|
||||
//latten the filtered array and exclude read-only widgets
|
||||
const flatArray = filteredArray?.flatMap((page) =>
|
||||
page.pos
|
||||
.filter((widget) => !widget.options?.isReadOnly)
|
||||
.map((widget) => ({
|
||||
widget,
|
||||
pageNumber: page.pageNumber
|
||||
}))
|
||||
);
|
||||
// Flatten the filtered array, exclude read-only widgets,
|
||||
// carry yPosition for sorting, then sort by pageNumber asc → yPosition asc
|
||||
// (mirrors the newSignPos.sort in PdfRequestFiles so widgets appear in
|
||||
// the same top-to-bottom, page-1-first order as they do in the document)
|
||||
const flatArray = filteredArray
|
||||
?.flatMap((page) =>
|
||||
page.pos
|
||||
.filter((widget) => !widget.options?.isReadOnly)
|
||||
.map((widget) => ({
|
||||
widget,
|
||||
pageNumber: page.pageNumber,
|
||||
yPosition: widget.yPosition ?? 0
|
||||
}))
|
||||
)
|
||||
?.sort((a, b) =>
|
||||
a.pageNumber !== b.pageNumber
|
||||
? a.pageNumber - b.pageNumber // primary: page order (page 1 first)
|
||||
: a.yPosition - b.yPosition // secondary: top-to-bottom within page
|
||||
);
|
||||
|
||||
return flatArray || [];
|
||||
}, [props.prefillData]);
|
||||
@@ -896,4 +906,4 @@ function PrefillWidgetModal(props) {
|
||||
);
|
||||
}
|
||||
|
||||
export default PrefillWidgetModal;
|
||||
export default PrefillWidgetModal;
|
||||
@@ -577,8 +577,8 @@ function PdfRequestFiles(
|
||||
setContractName("_Contactbook");
|
||||
setSignerUserId(contact?.objectId);
|
||||
handleTourStatus(isTourEnabled, contact?.TourStatus);
|
||||
} catch (err) {
|
||||
console.log("err while getting tourstatus", err);
|
||||
} catch (error) {
|
||||
console.log("err while getting tourstatus", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user