forked from coracle/zooid
Fix some access logic
This commit is contained in:
+4
-4
@@ -57,7 +57,7 @@ func (bl *BlossomStore) Enable(instance *Instance) {
|
||||
return true, "file too large", 413
|
||||
}
|
||||
|
||||
if auth == nil || !instance.Management.IsPubkeyAllowed(auth.PubKey) {
|
||||
if auth == nil || !instance.Management.HasAccess(auth.PubKey) {
|
||||
return true, "unauthorized", 403
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func (bl *BlossomStore) Enable(instance *Instance) {
|
||||
}
|
||||
|
||||
backend.RejectGet = func(ctx context.Context, auth *nostr.Event, sha256 string, ext string) (bool, string, int) {
|
||||
if auth == nil || !instance.Management.IsPubkeyAllowed(auth.PubKey) {
|
||||
if auth == nil || !instance.Management.HasAccess(auth.PubKey) {
|
||||
return true, "unauthorized", 403
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func (bl *BlossomStore) Enable(instance *Instance) {
|
||||
}
|
||||
|
||||
backend.RejectList = func(ctx context.Context, auth *nostr.Event, pubkey nostr.PubKey) (bool, string, int) {
|
||||
if auth == nil || !instance.Management.IsPubkeyAllowed(auth.PubKey) {
|
||||
if auth == nil || !instance.Management.HasAccess(auth.PubKey) {
|
||||
return true, "unauthorized", 403
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func (bl *BlossomStore) Enable(instance *Instance) {
|
||||
}
|
||||
|
||||
backend.RejectDelete = func(ctx context.Context, auth *nostr.Event, sha256 string, ext string) (bool, string, int) {
|
||||
if auth == nil || !instance.Management.IsPubkeyAllowed(auth.PubKey) {
|
||||
if auth == nil || !instance.Management.HasAccess(auth.PubKey) {
|
||||
return true, "unauthorized", 403
|
||||
}
|
||||
|
||||
|
||||
+25
-20
@@ -95,13 +95,13 @@ func (config *Config) IsOwner(pubkey nostr.PubKey) bool {
|
||||
return pubkey.Hex() == config.Info.Pubkey
|
||||
}
|
||||
|
||||
func (config *Config) GetRolesForPubkey(pubkey nostr.PubKey) []Role {
|
||||
roles := make([]Role, 0)
|
||||
for name, role := range config.Roles {
|
||||
if name == "member" {
|
||||
roles = append(roles, role)
|
||||
}
|
||||
func (config *Config) IsAdmin(pubkey nostr.PubKey) bool {
|
||||
return config.IsOwner(pubkey) || config.IsSelf(pubkey)
|
||||
}
|
||||
|
||||
func (config *Config) GetAssignedRoles(pubkey nostr.PubKey) []Role {
|
||||
roles := make([]Role, 0)
|
||||
for _, role := range config.Roles {
|
||||
if slices.Contains(role.Pubkeys, pubkey.Hex()) {
|
||||
roles = append(roles, role)
|
||||
}
|
||||
@@ -110,18 +110,25 @@ func (config *Config) GetRolesForPubkey(pubkey nostr.PubKey) []Role {
|
||||
return roles
|
||||
}
|
||||
|
||||
func (config *Config) CanManage(pubkey nostr.PubKey) bool {
|
||||
for _, role := range config.GetRolesForPubkey(pubkey) {
|
||||
if role.CanManage {
|
||||
return true
|
||||
func (config *Config) GetAllRoles(pubkey nostr.PubKey) []Role {
|
||||
roles := make([]Role, 0)
|
||||
for name, role := range config.Roles {
|
||||
if name == "member" {
|
||||
roles = append(roles, role)
|
||||
} else if slices.Contains(role.Pubkeys, pubkey.Hex()) {
|
||||
roles = append(roles, role)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return roles
|
||||
}
|
||||
|
||||
func (config *Config) CanInvite(pubkey nostr.PubKey) bool {
|
||||
for _, role := range config.GetRolesForPubkey(pubkey) {
|
||||
if config.IsAdmin(pubkey) {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, role := range config.GetAllRoles(pubkey) {
|
||||
if role.CanInvite {
|
||||
return true
|
||||
}
|
||||
@@ -130,17 +137,15 @@ func (config *Config) CanInvite(pubkey nostr.PubKey) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (config *Config) IsAdmin(pubkey nostr.PubKey) bool {
|
||||
if config.IsOwner(pubkey) {
|
||||
func (config *Config) CanManage(pubkey nostr.PubKey) bool {
|
||||
if config.IsAdmin(pubkey) {
|
||||
return true
|
||||
}
|
||||
|
||||
if config.IsSelf(pubkey) {
|
||||
return true
|
||||
}
|
||||
|
||||
if config.CanManage(pubkey) {
|
||||
return true
|
||||
for _, role := range config.GetAllRoles(pubkey) {
|
||||
if role.CanManage {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
+66
-66
@@ -137,7 +137,7 @@ func (instance *Instance) Cleanup() {
|
||||
func (instance *Instance) StripSignature(ctx context.Context, event nostr.Event) nostr.Event {
|
||||
pubkey, _ := khatru.GetAuthed(ctx)
|
||||
|
||||
if instance.Config.Policy.StripSignatures && !instance.Config.IsAdmin(pubkey) {
|
||||
if instance.Config.Policy.StripSignatures && !instance.Config.CanManage(pubkey) {
|
||||
var zeroSig [64]byte
|
||||
event.Sig = zeroSig
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func (instance *Instance) AllowRecipientEvent(event nostr.Event) bool {
|
||||
if recipientTag != nil {
|
||||
pubkey, err := nostr.PubKeyFromHex(recipientTag[1])
|
||||
|
||||
if err == nil && instance.Management.IsPubkeyAllowed(pubkey) {
|
||||
if err == nil && instance.Management.HasAccess(pubkey) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -251,6 +251,68 @@ func (instance *Instance) DeleteEvent(ctx context.Context, id nostr.ID) error {
|
||||
return instance.Events.DeleteEvent(id)
|
||||
}
|
||||
|
||||
// Requests
|
||||
|
||||
func (instance *Instance) OnRequest(ctx context.Context, filter nostr.Filter) (reject bool, msg string) {
|
||||
pubkey, ok := khatru.GetAuthed(ctx)
|
||||
|
||||
if !ok {
|
||||
return true, "auth-required: authentication is required for access"
|
||||
}
|
||||
|
||||
if !instance.Management.HasAccess(pubkey) {
|
||||
return true, "restricted: you are not a member of this relay"
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func (instance *Instance) QueryStored(ctx context.Context, filter nostr.Filter) iter.Seq[nostr.Event] {
|
||||
return func(yield func(nostr.Event) bool) {
|
||||
if khatru.IsInternalCall(ctx) {
|
||||
for event := range instance.Events.QueryEvents(filter, 0) {
|
||||
if !yield(event) {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pubkey, _ := khatru.GetAuthed(ctx)
|
||||
|
||||
if slices.Contains(filter.Kinds, RELAY_INVITE) && instance.Config.CanInvite(pubkey) {
|
||||
if !yield(instance.StripSignature(ctx, instance.GenerateInviteEvent(pubkey))) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for event := range instance.Events.QueryEvents(filter, 1000) {
|
||||
if instance.IsWriteOnlyEvent(event) {
|
||||
continue
|
||||
}
|
||||
|
||||
h := GetGroupIDFromEvent(event)
|
||||
|
||||
if h != "" {
|
||||
if !instance.Config.Groups.Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
if !instance.Groups.HasAccess(h, pubkey) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !instance.Config.Groups.Enabled && slices.Contains(nip29.MetadataEventKinds, event.Kind) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !yield(instance.StripSignature(ctx, event)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Event publishing
|
||||
|
||||
func (instance *Instance) OnEvent(ctx context.Context, event nostr.Event) (reject bool, msg string) {
|
||||
@@ -270,7 +332,7 @@ func (instance *Instance) OnEvent(ctx context.Context, event nostr.Event) (rejec
|
||||
return instance.Management.ValidateJoinRequest(event)
|
||||
}
|
||||
|
||||
if !instance.Management.IsPubkeyAllowed(pubkey) {
|
||||
if !instance.Management.HasAccess(pubkey) {
|
||||
return true, "restricted: you are not a member of this relay"
|
||||
}
|
||||
|
||||
@@ -282,7 +344,7 @@ func (instance *Instance) OnEvent(ctx context.Context, event nostr.Event) (rejec
|
||||
return true, "invalid: group metadata cannot be set directly"
|
||||
}
|
||||
|
||||
if slices.Contains(nip29.ModerationEventKinds, event.Kind) && !instance.Config.IsAdmin(event.PubKey) {
|
||||
if slices.Contains(nip29.ModerationEventKinds, event.Kind) && !instance.Config.CanManage(event.PubKey) {
|
||||
return true, "restricted: you are not authorized to manage groups"
|
||||
}
|
||||
|
||||
@@ -369,65 +431,3 @@ func (instance *Instance) OnEventSaved(ctx context.Context, event nostr.Event) {
|
||||
instance.Groups.DeleteGroup(GetGroupIDFromEvent(event))
|
||||
}
|
||||
}
|
||||
|
||||
// Requests
|
||||
|
||||
func (instance *Instance) OnRequest(ctx context.Context, filter nostr.Filter) (reject bool, msg string) {
|
||||
pubkey, ok := khatru.GetAuthed(ctx)
|
||||
|
||||
if !ok {
|
||||
return true, "auth-required: authentication is required for access"
|
||||
}
|
||||
|
||||
if !instance.Management.IsPubkeyAllowed(pubkey) {
|
||||
return true, "restricted: you are not a member of this relay"
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func (instance *Instance) QueryStored(ctx context.Context, filter nostr.Filter) iter.Seq[nostr.Event] {
|
||||
return func(yield func(nostr.Event) bool) {
|
||||
if khatru.IsInternalCall(ctx) {
|
||||
for event := range instance.Events.QueryEvents(filter, 0) {
|
||||
if !yield(event) {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pubkey, _ := khatru.GetAuthed(ctx)
|
||||
|
||||
if slices.Contains(filter.Kinds, RELAY_INVITE) && instance.Config.CanInvite(pubkey) {
|
||||
if !yield(instance.StripSignature(ctx, instance.GenerateInviteEvent(pubkey))) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for event := range instance.Events.QueryEvents(filter, 1000) {
|
||||
if instance.IsWriteOnlyEvent(event) {
|
||||
continue
|
||||
}
|
||||
|
||||
h := GetGroupIDFromEvent(event)
|
||||
|
||||
if h != "" {
|
||||
if !instance.Config.Groups.Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
if !instance.Groups.HasAccess(h, pubkey) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !instance.Config.Groups.Enabled && slices.Contains(nip29.MetadataEventKinds, event.Kind) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !yield(instance.StripSignature(ctx, event)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-14
@@ -259,20 +259,8 @@ func (m *ManagementStore) GetAllowedPubkeyItems() []nip86.PubKeyReason {
|
||||
return reasons
|
||||
}
|
||||
|
||||
func (m *ManagementStore) IsPubkeyAllowed(pubkey nostr.PubKey) bool {
|
||||
if m.Config.IsOwner(pubkey) || m.Config.IsSelf(pubkey) {
|
||||
return true
|
||||
}
|
||||
|
||||
for range m.Config.GetRolesForPubkey(pubkey) {
|
||||
return true
|
||||
}
|
||||
|
||||
return m.IsMember(pubkey)
|
||||
}
|
||||
|
||||
func (m *ManagementStore) AllowPubkey(pubkey nostr.PubKey) error {
|
||||
if m.IsPubkeyAllowed(pubkey) {
|
||||
if m.HasAccess(pubkey) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -287,6 +275,18 @@ func (m *ManagementStore) AllowPubkey(pubkey nostr.PubKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ManagementStore) HasAccess(pubkey nostr.PubKey) bool {
|
||||
if m.Config.IsAdmin(pubkey) {
|
||||
return true
|
||||
}
|
||||
|
||||
for range m.Config.GetAssignedRoles(pubkey) {
|
||||
return true
|
||||
}
|
||||
|
||||
return m.IsMember(pubkey)
|
||||
}
|
||||
|
||||
// Joining
|
||||
|
||||
func (m *ManagementStore) ValidateJoinRequest(event nostr.Event) (reject bool, err string) {
|
||||
@@ -319,7 +319,15 @@ func (m *ManagementStore) Enable(instance *Instance) {
|
||||
instance.Relay.ManagementAPI.OnAPICall = func(ctx context.Context, mp nip86.MethodParams) (reject bool, msg string) {
|
||||
pubkey, ok := khatru.GetAuthed(ctx)
|
||||
|
||||
if ok && m.Config.CanManage(pubkey) {
|
||||
if !ok {
|
||||
return true, "blocked: please authenticate in order to manage this relay"
|
||||
}
|
||||
|
||||
if !m.HasAccess(pubkey) {
|
||||
return true, "blocked: you are not a member of this relay"
|
||||
}
|
||||
|
||||
if !m.Config.CanManage(pubkey) {
|
||||
return true, "blocked: only relay admins can manage this relay."
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user