always run custom policy

This commit is contained in:
Siddharth Singh 2025-04-12 03:04:20 +05:30
parent 3d1ece7ec8
commit aede53e9a9
No known key found for this signature in database
7 changed files with 49 additions and 71 deletions

8
deno.lock generated
View file

@ -7,6 +7,7 @@
"jsr:@denosaurs/plug@1.0.3": "1.0.3",
"jsr:@esroyo/scoped-performance@^3.1.0": "3.1.0",
"jsr:@gfx/canvas-wasm@~0.4.2": "0.4.2",
"jsr:@gleasonator/policy@*": "0.9.0",
"jsr:@hono/hono@^4.4.6": "4.7.5",
"jsr:@negrel/http-ece@0.6.0": "0.6.0",
"jsr:@negrel/webpush@0.3": "0.3.0",
@ -133,6 +134,13 @@
"jsr:@std/encoding@1.0.5"
]
},
"@gleasonator/policy@0.9.0": {
"integrity": "483f87c3a18fb39f795495d3388453193f1115ab7e130981121f7828ce6b51bb",
"dependencies": [
"jsr:@nostrify/nostrify@0.36",
"jsr:@nostrify/policies"
]
},
"@hono/hono@4.7.5": {
"integrity": "36a7e1b3db8a58e5dc2bd36a76be53346f0966e04c24c635c4d6f58875575b0a"
},

View file

@ -3,7 +3,7 @@ import { HashtagPolicy } from '@nostrify/policies';
export default class TestPolicy implements NPolicy {
call(event: NostrEvent): Promise<NostrRelayOK> {
return new HashtagPolicy(['porn']).call(event);
return new HashtagPolicy(['other-blocked-tag']).call(event);
}
info?: NostrRelayInfo | undefined;
}

View file

@ -368,10 +368,6 @@ export class DittoConf {
return this.env.get('DITTO_POLICY') || path.join(this.dataDir, 'policy.ts');
}
get policyMode(): 'script' | 'event' {
return this.env.get('DITTO_CUSTOM_POLICY') ? 'script' : 'event';
}
/** Absolute path to the data directory used by Ditto. */
get dataDir(): string {
return this.env.get('DITTO_DATA_DIR') || path.join(Deno.cwd(), 'data');

View file

@ -26,10 +26,10 @@ export const adminCurrentPolicyController: AppController = async (c) => {
kinds: [11984],
}]).then((events) => events[0]);
if (current) return c.json({ mode: conf.policyMode, spec: JSON.parse(current.content) });
if (current) return c.json({ spec: JSON.parse(current.content) });
await relay.event(await createPolicyEvent(conf, DEFAULT_POLICY_SPEC));
return c.json({ mode: conf.policyMode, spec: DEFAULT_POLICY_SPEC });
return c.json({ spec: DEFAULT_POLICY_SPEC });
};
const PolicySpecSchema = z.object({
@ -41,13 +41,6 @@ const PolicySpecSchema = z.object({
export const adminUpdatePolicyController: AppController = async (c) => {
const { relay, conf } = c.var;
if (conf.policyMode === 'script') {
return c.json({
error:
"The Ditto policy mode is set to 'script'. You will not be able to use the Policy UI until you change it to 'event'.",
});
}
try {
const req = await c.req.json();
const parsed = PolicySpecSchema.parse(req);

View file

@ -9,8 +9,8 @@ const blocked = {
id: '19afd70437944671e7f5a02b29221ad444ef7cf60113a5731667e272e59a3979',
pubkey: '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
kind: 1,
tags: [['t', 'porn']],
content: 'this is a test of the policy system #porn',
tags: [['t', 'porn'], ['t', 'other-blocked-tag']],
content: 'this is a test of the policy system',
sig:
'1d73a7480cfd737b89dc1e0e7175dff67119915f31d24a279a45d56622f4b991b01e431d07b693ee6cd652f3f27274d9e203ee43ae44af7e70ce8647e5326196',
created_at: 1743685015,
@ -20,7 +20,6 @@ Deno.test('PolicyWorker with script policy', async () => {
const conf = new DittoConf(
new Map([
['DITTO_NSEC', nip19.nsecEncode(generateSecretKey())],
['DITTO_CUSTOM_POLICY', '1'],
['DATABASE_URL', Deno.env.get('DATABASE_URL')],
['DITTO_POLICY', join(Deno.cwd(), 'fixtures', 'policy.ts')],
]),

View file

@ -53,28 +53,15 @@ export class PolicyWorker implements NPolicy {
path: conf.policy,
databaseUrl: conf.databaseUrl,
pubkey: await conf.signer.getPublicKey(),
mode: conf.policyMode,
});
logi({
level: 'info',
ns: 'ditto.system.policy',
msg: `Using ${conf.policyMode === 'script' ? 'custom' : 'event'} policy`,
path: conf.policyMode === 'script' ? conf.policy : undefined,
msg: `Initialising custom policy`,
path: conf.policy,
enabled: true,
});
} catch (e) {
if (e instanceof Error && e.message.includes('Module not found')) {
logi({
level: 'info',
ns: 'ditto.system.policy',
msg: 'Custom policy not found <https://docs.soapbox.pub/ditto/policies/>',
path: null,
enabled: false,
});
this.enabled = false;
return;
}
if (e instanceof Error && e.message.includes('PGlite is not supported in worker threads')) {
logi({
level: 'warn',

View file

@ -13,26 +13,14 @@ import { logi } from '@soapbox/logi';
// @ts-ignore Don't try to access the env from this worker.
Deno.env = new Map<string, string>();
interface PolicyInitCommon {
interface PolicyInit {
/** Database URL to connect to. */
databaseUrl: string;
/** Admin pubkey to use for DittoPgStore checks. */
pubkey: string;
mode: 'script' | 'event';
}
interface ScriptPolicyInit {
/** Path to the policy module (https, jsr, file, etc) */
path: string;
mode: 'script';
}
interface EventPolicyInit {
mode: 'event';
}
type PolicyInit = PolicyInitCommon & (ScriptPolicyInit | EventPolicyInit);
export class CustomPolicy implements NPolicy {
private policy: NPolicy = new ReadOnlyPolicy();
@ -55,18 +43,26 @@ export class CustomPolicy implements NPolicy {
},
});
const policies: NPolicy[] = [];
const store = new DittoPgStore({
db,
conf,
timeout: 5_000,
});
if (opts.mode === 'script') {
try {
const Policy = (await import(opts.path)).default;
this.policy = new Policy({ db, store, pubkey });
} else {
policies.push(new Policy({ db, store, pubkey }));
} catch (e) {
if (e instanceof Error && e.message.includes('Module not found')) {
logi({
level: 'info',
ns: 'ditto.system.policy',
msg: 'Custom policy not found <https://docs.soapbox.pub/ditto/policies/>',
path: null,
});
}
}
const registry = new PolicyRegistry({ store, antiDuplicationPolicyStore: await Deno.openKv() });
const policies: NPolicy[] = [];
const event = await store
.query([{ kinds: [11984], authors: [await conf.signer.getPublicKey()] }])
.then((results) => results[0]);
@ -90,6 +86,5 @@ export class CustomPolicy implements NPolicy {
this.policy = new PipePolicy(policies);
}
}
}
Comlink.expose(new CustomPolicy());