Files
XCDesktop/dist-api/chunk-ER4KPD22.js

164 lines
4.4 KiB
JavaScript

import {
NOTEBOOK_ROOT
} from "./chunk-74TMTGBG.js";
// shared/errors/index.ts
var AppError = class extends Error {
constructor(code, message, statusCode = 500, details) {
super(message);
this.code = code;
this.name = "AppError";
this.statusCode = statusCode;
this.details = details;
}
statusCode;
details;
toJSON() {
return {
name: this.name,
code: this.code,
message: this.message,
statusCode: this.statusCode,
details: this.details
};
}
};
var ValidationError = class extends AppError {
constructor(message, details) {
super("VALIDATION_ERROR", message, 400, details);
this.name = "ValidationError";
}
};
var NotFoundError = class extends AppError {
constructor(message = "Resource not found", details) {
super("NOT_FOUND", message, 404, details);
this.name = "NotFoundError";
}
};
var AccessDeniedError = class extends AppError {
constructor(message = "Access denied", details) {
super("ACCESS_DENIED", message, 403, details);
this.name = "AccessDeniedError";
}
};
var BadRequestError = class extends AppError {
constructor(message, details) {
super("BAD_REQUEST", message, 400, details);
this.name = "BadRequestError";
}
};
var NotADirectoryError = class extends AppError {
constructor(message = "\u4E0D\u662F\u76EE\u5F55", details) {
super("NOT_A_DIRECTORY", message, 400, details);
this.name = "NotADirectoryError";
}
};
var AlreadyExistsError = class extends AppError {
constructor(message = "Resource already exists", details) {
super("ALREADY_EXISTS", message, 409, details);
this.name = "AlreadyExistsError";
}
};
var ForbiddenError = class extends AppError {
constructor(message = "\u7981\u6B62\u8BBF\u95EE", details) {
super("FORBIDDEN", message, 403, details);
this.name = "ForbiddenError";
}
};
var UnsupportedMediaTypeError = class extends AppError {
constructor(message = "\u4E0D\u652F\u6301\u7684\u5A92\u4F53\u7C7B\u578B", details) {
super("UNSUPPORTED_MEDIA_TYPE", message, 415, details);
this.name = "UnsupportedMediaTypeError";
}
};
var ResourceLockedError = class extends AppError {
constructor(message = "\u8D44\u6E90\u5DF2\u9501\u5B9A", details) {
super("RESOURCE_LOCKED", message, 423, details);
this.name = "ResourceLockedError";
}
};
var InternalError = class extends AppError {
constructor(message = "\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF", details) {
super("INTERNAL_ERROR", message, 500, details);
this.name = "InternalError";
}
};
function isAppError(error) {
return error instanceof AppError;
}
function isNodeError(error) {
return error instanceof Error && "code" in error;
}
// api/utils/pathSafety.ts
import path from "path";
var DANGEROUS_PATTERNS = [
/\.\./,
/\0/,
/%2e%2e[%/]/i,
/%252e%252e[%/]/i,
/\.\.%2f/i,
/\.\.%5c/i,
/%c0%ae/i,
/%c1%9c/i,
/%c0%ae%c0%ae/i,
/%c1%9c%c1%9c/i,
/\.\.%c0%af/i,
/\.\.%c1%9c/i,
/%252e/i,
/%uff0e/i,
/%u002e/i
];
var DOUBLE_ENCODE_PATTERNS = [
/%25[0-9a-fA-F]{2}/,
/%[0-9a-fA-F]{2}%[0-9a-fA-F]{2}/
];
var normalizeRelPath = (input) => {
const trimmed = input.replace(/\0/g, "").trim();
return trimmed.replace(/^[/\\]+/, "");
};
var containsPathTraversal = (input) => {
const decoded = decodeURIComponentSafe(input);
return DANGEROUS_PATTERNS.some((pattern) => pattern.test(input) || pattern.test(decoded));
};
var containsDoubleEncoding = (input) => {
return DOUBLE_ENCODE_PATTERNS.some((pattern) => pattern.test(input));
};
var hasPathSecurityIssues = (input) => {
return containsPathTraversal(input) || containsDoubleEncoding(input);
};
var decodeURIComponentSafe = (input) => {
try {
return decodeURIComponent(input);
} catch {
return input;
}
};
var resolveNotebookPath = (relPath) => {
if (hasPathSecurityIssues(relPath)) {
throw new AccessDeniedError("Path traversal detected");
}
const safeRelPath = normalizeRelPath(relPath);
const notebookRoot = path.resolve(NOTEBOOK_ROOT);
const fullPath = path.resolve(notebookRoot, safeRelPath);
if (!fullPath.startsWith(notebookRoot)) {
throw new AccessDeniedError("Access denied");
}
return { safeRelPath, fullPath };
};
export {
ValidationError,
NotFoundError,
BadRequestError,
NotADirectoryError,
AlreadyExistsError,
ForbiddenError,
UnsupportedMediaTypeError,
ResourceLockedError,
InternalError,
isAppError,
isNodeError,
resolveNotebookPath
};