reorganize backend code a little.

This commit is contained in:
fiatjaf 2023-10-16 23:09:12 -03:00
parent 1bb9f22539
commit 6fbde5f302
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1
7 changed files with 69 additions and 57 deletions

View File

@ -1,8 +1,4 @@
# Nostr Standard Relay Info
RELAY_NAME="Name of the Relay"
RELAY_DESCRIPTION="Description of the relay"
RELAY_PUBKEY="07adfda9c5adc80881bb2a5220f6e3181e0c043b90fa115c4f183464022968e6"
RELAY_CONTACT="email@example.com"
# Custom invite-relay settings
INVITE_RELAY_MASTER="07adfda9c5adc80881bb2a5220f6e3181e0c043b90fa115c4f183464022968e6" # Master of the relay (pubkey hex)

6
go.mod
View File

@ -5,7 +5,9 @@ go 1.20
require (
github.com/fiatjaf/khatru v0.0.0-20231003113207-bbe186494e68
github.com/joho/godotenv v1.5.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/nbd-wtf/go-nostr v0.20.0
github.com/rs/zerolog v1.31.0
)
require (
@ -32,6 +34,8 @@ require (
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-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/puzpuzpuz/xsync v1.5.2 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
@ -45,6 +49,6 @@ require (
go.opencensus.io v0.22.5 // indirect
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/sys v0.12.0 // indirect
google.golang.org/protobuf v1.23.0 // indirect
)

17
go.sum
View File

@ -31,6 +31,7 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -62,6 +63,7 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.2.0 h1:u0p9s3xLYpZCA1z5JgCkMeB34CKCMMQbM+G8Ii7YD0I=
github.com/gobwas/ws v1.2.0/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
@ -94,6 +96,8 @@ github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwA
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
@ -101,6 +105,11 @@ github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/d
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@ -122,6 +131,9 @@ github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9p
github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -188,10 +200,11 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=

View File

@ -20,8 +20,8 @@ func inviteTreeHandler(w http.ResponseWriter, r *http.Request) {
formattedInviteData := buildHTMLTree(whitelist, "")
data := map[string]interface{}{
"Relayname": relayName,
"Relaydescription": relayDescription,
"Relayname": s.RelayName,
"Relaydescription": s.RelayDescription,
"Pagetitle": "Invite Hierarchy",
"Pagecontent": `
<input type="text" id="inviteuser-input" placeholder="npub1..." /><button class="inviteuser">Invite!</button>
@ -63,7 +63,7 @@ func reportsViewerHandler(w http.ResponseWriter, r *http.Request) {
eTag := ev.Tags.GetFirst([]string{"e"})
if pTag != nil {
var typeReport = eTag.Relay()[6:]
typeReport := eTag.Relay()[6:]
if typeReport == "" {
typeReport = pTag.Relay()[6:]
}
@ -132,8 +132,8 @@ func reportsViewerHandler(w http.ResponseWriter, r *http.Request) {
}
data := map[string]interface{}{
"Relayname": relayName,
"Relaydescription": relayDescription,
"Relayname": s.RelayName,
"Relaydescription": s.RelayDescription,
"Pagetitle": "Reports Viewer",
"Pagecontent": formattedReportsData,
}
@ -153,11 +153,11 @@ func reportsViewerHandler(w http.ResponseWriter, r *http.Request) {
}
func homePageHandler(w http.ResponseWriter, r *http.Request) {
relayOwnerInfo := getUserInfo(context.Background(), relayPubkey)
relayOwnerInfo := getUserInfo(context.Background(), s.RelayPubkey)
data := map[string]interface{}{
"Relayname": relayName,
"Relaydescription": relayDescription,
"Relayname": s.RelayName,
"Relaydescription": s.RelayDescription,
"Pagetitle": "Info",
"Pagecontent": template.HTML(fmt.Sprintf(`
<div>Relay Name: %v</div>
@ -166,7 +166,7 @@ func homePageHandler(w http.ResponseWriter, r *http.Request) {
<div>Relay Alternative Contact: %v</div>
<br />
<div><sub>This relay uses <a target="_blank" rel="noopener noreferrer" href="https://github.com/github-tijlxyz/khatru-invite">Khatru Invite</a>, which is build with <a target="_blank" rel="noopener noreferrer" href="https://github.com/fiatjaf/khatru">Khatru</a></sub></div>
`, relayName, relayDescription, relayOwnerInfo.Npub, relayOwnerInfo.Name, relayContact)),
`, s.RelayName, s.RelayDescription, relayOwnerInfo.Npub, relayOwnerInfo.Name, s.RelayContact)),
}
tmpl, err := template.ParseFS(dist, "ui/dist/index.html")

43
main.go
View File

@ -1,7 +1,6 @@
package main
import (
"fmt"
"net/http"
"os"
"os/signal"
@ -12,18 +11,30 @@ import (
"github.com/fiatjaf/khatru"
"github.com/fiatjaf/khatru/plugins/storage/badgern"
"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
"github.com/rs/zerolog"
)
type Settings struct {
RelayName string `envconfig:"RELAY_NAME" required:"true"`
RelayPubkey string `envconfig:"RELAY_PUBKEY" required:"true"`
RelayDescription string `envconfig:"RELAY_DESCRIPTION"`
RelayContact string `envconfig:"RELAY_CONTACT"`
}
var (
relayMaster string
db badgern.BadgerBackend
relayName string = ""
relayPubkey string = ""
relayDescription string = "none"
relayContact string = "none"
db badgern.BadgerBackend
s Settings
log = zerolog.New(os.Stderr).Output(zerolog.ConsoleWriter{Out: os.Stdout}).With().Timestamp().Logger()
)
func main() {
err := envconfig.Process("", &s)
if err != nil {
log.Fatal().Err(err).Msg("couldn't process envconfig")
return
}
// save whitelist on shutdown
var wg sync.WaitGroup
wg.Add(1)
@ -46,18 +57,10 @@ func main() {
// init relay
relay := khatru.NewRelay()
relayMaster = os.Getenv("INVITE_RELAY_MASTER")
// add information here!
relayName = os.Getenv("RELAY_NAME")
relayPubkey = os.Getenv("RELAY_PUBKEY")
relayDescription = os.Getenv("RELAY_DESCRIPTION")
relayContact = os.Getenv("RELAY_CONTACT")
relay.Name = relayName
relay.PubKey = relayPubkey
relay.Description = relayDescription
relay.Contact = relayContact
relay.Name = s.RelayName
relay.PubKey = s.RelayPubkey
relay.Description = s.RelayDescription
relay.Contact = s.RelayContact
// load whitelist storage
if err := loadWhitelist(); err != nil {
@ -82,7 +85,7 @@ func main() {
relay.Router().HandleFunc("/users", inviteTreeHandler)
relay.Router().HandleFunc("/", redirectHandler)
fmt.Println("running on :3334")
log.Info().Msg("running on http://127.0.0.1:3334")
http.ListenAndServe(":3334", relay)
}

View File

@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"html/template"
"log"
"github.com/nbd-wtf/go-nostr"
)
@ -15,7 +14,7 @@ func buildHTMLTree(entries []WhitelistEntry, invitedBy string) template.HTML {
for _, entry := range entries {
if entry.InvitedBy == invitedBy {
user := getUserInfo(context.TODO(), entry.Pk)
user := getUserInfo(context.TODO(), entry.PublicKey)
html += fmt.Sprintf(`
<li>
<a class="user" href="nostr:%s">%s</a>
@ -23,8 +22,8 @@ func buildHTMLTree(entries []WhitelistEntry, invitedBy string) template.HTML {
%s
</li>`, template.HTMLEscapeString(user.Npub),
template.HTMLEscapeString(user.Name),
entry.Pk,
buildHTMLTree(entries, entry.Pk))
entry.PublicKey,
buildHTMLTree(entries, entry.PublicKey))
}
}
@ -34,7 +33,7 @@ func buildHTMLTree(entries []WhitelistEntry, invitedBy string) template.HTML {
func isPkInWhitelist(targetPk string) bool {
for i := 0; i < len(whitelist); i++ {
if whitelist[i].Pk == targetPk {
if whitelist[i].PublicKey == targetPk {
return true
}
}
@ -47,11 +46,11 @@ func deleteFromWhitelistRecursively(ctx context.Context, target string) {
// Remove from whitelist
for _, user := range whitelist {
if user.Pk != target {
if user.PublicKey != target {
updatedWhitelist = append(updatedWhitelist, user)
}
if user.InvitedBy == target {
queue = append(queue, user.Pk)
queue = append(queue, user.PublicKey)
}
}
whitelist = updatedWhitelist
@ -64,7 +63,7 @@ func deleteFromWhitelistRecursively(ctx context.Context, target string) {
for ev := range events {
err := db.DeleteEvent(ctx, ev)
if err != nil {
log.Println("error while deleting event", err)
log.Error().Err(err).Msg("failed to delete event")
}
}
@ -80,7 +79,7 @@ func getProfileInfoFromJson(jsonStr string) (string, string) {
var data map[string]interface{}
err := json.Unmarshal([]byte(jsonStr), &data)
if err != nil {
fmt.Println("Error parsing JSON:", err)
log.Error().Err(err).Msg("failed to read profile from json")
return "", ""
}

View File

@ -3,21 +3,19 @@ package main
import (
"context"
"encoding/json"
"log"
"os"
"github.com/nbd-wtf/go-nostr"
)
type WhitelistEntry struct {
Pk string `json:"pk"`
PublicKey string `json:"pk"`
InvitedBy string `json:"invited_by"`
}
var whitelist []WhitelistEntry
func whitelistRejecter(ctx context.Context, evt *nostr.Event) (reject bool, msg string) {
// check if user in whitelist
if !isPkInWhitelist(evt.PubKey) {
return true, "You are not invited to this relay"
@ -32,7 +30,7 @@ func whitelistRejecter(ctx context.Context, evt *nostr.Event) (reject bool, msg
for _, tag := range pTags {
if !isPkInWhitelist(tag.Value()) {
if nostr.IsValidPublicKeyHex(tag.Value()) {
whitelist = append(whitelist, WhitelistEntry{Pk: tag.Value(), InvitedBy: evt.PubKey})
whitelist = append(whitelist, WhitelistEntry{PublicKey: tag.Value(), InvitedBy: evt.PubKey})
}
}
}
@ -52,13 +50,13 @@ func whitelistRejecter(ctx context.Context, evt *nostr.Event) (reject bool, msg
2: Cant remove self
3: User should have invited user OR be relay admin
*/
if user.Pk == tag.Value() && evt.PubKey != tag.Value() && (user.InvitedBy == evt.PubKey || evt.PubKey == relayMaster) {
log.Println("deleting user", tag.Value())
if user.PublicKey == tag.Value() && evt.PubKey != tag.Value() && (user.InvitedBy == evt.PubKey || evt.PubKey == s.RelayPubkey) {
log.Info().Str("user", tag.Value()).Msg("deleting user")
deleteFromWhitelistRecursively(ctx, tag.Value())
}
}
}
if evt.PubKey == relayMaster {
if evt.PubKey == s.RelayPubkey {
eTags := evt.Tags.GetAll([]string{"e"})
for _, tag := range eTags {
filter := nostr.Filter{
@ -66,11 +64,11 @@ func whitelistRejecter(ctx context.Context, evt *nostr.Event) (reject bool, msg
}
events, _ := db.QueryEvents(ctx, filter)
for ev := range events {
log.Println("deleting event", ev.ID)
err := db.DeleteEvent(ctx, ev)
for evt := range events {
log.Info().Str("event", evt.ID).Msg("deleting event")
err := db.DeleteEvent(ctx, evt)
if err != nil {
log.Println("error while deleting event", err)
log.Warn().Err(err).Msg("failed to delete event")
}
}
}
@ -78,7 +76,6 @@ func whitelistRejecter(ctx context.Context, evt *nostr.Event) (reject bool, msg
}
return false, ""
}
func loadWhitelist() error {