making everything almost work again.

This commit is contained in:
fiatjaf 2023-10-28 20:21:15 -03:00
parent 32c484178f
commit 86509c59b5
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1
5 changed files with 66 additions and 59 deletions

View File

@ -19,6 +19,26 @@ func inviteTreeHandler(w http.ResponseWriter, r *http.Request) {
htmlgo.Fprint(w, baseHTML(content), r.Context())
}
func addToWhitelistHandler(w http.ResponseWriter, r *http.Request) {
pubkey := r.PostFormValue("pubkey")
if err := addToWhitelist(r.Context(), pubkey, s.RelayPubkey); err != nil {
http.Error(w, "failed to add to whitelist: "+err.Error(), 500)
return
}
content := buildInviteTree(r.Context(), s.RelayPubkey)
htmlgo.Fprint(w, content, r.Context())
}
func removeFromWhitelistHandler(w http.ResponseWriter, r *http.Request) {
pubkey := r.PostFormValue("pubkey")
if err := removeFromWhitelist(r.Context(), pubkey); err != nil {
http.Error(w, "failed to remove from whitelist: "+err.Error(), 500)
return
}
content := buildInviteTree(r.Context(), s.RelayPubkey)
htmlgo.Fprint(w, content, r.Context())
}
func reportsViewerHandler(w http.ResponseWriter, r *http.Request) {
// var formattedReportsData template.HTML = ""

2
justfile Normal file
View File

@ -0,0 +1,2 @@
dev:
godotenv go run .

37
main.go
View File

@ -3,14 +3,9 @@ package main
import (
"net/http"
"os"
"os/signal"
"sync"
"syscall"
"time"
"github.com/fiatjaf/khatru"
"github.com/fiatjaf/khatru/plugins/storage/badgern"
"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
"github.com/rs/zerolog"
)
@ -36,25 +31,6 @@ func main() {
return
}
// save whitelist on shutdown
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
handleSignals()
}()
// backup whitelist every hour
go func() {
for {
time.Sleep(time.Hour)
saveWhitelist()
}
}()
// init env config
godotenv.Load(".env")
// init relay
relay := khatru.NewRelay()
@ -78,11 +54,11 @@ func main() {
relay.QueryEvents = append(relay.QueryEvents, db.QueryEvents)
relay.CountEvents = append(relay.CountEvents, db.CountEvents)
relay.DeleteEvent = append(relay.DeleteEvent, db.DeleteEvent)
relay.RejectEvent = append(relay.RejectEvent, whitelistRejecter)
// ui
relay.Router().HandleFunc("/reports", reportsViewerHandler)
relay.Router().HandleFunc("/add-to-whitelist", addToWhitelistHandler)
relay.Router().HandleFunc("/remove-from-whitelist", removeFromWhitelistHandler)
relay.Router().HandleFunc("/users", inviteTreeHandler)
relay.Router().HandleFunc("/", homePageHandler)
@ -91,12 +67,3 @@ func main() {
log.Fatal().Err(err).Msg("failed to serve")
}
}
// save whitelist on shutdown
func handleSignals() {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
<-sigCh
saveWhitelist()
os.Exit(0)
}

View File

