diff --git a/handler.go b/handler.go index 24377ef..5d655a4 100644 --- a/handler.go +++ b/handler.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "net/http" "github.com/nbd-wtf/go-nostr" @@ -23,6 +24,11 @@ func addToWhitelistHandler(w http.ResponseWriter, r *http.Request) { pubkey = value.(string) } + if hasInvitedAtLeast(loggedUser, s.MaxInvitesPerPerson) { + http.Error(w, fmt.Sprintf("cannot invite more than %d", s.MaxInvitesPerPerson), 403) + return + } + if err := addToWhitelist(pubkey, loggedUser); err != nil { http.Error(w, "failed to add to whitelist: "+err.Error(), 500) return diff --git a/main.go b/main.go index 4a31b7c..dcb886f 100644 --- a/main.go +++ b/main.go @@ -28,6 +28,8 @@ type Settings struct { RelayContact string `envconfig:"RELAY_CONTACT"` RelayIcon string `envconfig:"RELAY_ICON"` DatabasePath string `envconfig:"DATABASE_PATH" default:"./db"` + + MaxInvitesPerPerson int `envconfig:"MAX_INVITES_PER_PERSON" default:"3"` } var ( diff --git a/pages.go b/pages.go index 22d5cfd..e51eb18 100644 --- a/pages.go +++ b/pages.go @@ -51,7 +51,7 @@ type InviteTreePageParams struct { func inviteTreePageHTML(ctx context.Context, params InviteTreePageParams) HTMLComponent { inviteForm := Div() - if params.loggedUser != "" { + if params.loggedUser != "" && !hasInvitedAtLeast(params.loggedUser, s.MaxInvitesPerPerson) { inviteForm = 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+" ml-2 p-2 bg-white hover:bg-gray-50"), diff --git a/whitelist.go b/whitelist.go index fbe9d13..c677555 100644 --- a/whitelist.go +++ b/whitelist.go @@ -17,7 +17,7 @@ func addToWhitelist(pubkey string, inviter string) error { return fmt.Errorf("pubkey %s doesn't have permission to invite", inviter) } - if !nostr.IsValidPublicKeyHex(pubkey) { + if !nostr.IsValidPublicKey(pubkey) { return fmt.Errorf("pubkey invalid: %s", pubkey) } @@ -34,6 +34,19 @@ func isPublicKeyInWhitelist(pubkey string) bool { return ok } +func hasInvitedAtLeast(ancestor string, target int) bool { + count := 0 + for _, inviter := range whitelist { + if inviter == ancestor { + count++ + } + if count >= target { + return true + } + } + return false +} + func isAncestorOf(ancestor string, target string) bool { parent, ok := whitelist[target] if !ok {