@schafevormfenster/rest-commons 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +1190 -0
- package/README.md +275 -0
- package/bin/setup.js +10 -0
- package/dist/api-schemas/error.schema.d.ts +20 -0
- package/dist/api-schemas/error.schema.d.ts.map +1 -0
- package/dist/api-schemas/error.schema.js +17 -0
- package/dist/api-schemas/health.schema.d.ts +497 -0
- package/dist/api-schemas/health.schema.d.ts.map +1 -0
- package/dist/api-schemas/health.schema.js +33 -0
- package/dist/api-schemas/okay.schema.d.ts +13 -0
- package/dist/api-schemas/okay.schema.d.ts.map +1 -0
- package/dist/api-schemas/okay.schema.js +5 -0
- package/dist/api-schemas/paginated-results.schema.d.ts +59 -0
- package/dist/api-schemas/paginated-results.schema.d.ts.map +1 -0
- package/dist/api-schemas/paginated-results.schema.js +10 -0
- package/dist/api-schemas/partial-results.schema.d.ts +30 -0
- package/dist/api-schemas/partial-results.schema.d.ts.map +1 -0
- package/dist/api-schemas/partial-results.schema.js +10 -0
- package/dist/api-schemas/result.schema.d.ts +17 -0
- package/dist/api-schemas/result.schema.d.ts.map +1 -0
- package/dist/api-schemas/result.schema.js +5 -0
- package/dist/api-schemas/results.schema.d.ts +21 -0
- package/dist/api-schemas/results.schema.d.ts.map +1 -0
- package/dist/api-schemas/results.schema.js +5 -0
- package/dist/helpers/correlation/get-correlation-id.d.ts +7 -0
- package/dist/helpers/correlation/get-correlation-id.d.ts.map +1 -0
- package/dist/helpers/correlation/get-correlation-id.js +16 -0
- package/dist/helpers/correlation/get-header.d.ts +7 -0
- package/dist/helpers/correlation/get-header.d.ts.map +1 -0
- package/dist/helpers/correlation/get-header.js +11 -0
- package/dist/helpers/detect-mime-type.d.ts +11 -0
- package/dist/helpers/detect-mime-type.d.ts.map +1 -0
- package/dist/helpers/detect-mime-type.js +40 -0
- package/dist/helpers/detect-suspicious-patterns.d.ts +8 -0
- package/dist/helpers/detect-suspicious-patterns.d.ts.map +1 -0
- package/dist/helpers/detect-suspicious-patterns.js +55 -0
- package/dist/helpers/eventify-constants.types.d.ts +32 -0
- package/dist/helpers/eventify-constants.types.d.ts.map +1 -0
- package/dist/helpers/eventify-constants.types.js +40 -0
- package/dist/helpers/hash-binary.d.ts +21 -0
- package/dist/helpers/hash-binary.d.ts.map +1 -0
- package/dist/helpers/hash-binary.js +28 -0
- package/dist/helpers/mime-types/detect-image-mime-type.d.ts +5 -0
- package/dist/helpers/mime-types/detect-image-mime-type.d.ts.map +1 -0
- package/dist/helpers/mime-types/detect-image-mime-type.js +41 -0
- package/dist/helpers/mime-types/detect-ole-mime-type.d.ts +6 -0
- package/dist/helpers/mime-types/detect-ole-mime-type.d.ts.map +1 -0
- package/dist/helpers/mime-types/detect-ole-mime-type.js +34 -0
- package/dist/helpers/mime-types/detect-pdf-mime-type.d.ts +5 -0
- package/dist/helpers/mime-types/detect-pdf-mime-type.d.ts.map +1 -0
- package/dist/helpers/mime-types/detect-pdf-mime-type.js +13 -0
- package/dist/helpers/mime-types/detect-zip-mime-type.d.ts +6 -0
- package/dist/helpers/mime-types/detect-zip-mime-type.d.ts.map +1 -0
- package/dist/helpers/mime-types/detect-zip-mime-type.js +23 -0
- package/dist/helpers/parameter-validation.d.ts +6 -0
- package/dist/helpers/parameter-validation.d.ts.map +1 -0
- package/dist/helpers/parameter-validation.js +19 -0
- package/dist/helpers/parameter-validation.types.d.ts +16 -0
- package/dist/helpers/parameter-validation.types.d.ts.map +1 -0
- package/dist/helpers/parameter-validation.types.js +38 -0
- package/dist/helpers/response-headers/build-api-unauthorized-headers.d.ts +6 -0
- package/dist/helpers/response-headers/build-api-unauthorized-headers.d.ts.map +1 -0
- package/dist/helpers/response-headers/build-api-unauthorized-headers.js +23 -0
- package/dist/helpers/response-headers/environment.types.d.ts +2 -0
- package/dist/helpers/response-headers/environment.types.d.ts.map +1 -0
- package/dist/helpers/response-headers/environment.types.js +1 -0
- package/dist/helpers/response-headers/resolve-environment.d.ts +8 -0
- package/dist/helpers/response-headers/resolve-environment.d.ts.map +1 -0
- package/dist/helpers/response-headers/resolve-environment.js +18 -0
- package/dist/helpers/slugify.d.ts +15 -0
- package/dist/helpers/slugify.d.ts.map +1 -0
- package/dist/helpers/slugify.js +32 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/normalization/normalize-list.d.ts +11 -0
- package/dist/normalization/normalize-list.d.ts.map +1 -0
- package/dist/normalization/normalize-list.js +19 -0
- package/dist/normalization/normalize-location.d.ts +16 -0
- package/dist/normalization/normalize-location.d.ts.map +1 -0
- package/dist/normalization/normalize-location.js +26 -0
- package/dist/primitives/coordinate-precision.d.ts +10 -0
- package/dist/primitives/coordinate-precision.d.ts.map +1 -0
- package/dist/primitives/coordinate-precision.js +27 -0
- package/dist/primitives/geo-point.schema.d.ts +8 -0
- package/dist/primitives/geo-point.schema.d.ts.map +1 -0
- package/dist/primitives/geo-point.schema.js +10 -0
- package/dist/primitives/geoname-id.schema.d.ts +8 -0
- package/dist/primitives/geoname-id.schema.d.ts.map +1 -0
- package/dist/primitives/geoname-id.schema.js +9 -0
- package/dist/primitives/international-zip.schema.d.ts +76 -0
- package/dist/primitives/international-zip.schema.d.ts.map +1 -0
- package/dist/primitives/international-zip.schema.js +81 -0
- package/dist/primitives/latitude.schema.d.ts +9 -0
- package/dist/primitives/latitude.schema.d.ts.map +1 -0
- package/dist/primitives/latitude.schema.js +13 -0
- package/dist/primitives/location.schema.d.ts +8 -0
- package/dist/primitives/location.schema.d.ts.map +1 -0
- package/dist/primitives/location.schema.js +15 -0
- package/dist/primitives/longitude.schema.d.ts +9 -0
- package/dist/primitives/longitude.schema.d.ts.map +1 -0
- package/dist/primitives/longitude.schema.js +13 -0
- package/dist/primitives/numeric-id.schema.d.ts +8 -0
- package/dist/primitives/numeric-id.schema.d.ts.map +1 -0
- package/dist/primitives/numeric-id.schema.js +10 -0
- package/dist/primitives/slug.schema.d.ts +17 -0
- package/dist/primitives/slug.schema.d.ts.map +1 -0
- package/dist/primitives/slug.schema.js +30 -0
- package/dist/primitives/uuid.schema.d.ts +8 -0
- package/dist/primitives/uuid.schema.d.ts.map +1 -0
- package/dist/primitives/uuid.schema.js +9 -0
- package/dist/primitives/wikidata-id.schema.d.ts +9 -0
- package/dist/primitives/wikidata-id.schema.d.ts.map +1 -0
- package/dist/primitives/wikidata-id.schema.js +10 -0
- package/dist/time/boundary-enforcement.d.ts +11 -0
- package/dist/time/boundary-enforcement.d.ts.map +1 -0
- package/dist/time/boundary-enforcement.js +43 -0
- package/dist/time/bounded-time.schema.d.ts +31 -0
- package/dist/time/bounded-time.schema.d.ts.map +1 -0
- package/dist/time/bounded-time.schema.js +77 -0
- package/dist/time/flexible-time-parser.d.ts +12 -0
- package/dist/time/flexible-time-parser.d.ts.map +1 -0
- package/dist/time/flexible-time-parser.js +94 -0
- package/dist/time/flexible-time.schema.d.ts +31 -0
- package/dist/time/flexible-time.schema.d.ts.map +1 -0
- package/dist/time/flexible-time.schema.js +31 -0
- package/dist/time/get-week-end.d.ts +10 -0
- package/dist/time/get-week-end.d.ts.map +1 -0
- package/dist/time/get-week-end.js +25 -0
- package/dist/time/get-week-start.d.ts +10 -0
- package/dist/time/get-week-start.d.ts.map +1 -0
- package/dist/time/get-week-start.js +25 -0
- package/dist/time/is-relative-time.d.ts +8 -0
- package/dist/time/is-relative-time.d.ts.map +1 -0
- package/dist/time/is-relative-time.js +9 -0
- package/dist/time/iso8601.schema.d.ts +14 -0
- package/dist/time/iso8601.schema.d.ts.map +1 -0
- package/dist/time/iso8601.schema.js +17 -0
- package/dist/time/iso8601.types.d.ts +6 -0
- package/dist/time/iso8601.types.d.ts.map +1 -0
- package/dist/time/iso8601.types.js +11 -0
- package/dist/time/parse-relative-time.d.ts +9 -0
- package/dist/time/parse-relative-time.d.ts.map +1 -0
- package/dist/time/parse-relative-time.js +36 -0
- package/dist/time/relative-time.schema.d.ts +23 -0
- package/dist/time/relative-time.schema.d.ts.map +1 -0
- package/dist/time/relative-time.schema.js +25 -0
- package/dist/time/since-parameter.schema.d.ts +8 -0
- package/dist/time/since-parameter.schema.d.ts.map +1 -0
- package/dist/time/since-parameter.schema.js +56 -0
- package/dist/time/time-helpers.d.ts +19 -0
- package/dist/time/time-helpers.d.ts.map +1 -0
- package/dist/time/time-helpers.js +56 -0
- package/dist/time/time-schemas.d.ts +20 -0
- package/dist/time/time-schemas.d.ts.map +1 -0
- package/dist/time/time-schemas.js +25 -0
- package/dist/time/timezone.types.d.ts +17 -0
- package/dist/time/timezone.types.d.ts.map +1 -0
- package/dist/time/timezone.types.js +15 -0
- package/dist/validation/zod-error-handler.d.ts +3 -0
- package/dist/validation/zod-error-handler.d.ts.map +1 -0
- package/dist/validation/zod-error-handler.js +189 -0
- package/dist/validation/zod-utils.d.ts +9 -0
- package/dist/validation/zod-utils.d.ts.map +1 -0
- package/dist/validation/zod-utils.js +23 -0
- package/eslint.config.mjs +16 -0
- package/package.json +44 -0
- package/src/api-schemas/error.schema.test.ts +27 -0
- package/src/api-schemas/error.schema.ts +23 -0
- package/src/api-schemas/health.schema.test.ts +104 -0
- package/src/api-schemas/health.schema.ts +63 -0
- package/src/api-schemas/okay.schema.test.ts +15 -0
- package/src/api-schemas/okay.schema.ts +8 -0
- package/src/api-schemas/paginated-results.schema.ts +17 -0
- package/src/api-schemas/partial-results.schema.ts +13 -0
- package/src/api-schemas/result.schema.test.ts +19 -0
- package/src/api-schemas/result.schema.ts +9 -0
- package/src/api-schemas/results.schema.test.ts +15 -0
- package/src/api-schemas/results.schema.ts +9 -0
- package/src/helpers/correlation/get-correlation-id.test.ts +126 -0
- package/src/helpers/correlation/get-correlation-id.ts +22 -0
- package/src/helpers/correlation/get-header.test.ts +179 -0
- package/src/helpers/correlation/get-header.ts +21 -0
- package/src/helpers/detect-mime-type.test.ts +100 -0
- package/src/helpers/detect-mime-type.ts +46 -0
- package/src/helpers/detect-suspicious-patterns.test.ts +45 -0
- package/src/helpers/detect-suspicious-patterns.ts +57 -0
- package/src/helpers/eventify-constants.test.ts +52 -0
- package/src/helpers/eventify-constants.types.test.ts +52 -0
- package/src/helpers/eventify-constants.types.ts +51 -0
- package/src/helpers/hash-binary.test.ts +60 -0
- package/src/helpers/hash-binary.ts +30 -0
- package/src/helpers/mime-types/detect-image-mime-type.test.ts +73 -0
- package/src/helpers/mime-types/detect-image-mime-type.ts +50 -0
- package/src/helpers/mime-types/detect-ole-mime-type.test.ts +86 -0
- package/src/helpers/mime-types/detect-ole-mime-type.ts +44 -0
- package/src/helpers/mime-types/detect-pdf-mime-type.test.ts +39 -0
- package/src/helpers/mime-types/detect-pdf-mime-type.ts +15 -0
- package/src/helpers/mime-types/detect-zip-mime-type.test.ts +88 -0
- package/src/helpers/mime-types/detect-zip-mime-type.ts +28 -0
- package/src/helpers/parameter-validation.test.ts +35 -0
- package/src/helpers/parameter-validation.ts +32 -0
- package/src/helpers/process-eventify-request.ts +146 -0
- package/src/helpers/response-headers/build-api-unauthorized-headers.ts +30 -0
- package/src/helpers/response-headers/environment.types.ts +1 -0
- package/src/helpers/response-headers/resolve-environment.ts +17 -0
- package/src/helpers/slugify.test.ts +77 -0
- package/src/helpers/slugify.ts +34 -0
- package/src/index.ts +46 -0
- package/src/normalization/normalize-list.test.ts +43 -0
- package/src/normalization/normalize-list.ts +21 -0
- package/src/normalization/normalize-location.test.ts +91 -0
- package/src/normalization/normalize-location.ts +29 -0
- package/src/primitives/coordinate-precision.test.ts +46 -0
- package/src/primitives/coordinate-precision.ts +30 -0
- package/src/primitives/geo-point.schema.test.ts +70 -0
- package/src/primitives/geo-point.schema.ts +14 -0
- package/src/primitives/geoname-id.schema.test.ts +60 -0
- package/src/primitives/geoname-id.schema.ts +12 -0
- package/src/primitives/international-zip.schema.test.ts +212 -0
- package/src/primitives/international-zip.schema.ts +103 -0
- package/src/primitives/latitude.schema.test.ts +77 -0
- package/src/primitives/latitude.schema.ts +20 -0
- package/src/primitives/location.schema.test.ts +21 -0
- package/src/primitives/location.schema.ts +22 -0
- package/src/primitives/longitude.schema.test.ts +77 -0
- package/src/primitives/longitude.schema.ts +20 -0
- package/src/primitives/numeric-id.schema.test.ts +32 -0
- package/src/primitives/numeric-id.schema.ts +13 -0
- package/src/primitives/slug.schema.test.ts +101 -0
- package/src/primitives/slug.schema.ts +41 -0
- package/src/primitives/uuid.schema.test.ts +45 -0
- package/src/primitives/uuid.schema.ts +12 -0
- package/src/primitives/wikidata-id.schema.test.ts +51 -0
- package/src/primitives/wikidata-id.schema.ts +16 -0
- package/src/time/README.md +220 -0
- package/src/time/boundary-enforcement.test.ts +130 -0
- package/src/time/boundary-enforcement.ts +59 -0
- package/src/time/bounded-time.schema.test.ts +294 -0
- package/src/time/bounded-time.schema.ts +111 -0
- package/src/time/flexible-time-parser.test.ts +586 -0
- package/src/time/flexible-time-parser.ts +122 -0
- package/src/time/flexible-time.schema.test.ts +243 -0
- package/src/time/flexible-time.schema.ts +43 -0
- package/src/time/is-relative-time.test.ts +23 -0
- package/src/time/is-relative-time.ts +9 -0
- package/src/time/iso8601.schema.ts +29 -0
- package/src/time/iso8601.types.test.ts +112 -0
- package/src/time/iso8601.types.ts +21 -0
- package/src/time/parse-relative-time.test.ts +49 -0
- package/src/time/parse-relative-time.ts +50 -0
- package/src/time/relative-time.schema.test.ts +23 -0
- package/src/time/relative-time.schema.ts +38 -0
- package/src/time/since-parameter.schema.test.ts +59 -0
- package/src/time/since-parameter.schema.ts +69 -0
- package/src/time/time-helpers.test.ts +263 -0
- package/src/time/time-helpers.ts +78 -0
- package/src/time/time-schemas.test.ts +181 -0
- package/src/time/time-schemas.ts +42 -0
- package/src/time/time.schema.test.ts +237 -0
- package/src/time/timezone-independence.test.ts +188 -0
- package/src/time/timezone.types.test.ts +55 -0
- package/src/time/timezone.types.ts +22 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const ResultsSchema: z.ZodObject<{
|
|
3
|
+
status: z.ZodNumber;
|
|
4
|
+
message: z.ZodOptional<z.ZodString>;
|
|
5
|
+
} & {
|
|
6
|
+
timestamp: z.ZodEffects<z.ZodString, string, string>;
|
|
7
|
+
} & {
|
|
8
|
+
results: z.ZodNumber;
|
|
9
|
+
}, "strict", z.ZodTypeAny, {
|
|
10
|
+
status: number;
|
|
11
|
+
timestamp: string;
|
|
12
|
+
results: number;
|
|
13
|
+
message?: string | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
status: number;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
results: number;
|
|
18
|
+
message?: string | undefined;
|
|
19
|
+
}>;
|
|
20
|
+
export type Results = z.infer<typeof ResultsSchema>;
|
|
21
|
+
//# sourceMappingURL=results.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"results.schema.d.ts","sourceRoot":"","sources":["../../src/api-schemas/results.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;EAExB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-correlation-id.d.ts","sourceRoot":"","sources":["../../../src/helpers/correlation/get-correlation-id.ts"],"names":[],"mappings":"AAEA,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,OAAO,CAAC,EACJ,OAAO,GACP;QAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CACvE,GAAG,MAAM,CAeT"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getHeader } from "./get-header";
|
|
2
|
+
export function getCorrelationId(request) {
|
|
3
|
+
const existingId = getHeader(request, "x-correlation-id");
|
|
4
|
+
if (existingId && typeof existingId === "string" && existingId.length > 0) {
|
|
5
|
+
return existingId;
|
|
6
|
+
}
|
|
7
|
+
// Use crypto for secure random ID generation
|
|
8
|
+
const bytes = new Uint8Array(8);
|
|
9
|
+
crypto.getRandomValues(bytes);
|
|
10
|
+
let randomPart = "";
|
|
11
|
+
for (const byte of bytes) {
|
|
12
|
+
randomPart += byte.toString(16).padStart(2, "0");
|
|
13
|
+
}
|
|
14
|
+
const timestamp = Date.now().toString(16);
|
|
15
|
+
return `${timestamp}-${randomPart}`;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-header.d.ts","sourceRoot":"","sources":["../../../src/helpers/correlation/get-header.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CACvB,OAAO,EAAE;IACP,OAAO,CAAC,EACJ,OAAO,GACP;QAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CACvE,EACD,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAapB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function getHeader(request, name) {
|
|
2
|
+
const headers = request?.headers;
|
|
3
|
+
if (!headers)
|
|
4
|
+
return undefined;
|
|
5
|
+
if (typeof headers.get === "function") {
|
|
6
|
+
const v = headers.get(name);
|
|
7
|
+
return v === null ? undefined : v;
|
|
8
|
+
}
|
|
9
|
+
const key = Object.keys(headers).find((k) => k.toLowerCase() === name.toLowerCase());
|
|
10
|
+
return key ? String(headers[key]) : undefined;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect MIME type from file magic bytes (file signature)
|
|
3
|
+
*
|
|
4
|
+
* This function performs magic byte detection to determine the actual
|
|
5
|
+
* file type regardless of file extension or Content-Type header.
|
|
6
|
+
*
|
|
7
|
+
* @param buffer - File content as Buffer
|
|
8
|
+
* @returns Detected MIME type or undefined if unknown
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectMimeType(buffer: Buffer): string | undefined;
|
|
11
|
+
//# sourceMappingURL=detect-mime-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-mime-type.d.ts","sourceRoot":"","sources":["../../src/helpers/detect-mime-type.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA+BjE"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { detectImageMimeType } from "./mime-types/detect-image-mime-type";
|
|
2
|
+
import { detectOleMimeType } from "./mime-types/detect-ole-mime-type";
|
|
3
|
+
import { detectPdfMimeType } from "./mime-types/detect-pdf-mime-type";
|
|
4
|
+
import { detectZipMimeType } from "./mime-types/detect-zip-mime-type";
|
|
5
|
+
/**
|
|
6
|
+
* Detect MIME type from file magic bytes (file signature)
|
|
7
|
+
*
|
|
8
|
+
* This function performs magic byte detection to determine the actual
|
|
9
|
+
* file type regardless of file extension or Content-Type header.
|
|
10
|
+
*
|
|
11
|
+
* @param buffer - File content as Buffer
|
|
12
|
+
* @returns Detected MIME type or undefined if unknown
|
|
13
|
+
*/
|
|
14
|
+
export function detectMimeType(buffer) {
|
|
15
|
+
if (!buffer || buffer.length < 4) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
// Check for image formats
|
|
19
|
+
const imageType = detectImageMimeType(buffer);
|
|
20
|
+
if (imageType) {
|
|
21
|
+
return imageType;
|
|
22
|
+
}
|
|
23
|
+
// Check for document formats
|
|
24
|
+
// PDF
|
|
25
|
+
const pdfType = detectPdfMimeType(buffer);
|
|
26
|
+
if (pdfType) {
|
|
27
|
+
return pdfType;
|
|
28
|
+
}
|
|
29
|
+
// ZIP-based formats (DOCX, PPTX)
|
|
30
|
+
const zipType = detectZipMimeType(buffer);
|
|
31
|
+
if (zipType) {
|
|
32
|
+
return zipType;
|
|
33
|
+
}
|
|
34
|
+
// MS Office OLE2 formats (DOC, PPT)
|
|
35
|
+
const oleType = detectOleMimeType(buffer);
|
|
36
|
+
if (oleType) {
|
|
37
|
+
return oleType;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect suspicious patterns from a request body without logging or exposing the content.
|
|
3
|
+
* Returns a list of pattern identifiers suitable for security logging.
|
|
4
|
+
*
|
|
5
|
+
* This helper is intentionally conservative and only flags common patterns.
|
|
6
|
+
*/
|
|
7
|
+
export declare function detectSuspiciousPatternsFromBody(body: unknown): string[];
|
|
8
|
+
//# sourceMappingURL=detect-suspicious-patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-suspicious-patterns.d.ts","sourceRoot":"","sources":["../../src/helpers/detect-suspicious-patterns.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAkDxE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect suspicious patterns from a request body without logging or exposing the content.
|
|
3
|
+
* Returns a list of pattern identifiers suitable for security logging.
|
|
4
|
+
*
|
|
5
|
+
* This helper is intentionally conservative and only flags common patterns.
|
|
6
|
+
*/
|
|
7
|
+
export function detectSuspiciousPatternsFromBody(body) {
|
|
8
|
+
const patterns = [];
|
|
9
|
+
const checkString = (s) => {
|
|
10
|
+
const lower = s.toLowerCase();
|
|
11
|
+
// XSS/HTML injection indicators
|
|
12
|
+
if (lower.includes("<script"))
|
|
13
|
+
patterns.push("html.script_tag");
|
|
14
|
+
// Basic SQLi strings
|
|
15
|
+
if (lower.includes("union select"))
|
|
16
|
+
patterns.push("sql.union_select");
|
|
17
|
+
if (lower.includes("drop table"))
|
|
18
|
+
patterns.push("sql.drop_table");
|
|
19
|
+
// Prompt injection style phrases
|
|
20
|
+
if (lower.includes("ignore previous") ||
|
|
21
|
+
lower.includes("disregard previous")) {
|
|
22
|
+
patterns.push("prompt.injection.language");
|
|
23
|
+
}
|
|
24
|
+
// Embedded external URLs (often used in attacks/phishing)
|
|
25
|
+
if (lower.includes("http://") || lower.includes("https://")) {
|
|
26
|
+
patterns.push("url.embedded");
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
if (typeof body === "string") {
|
|
30
|
+
checkString(body);
|
|
31
|
+
}
|
|
32
|
+
else if (body && typeof body === "object") {
|
|
33
|
+
const walk = (object, depth = 0) => {
|
|
34
|
+
if (depth > 2)
|
|
35
|
+
return; // limit traversal depth
|
|
36
|
+
for (const v of Object.values(object)) {
|
|
37
|
+
if (typeof v === "string") {
|
|
38
|
+
checkString(v);
|
|
39
|
+
}
|
|
40
|
+
else if (Array.isArray(v)) {
|
|
41
|
+
for (const x of v.slice(0, 10)) {
|
|
42
|
+
if (typeof x === "string") {
|
|
43
|
+
checkString(x);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (v && typeof v === "object") {
|
|
48
|
+
walk(v, depth + 1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
walk(body);
|
|
53
|
+
}
|
|
54
|
+
return [...new Set(patterns)];
|
|
55
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for file handling in API endpoints
|
|
3
|
+
* Defines file size limits
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Maximum file size in bytes (10 MB)
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_MAX_FILE_SIZE: number;
|
|
9
|
+
/**
|
|
10
|
+
* Allowed image MIME types for image eventification
|
|
11
|
+
*/
|
|
12
|
+
export declare const IMAGE_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp"];
|
|
13
|
+
/**
|
|
14
|
+
* PDF MIME type for PDF image extraction
|
|
15
|
+
*/
|
|
16
|
+
export declare const PDF_MIME_TYPES: readonly ["application/pdf"];
|
|
17
|
+
/**
|
|
18
|
+
* Combined MIME types for image endpoint (images + PDF)
|
|
19
|
+
* PDF files are converted to images before processing
|
|
20
|
+
*/
|
|
21
|
+
export declare const IMAGE_ENDPOINT_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "application/pdf"];
|
|
22
|
+
/**
|
|
23
|
+
* Allowed document MIME types for document eventification
|
|
24
|
+
* Supports PDF, DOC, DOCX, PPT, PPTX
|
|
25
|
+
*/
|
|
26
|
+
export declare const DOCUMENT_MIME_TYPES: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation"];
|
|
27
|
+
export type ImageMimeType = (typeof IMAGE_MIME_TYPES)[number];
|
|
28
|
+
export type PdfMimeType = (typeof PDF_MIME_TYPES)[number];
|
|
29
|
+
export type ImageEndpointMimeType = (typeof IMAGE_ENDPOINT_MIME_TYPES)[number];
|
|
30
|
+
export type DocumentMimeType = (typeof DOCUMENT_MIME_TYPES)[number];
|
|
31
|
+
export type AllowedMimeType = ImageMimeType | DocumentMimeType | PdfMimeType;
|
|
32
|
+
//# sourceMappingURL=eventify-constants.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventify-constants.types.d.ts","sourceRoot":"","sources":["../../src/helpers/eventify-constants.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAAmB,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,gBAAgB,iEAKnB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,cAAc,8BAA+B,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,yBAAyB,oFAG5B,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,mBAAmB,6OAMtB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1D,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC/E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AACpE,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,gBAAgB,GAAG,WAAW,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for file handling in API endpoints
|
|
3
|
+
* Defines file size limits
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Maximum file size in bytes (10 MB)
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB
|
|
9
|
+
/**
|
|
10
|
+
* Allowed image MIME types for image eventification
|
|
11
|
+
*/
|
|
12
|
+
export const IMAGE_MIME_TYPES = [
|
|
13
|
+
'image/jpeg',
|
|
14
|
+
'image/png',
|
|
15
|
+
'image/gif',
|
|
16
|
+
'image/webp',
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* PDF MIME type for PDF image extraction
|
|
20
|
+
*/
|
|
21
|
+
export const PDF_MIME_TYPES = ['application/pdf'];
|
|
22
|
+
/**
|
|
23
|
+
* Combined MIME types for image endpoint (images + PDF)
|
|
24
|
+
* PDF files are converted to images before processing
|
|
25
|
+
*/
|
|
26
|
+
export const IMAGE_ENDPOINT_MIME_TYPES = [
|
|
27
|
+
...IMAGE_MIME_TYPES,
|
|
28
|
+
...PDF_MIME_TYPES,
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* Allowed document MIME types for document eventification
|
|
32
|
+
* Supports PDF, DOC, DOCX, PPT, PPTX
|
|
33
|
+
*/
|
|
34
|
+
export const DOCUMENT_MIME_TYPES = [
|
|
35
|
+
'application/pdf',
|
|
36
|
+
'application/msword', // DOC
|
|
37
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // DOCX
|
|
38
|
+
'application/vnd.ms-powerpoint', // PPT
|
|
39
|
+
'application/vnd.openxmlformats-officedocument.presentationml.presentation', // PPTX
|
|
40
|
+
];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes a deterministic SHA-256 hash from binary data
|
|
3
|
+
*
|
|
4
|
+
* Algorithm: SHA-256 (non-reversible cryptographic hash)
|
|
5
|
+
* Output: Hex-encoded string (64 characters)
|
|
6
|
+
*
|
|
7
|
+
* The same binary input will always produce the same hash output,
|
|
8
|
+
* making it suitable for content-based deduplication and caching.
|
|
9
|
+
*
|
|
10
|
+
* @param data Binary data as Buffer or Uint8Array
|
|
11
|
+
* @returns Hex-encoded SHA-256 hash string (64 characters)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const fileBytes = Buffer.from('example file content');
|
|
16
|
+
* const hash = hashBinary(fileBytes);
|
|
17
|
+
* // hash = "50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c"
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function hashBinary(data: Buffer | Uint8Array): string;
|
|
21
|
+
//# sourceMappingURL=hash-binary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-binary.d.ts","sourceRoot":"","sources":["../../src/helpers/hash-binary.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAQ5D"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Computes a deterministic SHA-256 hash from binary data
|
|
4
|
+
*
|
|
5
|
+
* Algorithm: SHA-256 (non-reversible cryptographic hash)
|
|
6
|
+
* Output: Hex-encoded string (64 characters)
|
|
7
|
+
*
|
|
8
|
+
* The same binary input will always produce the same hash output,
|
|
9
|
+
* making it suitable for content-based deduplication and caching.
|
|
10
|
+
*
|
|
11
|
+
* @param data Binary data as Buffer or Uint8Array
|
|
12
|
+
* @returns Hex-encoded SHA-256 hash string (64 characters)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const fileBytes = Buffer.from('example file content');
|
|
17
|
+
* const hash = hashBinary(fileBytes);
|
|
18
|
+
* // hash = "50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c"
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function hashBinary(data) {
|
|
22
|
+
// Convert Uint8Array to Buffer if needed
|
|
23
|
+
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
24
|
+
// Compute SHA-256 hash and encode as hex
|
|
25
|
+
const hash = createHash('sha256');
|
|
26
|
+
hash.update(buffer);
|
|
27
|
+
return hash.digest('hex');
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-image-mime-type.d.ts","sourceRoot":"","sources":["../../../src/helpers/mime-types/detect-image-mime-type.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA8CtE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect image MIME types from magic bytes
|
|
3
|
+
*/
|
|
4
|
+
export function detectImageMimeType(buffer) {
|
|
5
|
+
if (buffer.length < 4) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
// JPEG: FF D8 FF E0
|
|
9
|
+
if (buffer[0] === 0xFF && buffer[1] === 0xD8 && buffer[2] === 0xFF && buffer[3] === 0xE0) {
|
|
10
|
+
return "image/jpeg";
|
|
11
|
+
}
|
|
12
|
+
// PNG: 89 50 4E 47 0D 0A 1A 0A
|
|
13
|
+
if (buffer.length >= 8 &&
|
|
14
|
+
buffer[0] === 0x89 &&
|
|
15
|
+
buffer[1] === 0x50 &&
|
|
16
|
+
buffer[2] === 0x4E &&
|
|
17
|
+
buffer[3] === 0x47 &&
|
|
18
|
+
buffer[4] === 0x0D &&
|
|
19
|
+
buffer[5] === 0x0A &&
|
|
20
|
+
buffer[6] === 0x1A &&
|
|
21
|
+
buffer[7] === 0x0A) {
|
|
22
|
+
return "image/png";
|
|
23
|
+
}
|
|
24
|
+
// GIF: 47 49 46 (GIF87a or GIF89a)
|
|
25
|
+
if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46) {
|
|
26
|
+
return "image/gif";
|
|
27
|
+
}
|
|
28
|
+
// WebP: RIFF....WEBP (52 49 46 46 ... 57 45 42 50)
|
|
29
|
+
if (buffer.length >= 12 &&
|
|
30
|
+
buffer[0] === 0x52 &&
|
|
31
|
+
buffer[1] === 0x49 &&
|
|
32
|
+
buffer[2] === 0x46 &&
|
|
33
|
+
buffer[3] === 0x46 &&
|
|
34
|
+
buffer[8] === 0x57 &&
|
|
35
|
+
buffer[9] === 0x45 &&
|
|
36
|
+
buffer[10] === 0x42 &&
|
|
37
|
+
buffer[11] === 0x50) {
|
|
38
|
+
return "image/webp";
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-ole-mime-type.d.ts","sourceRoot":"","sources":["../../../src/helpers/mime-types/detect-ole-mime-type.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAuCpE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect OLE2 (legacy Office) formats from magic bytes
|
|
3
|
+
* Detects DOC, PPT, and XLS files which use OLE2 container format
|
|
4
|
+
*/
|
|
5
|
+
export function detectOleMimeType(buffer) {
|
|
6
|
+
if (buffer.length < 8) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
// OLE2 signature: D0 CF 11 E0 A1 B1 1A E1
|
|
10
|
+
if (!(buffer[0] === 0xD0 &&
|
|
11
|
+
buffer[1] === 0xCF &&
|
|
12
|
+
buffer[2] === 0x11 &&
|
|
13
|
+
buffer[3] === 0xE0 &&
|
|
14
|
+
buffer[4] === 0xA1 &&
|
|
15
|
+
buffer[5] === 0xB1 &&
|
|
16
|
+
buffer[6] === 0x1A &&
|
|
17
|
+
buffer[7] === 0xE1)) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
// If it's OLE2, try to detect Office type by looking for content indicators
|
|
21
|
+
// Look for "PowerPoint Document" or "Word.Document" in buffer
|
|
22
|
+
const bufferString = buffer.toString("utf8", 0, Math.min(buffer.length, 1024));
|
|
23
|
+
if (bufferString.includes("PowerPoint Document")) {
|
|
24
|
+
return "application/vnd.ms-powerpoint";
|
|
25
|
+
}
|
|
26
|
+
if (bufferString.includes("Word.Document") || bufferString.includes("Microsoft Word")) {
|
|
27
|
+
return "application/msword";
|
|
28
|
+
}
|
|
29
|
+
if (bufferString.includes("Workbook") || bufferString.includes("Excel")) {
|
|
30
|
+
return "application/vnd.ms-excel";
|
|
31
|
+
}
|
|
32
|
+
// Default OLE2 MIME type is Word document
|
|
33
|
+
return "application/msword";
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-pdf-mime-type.d.ts","sourceRoot":"","sources":["../../../src/helpers/mime-types/detect-pdf-mime-type.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAWpE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect PDF MIME type from magic bytes
|
|
3
|
+
*/
|
|
4
|
+
export function detectPdfMimeType(buffer) {
|
|
5
|
+
if (buffer.length < 4) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
// PDF: 25 50 44 46 (%PDF)
|
|
9
|
+
if (buffer[0] === 0x25 && buffer[1] === 0x50 && buffer[2] === 0x44 && buffer[3] === 0x46) {
|
|
10
|
+
return "application/pdf";
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect ZIP-based Office formats from magic bytes
|
|
3
|
+
* Detects DOCX, PPTX by checking ZIP signature followed by Office content
|
|
4
|
+
*/
|
|
5
|
+
export declare function detectZipMimeType(buffer: Buffer): string | undefined;
|
|
6
|
+
//# sourceMappingURL=detect-zip-mime-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-zip-mime-type.d.ts","sourceRoot":"","sources":["../../../src/helpers/mime-types/detect-zip-mime-type.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAuBpE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect ZIP-based Office formats from magic bytes
|
|
3
|
+
* Detects DOCX, PPTX by checking ZIP signature followed by Office content
|
|
4
|
+
*/
|
|
5
|
+
export function detectZipMimeType(buffer) {
|
|
6
|
+
if (buffer.length < 4) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
// ZIP signature: 50 4B 03 04
|
|
10
|
+
if (!(buffer[0] === 0x50 && buffer[1] === 0x4B && buffer[2] === 0x03 && buffer[3] === 0x04)) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
// If it's a ZIP, check for Office format indicators
|
|
14
|
+
// Look for word/ or ppt/ in the buffer to distinguish Office formats
|
|
15
|
+
const bufferString = buffer.toString("utf8", 30, Math.min(buffer.length, 8192)).toLowerCase();
|
|
16
|
+
if (bufferString.includes("word/")) {
|
|
17
|
+
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
18
|
+
}
|
|
19
|
+
if (bufferString.includes("ppt/")) {
|
|
20
|
+
return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates that a string parameter does not contain suspicious patterns
|
|
3
|
+
* that could indicate injection attacks or other security threats.
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateNoSuspiciousPatterns(value: string, parameterName: string): string;
|
|
6
|
+
//# sourceMappingURL=parameter-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parameter-validation.d.ts","sourceRoot":"","sources":["../../src/helpers/parameter-validation.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,MAAM,CAkBR"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getLogger } from "@schafevormfenster/logging";
|
|
2
|
+
import { detectSuspiciousPatternsFromBody } from "./detect-suspicious-patterns";
|
|
3
|
+
const log = getLogger("rest.helpers.parameter-validation");
|
|
4
|
+
/**
|
|
5
|
+
* Validates that a string parameter does not contain suspicious patterns
|
|
6
|
+
* that could indicate injection attacks or other security threats.
|
|
7
|
+
*/
|
|
8
|
+
export function validateNoSuspiciousPatterns(value, parameterName) {
|
|
9
|
+
const suspiciousPatterns = detectSuspiciousPatternsFromBody(value);
|
|
10
|
+
if (suspiciousPatterns.length > 0) {
|
|
11
|
+
log.error({
|
|
12
|
+
parameterName,
|
|
13
|
+
suspiciousPatterns,
|
|
14
|
+
error: `Parameter '${parameterName}' contains suspicious patterns`,
|
|
15
|
+
}, `Parameter '${parameterName}' contains suspicious patterns: ${suspiciousPatterns.join(", ")}`);
|
|
16
|
+
throw new Error(`Parameter '${parameterName}' contains suspicious patterns: ${suspiciousPatterns.join(", ")}`);
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schema for validating location parameter in findbyaddress endpoint.
|
|
3
|
+
* Checks for minimum length and suspicious patterns.
|
|
4
|
+
*/
|
|
5
|
+
export declare const LocationParameterSchema: any;
|
|
6
|
+
/**
|
|
7
|
+
* Zod schema for validating slug parameter in community slug endpoint.
|
|
8
|
+
* Checks for length between 2-150 characters and suspicious patterns.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SlugParameterSchema: any;
|
|
11
|
+
/**
|
|
12
|
+
* Zod schema for validating ID parameter in community ID endpoint.
|
|
13
|
+
* Checks that ID contains only numbers and is between 3-20 characters long.
|
|
14
|
+
*/
|
|
15
|
+
export declare const NumericIdParameterSchema: any;
|
|
16
|
+
//# sourceMappingURL=parameter-validation.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parameter-validation.types.d.ts","sourceRoot":"","sources":["../../src/helpers/parameter-validation.types.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAWjC,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KAY7B,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,wBAAwB,KAIuB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { validateNoSuspiciousPatterns } from "./parameter-validation";
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for validating location parameter in findbyaddress endpoint.
|
|
5
|
+
* Checks for minimum length and suspicious patterns.
|
|
6
|
+
*/
|
|
7
|
+
export const LocationParameterSchema = z
|
|
8
|
+
.string()
|
|
9
|
+
.min(2, "Location must be at least 2 characters long")
|
|
10
|
+
.refine((value) => {
|
|
11
|
+
validateNoSuspiciousPatterns(value, "location");
|
|
12
|
+
return true;
|
|
13
|
+
}, {
|
|
14
|
+
message: "Location parameter contains suspicious patterns that are not allowed",
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Zod schema for validating slug parameter in community slug endpoint.
|
|
18
|
+
* Checks for length between 2-150 characters and suspicious patterns.
|
|
19
|
+
*/
|
|
20
|
+
export const SlugParameterSchema = z
|
|
21
|
+
.string()
|
|
22
|
+
.min(2, "Slug must be at least 2 characters long")
|
|
23
|
+
.max(150, "Slug must not exceed 150 characters")
|
|
24
|
+
.refine((value) => {
|
|
25
|
+
validateNoSuspiciousPatterns(value, "slug");
|
|
26
|
+
return true;
|
|
27
|
+
}, {
|
|
28
|
+
message: "Slug parameter contains suspicious patterns that are not allowed",
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Zod schema for validating ID parameter in community ID endpoint.
|
|
32
|
+
* Checks that ID contains only numbers and is between 3-20 characters long.
|
|
33
|
+
*/
|
|
34
|
+
export const NumericIdParameterSchema = z
|
|
35
|
+
.string()
|
|
36
|
+
.min(3, "ID must be at least 3 characters long")
|
|
37
|
+
.max(20, "ID must not exceed 20 characters")
|
|
38
|
+
.regex(/^\d+$/, "ID must contain only numeric characters");
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a consistent set of headers for unauthorized API responses, including
|
|
3
|
+
* security headers and correlation id propagation.
|
|
4
|
+
*/
|
|
5
|
+
export declare function buildApiUnauthorizedHeaders(correlationId: string): Record<string, string>;
|
|
6
|
+
//# sourceMappingURL=build-api-unauthorized-headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-api-unauthorized-headers.d.ts","sourceRoot":"","sources":["../../../src/helpers/response-headers/build-api-unauthorized-headers.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,GACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmBxB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getApiSecurityHeaders } from "@schafevormfenster/security";
|
|
2
|
+
import { resolveEnvironment } from "./resolve-environment";
|
|
3
|
+
/**
|
|
4
|
+
* Build a consistent set of headers for unauthorized API responses, including
|
|
5
|
+
* security headers and correlation id propagation.
|
|
6
|
+
*/
|
|
7
|
+
export function buildApiUnauthorizedHeaders(correlationId) {
|
|
8
|
+
const environment = resolveEnvironment();
|
|
9
|
+
const securityHeaders = getApiSecurityHeaders({
|
|
10
|
+
environment,
|
|
11
|
+
enforceHTTPS: environment !== "development",
|
|
12
|
+
allowEmbedding: false,
|
|
13
|
+
});
|
|
14
|
+
const result = {
|
|
15
|
+
"content-type": "application/json",
|
|
16
|
+
"Cache-Control": "no-store",
|
|
17
|
+
"x-correlation-id": correlationId,
|
|
18
|
+
};
|
|
19
|
+
for (const h of securityHeaders) {
|
|
20
|
+
result[h.key] = h.value;
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
}
|