diff options
| author | bndw <ben@bdw.to> | 2026-02-13 20:38:59 -0800 |
|---|---|---|
| committer | bndw <ben@bdw.to> | 2026-02-13 20:38:59 -0800 |
| commit | dfa19ff0776be0850ad7b86ca579601431349593 (patch) | |
| tree | b56a3af23dda020bd6fd6709a7d1fc3c2d9f625f /internal/handler/grpc | |
| parent | 89b8948195f24df127b7ae656ab3f60bd1b49ac7 (diff) | |
feat: implement NIP-09 with hard delete
Implement event deletion (NIP-09) using hard delete approach:
- Kind 5 events trigger deletion but are not stored themselves
- ProcessDeletion hard deletes referenced events (DELETE FROM events)
- Only authors can delete their own events (pubkey verification)
- Support multiple event IDs in single deletion request
- No deletions table needed (simpler schema)
- Added 4 deletion tests covering various scenarios
- All 45 tests passing
Diffstat (limited to 'internal/handler/grpc')
| -rw-r--r-- | internal/handler/grpc/server.go | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/internal/handler/grpc/server.go b/internal/handler/grpc/server.go index b65b527..4d6e700 100644 --- a/internal/handler/grpc/server.go +++ b/internal/handler/grpc/server.go | |||
| @@ -13,6 +13,7 @@ import ( | |||
| 13 | type EventStore interface { | 13 | type EventStore interface { |
| 14 | StoreEvent(context.Context, *storage.EventData) error | 14 | StoreEvent(context.Context, *storage.EventData) error |
| 15 | QueryEvents(context.Context, []*pb.Filter, *storage.QueryOptions) ([]*pb.Event, error) | 15 | QueryEvents(context.Context, []*pb.Filter, *storage.QueryOptions) ([]*pb.Event, error) |
| 16 | ProcessDeletion(context.Context, *pb.Event) error | ||
| 16 | } | 17 | } |
| 17 | 18 | ||
| 18 | type Server struct { | 19 | type Server struct { |
| @@ -58,6 +59,22 @@ func (s *Server) PublishEvent(ctx context.Context, req *pb.PublishEventRequest) | |||
| 58 | 59 | ||
| 59 | canonicalJSON := nostrEvent.Serialize() | 60 | canonicalJSON := nostrEvent.Serialize() |
| 60 | 61 | ||
| 62 | // Handle deletion events (kind 5) - process but don't store | ||
| 63 | if req.Event.Kind == 5 { | ||
| 64 | if err := s.store.ProcessDeletion(ctx, req.Event); err != nil { | ||
| 65 | return &pb.PublishEventResponse{ | ||
| 66 | Accepted: false, | ||
| 67 | Message: fmt.Sprintf("deletion failed: %v", err), | ||
| 68 | CanonicalJson: canonicalJSON, | ||
| 69 | }, nil | ||
| 70 | } | ||
| 71 | return &pb.PublishEventResponse{ | ||
| 72 | Accepted: true, | ||
| 73 | Message: "deleted", | ||
| 74 | CanonicalJson: canonicalJSON, | ||
| 75 | }, nil | ||
| 76 | } | ||
| 77 | |||
| 61 | eventData := &storage.EventData{ | 78 | eventData := &storage.EventData{ |
| 62 | Event: req.Event, | 79 | Event: req.Event, |
| 63 | CanonicalJSON: canonicalJSON, | 80 | CanonicalJSON: canonicalJSON, |
