Couche Sync :How to filter retrieval and update of documents for specific users/profiles?

62 views
Skip to first unread message

Souhail Marghabi

unread,
Mar 11, 2015, 12:13:50 PM3/11/15
to mobile-c...@googlegroups.com
Greetings,

I am new to couchbase Mobile and I am developing an iOS app with couchbase as a backend. I have a object called Survey which has another object called "Profile" as an  attribute. When syncing I want to make sure that the survey data gets only synced for the specific "profile" that applied change to it. in  Other words how to make that we sync only and retrieve only the related data for the current "profile" / user using the app.

Apologies if it's a generic or "simple" question, I am having a hard understanding how to config a couch sync JSON to enforce the criteria described above.

Jens Alfke

unread,
Mar 11, 2015, 12:22:48 PM3/11/15
to mobile-c...@googlegroups.com

On Mar 11, 2015, at 4:18 AM, Souhail Marghabi <souhail....@gmail.com> wrote:

I am new to couchbase Mobile and I am developing an iOS app with couchbase as a backend. I have a object called Survey which has another object called "Profile" as an  attribute. When syncing I want to make sure that the survey data gets only synced for the specific "profile" that applied change to it. in  Other words how to make that we sync only and retrieve only the related data for the current "profile" / user using the app.

In the sync function:
requireUser(doc.profile);
channel(“profile-“ + doc.profile);

The first line ensures that only the user named in the ‘profile’ property can change the document.
The second adds the document to a channel named after the profile. Then you need to configure your user accounts so each has access to the channel with the corresponding name, e.g. for user “foo” add “profile-foo” to the admin_channels property.

—Jens

Souhail Marghabi

unread,
Mar 12, 2015, 7:18:49 PM3/12/15
to mobile-c...@googlegroups.com
Hello, 
Thanks for response. I tried to apply what you suggested:

let's say that I didn't really create user accounts beside the Admin one i use to connect to admin couch server Interface and that I am trying to sync to a password protected Bucket + I have a shadow one too: {
    "interface": ":4984",
    "adminInterface": ":4985",
    "log": ["CRUD", "CRUD+", "HTTP", "HTTP+", "Access", "Cache", "Shadow", "Shadow+", "Changes", "Changes+"],
    "databases": {
        "showRoom": {
            "server": "http://myServer:8091",
            "bucket": "sync_gateway",
            "sync": `function(doc, oldDoc) { 



  if (doc.type != "client" && 
            doc.type != "surveyAnswers") {

          // everyone can sync these documents
          channel("public");
        }
 if (doc.type == "client") {
            // Users can't assign their contact document to another user.
            if (oldDoc != null && oldDoc.userID != doc.userID) throw({forbidden: "Can't change userId."});            
            // Users can only change their own contact.
            requireUser(oldDoc == null ? doc.userID : oldDoc.userID);

        } else
     if (doc.type == "surveyAnswers") {
          // give user access to his survey Answers
          access(doc.userId, "survey-" + doc.userId);
          // add doc to user's  channel
          channel("surveyAnswer - " + doc.userId);

requireUser(doc.userId);
        }



}`,
            "users": {
                "GUEST": {
                    "disabled": true }
            },
            "shadow": {
                 "server": "http://myServer:8091",
                 "bucket": "shadowDB"
            }
        }
    }
}

My questions are as follows:

Will this filter the sync making sure that only the profile  "client" of the current user will be updated & synced as for type == survey result?. 
How do I specify the password to access the bucket that is secured especially for the shadowing.

Sorry for long post. I am still new to this subject

Looking forward to your reply.

Souhail Marghabi

unread,
Mar 13, 2015, 9:40:52 AM3/13/15
to mobile-c...@googlegroups.com
In the iOS app I am making, I don't have pre existing accounts, the user creates a "profile" document and continues navigation in the app. I attached my sync config file and I am not sure if I am doing this correctly to make sure that the current user syncs only his own profile and survey answer Document.

Jens Alfke

unread,
Mar 13, 2015, 11:30:20 AM3/13/15
to mobile-c...@googlegroups.com

On Mar 13, 2015, at 6:40 AM, Souhail Marghabi <souhail....@gmail.com> wrote:

In the iOS app I am making, I don't have pre existing accounts, the user creates a "profile" document and continues navigation in the app. 

You can build an application that way, but then you can’t use any of the sync function features that involve users. So for example the requireUser() and access() calls in your sync function won’t work, because there aren’t any user accounts that the Sync Gateway knows about.

—Jens

Souhail Marghabi

unread,
Mar 13, 2015, 11:57:07 AM3/13/15
to mobile-c...@googlegroups.com
I see, but what are actually these accounts.
In my my current sync these functions "channel" and "requireUser" will not work? What should I explicitly add to enforce the filters and rules?

