はじめに
Couchbase Mobileは、エッジコンピューティングを実現するデータプラットフォームであり、AndroidやiPhone(Swift, Objective-C)のようなスマートフォンやエッジデバイス用の組込データベースであるCouchbase Liteと、Couchbase Server、そしてそれらの間のデータの同期を実現する、Sync Gatewayから構成されます。
エッジコンピューティングを実現するCouchbase Mobile紹介:Sync Gatewayによるデータ同期におけるアクセス制御モデルにも書いた通り、Sync Gatewayでは、ユーザーとロールとチャネルによって、データ(ドキュメント)のルーティングを構成します。
ここで紹介するSync関数(Sync Function)を定義することによって、アプリケーションは、データルーティングとアクセス制御を実装することができます。
Couchbase Mobileアプリケーション開発へのロードマップもご覧ください。
Sync関数概要
Sync関数は、ドキュメントに対して新しいリビジョン/更新が行われるたびに呼び出されます。
Sync関数は、データルーティングとアクセス制御のため、以下のような処理を管理することができます。
- ドキュメントの検証
- 変更の承認
- チャネルへのユーザーアクセスの許可
- チャネルへのドキュメントの割り当て
また、アクセス制御の粒度として、
- ドキュメントレベルの読み取り許可
のみではなく、
- フィールド レベルの書き込み許可
を実現することができます。
Sync関数機能の基本
ヘルパー関数
Sync Gatewayは、Sync関数の中で利用することのできる、アクセスを制御するための多数のヘルパー関数を提供しています(詳しくは、Sync Function APIリファレンスを参照してください)。
たとえば、ユーザーにチャネルへのアクセスを許可するにはaccess()
ヘルパー関数を使用します。
このaccess()
関数は、ロールを操作することもできます。ユーザー名の文字列がrole:
で始まる場合、文字列の残りの部分は役割名として解釈されます(「:」はユーザー名またはロール名の不正な文字であるため、ここにあいまいさはありません)。
また、匿名リクエストはユーザー「GUEST」として認証されるため、GUEST
というユーザー名でaccess()
を呼び出すことにより、チャネルとそのドキュメントを公開できます。
削除ドキュメント
削除されたドキュメントのチェックを含め、検証時にこれらを異なる方法で処理する必要がある可能性があります。削除は、_deleted:true
プロパティを持つ単なるリビジョンです。このリビジョンには、他のプロパティは存在しません。
プロパティがないために検証チェックが失敗する可能性があるため、doc._deleted == true
のチェックを組み込みます。
Sync関数利用の基本
function (doc, oldDoc, meta) {
channel(doc.channels);
}
Sync Gateway 3.0ベータから、XATTR(拡張属性)の内容を使用してアクセス制御を駆動できるようになりました。これをサポートするために、追加のオプションの引数meta
が追加されています。
引数
Sync関数のそれぞれの引数について解説します。
doc
このオブジェクトは、保存されているドキュメントのコンテンツを参照します。これは、Couchbase Liteアプリケーションによって保存され、Sync Gatewayに複製されたJSONと一致します。
ドキュメントの_id
プロパティにはドキュメントIDが含まれていますドキュメントの_rev
プロパティは新しいリビジョンIDです。ドキュメントが削除される場合、値がtrue
の_deleted
プロパティがあります。
oldDoc
ドキュメントが以前に保存されている場合、このオブジェクトは置き換えられるリビジョンを参照します。それ以外の場合はnullです。
同期関数の実装では、oldDoc
パラメーターが必要ない場合は省略できます(Java Scriptは、関数に渡された余分なパラメーターを無視します)。
meta
この引数は、アクセス許可データを保持するために使用しているユーザー定義のXATTRを参照します。
参照されるオブジェクトには、チャネルやロールなどのアイテムを含めることができます。したがって、チャネル情報をドキュメント本文に直接埋め込む代わりに、ユーザーはドキュメントに関連付けられているこのユーザー定義のXATTRを指定できます。
構成方法
Sync関数を定義しない場合、SyncGatewayはデフォルトのSync関数を使用します。
ここでは、REST APIを使用してSync関数をプロビジョニングします。
この例ではcurlコマンドを使用します(他の方法を使用することも可能です)。
curl --location --request PUT 'http://localhost:4985/getting-started-db/_config' \
--header 'accept: application/json' \
--header 'Content-Type: application/json' \
--data-raw '{
"sync": ` /* sync function code */ `
}'
Sync関数はバッククォートで囲まれていることに注意してください。
定義例
Sync関数を構築するときは、アクセス制御とドキュメント配布の要件を決定する必要があります。例えば:
- 処理するドキュメントタイプ
- 提供するユーザー
- どのユーザーがどのドキュメントタイプにアクセスする必要があるか
- ドキュメントの作成、更新、および/または削除にどのような制約を課すか
この例の要件は次のとおりです。
- ドキュメントに次のプロパティがあること:
title
、title
、channels
、writers
-
editor
ロールを持つユーザーへのアクセスの作成および/または削除のみを許可 - ドキュメントの
writers
プロパティで識別されたユーザーのみが削除を含む変更を行うことを許可 - ドキュメントのメタデータ内で設定されたチャネルにドキュメントを割り当てる
// Note the new (3.0), optional, argument `meta`
function (doc, oldDoc, meta) {
if (doc._deleted) {
// Only editors with write access can delete documents:
requireRole("role:editor");
requireUser(oldDoc.writers);
// Skip other validation because a deletion has no other properties:
return;
}
// Required properties:
if (!doc.title || !doc.creator ||
!doc.channels || !doc.writers) {
throw({forbidden: "Missing required properties"});
} else if (doc.writers.length == 0) {
throw({forbidden: "No writers"});
}
if (oldDoc == null) {
// Only editors can create documents:
requireRole("role:editor");
// The 'creator' property must match the user creating the document:
requireUser(doc.creator)
} else {
// Only users in the existing doc's writers list can change a document:
requireUser(oldDoc.writers);
// The "creator" property is immutable:
if (doc.creator != oldDoc.creator) {
throw({forbidden: "Can't change creator"});
}
}
// Finally, assign the document to the channels in the list:
channel(meta.XattrChannels.channels);
}
関連情報