Salesforce で所有者を変更しても、共有の直接設定を残しておきたい

みなさまこんにちは、某Platform Specialistのしょっさんなんですが、これは [Salesforce Platform Advent Calendar 2020](https://qiita.com/advent-calendar/2020/salesforce-platform) 5日目です。

今日は22日です。はい、すいません、イロイロあったんです、悟ってください。申し訳ない。

なお、4日目は @hanamizuki10 さんの[Salesforce:ソフトフォン（ Lightning Open CTI ）の環境構築方法について](https://qiita.com/hanamizuki10/items/9bbcf98de7924e2001f1)、6日目は @laughingman さんの [Open CTI で Lightning Message Service を使用してみる](https://qiita.com/laughingman/items/36823e819e026d16c826) です。CTIに囲まれている私は、空気も読まずに「共有の直接設定」について説明します。

実はこれ重要です。試験に出るから覚えておけよー。

## 共有の直接設定って？

Salesforce のもつ、複雑かつ自由度の高い認可の仕組みの中で、個人的に不思議な機能があります。「[共有の直接設定](https://help.salesforce.com/articleView?id=granting_access_to_records.htm&type=5)」です。

Salesforce のレコードは、"レコード所有者"および"その所有者よりもロールが上のユーザ"、"レコードのフルアクセスが許可されたユーザ"、"システム管理者"は、アクセス認可のないユーザに独自にアクセスを許可することができる仕組みです。例外中の例外を司る仕組みな気がします。しかも、「`Classic`でしか」使えません。しかし、この自由度のおかげで、共有ルールやロール階層からはじかれているが、どうしても、なんとしてもこのレコードだけは見せてあげたい、編集させてあげたい、というわがままな意向をくんでくれる素晴らしい機能です。`Classic`じゃないと使えませんが。

しかし、これ。ちょっとだけ難儀な部分があります。「所有者を変更すると、その所有者が共有したユーザのアクセス権が奪われる」のです。

こちらをご覧ください。「しょっさん」が「プラットフォーム」というユーザに対して、「共有の直接設定」を使って参照を許可したの図です

![Screen Shot 2020-12-22 at 10.38.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/65e09ad9-7e52-6bc7-0725-502885370d31.png)

このときに「しょっさん」が所有者を他の「QP」さんへ変更したとします。すると、こう。

![Screen Shot 2020-12-22 at 10.40.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/2572fc5f-6290-60a5-45f6-066c71a9ac30.png)

この仕組み自体の考え方には賛同できます。所有者が変わったときに、前任者が好き放題共有しているかもしれません。新しい所有者は、共有された彼らと仲が良いとは限りません。絶対に見せない意思を持っている可能性もあります。

しかし、世の中はそんなに殺伐としたものだけではありません。共有設定したユーザたちを残したい。そんな意向をくんであげてもいいじゃないですか。しかし、標準の機能では実装できません。どうしたものか。

そうだ、ボクたちには `apex` があった。

## Apex を使ったレコードの共有

Apex でもこの機能を利用することができます。Salesforce には、共有を管理するための「[共有オブジェクト](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_bulk_sharing_understanding.htm)」があります。Apex では、この共有オブジェクトを直接操作することで、プログラムで自動的に共有を制御できます。お便利ですね。さすがApex(褒めてる)。

機能的には「共有の直接設定」と同様の機能が利用できるのですが、大きく異なるのは「共有の理由」をカスタマイズして設定できることです。

「どういうこと？」という感じですね。この「所有者変更により、共有されたユーザが一掃される原因」は「共有の理由が`Manual`だから」です。そういう仕様です。決め事です。大人の事情です。`Classic`画面に表示される「共有」ボタンを使って「共有の直接設定」を行うと「共有の理由」を `Manual`で共有します。画面上では「共有の直接設定」と出ていますね。所有者変更で、共有が削除されるトリガは、この「共有の理由が何か」なのです。

では、所有者を変更しても、共有設定を維持したい場合にはどうしたらいいか。それが「共有の理由を`Manual`以外にすればいい」ということなのです。そして、この共有理由をカスタマイズして設定できるのは`Apex`「だけ」です!!! Ω ΩΩ< な、なんだってー!! (正確に言うと、共有ルールや商談チームなどで割り当てられる「理由」も`Manual`以外の何かが設定されてます → 「[共有の理解](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_bulk_sharing_understanding.htm)内の「共有の理由項目」を参照ください)

では、試しにやってみましょう。次の手順で設定します。

1. 独自の [Apex 共有の理由を作成](https://help.salesforce.com/articleView?id=security_apex_sharing_reasons.htm&type=5)する
2. Apex を書く

シンプルですね! やってみましょう(๑•̀ㅂ•́)و✧

### [Apex 共有の理由を作成](https://help.salesforce.com/articleView?id=security_apex_sharing_reasons.htm&type=5)する

`Classic` で、対象のオブジェクトの設定を表示します。下の方に「Apex 共有の理由」という関連リストがあります。ここで、自分の好きな`Apex`だけでつかえる「共有の理由」を作成できます。

![Screen Shot 2020-12-22 at 11.00.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/88acbfd6-7f06-183a-5d51-fd5744933b21.png)

「共有の理由」というくらいなので、本来は、どの Apex でどのような仕様に従ってその共有がなされたか、を示すものです。一つならまだしも、複数の共有仕様がやってくると、なぜそのユーザに共有されたかが分からなくなります。その「なぜ」を追跡できるように定義するんですね、素晴らしい。

そんなわけで試しに作ってみました。お試しなのでそのままの理由です。

![Screen Shot 2020-12-22 at 11.03.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/a839e31f-d55f-eb2c-e12c-7fbbaf3651df.png)

この「理由名」がAPI名になります。カスタムオブジェクトにカスタムで定義したので、実際には `SharingReason__c` というAPI名です。はい、これで事前準備はおしまいです。

### Apex を書く

最低限のコードで書きます。恥ずかしい。クラスかもしてないので開発者コンソールからダイレクトにいけます。試すには十分です。

```Java
SharingObject__Share objShr = new SharingObject__Share();

objShr.ParentId = <対象のレコードID>;
objShr.UserOrGroupId = <共有したいグループ・ロール、またはユーザのID>;
objShr.AccessLevel = 'Read'; // None, Read, Edit, All
objShr.RowCause = Schema.SharingObject__Share.RowCause.SharingReason__c; // 作成した「共有の理由」

insert objShr;
```

このコードを実行すると、このように「共有理由」という理由になっています。独自の理由になっていることが分かりますね。

![Screen Shot 2020-12-22 at 11.08.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/b9047c0f-3cf3-69fe-d1be-642e8655f0b9.png)

この状態で、所有者変更を行ってみましょう。はい、ご想像の通り共有設定が残ったまま所有者が変更できました。やったね(๑•̀ㅂ•́)و✧

![Screen Shot 2020-12-22 at 11.13.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/e4c737a3-6588-4c8e-4e91-511e4c8f9520.png)

### 追記

確定ではありませんが、[Spring '21 Release Notes(preview)](https://help.salesforce.com/articleView?id=release-notes.rn_forcecom_manual_sharing_lex.htm&release=230&type=5) によると、Lightning でも「共有の直接設定」できるようになりそうですね、嬉しいです(´∀｀*)ﾎﾟｯ