{"id":2123,"date":"2016-01-13T21:37:07","date_gmt":"2016-01-13T21:37:06","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2123"},"modified":"2020-11-12T12:45:02","modified_gmt":"2020-11-12T20:45:02","slug":"augment-your-sync-function-with-roles-in-couchbase-sync-gateway","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/","title":{"rendered":"Augment your Sync Function with Roles in Couchbase Sync Gateway"},"content":{"rendered":"<p>Roles in Sync Gateway are often overlooked because they seem more complex to use than Users and Channels. However, they provide one additional layer of abstraction and can greatly simplify your data model. Take the example of an application to share reviews of restaurants by city. Different users could have different privileges such as moderators and guest users. In this tutorial, you will configure the <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/sync-gateway\/sync-function-api-guide\/index.html\">Sync Function<\/a> to allow authenticated users of such an application to approve, post reviews or assign roles to other users.<\/p>\n<p>In total, there will be 3 types of roles in the application:<\/p>\n<ul>\n<li><strong>level-1<\/strong>: users with the <strong>level-1<\/strong> role can post reviews but they must be accepted by users with the <strong>level-3<\/strong> role (i.e. moderators) to be public.<\/li>\n<li><strong>level-2<\/strong>: users can post reviews without validation needed from moderators. This means they can post a comment without requiring an approval.<\/li>\n<li><strong>level-3<\/strong>: users can approve reviews or reject them.Let\u2019s get started!<\/li>\n<\/ul>\n<h2 id=\"toc_1\">Download Sync Gateway<\/h2>\n<p>Download Sync Gateway and unzip the file:<\/p>\n<blockquote><p>https:\/\/www.couchbase.com\/downloads?family=sync-gateway<\/p><\/blockquote>\n<p>You will find the Sync Gateway binary in the <code>bin<\/code> folder and examples of configuration files in the <code>examples<\/code> folder. Copy the <code>users-role.json<\/code> file to the root of your project:<\/p>\n<pre><code class=\"language-bash\">cp ~\/Downloads\/couchbase-sync-gateway\/examples\/users-roles.json \/path\/to\/proj\/sync-gateway-config.json<\/code><\/pre>\n<p>In the next section, you will update the configuration file to create users and roles.<\/p>\n<h2 id=\"toc_2\">Editing the Config File<\/h2>\n<p>In <code>sync-gateway-config.json<\/code>, update the db object to read:<\/p>\n<pre><code class=\"language-javascript\">{\r\n  \"log\": [\"*\"],\r\n  \"databases\": {\r\n    \"db\": {\r\n      \"server\": \"walrus:\",\r\n      \"users\": {\r\n        \"jens\": {\r\n          \"admin_roles\": [\"level-1\"],\r\n          \"password\": \"letmein\"\r\n        },\r\n        \"andy\": {\r\n          \"admin_roles\": [\"level-2\"],\r\n          \"password\": \"letmein\"\r\n        },\r\n        \"william\": {\r\n          \"admin_roles\": [],\r\n          \"password\": \"letmein\"\r\n        },\r\n        \"traun\": {\r\n          \"admin_roles\": [\"level-3\"],\r\n          \"password\": \"letmein\"\r\n        }\r\n      },\r\n      \"roles\": {\r\n        \"level-1\": {},\r\n        \"level-2\": {},\r\n        \"level-3\": {}\r\n      },\r\n    }\r\n  }\r\n}<\/code><\/pre>\n<p>A couple of things are happening above:<\/p>\n<ol>\n<li>You create the user <code>jens<\/code> with the <code>level-1<\/code> role.<\/li>\n<li>You create the user <code>andy<\/code> with the <code>level-2<\/code> role.<\/li>\n<li>You create the user <code>william<\/code> without any role.<\/li>\n<li>You create the user <code>traun<\/code> with the <code>level-3<\/code> role.<\/li>\n<li>You define the 3 roles. Just like users, roles must be explicitly created on the Admin REST API or in the config file.<\/li>\n<\/ol>\n<p><strong>Note on creating roles<\/strong><\/p>\n<p>The easiest way to create roles is in the configuration file as you did above.<\/p>\n<p>Another way to create roles is through the admin REST API. Provided that you expose an endpoint to create those roles from the application, you can create roles dynamically by sending a request to your app server (blue arrows) which will create the role and send back a 201 Created if it was successful (green arrows).<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2016\/january\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/diagram.png\" \/><\/p>\n<p>In the next section, you will add the Sync Function to handle write and read operations for the three different types of documents (<code>restaurant<\/code>, <code>review<\/code>, <code>profile<\/code>).<\/p>\n<h2 id=\"toc_3\">Adding the Sync Function<\/h2>\n<p><a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/sync-gateway\/sync-function-api-guide\/routing\/index.html#role\">Roles<\/a> and <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/sync-gateway\/sync-function-api-guide\/routing\/index.html#access\">users<\/a> can both be granted access to <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/sync-gateway\/sync-function-api-guide\/routing\/index.html#channel\">channels<\/a>. Users can be granted roles, and inherit any channel access for those roles.<\/p>\n<p>Channel access determines a user\u2019s read security. Write security can also be based on channels (using <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/sync-gateway\/sync-function-api-guide\/validation\/index.html#require-access\">requireAccess<\/a>), but can also be based on user\/role (<a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/sync-gateway\/sync-function-api-guide\/validation\/index.html#require-user\">requireUser<\/a> and <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/sync-gateway\/sync-function-api-guide\/validation\/index.html#require-role\">requireRole<\/a>), or document content (using <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/sync-gateway\/sync-function-api-guide\/validation\/index.html#throw\">throw<\/a>).<\/p>\n<p>Read and write access to documents are independent. In fact write access is entirely governed by your sync function: unless the sync function rejects the revision, a client can modify any document. All the require* functions act as validators but also write access APIs.<\/p>\n<p>It\u2019s very common to see sync function creating lots and lots of channels. This is absolutely fine. However, it can get cumbersome to assign each user in turn to a channel. Instead you can use a role!<\/p>\n<p>Let this sink in one more time, users can be granted roles and inherit any channel access for those roles.<\/p>\n<p>This means you can grant a user access to multiple channels by simply assigning a role. This is very powerful because you don\u2019t need to assign every single user to a channel. You simply grant the role access to the channel and assign the users to the role.<\/p>\n<p>With that in mind, replace the sync function in <code>sync-gateway-config.json<\/code>:<\/p>\n<pre><code class=\"language-javascript\">function(doc, oldDoc) {\r\n  if (doc.type == \"restaurant\"){\r\n    channel(doc.restaurant_id);\r\n  } else if (doc.type == \"review\") {\r\n    switch(doc.role) {\r\n      case \"level-1\": \/\/ Step 1\r\n        requireRole(doc.role);\r\n        var channelname = doc.owner + \"-in-review\";\r\n        channel(channelname);\r\n        access(doc.owner, channelname);\r\n        access(\"role:level-3\", channelname);\r\n        break;\r\n    case \"level-2\": \/\/ Step 2\r\n      requireRole(doc.role);\r\n      channel(doc.restaurant_id);\r\n      break;\r\n    case \"level-3\": \/\/ Step 3\r\n      requireRole(doc.role);\r\n      channel(doc.restaurant_id);\r\n      break;\r\n    }\r\n  } else if (doc.type == \"profile\") {\r\n    requireRole(\"level-3\");\r\n    role(doc.name, \"role:\" + doc.role);\r\n  }\r\n}<\/code><\/pre>\n<p>Here\u2019s what\u2019s happening:<\/p>\n<ol>\n<li>Users with the <strong>level-1<\/strong> role have write access because you call the <code>channel<\/code> function. Then grant that user and the <strong>level-3<\/strong> access to this channel. This is where the power of roles really shines. By granting a role access, you are granting all the users with that role access to the channel. The call to <code>requireRole<\/code> will grant the write permission.<\/li>\n<li>Documents of type <code>review<\/code> created by a <strong>level-2<\/strong> role: the document should go in the same channel as the restaurant it belongs to. The call to <code>requireRole<\/code> will grant the write permission.<\/li>\n<li>Documents of type <code>review<\/code> created by a <strong>level-3<\/strong> role: the document should go in the channel for that restaurant. <strong>level-3<\/strong> users also have read access to all the <code>{user_name}-in-review<\/code> channels. They can approve\/reject the pending reviews of other users.<\/li>\n<\/ol>\n<p>Start Sync Gateway with the updated configuration file:<\/p>\n<pre><code class=\"language-bash\">$ ~\/Downloads\/couchbase-sync-gateway\/bin\/sync_gateway \/path\/to\/proj\/sync-gateway-config.json<\/code><\/pre>\n<p>In this example, you are utilising the 3 main features of roles:<\/p>\n<ul>\n<li>Granting a role access to a channel and indirectly to all the users with that role.<\/li>\n<li>Granting write permission using a requireRole.<\/li>\n<li>Assigning a role to a user.<\/li>\n<\/ul>\n<p>Now you can test the Sync Function behaves as expected with the following HTTP requests.<\/p>\n<h2 id=\"toc_4\">Running Different Scenarios<\/h2>\n<p><strong>Scenario 1<\/strong><\/p>\n<p>Documents of type <code>review<\/code> created by a <strong>level-1<\/strong> user: the document should go in the <code>{user_name}-in-review<\/code> channel and the users with the <strong>level-3<\/strong> role should have access to this channel too.<\/p>\n<p>Login as the user <code>jens<\/code>:<\/p>\n<pre><code class=\"language-bash\">curl -vX POST -H 'Content-Type: application\/json' \r\n     :4984\/db\/_session \r\n     -d '{\"name\": \"jens\", \"password\": \"letmein\"}'\r\n     \r\n&gt; POST \/db\/_session HTTP\/1.1\r\n&gt; User-Agent: curl\/7.37.1\r\n&gt; Host: :4984\r\n&gt; Accept: *\/*\r\n&gt; Content-Type: application\/json\r\n&gt; Content-Length: 39\r\n&gt; \r\n* upload completely sent off: 39 out of 39 bytes\r\n&lt; HTTP\/1.1 200 OK\r\n&lt; Content-Length: 103\r\n&lt; Content-Type: application\/json\r\n* Server Couchbase Sync Gateway\/1.1.0 is not blacklisted\r\n&lt; Server: Couchbase Sync Gateway\/1.1.0\r\n&lt; Set-Cookie: SyncGatewaySession=6c52b8cd2c706d55e97d9606058c0abd90a5d200; Path=\/db\/; Expires=Tue, 07 Jul 2015 08:23:03 UTC\r\n&lt; Date: Mon, 06 Jul 2015 08:23:03 GMT\r\n&lt; \r\n* Connection #0 to host  left intact\r\n{\"authentication_handlers\":[\"default\",\"cookie\"],\"ok\":true,\"userCtx\":{\"channels\":{\"!\":1},\"name\":\"jens\"}}\u23ce                                                                            <\/code><\/pre>\n<p>Save a new document of type <code>review<\/code> (substitute the token with the one returned in the <code>Set-Cookie<\/code> header above):<\/p>\n<pre><code class=\"language-bash\">curl -vX POST -H 'Content-Type: application\/json' \r\n     --cookie 'SyncGatewaySession=d007ceb561f0111512c128040c32c02ea9d90234' \r\n     :4984\/db\/ \r\n     -d '{\"type\": \"review\", \"role\": \"level-1\", \"owner\": \"jens\"}'<\/code><\/pre>\n<ul>\n<li>Check that user <code>jens<\/code> has access to the channel <code>jens-in-review<\/code> and the comment document is in there.<img decoding=\"async\" src=\"\/wp-content\/original-assets\/2016\/january\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/level-1.png\" \/><\/li>\n<li>Check that user <code>traun<\/code> has access to channel <code>jens-in-review<\/code>.<img decoding=\"async\" src=\"\/wp-content\/original-assets\/2016\/january\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/level-3.png\" \/><\/li>\n<\/ul>\n<p>You can also view the channels this document belongs to and roles\/users that have access to it in the <code>Documents<\/code> tab:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2016\/january\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/doc-jens.png\" \/><\/p>\n<p><strong>Scenario 2<\/strong><\/p>\n<p>Granting write access using a role.<\/p>\n<p>Login as <code>andy<\/code> and replace the token with the one you got back from the login request.<\/p>\n<pre><code class=\"language-bash\">curl -vX POST -H 'Content-Type: application\/json' \r\n              --cookie 'SyncGatewaySession=6e7ce145ae53c83de436b47ae37d8d94beebebea' \r\n              :4984\/db\/ \r\n              -d '{\"type\": \"review\", \"role\": \"level-2\", \"owner\": \"andy\", \"restaurant_id\": \"123\"}'<\/code><\/pre>\n<ul>\n<li>Check that the comment was added to the restaurant channel (named <code>123<\/code> in this example).<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2016\/january\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/doc-andy.png\" \/><\/p>\n<p><strong>Scenario 3<\/strong><\/p>\n<p>Assigning a role to a user.<\/p>\n<p>Login as <code>traun<\/code> and replace the token with the one you got back from the login request.<\/p>\n<pre><code class=\"language-bash\">curl -vX POST -H 'Content-Type: application\/json' \r\n              --cookie 'SyncGatewaySession=3a5c5a67ff67643f8ade175363c65354584429e9' \r\n              :4984\/db\/ \r\n              -d '{\"type\": \"profile\", \"name\": \"william\", \"role\": \"level-3\"}'<\/code><\/pre>\n<ul>\n<li>Check that <code>william<\/code> has role <code>level-3<\/code>.<\/li>\n<li>Check that <code>william<\/code> has access to the <code>jens-in-review<\/code> channel.<img decoding=\"async\" src=\"\/wp-content\/original-assets\/2016\/january\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/user-william.png\" \/><\/li>\n<\/ul>\n<h2 id=\"toc_5\">Conclusion<\/h2>\n<p>In this tutorial, you learnt how to use channels and requireRole to dynamically validate and perform write operations. You also assigned multiple channels at once to multiple users using the role API.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Roles in Sync Gateway are often overlooked because they seem more complex to use than Users and Channels. However, they provide one additional layer of abstraction and can greatly simplify your data model. Take the example of an application to [&hellip;]<\/p>\n","protected":false},"author":51,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1810],"tags":[],"ppma_author":[9028],"class_list":["post-2123","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-mobile"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Augment Sync Function with Roles in Couchbase Sync Gateway<\/title>\n<meta name=\"description\" content=\"See how to configure the Sync Function to allow authenticated users of such an application to approve, post reviews or assign roles to other users.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Augment your Sync Function with Roles in Couchbase Sync Gateway\" \/>\n<meta property=\"og:description\" content=\"See how to configure the Sync Function to allow authenticated users of such an application to approve, post reviews or assign roles to other users.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-01-13T21:37:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-11-12T20:45:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"James Nocentini, Technical Writer, Mobile, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"James Nocentini, Technical Writer, Mobile, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/\"},\"author\":{\"name\":\"James Nocentini, Technical Writer, Mobile, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6\"},\"headline\":\"Augment your Sync Function with Roles in Couchbase Sync Gateway\",\"datePublished\":\"2016-01-13T21:37:06+00:00\",\"dateModified\":\"2020-11-12T20:45:02+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/\"},\"wordCount\":1005,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Couchbase Mobile\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/\",\"name\":\"Augment Sync Function with Roles in Couchbase Sync Gateway\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2016-01-13T21:37:06+00:00\",\"dateModified\":\"2020-11-12T20:45:02+00:00\",\"description\":\"See how to configure the Sync Function to allow authenticated users of such an application to approve, post reviews or assign roles to other users.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Augment your Sync Function with Roles in Couchbase Sync Gateway\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6\",\"name\":\"James Nocentini, Technical Writer, Mobile, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/09977bdd14473dc23a125f2f74c3e816\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g\",\"caption\":\"James Nocentini, Technical Writer, Mobile, Couchbase\"},\"description\":\"James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for raywenderlich.com in his spare time.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/james-nocentini\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Augment Sync Function with Roles in Couchbase Sync Gateway","description":"See how to configure the Sync Function to allow authenticated users of such an application to approve, post reviews or assign roles to other users.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/","og_locale":"en_US","og_type":"article","og_title":"Augment your Sync Function with Roles in Couchbase Sync Gateway","og_description":"See how to configure the Sync Function to allow authenticated users of such an application to approve, post reviews or assign roles to other users.","og_url":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/","og_site_name":"The Couchbase Blog","article_published_time":"2016-01-13T21:37:06+00:00","article_modified_time":"2020-11-12T20:45:02+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"James Nocentini, Technical Writer, Mobile, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"James Nocentini, Technical Writer, Mobile, Couchbase","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/"},"author":{"name":"James Nocentini, Technical Writer, Mobile, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6"},"headline":"Augment your Sync Function with Roles in Couchbase Sync Gateway","datePublished":"2016-01-13T21:37:06+00:00","dateModified":"2020-11-12T20:45:02+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/"},"wordCount":1005,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Couchbase Mobile"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/","url":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/","name":"Augment Sync Function with Roles in Couchbase Sync Gateway","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2016-01-13T21:37:06+00:00","dateModified":"2020-11-12T20:45:02+00:00","description":"See how to configure the Sync Function to allow authenticated users of such an application to approve, post reviews or assign roles to other users.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/augment-your-sync-function-with-roles-in-couchbase-sync-gateway\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Augment your Sync Function with Roles in Couchbase Sync Gateway"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6","name":"James Nocentini, Technical Writer, Mobile, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/09977bdd14473dc23a125f2f74c3e816","url":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","caption":"James Nocentini, Technical Writer, Mobile, Couchbase"},"description":"James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for raywenderlich.com in his spare time.","url":"https:\/\/www.couchbase.com\/blog\/author\/james-nocentini\/"}]}},"authors":[{"term_id":9028,"user_id":51,"is_guest":0,"slug":"james-nocentini","display_name":"James Nocentini, Technical Writer, Mobile, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","author_category":"","last_name":"Nocentini","first_name":"James","job_title":"","user_url":"","description":"James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for raywenderlich.com in his spare time."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/51"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=2123"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2123\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=2123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=2123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=2123"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=2123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}