Start help with Sync Function :-)


#1

I’m new to Couchbase (first server app migrated to this db though) and Sync Gateway (rewriting first app to use sync). Therefore, I think I need a little guidance prior to running forward with my head down :slight_smile:

So I have a few documents with these characteristics:

  • All docs have a type property
  • Some docs are ‘Public’ (with a doc.ispublic boolean property) - these can ONLY be read
  • Docs with type=“User” have a key property with the user key
  • Other docs have a userkey property with the user key
  • Some of a user’s docs can also be ‘Public’ - the user can change these

I have started “playing” with a Sync Function:

function (doc, oldDoc) {
	//	Document type is mandatory
	if (!doc.type){
		throw({forbidden: "Document type is required."});
	}
	if (doc.ispublic) {
		channel('public');
        return;
	}
	var key = doc.type == 'User' ? doc.key : doc.userkey;
	requireUser(key);
}

I have enabled the GUEST account and want it to be able to sync all public documents so app can sync prior to the user logging in (or being registered). Setting the admin_channels to ‘public’ seems to do that trick:

 "users": { "GUEST": { "disabled": false, "admin_channels": ["public"] } },

So now to some questions:

  1. How can I make the ‘public’ channel a “pull only” ?
  2. Should I use two replicators in my app? - one for public and one for user docs? As I understand it I should start the replicator when starting the app - and only restart it in the event of the server having been offline (or app has been in the background) - and I guess that points in the direction of one replicator (due to resources).
  3. What is the best way to handle the user docs - do I need to use a channel (e.g. defined in the sync function)? - or will what I have above work Ok?
  4. How can I make sure that the user can update his/hers documents that are public?

I understand that when I make changes to the sync function I cannot deploy those from the admin console (not sure what the “Deploy to Server” button is meant to do though…?). Instead, if I understand it correctly, I have to:

  1. Edit the config file directly on the server
  2. Restart the sync gateway task on the server
  3. Take the DB offline (via a POST REST call)
  4. Resync the DB (via another POST REST call)
  5. Take the DB online again (via yet another POST REST call)

Number 3 above seem to never complete - the status of the DB is “Stopping” until I give up and restart the server… What could be wrong? - or am I doing this wrong?

Thanks for any input!

/John


#2

Hi John,
Here are few things I can help you with sync_gateway questions
# 2 . You do not need to use two replicators. One replicator should work for public and user docs. Yes you need to start the replicator when app is up and running and restart when server is offline or in background.

#3. Using channels is the best way to use user docs. To assign channels, you can use default one
function (doc) {
channel (doc.channels);
}

or you can use customized one
function(doc) {
channel (doc.anything);
}
There is more information how to use channels in this link : https://docs.couchbase.com/sync-gateway/2.1/data-routing.html#special-channels

#4. To make sure user can update their own documents that are public, you can check changes feed. It is one of the sync_gateway API and also you can check sync gateway logs.


#3

Thanks for your input Sridevi

So really I could just use the “!” channel and not grant GUEST access to any channel at all :+1:

But should I then invent a channel for each user? And just use the user key as the name for the channel? Can I create and connect it to the user via the sync function or do I need some more “fixed” setup? I have not gone this way as I understand one of the changes in the recent version(s) is that you don’t need to have a channel per user (but I may have misunderstood the change from the previous versions).

When I use one replicator in my app with pull-push how do I then make the documents in the “!” channel read only?

All the data I have worked on have been migrated from another system. This means that I have had to delete all documents and re-do the migration a couple of times. But it seems that this exercise leaves som “stubs” (aka. deletion stubs - maybe the same as “tomb stones”?) in the database. This would make sense in a normal environment so that deleted docs are tracked and can be removed from the replicas around - however, in my scenario I guess I could just get rid of them. Any thoughts? - and if needed how do I get rid of them?


#4

Yes, the “!” channel sounds like what you want for the public part.

In typical scenarios, users should have access to a limited subset of all documents. In this case, you would usually have a channel per user. You can authorize users to access a channel dynamically via the sync function.

Write authorization happens via the sync function, too. So you’d put a check in the sync function verifying the user has permission to write a doc. Note a user can, in principal, write a doc they can’t themselves read. See https://blog.couchbase.com/access-denied-or-access-lost-some-tips-on-sync-gateway/ for a more in-depth explanation.

You might also find this post about working with Sync Gateway from the command line helpful: https://blog.couchbase.com/getting-comfortable-with-couchbase-mobile-sync-gateway-via-the-command-line/

None of this has changed between the 1.x and 2.x versions. If you found the docs confusing about that somewhere, let me know and we can work to get it clarified.