Putting a doc with id X to channel Y using sync function


#1

I am having a docs of user profiles. For example, user X and user Y is having their profile docs like this:

{
    _id   : "X"
    type  : "profile",
    name  : "ABC",
    email : "abc@xyz.com"
}

{
    _id   : "Y"
    type  : "profile",
    name  : "PQR",
    email : "pqr@xyz.com"
}

When a user X adds as a contact user Y, he/she should be able to see that user’s profile.
So to have user Y in its list I’m adding a doc like this:

{
    _id   : "uuid",
    type  : "contact",
    pid   : "Y",
    contact_of : "X"
}

So for X to be able to see Y’s profile, I need to put doc with id Y to channel of user X (each user is having channel of its own name)

My sync function for mapping this doc in channel is something like this:

if (doc.type == "contact") {
    channel(doc.contact_of);
    requireUser(doc.contact_of);
}

However, I am not able to find any way to put doc with id Y to to channel X. because channel function put the current doc to a particular channel. Here the profile document of user Y is not updated, so the sync function will not be called for that.

Is there any way to achieve this using webhooks? or ADMIN REST API? or t are there any better approach to map contact profile to user?


#2

There is a few ways

1: Make the “contact_of” into an array.

{
_id : “uuid”,
type : “contact”,
pid : “Y”,
contact_of :[“x”,“y”]
}

2: Update Sync Function:

if (doc.type && doc.type ===“contact” && doc.contact_of && doc.contact_of.length >0) {
for(x in doc.contact_of){
channel(doc.contact_of[x]);
}
}

3: Update Users account with new channel access.
http://developer.couchbase.com/documentation/mobile/1.2/develop/references/sync-gateway/admin-rest-api/user-admin/put-user/index.html

PUT /cookbook/_user/chef123 HTTP/1.1
Host: localhost:4985
Content-Type: application/json
{
“name”: “x”,
“admin_roles”: [“x”,“y”]
}


#3

If I understood correctly from you answer,

You are trying to put that contact in both channel X and Y. That will not grant me the access of Y’s profile doc.

I’ll try to explain a bit more here:
Initial State has each user’s profile in a channel of their user’s name.

After adding a doc marking B is a contact of A, profile doc of B should also be added to channel A so that user A can see user B’s details.

I made a drawing to understand the problem:

with channel(doc.contact_of), I can put this document to channel “A”, but how can I put a doc with id B to channel A?


#4

@kirtan403

If you assign a channel for each users profile document only:

e.g.

X-profile, Y-profile

When you receive a document with type contact, use the access() function to assign the user in ‘contact_of’ to the ‘pid’ users profile channel e.g.

if (doc.type == "profile") {
    channel(doc._id);
    channel(doc._id + "-profile");
    requireUser(doc.contact_of);
}
if (doc.type == "contact") {
    access(doc.contact_of, doc.pid + "-profile");
    requireUser(doc.contact_of);
}

You might also find the todo-lite sync function a useful reference.


#5

A perfect solution I must say ! I was checking this on live preview mode, it seems to work.

I think there should be a way to assign a doc other than which is syncing to channel. Or else an ADMIN REST API should provide a function which can do be done with the help of webhooks.


#6

So for X to be able to see Y’s profile, I need to put doc with id Y to channel of user X (each user is having channel of its own name)

I don’t know what your privacy requirements are for profiles, but this doesn’t provide any privacy. Any user can see any other user’s profile if they know their ID, just by adding them as a contact; then they get access to the user’s profile.

I think there should be a way to assign a doc other than which is syncing to channel.

The current design of SG ties the channel assignments to the document revision, and assumes that a doc’s channels can only change when the doc is updated. It would be a lot harder to implement what you’re asking for. It’s also less functional, since updating a doc can create side effects on other docs.


#7

It happens in the background, just after the user approves other user to be added. The user ids are the UUIDs, and not the simple text. I used A, B and C for illustrative purposes only.

It would be a lot harder to implement what you’re asking for.

I would be happy to see this coming in future :slightly_smiling:


#8

It still sounds like if you can discover someone’s UUID, you can read their profile. I wouldn’t call that secure enough — a 3rd party might tell you a person’s UUID, or you may have had them as a contact in the past but now they want to remove you and don’t want you to see any changes to their profile (think of someone leaving a relationship and not wanting their ex-partner to be able to get their new phone number or address.)

The approach Andy suggested is more secure because it puts users in charge of who can see their profiles.


#9

Haha… :smiley: … That is a tough scenario. But in my case its something different. Where people come together to contribute in a group. So it is fine where people can see each other and they can add someone to their personal contact so that they can follow their contributions. (It’s almost same as what we are doing in this forum but for different reasons).