Salesforce のデータアクセス

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)



+ [レコードアクセス権に関連して Salesforce 内部で実行される処理](https://developer.salesforce.com/docs/atlas.ja-jp.244.0.salesforce_record_access_under_the_hood.meta/salesforce_record_access_under_the_hood/uth_preface.htm)

アーキテクトの観点からみると、Salesforce のデータアクセスは、オブジェクトレベルのアクセス権 (項目レベルのアクセス権を含む) とレコードレベルのアクセス権の 2 つに大別されます。

オブジェクトレベルのアクセス権は、ユーザが特定のオブジェクトにアクセスできるかどうか、そのオブジェクトのどの項目を表示できるか、どのアクションを実行できるかを決定します。オブジェクトレベルのアクセス権はユーザプロファイルで設定します。

**アクセスの制限**
「参照」、「作成」、「編集」、および「削除」のオブジェクト権限は、ユーザがアクセス権を持つオブジェクトのレコードでどのアクションを実行できるかを決定します。項目レベルセキュリティでは、特定のユーザに対して、表示されるレコードに含まれる部外秘または機密の情報を非表示にすることができます。

**アクセス権の開放**
「すべて表示」および「すべて変更」オブジェクト権限を使用すると、ユーザが、レコードレベルのアクセス権に関係なく、オブジェクトの全レコードにアクセスできます。

レコードレベルのアクセス権 (Salesforce では「共有」という) は、次のツールを使用して、ユーザが特定のオブジェクトのどのレコードを表示できるかを決定します。

+ 組織の共有設定
+ ロール階層
+ テリトリー階層
+ 共有ルール
+ チーム
+ 共有の直接設定
+ プログラムによる共有

# レコードアクセス権の計算

ユーザがユーザインターフェースまたは API を使用して、レコードを開こうとしたり、レポートを実行しようとしたり、リストビューにアクセスしようとしたり、データを検索しようとしたりするたびに、Salesforce により、ユーザがアクセスできるレコードを判別するためにレコードアクセス機能の設定がチェックされます。特に何百もの階層ノード、何千もの共有ルール、何百万ものデータ行、および顧客やビジネスパートナー用のポータルがある大規模な組織の場合、これらの設定が複雑になっている可能性があります。そのような異種データや複雑なリレーションを処理する場合、ページを表示するのに 300 ミリ秒 (Salesforce ベンチマーク) をはるかに超える時間が必要になります。

Salesforce では、各共有ルールの適用、すべての階層のトラバース、レコードアクセス権の継承の分析をリアルタイムで行うのではなく、設定の変更が発生した場合にのみレコードアクセスデータを計算します。計算結果は、迅速なスキャンを容易にし、実行時にアクセスできるレコードを判別するために必要なデータベーステーブル結合数を最小化するような方法で保持されます。

# アクセス権の付与

オブジェクトに組織の共有設定として [非公開] または [公開/参照のみ] が設定されている場合、Salesforce では、アクセス権の付与によって、ユーザまたはグループがそのオブジェクトのレコードにどの程度アクセスできるかを定義します。各アクセス付与によって、特定のレコードに対するアクセス権が、特定のユーザまたはグループに付与されます。また、そのアクセス権の付与に使用する共有ツールの種類 (共有ルール、チームなど) も記録されます。Salesforce では、明示的付与、グループメンバーシップの付与、継承による付与、暗黙的付与の 4 種類のアクセス付与を使用します。

**明示的付与**

Salesforce は、レコードがユーザまたはグループと直接共有される場合に明示的付与を使用します。Salesforce が明示的付与を使用するのは、具体的に次の場合です。

+ ユーザまたはキューがレコードの所有者になる。
+ 共有ルールが、非公開グループ、公開グループ、キュー、ロール、またはテリトリーとレコードを共有している。
+ 割り当てルールが、ユーザまたはキューとレコードを共有している。
+ テリトリー割り当てルールが、テリトリーとレコードを共有している。
+ ユーザが、ユーザ、非公開グループ、公開グループ、キュー、ロール、またはテリトリーとレコードを手動で共有している。
+ ユーザが、取引先、商談、またはケースのチームの一員になる。
+ プログラムを使用するカスタマイズで、ユーザ、非公開グループ、公開グループ、キュー、ロール、またはテリトリーとレコードを共有している。


**グループの種類**

ここで、salesforce に存在するさまざまな種類のグループと、それらがグループ保守テーブルにどのように保存されるかを理解しましょう。以下に示すように、グループには 2 種類があります。

ユーザーによって作成され、以下で構成されるユーザー定義グループ。
+ 公開グループ
+ プライベートグループ

システム定義のグループ。Role グループ、RoleAndSubowned グループ、RoleAndInternalSubowned グループで構成されます。外部 OWD が有効な場合は、RoleAndInternalSubowned が使用されます。これらは以下に基づいています。
+ 役割の階層
+ テリトリー階層
+ キュー


**グループメンバーシップの付与**

ユーザ、公開グループ、非公開グループ、キュー、ロール、またはテリトリーが、レコードへの明示的アクセス権を持つグループのメンバーである場合に行われる付与です。たとえば、共有ルールによって Acme レコードへのアクセス権が「Strategy」というグループに明示的に付与され、Bob がそのグループのメンバーである場合、Bob の Strategy グループのメンバーシップによって、Acme レコードへのアクセス権が Bob に付与されます。


**継承による付与**

ユーザ、公開グループ、非公開グループ、キュー、ロール、またはテリトリーが、ロールまたはテリトリー階層に従ってアクセス権を継承するか、グループ階層に従ってアクセス権を継承するグループのメンバーである場合に行われる付与です。

**暗黙的付与**

Salesforce のセールス、サービス、およびポータルのアプリケーション内に組み込まれた、設定不可能なレコード共有動作によって、特定の親レコードと子レコードへのアクセス権が付与される場合に行われる付与です。たとえば、組み込みの共有と呼ばれることもあるこのデフォルトロジックを使用して、ユーザは、親取引先レコードを、その子である商談、ケース、または取引先責任者のレコードへのアクセス権を持っている場合に表示できます。これらのユーザが親取引先レコードへのアクセス権を持っている場合、その子である商談、ケース、および取引先責任者レコードにもアクセスできます。


パフォーマンスを向上するには、リリース更新を使用して取引先の共有再適用の高速化を有効にすることをお勧めします。取引先とその子のケースおよび取引先責任者レコードの間で暗黙的な共有レコードを保存する代わりに、ユーザがこれらのケースおよび取引先責任者レコードにアクセスするときに、ユーザがそれらのレコードにアクセスできるかどうかがシステムによって動的に判断されます。詳細は、「[取引先の共有再適用の高速化](https://help.salesforce.com/s/articleView?id=000394638&type=1&language=ja)」ナレッジ記事を参照してください。

# データベースアーキテクチャ

Salesforce では、3 種類のテーブルにアクセス権が保存されます。

**Object Record テーブル**

特定のオブジェクトのレコードが保存されるテーブルで、各レコードを所有するユーザ、グループ、またはキューを示します。


**Object Sharing テーブル**

明示的または暗黙的な権限をサポートするデータが保存されるテーブル。次のいずれかの条件が true の場合を除き、組織のほとんどのオブジェクト (表示するには、[設定] から [クイック検索] に「共有設定」と入力して、[共有設定] を選択) は、それぞれが Object Sharing テーブルを取得します。

+ オブジェクトが主従関係の従オブジェクトである。主従関係がある場合、主オブジェクトのオブジェクト共有テーブルが従オブジェクトへのアクセスを制御します。
+ 組織のデフォルト設定 (社内外) がいずれも「公開/参照・更新可能」である。
+ オブジェクトが Object Sharing テーブルをサポートしない種別である (Activities や Files など)。これらのオブジェクトには独自のアクセス制御メカニズムがあります。

**Group Maintenance テーブル**

グループメンバーシップと継承されたアクセス権をサポートするデータが保存されるテーブル。たとえば、Object Sharing テーブルが Bob に Acme 取引先レコードへの明示的なアクセス権を付与した場合、Salesforce は、Group Maintenance テーブルをチェックして、Bob からレコードアクセス権を継承したユーザを確認し、ユーザに Acme レコードへのアクセス権を付与します。これらの付与は、グループ (またはロールあるいはテリトリー) メンバーシップ情報の作成または変更時にあらかじめ確定されます。

**Object Sharing テーブルには個人およびグループへのアクセス付与が保存されるのに対し、Group Maintenance テーブルにはグループメンバーシップを示す、各グループに属するユーザまたはグループのリストが保存されます。** どちらのタイプのテーブルも、ユーザがレポートまたはリストビューを検索、クエリ、またはプルアップする場合にそのユーザのデータへのアクセス権を判断するために使用されます。

ユーザが 1 つ以上のレコードを取得しようとすると、Salesforce は、Object Record テーブルでユーザの検索文字列に一致するレコードを検索する SQL ステートメントを生成します。レコードが存在する場合、Salesforce は、ステートメントに Object Record テーブルと Object Sharing テーブル、Object Sharing テーブルと Group Maintenance テーブルを結合する SQL を付加します。Salesforce は、結合されたテーブルで、クエリ実行ユーザにレコードへのアクセスを許可するアクセス権を照会します。

|結合するテーブル|Salesforce の一致基準|
|:--------------|:-------------------|
|Object Record と Object Sharing|レコード ID|
|Object Sharing と Group Maintenance|ユーザ ID またはグループ ID|

この図は、Salesforce の一致プロセスを順序に従って示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cb7c868b-ff53-b691-7c5c-28d0698b0d7e.png)


Salesforce は、付加した SQL を含め、ステートメント全体を満たすレコードのみを返します。ステートメントを満たすには、レコードが存在し、Object Sharing テーブルまたは Group Maintenance テーブルがクエリ実行ユーザにアクセス権を付与する必要があります。

オブジェクト共有テーブルとグループメンテナンステーブルの両方がアクセス権を付与することができますが、その方法は大きく異なります。

+ Object Sharing テーブルでは、単純に各アクセス権が共有行と呼ばれる個別の行に保存され、各共有行がユーザまたはグループに特定のレコードへのアクセス権を付与します。
+ グループメンテナンステーブルでは、1 つのグループメンバーシップまたは継承されたアクセス権によって、各ユーザおよびグループがレコードにアクセスする方法が複数存在するため、より複雑です。

# 共有行

各共有行には、次の情報が含まれます。

+ この行がアクセス権を付与するレコードの ID
+ この行がアクセス権を付与するユーザまたはグループの ID
+ この行が許可するアクセスレベル (参照のみ、フルアクセスなど)
+ Salesforce がユーザまたはグループにレコードへのアクセス権を付与する理由を示す共有理由

例 1
Sales Executive ロールの Maria が、「Acme」という企業の取引先レコード (ID=A1) を作成します。内部では、Salesforce が Account Sharing テーブル (Account オブジェクトの Object Sharing テーブル) にレコード所有者として Maria の共有行を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2c3e7c79-c55f-6f01-b4b8-80baf8eb2b3f.png)

