Loading
Salesforce から送信されるメールは、承認済ドメインからのみとなります続きを読む

ContentDocumentLink のプログラム共有を使用した関数によるコンテンツオブジェクトへのアクセス

公開日: Oct 13, 2022
説明

用語

コンテンツドキュメント:Salesforce CRM Content または Salesforce Files のライブラリにアップロードされたドキュメントを表します。

コンテンツバージョン:Salesforce CRM Content または Salesforce Files にあるドキュメントの特定のバージョンを表します。1 つのコンテンツドキュメントに複数のコンテンツバージョンがある場合があります。

コンテンツドキュメントリンク:
Salesforce CRM Content ドキュメントまたは Salesforce ファイルと、その共有場所の間のリンクを表します。ファイルは他のユーザー、グループ、レコード、Salesforce CRM Content ライブラリと共有できます。
 

ドキュメントリンクの作成とコンテンツアクセス

2 種類のコンテンツアクセスが可能です。
  1. 自身のコンテンツにアクセスする関数
  2. 他のユーザーのコンテンツにアクセスする関数
関数によって新しいコンテンツが作成されると、クラウドインテグレーションユーザーがそのコンテンツを所有するため、関数を使用してそのコンテンツにアクセスできます。これは単純なシナリオです。より一般的なのは、コンテンツがすでに存在し、関数によってアクセスする必要があるというシナリオです。
 

自身のコンテンツにアクセスする関数

関数によってコンテンツを作成し、REST API エンドポイントを使用して次の場所にそのコンテンツを挿入できます。
services/data/vXX.X/sobjects/ContentVersion

この操作により、クラウドインテグレーションユーザーが自動的にコンテンツの所有者になり、関数 (および他のユーザー) がこのコンテンツにアクセスできるようになります。ドキュメントリンクは自動的に挿入されるため、他の手順は必要ありません。

他のユーザーのコンテンツにアクセスする関数

コンテンツと共有先のユーザーとをリンクするレコードを ContentDocumentLink に作成する必要があります。この場合、ユーザーはクラウドインテグレーションユーザーです。この操作はコンテンツの作成後に Apex を使用して、またはコンテンツのアップロード後にデータローダを使用して行います。

以下は、コンテンツ (ContentVersion レコード) を作成し、それを ContentDocumentLink (ContentDocumentLink レコード) にリンクするために使用する Apex コードの例です。
 
//ドキュメントを生成します。
//メモ:この例では Apex でコンテンツを作成します
//データローダを使用してコンテンツをロードすることもできます。
ContentVersion cv = new ContentVersion();
cv.Title = 'Test Document';
cv.PathOnClient = 'TestDocument.pdf';
cv.VersionData = Blob.valueOf('Test Content');
cv.IsMajorVersion = true;
Insert cv;
 
//コンテンツドキュメントを取得します。
Id conDocId = [SELECT ContentDocumentId FROM ContentVersion WHERE Id =:cv.Id].ContentDocumentId;
 
//ContentDocumentLink を作成します。 
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = conDocId;
//ラベルにはクラウドインテグレーションユーザーのユーザー ID (別途取得) が含まれます。
cdl.LinkedEntityId = Label.Platform_User_Id;
//V - 閲覧者権限。C - コラボレータ権限。I - 推定される権限
cdl.ShareType = 'V';
Insert cdl;

ここで、ContentDocumentId は ContentVersion (以前に作成されたドキュメントのバージョン。ここには表示されていません) から取得されます。

LinkedEntityId は、クラウドインテグレーションユーザー ID を参照します。これは事前に取得してこのコードに渡すか、グローバル変数として (またはプラットフォームキャッシュ経由で) このコードからアクセスできるようにする必要があります。

ContentDocumentLink にエントリを作成 (上の説明のとおり) すると、関数は SDK を介して通常どおりコンテンツにアクセスできるようになります。

クラウドインテグレーションユーザー ID の取得
クラウドインテグレーションユーザーは、他のユーザーとは異なり Salesforce に公開されないため、このユーザーの ID は次のいずれかの方法で取得します。

1.ユーザーオブジェクトをクエリすると CloudIntegrationUser のユーザー名を特定できます。クラウドインテグレーションユーザー名は cloud@ + 小文字 18 文字の orgId です。次の SOQL クエリを参照してください。 
SELECT Id, UserName from User WHERE username like 'cloud@00d%'

2.関数を使用してレコードを挿入します。このレコードを挿入したユーザーの ID は、クラウドインテグレーションユーザーの ID となります。

ID を取得したら、保存して上の Apex コードで使用できます。
次のコードは、上で示したように共有が確立された後、特定のコンテンツドキュメントにアクセスする関数を示しています。
// プラットフォームインテグレーションユーザーが所有していない別のファイルを意図的に選択します
// (ハードコード化されたプラットフォームインテグレーションユーザー ID。より動的な ID に置き換えられます 
// クエリでマージします)
let contentQuery = "SELECT Id 
                    FROM ContentVersion 
                    WHERE OwnerId != '0055f0000057ROYAA2' 
                    ORDER BY CreatedDate DESC LIMIT 1";
