diff --git a/charts/nostr/strfry/files/whitelist.js b/charts/nostr/strfry/files/whitelist.js new file mode 100644 index 000000000..b404f212c --- /dev/null +++ b/charts/nostr/strfry/files/whitelist.js @@ -0,0 +1,123 @@ +#!/usr/bin/env node + +const axios = require("axios"); +const nostrTools = require("nostr-tools"); + +const GRAPHQL_URL = "https://api.flashapp.me/graphql"; // Replace with your actual GraphQL endpoint + +const rl = require("readline").createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false, +}); + +const checkWhitelist = async (hexPubkey) => { + try { + let npub = nostrTools.nip19.npubEncode(hexPubkey); + const query = ` + query Query($input: IsFlashNpubInput!) { + isFlashNpub(input: $input) { + isFlashNpub + } + } + `; + + const variables = { + input: { npub: npub }, + }; + + console.error( + "Making API request with variables:", + JSON.stringify(variables) + ); // Log request to stderr + + try { + const response = await axios.post( + GRAPHQL_URL, + { + query, + variables, + }, + { + headers: { "Content-Type": "application/json" }, + } + ); + console.error("API response:", response.data); // Log response to stderr + return response.data.data.isFlashNpub.isFlashNpub; + } catch (error) { + console.error("Error fetching whitelist status:", error.message); + console.error("Request variables were:", JSON.stringify(variables)); + return false; + } + } catch (error) { + console.error("Error encoding pubkey:", error.message); + return false; + } +}; + +rl.on("line", async (line) => { + let req; + let res = {}; + + // Parse the input line + try { + req = JSON.parse(line); + } catch (error) { + console.error("Invalid JSON format:", error.message); + console.log( + JSON.stringify({ + action: "reject", + msg: "invalid JSON format", + }) + ); + return; + } + + // Check if the request has an event ID + if (!req.event || !req.event.id) { + console.error("Missing event ID"); + console.log( + JSON.stringify({ + action: "reject", + msg: "missing event ID", + }) + ); + return; + } + + // Set the event ID for the response + res.id = req.event.id; + + // Check request type + if (req.type !== "new") { + console.error("Unexpected request type:", req.type); + res.action = "reject"; + res.msg = "unexpected request type"; + console.log(JSON.stringify(res)); + return; + } + + // Check for p tag + const hexPubkey = req.event.tags.filter((t) => t[0] === "p")[0]?.[1]; + console.error("Hex pubkey is", hexPubkey, "Request event is", req.event); + + if (!hexPubkey) { + console.error("No referenced pubkey"); + res.action = "reject"; + res.msg = "no referenced pubkey (p tag)"; + console.log(JSON.stringify(res)); + return; + } + + // Check if the pubkey is on the whitelist via GraphQL query + const isWhitelisted = await checkWhitelist(hexPubkey); + + if (isWhitelisted) { + res.action = "accept"; + } else { + res.action = "reject"; + res.msg = "blocked: not on white-list"; + } + + console.log(JSON.stringify(res)); +}); diff --git a/charts/nostr/strfry/templates/deployment.yaml b/charts/nostr/strfry/templates/deployment.yaml index 259f8ccef..3e5bf2e78 100644 --- a/charts/nostr/strfry/templates/deployment.yaml +++ b/charts/nostr/strfry/templates/deployment.yaml @@ -12,6 +12,28 @@ spec: labels: app: strfry spec: + initContainers: + - name: npm-install + image: node:alpine + command: ["sh", "-c"] + args: + - | + cd /app + npm install + echo "Dependencies installed successfully" + volumeMounts: + - name: app-deps + mountPath: /app + - name: package-json + mountPath: /app/package.json + subPath: package.json + resources: + limits: + memory: 128Mi + cpu: 200m + requests: + memory: 64Mi + cpu: 50m containers: - name: strfry image: {{ .Values.image.repository }}:{{ .Values.image.tag }}@sha256:{{ .Values.image.digest }} @@ -25,6 +47,12 @@ spec: subPath: strfry.conf - name: strfry-logs mountPath: /app/logs + - name: strfry-plugin + mountPath: /app/whitelist.js + subPath: whitelist.js + - name: app-deps + mountPath: /app/node_modules + subPath: node_modules - name: vector image: timberio/vector:0.34.X-debian @@ -37,7 +65,7 @@ spec: cpu: 100m volumeMounts: - name: strfry-logs - mountPath: /app/logs # changed from /logs to /app/logs + mountPath: /app/logs - name: vector-config mountPath: /etc/vector readOnly: true @@ -49,8 +77,17 @@ spec: - name: strfry-conf configMap: name: {{ include "strfry.fullname" . }}-configmap + - name: strfry-plugin + configMap: + name: {{ include "strfry.fullname" . }}-plugin-configmap + defaultMode: 0755 + - name: package-json + configMap: + name: {{ include "strfry.fullname" . }}-package-json-configmap + - name: app-deps + emptyDir: {} - name: strfry-logs emptyDir: {} - name: vector-config configMap: - name: vector-config + name: vector-config \ No newline at end of file diff --git a/charts/nostr/strfry/templates/pacage-json-configmap.yaml b/charts/nostr/strfry/templates/pacage-json-configmap.yaml new file mode 100644 index 000000000..68a5d8fa2 --- /dev/null +++ b/charts/nostr/strfry/templates/pacage-json-configmap.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "strfry.fullname" . }}-package-json-configmap +data: + package.json: | + { + "name": "strfry-custom", + "version": "1.0.0", + "dependencies": { + "axios": "^1.7.7", + "nostr-tools": "^2.8.1" + } + } \ No newline at end of file diff --git a/charts/nostr/strfry/templates/plugin-configmap.yml b/charts/nostr/strfry/templates/plugin-configmap.yml new file mode 100644 index 000000000..54fa4c7bc --- /dev/null +++ b/charts/nostr/strfry/templates/plugin-configmap.yml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "strfry.fullname" . }}-plugin-configmap +data: + whitelist.js: | +{{ .Files.Get "files/whitelist.js" | indent 4 }} \ No newline at end of file diff --git a/charts/nostr/strfry/values.yaml b/charts/nostr/strfry/values.yaml index 0af43a98b..f0cd3836d 100644 --- a/charts/nostr/strfry/values.yaml +++ b/charts/nostr/strfry/values.yaml @@ -5,9 +5,9 @@ replicaCount: 1 image: - repository: lnflash/strfry-custom + repository: dockurr/strfry tag: latest - digest: e433d1ac4cc23a4e9a40ef97bcb2d5477b42bea99694d0ef5f08b2f6f4facfcd + digest: df140472554e5a0b5bbe08ec417805d283098621833e44827d8018c98b74243d pullPolicy: IfNotPresent persistence: