@lock-dev/next-adapter
Version:
Nextjs adapter module for lock.dev security framework
317 lines (310 loc) • 9.88 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
createEdgeMiddleware: () => createEdgeMiddleware,
createErrorData: () => createErrorData,
createErrorResponse: () => createErrorResponse,
createResponseProxy: () => createResponseProxy,
extractSecurityMetadata: () => extractSecurityMetadata,
getErrorConfig: () => getErrorConfig,
handleSecurityFailure: () => handleSecurityFailure,
registerModule: () => import_core5.registerModule,
secureAppRoute: () => secureAppRoute,
securePagesApi: () => securePagesApi,
secureServerAction: () => secureServerAction
});
module.exports = __toCommonJS(index_exports);
var import_core5 = require("@lock-dev/core");
// src/utils/index.ts
function createResponseProxy() {
return {
headersSent: false,
writableEnded: false,
statusCode: 200,
headers: new Headers(),
status(code) {
this.statusCode = code;
return this;
},
setHeader(name, value) {
this.headers.set(name, value);
return this;
},
json(body) {
return new Response(JSON.stringify(body), {
status: this.statusCode,
headers: this.headers
});
}
};
}
function extractSecurityMetadata(result) {
if (result.event) {
return {
module: result.event.moduleName,
reason: result.event.message,
type: result.event.type,
timestamp: new Date(result.event.timestamp).toISOString(),
severity: result.event.severity,
details: result.event.data || {}
};
} else {
return {
module: "unknown",
reason: "Access denied by security policy",
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
details: {}
};
}
}
function getErrorConfig(context, result) {
let statusCode = 403;
let errorMessage = "Access denied by security policy";
if (result.event && result.event.moduleName) {
const configKey = `${result.event.moduleName}:config`;
const config = context.data.get(configKey);
if (config) {
statusCode = config.blockStatusCode || config.statusCode || statusCode;
errorMessage = config.blockMessage || config.message || errorMessage;
}
}
return { statusCode, errorMessage };
}
function createErrorData(context, result) {
const metadata = extractSecurityMetadata(result);
const { statusCode, errorMessage } = getErrorConfig(context, result);
return {
error: errorMessage,
blocked: true,
meta: metadata,
statusCode
};
}
function createErrorResponse(context, result) {
const errorData = createErrorData(context, result);
const headers = new Headers({
"Content-Type": "application/json"
});
if (context.response && "headers" in context.response) {
const responseHeaders = context.response.headers;
if (responseHeaders instanceof Headers) {
responseHeaders.forEach((value, key) => {
headers.set(key, value);
});
} else if (typeof responseHeaders === "object") {
Object.entries(responseHeaders).forEach(([key, value]) => {
if (typeof value === "string") {
headers.set(key, value);
}
});
}
}
return new Response(JSON.stringify(errorData), {
status: errorData.statusCode,
headers
});
}
function handleSecurityFailure(context, result, res) {
if (!res.headersSent && !res.writableEnded) {
const errorData = createErrorData(context, result);
res.status(errorData.statusCode).json({
error: errorData.error,
blocked: true,
meta: errorData.meta
});
}
}
// src/pages-router.ts
var import_core = require("@lock-dev/core");
function securePagesApi(handler) {
return (...modules) => {
const composedModule = (0, import_core.composeModules)(...modules);
return async (req, res) => {
const context = (0, import_core.createContext)(req, res, {});
try {
const result = await composedModule.check(context);
if (result.passed) {
return handler(req, res);
} else {
handleSecurityFailure(context, result, res);
}
} catch (error) {
console.error("Security middleware error:", error);
if (!res.headersSent) {
return res.status(500).json({ error: "Internal security error" });
}
}
};
};
}
// src/app-router.ts
var import_core2 = require("@lock-dev/core");
function secureAppRoute(handler) {
return (...modules) => {
const composedModule = (0, import_core2.composeModules)(...modules);
return async (req) => {
const resProxy = createResponseProxy();
const context = (0, import_core2.createContext)(req, resProxy, {});
try {
const result = await composedModule.check(context);
if (result.passed) {
const originalResponse = await handler(req);
const responseClone = new Response(originalResponse.body, {
status: originalResponse.status,
statusText: originalResponse.statusText,
headers: new Headers({
...Object.fromEntries(originalResponse.headers.entries()),
...Object.fromEntries(resProxy.headers.entries())
})
});
return responseClone;
} else {
return createErrorResponse(context, result);
}
} catch (error) {
console.error("Middleware error:", error);
return new Response(JSON.stringify({ error: "Internal security error" }), {
status: 500,
headers: {
"Content-Type": "application/json"
}
});
}
};
};
}
// src/server-actions.ts
var import_core3 = require("@lock-dev/core");
function secureServerAction(action) {
return (...modules) => {
const composedModule = (0, import_core3.composeModules)(...modules);
return async (...args) => {
const req = {
headers: {},
cookies: {},
method: "POST",
url: "/",
body: {}
};
const formDataArg = args.find((arg) => arg instanceof FormData);
if (formDataArg && formDataArg instanceof FormData) {
const requestHeaders = formDataArg.get("$REQUEST_HEADERS");
if (requestHeaders && typeof requestHeaders === "string") {
try {
req.headers = JSON.parse(requestHeaders);
} catch (e) {
console.warn("Failed to parse request headers in server action");
}
}
const csrfToken = formDataArg.get("csrf-token") || formDataArg.get("csrfToken");
if (csrfToken && typeof csrfToken === "string") {
req.headers["x-csrf-token"] = csrfToken;
}
}
const res = {
headersSent: false,
writableEnded: false,
statusCode: 200,
headers: {},
status(code) {
this.statusCode = code;
return this;
},
setHeader(name, value) {
this.headers[name] = value;
return this;
},
json(body) {
return body;
}
};
const context = (0, import_core3.createContext)(req, res, {});
try {
const result = await composedModule.check(context);
if (result.passed) {
return action(...args);
} else {
const errorData = createErrorData(context, result);
throw new Error(JSON.stringify(errorData));
}
} catch (error) {
if (error instanceof Error && error.message.startsWith("{")) {
throw error;
}
console.error("Security middleware error:", error);
throw new Error(
JSON.stringify({
error: "Internal security error",
statusCode: 500
})
);
}
};
};
}
// src/edge.ts
var import_core4 = require("@lock-dev/core");
function createEdgeMiddleware(...modules) {
const composedModule = (0, import_core4.composeModules)(...modules);
return async function middleware(req) {
const resProxy = createResponseProxy();
const context = (0, import_core4.createContext)(req, resProxy, {});
try {
const result = await composedModule.check(context);
if (result.passed) {
const headers = new Headers({
"x-middleware-next": "1"
});
resProxy.headers.forEach((value, key) => {
headers.set(key, value);
});
return new Response(null, {
status: 200,
headers
});
} else {
return createErrorResponse(context, result);
}
} catch (error) {
console.error("Security middleware error:", error);
return new Response(JSON.stringify({ error: "Internal security error" }), {
status: 500,
headers: {
"Content-Type": "application/json"
}
});
}
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createEdgeMiddleware,
createErrorData,
createErrorResponse,
createResponseProxy,
extractSecurityMetadata,
getErrorConfig,
handleSecurityFailure,
registerModule,
secureAppRoute,
securePagesApi,
secureServerAction
});