From dc76432a553baa13ba2e0b3b92c11e68e95083b7 Mon Sep 17 00:00:00 2001 From: ibsoln <52778946+ibsoln@users.noreply.github.com> Date: Fri, 30 Apr 2021 10:25:46 +0100 Subject: [PATCH] DOC-8425 -- Revise Channels Documentation https://issues.couchbase.com/browse/DOC-8425 --- modules/ROOT/assets/attachments/sg.yaml | 19 +- .../attachments/sync-gateway-admin.yaml | 4 +- modules/ROOT/pages/_partials/_page-index.adoc | 1 + .../_partials/topic-group-access-control.adoc | 78 +++++ .../pages/_partials/topic-group-concepts.adoc | 80 ++++++ modules/ROOT/pages/channels.adoc | 266 ++++++++++++++---- modules/ROOT/pages/import-process.adoc | 10 +- modules/ROOT/pages/read-access.adoc | 8 +- modules/ROOT/pages/revisions.adoc | 4 +- modules/ROOT/pages/roles.adoc | 5 +- modules/ROOT/pages/sync-function.adoc | 26 +- modules/ROOT/pages/users.adoc | 5 +- modules/ROOT/pages/what-are-tombstones.adoc | 4 +- modules/ROOT/pages/write-access.adoc | 7 +- 14 files changed, 428 insertions(+), 89 deletions(-) create mode 100644 modules/ROOT/pages/_partials/topic-group-access-control.adoc create mode 100644 modules/ROOT/pages/_partials/topic-group-concepts.adoc diff --git a/modules/ROOT/assets/attachments/sg.yaml b/modules/ROOT/assets/attachments/sg.yaml index 7369079c3..48c92ed5f 100644 --- a/modules/ROOT/assets/attachments/sg.yaml +++ b/modules/ROOT/assets/attachments/sg.yaml @@ -277,7 +277,7 @@ properties: enable_star_channel: type: boolean description: |+ - Enable the star (*) channel. + Enable the all documents (*) channel -- sometimes referred to as the 'star' channel. default: 'true' max_length: type: integer @@ -612,9 +612,11 @@ properties: properties: admin_channels: type: array - description: | + description: |+ The list of channels this role is automatically granted access to when Sync Gateway starts. - If "*" is specified then the role is granted access to the star channel which contains all documents. + + If you use the all channels wildcard ("*") the role is granted access to all channels and to all documents within all channels. This will be inherited by any user assigned this role. + items: type: string send_www_authenticate_header: @@ -806,7 +808,11 @@ properties: description: The user's password. admin_channels: type: array - description: The list of channels this user is automatically granted access to when Sync Gateway starts. If `"*"` is specified then the user is granted access to the [star channel](sync-gateway-channels.html#special-channels) which contains all documents. + description: |+ + The list of channels this user is automatically granted access to when Sync Gateway starts. + + If you use the all channels wildcard ("*") the user is granted access to all channels and to all documents within all channels -- see: [all channels wildcard](channels.html#lbl-all-channels). + items: type: string admin_roles: @@ -1301,6 +1307,11 @@ properties: These details are used to authenticate credentials and approve access to data Once provided and recorded, the username data is redacted and will not be displayed in either the configuration file or Admin REST API. A string of `****` will be displayed in its place. + + Replications initiated by this user will pull all documents in all channels the user has access grants for. + If the all channels wildcard was used to grant access then the sync will pull *ALL* documents. + Use a filter to avoid syncing excessive amounts of data to mobile devices. + facebook: description: Configuration for Facebook Login authentication. type: object diff --git a/modules/ROOT/assets/attachments/sync-gateway-admin.yaml b/modules/ROOT/assets/attachments/sync-gateway-admin.yaml index 5a307c2f7..642f36978 100644 --- a/modules/ROOT/assets/attachments/sync-gateway-admin.yaml +++ b/modules/ROOT/assets/attachments/sync-gateway-admin.yaml @@ -1478,7 +1478,7 @@ paths: admin_channels: type: array description: | - The admin channels that this role has granted access to. Admin channels are the ones which were + The admin channels that this role has granted access to. Admin channels are the ones which are granted access to in the config file or via the Admin REST API. items: type: string @@ -2507,7 +2507,7 @@ definitions: properties: channels: type: object - description: Key-value pairs with a channel name as the key and the sequence number that granted the user access to the channel as value. `!` is the public channel and every user has access to it. + description: Key-value pairs with a channel name as the key and the sequence number that granted the user access to the channel as value.Note that `!` is the public channel and every user has access to it. name: type: string description: The user's name. diff --git a/modules/ROOT/pages/_partials/_page-index.adoc b/modules/ROOT/pages/_partials/_page-index.adoc index bbb069e98..acfe7b15f 100644 --- a/modules/ROOT/pages/_partials/_page-index.adoc +++ b/modules/ROOT/pages/_partials/_page-index.adoc @@ -248,6 +248,7 @@ endif::xref--pfx-sgw[] :supported-environments--xref: {sgw--xref}{supported-environments--page}[Supported Environments] :sync-function--page: sync-function.adoc :sync-function--xref: {sgw--xref}{sync-function--page}[Sync Function] +:sync-function--bmk-requireAcces: {sgw--xref}{sync-function--page}[Sync Function -- requireAccess()] :sync-inter-syncgateway-conflict-resolution--page: sync-inter-syncgateway-conflict-resolution.adoc :sync-inter-syncgateway-conflict-resolution--xref: {sgw--xref}{sync-inter-syncgateway-conflict-resolution--page}[Inter Sync Gateway Sync - Conflict Resolution] :sync-inter-syncgateway-manage--page: sync-inter-syncgateway-manage.adoc diff --git a/modules/ROOT/pages/_partials/topic-group-access-control.adoc b/modules/ROOT/pages/_partials/topic-group-access-control.adoc new file mode 100644 index 000000000..49c2055ec --- /dev/null +++ b/modules/ROOT/pages/_partials/topic-group-access-control.adoc @@ -0,0 +1,78 @@ +// BEGIN -- inclusion -- topic-group-access-control.adoc +// Purpose: +// Show the topic group, allowing easy cycle-through +// Do not show current page as a click-through though +// Container: /modules/ROOT/pages/_partials/ + +// BEGIN -- get the current calling page's name +:this-page: {page-relative-src-path} +// END -- get the current calling page's name + +// Begin -- Define Local Attributes with Required Links and Titles for this topic group +// Set titles for xrefs +:title-1: Sync function +:title-2: Read access +:title-3: Write access +// :title-4: Revisions +// :title-5: Tombstones + + +// Set the pages for the xrefs to link to (we are using attributes from _page-index.adoc here) +:topic-1: {sync-function--page} +:topic-2: {read-access--page} +:topic-3: {write-access-page} +// :topic-4: {revisions--page} +// :topic-5: {what-are-tombstones--page} +// Set the xrefs up using attribute from _page-index.adoc and above attributes +:topic-1--xref: {sgw--xref}{topic-1}[{title-1}] +:topic-2--xref: {sgw--xref}{topic-2}[{title-2}] +:topic-3--xref: {sgw--xref}{topic-3}[{title-3}] +// :topic-4--xref: {sgw--xref}{topic-4}[{title-4}] +// :topic-5--xref: {sgw--xref}{topic-5}[{title-5}] +// End -- Local Attributes + +// Begin -- Remove the xref link from current calling page +ifeval::["{this-page}"=="{topic-1}"] +:topic-1--xref: pass:q,a[*{title-1}*] +endif::[] + +ifeval::["{this-page}"=="{topic-2}"] +:topic-2--xref: {title-2} +endif::[] + +ifeval::["{this-page}"=="{topic-3}"] +:topic-3--xref: {title-3} +endif::[] + +// ifeval::["{this-page}"=="{topic-4}"] +// :topic-4--xref: {title-4} +// endif::[] + +// ifeval::["{this-page}"=="{topic-5}"] +// :topic-5--xref: {title-5} +// endif::[] +// End -- Remove xref link from current page +// Begin -- Output Block +_Related {param-topic-group} topics_: {topic-1--xref} | {topic-2--xref} | {topic-3--xref} | {topic-4--xref} | {topic-5--xref} +// End -- Output Block + +// Begin -- Tidy-up +:this-page!: +:topic-1!: +:topic-2!: +:topic-3!: +// :topic-4!: +// :topic-5!: +:title-1!: +:title-2!: +:title-3!: +// :title-4!: +// :title-5!: +:topic-1--xref!: +:topic-2--xref!: +:topic-3--xref!: +// :topic-4--xref!: +// :topic-5--xref!: +// End -- Tidy-up + +// END -- inclusion -- content-group-configuration.adoc \ No newline at end of file diff --git a/modules/ROOT/pages/_partials/topic-group-concepts.adoc b/modules/ROOT/pages/_partials/topic-group-concepts.adoc new file mode 100644 index 000000000..aee838632 --- /dev/null +++ b/modules/ROOT/pages/_partials/topic-group-concepts.adoc @@ -0,0 +1,80 @@ +// BEGIN -- inclusion -- topic-group-concepts.adoc +// Purpose: +// Show the topic group, allowing easy cycle-through +// Do not show current page as a click-through though +// Container: /modules/ROOT/pages/_partials/ + +// BEGIN -- get the current calling page's name +:this-page: {page-relative-src-path} +// END -- get the current calling page's name + +// Begin -- Define Local Attributes with Required Links and Titles for this topic group +// Set titles for xrefs +:title-1: Users +:title-2: Roles +:title-3: Channels +:title-4: Revisions +:title-5: Tombstones + + +// Set the pages for the xrefs to link to (we are using attributes from _page-index.adoc here) +:topic-1: {users--page} +:topic-2: {roles--page} +:topic-3: {channels--page} +:topic-4: {revisions--page} +:topic-5: {what-are-tombstones--page} + + +// Set the xrefs up using attribute from _page-index.adoc and above attributes +:topic-1--xref: {sgw--xref}{topic-1}[{title-1}] +:topic-2--xref: {sgw--xref}{topic-2}[{title-2}] +:topic-3--xref: {sgw--xref}{topic-3}[{title-3}] +:topic-4--xref: {sgw--xref}{topic-4}[{title-4}] +:topic-5--xref: {sgw--xref}{topic-5}[{title-5}] +// End -- Local Attributes + +// Begin -- Remove the xref link from current calling page +ifeval::["{this-page}"=="{topic-1}"] +:topic-1--xref: pass:q,a[*{title-1}*] +endif::[] + +ifeval::["{this-page}"=="{topic-2}"] +:topic-2--xref: {title-2} +endif::[] + +ifeval::["{this-page}"=="{topic-3}"] +:topic-3--xref: {title-3} +endif::[] + +ifeval::["{this-page}"=="{topic-4}"] +:topic-4--xref: {title-4} +endif::[] + +ifeval::["{this-page}"=="{topic-5}"] +:topic-5--xref: {title-5} +endif::[] +// End -- Remove xref link from current page +// Begin -- Output Block +_Related {param-topic-group} topics_: {topic-1--xref} | {topic-2--xref} | {topic-3--xref} | {topic-4--xref} | {topic-5--xref} +// End -- Output Block + +// Begin -- Tidy-up +:this-page!: +:topic-1!: +:topic-2!: +:topic-3!: +:topic-4!: +:topic-5!: +:title-1!: +:title-2!: +:title-3!: +:title-4!: +:title-5!: +:topic-1--xref!: +:topic-2--xref!: +:topic-3--xref!: +:topic-4--xref!: +:topic-5--xref!: +// End -- Tidy-up + +// END -- inclusion -- content-group-configuration.adoc \ No newline at end of file diff --git a/modules/ROOT/pages/channels.adoc b/modules/ROOT/pages/channels.adoc index e31ce50df..9963f845f 100644 --- a/modules/ROOT/pages/channels.adoc +++ b/modules/ROOT/pages/channels.adoc @@ -4,82 +4,193 @@ :idprefix: :idseparator: - :url-httpie: https://github.com/jakubroztocil/httpie -:keywords: access control, document routing, sync, +:keywords: access control, document routing, sync + include::partial$_std-hdr-sgw.adoc[] +// BEGIN -- Local Attributes +:alldocs--xref: {rest-api-admin--pfx}#/database/GetAllDocs[_all_docs] +:funcdef--xref: xref:sync-function.adoc#function-definition[Function Definition] +:requireaccessfunc--xref: xref:sync-function.adoc#requireaccesschannels[requireAccess()] +:addaccessfunc--xref: xref:{sgw-pg-read-access}#add-access[Add Access] +:accessfunc--xref: xref:sync-function.adoc#accessusername-channelname[access(username, channel)] +:channelfunc--xref: xref:sync-function.adoc#channelchannelname[channel(channel)] +// END -- Local Attributes + + // BEGIN -- Page Heading -:topic-group: concept +:param-topic-group: concepts :param-abstract: pass:q[Sync Gateway's _Channels_ are a key part of a flexible approach to data routing and access control.
In this topic we look at how to implement access-control and document routing using _Channels_. ] -:param-related: {revisions--xref} | {roles--xref} | {what-are-tombstones--xref} | {users--xref} include::partial$block-abstract.adoc[] // END -- Page Heading + == Introduction Sync Gateway uses _Channels_ to make it easy to share a database's documents across a large user base whilst retaining effective access control. They serve as a security conduit between the document and a user: -* Every document in the database is assigned a list of channels it belongs to. -* Every user is assigned a list of channels they are allowed to access. +* Every user is granted access to a list of channels. +* Every document in the database is assigned a list of channels it is distributed to. -This dual-purpose is reflected in the way you define channels: +This dual-purpose is reflected in the way you use channels: -* By assigning a channel to a user you are imposing access control -* By assigning a channel to a document you are imposing document routing +* By granting a user access to a channel, you are imposing access control +* By assigning a document to a channel you are imposing document routing == Use-cases You typically will use channels to: -* Partition the data set. -* Authorize users to access documents. -* Minimize the amount of data synced down to devices. +* Control who can access what +* Partition your data set +* Enable users to access just the documents they need +* Minimize the amount of data synced to mobile devices + + +== Channels and Wildcards + +Sync Gateway provides two special channels and a channel wildcard character: + +* The <> ('*!*') -- is a channel for publicly available documents. +It provides for the public dissemination of documents. +* The <> ('***') -- is a single, internal channel, comprising all documents from all channels. +All documents are implicitly assigned this channel. + +* The <> ('***') -- used when granting user access, this wildcard grants access to any document in any channel. + +See: <> for a Sync function that shows how you might use these channels and wildcards. + + +[#lbl-public-channel] == Public Channel -The *public channel*, written as `!` in the sync function, is automatically created when Sync Gateway starts. -Documents added to this channel are visible to any user (i.e all users are automatically granted access to the `!` channel). -This channel can be used as a public distribution channel. +The *Public Channel* is referred to by the symbol ('*!*'). +It is ideal for use in making information available across the user community. -The following Sync Function maps the document to the public channel if it contains an `isPublic` property set to true and grants users with the 'admin' role access to the all docs channel. +You assign a document to the _public_ (*!*) channel using the {channelfunc--xref} function. -[source,javascript] +Documents assigned to this channel can be accessed by all users; even users assigned no specific channel access. + +New users are automatically granted access to the channel. + +For an example of how to use the public channel -- see: <> + + +[#lbl-alldocs-channel] +== All Documents Channel + +Assignment to the _all documents_ (***) channel footnote:[Sometimes referred to as the *star* channel] is automatic and implicit. +You cannot explicitly assign documents to the channel or remove documents from it. + +This channel should not be confused with the use of the <> in access grants. + + +[#lbl-all-channels] +== All Channels Wildcard + +The *All Channels* wildcard is referred to by the symbol ('***'). + +You make dynamic user access grants in the sync function using the {accessfunc--xref} method -- for more, see: {addaccessfunc--xref}. + +Granting a user access with the _all channels_ wildcard gives them access to any channel, and any document in any channel, including those from private channels. + +Replications by users with _all channels_ wildcard access will pull *all* documents. +Because of this potential for syncing large volumes of data (sync pulls all documents in the bucket), users with _all channels_ wildcard access should use a channel filter to explicitly name the channel(s) to be sync'd. + +*Note:* Users granted access using the _all channels_ wildcard *do not* inherit {requireaccessfunc--xref} rights to any specific channel. + +TIP: Always use a filter in conjunction with the _all channels_ wildcard, to avoid sync unnecessarily pulling large numbers of documents to mobile devices. + +For an example of how to use the _all channels_ wildcard -- see: <> + + +== Using Channels in the Sync function + +Here we show the use of the _public channel_ and _all channels wildcard_ in a Sync function. +The function provides for: + +* Document Routing -- it routes public documents to the _public_ channel +* Access Control -- it grants users with an admin role access to _all documents in all channels_. + +[#ex-using-wildcard-channels] +.Using channels and wildcards +==== + +[source, javascript] ---- -function (doc, oldDoc) { - if (doc.isPublic) { - channel('!'); - } - if (doc.type == 'user') { - requireRole('admin'); - access(doc.username, '*'); - } +// "sync": ` +function sync(doc, oldDoc) { + + /* Validation -- add validation rules here */ + // e.g. Verify the requesting user is the oldDoc's user + if ((oldDoc != null) && (oldDoc.username)) { + requireUser(oldDoc.username); + } + + ourChannel = "channel." + getUserName()); + + /* Routing -- add channel routing rules here */ + // e.g. add public docs to the public channel. + if (doc.isPublic) { + channel('!'); + } else { + channel(ourChannel); // <.> + } + + /* Access Control -- add user access rules here */ + // If this is an admin user, grant access to 'all documents' + if (doc.type == 'user') { + requireRole('admin'); + access(doc.username, '*'); // <.> + } + + // If this is a ticket, require user have access to ourChannel + if (doc.type == 'ticket') { + requireAccess(ourChannel); // <.> + // further processing as required + } + + // further processing as required + + /* Supporting Functions */ + function getUserName() { + return (isDelete() ? oldDoc.username : doc.username); + } } +// ` + ---- -== Star Channel +<.> If the document is public, we assign it to the _public channel_, using the public channel wildcard; otherwise we assign it to the user's channel. -The *star* channel, written as `+*+` in the sync function, is automatically created when Sync Gateway starts. -All documents are added to this channel. -So any user that is granted access to the `+*+` channel can access all the documents in the database. -A user can be given access to the *star* channel through the sync function or in the configuration file (see xref:{sgw-pg-read-access}#add-access[Add Access]). +<.> For documents of type `user`, if the user has an admin role, we grant them access to _all_ documents using the _all channels_ wildcard. + +<.> For documents of type `ticket`, we require the user to have *explicit* access to 'ourChannel'. +Users with access granted only using the _all channels_ wildcard will *not* satisfy this criteria. + +==== -* *Note 1:* Sync Gateway automatically assigns documents to the all docs channel. -Explicitly assigning a document to it in the Sync Function (i.e `channel('*')`) will result in unexpected behavior such as receiving the document twice on the client side. -* *Note 2:* The *star* channel doesn't mean that the user is granted access to all channels. -It is only being granted access to 1 channel which contains *all documents*. -This distinction is important when using the xref:sync-function.adoc#requireaccess-channels[`requireAccess()`] Sync Function method. == Inspect a Document You can use the admin REST API to see the channels that documents are assigned to. -Issue a {rest-api-admin-pfx}#/database/get -\__db___all_docs[/+\{db}+/_all_docs] request, and add the query parameter `?channels=true` to the URL. -Here's an example of the response. -The output shows that the document is in the channels `short` and `word`. +Issue a {alldocs--xref} request as follows: + +[source, http] +---- +http://localhost:4984/travel-sample/_all_docs?channels=true +---- + +The output response will be similar to that shown in <>. + +[#ex-inspect-doc-response] +.Output from Inspect Document +==== [source,json] ---- { @@ -88,7 +199,7 @@ The output shows that the document is in the channels `short` and `word`. "id": "foo", "key": "foo", "value": { - "channels": [ + "channels": [ // <.> "short", "word" ], @@ -100,33 +211,44 @@ The output shows that the document is in the channels `short` and `word`. "update_seq": 26 } ---- +<.> The output shows that the document is distributed to two channels: `short` and `word`. +==== + == Add to Channel -You assign documents to channels by writing a Sync Function in the configuration file ({configuration-properties-pfx}#databases-this_db-sync[databases.$db.sync]). -The Sync Function is a JavaScript function that takes a document body as input and, based on the document content, decides what channels to assign the document to (see the xref:sync-function.adoc#function-definition[Function Definition]). +You assign documents to channels in a Sync Function. +You can provide this function in the configuration file ({configuration-properties--pfx}#databases-this_db-sync[databases.$db.sync]). +The Sync Function is a JavaScript function that takes a document body as input and, based on the document content, decides what channels to assign the document to (see the {funcdef--xref}). -Based on the contents of the document, the Sync Function can call xref:sync-function.adoc#channelchannelname[channel()] to add the document to one or more channels. +Based on the contents of the document, the Sync Function can call {channelfunc--xref} to add the document to one or more channels -- see <> This makes it accessible to users who have access to those channels, and will cause the document to be pulled by users that are subscribed to those channels. -The following Sync Function routes incoming documents to a channel named `foo`. +[#ex-use-channel] +.Routing Documents +==== [source,javascript] ---- function (doc, oldDoc) { - channel("foo"); + channel("foo"); // <.> } ---- +<.> The Sync Function routes incoming documents to a channel named `foo`. +==== -Channels come into existence as documents are assigned to them. +Channels are created as documents are assigned to them. The Sync Function cannot reference any external state and must return the same results every time it's called on the same input. Valid channel names consist of text letters `[A–Z, a–z]`, digits `[0–9]`, and a few special characters `[= + / . , _ @]`. Channel names are case-sensitive. Channels with no documents assigned to them are empty. -If you don't supply a Sync Function in the configuration file, Sync Gateway uses the {configuration-properties-pfx}#databases-this_db-sync[default Sync Function]. -The default Sync Function is really only useful for experimentation and development, it is recommended to write a Sync Function which contains the appropriate Validation, and Read and Write access for your application. +If you don't supply a Sync Function in the configuration file, Sync Gateway uses the {configuration-properties--pfx}#databases-this_db-sync[default Sync Function]. +This default function is really only useful for experimentation and development. + +TIP: You are advised to write a Sync Function that provides validation, routing and access-control appropriate to your business needs -- see: {sync-function--xref} for more on sync functions. + == Remove from Channel @@ -135,20 +257,54 @@ If the document was previously routed to a channel, but the current call to the This may cause users to lose access to that document. If that happens, the next time Couchbase Lite pulls changes from the gateway, it will purge the document from the database and trigger the document replication listener on Couchbase Lite with the `AccessRemoved` flag. -xref:couchbase-lite:swift:replication.adoc#replication-events[Swift] | xref:couchbase-lite:java:replication.adoc#replication-events[Java] | xref:couchbase-lite:android:replication.adoc#replication-events[Android (Java)] | xref:couchbase-lite:csharp:replication.adoc#replication-events[C#] | xref:couchbase-lite:objc:replication.adoc#replication-events[Objective-C] +:param-page: replication +:param-bookmark: replication-events +include::partial$blocklinks-cbl.adoc[] + + +== Limits and Constraints + +=== Channel Limits + +.Guidance on Channel Assignment Limits +[#tbl-limits, cols="2,4,^3", options="header"] +!=== + +| Element +| Limiting factor +| Guidance Limit (Channels) -== Sync Metadata +| Channels per document +| The amount of memory consumed by the combined number of channels and access grants must fit within the maximum 1Mb xattr size limit -- see: <>. +| 50 + +| Channels per user +a| The amount of memory consumed by channels must fit within the 20 MB available on Couchbase Server docs for storing metadata -- see: <> + +Note that the memory is retained for as long as the replication remains active. +| 1,000 + +!=== + + +=== Sync Metadata Limits Every time a document is assigned to a new channel, the channel name is appended to that document's sync metadata. -Therefore, a document's set of channels is bound by the allowed sync metadata size described in the following table. +Therefore, a document's set of channels is limited by the allowed sync metadata size described in <>. +.Size Limits for Sync Metadata +[#tbl-metadata-size,cols="^4,^4", options="header"] |=== -|`enable_shared_bucket_access: false`|`enable_shared_bucket_access: true` - 2+a|*Sync metadata size limit* -|20 MB per document -|1 MB per document +|Value of `enable_shared_bucket_access` +|Size (Mb per Document) + +m|false +|20 + +m|true +|1 + |=== Sync Gateway will assign a document to a new channel as long as the sync metadata remains under the allowed limit. @@ -160,7 +316,7 @@ In order to lower the sync metadata size per document, you can do one of the fol * Lower the number of channels per document. * Shorten the channel names. A shorter channel name will occupy less space ("customer==0030169303" vs "cs==0030169303"). -* Lower the {configuration-properties-pfx}#databases-this_db-revs_limit[revs_limit] value. +* Lower the {configuration-properties--pfx}#databases-this_db-revs_limit[revs_limit] value. Indeed, a copy of channel metadata is retained for each revision of a document. diff --git a/modules/ROOT/pages/import-process.adoc b/modules/ROOT/pages/import-process.adoc index 9c67e9d05..d7e77a919 100644 --- a/modules/ROOT/pages/import-process.adoc +++ b/modules/ROOT/pages/import-process.adoc @@ -26,9 +26,9 @@ The document is first run through the Sync Function to compute read security and This means that `requireAccess`, `requireUser` and `requireRole` calls in the Sync Function are treated as no-ops. * During import, `oldDoc` is `nil` when the Sync Function is executed. -You can specify a filter function using the {configuration-properties-pfx}#databases-this_db_import_filter[import_filter] property, which will only import specific documents. +You can specify a filter function using the {configuration-properties--pfx}#databases-this_db_import_filter[import_filter] property, which will only import specific documents. -TIP: Use the {configuration-properties-pfx}#log[Import+] log key to troubleshoot import processing issues in the logs. +TIP: Use the {configuration-properties--pfx}#log[Import+] log key to troubleshoot import processing issues in the logs. == Configuration @@ -102,8 +102,8 @@ The reference to the configuration properties can be found below. // * link:config-properties.html#databases-this_db-import_docs[$dbname.import_docs] to give a particular Sync Gateway node the role of importing the documents. // * link:config-properties.html#databases-this_db-import_filter[$dbname.import_filter] to select which document(s) to make aware to mobile clients. -* {configuration-properties-pfx}#databases-this_db-enable_shared_bucket_access[$dbname.enable_shared_bucket_access] to enable convergence for a given database. -* {configuration-properties-pfx}#databases-this_db-import_docs[$dbname.import_docs] to give a particular Sync Gateway node the role of importing the documents. -* {configuration-properties-pfx}#databases-this_db-import_filter[$dbname.import_filter] to select which document(s) to make aware to mobile clients. +* {configuration-properties--pfx}#databases-this_db-enable_shared_bucket_access[$dbname.enable_shared_bucket_access] to enable convergence for a given database. +* {configuration-properties--pfx}#databases-this_db-import_docs[$dbname.import_docs] to give a particular Sync Gateway node the role of importing the documents. +* {configuration-properties--pfx}#databases-this_db-import_filter[$dbname.import_filter] to select which document(s) to make aware to mobile clients. include::partial$block-related-content-api.adoc[] diff --git a/modules/ROOT/pages/read-access.adoc b/modules/ROOT/pages/read-access.adoc index e1f7b643d..31b624ce3 100644 --- a/modules/ROOT/pages/read-access.adoc +++ b/modules/ROOT/pages/read-access.adoc @@ -19,11 +19,11 @@ // END PAGE DEFINITION = Read Access :page-aliases: learn/read-access.adoc +:description: How to handle read-access include::partial$_std-hdr-sgw.adoc[] -:topic-group: access-control -:param-related: {sync-function--xref} | {write-access--xref} +:param-topic-group: access-control :param-abstract: pass:q[The sync function API provides several methods that you can use to validate user access.] include::partial$block-abstract.adoc[] @@ -84,7 +84,7 @@ Because anonymous requests are authenticated as the user "GUEST", you can make a === Configuration File -A user can be granted access to a channel through the {configuration-properties-pfx}#databases-this_db-users-this_user-admin_channels[admin_channels] property in the configuration file. +A user can be granted access to a channel through the {configuration-properties--pfx}#databases-this_db-users-this_user-admin_channels[admin_channels] property in the configuration file. === Admin REST API @@ -152,6 +152,6 @@ Client apps can use this ability to intelligently sync with a subset of the avai :param-bookmark: channels include::partial$blocklinks-cbl.adoc[] -include::partial$block-related-content-api.adoc[] +include::partial$block-related-content-sync.adoc[] // END -- PAGE -- read-access.adoc diff --git a/modules/ROOT/pages/revisions.adoc b/modules/ROOT/pages/revisions.adoc index 2ae57fc94..fc134a8e9 100644 --- a/modules/ROOT/pages/revisions.adoc +++ b/modules/ROOT/pages/revisions.adoc @@ -8,9 +8,9 @@ include::partial$_std-hdr-sgw.adoc[] // BEGIN -- Page Heading -:topic-group: concept +:param-topic-group: concepts :param-abstract: pass:q[Revisions are at the heart of Couchbase Mobile's ability to respond flexibly and securely to changing data from server to edge.] -:param-related: pass:q,a[{channels--xref} | {revisions--xref} | {roles--xref} | {what-are-tombstones--xref} | {users--xref}
_Related Blogs_: {url-blog-dbsizemng-pruning} | {url-blog-doc-conflicts-repl-protocol-revisions} | {url-blog-doc-conflicts-demystifying-mvcc}] +:param-related: {url-blog-dbsizemng-pruning} | {url-blog-doc-conflicts-repl-protocol-revisions} | {url-blog-doc-conflicts-demystifying-mvcc}] include::partial$block-abstract.adoc[] // END -- Page Heading diff --git a/modules/ROOT/pages/roles.adoc b/modules/ROOT/pages/roles.adoc index df07a0d2b..96b4372f9 100644 --- a/modules/ROOT/pages/roles.adoc +++ b/modules/ROOT/pages/roles.adoc @@ -9,9 +9,8 @@ include::partial$_std-hdr-sgw.adoc[] // BEGIN -- Page Heading -:topic-group: concept +:param-topic-group: concepts :param-abstract: pass:q[Here we introduce the concept of _Roles_ and the part they play in assuring secure access control within _Sync Gateway_.] -:param-related: {channels--xref} | {revisions--xref} | {users--xref} | {what-are-tombstones--xref} include::partial$block-abstract.adoc[] // END -- Page Heading @@ -61,5 +60,5 @@ This method is convenient for testing and to get started, otherwise it is genera ---- <1> {configuration-properties--pfx}#databases-this_db-users-this_user-admin_roles[databases.$db.users.$user.admin_roles] - include::partial$block-related-content-sync.adoc[] + diff --git a/modules/ROOT/pages/sync-function.adoc b/modules/ROOT/pages/sync-function.adoc index 1215d4ad7..a8c1a335c 100644 --- a/modules/ROOT/pages/sync-function.adoc +++ b/modules/ROOT/pages/sync-function.adoc @@ -29,8 +29,7 @@ include::partial$_std-hdr-sgw.adoc[] // BEGIN -- Page Heading -:topic-group: access control -:param-related: {read-access--xref} | {write-access--xref} +:param-topic-group: access-control :param-abstract: pass:q[The sync function is crucial to the security of an app. It is in charge of data validation, access control and routing.] include::partial$block-abstract.adoc[] // END -- Page Heading @@ -58,7 +57,7 @@ Configuration properties: <4> `num_index_replicas` is the number of index replicas stored in Couchbase Server, introduced with GSI/N1QL indexing -- see {xref-sgw-pg-indexing}. If you're running a single Couchbase Server node for development purposes the `num_index_replicas` must be set to `0`. <5> The sync function -- a javascript function enclosed in backticks, which is actioned every time a new document, document revision or deletion is made to a database -- see the: - {configuration-properties-pfx}#databases-this_db-sync[databases.$db.sync] property. + {configuration-properties--pfx}#databases-this_db-sync[databases.$db.sync] property. ==== == Function Definition @@ -89,7 +88,7 @@ Otherwise it's `null`. (In the case of a document with conflicts, the current provisional winning revision is passed in `oldDoc`.) Your implementation of the sync function can omit the `oldDoc` parameter if you do not need it (JavaScript ignores extra parameters passed to a function). -If you don't supply a sync function, Sync Gateway uses the {configuration-properties-pfx}#databases-this_db-sync[default Sync Function]. +If you don't supply a sync function, Sync Gateway uses the {configuration-properties--pfx}#databases-this_db-sync[default Sync Function]. == channel(channelname) @@ -129,6 +128,8 @@ As a convenience, either argument may be `null` or `undefined`, in which case no If a user name begins with the prefix `role:`, the rest of the name is interpreted as a role rather than a user. The call then grants access to the specified channels for all users with that role. +You can use the _all channels_ wildcard ('***') to grant the user access to all documents in all channels. + NOTE: The effects of all access calls by all active documents are effectively unioned together, so if _any_ document grants a user access to a channel, that user has access to the channel. Calling `access(username, channelname)` multiple times to grant the same user access to the same channel will result in negative performance implications. @@ -164,9 +165,14 @@ role ("ed", null); // no-op ---- NOTE: Roles, like users, have to be explicitly created by an administrator. -So unlike channels, which come into existence simply by being named, you can't create new roles with a `role()` call. + +Unlike channels, which come into existence simply by being named, you can't create new roles with a `role()` call. +Like _users_, they must be defined in the configuration or by API. + Nonexistent roles don't cause an error, but have no effect on the user's access privileges. -You can create a role after the fact; as soon as a role is created, any pre-existing references to it take effect. + +TIP: You can create roles retrospectively. +As soon as a role is created, any pre-existing references to it take effect. == requireUser(username) @@ -222,7 +228,13 @@ if (oldDoc) { The function signals rejection by throwing an exception, so the rest of the sync function will not be run. -If a user was granted access to the xref:{sgw-pg-channels}#special-channels[star channel] (noted `+*+`), a call to `requireAccess('any channel name')'` will fail because the user wasn't granted access to that channel (only to the `+*+` channel). To allow a user to perform a document update in this case, you can specify multiple channel names (`requireAccess('any channel name', '*')'`) +You can specify multiple channel names, for example: + +`requireAccess('any channel name', '*')'` + +If a user was granted access using only the xref:{sgw-pg-channels}#lbl-all-channels[all channels wildcard]] (`+*+`), then `requireAccess('any channel name')'` will fail because the user wasn't granted access to that channel (only to the `+*+` channel). + +NOTE: requireAccess() will only recognize grants made explicitly using a channel name (not by wildcard). + == requireAdmin() diff --git a/modules/ROOT/pages/users.adoc b/modules/ROOT/pages/users.adoc index 45def7e50..af63ae4ee 100644 --- a/modules/ROOT/pages/users.adoc +++ b/modules/ROOT/pages/users.adoc @@ -12,9 +12,9 @@ include::partial$_std-hdr-sgw.adoc[] // BEGIN -- Page Heading -:topic-group: concept +:param-topic-group: concepts :param-abstract: pass:q[Here we introduce the concept of _users_ and their role in assuring secure access control within _Sync Gateway_.] -:param-related: {channels--xref} | {revisions--xref} | {roles--xref} | {what-are-tombstones--xref} +:param-related!: include::partial$block-abstract.adoc[] // END -- Page Heading @@ -71,5 +71,4 @@ This method is convenient for testing and to get started, otherwise it is genera ---- <1> {configuration-properties--pfx}#databases-this_db-users[databases.$db.users] - include::partial$block-related-content-data.adoc[] \ No newline at end of file diff --git a/modules/ROOT/pages/what-are-tombstones.adoc b/modules/ROOT/pages/what-are-tombstones.adoc index 73909f0cf..fd34a0e8b 100644 --- a/modules/ROOT/pages/what-are-tombstones.adoc +++ b/modules/ROOT/pages/what-are-tombstones.adoc @@ -9,9 +9,9 @@ include::partial$_std-hdr-sgw.adoc[] // BEGIN -- Page Heading -:topic-group: concept +:param-topic-group: concepts :param-abstract: pass:q[Here we introduce the concept of _Tombstones_ and their role in the _Sync Gateway_ revision process.] -:param-related: {channels--xref} | {revisions--xref} | {roles--xref} | {users--xref} +:param-related!: include::partial$block-abstract.adoc[] // END -- Page Heading diff --git a/modules/ROOT/pages/write-access.adoc b/modules/ROOT/pages/write-access.adoc index fb8e71058..54e19bb0f 100644 --- a/modules/ROOT/pages/write-access.adoc +++ b/modules/ROOT/pages/write-access.adoc @@ -25,9 +25,9 @@ include::partial$_std-hdr-sgw.adoc[] // BEGIN -- Page Heading -:topic-group: access-control +:param-topic-group: access-control :param-abstract: pass:q[The Sync Function API provides several methods that you can use to validate document creation, updates and deletions.] -:param-related!: {sync-function--xref} | {read-access--xref} +:param-related!: include::partial$block-abstract.adoc[] // END -- Page Heading @@ -136,6 +136,9 @@ requireAccess(["events", "messages"]) // <.> <.> throw an error unless the can read one of these channels ==== + +When sending a change to Sync Gateway through the {rest-api-admin--xref}, the Sync Function is executed with admin privileges: calls to `requireUser`, `requireAccess` and `requireRole` are no-ops (that is, they will always be successful). + TIP: To create and manage user accounts, refer to {xref-sgw-pg-users}.