-
-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conditional publish based on user permissions #40
Comments
Hi Nathan, Thank you for raising this issue! Apologies for the delayed response – life just seems to happen and hamper my swiftness to reply. As a side-note, in retrospective it's just funny to me that I didn't think of these use-cases when I've first designed the library:
It can only make me happy that there's enough usage for them to have been uncovered and that even without their support the library has still gained some traction. Coming back on track to the issue, I can imagine how partitioning users by permissions might not work. But some other idea to use topics just came to my mind and maybe could work – let me know if it could apply to your use-case. Here's how it goes:
If your scenario is one where such an implementation would work, you're in the happy case to not have to wait for a library update. If you're not, let's see what could be done. I'll go through your proposals and also add some of mine:
func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
sess, err := sse.Upgrade(w, r)
if err != nil { /* handle unsupported client */ }
user, err := s.authenticate(r)
if err != nil { /* handle unauthenticated access */ }
msgs := make(chan *sse.Message)
// we can ignore this error because it will probably be just the context error with this update
go joe.Subscribe(r.Context(), sse.Subscription{Chan: msgs, LastEventID: sess.LastEventID, Topics: []string{...}})
for msg := range msgs {
// your own filtering based on permissions
switch err := s.shouldDispatch(r.Context(), user, msg); err.(type) {
case auth.ErrUnauthorized:
continue
default:
/* handle auth errors: e.g. database/auth provider access */
return
}
if err := sess.Send(msg); err != nil {
/* handle write error */
return
}
}
// on ServeHTTP return the request context will be cancelled, https://pkg.go.dev/net/http#Request.Context.
// Joe will respect cancellation and clean up the subscription.
}
These would be my thoughts. Would be very happy to have some more insight into your issue, as requested in points 1 and 2 above, and your feedback on 3 and 4, and whether any of these solutions would actually help you implement filtering in your application. Hopefully I've properly understood your problem and gave valuable insight and proposals. Looking forward to your answer! |
I'm enjoying this library and impressed by your responsiveness to people's issues!
One problem I'm having is I need to filter events per session based on authorization rules in my security layer. I have a single SSE endpoint that thousands of users connect to, each with unique permissions that influence the events they receive.
I thought about using a custom
MessageWriter
wrapper which might work, but the concreteMessage
struct is highly optimized for streaming and I'd rather not have to unmarshal the message data for every connected client on the way out.I also thought about partitioning my users into separate topics but my permissions are too fine-grained to make this feasible.
Couple of ideas off the top of my head:
Message
an interface so I can attach arbitrary metadatamap[string]any
field toMessage
context.Context
toMessageWriter.Send
so I can grab metadata from thatCheers!
The text was updated successfully, but these errors were encountered: