Merge branch 'feature/strfry_zap_receipts' into live
This commit is contained in:
commit
8aabbad5bb
@ -101,7 +101,7 @@ class LdapService < ApplicationService
|
|||||||
dn = "ou=#{ou},cn=users,#{ldap_suffix}"
|
dn = "ou=#{ou},cn=users,#{ldap_suffix}"
|
||||||
|
|
||||||
aci = <<-EOS
|
aci = <<-EOS
|
||||||
(target="ldap:///cn=*,ou=#{ou},cn=users,#{ldap_suffix}")(targetattr="cn || sn || uid || mail || userPassword || nsRole || objectClass") (version 3.0; acl "service-#{ou.gsub(".", "-")}-read-search"; allow (read,search) userdn="ldap:///uid=service,ou=#{ou},cn=applications,#{ldap_suffix}";)
|
(target="ldap:///cn=*,ou=#{ou},cn=users,#{ldap_suffix}")(targetattr="cn || sn || uid || userPassword || mail || mailRoutingAddress || serviceEnabled || nostrKey || nsRole || objectClass") (version 3.0; acl "service-#{ou.gsub(".", "-")}-read-search"; allow (read,search) userdn="ldap:///uid=service,ou=#{ou},cn=applications,#{ldap_suffix}";)
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
attrs = {
|
attrs = {
|
||||||
|
@ -107,16 +107,22 @@ services:
|
|||||||
- minio
|
- minio
|
||||||
- redis
|
- redis
|
||||||
|
|
||||||
nostr-relay:
|
strfry:
|
||||||
image: pluja/strfry:latest
|
image: gitea.kosmos.org/kosmos/strfry-deno:1.1.1
|
||||||
volumes:
|
volumes:
|
||||||
- ./docker/strfry/strfry.conf:/etc/strfry.conf
|
- ./docker/strfry/strfry.conf:/etc/strfry.conf
|
||||||
- strfry-data:/app/strfry-db
|
- ./extras/strfry:/opt/strfry
|
||||||
|
- strfry-data:/var/lib/strfry
|
||||||
networks:
|
networks:
|
||||||
- external_network
|
- external_network
|
||||||
- internal_network
|
- internal_network
|
||||||
ports:
|
ports:
|
||||||
- "4777:7777"
|
- "4777:7777"
|
||||||
|
environment:
|
||||||
|
LDAP_URL: 'ldap://ldap:3389'
|
||||||
|
LDAP_BIND_DN: 'cn=Directory Manager'
|
||||||
|
LDAP_PASSWORD: passthebutter
|
||||||
|
LDAP_SEARCH_DN: 'ou=kosmos.org,cn=users,dc=kosmos,dc=org'
|
||||||
|
|
||||||
# phpldapadmin:
|
# phpldapadmin:
|
||||||
# image: osixia/phpldapadmin:0.9.0
|
# image: osixia/phpldapadmin:0.9.0
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
##
|
##
|
||||||
|
|
||||||
# Directory that contains the strfry LMDB database (restart required)
|
# Directory that contains the strfry LMDB database (restart required)
|
||||||
db = "./strfry-db/"
|
db = "/var/lib/strfry/"
|
||||||
|
|
||||||
dbParams {
|
dbParams {
|
||||||
# Maximum number of threads/processes that can simultaneously have LMDB transactions open (restart required)
|
# Maximum number of threads/processes that can simultaneously have LMDB transactions open (restart required)
|
||||||
@ -54,7 +54,7 @@ relay {
|
|||||||
|
|
||||||
info {
|
info {
|
||||||
# NIP-11: Name of this server. Short/descriptive (< 30 characters)
|
# NIP-11: Name of this server. Short/descriptive (< 30 characters)
|
||||||
name = "akkounts-nostr-relay"
|
name = "Akkounts Nostr Relay"
|
||||||
|
|
||||||
# NIP-11: Detailed information about relay, free-form
|
# NIP-11: Detailed information about relay, free-form
|
||||||
description = "Local strfry instance for akkounts development"
|
description = "Local strfry instance for akkounts development"
|
||||||
@ -86,7 +86,7 @@ relay {
|
|||||||
|
|
||||||
writePolicy {
|
writePolicy {
|
||||||
# If non-empty, path to an executable script that implements the writePolicy plugin logic
|
# If non-empty, path to an executable script that implements the writePolicy plugin logic
|
||||||
plugin = ""
|
plugin = "/opt/strfry/strfry-policy.ts"
|
||||||
}
|
}
|
||||||
|
|
||||||
compression {
|
compression {
|
||||||
|
5
extras/strfry/deno.json
Normal file
5
extras/strfry/deno.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"@nostr/tools": "jsr:@nostr/tools@^2.3.1"
|
||||||
|
}
|
||||||
|
}
|
66
extras/strfry/ldap-policy.ts
Normal file
66
extras/strfry/ldap-policy.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import type { Policy } from 'https://gitlab.com/soapbox-pub/strfry-policies/-/raw/develop/mod.ts';
|
||||||
|
import { Client } from 'npm:ldapts';
|
||||||
|
import { nip57 } from '@nostr/tools';
|
||||||
|
|
||||||
|
interface LdapConfig {
|
||||||
|
url: string;
|
||||||
|
bindDN: string;
|
||||||
|
password: string;
|
||||||
|
searchDN: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ldapPolicy: Policy<LdapConfig> = async (msg, opts) => {
|
||||||
|
const client = new Client({ url: opts.url });
|
||||||
|
const { kind, tags } = msg.event;
|
||||||
|
let { pubkey } = msg.event;
|
||||||
|
let out = { id: msg.event.id }
|
||||||
|
|
||||||
|
// 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') {
|
||||||
|
out['action'] = 'reject';
|
||||||
|
out['msg'] = invalidZapRequestMsg;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const zapRequestJSON = descriptionTag[1];
|
||||||
|
const validationResult = nip57.validateZapRequest(zapRequestJSON);
|
||||||
|
|
||||||
|
if (validationResult === null) {
|
||||||
|
pubkey = JSON.parse(zapRequestJSON).pubkey;
|
||||||
|
} else {
|
||||||
|
out['action'] = 'reject';
|
||||||
|
out['msg'] = invalidZapRequestMsg;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.bind(opts.bindDN, opts.password);
|
||||||
|
|
||||||
|
const { searchEntries } = await client.search(opts.searchDN, {
|
||||||
|
filter: `(nostrKey=${pubkey})`,
|
||||||
|
attributes: ['nostrKey']
|
||||||
|
});
|
||||||
|
const memberKey = searchEntries[0]?.nostrKey;
|
||||||
|
|
||||||
|
if (memberKey === pubkey) {
|
||||||
|
out['action'] = 'accept';
|
||||||
|
out['msg'] = '';
|
||||||
|
} else {
|
||||||
|
out['action'] = 'reject';
|
||||||
|
out['msg'] = 'Only members can publish notes on this relay';
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
out['action'] = 'reject';
|
||||||
|
out['msg'] = 'Auth service temporarily unavailable';
|
||||||
|
} finally {
|
||||||
|
await client.unbind();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ldapPolicy;
|
33
extras/strfry/strfry-policy.ts
Executable file
33
extras/strfry/strfry-policy.ts
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
//bin/true; exec deno run -A "$0" "$@"
|
||||||
|
import {
|
||||||
|
antiDuplicationPolicy,
|
||||||
|
hellthreadPolicy,
|
||||||
|
pipeline,
|
||||||
|
rateLimitPolicy,
|
||||||
|
readStdin,
|
||||||
|
writeStdout,
|
||||||
|
} from 'https://gitlab.com/soapbox-pub/strfry-policies/-/raw/develop/mod.ts';
|
||||||
|
import ldapPolicy from './ldap-policy.ts';
|
||||||
|
import { load } from "https://deno.land/std@0.224.0/dotenv/mod.ts";
|
||||||
|
|
||||||
|
const dirname = new URL('.', import.meta.url).pathname;
|
||||||
|
await load({ envPath: `${dirname}/.env`, export: true });
|
||||||
|
|
||||||
|
const ldapConfig = {
|
||||||
|
url: Deno.env.get("LDAP_URL"),
|
||||||
|
bindDN: Deno.env.get("LDAP_BIND_DN"),
|
||||||
|
password: Deno.env.get("LDAP_PASSWORD"),
|
||||||
|
searchDN: Deno.env.get("LDAP_SEARCH_DN"),
|
||||||
|
}
|
||||||
|
|
||||||
|
for await (const msg of readStdin()) {
|
||||||
|
const result = await pipeline(msg, [
|
||||||
|
[hellthreadPolicy, { limit: 10 }],
|
||||||
|
[antiDuplicationPolicy, { ttl: 60000, minLength: 50 }],
|
||||||
|
[rateLimitPolicy, { whitelist: ['127.0.0.1'] }],
|
||||||
|
[ldapPolicy, ldapConfig],
|
||||||
|
]);
|
||||||
|
|
||||||
|
writeStdout(result);
|
||||||
|
}
|
39
extras/strfry/strfry-sync.ts
Normal file
39
extras/strfry/strfry-sync.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { load } from "https://deno.land/std@0.224.0/dotenv/mod.ts";
|
||||||
|
import { Client } from 'npm:ldapts';
|
||||||
|
|
||||||
|
const dirname = new URL('.', import.meta.url).pathname;
|
||||||
|
await load({ envPath: `${dirname}/.env`, export: true });
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
url: Deno.env.get("LDAP_URL"),
|
||||||
|
bindDN: Deno.env.get("LDAP_BIND_DN"),
|
||||||
|
password: Deno.env.get("LDAP_PASSWORD"),
|
||||||
|
searchDN: Deno.env.get("LDAP_SEARCH_DN"),
|
||||||
|
relayUrl: Deno.args[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new Client({ url: opts.url });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.bind(opts.bindDN, opts.password);
|
||||||
|
|
||||||
|
const { searchEntries } = await client.search(opts.searchDN, {
|
||||||
|
filter: `(nostrKey=*)`,
|
||||||
|
attributes: ['nostrKey']
|
||||||
|
});
|
||||||
|
|
||||||
|
const pubkeys = searchEntries.map(e => e.nostrKey);
|
||||||
|
const filter = JSON.stringify({ authors: pubkeys });
|
||||||
|
|
||||||
|
const p = Deno.run({ cmd: [
|
||||||
|
"strfry", "sync", opts.relayUrl,
|
||||||
|
"--dir", "down", "--filter", filter
|
||||||
|
]});
|
||||||
|
|
||||||
|
const result = await p.status();
|
||||||
|
|
||||||
|
Deno.exit(result.code);
|
||||||
|
} catch (ex) {
|
||||||
|
console.error(ex);
|
||||||
|
Deno.exit(1);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user