@ -9,6 +9,7 @@ import (
"github.com/coder/websocket"
"github.com/coder/websocket"
"lol.mleku.dev/chk"
"lol.mleku.dev/chk"
"lol.mleku.dev/log"
"lol.mleku.dev/log"
"next.orly.dev/pkg/acl"
"next.orly.dev/pkg/encoders/envelopes/eventenvelope"
"next.orly.dev/pkg/encoders/envelopes/eventenvelope"
"next.orly.dev/pkg/encoders/event"
"next.orly.dev/pkg/encoders/event"
"next.orly.dev/pkg/encoders/filter"
"next.orly.dev/pkg/encoders/filter"
@ -220,6 +221,34 @@ func (p *P) Deliver(ev *event.E) {
}
}
}
}
// Check for private tags - only deliver to authorized users
if ev . Tags != nil && ev . Tags . Len ( ) > 0 {
hasPrivateTag := false
var privatePubkey [ ] byte
for _ , t := range * ev . Tags {
if t . Len ( ) >= 2 {
keyBytes := t . Key ( )
if len ( keyBytes ) == 7 && string ( keyBytes ) == "private" {
hasPrivateTag = true
privatePubkey = t . Value ( )
break
}
}
}
if hasPrivateTag {
canSeePrivate := p . canSeePrivateEvent ( d . sub . AuthedPubkey , privatePubkey , d . sub . remote )
if ! canSeePrivate {
log . D . F ( "subscription delivery DENIED for private event %s to %s (unauthorized)" ,
hex . Enc ( ev . ID ) , d . sub . remote )
continue
}
log . D . F ( "subscription delivery ALLOWED for private event %s to %s (authorized)" ,
hex . Enc ( ev . ID ) , d . sub . remote )
}
}
var res * eventenvelope . Result
var res * eventenvelope . Result
if res , err = eventenvelope . NewResultWith ( d . id , ev ) ; chk . E ( err ) {
if res , err = eventenvelope . NewResultWith ( d . id , ev ) ; chk . E ( err ) {
log . E . F ( "failed to create event envelope for %s to %s: %v" ,
log . E . F ( "failed to create event envelope for %s to %s: %v" ,
@ -299,3 +328,25 @@ func (p *P) removeSubscriber(ws *websocket.Conn) {
clear ( p . Map [ ws ] )
clear ( p . Map [ ws ] )
delete ( p . Map , ws )
delete ( p . Map , ws )
}
}
// canSeePrivateEvent checks if the authenticated user can see an event with a private tag
func ( p * P ) canSeePrivateEvent ( authedPubkey , privatePubkey [ ] byte , remote string ) ( canSee bool ) {
// If no authenticated user, deny access
if len ( authedPubkey ) == 0 {
return false
}
// If the authenticated user matches the private tag pubkey, allow access
if len ( privatePubkey ) > 0 && utils . FastEqual ( authedPubkey , privatePubkey ) {
return true
}
// Check if user is an admin or owner (they can see all private events)
accessLevel := acl . Registry . GetAccessLevel ( authedPubkey , remote )
if accessLevel == "admin" || accessLevel == "owner" {
return true
}
// Default deny
return false
}