basic reports page (just displaying, untested).

This commit is contained in:
fiatjaf 2023-11-02 20:59:50 -03:00
parent 3846365c8e
commit 8885d99cac
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1
5 changed files with 120 additions and 111 deletions

View File

@ -32,13 +32,13 @@ func userRowComponent(ctx context.Context, profile sdk.ProfileMetadata, loggedUs
} }
return Li( return Li(
userNameComponent(ctx, profile), userNameComponent(profile),
button, button,
inviteTreeComponent(ctx, profile.PubKey, loggedUser), inviteTreeComponent(ctx, profile.PubKey, loggedUser),
).Class("ml-6") ).Class("ml-6")
} }
func userNameComponent(ctx context.Context, profile sdk.ProfileMetadata) HTMLComponent { func userNameComponent(profile sdk.ProfileMetadata) HTMLComponent {
return A().Href("nostr:" + profile.Npub()).Children( return A().Href("nostr:" + profile.Npub()).Children(
Span(profile.ShortName()).Attr( Span(profile.ShortName()).Attr(
"npub", profile.Npub(), "npub", profile.Npub(),

View File

@ -3,6 +3,7 @@ package main
import ( import (
"net/http" "net/http"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19" "github.com/nbd-wtf/go-nostr/nip19"
"github.com/theplant/htmlgo" "github.com/theplant/htmlgo"
) )
@ -43,114 +44,20 @@ func removeFromWhitelistHandler(w http.ResponseWriter, r *http.Request) {
} }
func reportsViewerHandler(w http.ResponseWriter, r *http.Request) { func reportsViewerHandler(w http.ResponseWriter, r *http.Request) {
// var formattedReportsData template.HTML = "" events, err := db.QueryEvents(r.Context(), nostr.Filter{
Kinds: []int{1984},
Limit: 52,
})
if err != nil {
http.Error(w, "failed to query reports: "+err.Error(), 500)
return
}
// events, _ := db.QueryEvents(context.Background(), nostr.Filter{ content := reportsPageHTML(r.Context(), ReportsPageParams{
// Kinds: []int{1984}, reports: events,
// Limit: 52, loggedUser: getLoggedUser(r),
// }) })
htmlgo.Fprint(w, content, r.Context())
// type Report struct {
// ID string
// ByUser string
// AboutUser string
// AboutEvent string
// Type string
// Content string
// }
// for ev := range events {
// pTag := ev.Tags.GetFirst([]string{"p"})
// eTag := ev.Tags.GetFirst([]string{"e"})
// if pTag != nil {
// typeReport := eTag.Relay()[6:]
// if typeReport == "" {
// typeReport = pTag.Relay()[6:]
// }
// report := Report{
// ID: ev.ID,
// ByUser: ev.PubKey,
// AboutUser: pTag.Value(),
// AboutEvent: eTag.Value(),
// Type: typeReport,
// Content: ev.Content,
// }
// // get AboutEvent content, note1 ect
// formattedReportsData += template.HTML(fmt.Sprintf(`
// <div>
// <p><b>Report %v</b></p>
// <p>By User: <a class="user" href="nostr:%v">%v</a></p>
// <p>About User: <a class="user" href="nostr:%v">%v</a></p>`,
// report.ID,
// getUserInfo(context.Background(), report.ByUser).Npub,
// getUserInfo(context.Background(), report.ByUser).Name,
// getUserInfo(context.Background(), report.AboutUser).Npub,
// getUserInfo(context.Background(), report.AboutUser).Name,
// ))
// if report.AboutEvent != "" {
// // fetch event data
// aboutEvents, _ := db.QueryEvents(context.TODO(), nostr.Filter{
// IDs: []string{report.AboutEvent},
// })
// for aboutEvent := range aboutEvents {
// formattedReportsData += template.HTML(fmt.Sprintf(`
// <p>
// About Event: <ul>
// <p>Kind: %v</p>
// <p>Tags: %v</p>
// <p>Content: %v</p>
// </ul>
// </p>`,
// template.HTMLEscaper(aboutEvent.Kind),
// template.HTMLEscaper(aboutEvent.Tags),
// template.HTMLEscaper(aboutEvent.Content),
// ))
// }
// }
// formattedReportsData += template.HTML(fmt.Sprintf(`
// <p>Type: %v</p>`,
// report.Type,
// ))
// if report.Content != "" {
// formattedReportsData += template.HTML(fmt.Sprintf(`
// <p>Content: %v</p>
// <div>
// <button data-actionarg='[["e", "%v"],["p", "%v"]]' class="removefromrelay">Ban Reported User and Remove Report</button>
// <button data-actionarg='[["e", "%v"]]' class="removefromrelay">Remove This Report</button>
// <button data-actionarg='[["p", "%v"]]' class="removefromrelay">Ban User who wrote report</button>
// </div>
// </div>
// <hr />`,
// template.HTMLEscaper(report.Content),
// template.HTMLEscaper(report.ID),
// template.HTMLEscaper(report.AboutUser),
// template.HTMLEscaper(report.ID),
// template.HTMLEscaper(report.ByUser),
// ))
// }
// }
// }
// data := map[string]interface{}{
// "Relayname": s.RelayName,
// "Relaydescription": s.RelayDescription,
// "Pagetitle": "Reports Viewer",
// "Pagecontent": formattedReportsData,
// }
// tmpl, err := template.ParseFS(dist, "ui/dist/index.html")
// if err != nil {
// http.Error(w, "Error parsing template: "+err.Error(), http.StatusInternalServerError)
// return
// }
// // Execute the template with the provided data and write it to the response
// err = tmpl.Execute(w, data)
// if err != nil {
// http.Error(w, "Error executing template: "+err.Error(), http.StatusInternalServerError)
// return
// }
} }
func homePageHandler(w http.ResponseWriter, r *http.Request) { func homePageHandler(w http.ResponseWriter, r *http.Request) {

View File

@ -56,7 +56,11 @@ func main() {
relay.QueryEvents = append(relay.QueryEvents, db.QueryEvents) relay.QueryEvents = append(relay.QueryEvents, db.QueryEvents)
relay.CountEvents = append(relay.CountEvents, db.CountEvents) relay.CountEvents = append(relay.CountEvents, db.CountEvents)
relay.DeleteEvent = append(relay.DeleteEvent, db.DeleteEvent) relay.DeleteEvent = append(relay.DeleteEvent, db.DeleteEvent)
relay.RejectEvent = append(relay.RejectEvent, rejectEventsFromUsersNotInWhitelist) relay.RejectEvent = append(relay.RejectEvent,
rejectEventsFromUsersNotInWhitelist,
restrictToKinds,
validateAndFilterReports,
)
// load users registry // load users registry
if err := loadWhitelist(); err != nil { if err := loadWhitelist(); err != nil {

View File

@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"github.com/nbd-wtf/go-nostr"
sdk "github.com/nbd-wtf/nostr-sdk" sdk "github.com/nbd-wtf/nostr-sdk"
. "github.com/theplant/htmlgo" . "github.com/theplant/htmlgo"
) )
@ -62,7 +63,7 @@ func homePageHTML(ctx context.Context, params HomePageParams) HTMLComponent {
contact, contact,
Div( Div(
Text("relay master: "), Text("relay master: "),
userNameComponent(ctx, params.relayOwnerInfo), userNameComponent(params.relayOwnerInfo),
), ),
Br(), Br(),
Div( Div(
@ -102,3 +103,71 @@ func inviteTreePageHTML(ctx context.Context, params InviteTreePageParams) HTMLCo
).Id("tree").Class("mt-3"), ).Id("tree").Class("mt-3"),
) )
} }
type ReportsPageParams struct {
reports chan *nostr.Event
loggedUser string
}
func reportsPageHTML(ctx context.Context, params ReportsPageParams) HTMLComponent {
items := make([]HTMLComponent, 0, 52)
for report := range params.reports {
var primaryType string
var secondaryType string
var relatedContent HTMLComponent
if e := report.Tags.GetFirst([]string{"e", ""}); e != nil {
// event report
res, _ := sys.StoreRelay().QuerySync(ctx, nostr.Filter{IDs: []string{(*e)[1]}})
if len(res) == 0 {
sys.Store.DeleteEvent(ctx, report)
continue
}
if len(*e) >= 3 {
primaryType = (*e)[2]
}
relatedEvent := res[0]
relatedContent = Div(
Text("event reported: "),
Div().Text(relatedEvent.String()).Class("text-mono"),
)
} else if p := report.Tags.GetFirst([]string{"p", ""}); p != nil {
// pubkey report
if !isPublicKeyInWhitelist((*p)[1]) {
sys.Store.DeleteEvent(ctx, report)
continue
}
if len(*p) >= 3 {
primaryType = (*p)[2]
}
relatedProfile := fetchAndStoreProfile(ctx, (*p)[1])
relatedContent = Div(
Text("profile reported: "),
userNameComponent(relatedProfile),
)
} else {
continue
}
reporter := sys.FetchProfileMetadata(ctx, report.PubKey)
report := Div(
Div(Span(primaryType).Class("font-semibold"), Text(" report")).Class("font-lg"),
Div().Text(secondaryType),
Div(Text("by "), userNameComponent(reporter)),
Div().Text(report.Content).Class("p-3"),
relatedContent,
)
items = append(items, report)
}
return baseHTML(
Div(
H1("reports received").Class("text-xl p-4"),
Div(items...),
),
)
}

View File

@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"github.com/fiatjaf/khatru/plugins"
"github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr"
) )
@ -10,5 +11,33 @@ func rejectEventsFromUsersNotInWhitelist(ctx context.Context, event *nostr.Event
if isPublicKeyInWhitelist(event.PubKey) { if isPublicKeyInWhitelist(event.PubKey) {
return false, "" return false, ""
} }
if event.Kind == 1985 {
// we accept reports from anyone (will filter them for relevance in the next function)
return false, ""
}
return true, "not authorized" return true, "not authorized"
} }
var restrictToKinds = plugins.RestrictToSpecifiedKinds(
0, 1, 3, 5, 6, 8, 16, 1063, 1985, 9735, 10000, 10001, 10002, 30008, 30009, 30311, 31922, 31923, 31924, 31925)
func validateAndFilterReports(ctx context.Context, event *nostr.Event) (reject bool, msg string) {
if event.Kind == 1985 {
if e := event.Tags.GetFirst([]string{"e", ""}); e != nil {
// event report: check if the target event is here
res, _ := sys.StoreRelay().QuerySync(ctx, nostr.Filter{IDs: []string{(*e)[1]}})
if len(res) == 0 {
return true, "we don't know anything about the target event"
}
} else if p := event.Tags.GetFirst([]string{"p", ""}); p != nil {
// pubkey report
if !isPublicKeyInWhitelist((*p)[1]) {
return true, "target pubkey is not a user of this relay"
}
} else {
return true, "invalid report"
}
}
return false, ""
}