Snippet from the sync config:
 
"
            "users": {
                "GUEST": {
                    "disabled": true}
            },

 if (doc.type == "ReponseQuestionnaire") {
          // give user access to his survey Answers
var user = doc.idClient.substring(doc.idClient.indexOf(":")+1);
          access(user, "survey-" + user);
          // add doc to user's  channel
          channel("reponseQuestionnaire- " + user);
    requireUser(user);

        }
"


Jens Alfke

unread,
Mar 13, 2015, 12:07:57 PM3/13/15
to mobile-c...@googlegroups.com

On Mar 13, 2015, at 8:57 AM, Souhail Marghabi <souhail....@gmail.com> wrote:

I see, but what are actually these accounts.

Souhail Marghabi

unread,
Mar 13, 2015, 12:19:28 PM3/13/15
to mobile-c...@googlegroups.com
Thanks for the link, I have read through, and I was wondering if using the guest account and putting "GUEST" to "True" is enough, and with respect to channels with format (document- doc.userID) how can i specify this in the property of admin_channels?

Souhail Marghabi

unread,
Mar 13, 2015, 12:20:18 PM3/13/15
to mobile-c...@googlegroups.com
An additional important question, do I need an account for each user logging into the app?

Jens Alfke

unread,
Mar 13, 2015, 2:18:31 PM3/13/15
to mobile-c...@googlegroups.com

On Mar 13, 2015, at 9:19 AM, Souhail Marghabi <souhail....@gmail.com> wrote:

Thanks for the link, I have read through, and I was wondering if using the guest account and putting "GUEST" to "True" is enough

No. How is SG going to know which user is logged in if you haven’t defined users?

do I need an account for each user logging into the app?

Yes. (Same reason.)

—Jens

Souhail Marghabi