@ -6,8 +6,10 @@ import (
. "github.com/theplant/htmlgo"
)
const buttonClass = "rounded-md bg-white p-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
func baseHTML(inside HTMLComponent) HTMLComponent {
navItemClass := "text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 font-medium"
navItemClass := "text-gray-600 hover:bg-gray-200 rounded-md px-3 py-2 font-medium"
return HTML(
Head(
@ -15,6 +17,8 @@ func baseHTML(inside HTMLComponent) HTMLComponent {
Meta().Name("viewport").Content("width=device-width, initial-scale=1"),
Title(s.RelayName),
Script("").Src("https://cdn.tailwindcss.com"),
Script("").Src("https://unpkg.com/htmx.org@1.9.6"),
Script("").Src("https://unpkg.com/hyperscript.org@0.9.12"),
),
Body(
Div(
@ -22,12 +26,12 @@ func baseHTML(inside HTMLComponent) HTMLComponent {
P().Text(s.RelayDescription).Class("text-lg"),
).Class("mx-auto my-6 text-center"),
Nav(
A().Text("information").Href("/").Class(navItemClass),
A().Text("invite tree").Href("/users").Class(navItemClass),
A().Text("reports").Href("/reports").Class(navItemClass),
A().Text("information").Href("/").Class(navItemClass).Attr("hx-boost", "true", "hx-target", "main", "hx-select", "main"),
A().Text("invite tree").Href("/users").Class(navItemClass).Attr("hx-boost", "true", "hx-target", "main", "hx-select", "main"),
A().Text("reports").Href("/reports").Class(navItemClass).Attr("hx-boost", "true", "hx-target", "main", "hx-select", "main"),
).Class("flex flex-1 items-center justify-center"),
Div(inside).Class("m-4"),
).Class("bg-gray-800 mx-4 my-6 text-white"),
Main(inside).Class("m-4"),
).Class("mx-4 my-6"),
)
}
@ -67,26 +71,28 @@ func homePageHTML(ctx context.Context, params HomePageParams) HTMLComponent {
type InviteTreePageParams struct{}
func inviteTreePageHTML(ctx context.Context, params InviteTreePageParams) HTMLComponent {
return Div(
Input("").Type("text").Placeholder("npub1..."),
Button("invite"),
buildInviteTree(ctx, ""),
)
return Form(
Input("pubkey").Type("text").Placeholder("npub1...").Class("w-96 rounded-md border-0 p-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600"),
Button("invite").Class(buttonClass),
Div(
buildInviteTree(ctx, s.RelayPubkey),
).Id("tree").Class("mt-3"),
).Attr("hx-post", "/add-to-whitelist", "hx-trigger", "submit", "hx-target", "#tree")
}
func buildInviteTree(ctx context.Context, invitedBy string) HTMLComponent {
tree := Ul()
children := make([]HTMLComponent, 0, len(whitelist))
for _, entry := range whitelist {
if entry.InvitedBy == invitedBy {
user := getUserInfo(ctx, entry.PublicKey)
tree = tree.Children(
children = append(children,
Li(
A().Href("nostr:"+user.Npub).Text(user.Name),
A().Text("remove"),
A().Href("nostr:"+user.Npub).Text(user.Name).Class("font-mono"),
Button("remove").Class(buttonClass).Attr("hx-post", "/remove-from-whitelist", "hx-trigger", "click", "hx-target", "#tree"),
buildInviteTree(ctx, entry.PublicKey),
),
).Class("ml-3"),
)
}
}
return tree
return Ul(children...)
}

View File

@ -6,11 +6,12 @@ import (
"os"
"github.com/nbd-wtf/go-nostr"
"golang.org/x/exp/slices"
)
type WhitelistEntry struct {
PublicKey string `json:"pk"`
InvitedBy string `json:"invited_by"`
PublicKey string `json:"pk"`
}
var whitelist []WhitelistEntry
@ -26,12 +27,6 @@ func whitelistRejecter(ctx context.Context, evt *nostr.Event) (reject bool, msg
invited/whitelisted user invites new user
*/
if evt.Kind == 20201 {
pTags := evt.Tags.GetAll([]string{"p"})
for _, tag := range pTags {
if nostr.IsValidPublicKeyHex(tag.Value()) && !isPublicKeyInWhitelist(tag.Value()) {
whitelist = append(whitelist, WhitelistEntry{PublicKey: tag.Value(), InvitedBy: evt.PubKey})
}
}
}
/*
@ -76,6 +71,23 @@ func whitelistRejecter(ctx context.Context, evt *nostr.Event) (reject bool, msg
return false, ""
}
func addToWhitelist(ctx context.Context, pubkey string, invitedBy string) error {
if nostr.IsValidPublicKeyHex(pubkey) && !isPublicKeyInWhitelist(pubkey) {
whitelist = append(whitelist, WhitelistEntry{PublicKey: pubkey, InvitedBy: invitedBy})
}
return saveWhitelist()
}
func removeFromWhitelist(ctx context.Context, pubkey string) error {
idx := slices.IndexFunc(whitelist, func(we WhitelistEntry) bool { return we.PublicKey == pubkey })
if idx == -1 {
return nil
}
whitelist = append(whitelist[0:idx], whitelist[idx+1:]...)
return saveWhitelist()
}
func loadWhitelist() error {
if _, err := os.Stat("whitelist.json"); os.IsNotExist(err) {
whitelist = []WhitelistEntry{}