Newer Version Available
Apex を使用したレコードの共有
プログラムから共有にアクセスするには、共有する標準オブジェクトまたはカスタムオブジェクトに関連付けられている共有オブジェクトを使用する必要があります。たとえば、AccountShare は Account オブジェクトの共有オブジェクト、ContactShare は Contact オブジェクトの共有オブジェクトです。他のオブジェクトについても同様です。さらに、すべてのカスタムオブジェクトの共有オブジェクトには次のように名前が付けられています。MyCustomObject は��スタムオブジェクトの名前です。
MyCustomObject__Share
主従関係の従側にあるオブジェクトには、関連付けられた共有オブジェクトはありません。従レコードへのアクセスは、主の共有オブジェクトと関係の共有設定により定義されます。詳細は、Salesforce オンラインヘルプの「カスタムオブジェクトのセキュリティ」を参照してください。
共有オブジェクトには、Force.com 共有管理、ユーザ共有管理、Apex 共有管理の 3 種類の共有すべてをサポートするレコードが含まれています。組織の共有設定、ロールの階層、および特定オブジェクトの「すべての参照」や「すべての編集」などの権限、「すべてのデータの参照」および「すべてのデータの編集」を使用してユーザに暗黙的に付与された共有は、このオブジェクトでは追跡されません。
各共有オブジェクトには、次のプロパティがあります。
| プロパティ名 | 説明 |
|---|---|
| objectNameAccessLevel | 共有 sObject に対し、指定されたユーザまたはグループが権限を与えられたアクセスレベル。プロパティ名は、オブジェクト名に AccessLevel が追加したものです。たとえば、LeadShare オブジェクトのプロパティ名は LeadShareAccessLevel です。有効な値は、次のとおりです。
|
| ParentID | オブジェクトの ID。この項目は更新できません。 |
| RowCause | ユーザまたはグループにアクセス権が付与される理由。この理由によって、共有のタイプが決まります。共有のタイプは、共有レコードの変更権限を制御します。この項目は更新できません。 |
| UserOrGroupId | アクセス権を付与するユーザまたはグループの ID。グループには、ロールまたはテリトリーに関連付けられた公開グループまたは共有グループを指定できます。この項目は更新できません。 |
ユーザまたはグループでは標準オブジェクトまたはカスタムオブジェクトは共有できません。オブジェクトを共有できるユーザおよびグループの種別についての詳細は、『Salesforce および Force.com のオブジェクトリファレンス』の「User」と「Group」を参照してください。
Apex を使用したユーザ共有管理の作成
1public class JobSharing {
2
3 public static boolean manualShareRead(Id recordId, Id userOrGroupId){
4 // Create new sharing object for the custom object Job.
5 Job__Share jobShr = new Job__Share();
6
7 // Set the ID of record being shared.
8 jobShr.ParentId = recordId;
9
10 // Set the ID of user or group being granted access.
11 jobShr.UserOrGroupId = userOrGroupId;
12
13 // Set the access level.
14 jobShr.AccessLevel = 'Read';
15
16 // Set rowCause to 'manual' for manual sharing.
17 // This line can be omitted as 'manual' is the default value for sharing objects.
18 jobShr.RowCause = Schema.Job__Share.RowCause.Manual;
19
20 // Insert the sharing record and capture the save result.
21 // The false parameter allows for partial processing if multiple records passed
22 // into the operation.
23 Database.SaveResult sr = Database.insert(jobShr,false);
24
25 // Process the save results.
26 if(sr.isSuccess()){
27 // Indicates success
28 return true;
29 }
30 else {
31 // Get first save result error.
32 Database.Error err = sr.getErrors()[0];
33
34 // Check if the error is related to trival access level.
35 // Access level must be more permissive than the object's default.
36 // These sharing records are not required and thus an insert exception is acceptable.
37 if(err.getStatusCode() == StatusCode.FIELD_FILTER_VALIDATION_EXCEPTION &&
38 err.getMessage().contains('AccessLevel')){
39 // Indicates success.
40 return true;
41 }
42 else{
43 // Indicates failure.
44 return false;
45 }
46 }
47 }
48
49}1@isTest
2private class JobSharingTest {
3 // Test for the manualShareRead method
4 static testMethod void testManualShareRead(){
5 // Select users for the test.
6 List<User> users = [SELECT Id FROM User WHERE IsActive = true LIMIT 2];
7 Id User1Id = users[0].Id;
8 Id User2Id = users[1].Id;
9
10 // Create new job.
11 Job__c j = new Job__c();
12 j.Name = 'Test Job';
13 j.OwnerId = user1Id;
14 insert j;
15
16 // Insert manual share for user who is not record owner.
17 System.assertEquals(JobSharing.manualShareRead(j.Id, user2Id), true);
18
19 // Query job sharing records.
20 List<Job__Share> jShrs = [SELECT Id, UserOrGroupId, AccessLevel,
21 RowCause FROM job__share WHERE ParentId = :j.Id AND UserOrGroupId= :user2Id];
22
23 // Test for only one manual share on job.
24 System.assertEquals(jShrs.size(), 1, 'Set the object\'s sharing model to Private.');
25
26 // Test attributes of manual share.
27 System.assertEquals(jShrs[0].AccessLevel, 'Read');
28 System.assertEquals(jShrs[0].RowCause, 'Manual');
29 System.assertEquals(jShrs[0].UserOrGroupId, user2Id);
30
31 // Test invalid job Id.
32 delete j;
33
34 // Insert manual share for deleted job id.
35 System.assertEquals(JobSharing.manualShareRead(j.Id, user2Id), false);
36 }
37}Apex による共有管理の作成
開発者は Apex による共有管理を使用すると、Apex または SOAP API を通じて、アプリケーションの動作をサポートする共有をプログラムで操作できるようになります。この種類の共有は、Force.com による共有管理に類似しています。「すべてのデータの編集」権限を持つユーザのみが、レコードへの Apex による共有管理を追加または変更できます。Apex による共有管理は、レコードの所有者を変更しても維持されます。
Apex による共有管理には、Apex 共有の理由を使用する必要があります。Apex 共有の理由は、ユーザやユーザグループでレコードを共有した理由を開発者が追跡するための 1 つの方法です。複数の Apex 共有理由を使用することで、共有レコードの更新や削除に必要なコーディングを簡略化することができます。また、開発者は、同じユーザやグループに対して異なる共有理由を設定して複数の共有を設定できます。
- ユーザインターフェースでレコードの共有を参照すると、[理由] 列に表示ラベルが表示されます。この表示ラベルにより、ユーザとシステム管理者が共有の目的を理解できます。表示ラベルは、トランスレーションワークベンチを使用する翻訳についても有効化されます。
- この名前は、API および Apex で理由を参照するときに使用します。
Apex 共有の理由の名前の形式は次のとおりです。
1MyReasonName__c1Schema.CustomObject__Share.rowCause.SharingReason__c1Schema.Job__Share.rowCause.Recruiter__c詳細は、「Schema クラス」を参照してください。
- カスタムオブジェクトの管理設定から、[Apex 共有の理由] 関連リストの [新規] をクリックします。
- Apex 共有の理由の表示ラベルを入力します。ユーザインターフェースでレコードの共有を参照すると、[理由] 列に表示ラベルが表示されます。表示ラベルは、トランスレーションワークベンチを使用する翻訳についても有効化されます。
- Apex 共有の理由の名前を入力します。この名前は、API および Apex で理由を参照するときに使用します。この名前は、アンダースコアと英数字のみを使用でき、組織内で一意にする必要があります。最初は文字であること、空白は使用しない、最後にアンダースコアを使用しない、2 つ続けてアンダースコアを使用しないという制約があります。
- [保存] をクリックします。
Apex による共有管理の例
この例では、人事採用アプリケーションの構築中で、Job というオブジェクトが存在すると仮定しています。ジョブにリストされた採用担当者および採用担当マネージャにレコードへのアクセス権が付与されていることを確認したいと考えています。次のトリガは、ジョブレコード作成時に採用担当者および採用担当マネージャにアクセス権を付与します。この例では、User レコードと関連付けられた、Hiring_Manager および Recruiter という 2 つの参照項目を持つ Job というカスタムオブジェクトが必要です。また、Job カスタムオブジェクトには、Hiring_Manager と Recruiter という 2 つの共有の理由を追加する必要があります。
1trigger JobApexSharing on Job__c (after insert) {
2
3 if(trigger.isInsert){
4 // Create a new list of sharing objects for Job
5 List<Job__Share> jobShrs = new List<Job__Share>();
6
7 // Declare variables for recruiting and hiring manager sharing
8 Job__Share recruiterShr;
9 Job__Share hmShr;
10
11 for(Job__c job : trigger.new){
12 // Instantiate the sharing objects
13 recruiterShr = new Job__Share();
14 hmShr = new Job__Share();
15
16 // Set the ID of record being shared
17 recruiterShr.ParentId = job.Id;
18 hmShr.ParentId = job.Id;
19
20 // Set the ID of user or group being granted access
21 recruiterShr.UserOrGroupId = job.Recruiter__c;
22 hmShr.UserOrGroupId = job.Hiring_Manager__c;
23
24 // Set the access level
25 recruiterShr.AccessLevel = 'edit';
26 hmShr.AccessLevel = 'read';
27
28 // Set the Apex sharing reason for hiring manager and recruiter
29 recruiterShr.RowCause = Schema.Job__Share.RowCause.Recruiter__c;
30 hmShr.RowCause = Schema.Job__Share.RowCause.Hiring_Manager__c;
31
32 // Add objects to list for insert
33 jobShrs.add(recruiterShr);
34 jobShrs.add(hmShr);
35 }
36
37 // Insert sharing records and capture save result
38 // The false parameter allows for partial processing if multiple records are passed
39 // into the operation
40 Database.SaveResult[] lsr = Database.insert(jobShrs,false);
41
42 // Create counter
43 Integer i=0;
44
45 // Process the save results
46 for(Database.SaveResult sr : lsr){
47 if(!sr.isSuccess()){
48 // Get the first save result error
49 Database.Error err = sr.getErrors()[0];
50
51 // Check if the error is related to a trivial access level
52 // Access levels equal or more permissive than the object's default
53 // access level are not allowed.
54 // These sharing records are not required and thus an insert exception is
55 // acceptable.
56 if(!(err.getStatusCode() == StatusCode.FIELD_FILTER_VALIDATION_EXCEPTION
57 && err.getMessage().contains('AccessLevel'))){
58 // Throw an error when the error is not related to trivial access level.
59 trigger.newMap.get(jobShrs[i].ParentId).
60 addError(
61 'Unable to grant sharing access due to following exception: '
62 + err.getMessage());
63 }
64 }
65 i++;
66 }
67 }
68
69}- 共有の直接設定アクセスレベルが「参照」に設定されている場合に、「更新」に設定された新しい共有行を挿入します。元の共有行はより高いアクセスレベルを示す「更新」に更新されます。
- ユーザは子レコード (取引先責任者、ケース、商談など) にアクセスできるため、取引先にアクセスできます。取引先共有ルールが作成されている場合、共有ルールの共有理由 (より高いアクセスレベル) によって親の暗黙的共有の共有理由が置き換えられ、高い方のアクセスレベルを示します。
カスタマーコミュニティプラスユーザのための Apex による共有管理の作成
カスタマーコミュニティプラスユーザは以前、カスタマーポータルユーザと呼ばれていました。これらのユーザは、共有オブジェクト (AccountShare、ContactShare など) を使用できません。カスタマーコミュニティプラスユーザとして共有オブジェクトを使用する必要がある場合は、デフォルトで without sharing キーワードを使用して動作するトリガの使用を検討してください。または、この同じキーワードで内部クラスを使用し、DML 操作を正常に実行できるようにします。別のユーティリティクラスを使用してこのアクセスを有効にすることもできます。
記述した共有の直接設定または Apex による共有を介した共有オブジェクトに対する表示の許可はサポートされていますが、オブジェクト自体をカスタマーコミュニティプラスユーザが使用することはできません。ただし、他のユーザは共有を追加してカスタマーコミュニティプラスユーザにアクセス権を付与することができます。