⛰️

Salesforce Spring'25の「すべての項目の表示」権限でハマった話

2025/03/07に公開

Salesforce Spring'25でリリースされた「すべての項目の表示」を管理パッケージの開発の際に利用して、ハマったことをまとめておきます。

TL;DR

  • 「すべての項目の表示」を有効にすると、対象オブジェクトに対して Apex から FieldPermissions を使って項目権限を管理することが困難になる。
  • 「すべての項目の表示」を付ける → 外すとしても、付ける前と同じ状態にはならない。
  • 項目権限の付与は権限セットで扱う方式で統一するのがベストプラクティス。

はじめに

Spring'25で「すべての項目の表示」がリリースされました。オブジェクトの項目ごとに参照権限を設定するのではなく、オブジェクト単位で全ての項目に一律で参照権限を付与できるようになります。

リリースノート「実現されたアイディア:指定したオブジェクトのすべての項目の表示をユーザーに許可」
https://help.salesforce.com/s/articleView?id=release-notes.rn_permissions_view_all_fields.htm&release=254&type=5

この機能の便利な点は、その後に新しく作成された項目にも自動的に参照権限が付与されることです。「カスタム項目を作ったけど項目権限の付与を忘れていたため、権限不足でエラーになってしまった!」みたいなリスクを回避できます。便利ですね!

今回の前提

2つのハマったことを紹介する前に、前提について説明します。

私たちはAppExchangeアプリを開発しています。AppExchangeアプリはバージョンアップしていくことが前提なので、バージョンアップで追加したオブジェクトや項目の権限をどう管理していくかを考えていく必要があります。
項目権限については、プロファイルではなく権限セットおよび権限セットグループで管理するのがベストプラクティスです[1]
ですが私たちのアプリの場合、歴史的な事情から権限管理の方法として、以下の2つを併用していました。

  • 権限セットによって管理する運用
  • 権限セットが付与されていないユーザー向けのApexプログラムによる項目権限付与

後者のApexプログラムによる項目権限付与について説明します。
管理パッケージでは、パッケージのインストールまたはアップデートした後に自動的に実行されるApexプログラムを InstallHandler インターフェースの実装クラスとして定義できます[2]。また項目権限は内部的には FieldPermissions [3]という標準オブジェクトで管理されており、このレコードを登録することで項目権限の付与ができます。
つまりまとめると、 InstallHandler インターフェースの実装クラスにて FieldPermissions を登録することで、パッケージのインストール時に自動で項目権限を付与させることができます。

ハマったこと

無効なID形式のFieldPermissionsレコードが作られる & Apexでupsert不可になる

「すべての項目の表示」を有効にすると、項目権限が付与されていない項目に対して「000」から始まる無効な FieldPermissions レコードが作られます。
Salesforceのレコードの ID は、先頭3桁がレコードの種類(オブジェクト)を表します。この時、「000」で始まる ID は無効なIDとして扱われます。本記事では便宜上、「000」で始まるレコードを「無効レコード」と表現します。

例として1つ権限セットを作り(名前は test とします)、取引先オブジェクトの「すべての項目の表示」をチェックして登録します。

権限セット「 test 」に紐づく FieldPermissions レコードは以下のSOQLクエリで取得できます。

SELECT 
  Id, 
  Parent.Name, 
  Parent.Profileid, 
  Parent.Type, 
  Parent.Profile.Name, Field 
FROM FieldPermissions 
WHERE SobjectType = 'Account' AND Parent.Name = 'test'
ORDER BY Id

結果は次のようになります。
取引先のそれぞれの項目に対して FieldPermissions が作成されています。また ID は全て 000 で始まる無効レコードになっていることがわかります。

無効レコードは upsert ができません。upsert を行うと次のエラーになります。

System.DmlException: Upsert failed. First exception on row 0 with id 0000000CmqjB3qmAEC; first error: INVALID_ID_FIELD, '0000000CmqjB3qm' is not a valid Salesforce ID for the type 項目権限: []

upsert ができない無効レコードを除外するようにクエリして、upsert をしてみましょう。
ただし ID は特殊な型であり WHERE Id NOT LIKE '000%' といった指定はできません。
やや邪道ですが WHERE Id >= '0010000000000' といった条件は有効なため、この方法で無効レコードを除外したクエリが可能です。

上記のように苦労して無効レコードを除外して有効なレコードだけを選んで upsert をしても、結局次のエラーにぶつかります。

System.DmlException: Upsert failed. First exception on row 1117; first error: FIELD_INTEGRITY_EXCEPTION, このオブジェクトの [すべての項目の表示] 権限が有効になっているため、項目権限を有効にできません。: []

エラーメッセージの通り、「すべての項目の表示」をチェックしていると FieldPermissions での項目権限と干渉してしまうようです。

「すべての項目の表示」は不可逆

一度「すべての項目の表示」をチェックを入れると、チェックを外しても完全に元の状態には戻りません。
「すべての項目の表示」をチェックを入れた段階で、各項目権限の参照アクセス権も自動的にチェックされて登録されます。

一方で、「すべての項目の表示」をチェックを外しても、各項目権限の参照アクセス権のチェックは自動的に外れたりはしません。

あまり機会がないとは思いますが「一度チェックを入れてからやっぱり元に戻したい」と思った時に、上記については留意しておきたいところです。

おわりに

今回のリリースはとても便利なアップデートです。
特に大きなリスクもなくよかれと思って設定してみたのですが、思わぬところでハマってしまいました。Apexテストが通らなくなったことで、本リリース前に気づくことが事なきを得ましたが、些細なことでも事前の検証は大事ですね。
そして結局のところ、項目権限については権限セットで管理する方式で統一するのがベストだと改めて思いました。
権限セットを使用すれば、AppExchangeのアップグレード時に自動的にその内容も更新されていくので、パッケージの更新内容と必要な権限の足並みを揃えることができます。

また今回リリースした「すべての項目の表示」はSpring '25時点では参照権限のみであり、編集権限の付与は保証されていないので注意しましょう。編集権限の付与については、これまでと同じように考慮していく必要がありそうです(少なくとも執筆時点では)

脚注
  1. 権限セットとプロファイルでの項目権限の設定 ↩︎

  2. InstallHandler インターフェース ↩︎

  3. FieldPermissions ↩︎

株式会社キャリオット

Discussion