Skip to content

Commit 317b2f1

Browse files
author
Jon Staab
committed
Refactor group access, implement hidden/private/closed
1 parent f035dad commit 317b2f1

File tree

4 files changed

+81
-76
lines changed

4 files changed

+81
-76
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ Configures NIP 29 support.
4444

4545
- `enabled` - whether NIP 29 is enabled.
4646
- `auto_join` - whether relay members can join `open` groups without approval. Defaults to `true`.
47-
- `auto_leave` - whether relay members can leave groups without approval. Defaults to `true`.
4847

4948
### `[management]`
5049

@@ -90,7 +89,6 @@ strip_signatures = false
9089
[groups]
9190
enabled = true
9291
auto_join = false
93-
auto_leave = true
9492

9593
[management]
9694
enabled = true

zooid/config.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ type Config struct {
3333
Groups struct {
3434
Enabled bool `toml:"enabled"`
3535
AutoJoin bool `toml:"auto_join"`
36-
AutoLeave bool `toml:"auto_leave"`
3736
} `toml:"groups"`
3837

3938
Management struct {

zooid/groups.go

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,25 +223,94 @@ func (g *GroupStore) UpdateMembersList(h string) error {
223223
// Other stuff
224224

225225
func (g *GroupStore) HasAccess(h string, pubkey nostr.PubKey) bool {
226+
return g.IsAdmin(h, pubkey) || g.IsMember(h, pubkey)
227+
}
228+
229+
func (g *GroupStore) IsGroupEvent(event nostr.Event) bool {
230+
if slices.Contains(nip29.MetadataEventKinds, event.Kind) {
231+
return true
232+
}
233+
234+
if slices.Contains(nip29.ModerationEventKinds, event.Kind) {
235+
return true
236+
}
237+
238+
joinKinds := []nostr.Kind{
239+
nostr.KindSimpleGroupJoinRequest,
240+
nostr.KindSimpleGroupLeaveRequest,
241+
}
242+
243+
if slices.Contains(joinKinds, event.Kind) {
244+
return true
245+
}
246+
247+
return GetGroupIDFromEvent(event) != ""
248+
}
249+
250+
func (g *GroupStore) CanRead(pubkey nostr.PubKey, event nostr.Event) bool {
251+
if !g.Config.Groups.Enabled {
252+
return false
253+
}
254+
255+
h := GetGroupIDFromEvent(event)
226256
meta, found := g.GetMetadata(h)
227257

228258
if !found {
229259
return false
230260
}
231261

232-
if !HasTag(meta.Tags, "closed") {
233-
return true
262+
if slices.Contains(nip29.MetadataEventKinds, event.Kind) {
263+
if HasTag(meta.Tags, "hidden") && !g.HasAccess(h, pubkey) {
264+
return false
265+
}
234266
}
235267

236-
if g.IsAdmin(h, pubkey) {
237-
return true
268+
if HasTag(meta.Tags, "private") && !g.HasAccess(h, pubkey) {
269+
return false
238270
}
239271

240-
if g.IsMember(h, pubkey) {
241-
return true
272+
return true
273+
}
274+
275+
func (g *GroupStore) CheckWrite(event nostr.Event) string {
276+
if !g.Config.Groups.Enabled {
277+
return "invalid: groups are not enabled"
242278
}
243279

244-
return false
280+
if slices.Contains(nip29.MetadataEventKinds, event.Kind) {
281+
return "invalid: group metadata cannot be set directly"
282+
}
283+
284+
h := GetGroupIDFromEvent(event)
285+
meta, found := g.GetMetadata(h)
286+
287+
if found && event.Kind == nostr.KindSimpleGroupCreateGroup {
288+
return "invalid: that group already exists"
289+
} else if !found {
290+
return "invalid: group not found"
291+
}
292+
293+
if event.Kind == nostr.KindSimpleGroupJoinRequest && g.IsMember(h, event.PubKey) {
294+
return "duplicate: already a member"
295+
}
296+
297+
if event.Kind == nostr.KindSimpleGroupLeaveRequest && !g.IsMember(h, event.PubKey) {
298+
return "duplicate: not currently a member"
299+
}
300+
301+
if slices.Contains(nip29.ModerationEventKinds, event.Kind) && !g.Config.CanManage(event.PubKey) {
302+
return "restricted: you are not authorized to manage groups"
303+
}
304+
305+
if HasTag(meta.Tags, "hidden") && !g.HasAccess(h, event.PubKey) {
306+
return "invalid: group not found"
307+
}
308+
309+
if HasTag(meta.Tags, "closed") && !g.HasAccess(h, event.PubKey) {
310+
return "restricted: you are not a member of that group"
311+
}
312+
313+
return ""
245314
}
246315

247316
// Middleware

zooid/instance.go

Lines changed: 5 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
"fiatjaf.com/nostr"
1212
"fiatjaf.com/nostr/khatru"
13-
"fiatjaf.com/nostr/nip29"
1413
"github.com/gosimple/slug"
1514
)
1615

@@ -317,19 +316,7 @@ func (instance *Instance) QueryStored(ctx context.Context, filter nostr.Filter)
317316
continue
318317
}
319318

320-
h := GetGroupIDFromEvent(event)
321-
322-
if h != "" {
323-
if !instance.Config.Groups.Enabled {
324-
continue
325-
}
326-
327-
if !instance.Groups.HasAccess(h, pubkey) {
328-
continue
329-
}
330-
}
331-
332-
if !instance.Config.Groups.Enabled && slices.Contains(nip29.MetadataEventKinds, event.Kind) {
319+
if instance.Groups.IsGroupEvent(event) && !instance.Groups.CanRead(pubkey, event) {
333320
continue
334321
}
335322

@@ -372,57 +359,9 @@ func (instance *Instance) OnEvent(ctx context.Context, event nostr.Event) (rejec
372359
return true, "invalid: this event's kind is not accepted"
373360
}
374361

375-
if slices.Contains(nip29.MetadataEventKinds, event.Kind) {
376-
return true, "invalid: group metadata cannot be set directly"
377-
}
378-
379-
if slices.Contains(nip29.ModerationEventKinds, event.Kind) && !instance.Config.CanManage(event.PubKey) {
380-
return true, "restricted: you are not authorized to manage groups"
381-
}
382-
383-
allGroupKinds := append(
384-
nip29.ModerationEventKinds,
385-
nostr.KindSimpleGroupJoinRequest,
386-
nostr.KindSimpleGroupLeaveRequest,
387-
)
388-
389-
h := GetGroupIDFromEvent(event)
390-
391-
if slices.Contains(allGroupKinds, event.Kind) {
392-
if !instance.Config.Groups.Enabled {
393-
return true, "invalid: group events not accepted on this relay"
394-
}
395-
396-
if h == "" {
397-
return true, "invalid: h tag is required"
398-
}
399-
400-
_, found := instance.Groups.GetMetadata(h)
401-
402-
if event.Kind == nostr.KindSimpleGroupCreateGroup {
403-
if found {
404-
return true, "invalid: that group already exists"
405-
}
406-
} else if !found {
407-
return true, "invalid: no such group exists"
408-
}
409-
410-
if event.Kind == nostr.KindSimpleGroupJoinRequest && instance.Groups.IsMember(h, event.PubKey) {
411-
return true, "duplicate: already a member"
412-
}
413-
414-
if event.Kind == nostr.KindSimpleGroupLeaveRequest && !instance.Groups.IsMember(h, event.PubKey) {
415-
return true, "duplicate: not currently a member"
416-
}
417-
} else if h != "" {
418-
_, found := instance.Groups.GetMetadata(h)
419-
420-
if !found {
421-
return true, "invalid: no such group exists"
422-
}
423-
424-
if !instance.Groups.HasAccess(h, pubkey) {
425-
return true, "restricted: you are not a member of that group"
362+
if instance.Groups.IsGroupEvent(event) {
363+
if err := instance.Groups.CheckWrite(event); err != "" {
364+
return true, err
426365
}
427366
}
428367

@@ -455,7 +394,7 @@ func (instance *Instance) OnEventSaved(ctx context.Context, event nostr.Event) {
455394
}
456395
}
457396

458-
if event.Kind == nostr.KindSimpleGroupLeaveRequest && instance.Config.Groups.AutoLeave {
397+
if event.Kind == nostr.KindSimpleGroupLeaveRequest {
459398
instance.Groups.RemoveMember(h, event.PubKey)
460399
instance.Groups.UpdateMembersList(h)
461400
}

0 commit comments

Comments
 (0)