|
|
|
@ -12,6 +12,7 @@ import ( |
|
|
|
"next.orly.dev/pkg/encoders/envelopes/authenvelope" |
|
|
|
"next.orly.dev/pkg/encoders/envelopes/authenvelope" |
|
|
|
"next.orly.dev/pkg/encoders/envelopes/eventenvelope" |
|
|
|
"next.orly.dev/pkg/encoders/envelopes/eventenvelope" |
|
|
|
"next.orly.dev/pkg/encoders/envelopes/okenvelope" |
|
|
|
"next.orly.dev/pkg/encoders/envelopes/okenvelope" |
|
|
|
|
|
|
|
"next.orly.dev/pkg/encoders/hex" |
|
|
|
"next.orly.dev/pkg/encoders/kind" |
|
|
|
"next.orly.dev/pkg/encoders/kind" |
|
|
|
"next.orly.dev/pkg/encoders/reason" |
|
|
|
"next.orly.dev/pkg/encoders/reason" |
|
|
|
"next.orly.dev/pkg/utils" |
|
|
|
"next.orly.dev/pkg/utils" |
|
|
|
@ -21,14 +22,19 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { |
|
|
|
log.D.F("handling event: %s", msg) |
|
|
|
log.D.F("handling event: %s", msg) |
|
|
|
// decode the envelope
|
|
|
|
// decode the envelope
|
|
|
|
env := eventenvelope.NewSubmission() |
|
|
|
env := eventenvelope.NewSubmission() |
|
|
|
|
|
|
|
log.I.F("HandleEvent: received event message length: %d", len(msg)) |
|
|
|
if msg, err = env.Unmarshal(msg); chk.E(err) { |
|
|
|
if msg, err = env.Unmarshal(msg); chk.E(err) { |
|
|
|
|
|
|
|
log.E.F("HandleEvent: failed to unmarshal event: %v", err) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
log.I.F("HandleEvent: successfully unmarshaled event, kind: %d, pubkey: %s", env.E.Kind, hex.Enc(env.E.Pubkey)) |
|
|
|
defer func() { |
|
|
|
defer func() { |
|
|
|
if env != nil && env.E != nil { |
|
|
|
if env != nil && env.E != nil { |
|
|
|
env.E.Free() |
|
|
|
env.E.Free() |
|
|
|
} |
|
|
|
} |
|
|
|
}() |
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log.I.F("HandleEvent: continuing with event processing...") |
|
|
|
if len(msg) > 0 { |
|
|
|
if len(msg) > 0 { |
|
|
|
log.I.F("extra '%s'", msg) |
|
|
|
log.I.F("extra '%s'", msg) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -128,44 +134,83 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
// check permissions of user
|
|
|
|
// check permissions of user
|
|
|
|
accessLevel := acl.Registry.GetAccessLevel(l.authedPubkey.Load(), l.remote) |
|
|
|
log.I.F("HandleEvent: checking ACL permissions for pubkey: %s", hex.Enc(l.authedPubkey.Load())) |
|
|
|
switch accessLevel { |
|
|
|
|
|
|
|
case "none": |
|
|
|
// If ACL mode is "none" and no pubkey is set, use the event's pubkey
|
|
|
|
log.D.F( |
|
|
|
var pubkeyForACL []byte |
|
|
|
"handle event: sending 'OK,false,auth-required...' to %s", l.remote, |
|
|
|
if len(l.authedPubkey.Load()) == 0 && acl.Registry.Active.Load() == "none" { |
|
|
|
) |
|
|
|
pubkeyForACL = env.E.Pubkey |
|
|
|
if err = okenvelope.NewFrom( |
|
|
|
log.I.F("HandleEvent: ACL mode is 'none', using event pubkey for ACL check: %s", hex.Enc(pubkeyForACL)) |
|
|
|
env.Id(), false, |
|
|
|
} else { |
|
|
|
reason.AuthRequired.F("auth required for write access"), |
|
|
|
pubkeyForACL = l.authedPubkey.Load() |
|
|
|
).Write(l); chk.E(err) { |
|
|
|
} |
|
|
|
// return
|
|
|
|
|
|
|
|
|
|
|
|
accessLevel := acl.Registry.GetAccessLevel(pubkeyForACL, l.remote) |
|
|
|
|
|
|
|
log.I.F("HandleEvent: ACL access level: %s", accessLevel) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Skip ACL check for admin/owner delete events
|
|
|
|
|
|
|
|
skipACLCheck := false |
|
|
|
|
|
|
|
if env.E.Kind == kind.EventDeletion.K { |
|
|
|
|
|
|
|
// Check if the delete event signer is admin or owner
|
|
|
|
|
|
|
|
for _, admin := range l.Admins { |
|
|
|
|
|
|
|
if utils.FastEqual(admin, env.E.Pubkey) { |
|
|
|
|
|
|
|
skipACLCheck = true |
|
|
|
|
|
|
|
log.I.F("HandleEvent: admin delete event - skipping ACL check") |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
log.D.F("handle event: sending challenge to %s", l.remote) |
|
|
|
if !skipACLCheck { |
|
|
|
if err = authenvelope.NewChallengeWith(l.challenge.Load()). |
|
|
|
for _, owner := range l.Owners { |
|
|
|
Write(l); chk.E(err) { |
|
|
|
if utils.FastEqual(owner, env.E.Pubkey) { |
|
|
|
return |
|
|
|
skipACLCheck = true |
|
|
|
|
|
|
|
log.I.F("HandleEvent: owner delete event - skipping ACL check") |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
case "read": |
|
|
|
|
|
|
|
log.D.F( |
|
|
|
if !skipACLCheck { |
|
|
|
"handle event: sending 'OK,false,auth-required:...' to %s", |
|
|
|
switch accessLevel { |
|
|
|
l.remote, |
|
|
|
case "none": |
|
|
|
) |
|
|
|
log.D.F( |
|
|
|
if err = okenvelope.NewFrom( |
|
|
|
"handle event: sending 'OK,false,auth-required...' to %s", l.remote, |
|
|
|
env.Id(), false, |
|
|
|
) |
|
|
|
reason.AuthRequired.F("auth required for write access"), |
|
|
|
if err = okenvelope.NewFrom( |
|
|
|
).Write(l); chk.E(err) { |
|
|
|
env.Id(), false, |
|
|
|
|
|
|
|
reason.AuthRequired.F("auth required for write access"), |
|
|
|
|
|
|
|
).Write(l); chk.E(err) { |
|
|
|
|
|
|
|
// return
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
log.D.F("handle event: sending challenge to %s", l.remote) |
|
|
|
|
|
|
|
if err = authenvelope.NewChallengeWith(l.challenge.Load()). |
|
|
|
|
|
|
|
Write(l); chk.E(err) { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
case "read": |
|
|
|
log.D.F("handle event: sending challenge to %s", l.remote) |
|
|
|
log.D.F( |
|
|
|
if err = authenvelope.NewChallengeWith(l.challenge.Load()). |
|
|
|
"handle event: sending 'OK,false,auth-required:...' to %s", |
|
|
|
Write(l); chk.E(err) { |
|
|
|
l.remote, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
if err = okenvelope.NewFrom( |
|
|
|
|
|
|
|
env.Id(), false, |
|
|
|
|
|
|
|
reason.AuthRequired.F("auth required for write access"), |
|
|
|
|
|
|
|
).Write(l); chk.E(err) { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
log.D.F("handle event: sending challenge to %s", l.remote) |
|
|
|
|
|
|
|
if err = authenvelope.NewChallengeWith(l.challenge.Load()). |
|
|
|
|
|
|
|
Write(l); chk.E(err) { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
return |
|
|
|
return |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
// user has write access or better, continue
|
|
|
|
|
|
|
|
log.I.F("HandleEvent: user has %s access, continuing", accessLevel) |
|
|
|
} |
|
|
|
} |
|
|
|
return |
|
|
|
} else { |
|
|
|
default: |
|
|
|
log.I.F("HandleEvent: skipping ACL check for admin/owner delete event") |
|
|
|
// user has write access or better, continue
|
|
|
|
|
|
|
|
// log.D.F("user has %s access", accessLevel)
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// check if event is ephemeral - if so, deliver and return early
|
|
|
|
// check if event is ephemeral - if so, deliver and return early
|
|
|
|
@ -197,6 +242,7 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// if the event is a delete, process the delete
|
|
|
|
// if the event is a delete, process the delete
|
|
|
|
|
|
|
|
log.I.F("HandleEvent: checking if event is delete - kind: %d, EventDeletion.K: %d", env.E.Kind, kind.EventDeletion.K) |
|
|
|
if env.E.Kind == kind.EventDeletion.K { |
|
|
|
if env.E.Kind == kind.EventDeletion.K { |
|
|
|
log.I.F("processing delete event %0x", env.E.ID) |
|
|
|
log.I.F("processing delete event %0x", env.E.ID) |
|
|
|
|
|
|
|
|
|
|
|
@ -204,6 +250,7 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { |
|
|
|
saveCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) |
|
|
|
saveCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) |
|
|
|
defer cancel() |
|
|
|
defer cancel() |
|
|
|
log.I.F("attempting to save delete event %0x from pubkey %0x", env.E.ID, env.E.Pubkey) |
|
|
|
log.I.F("attempting to save delete event %0x from pubkey %0x", env.E.ID, env.E.Pubkey) |
|
|
|
|
|
|
|
log.I.F("delete event pubkey hex: %s", hex.Enc(env.E.Pubkey)) |
|
|
|
if _, _, err = l.SaveEvent(saveCtx, env.E); err != nil { |
|
|
|
if _, _, err = l.SaveEvent(saveCtx, env.E); err != nil { |
|
|
|
log.E.F("failed to save delete event %0x: %v", env.E.ID, err) |
|
|
|
log.E.F("failed to save delete event %0x: %v", env.E.ID, err) |
|
|
|
if strings.HasPrefix(err.Error(), "blocked:") { |
|
|
|
if strings.HasPrefix(err.Error(), "blocked:") { |
|
|
|
|