rocicorp / replicache

Realtime Sync for Any Backend Stack
https://doc.replicache.dev
1.02k stars 37 forks source link

Does it support tracking deletes and lost permissions? #1000

Closed pie6k closed 2 years ago

pie6k commented 2 years ago

First of all - replicache seems amazing!

Our team has an in-house thing (we call it clientdb) which is very similar. It is however very complex and if there is an alternative, we'd strongly consider that.

I have some a bit in-depth questions and assumptions I'd like to confirm:

Tracking deletes and lost permissions:

Let's say we have todo app with such data:

interface User {
  id: string;
  name: string;
}

interface Todo {
  id: string;
  ownerId: string;
  doneAt: Date;
  title: string
}

interface TodoMember {
  todoId: string;
  userId: string;
}

Users can access todo if it is owned by this user or if the user is a member of this todo.

Let's say we have users UA and UB.

UA creates todo (TA) and adds UB to it (TodoMember for TA<>UB)

UB should now be able to see TA so it is fetched client-side

UB goes offline

UA removes TodoMember for UB so UB has lost the access to see this todo (but todo itself still exists)

UB goes online again - how does the UB client know to remove TA now from the local cache?

Assumptions:

Simpler case: tracking normal direct deletes:

In case: I'm open for having some call discussing it in details.

aboodman commented 2 years ago

Hi Adam, thanks for asking. Hopefully we can help you out.

So simple case first. The typical way that we see almost everyone handle basic deletes is with a "soft delete" server-side. See, e.g., the postgres schema for our todo app: https://github.com/rocicorp/replicache-todo/blob/main/backend/data.ts#L53.

The pull handler tracks soft delete like any other mutation and sends a delete op in the pull response:

https://doc.replicache.dev/api#PullResponse https://github.com/rocicorp/replicache-todo/blob/main/pages/api/replicache-pull.ts#L52

If you use the todo starter app with the postgres backend, simple deletes are handled this way automatically.

===

Now the more interesting question. It's important to understand that Replicache doesn't know anything about users or ACLs. The data inside a Replicache instance is called the "client view". We call it that because it's a view on the server state, in the database sense. The client doesn't have all the data the server has, it just has a view of the data, the view appropriate for this client. Replicache doesn't know why this view changes from time to time. It could be because data got deleted, or because the user lost access to it.

So the bad news is that you have to track access changes yourself, somehow, server-side and tell Replicache about the entries that got deleted from a client's view.

The good news is that this is entirely a server-side task and has nothing to do with Replicache. Which makes it a lot easier to reason about and test. Your permission system can get arbitrarily complex and Replicache doesn't care.

For your simple case of a todo having members, one easy way to do it would be to compute the acl expansion server-side (either persistently or as a database view) and have a version like the todo sample does, but have it on the view instead. That way each user/todo pair has their own version, and that can be used in the pull handler the same way it is now. This basic idea can work with arbitrarily complex ACLs. There are other was to do this though that are more dynamic. If you'd like help thinking them through, come find me on discord or schedule me here: calendly.com/aboodman.

pie6k commented 2 years ago

Thank you for clarification!

boomfly commented 2 years ago

Could you please make basic example with users and acl?