let queryResults = await context.org.dataApi.query(contentQuery);
let contId = "";
for (const downItem of queryResults.records) {
    contId = downItem.fields["Id"];
    break;
}

// ダウンロード用のファイル ID
logger.info("contId: " + JSON.parse(JSON.stringify(contId)));

// 印刷
logger.info("DOWNLOAD LATEST FILE NOT OWNED BY FUNCTIONS USER");

await request
    .get(
        context.org.baseUrl +
        "/services/data/v54.0/sobjects/ContentVersion/" +
        contId +
        "/VersionData"
    )
    .auth(null, null, true, context.org.dataApi.accessToken)
    .on("error", function (err) {
        logger.info("Exception: " + err);
    })
    .pipe(
        fs.createWriteStream("./tempFiles/downFile.csv", { encoding: "utf8" })
    )
    .on("finish", doSomethingAfterDownload);    
}

注意 1

このコードは、クラウドインテグレーションユーザー以外のユーザーが作成したコンテンツに意図的にアクセスを試みます。前述のように、コンテンツが ContentDocumentLink で正常に共有された場合、この関数はコンテンツへのアクセスに成功します。

注意 2

関数コードがクラウドインテグレーションユーザーの作成したコンテンツにアクセスする場合、ContentDocumentLink を通じてコンテンツを共有する必要はありません (ContentDocumentLink は自動的に作成されるため)。この場合、コンテンツへのアクセスは容易になります。

ドキュメントリンクの自動作成

新しいコンテンツが作成されるときに行われるドキュメントリンクレコードの作成を自動化できます。その方法の例を示します。

サンプルトリガーコード

以下のコードは、ContentVersion レコードの作成時に ContentDocumentLink レコードを作成するトリガーです (ドキュメントリンクの作成に必要となるため、前の例の Platform_User_Id が必要です)。
 
trigger ContentVersionTrigger on ContentVersion (after insert) {
    ContentVersionTriggerHelper.triggerHelper(
        Trigger.operationType,
        Trigger.new,
        Trigger.oldMap);
}
public with sharing class ContentVersionTriggerHelper {
    public static void triggerHelper(
        System.TriggerOperation operationType,
        List<ContentVersion> newList,
        Map<Id, ContentVersion> oldMap
    ) {
        switch on operationType {
            when AFTER_INSERT{
                List<ContentVersion> docsToProcess = getDocsToShare(newList);
                if(!docsToProcess.isEmpty()){
                    shareWithIntegrationUser(docsToProcess);
                }
            }
        }
    }

    public static List<ContentVersion> getDocsToShare(List<ContentVersion> allDocuments){
        List<ContentVersion> docsToProcess = new List<ContentVersion>();
        for(ContentVersion cVer : allDocuments){
            if(cDoc.OwnerId != Label.Platform_User_Id){
                docsToProcess.add(cVer);
            }
        }
        return docsToProcess;
    } 

    public static void shareWithIntegrationUser(List<ContentVersion> documents){
        List<ContentDocumentLink> shareLinks = new List<ContentDocumentLink>();
        for(ContentVersion cVer : documents){
            ContentDocumentLink cdl = new ContentDocumentLink();
            cdl.ContentDocumentId = cVer.ContentDocumentId;
            cdl.LinkedEntityId = Label.Platform_User_Id;
            cdl.ShareType = 'V';
            shareLinks.add(cdl);
        }
        Database.insert(shareLinks,false);
    }
}
 

考慮事項とリスク

  • コンテンツのドキュメントリンクが共有されると、どの関数からもアクセスできるようになります。今後そのドキュメントにアクセスできないようにするには、ContentDocumentLink からドキュメントの共有を明示的に解除する必要があります。この方法ではすべての関数でドキュメントにアクセスできるか、またはどの関数でもアクセスできなくなります。すべての関数はクラウドインテグレーションユーザーとして実行されるためです。
  • クラウドインテグレーションユーザーのユーザー ID を手動で取得し、Apex トリガーに挿入する必要があります。そのためにはカスタム設定、オブジェクト、またはラベルに ID を保存する必要があります。または、プラットフォームキャッシュに保存してアクセスすることもできます。また、組織の移行後にはユーザー ID が変わる可能性があり、その場合は新しい ID で共有を再作成する必要があります。
  • ドキュメントはドキュメントごとにレコード共有を作成して個別に共有する必要があります。その際、大量のドキュメントを処理する場合は拡張性の問題が発生する可能性があります。
ナレッジ記事番号

000393095

 
読み込み中
Salesforce Help | Article