WhatsApp/Signal/Formstack/admin updates

This commit is contained in:
Darren Clarke 2025-11-21 14:55:28 +01:00
parent bcecf61a46
commit d0cc5a21de
451 changed files with 16139 additions and 39623 deletions

View file

@ -1,21 +1,30 @@
import { NextResponse } from "next/server";
import { withAuth, NextRequestWithAuth } from "next-auth/middleware";
import { createLogger } from "@link-stack/logger";
const logger = createLogger('link-middleware');
/*
const rewriteURL = (
request: NextRequestWithAuth,
originBaseURL: string,
destinationBaseURL: string,
headers: any = {},
) => {
logger.debug({
originBaseURL,
destinationBaseURL,
headerKeys: Object.keys(headers)
}, "Rewriting URL");
let path = request.url.replace(originBaseURL, "");
if (path.startsWith("/")) {
path = path.slice(1);
}
const destinationURL = `${destinationBaseURL}/${path}`;
console.log(`Rewriting ${request.url} to ${destinationURL}`);
logger.debug({ from: request.url, to: destinationURL }, "URL rewrite");
const requestHeaders = new Headers(request.headers);
requestHeaders.delete("x-forwarded-user");
requestHeaders.delete("x-forwarded-roles");
requestHeaders.delete("connection");
for (const [key, value] of Object.entries(headers)) {
@ -26,17 +35,61 @@ const rewriteURL = (
request: { headers: requestHeaders },
});
};
*/
const checkRewrites = async (request: NextRequestWithAuth) => {
// const linkBaseURL = process.env.LINK_URL ?? "http://localhost:3000";
const linkBaseURL = process.env.LINK_URL ?? "http://localhost:3000";
logger.debug({ linkBaseURL }, "Link base URL");
const opensearchBaseURL =
process.env.OPENSEARCH_DASHBOARDS_URL ??
"http://opensearch-dashboards:5601";
const { token } = request.nextauth;
const email = token?.email?.toLowerCase() ?? "unknown";
// let headers = { "x-forwarded-user": email };
const roles = (token?.roles as string[]) ?? [];
let headers = {
"x-forwarded-user": email,
"x-forwarded-roles": roles.join(","),
};
if (request.nextUrl.pathname.startsWith("/dashboards")) {
// Extract the path after /dashboards and append to OpenSearch URL
let path = request.nextUrl.pathname.slice("/dashboards".length);
if (path.startsWith("/")) {
path = path.slice(1);
}
const search = request.nextUrl.search;
const destinationURL = `${opensearchBaseURL}/${path}${search}`;
logger.debug({
pathname: request.nextUrl.pathname,
path,
search,
destinationURL
}, "OpenSearch proxy");
const requestHeaders = new Headers(request.headers);
requestHeaders.delete("x-forwarded-user");
requestHeaders.delete("x-forwarded-roles");
requestHeaders.delete("connection");
for (const [key, value] of Object.entries(headers)) {
requestHeaders.set(key, value as string);
}
return NextResponse.rewrite(new URL(destinationURL), {
request: { headers: requestHeaders },
});
}
const isDev = process.env.NODE_ENV === "development";
const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
// Allow digiresilience.org for embedding documentation
const frameSrcDirective = `frame-src 'self' https://digiresilience.org;`;
const cspHeader = `
default-src 'self';
${frameSrcDirective}
connect-src 'self';
script-src 'self' 'nonce-${nonce}' 'strict-dynamic' ${isDev ? "'unsafe-eval'" : ""};
style-src 'self' 'unsafe-inline';
@ -45,7 +98,7 @@ const checkRewrites = async (request: NextRequestWithAuth) => {
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
frame-ancestors 'self';
upgrade-insecure-requests;
`;
const contentSecurityPolicyHeaderValue = cspHeader
@ -70,8 +123,18 @@ const checkRewrites = async (request: NextRequestWithAuth) => {
contentSecurityPolicyHeaderValue,
);
// Additional security headers
response.headers.set("X-Frame-Options", "SAMEORIGIN");
response.headers.set("X-Content-Type-Options", "nosniff");
response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
response.headers.set("X-XSS-Protection", "1; mode=block");
response.headers.set(
"Permissions-Policy",
"camera=(), microphone=(), geolocation=()"
);
return response;
};
}
export default withAuth(checkRewrites, {
callbacks: {
@ -101,5 +164,7 @@ export default withAuth(checkRewrites, {
});
export const config = {
matcher: ["/((?!ws|wss|api|_next/static|_next/image|favicon.ico).*)"],
};
matcher: [
"/((?!ws|wss|api/signal|api/whatsapp|api/formstack|_next/static|_next/image|favicon.ico).*)",
],
}