diff --git a/.env b/.env index 252a1f1..5bdf067 100644 --- a/.env +++ b/.env @@ -5,4 +5,4 @@ RELAY_PUBKEY="" RELAY_CONTACT="" # Custom invite-relay settings -INVITE_MASTER="" # Master of the relay +INVITE_RELAY_MASTER="" # Master of the relay (pubkey hex) diff --git a/.gitignore b/.gitignore index 78f0117..fb60724 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ whitelist.json -khatru-invite \ No newline at end of file +khatru-invite +.env +khatru-badgern-db \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..337bfcd --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# Khatru Invite + +A relay based on [Khatru](https://github.com/fiatjaf/khatru) with a invite hierarchy feature. + +some notes before running: +1. change `ws://localhost:3334` in `ui/src/lib/consts.ts` to your relay url endpoint and build the UI +2. configure the relay settings in `.env` +3. manually add someone to the `whitelist.json` file, like this: `[{"pk":"07adfda9c5adc80881bb2a5220f6e3181e0c043b90fa115c4f183464022968e6","invited_by":""}]` \ No newline at end of file diff --git a/go.mod b/go.mod index add2259..442e36e 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,16 @@ module github.com/github-tijlxyz/khatru-invite -go 1.20 +go 1.21.1 require ( - github.com/fiatjaf/khatru v0.0.2 + github.com/fiatjaf/khatru v0.0.0-20230916185141-24d1e3aebd67 github.com/joho/godotenv v1.5.1 github.com/nbd-wtf/go-nostr v0.20.0 ) require ( github.com/andybalholm/brotli v1.0.5 // indirect + github.com/bmatsuo/lmdb-go v1.8.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -28,9 +29,11 @@ require ( github.com/golang/protobuf v1.3.1 // indirect github.com/golang/snappy v0.0.3 // indirect github.com/google/flatbuffers v1.12.1 // indirect + github.com/jmoiron/sqlx v1.3.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.16.5 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-sqlite3 v1.14.6 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/puzpuzpuz/xsync v1.5.2 // indirect github.com/rs/cors v1.7.0 // indirect diff --git a/go.sum b/go.sum index f92bdef..9028c9a 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/bmatsuo/lmdb-go v1.8.0 h1:ohf3Q4xjXZBKh4AayUY4bb2CXuhRAI8BYGlJq08EfNA= +github.com/bmatsuo/lmdb-go v1.8.0/go.mod h1:wWPZmKdOAZsl4qOqkowQ1aCrFie1HU8gWloHMCeAUdM= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= @@ -27,8 +29,9 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fasthttp/websocket v1.5.3 h1:TPpQuLwJYfd4LJPXvHDYPMFWbLjsT91n3GpWtCQtdek= github.com/fasthttp/websocket v1.5.3/go.mod h1:46gg/UBmTU1kUaTcwQXpUxtRwG2PvIZYeA8oL6vF3Fs= -github.com/fiatjaf/khatru v0.0.2 h1:+OaARQhrColJG1NypLDWgkaERjJhbLAtUk8RIYETeGU= -github.com/fiatjaf/khatru v0.0.2/go.mod h1:XDX+UIURFlTrAAw/ya7M5YRC4ft2Qm2gAAvs3ELoVps= +github.com/fiatjaf/khatru v0.0.0-20230916185141-24d1e3aebd67 h1:nsaUBS6rjAZCvPDgGUxG3tzfZnx6DX9iUBqPtDWDT/g= +github.com/fiatjaf/khatru v0.0.0-20230916185141-24d1e3aebd67/go.mod h1:XDX+UIURFlTrAAw/ya7M5YRC4ft2Qm2gAAvs3ELoVps= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= @@ -50,6 +53,8 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/jmoiron/sqlx v1.3.1 h1:aLN7YINNZ7cYOPK3QC83dbM6KT0NMqVMw961TqrejlE= +github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -58,8 +63,11 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/nbd-wtf/go-nostr v0.20.0 h1:97SYhg68jWh5G1bW1g454hA0dTV7btwtPg836n4no0o= github.com/nbd-wtf/go-nostr v0.20.0/go.mod h1:iFfiZr8YYSC1vmdUei0VfDB7GH/RjS3cbmiD1I5BKyo= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -75,6 +83,7 @@ github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -148,4 +157,5 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/handler.go b/handler.go index 5c05cb4..ff5c181 100644 --- a/handler.go +++ b/handler.go @@ -7,20 +7,6 @@ import ( "strings" ) -func inviteDataApiHandler(w http.ResponseWriter, re *http.Request) { - jsonBytes, err := json.Marshal(whitelist) - if err != nil { - http.Error(w, "internal server error", http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Access-Control-Allow-Origin", "*") - w.WriteHeader(http.StatusOK) - if _, err := w.Write(jsonBytes); err != nil { - http.Error(w, "internal server error", http.StatusInternalServerError) - } -} - // embed ui files //go:embed ui/dist/* var uiContent embed.FS @@ -52,3 +38,31 @@ func embeddedUIHandler(w http.ResponseWriter, r *http.Request) { return } } + +func inviteDataApiHandler(w http.ResponseWriter, re *http.Request) { + jsonBytes, err := json.Marshal(whitelist) + if err != nil { + http.Error(w, "internal server error 00", http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.WriteHeader(http.StatusOK) + if _, err := w.Write(jsonBytes); err != nil { + http.Error(w, "internal server error 01", http.StatusInternalServerError) + } +} + +func relayMasterApiHandler(w http.ResponseWriter, re *http.Request) { + jsonBytes, err := json.Marshal(relayMaster) + if err != nil { + http.Error(w, "internal server error 10", http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.WriteHeader(http.StatusOK) + if _, err := w.Write(jsonBytes); err != nil { + http.Error(w, "internal server error 11", http.StatusInternalServerError) + } +} diff --git a/main.go b/main.go index 117e9f5..8c39a3f 100644 --- a/main.go +++ b/main.go @@ -40,7 +40,7 @@ func main() { // init relay relay := khatru.NewRelay() - relayMaster = os.Getenv("INVITE_MASTER") + relayMaster = os.Getenv("INVITE_RELAY_MASTER") relay.Name = os.Getenv("RELAY_NAME") relay.Description = os.Getenv("RELAY_DESCRIPTION") relay.PubKey = os.Getenv("RELAY_PUBKEY") @@ -52,7 +52,7 @@ func main() { } // load db - db = badgern.BadgerBackend{Path: "/tmp/khatru-badgern-tmp"} + db = badgern.BadgerBackend{Path: "./khatru-badgern-db"} if err := db.Init(); err != nil { panic(err) } @@ -62,11 +62,12 @@ func main() { relay.CountEvents = append(relay.CountEvents, db.CountEvents) relay.DeleteEvent = append(relay.DeleteEvent, db.DeleteEvent) - relay.RejectEvent = append(relay.RejectEvent, whitelistRejecter) // invitedata api relay.Router().HandleFunc("/invitedata", inviteDataApiHandler) + relay.Router().HandleFunc("/relaymaster", relayMasterApiHandler) + // ui relay.Router().HandleFunc("/", embeddedUIHandler) diff --git a/ui/src/App.svelte b/ui/src/App.svelte index 9c097fd..1d2a356 100644 --- a/ui/src/App.svelte +++ b/ui/src/App.svelte @@ -3,7 +3,7 @@ import Hieracy from "./components/Hierarchy.svelte"; import Invite from "./components/Invite.svelte"; import { onMount } from "svelte"; - import { ndk, userPublickey } from "./lib/nostr"; + import { ndk, relayMaster, userPublickey } from "./lib/nostr"; import { NDKNip07Signer } from "@nostr-dev-kit/ndk"; import { buildHierarchy } from "./lib/utils"; import { nip19 } from "nostr-tools"; @@ -20,9 +20,15 @@ } async function fetchData() { + // Fetch Invite Data const response = await fetch("/invitedata"); invitedata = Object.values(await response.json()); hierarchy = buildHierarchy(invitedata, { pk: "", invited_by: "" }); + + // Fetch Relay Master Pubkey + const response0 = await fetch("/relaymaster"); + $relayMaster = await response0.json(); + relayMaster.set($relayMaster); } let invitedata = []; @@ -30,54 +36,62 @@ onMount(() => { addEventListener("load", (e) => { - login(); + setTimeout(() => { + login(); + }, 1); }); fetchData(); });
-

