mirror of
https://github.com/aljazceru/njump.git
synced 2025-12-17 06:14:22 +01:00
commands to ban (and unban) events using the relay management api.
This commit is contained in:
109
internal.pb.go
109
internal.pb.go
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.34.2
|
||||
// protoc v5.28.1
|
||||
// protoc v5.28.2
|
||||
// source: internal.proto
|
||||
|
||||
package main
|
||||
@@ -185,7 +185,7 @@ func (x *PubKeyArchive) GetPubkey() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type EventInRelay struct {
|
||||
type ID struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@@ -193,8 +193,8 @@ type EventInRelay struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *EventInRelay) Reset() {
|
||||
*x = EventInRelay{}
|
||||
func (x *ID) Reset() {
|
||||
*x = ID{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_internal_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
@@ -202,13 +202,13 @@ func (x *EventInRelay) Reset() {
|
||||
}
|
||||
}
|
||||
|
||||
func (x *EventInRelay) String() string {
|
||||
func (x *ID) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*EventInRelay) ProtoMessage() {}
|
||||
func (*ID) ProtoMessage() {}
|
||||
|
||||
func (x *EventInRelay) ProtoReflect() protoreflect.Message {
|
||||
func (x *ID) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
@@ -220,18 +220,73 @@ func (x *EventInRelay) ProtoReflect() protoreflect.Message {
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use EventInRelay.ProtoReflect.Descriptor instead.
|
||||
func (*EventInRelay) Descriptor() ([]byte, []int) {
|
||||
// Deprecated: Use ID.ProtoReflect.Descriptor instead.
|
||||
func (*ID) Descriptor() ([]byte, []int) {
|
||||
return file_internal_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *EventInRelay) GetId() string {
|
||||
func (x *ID) GetId() string {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type BannedEvent struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BannedEvent) Reset() {
|
||||
*x = BannedEvent{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_internal_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *BannedEvent) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BannedEvent) ProtoMessage() {}
|
||||
|
||||
func (x *BannedEvent) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BannedEvent.ProtoReflect.Descriptor instead.
|
||||
func (*BannedEvent) Descriptor() ([]byte, []int) {
|
||||
return file_internal_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *BannedEvent) GetId() []byte {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BannedEvent) GetReason() string {
|
||||
if x != nil {
|
||||
return x.Reason
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_internal_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_internal_proto_rawDesc = []byte{
|
||||
@@ -248,11 +303,14 @@ var file_internal_proto_rawDesc = []byte{
|
||||
0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x27, 0x0a, 0x0d, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79,
|
||||
0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22,
|
||||
0x1e, 0x0a, 0x0c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12,
|
||||
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x42,
|
||||
0x1f, 0x5a, 0x1d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x69,
|
||||
0x61, 0x74, 0x6a, 0x61, 0x66, 0x2f, 0x6e, 0x6a, 0x75, 0x6d, 0x70, 0x3b, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x14, 0x0a, 0x02, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x35, 0x0a, 0x0b, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x45,
|
||||
0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x1f, 0x5a, 0x1d,
|
||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x69, 0x61, 0x74, 0x6a,
|
||||
0x61, 0x66, 0x2f, 0x6e, 0x6a, 0x75, 0x6d, 0x70, 0x3b, 0x6d, 0x61, 0x69, 0x6e, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -267,12 +325,13 @@ func file_internal_proto_rawDescGZIP() []byte {
|
||||
return file_internal_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||
var file_internal_proto_goTypes = []any{
|
||||
(*CachedEvent)(nil), // 0: CachedEvent
|
||||
(*FollowListArchive)(nil), // 1: FollowListArchive
|
||||
(*PubKeyArchive)(nil), // 2: PubKeyArchive
|
||||
(*EventInRelay)(nil), // 3: EventInRelay
|
||||
(*ID)(nil), // 3: ID
|
||||
(*BannedEvent)(nil), // 4: BannedEvent
|
||||
}
|
||||
var file_internal_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
@@ -325,7 +384,19 @@ func file_internal_proto_init() {
|
||||
}
|
||||
}
|
||||
file_internal_proto_msgTypes[3].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*EventInRelay); i {
|
||||
switch v := v.(*ID); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_internal_proto_msgTypes[4].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*BannedEvent); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@@ -343,7 +414,7 @@ func file_internal_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_internal_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumMessages: 5,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -17,6 +17,11 @@ message PubKeyArchive {
|
||||
string pubkey = 1;
|
||||
}
|
||||
|
||||
message EventInRelay {
|
||||
message ID {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message BannedEvent {
|
||||
bytes id = 1;
|
||||
string reason = 2;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ const (
|
||||
TypeFollowListArchive leafdb.DataType = 3
|
||||
TypePubKeyArchive leafdb.DataType = 4
|
||||
TypeEventInRelay leafdb.DataType = 5
|
||||
TypeBannedEvent leafdb.DataType = 6
|
||||
)
|
||||
|
||||
func NewInternalDB(path string) (*InternalDB, error) {
|
||||
@@ -36,7 +37,9 @@ func NewInternalDB(path string) (*InternalDB, error) {
|
||||
case TypePubKeyArchive:
|
||||
v = &PubKeyArchive{}
|
||||
case TypeEventInRelay:
|
||||
v = &EventInRelay{}
|
||||
v = &ID{}
|
||||
case TypeBannedEvent:
|
||||
v = &BannedEvent{}
|
||||
default:
|
||||
return nil, fmt.Errorf("what is this? %v", t)
|
||||
}
|
||||
@@ -74,6 +77,14 @@ func NewInternalDB(path string) (*InternalDB, error) {
|
||||
emit(pkb)
|
||||
},
|
||||
},
|
||||
"banned-event": {
|
||||
Version: 1,
|
||||
Types: []leafdb.DataType{TypeBannedEvent},
|
||||
Emit: func(t leafdb.DataType, value proto.Message, emit func([]byte)) {
|
||||
ban := value.(*BannedEvent)
|
||||
emit(ban.Id[0:8])
|
||||
},
|
||||
},
|
||||
},
|
||||
Views: map[string]leafdb.ViewDefinition[proto.Message]{
|
||||
"pubkey-archive": {
|
||||
@@ -92,7 +103,7 @@ func NewInternalDB(path string) (*InternalDB, error) {
|
||||
Emit: func(t leafdb.DataType, value proto.Message, emit func(idxkey []byte, t leafdb.DataType, value proto.Message)) {
|
||||
ee := value.(*CachedEvent)
|
||||
for _, r := range ee.Relays {
|
||||
emit([]byte(trimProtocolAndEndingSlash(r)), TypeEventInRelay, &EventInRelay{Id: ee.Id})
|
||||
emit([]byte(trimProtocolAndEndingSlash(r)), TypeEventInRelay, &ID{Id: ee.Id})
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -194,10 +205,46 @@ func (internal *InternalDB) getRelaysForEvent(eventId string) []string {
|
||||
func (internal *InternalDB) getEventsInRelay(hostname string) iter.Seq[string] {
|
||||
return func(yield func(string) bool) {
|
||||
for value := range internal.DB.View(leafdb.ExactQuery("events-in-relay", []byte(hostname))) {
|
||||
evtid := value.(*EventInRelay)
|
||||
evtid := value.(*ID)
|
||||
if !yield(evtid.Id) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (internal *InternalDB) banEvent(id, reason string) error {
|
||||
idb, err := hex.DecodeString(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = internal.DB.AddOrReplace("banned-event", TypeBannedEvent, &BannedEvent{
|
||||
Id: idb,
|
||||
Reason: reason,
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (internal *InternalDB) unbanEvent(id string) error {
|
||||
idb, err := hex.DecodeString(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = internal.DB.DeleteQuery(leafdb.ExactQuery("banned-event", idb[0:8]))
|
||||
return err
|
||||
}
|
||||
|
||||
func (internal *InternalDB) isBanned(id string) (bool, string) {
|
||||
idb, err := hex.DecodeString(id)
|
||||
if err != nil {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
for record := range internal.DB.Query(leafdb.ExactQuery("banned-event", idb[0:8])) {
|
||||
return true, record.(*BannedEvent).Reason
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
3
main.go
3
main.go
@@ -129,6 +129,9 @@ func main() {
|
||||
},
|
||||
)
|
||||
|
||||
// admin
|
||||
setupRelayManagement(relay)
|
||||
|
||||
// routes
|
||||
mux := relay.Router()
|
||||
mux.Handle("/njump/static/", http.StripPrefix("/njump/", http.FileServer(http.FS(static))))
|
||||
|
||||
45
management.go
Normal file
45
management.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
|
||||
"github.com/fiatjaf/khatru"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip86"
|
||||
)
|
||||
|
||||
func setupRelayManagement(relay *khatru.Relay) {
|
||||
relay.ManagementAPI.RejectAPICall = append(relay.ManagementAPI.RejectAPICall,
|
||||
func(ctx context.Context, mp nip86.MethodParams) (reject bool, msg string) {
|
||||
if slices.Contains(s.TrustedPubKeys, khatru.GetAuthed(ctx)) {
|
||||
return false, ""
|
||||
}
|
||||
return true, "you are not a trusted pubkey"
|
||||
},
|
||||
)
|
||||
relay.ManagementAPI.BanEvent = func(ctx context.Context, id, reason string) error {
|
||||
log.Info().Str("id", id).Str("reason", reason).Msg("banning event")
|
||||
ch, err := sys.Store.QueryEvents(ctx, nostr.Filter{IDs: []string{id}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for evt := range ch {
|
||||
sys.Store.DeleteEvent(ctx, evt)
|
||||
}
|
||||
|
||||
if err := internal.banEvent(id, reason); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
relay.ManagementAPI.AllowEvent = func(ctx context.Context, id, reason string) error {
|
||||
log.Info().Str("id", id).Str("reason", reason).Msg("unbanning event")
|
||||
if err := internal.unbanEvent(id); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,14 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if banned, reason := internal.isBanned(data.event.ID); banned {
|
||||
w.Header().Set("Cache-Control", "max-age=60")
|
||||
log.Warn().Err(err).Str("code", code).Str("reason", reason).Msg("event banned")
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
errorTemplate(ErrorPageParams{Errors: "event banned"}).Render(ctx, w)
|
||||
return
|
||||
}
|
||||
|
||||
// if we originally got a note code or an nevent with no hints
|
||||
// augment the URL to point to an nevent with hints -- redirect
|
||||
if p, ok := decoded.(nostr.EventPointer); (ok && p.Author == "" && len(p.Relays) == 0) || prefix == "note" {
|
||||
|
||||
Reference in New Issue
Block a user