みなさん、はじめまして。
テラスカイの鈴木です。
普段はOMLINE-I、OMLINE-OといったAppExchangeパッケージの開発を行っています。
今回はそんなパッケージ開発で活用される「保護されたカスタムメタデータ」とその利用方法についてご紹介したいと思います。
保護されたカスタムメタデータとは?
保護されたカスタムメタデータは管理パッケージで利用するサーバURLなどの機密情報を保持しておく場所として利用されます。
そのため、保護されたカスタムメタデータは管理パッケージでのみ作成可能で、通常のカスタムメタデータと違い、 インストール先の組織では参照できません。
一般的なカスタムメタデータは作成した組織内で自由に参照・編集・レコード管理が可能ですが、保護されたカスタムメタデータは基本的に管理パッケージ内のApexコードのみ参照・編集・レコード管理が可能です。
| カスタムメタデータの種類 | アクセシビリティ |
|---|---|
| カスタムメタデータ | 作成した組織内で参照・編集・レコード管理が可能。 |
| 保護されたカスタムメタデータ | インストール先の組織では参照・編集・レコード管理不可。同じ管理パッケージ内のApexコードのみが参照・編集・レコード管理可能。 |
https://help.salesforce.com/articleView?id=custommetadatatypes_package_access.htm&type=5
保護されたカスタムメタデータの利用
保護されたカスタムメタデータは、インストール先組織でレコード管理ができません。
しかし、外部サービスのアクセストークンのような組織ごとに値が違う機密情報を保持したい場合など、インストール先組織から保護されたカスタムメタデータのレコードを編集したいユースケースは存在します。
OMLINE-Iではこの問題を解決するために、管理パッケージに保護されたカスタムメタデータにアクセスするためのApexクラスを用意しています。
保護されたカスタムメタデータにアクセスするためのApexクラスを提供することで、インストール先組織から参照・編集できるようになり、組織ごとの設定や拡張が可能になるわけです。
それでは、具体的な方法を確認していきましょう。
1.保護されたカスタムメタデータの作成
まずは、保護されたカスタムメタデータを作成してみましょう。
今回は比較のために、公開された通常のカスタムメタデータも一緒に作成します。
2.アクセス用のApexクラスの作成
次に、保護されたカスタムメタデータを扱うApexクラスを作成します。
OMLINE-Iでは保護されたカスタムメタデータのモデルクラスと、レコードを扱う処理をまとめたサービスクラスをglobalで提供しています。
こうすることで保護されたカスタムメタデータへのアクセスが可能となり、参照させたくない項目の制御も可能になります。
global class ProtectedCustomMetadata {
global String label = null;
global String developerName = null;
global String protectedField = null;
global ProtectedCustomMetadata() {
}
global ProtectedCustomMetadata(String label, String name, String text) {
this.label = label;
this.developerName = name;
this.protectedField = text;
}
global ProtectedCustomMetadata(ProtectedCustomMetadata__mdt record) {
this.label = record.label;
this.developerName = record.DeveloperName;
this.protectedField = record.ProtectedField__c;
}
}global with sharing class CustomMetadataService {
/*
* developerNameを指定してレコードを取得するメソッド
* 戻り値はパッケージ内でglobalに宣言したラッパークラス
*/
global ProtectedCustomMetadata get(String developerName) {
ProtectedCustomMetadata__mdt[] records = [
select Id
, label
, DeveloperName
, ProtectedField__c
from ProtectedCustomMetadata__mdt
where DeveloperName = :developerName
];
if (records.size() == 0) {
return null;
}
return new ProtectedCustomMetadata(records[0]);
}
/*
* 全レコードを取得するメソッド
* 戻り値はパッケージ内でglobalに宣言したラッパークラスの配列
*/
global ProtectedCustomMetadata[] getAll() {
ProtectedCustomMetadata__mdt[] records = [
select Id
, label
, DeveloperName
, ProtectedField__c
from ProtectedCustomMetadata__mdt
];
ProtectedCustomMetadata[] metadataList = new ProtectedCustomMetadata[0];
for (ProtectedCustomMetadata__mdt record : records) {
metadataList.add(new ProtectedCustomMetadata(record));
}
return metadataList;
}
/*
* パッケージ内でglobalに宣言したラッパークラスを受け取り
* 保護されたカスタムメタデータのレコードを作成するメソッド
*
* 実際にデプロイする処理はテストクラスでテストできないため、別メソッドとして分離する。
*/
global Id deploy(ProtectedCustomMetadata customMeta) {
Metadata.DeployContainer container = createDeployContainer(customMeta);
return Metadata.Operations.enqueueDeployment(container , null);
}
/*
* パッケージ内でglobalに宣言したラッパークラスを受け取り
* 保護されたカスタムメタデータのレコードを作成するメソッド
*
* デプロイ処理はテストクラスで実行できないため、デプロイするメタデータの作成処理を別メソッドとして分離する。
* テストクラスでは本メソッドの戻り値から含まれるメタデータを取得して比較する。
* 例)
* Metadata.DeployContainer container = service.createDeployContainer(customMeta);
* Metadata.Metadata[] contents = container.getMetadata();
* System.assertEquals(1, contents.size());
*/
@TestVisible
private Metadata.DeployContainer createDeployContainer(ProtectedCustomMetadata customMeta) {
Metadata.CustomMetadata customMetadata = new Metadata.CustomMetadata();
customMetadata.fullName = 'SuzukiExample__ProtectedCustomMetadata__mdt.' + customMeta.DeveloperName;
customMetadata.label = customMeta.label;
Metadata.CustomMetadataValue field = new Metadata.CustomMetadataValue();
field.field = 'SuzukiExample__ProtectedField__c';
field.value = customMeta.protectedField;
customMetadata.values.add(field);
Metadata.DeployContainer container = new Metadata.DeployContainer();
container.addMetadata(customMetadata);
return container;
}
}3.管理パッケージの作成
それではいよいよ、管理パッケージを作成してみます。
管理パッケージ内には、各カスタムメタデータとApexクラスを追加しましょう。
4.パッケージのインストール
管理パッケージの作成が終わった後は、実際にインストールして、保護されたカスタムメタデータを利用してみましょう。
5.Apexクラスのメタデータリリース許可
Apexクラスからメタデータのデプロイを行う場合、「Apex設定」からメタデータのリリースを許可する必要があります。
6.カスタムメタデータとの比較
まずは標準画面からカスタムメタデータを確認してみます。
画像のように、公開カスタムメタデータのみ表示され、保護されたカスタムメタデータは表示されません。
インストール先組織では保護されたカスタムメタデータが参照できなくなっています。
次にSOQLを実行し、Apexからもカスタムメタデータが参照できないことを確認しましょう。
下記のようなApexを匿名実行してみます。
System.debug([
select Id
from SuzukiExample__ProtectedCustomMetadata__mdt
]);下記のようなエラーが発生し、Apexからも参照できないことが確認できます。
今度は管理パッケージ内のサービスクラスを用いて、デプロイとレコード取得をしてみましょう。
下記のApexコードを匿名実行してみます。
SuzukiExample.ProtectedCustomMetadata customMeta
= new SuzukiExample.ProtectedCustomMetadata('TestCustomMeta', 'TestCustomMeta', 'TestField');
SuzukiExample.CustomMetadataService service = new SuzukiExample.CustomMetadataService();
service.deploy(customMeta);その後、「リリース状況」からメタデータのデプロイが完了したことを確認し、下記のApexコードを匿名実行します。
SuzukiExample.CustomMetadataService service = new SuzukiExample.CustomMetadataService(); System.debug(service.getAll());
管理パッケージから提供されたApexクラスでレコードの取得ができました!
このように同じ管理パッケージ内のApexコードを用いて、インストール先組織で実装したApexコードから保護されたカスタムメタデータを参照したり、専用のVisualforce画面を開発して、一部の項目のみユーザに入力してもらったりすることができます。
テストクラスについて
保護されたメタデータのデプロイ処理を提供する場合、テストクラスの作成に注意が必要です。 テストクラスでは実際にメタデータのデプロイすることはできません。 そのため、テストクラスでは
- デプロイ予定のコンポーネントのチェック
- デプロイ後のコールバックのテスト
保護されたカスタム設定の利用
今回は、セキュアなデータの保管場所として保護されたカスタムメタデータをご紹介しました。
しかし、一方で カスタム設定 もパッケージの機密情報を保持する目的で利用できます。
カスタムメタデータと同じように、カスタム設定も保護することが可能です。
両者の使い分けポイントとしては、下記が挙げられます。
| カスタム設定 | 組織レベル、プロファイルごと、ユーザごとの設定が可能。 |
| カスタムメタデータ | レコード単位で設定の管理が可能。 |
最後に
いかがだったでしょうか。
保護されたカスタムメタデータはセキュアな分、扱いの難しい機能でもあります。
しかし、パッケージを提供するうえで大切な機能の一つですので、ぜひ利用してみてください!
https://help.salesforce.com/articleView?id=custommetadatatypes_limitations.htm&type=5
https://help.salesforce.com/articleView?id=custommetadatatypes_protection.htm&type=5
https://help.salesforce.com/articleView?id=custommetadatatypes_package_access.htm&type=5
https://help.salesforce.com/articleView?id=custommetadatatypes_relationships_limits.htm&type=5


ポスト

