Salesforceのデータ共有は、組織内での情報アクセスを制御するための重要な要素です。
この記事では、Apexを使用してレコードを共有するための具体的な方法について、実際のコード例を含めて解説します。
Apexを活用したレコード共有の基本
レコード共有の基礎知識
Salesforceでは、標準オブジェクトやカスタムオブジェクトの共有をプログラムから制御するために、関連する共有オブジェクトを使用します。
これにより、特定のユーザーやグループに対してデータアクセス権を柔軟に設定できます。
なお、この共有オブジェクトを使用した仕組みはApexだけでなく共有ルールなどの全ての共有の仕組みで使用されています。
Apexによるレコードアクセス権の共有についての詳細は以下の関連記事にも記載しています。
共有オブジェクトの構造
各共有オブジェクトには、アクセスレベルや対象となるユーザーのIDなど、共有に必要な情報が含まれています。
たとえば、AccountShare
はAccount
オブジェクトに対する共有オブジェクトです。
カスタムオブジェクトの場合、その名前はMyCustomObject__Share
となります。
共有オブジェクトは元になるオブジェクトを作成したタイミングで自動的に作成されます。
システム用のオブジェクトのため、一般ユーザーは表側からアクセスをしたり、カスタム項目を追加したりすることはできません。
Apexを用いた共有設定
Apexを使用してレコードを共有する場合、共有オブジェクトの項目に値を適切に設定し、レコードをinsertする必要があります。
共有レコードの項目には以下の役割があります。
- ParentId …… 共有するレコードIdを指定
- UserOrGroupId …… レコードの共有先のユーザーIdもしくは公開グループのIdを指定
- AccessLevel …… 付与するアクセスレベルを指定(例:edit、readなど)
- RowCause …… 共有の理由。レコードが何の仕組みで共有されているかを表示または指定(例:Manual、Owner、Ruleなど)
上記の項目にそれぞれ値を設定したレコードをApexで作成する操作により、対象のレコードが指定したユーザーやグループに対して共有されます。
共有オブジェクトの項目については次の章でより詳しく解説します。
共有オブジェクトの項目とその役割
AccessLevelの設定
AccessLevelプロパティは、共有されるレコードに対するアクセス権限を定義します。
有効な値には、Edit
、Read
が含まれ、組織の共有設定でデフォルトとして設定されている以上のアクセスレベルが求められます。
たとえば組織の共有が「非公開」の場合はEdit(編集)もしくはRead(参照)を設定し、「参照のみ」の場合はEditを設定します。
RowCauseの重要性
RowCauseプロパティは、なぜそのユーザーやグループにアクセス権が与えられたのかを示します。
手動で設定された共有には、Manual
がデフォルトで設定されますが、「Apex共有の理由」を使用することでカスタムの理由を指定することも可能です。
RowCauseがManualで設定されていた場合、レコードの所有者を変更した際に共有レコードは削除されてしまいます。
しかしApex共有の理由の値が設定されている共有レコードは所有者が変わっても削除されません。
Apex共有の理由は2024年8月時点ではClassicの画面からのみ設定できます。
UserOrGroupIdプロパティの指定方法
この項目には、アクセスを付与する対象ユーザーまたはグループのIDを指定します。
指定可能なグループには、ロールに関連付けられた公開グループやテリトリーグループなどが含まれます。
Apexを活用した具体的な共有管理の実装について
手動共有の実装方法
以下のコード例は、Apexを使用して特定のユーザーにレコードを手動で共有する方法を示しています。
この例では、SampleObject__Share
オブジェクトを用いて、特定のジョブレコードを別のユーザーに対してRead
アクセスで共有します。
またSampleObject__cに対して「ApexTrigger」というApex共有の理由をあらかじめ設定しておきます。
public class SampleSharing {
public static boolean manualShareRead(Id recordId, Id userOrGroupId){
SampleObject__Share shr = new SampleObject__Share ();
shr.ParentId = recordId; //アクセス権を付与したいレコード
shr.UserOrGroupId = userOrGroupId; // レコードのアクセス権を付与するユーザId
shr.AccessLevel = 'Read'; // アクセスレベル = 参照のみ
shr.RowCause = Schema.SampleObject__Share.RowCause.ApexTrigger__c; // Apex共有の理由を設定
Database.SaveResult sr = Database.insert(shr,false);
return sr.isSuccess();
}
}
Apex共有の理由のAPI名は「ApexTrigger」ですが、共有レコードで使用するときには末尾に「__c」を付与してください。
Apexトリガーを利用した自動共有の実装
次の例では、レコードが作成された際に、自動的に関連するユーザーに対して共有を設定するApexトリガーを紹介します。
このトリガーは、新しいジョブレコードが作成されるたびに実行され、SampleObjectのユーザー項目「targetUser__c」に対してアクセス権を付与します。
trigger SampleObjectTrigger on SampleObject__c (After insert) {
if (Trigger.isAfter && Trigger.isInsert) {
List<SampleObject__Share> shares = new List<SampleObject__Share>();
for (SampleObject__c rec : Trigger.new) {
// targetUser__cがnullでない場合、共有レコードを作成
if (rec.targetUser__c != null) {
SampleObject__Share shr = new SampleObject__Share ();
shr.ParentId = rec.Id;
shr.UserOrGroupId = rec.targetUser__c;
shr.AccessLevel = 'Read';
shr.RowCause = Schema.SampleObject__Share.RowCause.ApexTrigger__c; // Apex共有の理由を設定
shares.add(shr);
}
}
if (shares.size() > 0) {
insert shares;
}
}
}
共有オブジェクトはPlatformプロファイルなどの一般ユーザーの持つ権限ではアクセスできません。
今回の例ではApexトリガー内に直接記載しましたが、実際の運用時はwithout Sharingキーワードを付与したApexクラスなど、必要に応じてアクセス権関係なしにレコードを操作できる状況で実装してください。
共有レコードの追跡とApex共有の理由の活用
Apex共有理由は、複数の理由を使用してレコードの共有を管理しやすくするための強力なツールです。
これにより、異なる状況に応じた共有理由を設定し、必要に応じて追跡・更新できます。
以下の図は前項で実装したApexトリガーを使ってレコードを共有した場合の例で、RowCauseにApex共有の理由の「ApexTrigger__c」が、AccessLevelに「Read」が設定されています。
また一つ上のレコードのRowCauseは「Owner」となっているため、レコードの所有者の持つ権限であることが分かります
まとめ
Apexを使用したレコード共有は、Salesforceのセキュリティモデルを強化し、特定のビジネスニーズに応じたデータアクセスを実現するための重要な手法です。
上記の方法を活用して、効率的かつ柔軟に共有設定を行うことで、組織全体のデータ管理が一層効果的になります。