7-6-17. 16.1パッケージ導入後、データテーブルの行コピーを使用すると保存時に権限エラーメッセージが表示され、保存に失敗する

本事象はV17.0 (AppExchangeパッケージバージョン17.1) で解消されました。

・2021/12/12(日)にリリースされたAppExchangeパッケージ16.1をSalesforce組織に導入後、

 データテーブルの行コピーを実行するとレコード保存時に権限エラーメッセージが発生し、保存に失敗する場合があります。

・近日中のバージョンアップにて対処予定となります。


発生条件

 下記条件を満たした場合に発生します。

  ①対象ページで行コピー機能が有効化されたデータテーブルを使用している

   (検索テンプレートにおける検索結果テーブルも同様です)

  ②対象ページ利用ユーザには編集権限がない項目(数式項目など)をデータテーブル列に配置している

  ③対象Salesforce組織にはバージョン16.1のSkyVisualEditor VFパッケージが導入されている

  ④対象データテーブルで行コピーを実施し、レコード保存する



回避策

 ・データテーブルの行コピー機能を一時的に無効化いただき、行追加ボタンからレコード保存することで、運用回避いただけます。

 ・対象ページにおいて行コピー機能が有効なデータテーブルが一つである場合、

  下記コードをApexクラス拡張機能で設定することで、事象を回避いただけます。


※下記内容はご利用ページの設定に置き換えください。
  ページ名: SVE_pagename
  Apex拡張機能クラス名: SVE_pagenameExtender
  データテーブルのID: datatableId
  データテーブルの関連オブジェクトAPI参照名: TestSObject01__c
Apex拡張機能クラス
global with sharing class SVE_pagenameExtender extends SkyEditor2.Extender{
    SVE_pagename.datatableId table;
    public SVE_pagename extension {get;set;} 
    public SVE_pagenameExtender(SVE_pagename extension){
        this.extension = extension;
        this.table = extension.datatableId;
    }

    Integer getRecordIndex(SObject r) {
        for (Integer i = 0; i < table.records.size(); i++) {
            if (table.records[i] === r) {
                 return i;
            }
        }
        throw new NullPointerException();
    }

    global override void afterClone(SObject obj) {
        Integer i = getRecordIndex(obj);
        SObjectAccessDecision insertSecurityDecision = Security.stripInaccessible(AccessType.CREATABLE, new List<SObject>{obj});
        obj = insertSecurityDecision.getRecords()[0];

        table.remove(i);
        if(i == table.records.size()){
            table.add(obj);
        } else {
            table.records.add(i, obj);
            table.items.add(i, (SVE_pagename.datatableIdItem) table.create(obj));
        }
    }
}
Apex拡張機能テストクラス
@isTest
private class SVE_pagenameExtenderTest{
    @isTest
    static void test() {
        TestSObject01__c record = new TestSObject01__c();
        ApexPages.StandardController controller = new ApexPages.StandardController(record);
        SVE_pagename extension = new SVE_pagename(controller);
        extension.datatableId.add();
        extension.datatableId.add();
        extension.datatableId.items[0].selected = true;
        extension.datatableId.items[1].selected = true;
        extension.datatableId.cloneRows();
        System.assertEquals(extension.datatableId.items.size(), 4);
        System.assertEquals(extension.datatableId.records.size(), 4);
    }
}