Create AdminStore to filter out banned users
This commit is contained in:
parent
a30cdec79b
commit
e5fadafc7a
|
@ -1,14 +1,11 @@
|
||||||
import { NKinds, NostrEvent, NSchema as n } from '@nostrify/nostrify';
|
import { NKinds, NostrEvent, NSchema as n } from '@nostrify/nostrify';
|
||||||
import { PipePolicy } from '@nostrify/nostrify/policies';
|
|
||||||
import Debug from '@soapbox/stickynotes/debug';
|
import Debug from '@soapbox/stickynotes/debug';
|
||||||
import { sql } from 'kysely';
|
import { sql } from 'kysely';
|
||||||
import { LRUCache } from 'lru-cache';
|
import { LRUCache } from 'lru-cache';
|
||||||
|
|
||||||
import { Conf } from '@/config.ts';
|
|
||||||
import { DittoDB } from '@/db/DittoDB.ts';
|
import { DittoDB } from '@/db/DittoDB.ts';
|
||||||
import { deleteAttachedMedia } from '@/db/unattached-media.ts';
|
import { deleteAttachedMedia } from '@/db/unattached-media.ts';
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { MuteListPolicy } from '@/policies/MuteListPolicy.ts';
|
|
||||||
import { RelayError } from '@/RelayError.ts';
|
import { RelayError } from '@/RelayError.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
import { Storages } from '@/storages.ts';
|
||||||
|
@ -44,6 +41,15 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise<void
|
||||||
|
|
||||||
await hydrateEvent(event, signal);
|
await hydrateEvent(event, signal);
|
||||||
|
|
||||||
|
const n = getTagSet(event.user?.tags ?? [], 'n');
|
||||||
|
|
||||||
|
if (n.has('disable')) {
|
||||||
|
throw new RelayError('blocked', 'user is disabled');
|
||||||
|
}
|
||||||
|
if (n.has('suspend')) {
|
||||||
|
throw new RelayError('blocked', 'user is suspended');
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
storeEvent(event, signal),
|
storeEvent(event, signal),
|
||||||
parseMetadata(event, signal),
|
parseMetadata(event, signal),
|
||||||
|
@ -55,13 +61,8 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise<void
|
||||||
async function policyFilter(event: NostrEvent): Promise<void> {
|
async function policyFilter(event: NostrEvent): Promise<void> {
|
||||||
const debug = Debug('ditto:policy');
|
const debug = Debug('ditto:policy');
|
||||||
|
|
||||||
const policy = new PipePolicy([
|
|
||||||
new MuteListPolicy(Conf.pubkey, await Storages.admin()),
|
|
||||||
policyWorker,
|
|
||||||
]);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await policy.call(event);
|
const result = await policyWorker.call(event);
|
||||||
debug(JSON.stringify(result));
|
debug(JSON.stringify(result));
|
||||||
RelayError.assert(result);
|
RelayError.assert(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -3,15 +3,15 @@ import { RelayPoolWorker } from 'nostr-relaypool';
|
||||||
|
|
||||||
import { Conf } from '@/config.ts';
|
import { Conf } from '@/config.ts';
|
||||||
import { DittoDB } from '@/db/DittoDB.ts';
|
import { DittoDB } from '@/db/DittoDB.ts';
|
||||||
|
import { AdminStore } from '@/storages/AdminStore.ts';
|
||||||
import { EventsDB } from '@/storages/EventsDB.ts';
|
import { EventsDB } from '@/storages/EventsDB.ts';
|
||||||
import { PoolStore } from '@/storages/pool-store.ts';
|
import { PoolStore } from '@/storages/pool-store.ts';
|
||||||
import { SearchStore } from '@/storages/search-store.ts';
|
import { SearchStore } from '@/storages/search-store.ts';
|
||||||
import { InternalRelay } from '@/storages/InternalRelay.ts';
|
import { InternalRelay } from '@/storages/InternalRelay.ts';
|
||||||
import { UserStore } from '@/storages/UserStore.ts';
|
|
||||||
|
|
||||||
export class Storages {
|
export class Storages {
|
||||||
private static _db: Promise<EventsDB> | undefined;
|
private static _db: Promise<EventsDB> | undefined;
|
||||||
private static _admin: Promise<UserStore> | undefined;
|
private static _admin: Promise<AdminStore> | undefined;
|
||||||
private static _client: Promise<PoolStore> | undefined;
|
private static _client: Promise<PoolStore> | undefined;
|
||||||
private static _pubsub: Promise<InternalRelay> | undefined;
|
private static _pubsub: Promise<InternalRelay> | undefined;
|
||||||
private static _search: Promise<SearchStore> | undefined;
|
private static _search: Promise<SearchStore> | undefined;
|
||||||
|
@ -28,9 +28,9 @@ export class Storages {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Admin user storage. */
|
/** Admin user storage. */
|
||||||
public static async admin(): Promise<UserStore> {
|
public static async admin(): Promise<AdminStore> {
|
||||||
if (!this._admin) {
|
if (!this._admin) {
|
||||||
this._admin = Promise.resolve(new UserStore(Conf.pubkey, await this.db()));
|
this._admin = Promise.resolve(new AdminStore(await this.db()));
|
||||||
}
|
}
|
||||||
return this._admin;
|
return this._admin;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { NostrEvent, NostrFilter, NStore } from '@nostrify/nostrify';
|
||||||
|
|
||||||
|
import { Conf } from '@/config.ts';
|
||||||
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
|
import { getTagSet } from '@/utils/tags.ts';
|
||||||
|
|
||||||
|
/** A store that prevents banned users from being displayed. */
|
||||||
|
export class AdminStore implements NStore {
|
||||||
|
constructor(private store: NStore) {}
|
||||||
|
|
||||||
|
async event(event: NostrEvent, opts?: { signal?: AbortSignal }): Promise<void> {
|
||||||
|
return await this.store.event(event, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
async query(filters: NostrFilter[], opts: { signal?: AbortSignal; limit?: number } = {}): Promise<DittoEvent[]> {
|
||||||
|
const events = await this.store.query(filters, opts);
|
||||||
|
|
||||||
|
const users = await this.store.query([{
|
||||||
|
kinds: [30382],
|
||||||
|
authors: [Conf.pubkey],
|
||||||
|
'#d': events.map((event) => event.pubkey),
|
||||||
|
limit: 1,
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return events.filter((event) => {
|
||||||
|
const user = users.find(
|
||||||
|
({ kind, pubkey, tags }) =>
|
||||||
|
kind === 30382 && pubkey === Conf.pubkey && tags.find(([name]) => name === 'd')?.[1] === event.pubkey,
|
||||||
|
);
|
||||||
|
|
||||||
|
const n = getTagSet(user?.tags ?? [], 'n');
|
||||||
|
|
||||||
|
if (n.has('disable') || n.has('suspend')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue