この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

Apex を使用したレコードの共有

プログラムから共有にアクセスするには、共有する標準オブジェクトまたはカスタムオブジェクトに関連付けられている共有オブジェクトを使用する必要があります。たとえば、AccountShare は Account オブジェクトの共有オブジェクト、ContactShare は Contact オブジェクトの共有オブジェクトです。他のオブジェクトについても同様です。さらに、すべてのカスタムオブジェクトの共有オブジェクトには次のように名前が付けられています。MyCustomObject はカスタムオブジェクトの名前です。

MyCustomObject__Share

主従関係の従側にあるオブジェクトには、関連付けられた共有オブジェクトはありません。従レコードへのアクセスは、主の共有オブジェクトと関係の共有設定により定義されます。詳細は、Salesforce オンラインヘルプの「カスタムオブジェクトのセキュリティの概要」を参照してください。

共有オブジェクトには、Force.com 共有管理、ユーザ共有管理、Apex 共有管理の 3 種類の共有すべてをサポートするレコードが含まれています。組織の共有設定、ロールの階層、および特定オブジェクトの「すべての参照」や「すべての編集」などの権限、「すべてのデータの参照」および「すべてのデータの編集」を使用してユーザに暗黙的に付与された共有は、このオブジェクトでは追跡されません。

各共有オブジェクトには、次のプロパティがあります。

プロパティ名 説明
objectNameAccessLevel 共有 sObject に対し、指定されたユーザまたはグループが権限を与えられたアクセスレベル。プロパティ名は、オブジェクト名に AccessLevel が追加したものです。たとえば、LeadShare オブジェクトのプロパティ名は LeadShareAccessLevel です。有効な値は、次のとおりです。
  • Edit
  • Read
  • All

All アクセスレベルは、Force.com 共有管理でのみ使用できます。

メモ

この項目には、その親オブジェクトに割り当てられた組織のデフォルトアクセスレベルよりも高いアクセスレベルを割り当てる必要があります。詳細は、アクセスレベルを参照してください。
ParentID オブジェクトの ID。この項目は更新できません。
RowCause ユーザまたはグループにアクセス権が付与される理由。この理由によって、共有のタイプが決まります。共有のタイプは、共有レコードの変更権限を制御します。この項目は更新できません。
UserOrGroupId アクセス権を付与するユーザまたはグループの ID。グループには、ロールまたはテリトリーに関連付けられた公開グループまたは共有グループを指定できます。この項目は更新できません。

ユーザまたはグループでは標準オブジェクトまたはカスタムオブジェクトは共有できません。カスタマーコミュニティユーザは、Apex 共有を使用できません。オブジェクトを共有できるユーザおよびグループの種別についての詳細は、Salesforce および Force.com のオブジェクトリファレンス「User」「Group」を参照してください。

Apex を使用したユーザ共有管理の作成

Apex または SOAP API を使用して、1 つのユーザまたはグループに対してレコードの共有を直接設定できます。レコードの所有者が変更されると、共有は自動的に削除されます。次の例のクラスには、参照アクセスのある特定のユーザまたはグループ ID を伴うジョブ ID によって指定されたジョブを共有するメソッドが含まれます。また、このメソッドを検証するテストメソッドも含まれます。このクラス例を保存する前に、Job というカスタムオブジェクトを作成します。

1swfobject.registerObject("clippy.codeblock-0", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class JobSharing {
18   
19   public static boolean manualShareRead(Id recordId, Id userOrGroupId){
20      // Create new sharing object for the custom object Job.
21      Job__Share jobShr  = new Job__Share();
22   
23      // Set the ID of record being shared.
24      jobShr.ParentId = recordId;
25        
26      // Set the ID of user or group being granted access.
27      jobShr.UserOrGroupId = userOrGroupId;
28        
29      // Set the access level.
30      jobShr.AccessLevel = 'Read';
31        
32      // Set rowCause to 'manual' for manual sharing.
33      // This line can be omitted as 'manual' is the default value for sharing objects.
34      jobShr.RowCause = Schema.Job__Share.RowCause.Manual;
35        
36      // Insert the sharing record and capture the save result. 
37      // The false parameter allows for partial processing if multiple records passed 
38      // into the operation.
39      Database.SaveResult sr = Database.insert(jobShr,false);
40
41      // Process the save results.
42      if(sr.isSuccess()){
43         // Indicates success
44         return true;
45      }
46      else {
47         // Get first save result error.
48         Database.Error err = sr.getErrors()[0];
49         
50         // Check if the error is related to trival access level.
51         // Access levels equal or more permissive than the object's default 
52         // access level are not allowed. 
53         // These sharing records are not required and thus an insert exception is acceptable. 
54         if(err.getStatusCode() == StatusCode.FIELD_FILTER_VALIDATION_EXCEPTION  &&  
55                  err.getMessage().contains('AccessLevel')){
56            // Indicates success.
57            return true;
58         }
59         else{
60            // Indicates failure.
61            return false;
62         }
63       }
64   }
65   
66}
67
1swfobject.registerObject("clippy.codeblock-1", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17@isTest
18private class JobSharingTest {
19   // Test for the manualShareRead method
20   static testMethod void testManualShareRead(){
21      // Select users for the test.
22      List<User> users = [SELECT Id FROM User WHERE IsActive = true LIMIT 2];
23      Id User1Id = users[0].Id;
24      Id User2Id = users[1].Id;
25   
26      // Create new job.
27      Job__c j = new Job__c();
28      j.Name = 'Test Job';
29      j.OwnerId = user1Id;
30      insert j;    
31                
32      // Insert manual share for user who is not record owner.
33      System.assertEquals(JobSharing.manualShareRead(j.Id, user2Id), true);
34   
35      // Query job sharing records.
36      List<Job__Share> jShrs = [SELECT Id, UserOrGroupId, AccessLevel, 
37         RowCause FROM job__share WHERE ParentId = :j.Id AND UserOrGroupId= :user2Id];
38      
39      // Test for only one manual share on job.
40      System.assertEquals(jShrs.size(), 1, 'Set the object\'s sharing model to Private.');
41      
42      // Test attributes of manual share.
43      System.assertEquals(jShrs[0].AccessLevel, 'Read');
44      System.assertEquals(jShrs[0].RowCause, 'Manual');
45      System.assertEquals(jShrs[0].UserOrGroupId, user2Id);
46      
47      // Test invalid job Id.
48      delete j;   
49   
50      // Insert manual share for deleted job id. 
51      System.assertEquals(JobSharing.manualShareRead(j.Id, user2Id), false);
52   }  
53}
54

組織のデフォルトのアクセスレベルは、最も権限の大きいアクセスレベルに設定することはできません。カスタムオブジェクトの場合は「公開/参照・更新可能」です。詳細は、アクセスレベルを参照してください。

重要

Apex による共有管理の作成

開発者は Apex による共有管理を使用すると、Apex または SOAP API を通じて、アプリケーションの動作をサポートする共有をプログラムで操作できるようになります。この種類の共有は、Force.com による共有管理に類似しています。「すべてのデータの編集」権限を持つユーザのみが、レコードへの Apex による共有管理を追加または変更できます。Apex による共有管理は、レコードの所有者を変更しても維持されます。

Apex による共有管理には、Apex 共有の理由を使用する必要があります。Apex 共有の理由は、ユーザやユーザグループでレコードを共有した理由を開発者が追跡するための 1 つの方法です。複数の Apex 共有理由を使用することで、共有レコードの更新や削除に必要なコーディングを簡略化することができます。また、開発者は、同じユーザやグループに対して異なる共有理由を設定して複数の共有を設定できます。

Apex 共有の理由は、オブジェクトの詳細ページとして定義されます。Apex 共有の理由には、それぞれラベルと名前が付けられます。
  • ユーザインターフェースでレコードの共有を参照すると、[理由] 列に表示ラベルが表示されます。これにより、ユーザとシステム管理者が共有の目的を理解できます。表示ラベルは、トランスレーションワークベンチを使用する翻訳についても有効化されます。
  • この名前は、API および Apex で理由を参照するときに使用します。

Apex 共有の理由の名前の形式は次のとおりです。

1MyReasonName__c
Apex 共有の理由は、次のようにプログラムで参照できます。
1Schema.CustomObject__Share.rowCause.SharingReason__c
たとえば、Job というオブジェクトの Apex 共有の理由である Recruiter は、次のように参照できます。
1Schema.Job__Share.rowCause.Recruiter__c

詳細は、Schema クラスを参照してください。

Apex 共有の理由を作成する手順は、次のとおりです。
  1. [設定] で、[作成] | [オブジェクト] をクリックします。
  2. カスタムオブジェクトを選択します。
  3. [Apex 共有の理由] 関連リストで [新規] をクリックします。
  4. Apex 共有の理由の表示ラベルを入力します。ユーザインターフェースでレコードの共有を参照すると、[理由] 列に表示ラベルが表示されます。表示ラベルは、トランスレーションワークベンチを使用する翻訳についても有効化されます。
  5. Apex 共有の理由の名前を入力します。この名前は、API および Apex で理由を参照するときに使用します。この名前は、アンダースコアと英数字のみを含み、組織内で一意の名前にする必要があります。最初は文字であること、スペースは使用しない、最後にアンダースコアを使用しない、2 つ続けてアンダースコアを使用しないという制約があります。
  6. [保存] をクリックします。

Apex 共有の理由と Apex による共有管理の再適用は、カスタムオブジェクトでのみ使用できます。

メモ

Apex による共有管理の例

この例では、人事採用アプリケーションの構築中で、Job というオブジェクトが存在すると仮定しています。ジョブにリストされた採用担当者および採用担当マネージャにレコードへのアクセス権が付与されていることを確認したいと考えています。次のトリガは、ジョブレコード作成時に採用担当者および採用担当マネージャにアクセス権を付与します。この例では、User レコードと関連付けられた、Hiring_Manager および Recruiter という 2 つの参照項目を持つ Job というカスタムオブジェクトが必要です。また、Job カスタムオブジェクトには、Hiring_Manager と Recruiter という 2 つの共有の理由を追加する必要があります。

1swfobject.registerObject("clippy.codeblock-5", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17trigger JobApexSharing on Job__c (after insert) {
18    
19    if(trigger.isInsert){
20        // Create a new list of sharing objects for Job
21        List<Job__Share> jobShrs  = new List<Job__Share>();
22        
23        // Declare variables for recruiting and hiring manager sharing
24        Job__Share recruiterShr;
25        Job__Share hmShr;
26        
27        for(Job__c job : trigger.new){
28            // Instantiate the sharing objects
29            recruiterShr = new Job__Share();
30            hmShr = new Job__Share();
31            
32            // Set the ID of record being shared
33            recruiterShr.ParentId = job.Id;
34            hmShr.ParentId = job.Id;
35            
36            // Set the ID of user or group being granted access
37            recruiterShr.UserOrGroupId = job.Recruiter__c;
38            hmShr.UserOrGroupId = job.Hiring_Manager__c;
39            
40            // Set the access level
41            recruiterShr.AccessLevel = 'edit';
42            hmShr.AccessLevel = 'read';
43            
44            // Set the Apex sharing reason for hiring manager and recruiter
45            recruiterShr.RowCause = Schema.Job__Share.RowCause.Recruiter__c;
46            hmShr.RowCause = Schema.Job__Share.RowCause.Hiring_Manager__c;
47            
48            // Add objects to list for insert
49            jobShrs.add(recruiterShr);
50            jobShrs.add(hmShr);
51        }
52        
53        // Insert sharing records and capture save result 
54        // The false parameter allows for partial processing if multiple records are passed 
55        // into the operation 
56        Database.SaveResult[] lsr = Database.insert(jobShrs,false);
57        
58        // Create counter
59        Integer i=0;
60        
61        // Process the save results
62        for(Database.SaveResult sr : lsr){
63            if(!sr.isSuccess()){
64                // Get the first save result error
65                Database.Error err = sr.getErrors()[0];
66                
67                // Check if the error is related to a trivial access level
68                // Access levels equal or more permissive than the object's default 
69                // access level are not allowed. 
70                // These sharing records are not required and thus an insert exception is 
71                // acceptable. 
72                if(!(err.getStatusCode() == StatusCode.FIELD_FILTER_VALIDATION_EXCEPTION  
73                                               &&  err.getMessage().contains('AccessLevel'))){
74                    // Throw an error when the error is not related to trivial access level.
75                    trigger.newMap.get(jobShrs[i].ParentId).
76                      addError(
77                       'Unable to grant sharing access due to following exception: '
78                       + err.getMessage());
79                }
80            }
81            i++;
82        }   
83    }
84    
85}
特定の状況下では、共有行を挿入すると、既存の共有行が更新されます。次の例を参考にしてください。
  • 共有の直接設定アクセスレベルが「参照」に設定されている場合、「更新」に設定された新しい共有行を挿入すると、元の共有行はより高いアクセスレベルを示す「更新」に更新されます。
  • ユーザが子レコード (取引先責任者、ケース、商談など) にアクセスできるため取引先にアクセスでき、取引先共有ルールが作成されている場合、親の暗黙的共有の共有理由は、共有ルールの共有理由で置き換えられ、高い方のアクセスレベルを示します。

組織のデフォルトのアクセスレベルは、最も権限の大きいアクセスレベルに設定することはできません。カスタムオブジェクトの場合は「公開/参照・更新可能」です。詳細は、アクセスレベルを参照してください。

重要