Merge branch 'policy-env' into 'main'
Remote Policies See merge request soapbox-pub/ditto!264
This commit is contained in:
commit
4fafce27eb
|
@ -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/",
|
||||
|
@ -34,6 +34,7 @@
|
|||
"@std/media-types": "jsr:@std/media-types@^0.224.0",
|
||||
"@std/streams": "jsr:@std/streams@^0.223.0",
|
||||
"comlink": "npm:comlink@^4.4.1",
|
||||
"deno-safe-fetch": "https://gitlab.com/soapbox-pub/deno-safe-fetch/-/raw/v1.0.0/load.ts",
|
||||
"fast-stable-stringify": "npm:fast-stable-stringify@^1.0.0",
|
||||
"formdata-helper": "npm:formdata-helper@^0.3.0",
|
||||
"hono": "https://deno.land/x/hono@v3.10.1/mod.ts",
|
||||
|
|
|
@ -219,6 +219,10 @@ class Conf {
|
|||
static get firehoseEnabled(): boolean {
|
||||
return optionalBooleanSchema.parse(Deno.env.get('FIREHOSE_ENABLED')) ?? true;
|
||||
}
|
||||
/** 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).pathname;
|
||||
}
|
||||
}
|
||||
|
||||
const optionalBooleanSchema = z
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import 'https://gitlab.com/soapbox-pub/deno-safe-fetch/-/raw/v1.0.0/load.ts';
|
||||
import 'deno-safe-fetch';
|
||||
// @deno-types="npm:@types/lodash@4.14.194"
|
||||
export { default as lodash } from 'https://esm.sh/lodash@4.17.21';
|
||||
// @deno-types="npm:@types/mime@3.0.0"
|
||||
|
|
|
@ -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';
|
||||
|
@ -55,22 +56,39 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise<void
|
|||
}
|
||||
|
||||
async function policyFilter(event: NostrEvent): Promise<void> {
|
||||
const debug = Debug('ditto:policy');
|
||||
|
||||
const policies: NPolicy[] = [
|
||||
new MuteListPolicy(Conf.pubkey, await Storages.admin()),
|
||||
];
|
||||
|
||||
try {
|
||||
const CustomPolicy = (await import('../data/policy.ts')).default;
|
||||
policies.push(new CustomPolicy());
|
||||
} catch (_e) {
|
||||
debug('policy not found - https://docs.soapbox.pub/ditto/policies/');
|
||||
await policyWorker.import(Conf.policy);
|
||||
policies.push(policyWorker);
|
||||
debug(`Using custom policy: ${Conf.policy}`);
|
||||
} catch (e) {
|
||||
if (e.message.includes('Module not found')) {
|
||||
debug('Custom policy not found <https://docs.soapbox.pub/ditto/policies/>');
|
||||
} else {
|
||||
console.error(`DITTO_POLICY (error importing policy): ${Conf.policy}`, e);
|
||||
throw new RelayError('blocked', 'policy could not be loaded');
|
||||
}
|
||||
}
|
||||
|
||||
const policy = new PipePolicy(policies.reverse());
|
||||
|
||||
const result = await policy.call(event);
|
||||
debug(JSON.stringify(result));
|
||||
RelayError.assert(result);
|
||||
try {
|
||||
const result = await policy.call(event);
|
||||
debug(JSON.stringify(result));
|
||||
RelayError.assert(result);
|
||||
} catch (e) {
|
||||
if (e instanceof RelayError) {
|
||||
throw e;
|
||||
} else {
|
||||
console.error('POLICY ERROR:', e);
|
||||
throw new RelayError('blocked', 'policy error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Encounter the event, and return whether it has already been encountered. */
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import * as Comlink from 'comlink';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
import type { CustomPolicy } from '@/workers/policy.worker.ts';
|
||||
|
||||
export const policyWorker = Comlink.wrap<CustomPolicy>(
|
||||
new Worker(
|
||||
new URL('./policy.worker.ts', import.meta.url),
|
||||
{
|
||||
type: 'module',
|
||||
deno: {
|
||||
permissions: {
|
||||
read: [Conf.policy],
|
||||
write: false,
|
||||
net: 'inherit',
|
||||
env: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
|
@ -0,0 +1,20 @@
|
|||
import 'deno-safe-fetch';
|
||||
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<NostrRelayOK> {
|
||||
return this.policy.call(event);
|
||||
}
|
||||
|
||||
async import(path: string): Promise<void> {
|
||||
const Policy = (await import(path)).default;
|
||||
this.policy = new Policy();
|
||||
}
|
||||
}
|
||||
|
||||
Comlink.expose(new CustomPolicy());
|
Loading…
Reference in New Issue