Skip to content

Commit e073b28

Browse files
committed
publish and delete role definition events, block internal events from external publication everywhere.
1 parent 26b9a8b commit e073b28

9 files changed

Lines changed: 167 additions & 59 deletions

File tree

core.go

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ func basicRejectionLogic(ctx context.Context, event nostr.Event) (reject bool, m
4242
}
4343
}
4444

45+
if reject, msg := global.RejectInternalKinds(ctx, event); reject {
46+
return true, msg
47+
}
48+
4549
if validator != nil {
4650
if err := validator.ValidateEvent(event); err != nil {
4751
return true, "schema validation failed: " + err.Error()
@@ -119,7 +123,7 @@ func basicRejectionLogic(ctx context.Context, event nostr.Event) (reject bool, m
119123
return true, "invalid report"
120124
case 28934:
121125
if pyramid.IsMember(event.PubKey) {
122-
return false, "you are already a member of this relay, but fine"
126+
return false, "duplicate: you are already a member of this relay"
123127
}
124128

125129
claim := event.Tags.Find("claim")
@@ -326,65 +330,68 @@ func processLeaveRequest(ctx context.Context, event nostr.Event) {
326330
}
327331

328332
func publishMembershipChange(pubkey nostr.PubKey, added bool) {
329-
// publish to main and internal
330-
for _, c := range []struct {
331-
store *mmm.IndexingLayer
332-
relay *khatru.Relay
333-
}{{global.IL.Main, relay}, {global.IL.Internal, internal.Relay}} {
334-
if added {
335-
// publish kind 8000
336-
evt := nostr.Event{
337-
Kind: 8000,
338-
CreatedAt: nostr.Now(),
339-
Tags: nostr.Tags{
340-
{"-"},
341-
{"p", pubkey.Hex()},
342-
},
343-
}
344-
evt.Sign(global.Settings.RelayInternalSecretKey)
345-
c.store.SaveEvent(evt)
346-
c.relay.BroadcastEvent(evt)
347-
} else {
348-
// publish kind 8001
349-
evt := nostr.Event{
350-
Kind: 8001,
351-
CreatedAt: nostr.Now(),
352-
Tags: nostr.Tags{
353-
{"-"},
354-
{"p", pubkey.Hex()},
355-
},
356-
}
357-
evt.Sign(global.Settings.RelayInternalSecretKey)
333+
// publish the add/remove event and the updated member list
334+
if added {
335+
evt := nostr.Event{
336+
Kind: 8000,
337+
CreatedAt: nostr.Now(),
338+
Tags: nostr.Tags{
339+
{"-"},
340+
{"p", pubkey.Hex()},
341+
},
342+
}
343+
evt.Sign(global.Settings.RelayInternalSecretKey)
344+
for _, c := range []struct {
345+
store *mmm.IndexingLayer
346+
relay *khatru.Relay
347+
}{{global.IL.Main, relay}, {global.IL.Internal, internal.Relay}} {
358348
c.store.SaveEvent(evt)
359349
c.relay.BroadcastEvent(evt)
360350
}
361-
362-
// publish updated relay member list and nip29 room creation permission list
363-
relayMembersList := nostr.Event{
364-
Kind: 13534,
365-
CreatedAt: nostr.Now(),
366-
Tags: nostr.Tags{{"-"}},
367-
}
368-
roomCreationPermissionList := nostr.Event{
369-
Kind: 19004,
351+
} else {
352+
evt := nostr.Event{
353+
Kind: 8001,
370354
CreatedAt: nostr.Now(),
371-
Tags: nostr.Tags{{"-"}},
355+
Tags: nostr.Tags{
356+
{"-"},
357+
{"p", pubkey.Hex()},
358+
},
372359
}
373-
for m, member := range pyramid.Members.Range {
374-
memberTag := nostr.Tag{"member", m.Hex()}
375-
for _, rid := range member.Roles {
376-
memberTag = append(memberTag, rid)
377-
}
378-
relayMembersList.Tags = append(relayMembersList.Tags, memberTag)
379-
roomCreationPermissionList.Tags = append(roomCreationPermissionList.Tags, nostr.Tag{"p", m.Hex()})
380-
}
381-
relayMembersList.Sign(global.Settings.RelayInternalSecretKey)
382-
roomCreationPermissionList.Sign(global.Settings.RelayInternalSecretKey)
383-
c.store.ReplaceEvent(relayMembersList)
384-
c.store.ReplaceEvent(roomCreationPermissionList)
385-
c.relay.BroadcastEvent(relayMembersList)
386-
c.relay.BroadcastEvent(roomCreationPermissionList)
360+
evt.Sign(global.Settings.RelayInternalSecretKey)
361+
global.IL.Main.SaveEvent(evt)
362+
relay.BroadcastEvent(evt)
387363
}
364+
publishMemberListAndPermissions()
365+
}
366+
367+
// publishMemberListAndPermissions publishes the current NIP-43 kind 13534
368+
// relay member list and the NIP-29 kind 19004 room-creation permission list,
369+
// both signed by the relay's internal secret key.
370+
func publishMemberListAndPermissions() {
371+
relayMembersList := nostr.Event{
372+
Kind: 13534,
373+
CreatedAt: nostr.Now(),
374+
Tags: nostr.Tags{{"-"}},
375+
}
376+
roomCreationPermissionList := nostr.Event{
377+
Kind: 19004,
378+
CreatedAt: nostr.Now(),
379+
Tags: nostr.Tags{{"-"}},
380+
}
381+
for m, member := range pyramid.Members.Range {
382+
memberTag := nostr.Tag{"member", m.Hex()}
383+
for _, rid := range member.Roles {
384+
memberTag = append(memberTag, rid)
385+
}
386+
relayMembersList.Tags = append(relayMembersList.Tags, memberTag)
387+
roomCreationPermissionList.Tags = append(roomCreationPermissionList.Tags, nostr.Tag{"p", m.Hex()})
388+
}
389+
relayMembersList.Sign(global.Settings.RelayInternalSecretKey)
390+
roomCreationPermissionList.Sign(global.Settings.RelayInternalSecretKey)
391+
global.IL.Main.ReplaceEvent(relayMembersList)
392+
global.IL.Main.ReplaceEvent(roomCreationPermissionList)
393+
relay.BroadcastEvent(relayMembersList)
394+
relay.BroadcastEvent(roomCreationPermissionList)
388395
}
389396

390397
func fetchInvite(claim string) (nostr.Event, error) {

favorites/relay.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ func setupEnabled() {
8383
)
8484

8585
Relay.OnEvent = policies.SeqEvent(
86+
global.RejectInternalKinds,
8687
policies.PreventLargeContent(global.Settings.Limits.MaxEventSize),
8788
policies.PreventTooManyIndexableTags(global.Settings.Limits.MaxIndexableTags, []nostr.Kind{3}, nil),
8889
policies.PreventTooManyIndexableTags(global.Settings.Limits.MaxEntriesInFollowList, nil, []nostr.Kind{3}),

global/utils.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package global
22

33
import (
4+
"context"
45
"crypto/rand"
56
"encoding/base64"
67
"encoding/json"
@@ -233,6 +234,14 @@ func ParseDomainsTextarea(value string) []string {
233234
return out
234235
}
235236

237+
func RejectInternalKinds(_ context.Context, event nostr.Event) (bool, string) {
238+
switch event.Kind {
239+
case 8000, 8001, 13534, 19004, 33534:
240+
return true, "blocked: kind reserved for relay internal use"
241+
}
242+
return false, ""
243+
}
244+
236245
func RandomString(size int) string {
237246
buf := make([]byte, size)
238247
if _, err := io.ReadFull(rand.Reader, buf); err != nil {

inbox/relay.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ func setupEnabled() {
149149
rejectFilter,
150150
)
151151
Relay.OnEvent = policies.SeqEvent(
152+
global.RejectInternalKinds,
152153
policies.PreventLargeContent(global.Settings.Limits.MaxEventSize),
153154
policies.PreventTooManyIndexableTags(global.Settings.Limits.MaxIndexableTags, []nostr.Kind{3}, nil),
154155
policies.PreventTooManyIndexableTags(global.Settings.Limits.MaxEntriesInFollowList, nil, []nostr.Kind{3}),

internal/relay.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ func setupEnabled() {
9898
)
9999

100100
Relay.OnEvent = policies.SeqEvent(
101+
global.RejectInternalKinds,
101102
policies.PreventLargeContent(global.Settings.Limits.MaxEventSize),
102103
policies.PreventTooManyIndexableTags(global.Settings.Limits.MaxIndexableTags, []nostr.Kind{3}, nil),
103104
policies.PreventTooManyIndexableTags(global.Settings.Limits.MaxEntriesInFollowList, nil, []nostr.Kind{3}),

management.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,11 @@ func createRoleHandler(ctx context.Context, id, label, description string, color
224224
if color < 0 || color > 360 {
225225
return fmt.Errorf("color must be between 0 and 360")
226226
}
227-
return pyramid.AddRoleAction(pyramid.ActionCreateRole, caller, id, label, description, strconv.Itoa(color), order)
227+
if err := pyramid.AddRoleAction(pyramid.ActionCreateRole, caller, id, label, description, strconv.Itoa(color), order); err != nil {
228+
return err
229+
}
230+
go publishRoleDefinition(id)
231+
return nil
228232
}
229233

230234
func editRoleHandler(ctx context.Context, id, label, description string, color, order int) error {
@@ -238,7 +242,11 @@ func editRoleHandler(ctx context.Context, id, label, description string, color,
238242
if color < 0 || color > 360 {
239243
return fmt.Errorf("color must be between 0 and 360")
240244
}
241-
return pyramid.AddRoleAction(pyramid.ActionEditRole, caller, id, label, description, strconv.Itoa(color), order)
245+
if err := pyramid.AddRoleAction(pyramid.ActionEditRole, caller, id, label, description, strconv.Itoa(color), order); err != nil {
246+
return err
247+
}
248+
go publishRoleDefinition(id)
249+
return nil
242250
}
243251

244252
func deleteRoleHandler(ctx context.Context, id string) error {
@@ -249,7 +257,11 @@ func deleteRoleHandler(ctx context.Context, id string) error {
249257
if _, exists := pyramid.Roles.Load(id); !exists {
250258
return fmt.Errorf("role '%s' does not exist", id)
251259
}
252-
return pyramid.AddRoleAction(pyramid.ActionDeleteRole, caller, id, "", "", "", 0)
260+
if err := pyramid.AddRoleAction(pyramid.ActionDeleteRole, caller, id, "", "", "", 0); err != nil {
261+
return err
262+
}
263+
go publishRoleDefinitionDeletion(id)
264+
return nil
253265
}
254266

255267
func assignRoleHandler(ctx context.Context, pubkey nostr.PubKey, roleID string) error {
@@ -266,7 +278,11 @@ func assignRoleHandler(ctx context.Context, pubkey nostr.PubKey, roleID string)
266278
if pyramid.MemberHasRole(pubkey, roleID) {
267279
return fmt.Errorf("member already has role '%s'", roleID)
268280
}
269-
return pyramid.AddRoleAssignmentAction(pyramid.ActionAssignRole, caller, pubkey, roleID)
281+
if err := pyramid.AddRoleAssignmentAction(pyramid.ActionAssignRole, caller, pubkey, roleID); err != nil {
282+
return err
283+
}
284+
go publishMemberListAndPermissions()
285+
return nil
270286
}
271287

272288
func unassignRoleHandler(ctx context.Context, pubkey nostr.PubKey, roleID string) error {
@@ -283,7 +299,11 @@ func unassignRoleHandler(ctx context.Context, pubkey nostr.PubKey, roleID string
283299
if !pyramid.MemberHasRole(pubkey, roleID) {
284300
return fmt.Errorf("member does not have role '%s'", roleID)
285301
}
286-
return pyramid.AddRoleAssignmentAction(pyramid.ActionUnassignRole, caller, pubkey, roleID)
302+
if err := pyramid.AddRoleAssignmentAction(pyramid.ActionUnassignRole, caller, pubkey, roleID); err != nil {
303+
return err
304+
}
305+
go publishMemberListAndPermissions()
306+
return nil
287307
}
288308

289309
func listAllowedKindsHandler(ctx context.Context) ([]nostr.Kind, error) {

moderated/relay.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ func setupEnabled() {
9393
)
9494

9595
Relay.OnEvent = func(ctx context.Context, evt nostr.Event) (bool, string) {
96+
if reject, msg := global.RejectInternalKinds(ctx, evt); reject {
97+
return true, msg
98+
}
99+
96100
if !global.KindIsAllowed(evt.Kind) {
97101
return true, "blocked: kind unallowed"
98102
}

personal/relay.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ func setupEnabled() {
106106
)
107107

108108
Relay.OnEvent = policies.SeqEvent(
109+
global.RejectInternalKinds,
109110
policies.PreventLargeContent(global.Settings.Limits.MaxEventSize),
110111
policies.PreventTooManyIndexableTags(global.Settings.Limits.MaxIndexableTags, []nostr.Kind{3}, nil),
111112
policies.PreventTooManyIndexableTags(global.Settings.Limits.MaxEntriesInFollowList, nil, []nostr.Kind{3}),

roles.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package main
2+
3+
import (
4+
"strconv"
5+
6+
"fiatjaf.com/nostr"
7+
"github.com/fiatjaf/pyramid/global"
8+
"github.com/fiatjaf/pyramid/pyramid"
9+
)
10+
11+
func publishRoleDefinition(roleID string) {
12+
role, ok := pyramid.Roles.Load(roleID)
13+
if !ok {
14+
return
15+
}
16+
17+
evt := nostr.Event{
18+
Kind: 33534,
19+
PubKey: global.Settings.RelayInternalSecretKey.Public(),
20+
CreatedAt: nostr.Now(),
21+
Tags: nostr.Tags{
22+
{"-"},
23+
{"d", role.ID},
24+
{"label", role.Label},
25+
{"description", role.Description},
26+
{"color", role.Color},
27+
{"order", strconv.Itoa(role.Order)},
28+
},
29+
}
30+
31+
evt.Sign(global.Settings.RelayInternalSecretKey)
32+
if _, err := global.IL.Main.ReplaceEvent(evt); err != nil {
33+
log.Warn().Err(err).Str("role", roleID).Msg("failed to store role definition")
34+
}
35+
relay.BroadcastEvent(evt)
36+
}
37+
38+
func publishRoleDefinitionDeletion(roleID string) {
39+
self := global.Settings.RelayInternalSecretKey.Public()
40+
41+
del := nostr.Event{
42+
Kind: 5,
43+
PubKey: self,
44+
CreatedAt: nostr.Now(),
45+
Tags: nostr.Tags{
46+
{"a", "33534:" + self.Hex() + ":" + roleID},
47+
},
48+
}
49+
50+
for evt := range global.IL.Main.QueryEvents(nostr.Filter{
51+
Kinds: []nostr.Kind{33534},
52+
Authors: []nostr.PubKey{self},
53+
Tags: nostr.TagMap{"d": []string{roleID}},
54+
}, 10) {
55+
del.Tags = append(del.Tags, nostr.Tag{"e", evt.ID.Hex()})
56+
57+
if err := global.IL.Main.DeleteEvent(evt.ID); err != nil {
58+
log.Warn().Err(err).Str("role", roleID).Msg("failed to delete role definition")
59+
}
60+
}
61+
62+
del.Sign(global.Settings.RelayInternalSecretKey)
63+
relay.BroadcastEvent(del)
64+
}

0 commit comments

Comments
 (0)