@bgord/bun 1.23.1 → 1.23.3
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/dist/better-auth-logger.service.d.ts +1 -1
- package/dist/better-auth-logger.service.d.ts.map +1 -1
- package/dist/better-auth-logger.service.js +8 -3
- package/dist/better-auth-logger.service.js.map +1 -1
- package/dist/error-classifier-http-exception-hono.strategy.d.ts.map +1 -1
- package/dist/error-classifier-http-exception-hono.strategy.js +3 -2
- package/dist/error-classifier-http-exception-hono.strategy.js.map +1 -1
- package/dist/event.types.d.ts +2 -0
- package/dist/event.types.d.ts.map +1 -1
- package/dist/file-type-detector-fixed.strategy.d.ts +8 -0
- package/dist/file-type-detector-fixed.strategy.d.ts.map +1 -0
- package/dist/file-type-detector-fixed.strategy.js +10 -0
- package/dist/file-type-detector-fixed.strategy.js.map +1 -0
- package/dist/file-type-detector-magic-bytes.strategy.d.ts +6 -0
- package/dist/file-type-detector-magic-bytes.strategy.d.ts.map +1 -0
- package/dist/file-type-detector-magic-bytes.strategy.js +25 -0
- package/dist/file-type-detector-magic-bytes.strategy.js.map +1 -0
- package/dist/file-type-detector-text.strategy.d.ts +8 -0
- package/dist/file-type-detector-text.strategy.d.ts.map +1 -0
- package/dist/file-type-detector-text.strategy.js +22 -0
- package/dist/file-type-detector-text.strategy.js.map +1 -0
- package/dist/file-type-detector.strategy.d.ts +5 -0
- package/dist/file-type-detector.strategy.d.ts.map +1 -0
- package/dist/file-type-detector.strategy.js +2 -0
- package/dist/file-type-detector.strategy.js.map +1 -0
- package/dist/file-uploader-hono.middleware.d.ts +6 -1
- package/dist/file-uploader-hono.middleware.d.ts.map +1 -1
- package/dist/file-uploader-hono.middleware.js +2 -2
- package/dist/file-uploader-hono.middleware.js.map +1 -1
- package/dist/file-uploader.middleware.d.ts +7 -1
- package/dist/file-uploader.middleware.d.ts.map +1 -1
- package/dist/file-uploader.middleware.js +6 -3
- package/dist/file-uploader.middleware.js.map +1 -1
- package/dist/hcaptcha.service.d.ts +2 -1
- package/dist/hcaptcha.service.d.ts.map +1 -1
- package/dist/hcaptcha.service.js +2 -2
- package/dist/hcaptcha.service.js.map +1 -1
- package/dist/healthcheck.handler.d.ts +1 -1
- package/dist/healthcheck.handler.d.ts.map +1 -1
- package/dist/healthcheck.handler.js +1 -1
- package/dist/healthcheck.handler.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/language-detector-header.strategy.d.ts.map +1 -1
- package/dist/language-detector-header.strategy.js +0 -1
- package/dist/language-detector-header.strategy.js.map +1 -1
- package/dist/readiness.handler.d.ts +2 -0
- package/dist/readiness.handler.d.ts.map +1 -1
- package/dist/readiness.handler.js +1 -1
- package/dist/readiness.handler.js.map +1 -1
- package/dist/remote-file-storage-disk.adapter.d.ts.map +1 -1
- package/dist/remote-file-storage-disk.adapter.js +4 -1
- package/dist/remote-file-storage-disk.adapter.js.map +1 -1
- package/dist/sealer-aes-gcm.adapter.d.ts.map +1 -1
- package/dist/sealer-aes-gcm.adapter.js +8 -3
- package/dist/sealer-aes-gcm.adapter.js.map +1 -1
- package/dist/security-rule-user-agent.strategy.d.ts.map +1 -1
- package/dist/security-rule-user-agent.strategy.js +4 -3
- package/dist/security-rule-user-agent.strategy.js.map +1 -1
- package/dist/security-rule-violation-threshold.strategy.d.ts +3 -0
- package/dist/security-rule-violation-threshold.strategy.d.ts.map +1 -1
- package/dist/security-rule-violation-threshold.strategy.js +3 -3
- package/dist/security-rule-violation-threshold.strategy.js.map +1 -1
- package/dist/shield-body-limit.strategy.d.ts.map +1 -1
- package/dist/shield-body-limit.strategy.js +3 -1
- package/dist/shield-body-limit.strategy.js.map +1 -1
- package/dist/shield-hcaptcha-hono-local.strategy.d.ts +1 -0
- package/dist/shield-hcaptcha-hono-local.strategy.d.ts.map +1 -1
- package/dist/shield-hcaptcha-hono-local.strategy.js +5 -1
- package/dist/shield-hcaptcha-hono-local.strategy.js.map +1 -1
- package/dist/shield-hcaptcha-hono.strategy.d.ts +2 -2
- package/dist/shield-hcaptcha-hono.strategy.d.ts.map +1 -1
- package/dist/shield-hcaptcha-hono.strategy.js +3 -3
- package/dist/shield-hcaptcha-hono.strategy.js.map +1 -1
- package/dist/shield-hcaptcha.strategy.d.ts +6 -2
- package/dist/shield-hcaptcha.strategy.d.ts.map +1 -1
- package/dist/shield-hcaptcha.strategy.js +9 -5
- package/dist/shield-hcaptcha.strategy.js.map +1 -1
- package/dist/shield-recaptcha.strategy.d.ts +4 -0
- package/dist/shield-recaptcha.strategy.d.ts.map +1 -1
- package/dist/shield-recaptcha.strategy.js +4 -0
- package/dist/shield-recaptcha.strategy.js.map +1 -1
- package/dist/subject-segment-remote-ip.strategy.d.ts +7 -0
- package/dist/subject-segment-remote-ip.strategy.d.ts.map +1 -0
- package/dist/subject-segment-remote-ip.strategy.js +8 -0
- package/dist/subject-segment-remote-ip.strategy.js.map +1 -0
- package/dist/subject-segment-request.strategy.d.ts +2 -2
- package/dist/subject-segment-request.strategy.d.ts.map +1 -1
- package/dist/subject-segment-request.strategy.js.map +1 -1
- package/dist/webhook-body-builder-signed-headers.strategy.d.ts +8 -0
- package/dist/webhook-body-builder-signed-headers.strategy.d.ts.map +1 -0
- package/dist/webhook-body-builder-signed-headers.strategy.js +11 -0
- package/dist/webhook-body-builder-signed-headers.strategy.js.map +1 -0
- package/dist/webhook-signature.vo.d.ts +2 -1
- package/dist/webhook-signature.vo.d.ts.map +1 -1
- package/dist/webhook-signature.vo.js +4 -1
- package/dist/webhook-signature.vo.js.map +1 -1
- package/dist/webhook-verifier-sha256.strategy.d.ts.map +1 -1
- package/dist/webhook-verifier-sha256.strategy.js +4 -3
- package/dist/webhook-verifier-sha256.strategy.js.map +1 -1
- package/dist/woodchopper.d.ts +1 -1
- package/dist/woodchopper.d.ts.map +1 -1
- package/dist/woodchopper.js +1 -3
- package/dist/woodchopper.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +6 -0
- package/src/better-auth-logger.service.ts +8 -3
- package/src/error-classifier-http-exception-hono.strategy.ts +6 -1
- package/src/event.types.ts +2 -0
- package/src/file-type-detector-fixed.strategy.ts +10 -0
- package/src/file-type-detector-magic-bytes.strategy.ts +32 -0
- package/src/file-type-detector-text.strategy.ts +25 -0
- package/src/file-type-detector.strategy.ts +5 -0
- package/src/file-uploader-hono.middleware.ts +5 -2
- package/src/file-uploader.middleware.ts +10 -3
- package/src/hcaptcha.service.ts +3 -6
- package/src/healthcheck.handler.ts +2 -2
- package/src/index.ts +6 -0
- package/src/language-detector-header.strategy.ts +0 -1
- package/src/readiness.handler.ts +6 -2
- package/src/remote-file-storage-disk.adapter.ts +4 -1
- package/src/sealer-aes-gcm.adapter.ts +7 -3
- package/src/security-rule-user-agent.strategy.ts +4 -3
- package/src/security-rule-violation-threshold.strategy.ts +14 -8
- package/src/shield-body-limit.strategy.ts +3 -1
- package/src/shield-hcaptcha-hono-local.strategy.ts +6 -1
- package/src/shield-hcaptcha-hono.strategy.ts +7 -4
- package/src/shield-hcaptcha.strategy.ts +8 -3
- package/src/shield-recaptcha.strategy.ts +9 -2
- package/src/subject-segment-remote-ip.strategy.ts +14 -0
- package/src/subject-segment-request.strategy.ts +2 -0
- package/src/webhook-body-builder-signed-headers.strategy.ts +12 -0
- package/src/webhook-signature.vo.ts +5 -0
- package/src/webhook-verifier-sha256.strategy.ts +4 -3
- package/src/woodchopper.ts +2 -4
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { HasRequestHeader, HasRequestText } from "./request-context.port";
|
|
2
|
+
import type { WebhookBodyBuilderStrategy } from "./webhook-body-builder.strategy";
|
|
3
|
+
export declare class WebhookBodyBuilderSignedHeadersStrategy implements WebhookBodyBuilderStrategy {
|
|
4
|
+
private readonly headers;
|
|
5
|
+
constructor(headers: ReadonlyArray<string>);
|
|
6
|
+
build(context: HasRequestHeader & HasRequestText): Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=webhook-body-builder-signed-headers.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-body-builder-signed-headers.strategy.d.ts","sourceRoot":"","sources":["../src/webhook-body-builder-signed-headers.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAElF,qBAAa,uCAAwC,YAAW,0BAA0B;IAC5E,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAAI;IAEzD,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAIvE;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export class WebhookBodyBuilderSignedHeadersStrategy {
|
|
2
|
+
headers;
|
|
3
|
+
constructor(headers) {
|
|
4
|
+
this.headers = headers;
|
|
5
|
+
}
|
|
6
|
+
async build(context) {
|
|
7
|
+
const headers = this.headers.map((name) => [name, context.request.header(name) ?? null]);
|
|
8
|
+
return JSON.stringify([headers, await context.request.text()]);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=webhook-body-builder-signed-headers.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-body-builder-signed-headers.strategy.js","sourceRoot":"","sources":["../src/webhook-body-builder-signed-headers.strategy.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,uCAAuC;IACrB,OAAO;IAApC,YAA6B,OAA8B;uBAA9B,OAAO;IAA0B,CAAC;IAE/D,KAAK,CAAC,KAAK,CAAC,OAA0C;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;QAEzF,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;CACF"}
|
|
@@ -2,7 +2,8 @@ import * as v from "valibot";
|
|
|
2
2
|
export declare const WebhookSignatureError: {
|
|
3
3
|
Type: string;
|
|
4
4
|
Empty: string;
|
|
5
|
+
InvalidHex: string;
|
|
5
6
|
};
|
|
6
|
-
export declare const WebhookSignature: v.SchemaWithPipe<readonly [v.StringSchema<string>, v.NonEmptyAction<string, string>, v.BrandAction<string, "WebhookSignature">]>;
|
|
7
|
+
export declare const WebhookSignature: v.SchemaWithPipe<readonly [v.StringSchema<string>, v.NonEmptyAction<string, string>, v.RegexAction<string, string>, v.BrandAction<string, "WebhookSignature">]>;
|
|
7
8
|
export type WebhookSignatureType = v.InferOutput<typeof WebhookSignature>;
|
|
8
9
|
//# sourceMappingURL=webhook-signature.vo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-signature.vo.d.ts","sourceRoot":"","sources":["../src/webhook-signature.vo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,eAAO,MAAM,qBAAqB;IAChC,IAAI;IACJ,KAAK;
|
|
1
|
+
{"version":3,"file":"webhook-signature.vo.d.ts","sourceRoot":"","sources":["../src/webhook-signature.vo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,eAAO,MAAM,qBAAqB;IAChC,IAAI;IACJ,KAAK;IACL,UAAU;CACX,CAAC;AAKF,eAAO,MAAM,gBAAgB,iKAM5B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
|
@@ -2,8 +2,11 @@ import * as v from "valibot";
|
|
|
2
2
|
export const WebhookSignatureError = {
|
|
3
3
|
Type: "webhook.signature.type",
|
|
4
4
|
Empty: "webhook.signature.empty",
|
|
5
|
+
InvalidHex: "webhook.signature.invalid.hex",
|
|
5
6
|
};
|
|
6
|
-
|
|
7
|
+
// Hex chars allowed
|
|
8
|
+
const CHARS_WHITELIST = /^[a-fA-F0-9]+$/;
|
|
9
|
+
export const WebhookSignature = v.pipe(v.string(WebhookSignatureError.Type), v.nonEmpty(WebhookSignatureError.Empty), v.regex(CHARS_WHITELIST, WebhookSignatureError.InvalidHex),
|
|
7
10
|
// Stryker disable next-line StringLiteral
|
|
8
11
|
v.brand("WebhookSignature"));
|
|
9
12
|
//# sourceMappingURL=webhook-signature.vo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-signature.vo.js","sourceRoot":"","sources":["../src/webhook-signature.vo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,wBAAwB;IAC9B,KAAK,EAAE,yBAAyB;
|
|
1
|
+
{"version":3,"file":"webhook-signature.vo.js","sourceRoot":"","sources":["../src/webhook-signature.vo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,wBAAwB;IAC9B,KAAK,EAAE,yBAAyB;IAChC,UAAU,EAAE,+BAA+B;CAC5C,CAAC;AAEF,oBAAoB;AACpB,MAAM,eAAe,GAAG,gBAAgB,CAAC;AAEzC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CACpC,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,EACpC,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC,KAAK,CAAC,EACvC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE,qBAAqB,CAAC,UAAU,CAAC;AAC1D,0CAA0C;AAC1C,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAC5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-verifier-sha256.strategy.d.ts","sourceRoot":"","sources":["../src/webhook-verifier-sha256.strategy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAE3E,KAAK,MAAM,GAAG;IAAE,uBAAuB,EAAE,+BAA+B,CAAA;CAAE,CAAC;AAE3E,qBAAa,6BAA8B,YAAW,uBAAuB;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAnC,YAA6B,MAAM,EAAE,MAAM,EAAI;IAE/C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"webhook-verifier-sha256.strategy.d.ts","sourceRoot":"","sources":["../src/webhook-verifier-sha256.strategy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAE3E,KAAK,MAAM,GAAG;IAAE,uBAAuB,EAAE,+BAA+B,CAAA;CAAE,CAAC;AAE3E,qBAAa,6BAA8B,YAAW,uBAAuB;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAnC,YAA6B,MAAM,EAAE,MAAM,EAAI;IAE/C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB,GAAG,OAAO,CAM7D;CACF"}
|
|
@@ -5,10 +5,11 @@ export class WebhookVerifierSha256Strategy {
|
|
|
5
5
|
this.config = config;
|
|
6
6
|
}
|
|
7
7
|
verify(body, signature) {
|
|
8
|
-
const digest = this.config.WebhookSignatureCreator.create(body);
|
|
9
|
-
|
|
8
|
+
const digest = Buffer.from(this.config.WebhookSignatureCreator.create(body));
|
|
9
|
+
const candidate = Buffer.from(signature);
|
|
10
|
+
if (digest.length !== candidate.length)
|
|
10
11
|
return false;
|
|
11
|
-
return timingSafeEqual(
|
|
12
|
+
return timingSafeEqual(digest, candidate);
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
//# sourceMappingURL=webhook-verifier-sha256.strategy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-verifier-sha256.strategy.js","sourceRoot":"","sources":["../src/webhook-verifier-sha256.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAO9C,MAAM,OAAO,6BAA6B;IACX,MAAM;IAAnC,YAA6B,MAAc;sBAAd,MAAM;IAAW,CAAC;IAE/C,MAAM,CAAC,IAAY,EAAE,SAA+B;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"webhook-verifier-sha256.strategy.js","sourceRoot":"","sources":["../src/webhook-verifier-sha256.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAO9C,MAAM,OAAO,6BAA6B;IACX,MAAM;IAAnC,YAA6B,MAAc;sBAAd,MAAM;IAAW,CAAC;IAE/C,MAAM,CAAC,IAAY,EAAE,SAA+B;QAClD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7E,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEzC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACrD,OAAO,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;CACF"}
|
package/dist/woodchopper.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type WoodchopperConfig = {
|
|
|
10
10
|
level: LogLevelEnum;
|
|
11
11
|
environment: NodeEnvironmentEnum;
|
|
12
12
|
dispatcher: WoodchopperDispatcher;
|
|
13
|
-
redactor
|
|
13
|
+
redactor: RedactorStrategy;
|
|
14
14
|
diagnostics?: WoodchopperDiagnosticsStrategy;
|
|
15
15
|
};
|
|
16
16
|
type Dependencies = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"woodchopper.d.ts","sourceRoot":"","sources":["../src/woodchopper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EACL,KAAK,aAAa,EAIlB,KAAK,UAAU,EACf,YAAY,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACzF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAG/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,EAAE,mBAAmB,CAAC;IACjC,UAAU,EAAE,qBAAqB,CAAC;IAClC,QAAQ,
|
|
1
|
+
{"version":3,"file":"woodchopper.d.ts","sourceRoot":"","sources":["../src/woodchopper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EACL,KAAK,aAAa,EAIlB,KAAK,UAAU,EACf,YAAY,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACzF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAG/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,EAAE,mBAAmB,CAAC;IACjC,UAAU,EAAE,qBAAqB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,WAAW,CAAC,EAAE,8BAA8B,CAAC;CAC9C,CAAC;AAEF,KAAK,YAAY,GAAG;IAAE,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC;AAYzC,qBAAa,WAAY,YAAW,UAAU,EAAE,uBAAuB;IAKnE,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAEhD,YACmB,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,YAAY,EAQpC;IAED,OAAO,CAAC,GAAG;IA0CX,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAkD;IAC5E,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAiD;IACzE,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAiD;IACzE,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAiD;IACzE,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,CAAoD;IAClF,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAkD;IAC5E,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAkD;IAE5E,KAAK,SAKJ;IAED,QAAQ,IAAI,mBAAmB,CAE9B;CACF"}
|
package/dist/woodchopper.js
CHANGED
|
@@ -58,9 +58,7 @@ export class Woodchopper {
|
|
|
58
58
|
}
|
|
59
59
|
let withRedaction;
|
|
60
60
|
try {
|
|
61
|
-
withRedaction = this.config.redactor
|
|
62
|
-
? this.config.redactor.redact(withInjectedFields)
|
|
63
|
-
: withInjectedFields;
|
|
61
|
+
withRedaction = this.config.redactor.redact(withInjectedFields);
|
|
64
62
|
}
|
|
65
63
|
catch (error) {
|
|
66
64
|
this.stats.recordDropped();
|
package/dist/woodchopper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"woodchopper.js","sourceRoot":"","sources":["../src/woodchopper.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"woodchopper.js","sourceRoot":"","sources":["../src/woodchopper.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -207,6 +207,10 @@ src/
|
|
|
207
207
|
├── file-renamer-node.adapter.ts
|
|
208
208
|
├── file-renamer-noop.adapter.ts
|
|
209
209
|
├── file-renamer.port.ts
|
|
210
|
+
├── file-type-detector-fixed.strategy.ts
|
|
211
|
+
├── file-type-detector-magic-bytes.strategy.ts
|
|
212
|
+
├── file-type-detector-text.strategy.ts
|
|
213
|
+
├── file-type-detector.strategy.ts
|
|
210
214
|
├── file-uploader-hono.middleware.ts
|
|
211
215
|
├── file-uploader.middleware.ts
|
|
212
216
|
├── file-writer-forgiving.adapter.ts
|
|
@@ -615,6 +619,7 @@ src/
|
|
|
615
619
|
├── subject-segment-param.strategy.ts
|
|
616
620
|
├── subject-segment-path.strategy.ts
|
|
617
621
|
├── subject-segment-query.strategy.ts
|
|
622
|
+
├── subject-segment-remote-ip.strategy.ts
|
|
618
623
|
├── subject-segment-request.strategy.ts
|
|
619
624
|
├── subject-segment-user.strategy.ts
|
|
620
625
|
├── temporary-file-absolute.adapter.ts
|
|
@@ -653,6 +658,7 @@ src/
|
|
|
653
658
|
├── weak-etag-extractor-param.strategy.ts
|
|
654
659
|
├── weak-etag-extractor.middleware.ts
|
|
655
660
|
├── weak-etag-extractor.strategy.ts
|
|
661
|
+
├── webhook-body-builder-signed-headers.strategy.ts
|
|
656
662
|
├── webhook-body-builder-text.strategy.ts
|
|
657
663
|
├── webhook-body-builder.strategy.ts
|
|
658
664
|
├── webhook-id-extractor-header.strategy.ts
|
|
@@ -11,13 +11,18 @@ export class BetterAuthLogger {
|
|
|
11
11
|
return {
|
|
12
12
|
disabled: false,
|
|
13
13
|
level: "debug",
|
|
14
|
-
log: (level: LogLevel | undefined, message: string, ...
|
|
15
|
-
const entry = {
|
|
14
|
+
log: (level: LogLevel | undefined, message: string, ...params: ReadonlyArray<unknown>) => {
|
|
15
|
+
const entry = {
|
|
16
|
+
component: "infra",
|
|
17
|
+
operation: "better-auth",
|
|
18
|
+
message,
|
|
19
|
+
metadata: { params },
|
|
20
|
+
} as const;
|
|
16
21
|
|
|
17
22
|
if (level === "error") {
|
|
18
23
|
this.deps.Logger.error({
|
|
19
24
|
...entry,
|
|
20
|
-
error:
|
|
25
|
+
error: params.find((param) => param instanceof Error) ?? new Error(message),
|
|
21
26
|
});
|
|
22
27
|
} else if (level === "warn") {
|
|
23
28
|
this.deps.Logger.warn(entry);
|
|
@@ -15,7 +15,12 @@ export class ErrorClassifierHttpExceptionHonoStrategy implements ErrorClassifier
|
|
|
15
15
|
classify(error: unknown): Response | null {
|
|
16
16
|
if (!(error instanceof HTTPException)) return null;
|
|
17
17
|
|
|
18
|
-
if (!this.errors.has(error.message))
|
|
18
|
+
if (!this.errors.has(error.message)) {
|
|
19
|
+
return Response.json(
|
|
20
|
+
{ message: "general.unknown" },
|
|
21
|
+
{ status: error.status, headers: error.res?.headers },
|
|
22
|
+
);
|
|
23
|
+
}
|
|
19
24
|
|
|
20
25
|
return Response.json({ message: error.message }, { status: error.status, headers: error.res?.headers });
|
|
21
26
|
}
|
package/src/event.types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type * as tools from "@bgord/tools";
|
|
2
|
+
import type { CommitShaValueType } from "./commit-sha-value.vo";
|
|
2
3
|
import type { CorrelationIdType } from "./correlation-id.vo";
|
|
3
4
|
import type { EventStreamType } from "./event-stream.vo";
|
|
4
5
|
import type { UUIDType } from "./uuid.vo";
|
|
@@ -9,6 +10,7 @@ export type GenericEvent = {
|
|
|
9
10
|
createdAt: number;
|
|
10
11
|
stream: EventStreamType;
|
|
11
12
|
revision?: tools.RevisionValueType;
|
|
13
|
+
commit: CommitShaValueType;
|
|
12
14
|
name: string;
|
|
13
15
|
version: number;
|
|
14
16
|
payload: Record<string, unknown>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type * as tools from "@bgord/tools";
|
|
2
|
+
import type { FileTypeDetectorStrategy } from "./file-type-detector.strategy";
|
|
3
|
+
|
|
4
|
+
export class FileTypeDetectorFixedStrategy implements FileTypeDetectorStrategy {
|
|
5
|
+
constructor(private readonly mime: tools.Mime | null) {}
|
|
6
|
+
|
|
7
|
+
async detect(_file: File): Promise<tools.Mime | null> {
|
|
8
|
+
return this.mime;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// cSpell:ignore ftyp
|
|
2
|
+
import * as tools from "@bgord/tools";
|
|
3
|
+
import type { FileTypeDetectorStrategy } from "./file-type-detector.strategy";
|
|
4
|
+
|
|
5
|
+
type Signature = { mime: tools.Mime; offset: number; bytes: ReadonlyArray<number> };
|
|
6
|
+
|
|
7
|
+
const ASCII = (value: string): ReadonlyArray<number> => [...value].map((char) => char.charCodeAt(0));
|
|
8
|
+
|
|
9
|
+
const SIGNATURES: ReadonlyArray<Signature> = [
|
|
10
|
+
{ mime: tools.Mimes.png.mime, offset: 0, bytes: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a] },
|
|
11
|
+
{ mime: tools.Mimes.webp.mime, offset: 8, bytes: ASCII("WEBP") },
|
|
12
|
+
{ mime: tools.Mimes.wav.mime, offset: 8, bytes: ASCII("WAVE") },
|
|
13
|
+
{ mime: tools.Mimes.mp4.mime, offset: 4, bytes: ASCII("ftyp") },
|
|
14
|
+
{ mime: tools.Mimes.pdf.mime, offset: 0, bytes: ASCII("%PDF-") },
|
|
15
|
+
{ mime: tools.Mimes.zip.mime, offset: 0, bytes: [0x50, 0x4b, 0x03, 0x04] },
|
|
16
|
+
{ mime: tools.Mimes.jpg.mime, offset: 0, bytes: [0xff, 0xd8, 0xff] },
|
|
17
|
+
{ mime: tools.Mimes.tar.mime, offset: 0, bytes: [0x1f, 0x8b] },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
export class FileTypeDetectorMagicBytesStrategy implements FileTypeDetectorStrategy {
|
|
21
|
+
async detect(file: File): Promise<tools.Mime | null> {
|
|
22
|
+
const bytes = new Uint8Array(await file.slice(0, 12).arrayBuffer());
|
|
23
|
+
|
|
24
|
+
for (const signature of SIGNATURES) {
|
|
25
|
+
if (signature.bytes.every((byte, index) => bytes[signature.offset + index] === byte)) {
|
|
26
|
+
return signature.mime;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type * as tools from "@bgord/tools";
|
|
2
|
+
import type { FileTypeDetectorStrategy } from "./file-type-detector.strategy";
|
|
3
|
+
|
|
4
|
+
const ALLOWED_CONTROL_BYTES = [0x09, 0x0a, 0x0c, 0x0d];
|
|
5
|
+
|
|
6
|
+
const isControlByte = (byte: number) =>
|
|
7
|
+
(byte < 0x20 && !ALLOWED_CONTROL_BYTES.includes(byte)) || byte === 0x7f;
|
|
8
|
+
|
|
9
|
+
export class FileTypeDetectorTextStrategy implements FileTypeDetectorStrategy {
|
|
10
|
+
constructor(private readonly mime: tools.Mime) {}
|
|
11
|
+
|
|
12
|
+
async detect(file: File): Promise<tools.Mime | null> {
|
|
13
|
+
const bytes = new Uint8Array(await file.slice(0, 1445).arrayBuffer());
|
|
14
|
+
|
|
15
|
+
if (bytes.length === 0) return null;
|
|
16
|
+
if (bytes.some(isControlByte)) return null;
|
|
17
|
+
|
|
18
|
+
const text = new TextDecoder().decode(bytes);
|
|
19
|
+
|
|
20
|
+
if (text.includes("\ufffd")) return null;
|
|
21
|
+
if (text.trimStart().startsWith("<")) return null;
|
|
22
|
+
|
|
23
|
+
return this.mime;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { createMiddleware } from "hono/factory";
|
|
2
2
|
import { HTTPException } from "hono/http-exception";
|
|
3
|
+
import type { FileTypeDetectorStrategy } from "./file-type-detector.strategy";
|
|
3
4
|
import { type FileUploaderConfig, FileUploaderMiddleware } from "./file-uploader.middleware";
|
|
4
5
|
import type { MiddlewareHonoPort } from "./middleware-hono.port";
|
|
5
6
|
import { RequestContextHonoAdapter } from "./request-context-hono.adapter";
|
|
6
7
|
|
|
8
|
+
type Dependencies = { FileTypeDetector: FileTypeDetectorStrategy };
|
|
9
|
+
|
|
7
10
|
export class FileUploaderHonoMiddleware implements MiddlewareHonoPort {
|
|
8
11
|
private readonly middleware: FileUploaderMiddleware;
|
|
9
12
|
|
|
10
|
-
constructor(config: FileUploaderConfig) {
|
|
11
|
-
this.middleware = new FileUploaderMiddleware(config);
|
|
13
|
+
constructor(config: FileUploaderConfig, deps: Dependencies) {
|
|
14
|
+
this.middleware = new FileUploaderMiddleware(config, deps);
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
handle() {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as tools from "@bgord/tools";
|
|
2
|
+
import type { FileTypeDetectorStrategy } from "./file-type-detector.strategy";
|
|
2
3
|
import type { HasRequestForm } from "./request-context.port";
|
|
3
4
|
|
|
4
5
|
export type FileUploaderConfig = { MimeRegistry: tools.MimeRegistry; maxSize: tools.Size; field: string };
|
|
5
6
|
|
|
7
|
+
type Dependencies = { FileTypeDetector: FileTypeDetectorStrategy };
|
|
8
|
+
|
|
6
9
|
export const FileUploaderError = {
|
|
7
10
|
MissingFile: "file.uploader.missing.file",
|
|
8
11
|
EmptyFile: "file.uploader.empty.file",
|
|
@@ -15,7 +18,10 @@ export type FileValidationError = (typeof FileUploaderError)[keyof typeof FileUp
|
|
|
15
18
|
export type FileValidationResult = { valid: true } | { valid: false; error: FileValidationError };
|
|
16
19
|
|
|
17
20
|
export class FileUploaderMiddleware {
|
|
18
|
-
constructor(
|
|
21
|
+
constructor(
|
|
22
|
+
private readonly config: FileUploaderConfig,
|
|
23
|
+
private readonly deps: Dependencies,
|
|
24
|
+
) {}
|
|
19
25
|
|
|
20
26
|
async validate(context: HasRequestForm): Promise<FileValidationResult> {
|
|
21
27
|
const form = await context.request.form();
|
|
@@ -28,8 +34,9 @@ export class FileUploaderMiddleware {
|
|
|
28
34
|
|
|
29
35
|
if (size.isGreaterThan(this.config.maxSize)) return { valid: false, error: FileUploaderError.SizeLimit };
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
const mime = await this.deps.FileTypeDetector.detect(file);
|
|
38
|
+
|
|
39
|
+
if (!mime) return { valid: false, error: FileUploaderError.InvalidMime };
|
|
33
40
|
|
|
34
41
|
if (!this.config.MimeRegistry.hasMime(mime)) {
|
|
35
42
|
return { valid: false, error: FileUploaderError.InvalidMime };
|
package/src/hcaptcha.service.ts
CHANGED
|
@@ -4,14 +4,11 @@ export const HCaptchaServiceError = { Error: "hcaptcha.service.error" };
|
|
|
4
4
|
|
|
5
5
|
type HcaptchaTokenType = string;
|
|
6
6
|
|
|
7
|
-
export type HCaptchaVerificationResult = { success: boolean };
|
|
7
|
+
export type HCaptchaVerificationResult = { success: boolean; hostname?: string };
|
|
8
8
|
|
|
9
9
|
export class HCaptchaService {
|
|
10
|
-
async verify(
|
|
11
|
-
|
|
12
|
-
token: HcaptchaTokenType,
|
|
13
|
-
): Promise<HCaptchaVerificationResult> {
|
|
14
|
-
const body = new URLSearchParams({ secret: secretKey, response: token });
|
|
10
|
+
async verify(secret: HCaptchaSecretKeyType, token: HcaptchaTokenType): Promise<HCaptchaVerificationResult> {
|
|
11
|
+
const body = new URLSearchParams({ secret, response: token });
|
|
15
12
|
|
|
16
13
|
const response = await fetch("https://hcaptcha.com/siteverify", {
|
|
17
14
|
method: "POST",
|
|
@@ -37,7 +37,7 @@ export type HealthcheckDependencies = {
|
|
|
37
37
|
export type HealthcheckConfig = {
|
|
38
38
|
Env: NodeEnvironmentEnum;
|
|
39
39
|
prerequisites: ReadonlyArray<Prerequisite>;
|
|
40
|
-
redactor
|
|
40
|
+
redactor: RedactorStrategy;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
const self = new Prerequisite("self", new PrerequisiteVerifierSelfAdapter());
|
|
@@ -111,7 +111,7 @@ export class HealthcheckHandler {
|
|
|
111
111
|
|
|
112
112
|
return {
|
|
113
113
|
label: prerequisite.label,
|
|
114
|
-
outcome: this.config.redactor
|
|
114
|
+
outcome: this.config.redactor.redact(outcome),
|
|
115
115
|
ms: stopwatch.stop().ms,
|
|
116
116
|
};
|
|
117
117
|
}),
|
package/src/index.ts
CHANGED
|
@@ -180,6 +180,10 @@ export * from "./file-renamer.port";
|
|
|
180
180
|
export * from "./file-renamer-node.adapter";
|
|
181
181
|
export * from "./file-renamer-node-forgiving.adapter";
|
|
182
182
|
export * from "./file-renamer-noop.adapter";
|
|
183
|
+
export * from "./file-type-detector.strategy";
|
|
184
|
+
export * from "./file-type-detector-fixed.strategy";
|
|
185
|
+
export * from "./file-type-detector-magic-bytes.strategy";
|
|
186
|
+
export * from "./file-type-detector-text.strategy";
|
|
183
187
|
export * from "./file-uploader.middleware";
|
|
184
188
|
export * from "./file-uploader-hono.middleware";
|
|
185
189
|
export * from "./file-writer.adapter";
|
|
@@ -537,6 +541,7 @@ export * from "./subject-segment-method.strategy";
|
|
|
537
541
|
export * from "./subject-segment-param.strategy";
|
|
538
542
|
export * from "./subject-segment-path.strategy";
|
|
539
543
|
export * from "./subject-segment-query.strategy";
|
|
544
|
+
export * from "./subject-segment-remote-ip.strategy";
|
|
540
545
|
export * from "./subject-segment-request.strategy";
|
|
541
546
|
export * from "./subject-segment-user.strategy";
|
|
542
547
|
export * from "./temporary-file.port";
|
|
@@ -576,6 +581,7 @@ export * from "./weak-etag-extractor-header.strategy";
|
|
|
576
581
|
export * from "./weak-etag-extractor-hono.middleware";
|
|
577
582
|
export * from "./weak-etag-extractor-param.strategy";
|
|
578
583
|
export * from "./webhook-body-builder.strategy";
|
|
584
|
+
export * from "./webhook-body-builder-signed-headers.strategy";
|
|
579
585
|
export * from "./webhook-body-builder-text.strategy";
|
|
580
586
|
export * from "./webhook-id.vo";
|
|
581
587
|
export * from "./webhook-id-extractor.strategy";
|
|
@@ -23,7 +23,6 @@ export class LanguageDetectorHeaderStrategy<T extends tools.LanguageType>
|
|
|
23
23
|
quality: Number(quality.replace("q=", "")),
|
|
24
24
|
};
|
|
25
25
|
})
|
|
26
|
-
// Quality of 0 means the language is explicitly not acceptable
|
|
27
26
|
.filter((candidate) => candidate.quality > 0)
|
|
28
27
|
.sort((first, second) => second.quality - first.quality)
|
|
29
28
|
.map((candidate) => candidate.language);
|
package/src/readiness.handler.ts
CHANGED
|
@@ -3,8 +3,12 @@ import {
|
|
|
3
3
|
PrerequisiteVerificationOutcome,
|
|
4
4
|
type PrerequisiteVerificationResult,
|
|
5
5
|
} from "./prerequisite-verifier.port";
|
|
6
|
+
import type { RedactorStrategy } from "./redactor.strategy";
|
|
6
7
|
|
|
7
|
-
export type ReadinessConfig = {
|
|
8
|
+
export type ReadinessConfig = {
|
|
9
|
+
prerequisites: ReadonlyArray<Prerequisite>;
|
|
10
|
+
redactor: RedactorStrategy;
|
|
11
|
+
};
|
|
8
12
|
|
|
9
13
|
export enum ReadinessStatusCode {
|
|
10
14
|
Ready = 200,
|
|
@@ -28,7 +32,7 @@ export class ReadinessHandler {
|
|
|
28
32
|
const details = await Promise.all(
|
|
29
33
|
prerequisites.map(async (prerequisite) => ({
|
|
30
34
|
label: prerequisite.label,
|
|
31
|
-
outcome: await prerequisite.build().verify(),
|
|
35
|
+
outcome: this.config.redactor.redact(await prerequisite.build().verify()),
|
|
32
36
|
})),
|
|
33
37
|
);
|
|
34
38
|
|
|
@@ -37,7 +37,10 @@ export class RemoteFileStorageDiskAdapter implements RemoteFileStoragePort {
|
|
|
37
37
|
const parts = key.split("/");
|
|
38
38
|
const filename = tools.Filename.fromString(parts.pop() as string);
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
if (parts.length === 0) return tools.FilePathAbsolute.fromPartsSafe(this.config.root, filename);
|
|
41
|
+
|
|
42
|
+
const base = this.config.root === "/" ? "" : this.config.root;
|
|
43
|
+
const directory = v.parse(tools.DirectoryPathAbsoluteSchema, `${base}/${parts.join("/")}`);
|
|
41
44
|
|
|
42
45
|
return tools.FilePathAbsolute.fromPartsSafe(directory, filename);
|
|
43
46
|
}
|
|
@@ -34,9 +34,13 @@ export class SealerAesGcmAdapter implements SealerPort {
|
|
|
34
34
|
|
|
35
35
|
const key = await this.deps.CryptoKeyProvider.get();
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
try {
|
|
38
|
+
const encrypted = Uint8Array.fromBase64(value.slice(SealerAesGcmAdapter.PREFIX.length));
|
|
39
|
+
const plaintext = await CryptoAesGcm.decrypt(key, encrypted);
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
return JSON.parse(new TextDecoder().decode(plaintext));
|
|
42
|
+
} catch {
|
|
43
|
+
throw new Error(SealerAesGcmAdapterError.InvalidPayload);
|
|
44
|
+
}
|
|
41
45
|
}
|
|
42
46
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
2
|
import { ALL_BOTS } from "./bots.vo";
|
|
3
|
-
import { Client } from "./client.vo";
|
|
4
3
|
import type { RequestContext } from "./request-context.port";
|
|
5
4
|
import type { SecurityRuleStrategy } from "./security-rule.strategy";
|
|
6
5
|
import { SecurityRuleName, type SecurityRuleNameType } from "./security-rule-name.vo";
|
|
@@ -9,9 +8,11 @@ export class SecurityRuleUserAgentStrategy implements SecurityRuleStrategy {
|
|
|
9
8
|
constructor(private readonly blacklist: ReadonlyArray<string> = ALL_BOTS) {}
|
|
10
9
|
|
|
11
10
|
async isViolated(context: RequestContext): Promise<boolean> {
|
|
12
|
-
const
|
|
11
|
+
const ua = context.identity.ua()?.toLowerCase();
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
if (!ua) return false;
|
|
14
|
+
|
|
15
|
+
return this.blacklist.some((bot) => ua.includes(bot.toLowerCase()));
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
get name(): SecurityRuleNameType {
|
|
@@ -7,25 +7,31 @@ import type { SecurityRuleStrategy } from "./security-rule.strategy";
|
|
|
7
7
|
import { SecurityRuleName, type SecurityRuleNameType } from "./security-rule-name.vo";
|
|
8
8
|
import { SubjectRequestResolver } from "./subject-request-resolver.vo";
|
|
9
9
|
import { SubjectSegmentFixedStrategy } from "./subject-segment-fixed.strategy";
|
|
10
|
-
import {
|
|
10
|
+
import type { SubjectSegmentRequestStrategy } from "./subject-segment-request.strategy";
|
|
11
11
|
|
|
12
12
|
type Dependencies = { CacheRepository: CacheRepositoryPort; HashContent: HashContentStrategy };
|
|
13
|
-
type Config = {
|
|
13
|
+
type Config = {
|
|
14
|
+
threshold: tools.IntegerPositiveType;
|
|
15
|
+
segments: ReadonlyArray<SubjectSegmentRequestStrategy>;
|
|
16
|
+
};
|
|
14
17
|
|
|
15
18
|
export class SecurityRuleViolationThresholdStrategy implements SecurityRuleStrategy {
|
|
19
|
+
private readonly resolver: SubjectRequestResolver;
|
|
20
|
+
|
|
16
21
|
constructor(
|
|
17
22
|
private readonly rule: SecurityRuleStrategy,
|
|
18
23
|
private readonly config: Config,
|
|
19
24
|
private readonly deps: Dependencies,
|
|
20
|
-
) {
|
|
25
|
+
) {
|
|
26
|
+
this.resolver = new SubjectRequestResolver(
|
|
27
|
+
[new SubjectSegmentFixedStrategy(this.name), ...this.config.segments],
|
|
28
|
+
this.deps,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
21
31
|
|
|
22
32
|
// Best-effort increment, occasional lost increments are acceptable for concurrent requests.
|
|
23
33
|
async isViolated(context: RequestContext): Promise<boolean> {
|
|
24
|
-
const
|
|
25
|
-
[new SubjectSegmentFixedStrategy(this.name), new SubjectSegmentIpStrategy()],
|
|
26
|
-
this.deps,
|
|
27
|
-
);
|
|
28
|
-
const subject = await resolver.resolve(context);
|
|
34
|
+
const subject = await this.resolver.resolve(context);
|
|
29
35
|
|
|
30
36
|
const violated = await this.rule.isViolated(context);
|
|
31
37
|
|
|
@@ -12,9 +12,11 @@ export class ShieldBodyLimitStrategy {
|
|
|
12
12
|
evaluate(context: HasRequestHeader): boolean {
|
|
13
13
|
const header = context.request.header("content-length");
|
|
14
14
|
|
|
15
|
+
if (header === undefined) return true;
|
|
16
|
+
|
|
15
17
|
const contentLength = v.safeParse(tools.SizeBytes, Number(header));
|
|
16
18
|
|
|
17
|
-
if (!contentLength.success) return
|
|
19
|
+
if (!contentLength.success) return false;
|
|
18
20
|
|
|
19
21
|
const size = tools.Size.fromBytes(contentLength.output);
|
|
20
22
|
|
|
@@ -18,8 +18,13 @@ export class ShieldHcaptchaLocalHonoStrategy implements MiddlewareHonoPort {
|
|
|
18
18
|
|
|
19
19
|
private static readonly TOKEN_LOCAL = "10000000-aaaa-bbbb-cccc-000000000001";
|
|
20
20
|
|
|
21
|
+
private static readonly HOSTNAME_LOCAL = "local-pass";
|
|
22
|
+
|
|
21
23
|
constructor() {
|
|
22
|
-
this.strategy = new ShieldHcaptchaStrategy(
|
|
24
|
+
this.strategy = new ShieldHcaptchaStrategy({
|
|
25
|
+
secretKey: ShieldHcaptchaLocalHonoStrategy.SECRET_KEY_LOCAL,
|
|
26
|
+
hostname: ShieldHcaptchaLocalHonoStrategy.HOSTNAME_LOCAL,
|
|
27
|
+
});
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
handle(): MiddlewareHandler {
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type { MiddlewareHandler } from "hono";
|
|
2
2
|
import { HTTPException } from "hono/http-exception";
|
|
3
|
-
import type { HCaptchaSecretKeyType } from "./hcaptcha-secret-key.vo";
|
|
4
3
|
import type { MiddlewareHonoPort } from "./middleware-hono.port";
|
|
5
4
|
import { RequestContextHonoAdapter } from "./request-context-hono.adapter";
|
|
6
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type ShieldHcaptchaConfig,
|
|
7
|
+
ShieldHcaptchaStrategy,
|
|
8
|
+
ShieldHcaptchaStrategyError,
|
|
9
|
+
} from "./shield-hcaptcha.strategy";
|
|
7
10
|
|
|
8
11
|
export class ShieldHcaptchaHonoStrategy implements MiddlewareHonoPort {
|
|
9
12
|
private readonly strategy: ShieldHcaptchaStrategy;
|
|
10
13
|
|
|
11
|
-
constructor(
|
|
12
|
-
this.strategy = new ShieldHcaptchaStrategy(
|
|
14
|
+
constructor(config: ShieldHcaptchaConfig) {
|
|
15
|
+
this.strategy = new ShieldHcaptchaStrategy(config);
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
handle(): MiddlewareHandler {
|