unread,
Mar 13, 2015, 2:23:11 PM3/13/15
to mobile-c...@googlegroups.com
Ok, but how will i know the exact number of users accounts i need to manually create in _user since its incremental for something like channel("documentname+ doc.userId)? 
Suremy i am misunderstanding something here
--
You received this message because you are subscribed to a topic in the Google Groups "Couchbase Mobile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mobile-couchbase/UqelTaQDcnc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mobile-couchba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/mobile-couchbase/1C50C7D2-6D04-4DA4-B0E7-013575E64377%40couchbase.com.
For more options, visit https://groups.google.com/d/optout.

Jens Alfke

unread,
Mar 13, 2015, 2:34:33 PM3/13/15
to mobile-c...@googlegroups.com

On Mar 13, 2015, at 11:23 AM, Souhail Marghabi <souhail....@gmail.com> wrote:

Ok, but how will i know the exact number of users accounts i need to manually create in _user since its incremental for something like channel("documentname+ doc.userId)? 
Suremy i am misunderstanding something here

I think I’m not understanding what you want to do.

You’ll need a user account for every user that uses the app and replicates to Sync Gateway. When doing that, put the channel name “user-XXX” in the admin_channels property, where XXX is the userID. That defines a channel for docs for that user.

Then when the app creates a document, it puts the user ID in a property of the document. The SG can then use that to validate that documents are only updated by the users who own them, and it can assign a document to the channel “user-“+doc.userID, so that the user will have access to it (and probably no one else will, unless you specifically give another user access to that channel.)

—Jens

Souhail Marghabi

unread,
Mar 13, 2015, 3:30:54 PM3/13/15
to mobile-c...@googlegroups.com
Ok i think it s gettin clearer for me. I based my learning on the example apps couchbase(todolite or couchChat) and they dont assign userID(in the sense of couch sync accounts) to channels, it s more documentId. Anyways so let me summarize what i understood from here:
1- i need to do a curl put request to add an indefinite number of accounts( i dont know how many users will download. And launch the app).
2- i need to then add these in couchsync key "users" And individually setting admin channels to "survey-user1", "survey-user2"....etc
3- only after step 2, can the SG filter my "survey" document through the requireUser(doc.ClientID) with clientID being the _id of my other document "Client" similarly to the owner property in the List Document which is used to differentiate list documents by profiles.
4- is there a concrete couchsync config that shows filtering the syncing and updating without having a definite set of users or where the new users who create their documents or want to access some "public"
Ones is possible. My scenario: user launches app-->fill textfields- clicks button profile document created and can only sync his--> can read views in public channels---> can fill a survey documents which has as a property the profile document _id and can only sync his survey document.

Sorry for the inconvenience, 


On Friday, March 13, 2015, Jens Alfke <je...@couchbase.com> wrote:
--
You received this message because you are subscribed to a topic in the Google Groups "Couchbase Mobile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mobile-couchbase/UqelTaQDcnc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mobile-couchba...@googlegroups.com.

Jens Alfke

unread,
Mar 13, 2015, 3:41:02 PM3/13/15
to mobile-c...@googlegroups.com

On Mar 13, 2015, at 12:30 PM, Souhail Marghabi <souhail....@gmail.com> wrote:

1- i need to do a curl put request to add an indefinite number of accounts( i dont know how many users will download. And launch the app).

You create the user accounts in response to requests from the client apps, the same way you would if you were writing a web-based service. (First time a user launches the app, they get prompted to login or register a new account. If they register, the app sends the info to your server-side code, which talks to SG to create a user account.)

Alternatively you can use Facebook or Persona to log in, in which case accounts get created on SG for each user the first time they authenticate.

—Jens

Souhail Marghabi

unread,
Mar 13, 2015, 3:56:37 PM3/13/15
to mobile-c...@googlegroups.com
I see, so i need an external Component to dyanmicly add new user accounts in my remote server(my backend is SG couchbase). Actually there is no real login in my app(username,password) app users do not enter login credentials they are recognized by the unique identifiers of their document, my first page is a form where users who downloaded te app fill profile information and that appears only once, and through which a profil document(which _id: profile:email) is created and then the user navigates through other pages that pull non restricted data from "public" documents, except for " survey" document which is "tagged" with the current profile id property( profile object is an attribute to survey). So what would be an optimal aproachto dynamicly create new users with respect to the requirement of SG and the specifics of my scenario, while avoiding authenticating through facebook?


On Friday, March 13, 2015, Jens Alfke <je...@couchbase.com> wrote:

On Mar 13, 2015, at 12:30 PM, Souhail Marghabi <souhail....@gmail.com> wrote:

1- i need to do a curl put request to add an indefinite number of accounts( i dont know how many users will download. And launch the app).

You create the user accounts in response to  from the client apps, the same way you would if you were writing a web-based service. (First time a user launches the app, they get prompted to login or register a new account. If they register, the app sends the info to your server-side code, which talks to SG to create a user account.)

Alternatively you can use Facebook or Persona to log in, in which case accounts get created on SG for each user the first time they authenticate.

—Jens

--
You received this message because you are subscribed to a topic in the Google Groups "Couchbase Mobile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mobile-couchbase/UqelTaQDcnc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mobile-couchba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/mobile-couchbase/4CBC8D5B-E9B8-4921-9A3A-E1EFEF49CB07%40couchbase.com.

Jens Alfke

unread,
Mar 16, 2015, 12:07:45 PM3/16/15
to mobile-c...@googlegroups.com

> On Mar 13, 2015, at 12:56 PM, Souhail Marghabi <souhail....@gmail.com> wrote:
>
> Actually there is no real login in my app(username,password) app users do not enter login credentials they are recognized by the unique identifiers of their document

I see. Have you thought about the security aspects of this design? What would prevent one person from impersonating another? (Maybe they couldn’t do this from within the app, but what about sending commands directly to the REST API?)

Generally the two ways to securely implement something like you describe are
(a) The client registers an account with the server on first login, without visible user interaction, where the userID and password are just randomly generated and stored persistently in the app;
or,
(b) The client generates an asymmetric key-pair (i.e. RSA or elliptic) on first launch and uses it to sign documents it creates. The server verifies documents by validating the signature, and your identity is your public key.

(We’re not quite set up to do (b) yet because the Sync Gateway doesn’t have the ability to validate signatures. But it’s something I’ve been experimenting with. I have a prototype app that uses this approach, and a spec for signing JSON documents.)

—Jens

Souhail Marghabi

unread,
Mar 16, 2015, 4:17:48 PM3/16/15
to mobile-c...@googlegroups.com
Greetings,

Thanks for your answer. 

Actually option (a) would be the best, but I do not really how to dynamically create and register user sync accounts with the server.
I have seen how to create user accounts "manually"  with "curl" POST request to create users on "admin" port. 

Would love to have more visibility on how to automate the registration/login process(from iOS app? App server?) to use for each increasing number user devices.

Thank 



—Jens

--
You received this message because you are subscribed to a topic in the Google Groups "Couchbase Mobile" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mobile-couchbase/UqelTaQDcnc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mobile-couchba...@googlegroups.com.

Jens Alfke

unread,
Mar 17, 2015, 1:13:19 AM3/17/15
to mobile-c...@googlegroups.com

On Mar 16, 2015, at 1:17 PM, Souhail Marghabi <souhail....@gmail.com> wrote:

Actually option (a) would be the best, but I do not really how to dynamically create and register user sync accounts with the server.
I have seen how to create user accounts "manually"  with "curl" POST request to create users on "admin" port. 

It’s the same thing. Write some kind of server-side script to handle requests from the app, and have it send a request to the SG admin port.

—Jens
Reply all
Reply to author
Forward
0 new messages