akkounts/extras/strfry/ldap-policy.ts
Râu Cao c1bac2625c
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Only log exception to stdout
2025-05-21 16:42:49 +04:00

84 lines
2.5 KiB
TypeScript

import { NostrEvent, NostrRelayInfo, NostrRelayOK, NPolicy } from 'jsr:@nostrify/types@^0.35.0';
import { nip57 } from 'jsr:@nostr/tools';
import { Client } from 'npm:ldapts';
export interface LdapConfig {
url: string;
bindDN: string;
password: string;
searchDN: string;
whitelistPubkeys?: IterablePubkeys;
}
export class LdapPolicy implements NPolicy {
constructor(private opts: LdapConfig) {}
// deno-lint-ignore require-await
async call(event: NostrEvent): Promise<NostrRelayOK> {
const client = new Client({ url: this.opts.url });
const { id, kind, tags } = event;
let { pubkey } = event;
if (this.opts.whitelistPubkeys.includes(pubkey)) {
return ['OK', id, true, ''];
}
// Zap receipt
if (kind === 9735) {
const descriptionTag = tags.find(([t, v]) => t === 'description' && v);
const invalidZapRequestMsg = 'Zap receipts must contain a valid zap request from a relay member';
if (typeof descriptionTag === 'undefined') {
return ['OK', id, false, invalidZapRequestMsg];
}
const zapRequestJSON = descriptionTag[1];
const validationResult = nip57.validateZapRequest(zapRequestJSON);
// TODO
// The zap receipt event's pubkey MUST be the same as the recipient's lnurl provider's nostrPubkey (retrieved in step 1 of the protocol flow).
// The invoiceAmount contained in the bolt11 tag of the zap receipt MUST equal the amount tag of the zap request (if present).
if (validationResult === null) {
pubkey = JSON.parse(zapRequestJSON).pubkey;
} else {
return ['OK', id, false, invalidZapRequestMsg];
}
}
const out = { accept: true, msg: ''};
try {
await client.bind(this.opts.bindDN, this.opts.password);
const { searchEntries } = await client.search(this.opts.searchDN, {
filter: `(nostrKey=${pubkey})`,
attributes: ['nostrKey']
});
const memberKey = searchEntries[0]?.nostrKey;
if (memberKey === pubkey) {
out['accept'] = true;
} else {
out['accept'] = false;
out['msg'] = 'Only members can publish notes on this relay';
}
} catch (e) {
out['accept'] = false;
out['msg'] = 'Auth service temporarily unavailable';
console.warn(`[ldap-policy] Auth service temporarily unavailable: ${e.message}`)
} finally {
await client.unbind();
return ['OK', id, out['accept'], out['msg']];
}
}
get info(): NostrRelayInfo {
return {
limitation: {
restricted_writes: true,
},
};
}
}