例 2
Maria は Acme 取引先レコードを Services Executive の Frank と共有するよう直接設定します。内部では、Salesforce が Frank の共有行を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/08f32f84-5b64-7ceb-35cb-e4ba09fed1a2.png)

Acme の取引先レコードは 1 件のみですが、Account Sharing テーブルには、Acme レコード用に 2 つのエントリが含まれます。この更新は、Salesforce が Acme 取引先レコードへのアクセス権を 2 回 (所有者として Maria に 1 回、Frank に 1 回) 付与したために発生します。

例 3
システム管理者が、Sales Executive のレコードを Strategy グループと共有する共有ルールを作成し、Strategy グループに「参照のみ」アクセス権を付与します。内部では、Salesforce が、Strategy グループに Maria の Acme 取引先レコードへのアクセス権を付与する共有行を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/59e2e393-a9b9-0053-9585-f60ddd125636.png)

レコードへのアクセス権を複数持つユーザの場合、Salesforce は、レコードアクセス権を判定するときに最も権限の高い権限を使用します。たとえば、Frank が Strategy グループに参加した場合、Frank には例 2 で Maria から付与された「参照・更新」アクセス権もあります。

**複数のユーザのレコードアクセス要件が同じ場合、それらのユーザをグループにして、個人ではなくそのグループにアクセス権を付与すると効率的です。この方法では時間が節約され、結果的に共有行の数が少なくなるため、組織のレコードアクセスデータ量が削減されます。**

