Skip to content

"Changed" events for projections #199

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

Open
nickasd opened this issue Mar 14, 2018 · 11 comments
Open

"Changed" events for projections #199

nickasd opened this issue Mar 14, 2018 · 11 comments

Comments

@nickasd
Copy link

nickasd commented Mar 14, 2018

As seen in #143, in a projection subscription no "changed" events are sent. Is this a design decision? In my opinion projections would be a far more powerful feature if they completely behaved like real collections.

@nickasd nickasd changed the title Update events for projections "Changed" events for projections Mar 14, 2018
@balek
Copy link

balek commented Mar 14, 2018

I recommend you to not use projections. You can filter data in hooks. But don't forget to filter subscription operations in op hook.

I'll try to publish my high-level library for access control in near future.

@curran
Copy link
Contributor

curran commented Mar 15, 2018

@balek How can data be filtered in hooks? Can you provide a code snippet? This would be interesting to me. Just not sure exactly how to do it. Thank you.

@balek
Copy link

balek commented Mar 15, 2018

Something like this:

backend.use 'doc', (req, next) ->
    if req.agent.stream.isServer
        return next()
    doc = req.snapshot.data

    if req.collection == 'users'
        delete doc.password
        
    next()

backend.use 'op', (req, next) ->
    if req.agent.stream.isServer
        return next()

    if req.op.create or req.op.del
        # TODO: finish
        return next()

    i = 0
    while i < req.op.op.length
        op = req.op.op[i]
        if op.p.join('.') == 'password'
            _.remove req.op.op, i
        else
            i += 1
    next()

There still a lot of stuff to do. This code only controls reading of data (and not finished). You should also check queries (using server-query is the best way IMHO) and submitted operations.

Also be aware that req.agent.stream.isServer is true when a page is rendered on a server side. So server will fetch hidden fields and send them to a client. To avoid it you can set a flag in express middleware before app.router(). Like this:

    .use (req, res, next) ->
        req.model.socket.stream.checkServerAccess = true
        next()
    .use handlers.middleware
    .use app.router()

And check req.agent.stream.checkServerAccess with req.agent.stream.isServer in your hooks.

@nickasd
Copy link
Author

nickasd commented Mar 15, 2018

@balek Thank you for your help. Is there a specific reason why you suggest not to use projections? I can imagine that using projections is still more efficient than retrieving the data and then deleting the unnecessary properties (specifically if the data is large).

@balek
Copy link

balek commented Mar 15, 2018

Hm... I was talking about projections as a solution to restrict access to some data. In this case hooks are more flexible and simpler to use (you can't confuse collection and projection names).

If you want to decrease traffic usage, I'm not sure if sharedb has a good solution for you.

I can imagine that using projections is still more efficient than retrieving the data and then deleting the unnecessary properties

I believe projection works the same way. They are not used on a Mongo level. But I'm not sure.

@nickasd
Copy link
Author

nickasd commented Mar 15, 2018

I was talking about projections as a solution to restrict access to some data. In this case hooks are more flexible and simpler to use (you can't confuse collection and projection names).

Could you please elaborate on why hooks are more flexible? I thought that was exactly the use case for projections.

@houshuang
Copy link

houshuang commented Mar 15, 2018 via email

@balek
Copy link

balek commented Mar 15, 2018

Do you have a link to info about queries (server-query)?

https://github.com/dmapper/server-query

It's a little broken - not updated since ShareJS times. But can be easily fixed.

Could you please elaborate on why hooks are more flexible? I thought that was exactly the use case for projections.

You can dynamically decide which fields should be hidden. For example, make user settings visible only for the user himself, not others. Or you can give full access to admin.

@curran
Copy link
Contributor

curran commented Mar 15, 2018

@balek Thanks for the link to server-query! This is exactly what I was in need of (for security) when I opened #189

Looking forward to see your access control library. Struggling for a proper access control solution with ShareDB in our app.

@nickasd
Copy link
Author

nickasd commented Mar 22, 2018

In this case hooks are more flexible and simpler to use

Ok, I agree that hooks could be a possible solution to the problem. The question now is: since the clients will always access the real collection instead of the projection, how can the server differentiate the two cases: 1) the client wants the entire document, 2) the client only wants part of the document as defined in the projection?

@balek
Copy link

balek commented Mar 23, 2018

As I said, I misunderstood your problem. If you want to decrease traffic usage, I know only two solutions: sharedb projections and MongoDB aggregation queries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants