Hi All,
I’ve got an application where many users all collaborate on the same document in real time. Each user may have the ability to do different things. Some users may be able to add new blocks of content and others may only be able to edit existing ones and others may not be able to edit anything.
I was wondering if anyone knows of a way of implementing this in YJS? Can I prevent writes to specific parts of a document by some users? I’ve tried implementing something like this in ywebsocket but I couldn’t see a good way to work out what the user changed other than to make the change, get the JSON representation of the document and diff it to the state before the change. Is there a better way of doing this?
Thanks!
This is something every Yjs app wants to do at some point, but so far there’s no built-in way of accomplishing it. By design, your edits are either allowed or not allowed with nothing in-between. Implementing your own structured ACL is probably not going to work or at least, it can be hacked.
That in mind, you can simply block the operations client-side and that would probably be sufficient for 99% of normal use-cases. Sure, somebody could hack it but then again, it’d be equal to having full-write access with the expectation that you shouldn’t mess other’s work. Recovering of course needs snapshots and/or GC turned off.
If you truly need separate ACL for blocks you should either embed them as subdocs or nodes that use your APIs directly. You can of course write a wrapper around the Yjs doc that specifically watches the content and figures out how to overwrite “bad” writes (that pass the client validation). But that’s going to be hacky.
I concur that fine-grained access-control within the bounds of a single Y.Doc is out of scope for Y.js and something that’s probably hard to implement.
Not sure if this helps but what you can do (and what I’ve sometimes done) is to
- add an
observeDeep
observer on your server-side component and
- watch for any illegal changes and
- take appropriate action.
Yet, step 3 is challenging, because when you observe an illegal change, it has already been applied and possibly propagated to other clients. But you can at least prevent it from being saved to your database. A crude method could be to just ditch the whole Doc from the server at this point and close all related Websocket connections. When the clients connect again, the document would be reset to it’s earlierly stored, valid state.
I’m also dubious about step 2 - I’m not entirely sure if there are ways to introduce changes to the document in such a way that an observer may miss them. Maybe @dmonad can shed some light on this.
Thinking a bit further, you might introduce a different server-side architecture, where each client would have their own server-side copy of the document, in addition to a “master” copy that is also persisted to your database. In this model, you could detect an illegal change before propagating it to the master copy and other clients. But this is just an idea, I’ve never tried this. Lemme know if it makes sense 