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


みなさまこんにちは、某Platform Specialistのしょっさんなんですが、これは Salesforce Platform Advent Calendar 2020 5日目です。

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

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

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

共有の直接設定って?

Salesforce のもつ、複雑かつ自由度の高い認可の仕組みの中で、個人的に不思議な機能があります。「共有の直接設定」です。

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

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

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

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

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

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

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

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

Apex でもこの機能を利用することができます。Salesforce には、共有を管理するための「共有オブジェクト」があります。Apex では、この共有オブジェクトを直接操作することで、プログラムで自動的に共有を制御できます。お便利ですね。さすがApex(褒めてる)。

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

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

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

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

  1. 独自の Apex 共有の理由を作成する
  2. Apex を書く

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

Apex 共有の理由を作成する

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

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

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

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

Apex を書く

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

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;

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

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

追記

確定ではありませんが、Spring '21 Release Notes(preview) によると、Lightning でも「共有の直接設定」できるようになりそうですね、嬉しいです(´∀`*)ポッ