# サンプルシナリオ

シナリオ 1
Maria は、Acme の取引先レコード (A1) を作成します。内部では、Salesforce が Account Sharing テーブルに、Acme の新しい取引先レコードと、所有者として Maria の共有行を作成します。Marc のロール階層は Maria より上で、Marc は Maria の Sales Executive ロールグループの間接メンバーであるため、アクセス権を継承します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/7675822d-4cf2-cbef-897d-fa420cbd4599.png)

シナリオ 2
Maria は Acme の取引先レコードを Bob と共有するように直接設定します。内部では、Salesforce が Account Sharing テーブルに、Bob の共有行を作成します。Maria と Marc のロール階層は Bob より上で、Bob の East Sales Rep ロールグループの間接メンバーであるため、Maria と Marc はレコードへのアクセス権を持ちます。

レコード共有の直接設定、プログラムによるレコード共有の設定、およびチーム共有設定の場合、いずれも同様に Object Sharing テーブルに共有行が作成されますが、共有理由は異なります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c5f1275f-1b79-5ca2-da2f-7071fa622a66.png)

シナリオ 3
システム管理者は、Sales Executive のレコードを、Services Executive ロールとその下位のロールに含まれるユーザと共有する共有ルールを作成します。内部では、Salesforce が Services Executive ロールの RoleAndSubordinates グループの Account Sharing テーブルに共有行を作成し、Frank と Sam に Acme レコードへのアクセス権を与えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/68b64d75-8978-6a32-69f8-ca20eb676a54.png)


