diff --git a/Dockerfile b/Dockerfile index f8df8159..a0e21946 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM denoland/deno:1.43.3 EXPOSE 4036 WORKDIR /app -RUN mkdir -p data && chown -R deno data +RUN mkdir -p data/policy && chown -R deno data USER deno COPY . . RUN deno cache src/server.ts diff --git a/data/.gitignore b/data/.gitignore index c96a04f0..3c46d845 100644 --- a/data/.gitignore +++ b/data/.gitignore @@ -1,2 +1,3 @@ * -!.gitignore \ No newline at end of file +!.gitignore +!/policy \ No newline at end of file diff --git a/data/policy/.gitignore b/data/policy/.gitignore new file mode 100644 index 00000000..c96a04f0 --- /dev/null +++ b/data/policy/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/deno.json b/deno.json index 1ead2b92..399f4743 100644 --- a/deno.json +++ b/deno.json @@ -13,7 +13,7 @@ "admin:role": "deno run -A scripts/admin-role.ts", "stats:recompute": "deno run -A scripts/stats-recompute.ts" }, - "unstable": ["ffi", "kv"], + "unstable": ["ffi", "kv", "worker-options"], "exclude": ["./public"], "imports": { "@/": "./src/", diff --git a/src/config.ts b/src/config.ts index 589386f2..5a30c0e6 100644 --- a/src/config.ts +++ b/src/config.ts @@ -221,7 +221,7 @@ class Conf { } /** Path to the custom policy module. Must be an absolute path, https:, npm:, or jsr: URI. */ static get policy(): string { - return Deno.env.get('DITTO_POLICY') || new URL('../data/policy.ts', import.meta.url).toString(); + return Deno.env.get('DITTO_POLICY') || new URL('../data/policy.ts', import.meta.url).pathname; } } diff --git a/src/pipeline.ts b/src/pipeline.ts index 52cb5632..6f487ed4 100644 --- a/src/pipeline.ts +++ b/src/pipeline.ts @@ -16,6 +16,7 @@ import { Storages } from '@/storages.ts'; import { getTagSet } from '@/tags.ts'; import { eventAge, nostrDate, nostrNow, parseNip05, Time } from '@/utils.ts'; import { fetchWorker } from '@/workers/fetch.ts'; +import { policyWorker } from '@/workers/policy.ts'; import { TrendsWorker } from '@/workers/trends.ts'; import { verifyEventWorker } from '@/workers/verify.ts'; import { AdminSigner } from '@/signers/AdminSigner.ts'; @@ -62,11 +63,11 @@ async function policyFilter(event: NostrEvent): Promise { ]; try { - const CustomPolicy = (await import(Conf.policy)).default; - policies.push(new CustomPolicy()); + await policyWorker.import(Conf.policy); + policies.push(policyWorker); debug(`Using custom policy: ${Conf.policy}`); } catch (e) { - if (e.code === 'ERR_MODULE_NOT_FOUND') { + if (e.message.includes('Module not found')) { debug('Custom policy not found '); } else { console.error(`DITTO_POLICY (error importing policy): ${Conf.policy}`, e); diff --git a/src/workers/policy.ts b/src/workers/policy.ts new file mode 100644 index 00000000..3cc03c9c --- /dev/null +++ b/src/workers/policy.ts @@ -0,0 +1,23 @@ +import * as Comlink from 'comlink'; + +import { Conf } from '@/config.ts'; +import type { CustomPolicy } from '@/workers/policy.worker.ts'; + +const policyDir = new URL('../../data/policy', import.meta.url).pathname; + +export const policyWorker = Comlink.wrap( + new Worker( + new URL('./policy.worker.ts', import.meta.url), + { + type: 'module', + deno: { + permissions: { + read: [Conf.policy, policyDir], + write: [policyDir], + net: 'inherit', + env: false, + }, + }, + }, + ), +); diff --git a/src/workers/policy.worker.ts b/src/workers/policy.worker.ts new file mode 100644 index 00000000..146a116c --- /dev/null +++ b/src/workers/policy.worker.ts @@ -0,0 +1,19 @@ +import { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/nostrify'; +import { ReadOnlyPolicy } from '@nostrify/nostrify/policies'; +import * as Comlink from 'comlink'; + +export class CustomPolicy implements NPolicy { + private policy: NPolicy = new ReadOnlyPolicy(); + + // deno-lint-ignore require-await + async call(event: NostrEvent): Promise { + return this.policy.call(event); + } + + async import(path: string): Promise { + const Policy = (await import(path)).default; + this.policy = new Policy(); + } +} + +Comlink.expose(new CustomPolicy());