Device Sync 権限ガイド
項目一覧
このページでは、次の一般的なユースケースに合わせて Device Sync アプリの権限を設定する方法を説明します。
テンプレート アプリの使用
これらの権限モデルの一部は、Device Sync 権限ガイド テンプレート アプリを使用してすぐに起動して実行できます。 各テンプレート アプリには、バックエンドと Node.js デモ クライアントが付属しています。 バックエンドでは、すべての機能、権限、trigger がここで説明されているように設定されています。 デモ クライアントはバックエンドに接続し、簡単なスクリプトを実行してバックエンドの動作方法を説明します。
これらのテンプレートを使用するには、認証された App Services CLI が必要です。
App Services CLI は npm
で利用できます。 システムに CLI をインストールするには、 Node.js があることを確認してください。がインストールされたら、shell で次のコマンドを実行します。
npm install -g atlas-app-services-cli
ログイン手順については、 CLI リファレンス ページを参照してください。
ログインしたら、 --template
フラグとともにapps create
コマンドを使用してテンプレートをインスタンス化できます。
appservices apps create --template=TEMPLATE_NAME
TEMPLATE_NAME
次のいずれかになります。
flex-sync-guides.add-collaborators
(動的連携に対応)flex-sync-guides.restricted-feed
(制限付きニュースフィードに対応)flex-sync-guides.tiered
(階層化された特権に対応する)
これらの例について
ここの例では、デフォルトのロール を使用します。 つまり、アプリ内のすべてのコレクションに同じ権限ルールが適用されます。 アプリが複雑になるにつれて、一部のコレクションにのみ適用され、他のコレクションには適用されないコレクション固有のロールが必要になる場合があります。 特に、デフォルト ロールのルール式で、特定のコレクション内のオブジェクトに存在しない「クエリ可能なフィールド」が使用されている場合は、コレクション固有のロールを提供することでそのコレクションのルールを上書きできます。 詳細については、「ロールベースの権限」を参照してください。
自分のデータの読み取りと書込み
この場合、ユーザーは自分のデータの読み取りや書き込みができますが、他のユーザーのデータは読み取れません。 例えば、ユーザーが永続化されたり、自分のデバイス間でメモを共有したりしたいが、ユーザーのアカウントには非表示にしたいというメッセージが表示されるアプリを検討してください。
この戦略では、ドキュメントのowner_id
フィールドがユーザーの ID と等しい場合にのみ、ユーザーはドキュメントを作成および編集できます。
「独自データの読み取りと書込み」戦略を設定するには、一般的な手順に従います。
Realm UI にログインし、左側のパネルにある [ Syncをクリックします。
Sync Typeで [ Flexibleを選択します。
[] トグルを設定して、 Development Modeを有効にします。
同期するクラスターを選択します。
Define a Database Name: +Add a new databaseを選択し、Realm が同期されたオブジェクトを保存するために使用するデータベースの名前を入力します。 任意の名前を付けることができます。 作成するアプリにちなんでデータベースに名前を付けるのが一般的な戦略です。
Select Queryable Fields:
owner_id
の 型。 これにより、権限式(次に設定する式)で、owner_id
と呼ばれる任意のフィールドを使用できるようになります。Advanced Configurationをスキップし、 Save Changesをクリックして同期を有効にします。
次に、権限を構成する必要があります。 Rulesページに移動します。 デフォルトロールを編集するには、 Default Roles and Filtersボタンをクリックします。 テンプレートのドロップダウンを使用して、「ユーザーは自分のデータの読み取りと書込みのみが可能」というテンプレートを選択します。
これにより、ルール式ボックスに次の内容が入力されます。
{ "name": "owner-read-write", "apply_when": {}, "document_filters": { "read": { "owner_id": "%%user.id" }, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true }
document_filters.read
式とdocument_filters.write
式は、上記で「クエリ可能」としてマークしたowner_id
フィールドを使用していることに注意してください。 また、リクエスト元のユーザーの ID を読み取るために、 %%user
展開を使用します。 App Services は、評価時に展開を対応する値(この場合は ユーザー オブジェクト)に置き換えます(または「拡張」)。
特定のドキュメントに対する権限を評価する場合、App Services は対応する最上位のread
またはwrite
式の前に、 document_filters.read
とdocument_filters.write
をチェックします。 たとえば、 document_filters.write
が false と評価すると、書込みアクセスは拒否されます。後続のルールはチェックされません。 ただし、 document_filters.write
が true と評価された場合、App Services は最上位のwrite
式をチェックします。 この場合、 write
はtrue
であるため、ドキュメント全体に書込みアクセスが付与されます。 詳細については、「 Device Sync 互換の権限 」を参照してください。
自分のデータを書込み、すべてのデータを読み取り
この場合、ユーザーはすべてのデータを読み取ることができますが、自分のデータのみを書き込みます。 ユーザーがすべてのレシピを読み、新しいレシピを追加できるレシピアプリを検討してください。 追加されたレシピは、アプリを使っているすべてのユーザーが表示できます。 ユーザーは、自分が提供したレシピのみを更新または削除できます。
「独自のデータを書き込み、すべてのデータを読み取り」戦略を設定するには、次の一般的な手順に従います。
Realm UI にログインし、左側のパネルにある [ Sync ] をクリックします。
Sync Typeで [ Flexibleを選択します。
[] トグルを設定して、 Development Modeを有効にします。
同期するクラスターを選択します。
Define a Database Name: +Add a new databaseを選択し、Realm が同期されたオブジェクトを保存するために使用するデータベースの名前を入力します。 任意の名前を付けることができます。 作成するアプリにちなんでデータベースに名前を付けるのが一般的な戦略です。
Select Queryable Fields:
owner_id
の 型。 これにより、権限式(次に設定する式)で、owner_id
と呼ばれる任意のフィールドを使用できるようになります。Advanced Configurationをスキップし、 Save Changesをクリックして同期を有効にします。
次に、権限を構成する必要があります。 Rulesページに移動します。 デフォルトロールを編集するには、 Default Roles and Filtersボタンをクリックします。 テンプレート ドロップダウンを使用して、「ユーザーはすべてのデータを読み取ることができますが、自分のデータのみを書き込みます」というテンプレートを選択します。
これにより、ルール式ボックスに次の内容が入力されます。
{ "name": "owner-write", "apply_when": {}, "document_filters": { "read": true, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true }
document_filters.read
式はtrue
に設定されていることに注意してください。これは、どのユーザーが認証されているかに関係なく、すべてのデータを読み取ることができることを示しています。 document_filters.write
式は、上記で「クエリ可能」としてマークしたowner_id
フィールドを使用し、 %%user
展開を使用してリクエスト元のユーザーの ID と照合します。 Atlas App Services は、評価時に展開を対応する値(この場合は ユーザー オブジェクト)に置き換えます(「拡張」)。
により、 document_filters.write
が true と評価された場合にのみ、App Services は最上位のwrite
式をチェックします。 document_filters.write
が false と評価されると、最上位のwrite
式がどのように表示されても、書込みアクセスが拒否されます。 詳細については、「 Device Sync 互換の権限 」を参照してください。
管理者の特権
この権限戦略では、特定の「管理者」ロールを持つユーザーは任意のドキュメントの読み取りと書込みができます。 指定されたロールを持たないユーザーは、自分のデータの読み取りと書込みのみが可能になります。 この戦略を機能させるには、まず、管理者権限を持つユーザーを定義する必要があります。
Atlas App を使用すると、クラスター内のカスタム ユーザー データをアプリケーション ユーザーに関連付けることができます。 この機能を使用すると、ユーザーに管理特権があるかどうかを示す フィールドを持つドキュメントを作成できます。 これを設定する方法はさまざまありますが、1 つの方法は、 isGlobalAdmin
というブール値プロパティを追加することです。これは、昇格された権限を持つユーザーに対してtrue
に設定されます。 もう 1 つは、 role
という string フィールドを作成することです。ここでは、期待値の 1 つが「admin」である可能性があります。
次の例では、作成するカスタム ユーザー オブジェクトには、ユーザーの ID に対応する_id
フィールドと、 firstName
、 lastName
、 isGlobalAdmin
の 3 つの追加フィールドがあります。
{ "_id" : "1234", "firstName": "Lily", "lastName": "Realmster", "isGlobalAdmin": true }
注意
権限にカスタム ユーザー データを使用する場合は、クライアントがカスタム ユーザー データ オブジェクトを書込み (write) を許可しないでください。 そうすると、すべてのユーザーが自分自身に任意の権限を付与できるようになります。 代わりに、サーバー側でシステム関数を使用してカスタムユーザーデータオブジェクトをアップデートします。
カスタムユーザーデータの有効化と構成
Atlas App Services は、カスタム ユーザー データに対応する MongoDB ドキュメントをリンクされた MongoDB Atlas クラスターに保存します。 アプリケーションにカスタム ユーザー データを構成するときは、クラスター、データベース、コレクション、および最後に ユーザー ID フィールドを指定します。このフィールドは、カスタム ユーザー データ ドキュメントを認証されたユーザーの ID にマッピングします。
Atlas App Services UI でカスタム ユーザー データを有効にするには、次の手順に従います。
左側のパネルで [ App Users ] をクリックします。
[ User Settingsタブを選択し、 Custom User Dataセクションを見つけます。
Enable Custom User Data トグルを On に設定します。
次の値を指定します。
Cluster Name: カスタムユーザーデータデータベースを含むリンクされた MongoDB クラスターの名前。
Database Name: カスタム ユーザー データ コレクションを含む MongoDB database の名前。
Collection Name: カスタム ユーザー データが含まれる MongoDB コレクションの名前。
ユーザー ID フィールドを指定します。 カスタム ユーザー データ コレクション内のすべてのドキュメントには、特定のユーザーにマップするフィールドが必要です。 フィールドはユーザーにマッピングするすべてのドキュメントに存在する必要があり、ユーザーの IDが string として含まれている必要があります。 標準の
_id
フィールドを使用してユーザー ID を保存することを推奨します。 MongoDB は自動的に_id
フィールドに制約を適用し、一意性を確保します。注意
このコレクション内の 2 つのドキュメントに同じユーザー ID 値が含まれている場合、App Services は一致する最初のドキュメントを使用するため、予期しない結果が発生します。
変更を保存して配置します。
注意
カスタム ユーザー データを更新した後に同期セッションを再起動する
同期サーバーはセッション中にカスタムユーザー データをキャッシュします。 そのため、書込みエラーを回避するには、カスタム ユーザー データを更新した後に同期セッションを再起動する必要があります。 同期セッションを再開するには、クライアント アプリケーションで開いているすべての同期セッションを一時停止して再開します。 クライアント SDK からの同期の一時停止と再開の詳細については、希望 SDK を参照してください。
管理者特権を設定する
カスタム ユーザー データを有効にしたら、 管理者特権 戦略を実装できます。 これを行うには、次の一般的な手順に従います。
Realm UI にログインし、左側のパネルにある [ Sync ] をクリックします。
Sync Typeで [ Flexibleを選択します。
[] トグルを設定して、 Development Modeを有効にします。
同期するクラスターを選択します。
Define a Database Name: +Add a new databaseを選択し、Realm が同期されたオブジェクトを保存するために使用するデータベースの名前を入力します。 任意の名前を付けることができます。 作成するアプリにちなんでデータベースに名前を付けるのが一般的な戦略です。
Select Queryable Fields:
owner_id
の 型。 これにより、権限式(次に設定する式)で、owner_id
と呼ばれる任意のフィールドを使用できるようになります。Advanced Configurationをスキップし、 Save Changesをクリックして同期を有効にします。
次に、権限を構成する必要があります。 Rulesページに移動します。 デフォルトロールを編集するには、 Default Roles and Filtersボタンをクリックします。 テンプレート ドロップダウンを使用して、「ユーザーは自分のデータを読み取りと書込みができ、管理者はすべてのデータの読み取りと書込みが可能」というテンプレートを選択します。
これにより、ルール式ボックスに次の内容が入力されます。
[ { "name": "admin", "apply_when": { "%%user.custom_data.isGlobalAdmin": true }, "document_filters": { "read": true, "write": true }, "read": true, "write": true }, { "name": "user", "apply_when": {}, "document_filters": { "read": { "owner_id": "%%user.id" }, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true } ]
注意
デフォルト設定の変更
この構成には 2 つのデフォルト ロールがあります。 最初の は、管理者の権限を定義します。 自動生成された式では、カスタム ユーザー データ ドキュメントにisGlobalAdmin
という名前のブール値フィールドがあることを前提としていることに注意してください。 カスタム ユーザー データ ドキュメントの定義方法によっては、これを変更する必要がある場合があります。
2 番目のデフォルトのロールは、他のすべてのユーザーに対する ルールを指定します。 デフォルトでは、ユーザーのアクセスは自分のデータのみの読み取りと書込みに制限されています。 これらのフィールドのいずれかまたは両方をtrue
に変更すると、ユーザーはすべてのデータを読み書きできるようになります。 これらの戦略の詳細については、前のセクションを参照してください。
制限付きニュースフィード
注意
テンプレートが利用可能です。
バックエンド テンプレートを使用し、デモ クライアントを取得するには、次のコマンドを実行します。
appservices apps create --name=restricted-feed --template=flex-sync-guides.restricted-feed
カスタム ユーザー データ構成バグの回避策:テンプレート ジェネレーターがカスタム ユーザー データ構成を新しいアプリに正しくコピーしない場合があります。 これは次のように修正します。 appservices apps create
コマンドは、作成したアプリに関するいくつかの JSON を出力します。 このJSONから、「 URL 」の値(https://services.cloud.mongodb.com/groups/...
など)をコピーし、ブラウザでそのURLにアクセスします。 ログインするプロンプトが表示されたら、ログインします。 アプリ ダッシュボードから、左側のパネルで [ App Users ] をクリックします。 [ Custom
User Dataをクリックします。 Enable Custom User DataがON
であることを確認します。 オンになっていない場合はオンにし、 Cluster Name 、 Database Name 、 Collection
Nameにそれぞれ "mongodb-atlas"、"Item"、"User" を入力します。 User ID Fieldに_id
を入力します。 Saveを使用します(またはSave Draftを使用し、 を配置)。
次に、ターミナルで、クライアント ディレクトリにGoし、依存関係をインストールして、デモを実行します。
cd restricted-feed/frontend/flex-sync-guides.restricted-feed/ npm install npm run demo
コンソールの出力を読みて、デモがどのように動作しているかを確認します。
この権限戦略では、ユーザーは自分のコンテンツを作成し、他の作成者のコンテンツをサブスクライブできます。 管理特権 シナリオと同様に、 カスタム ユーザー データ コレクションを使用して、ユーザーが読み取るサブスクライブ
Flexible Device Sync は配列のクエリをサポートしているため、ユーザー データ オブジェクト内に配列を作成します。 この配列には、このユーザーが「追跡」する権限を持つ著者の ID が含まれています。 ID 、基本的に「 」、または「
重要
ユーザーが著者からサブスクライブまたはサブスクライブを解除すると、カスタムユーザーデータの配列がアップデートされますが、現在のセッションが閉じられ、新しいセッションが開始されるまで変更は有効になりません。
注意
サイズ制限
この例では、カスタム ユーザー データに配列を作成しています。 この配列のサイズは App Services によって制限されませんが、各リクエストにデータが含まれるため、サイズを 16 KB 未満に保つことをお勧めします。これは 1000 個の GUID 形式のユーザー ID に十分なスペースです。
注意
権限にカスタム ユーザー データを使用する場合は、クライアントがカスタム ユーザー データ オブジェクトを書込み (write) を許可しないでください。 そうすると、すべてのユーザーが自分自身に任意の権限を付与できるようになります。 代わりに、サーバー側でシステム関数を使用してカスタムユーザーデータオブジェクトをアップデートします。
カスタムユーザーデータの有効化と構成
Atlas App Services UI でカスタム ユーザー データを有効にするには、次の手順に従います。
左側のパネルで [ App Users ] をクリックします。
[ User Settingsタブを選択し、 Custom User Dataセクションを見つけます。
Enable Custom User Data トグルを On に設定します。
次の値を指定します。
Cluster Name: カスタムユーザーデータデータベースを含むリンクされた MongoDB クラスターの名前。
Database Name: カスタム ユーザー データ コレクションを含む MongoDB database の名前。
Collection Name: カスタム ユーザー データが含まれる MongoDB コレクションの名前。
ユーザー ID フィールドを指定します。 カスタム ユーザー データ コレクション内のすべてのドキュメントには、特定のユーザーにマップするフィールドが必要です。 フィールドはユーザーにマッピングするすべてのドキュメントに存在する必要があり、ユーザーの IDが string として含まれている必要があります。 標準の
_id
フィールドを使用してユーザー ID を保存することを推奨します。 MongoDB は自動的に_id
フィールドに制約を適用し、一意性を確保します。注意
このコレクション内の 2 つのドキュメントに同じユーザー ID 値が含まれている場合、App Services は一致する最初のドキュメントを使用するため、予期しない結果が発生します。
変更を保存して配置します。
注意
カスタム ユーザー データを更新した後に同期セッションを再起動する
同期サーバーはセッション中にカスタムユーザー データをキャッシュします。 そのため、書込みエラーを回避するには、カスタム ユーザー データを更新した後に同期セッションを再起動する必要があります。 同期セッションを再開するには、クライアント アプリケーションで開いているすべての同期セッションを一時停止して再開します。 クライアント SDK からの同期の一時停止と再開の詳細については、希望 SDK を参照してください。
認証trigger関数の作成
ユーザーが初めて認証するときにカスタム ユーザー オブジェクトを作成する認証trigger関数を作成する必要があります。 これを行うには、次の手順に従います。
Realm UI にログインし、左側のパネルにある [ Triggers ] をクリックします。
Add a Triggerボタンをクリックします。
Trigger Type トグルを Authentication に設定します。
[ trigger の詳細 ] で、次の値を指定します。
Name: "onUserCreed"
Enbaled: トグルを「オン」に切り替え
Action Type: 「作成」を選択します
Provider(s): [メール/パスワード] または使用している認証プロバイダを選択します
Select an Event Type: 「関数」を選択します
Function: "+New Function" を選択し、その後を行います。
Function Name: "onUserCreed"
Function: プレースホルダー テキストを次の関数で置き換えます。
exports = function(authEvent) { const user = authEvent.user; const collection = context.services.get("mongodb-atlas").db("Item").collection("User"); const newDoc = { _id: user.id, email: user.data.email, // Useful for looking up user IDs by email later - assuming email/password auth is used team: "", // Used for tiered privileges isTeamAdmin: false, // Used for tiered privileges isGlobalAdmin: false, // Used for admin privileges subscribedTo: [], // Used for restricted feed }; return collection.insertOne(newDoc); };
制限された権限を設定する
カスタム ユーザー データ オブジェクト内に、ユーザーが追跡している各著者の _id 値を保持する 配列を作成します。 この例では、それを「subscriptions」と呼びます。ユーザー データ オブジェクトは次のようになります。ここで、リリー リアルタイム( "_id": "1234"
)は、ユーザー "456" と "789" が作成したすべてのドキュメントをサブスクライブしています。
{ "_id" : "1234", "firstName": "Lily", "lastName": "Realmster", "user.custom_data.subscribedTo": [ "456", "789" ] }
制限された特権戦略を実装できるようになりました。 これを行うには、次の一般的な手順に従います。
Realm UI にログインし、左側のパネルにある [ Sync ] をクリックします。
Sync Typeで [ Flexibleを選択します。
[] トグルを設定して、 Development Modeを有効にします。
同期するクラスターを選択します。
Define a Database Name: +Add a new databaseを選択し、Realm が同期されたオブジェクトを保存するために使用するデータベースの名前を入力します。 任意の名前を付けることができます。 作成するアプリにちなんでデータベースに名前を付けるのが一般的な戦略です。
Select Queryable Fields:
owner_id
の 型。 これにより、権限式(次に設定する式)で、owner_id
と呼ばれる任意のフィールドを使用できるようになります。Advanced Configurationをスキップし、 Save Changesをクリックして同期を有効にします。
次に、権限を構成する必要があります。 Rulesページに移動します。 デフォルトロールを編集するには、 Default Roles and Filtersボタンをクリックします。 テンプレートのドロップダウンを使用して、「ユーザーは自分のデータの読み取りと書込みのみが可能」というテンプレートを選択します。 これにより、ルール式ボックスには次の内容が入力されます。これは正確には 必要ではありません が、ほとんどのロジックは提供されます。
{ "name": "owner-read-write", "apply_when": {}, "document_filters": { "read": { "owner_id": "%%user.id" }, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true }
ユーザーは現在、自分のドキュメントのみを読み取ることができることに注意してください( "read":
{"owner_id": "%%user.id"}
)。 これを変更して、著者が ID を持つドキュメントをユーザーの "subscribeTo" 配列に含めることができます。 そのためには、 $in
演算子を使用します。 式は次のようになります。
{ "name": "owner-read-write", "apply_when": {}, "document_filters": { "read": { "owner_id": { "$in": "%%user.custom_data.subscribedTo" } }, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true }
この新しいロジックでルール式ボックスを更新し、変更を保存します。
注: document_filters.read
式を変更して、subscriptedTo 配列の作成者のみを指定しましたが、 document_filters.read
式により、ユーザーは引き続き自分のドキュメントに「読み取り」アクセス権を持ちます。 書込みアクセスが付与されるたびに、読み取りアクセス権が暗黙的に付与されます。
preserveToUser 関数の作成
あるユーザーを別のユーザーにサブスクライブする関数が必要です。 著者のユーザー ID がサブスクライブのカスタムユーザーデータ「subscribeTo」配列にある場合、サブスクライブは著者に「サブスクライブ」されたと見なす権限が設定されています。 "subscribeToUser" 関数は、ユーザーのメールアドレスを受け取り、カスタムユーザーデータコレクションから対応するユーザー ID を検索し、その ID をリクエスト元ユーザーの "subscribeTo" 配列に追加します。
この関数はシステム認証の下で実行され、カスタム ユーザー データに書込まれることに注意してください。 権限にカスタム ユーザー データを使用する場合、クライアントがカスタム ユーザー データを直接編集できるようにしてはなりません。 それ以外の場合、すべてのユーザーが自分自身に任意の権限を付与できます。 代わりに、 System 関数を使用してバックエンド上のユーザー データを変更します。 この関数は、ユーザーの権限リクエストが有効であることを確認するために必要なチェックを行います。
関数を作成するには、次の手順に従います。
Realm UI にログインし、左側のパネルにある [ Functions ] をクリックします。
Create New Functionボタンをクリックします。
次の値を指定します。
Name: "subscribeToUser"
Authentication: "システム"
Function Editorタブに切り替え、プレースホルダー テキストを次のコードで置き換えます。
exports = async function(email) { const collection = context.services.get("mongodb-atlas").db("Item").collection("User"); // Look up the author object to get the user id from an email const author = await collection.findOne({email}); if (author == null) { return {error: `Author ${email} not found`}; } // Whoever called this function is the would-be subscriber const subscriber = context.user; try { return await collection.updateOne( {_id: subscriber.id}, {$addToSet: { subscribedTo: author._id, } }); } catch (error) { return {error: error.toString()}; } };
動的連携
注意
テンプレートが利用可能です。
バックエンド テンプレートを使用し、デモ クライアントを取得するには、次のコマンドを実行します。
appservices apps create --name=add-collaborators --template=flex-sync-guides.add-collaborators
次に、クライアント ディレクトリにGoし、依存関係をインストールし、デモを実行します。
cd add-collaborators/frontend/flex-sync-guides.add-collaborators/ npm install npm run demo
コンソールの出力を読みて、デモがどのように動作しているかを確認します。
動的連携戦略では、ユーザーはドキュメントを作成し、そのドキュメントのエディターとして他のユーザーを追加できます。
独自のデータの読み取りと書き込み 戦略と同様に、この戦略では、ドキュメントのowner_id
フィールドがユーザーの ID と等しい場合に、ユーザーがドキュメントを作成および編集できるようになります。 さらに、ドキュメントのcollaborators
配列フィールドに ID が含まれている場合、ユーザーはドキュメントを編集できるようになります。
権限を設定する
この戦略を実装するには、次の一般的な手順に従います。
Realm UI にログインし、左側のパネルにある [ Sync ] をクリックします。
Sync Typeで [ Flexibleを選択します。
[] トグルを設定して、 Development Modeを有効にします。
同期するクラスターを選択します。
Define a Database Name: +Add a new databaseを選択し、Realm が同期されたオブジェクトを保存するために使用するデータベースの名前を入力します。 任意の名前を付けることができます。 作成するアプリにちなんでデータベースに名前を付けるのが一般的な戦略です。
Select Queryable Fields:
owner_id
の 型。 これにより、権限式(次に設定する式)で、owner_id
と呼ばれる任意のフィールドを使用できるようになります。Advanced Configurationをスキップし、 Save Changesをクリックして同期を有効にします。
Select Queryable Fieldsフィールドに、 collaborators
も入力します。 これは、ドキュメントの読み取りと書込みも可能なユーザーの ID を保存する フィールドになります。
次に、権限を構成する必要があります。 Define Permissionsの下で、テンプレートのドロップダウンを使用して「カスタム(最初から開始)」を選択します。 以下をルール式ボックスに貼り付けます。
{ "name": "collaborator", "apply_when": {}, "document_filters": { "read": { "$or": [ { "owner_id": "%%user.id" }, { "collaborators": "%%user.id" } ] }, "write": { "$or": [ { "owner_id": "%%user.id" }, { "collaborators": "%%user.id" } ] } }, "read": true, "write": true }
"write" 式と "read" 式は同一です。 それらの 1 つを調べてください。 $or
は、オプションの配列を取ります。 ユーザーがドキュメントを書込み (write) できる条件として、次の 2 つあります。
ドキュメントの
owner_id
フィールドはユーザーの ID と等しいドキュメントの
collaborators
配列フィールドにはユーザーの ID が含まれています。
一般的に、ユーザーに書込み権限が付与されると、そのユーザーには自動的に読み取り権限が付与されます。 ただし、App Services では同期互換性のあるロールにdocument_filters.read
とdocument_filters.write
の両方を定義する必要があるため、 document_filters.read
式を省略できません。
コレクターの追加
ユーザーは、ドキュメントのcollaborators
配列フィールドにそのユーザーの ID を追加することで、別のユーザーにドキュメントへの書込みアクセス権を付与できます。 これはクライアント側で実行できます。
セキュリティ
このモデルは機密性の高いデータには使用しないでください。
このモデルでは、権限システムを使用して、ドキュメント作成者とドキュメントに追加される照合者の間でドキュメントのプライベートを保ちます。 ただし、ドキュメントへの書込み (write) アクセス権を持つユーザーは、ドキュメントの任意のフィールドに書込むことができます。 結果、この戦略では、照合者は他の照合者を追加することができます。 また、コラボレーションにowner_id
フィールドの編集も許可されます。 同期の互換性の場合、フィールドレベルの権限はブール値のリテラルである必要があるため、これらのフィールドへの書込みを特定のユーザーに制限することはできません。
ユーザー検索
他のユーザーの ID をどのように取得するかは、アプリの詳細によって異なります。 たとえば、ユーザーがドキュメントに別のユーザーを追加したい場合、メールアドレスを受け入れる検索ボックスが利用できます。 指定されたメールアドレスが別のユーザーに対応する場合、クライアントはそのユーザーの ID をドキュメントのcollaborators
配列に追加できます。
Realm にはユーザーを検索するための組み込み方法はありません。 一般的に、ユーザーを検索するためのフローは次のようになります。
ユーザーが登録するときにユーザー ドキュメントを作成するように認証triggerを設定します。 ユーザー ドキュメントには、ユーザーのメールアドレスなど、後で検索するために使用する情報が含まれています。
ユーザーのユーザー データ コレクションをクエリする関数を作成します。
ユーザーが別のユーザーを検索する場合は、クライアント側から関数を呼び出します。
認証triggerを作成するには、次の手順に従います。
Realm UI にログインし、左側のパネルにある [ Triggers ] をクリックします。
Add a Triggerボタンをクリックします。
Trigger Type トグルを Authentication に設定します。
[ trigger の詳細 ] で、次の値を指定します。
Name: "onUserCreed"
Enbaled: トグルを「オン」に切り替え
Action Type: 「作成」を選択します
Provider(s): [メール/パスワード] または使用している認証プロバイダを選択します
Select an Event Type: 「関数」を選択します
Function: "+New Function" を選択し、その後を行います。
Function Name: "onUserCreed"
Function: プレースホルダー テキストを次の関数で置き換えます。
exports = function(authEvent) { const user = authEvent.user; const collection = context.services.get("mongodb-atlas").db("Item").collection("User"); const newDoc = { _id: user.id, email: user.data.email, // Useful for looking up user IDs by email later - assuming email/password auth is used team: "", // Used for tiered privileges isTeamAdmin: false, // Used for tiered privileges isGlobalAdmin: false, // Used for admin privileges subscribedTo: [], // Used for restricted feed }; return collection.insertOne(newDoc); };
次に、 findUser
というシステム関数を作成します。
RealmUI にログインし、Go RealmアプリにFunctions し、左側のパネルにある [ ] をクリックします。
Create New Functionボタンをクリックします。
関数にはわかりやすいNameを指定します。
Authentication: Systemを選択します。 これにより、関数はコレクションに対する権限をバイパスできます。
Log Function Arguments:
off
のままにします。Authorization:
Can Evaluate: 空白のままにします。
Private:
off
のままにします。
[ Saveをクリックします。 これによりFunction Editorが表示され、いくつかの値を入力して実行できるようになります。
警告
この構成により、誰でもこの関数を呼び出すことができます。 システム関数として、この関数はアクセス ルールをバイパスします。 この関数を呼び出すクライアントには悪意があると想定します。
Function Editorで、次のコードを貼り付けて保存します。
exports = async function(email) { const collection = context.services.get("mongodb-atlas") .db("Item").collection("User"); const filter = { email, }; // Search for the user by email const result = await collection.findOne(filter); // Return corresponding user id or null return result != null ? result._id : null; };
クライアントから、この関数を呼び出せるようになりました。 関数の唯一の引数はメールアドレス string です。 メールがユーザーに対応する場合、関数はユーザーの ID を返します。 それ以外の場合は、null が返されます。
階層型特権
注意
テンプレートが利用可能です。
バックエンド テンプレートを使用し、デモ クライアントを取得するには、次のコマンドを実行します。
appservices apps create --name=tiered --template=flex-sync-guides.tiered
カスタム ユーザー データ構成バグの回避策:テンプレート ジェネレーターがカスタム ユーザー データ構成を新しいアプリに正しくコピーしない場合があります。 これは次のように修正します。 appservices apps create
コマンドは、作成したアプリに関するいくつかの JSON を出力します。 このJSONから、「 URL 」の値(https://services.cloud.mongodb.com/groups/...
など)をコピーし、ブラウザでそのURLにアクセスします。 ログインするプロンプトが表示されたら、ログインします。 アプリ ダッシュボードから、左側のパネルで [ App Users ] をクリックします。 [ Custom
User Dataをクリックします。 Enable Custom User DataがON
であることを確認します。 オンになっていない場合はオンにし、 Cluster Name 、 Database Name 、 Collection
Nameにそれぞれ "mongodb-atlas"、"Item"、"User" を入力します。 User ID Fieldに_id
を入力します。 Saveを使用します(またはSave Draftを使用し、 を配置)。
次に、ターミナルで、クライアント ディレクトリにGoし、依存関係をインストールして、デモを実行します。
cd tiered/frontend/flex-sync-guides.tiered/ npm install npm run demo
コンソールの出力を読みて、デモがどのように動作しているかを確認します。
この権限戦略では、ルールと特別なロールを追加します。 チーム メンバーとチーム管理者の 2 つのロールがあります。 ルールは次のとおりです。
各ユーザーはチームのメンバーです。
ユーザーは自分のドキュメントを読み書きできます。
チームの全メンバーは、チーム メンバーが作成したすべてのドキュメントを読み取ることができます。
各チームには、すべてのチーム ドキュメントに対する読み取りおよび書込み権限を持つチーム管理者がいます。
これを機能させるには、次の操作を行う必要があります。
カスタムユーザーデータの有効化
trigger関数を作成して、新しいユーザーごとに新しいカスタム ユーザー データ オブジェクトを作成する
チームにユーザーを追加するための関数を作成する
権限を定義する
注意
権限にカスタム ユーザー データを使用する場合は、クライアントがカスタム ユーザー データ オブジェクトを書込み (write) を許可しないでください。 そうすると、すべてのユーザーが自分自身に任意の権限を付与できるようになります。 代わりに、サーバー側でシステム関数を使用してカスタムユーザーデータオブジェクトをアップデートします。
カスタムユーザーデータの有効化と構成
Atlas App Services UI でカスタム ユーザー データを有効にするには、次の手順に従います。
左側のパネルで [ App Users ] をクリックします。
[ User Settingsタブを選択し、 Custom User Dataセクションを見つけます。
Enable Custom User Data トグルを On に設定します。
次の値を指定します。
Cluster Name: カスタムユーザーデータデータベースを含むリンクされた MongoDB クラスターの名前。
Database Name: カスタム ユーザー データ コレクションを含む MongoDB database の名前。
Collection Name: カスタム ユーザー データが含まれる MongoDB コレクションの名前。
ユーザー ID フィールドを指定します。 カスタム ユーザー データ コレクション内のすべてのドキュメントには、特定のユーザーにマップするフィールドが必要です。 フィールドはユーザーにマッピングするすべてのドキュメントに存在する必要があり、ユーザーの IDが string として含まれている必要があります。 標準の
_id
フィールドを使用してユーザー ID を保存することを推奨します。 MongoDB は自動的に_id
フィールドに制約を適用し、一意性を確保します。注意
このコレクション内の 2 つのドキュメントに同じユーザー ID 値が含まれている場合、App Services は一致する最初のドキュメントを使用するため、予期しない結果が発生します。
変更を保存して配置します。
注意
カスタム ユーザー データを更新した後に同期セッションを再起動する
同期サーバーはセッション中にカスタムユーザー データをキャッシュします。 そのため、書込みエラーを回避するには、カスタム ユーザー データを更新した後に同期セッションを再起動する必要があります。 同期セッションを再開するには、クライアント アプリケーションで開いているすべての同期セッションを一時停止して再開します。 クライアント SDK からの同期の一時停止と再開の詳細については、希望 SDK を参照してください。
認証trigger関数の作成
ユーザーが初めて認証するときにカスタム ユーザー オブジェクトを作成する認証trigger関数を作成する必要があります。 これを行うには、次の手順に従います。
Realm UI にログインし、左側のパネルにある [ Triggers ] をクリックします。
Add a Triggerボタンをクリックします。
Trigger Type トグルを Authentication に設定します。
[ trigger の詳細 ] で、次の値を指定します。
Name: "onUserCreed"
Enbaled: トグルを「オン」に切り替え
Action Type: 「作成」を選択します
Provider(s): [メール/パスワード] または使用している認証プロバイダを選択します
Select an Event Type: 「関数」を選択します
Function: "+New Function" を選択し、その後を行います。
Function Name: "onUserCreed"
Function: プレースホルダー テキストを次の関数で置き換えます。
exports = function(authEvent) { const user = authEvent.user; const collection = context.services.get("mongodb-atlas").db("Item").collection("User"); const newDoc = { _id: user.id, email: user.data.email, // Useful for looking up user IDs by email later - assuming email/password auth is used team: "", // Used for tiered privileges isTeamAdmin: false, // Used for tiered privileges isGlobalAdmin: false, // Used for admin privileges subscribedTo: [], // Used for restricted feed }; return collection.insertOne(newDoc); };
joinTeam 関数の作成
チームにユーザーを追加する関数が必要になりました。 この関数はシステム認証の下で実行され、カスタム ユーザー データに書込まれることに注意してください。 ユーザーが初めて正常に認証されたときにユーザー カスタム データが作成されたため、アップサートは実行されません。
関数を作成するには、次の手順に従います。
Realm UI にログインし、左側のパネルにある [ Functions ] をクリックします。
Create New Functionボタンをクリックします。
次の値を指定します。
Name: "joinTeam"
Authentication: "システム"
Function Editorタブに切り替え、プレースホルダー テキストを次のコードで置き換えます。
exports = async function(userId, teamName) { const collection = context.services.get("mongodb-atlas") .db("Item").collection("User"); const filter = { _id: userId }; const update = { $set: { team: teamName }}; const options = { upsert: false }; return collection.updateOne(filter, update, options); };
権限を定義する
次の権限では 2 つのロールを指定します。
teamAdminは、ユーザーのカスタム データが
isTeamAdmin: true
の場合にのみ適用されます。 その場合、ユーザーはドキュメントのteam
値がユーザーのteam
値と一致するすべてのドキュメントの読み取りと書き込みができます。teamMeaverはすべてのユーザーに適用されます。 ユーザーは自分のドキュメントを作成し、ドキュメントの
team
値がユーザーのteam
値と一致するすべてのドキュメントを読み取ることができます。
[ { "name": "admin", "apply_when": { "%%user.custom_data.isTeamAdmin": true }, "document_filter": { "read": { "team": "%%user.custom_data.team" }, "write": { "team": "%%user.custom_data.team" } }, "read": true, "write": true }, { "name": "user", "apply_when": {}, "document_filters": { "read": { "team": "%%user.custom_data.team" }, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true } ]
注意
さらに先へ進む
この戦略は、" globalAdmin" ロールをサポートするように拡張できます。 グローバル管理者には、任意のチームで作成されたドキュメントに対する読み取りおよび読み取り権限が付与されます。