シナリオ 4
Maria は Acme のレコードの所有者を Wendy に変更します。レコードの所有者が変わると、Salesforce は所有者に関連付けられ、共有理由が直接設定となっている共有行を削除するため、Bob はそのレコードへのアクセス権を失います。また、Sales Executive である Maria はレコードを所有しなくなるため、シナリオ 3 のルールは適用されなくなります。内部では、Salesforce がシナリオ 3 で作成された Services Executive ロールの RoleAndSubordinates グループの共有行を削除するため、Frank と Sam は Acme レコードへのアクセス権を失います。また、Salesforce は、Account Sharing テーブルで Maria の名前を Wendy の名前に置き換えます。

図中で赤い楕円形で囲まれた部分は、所有者の変更によって影響を受ける項目です。この一見したところ軽微に見える変更ですが、多数の項目に影響が及ぶことがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f107e70d-4327-81a5-6ad8-869f687ff467.png)




-------------------------
+ [SALESFORCE レコード共有 – アクセス許可と共有テーブル](https://blog.gigminds.com/salesforce-record-sharing-access-grants-sharing-tables_1601157660000/)


# シナリオの補足

これを、経営幹部と営業担当者が CEO に直属する単純な役割階層で理解してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/742fc3f9-e6d2-a3e9-53f7-61cf9b61f3af.png)

以下に示すように、ジョンは役員であり、営業担当者であるメアリーは、会社の CEO であるアレックスの直属です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2dff74ef-ff90-ae46-62b3-676ebbf4dfff.png)

**オブジェクト レコード テーブルとオブジェクト共有テーブル** – John がオブジェクトのレコードを作成するたびに、すべてのレコードがオブジェクトの Record テーブルに保存され、レコード所有者としての John の共有行がそのオブジェクトのオブジェクト共有テーブルに作成されます。

例: ジョンが所有するすべてのアカウント レコードについて、アカウント オブジェクト テーブルにはレコードが保存され、アカウント共有テーブルにはジョンのユーザー ID、アカウント ID、アクセス許可を含むジョンのアクセス許可レコードが含まれます。

**レコード ID によるオブジェクト レコード テーブルとオブジェクト共有テーブルの結合** -

John がデータベースから取引先レコードを取得しようとするたびに、Salesforce はまずレコードが取引先オブジェクト テーブルに存在するかどうかを確認しようとします。アカウント レコード テーブルでアカウント レコード ID を見つけると、アカウント共有テーブルで ID を検索し、アクセス許可を取得します。

**ユーザー/グループ ID によるオブジェクト共有テーブルとグループ メンテナンス テーブルの結合** -

次に、Salesforce は、ジョンの ID を使用してオブジェクト共有テーブルをグループメンテナンステーブルと結合し、グループメンバーシップや継承されたアクセス許可などの複雑なアクセス許可を取得します。これは、ロール階層からジョンから継承しているユーザにアクセス権を与えるのに役立ちます。共有ルールなど

John がデータベースのレコードを参照するには、そのレコードが Account Object テーブルに存在し、オブジェクト共有テーブルまたはグループ メンテナンス テーブルのいずれかに John 用のアクセス許可が保存されている必要があります。

**グループメンテナンステーブル** –

ここで、ロール階層内のノードのグループ メンテナンス テーブルに作成されたロール グループとRoleAndSubowned グループを見てみましょう。階層の役割グループは次のように定義されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/29c0eed6-8198-2b8d-c787-8f6a802a7d89.png)

**ロール階層では、共有設定の [階層を使用してアクセスを許可する]** チェックボックスにより、階層内のレコード所有者より上位のユーザーにレコード アクセスが自動的に許可されます。このオプションはデフォルトですべてのオブジェクトに対して有効になっており、カスタム オブジェクトに対してのみ変更できます。

**共有設定の「階層を使用してアクセスを許可」チェックボックス** –

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cfe34890-4154-2a65-0ab4-9908cca038e7.png)

アレックスは、階層内でジョンの下にあるため、ジョンとメアリーからアクセス権を継承します。これが、アレックスがジョンとメアリーの役割グループに追加される理由です。

**ロールグループを含むグループ保守テーブル** –

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0969458e-6bd5-7183-4914-d41abe6e9170.png)


次に、RoleAndInternalSubowned グループに移りましょう。これらのグループは、ロールおよび部下とレコードを共有する共有ルールを使用して、レコードが部下と共有されるたびに使用されます。

CEO のレコードへのアクセスを部下に許可するアカウント共有ルールを作成しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/868c1dd5-9a05-6d2d-21d1-ee7184ff7ccc.png)

オブジェクトの共有ルールを作成し、レコードを共有する場合

部下の場合、Salesforce は役割と内部部下グループを作成し、すべての部下をグループに追加します。このシナリオでは、CEO ロールのすべての部下が CEO のロールと部下グループに追加されます。ジョンとメアリーは、アレックスの役割と部下グループに追加されます

**役割と下位グループを含むグループ保守テーブル** –

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6da7f12c-aa7b-4169-e60b-d1a15adf7679.png)