Invite Relay

+

Invite Relay

{#if adminView == true} - - - {:else if adminView == false} -
- {#if $userPublickey === undefined} - - {/if} -
-
-
- {#if invitedata.find((p) => $userPublickey == nip19.npubEncode(p.pk))} + on:click={() => (adminView = false)} + type="button" + class="inline-flex mr-2 items-center px-3 py-2 border border-gray-300 shadow-sm text-sm leading-4 font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500" + >Leave Reports Viewer +

+ You are{$userPublickey == nip19.npubEncode($relayMaster) ? "" : " not"} logged + in as a relay master +

+ + {:else if adminView == false}
-

Invite Someone

+ {#if $userPublickey === undefined} + + {/if} +
+ {#if $userPublickey !== undefined}
- + +
+ {/if} + {#if invitedata.find((p) => $userPublickey == nip19.npubEncode(p.pk))} +
+

Invite Someone

+
+ +
+
+ {/if} +
+

Current hieracy

+
+
{/if} -
-

Current hieracy

-
- -
-
- {/if}
diff --git a/ui/src/components/AdminView.svelte b/ui/src/components/AdminView.svelte index 2d3d559..c4eee87 100644 --- a/ui/src/components/AdminView.svelte +++ b/ui/src/components/AdminView.svelte @@ -1,12 +1,9 @@ -