Loading

Accès à l’objet de contenu par des fonctions à l’aide du partage programmatique sur ContentDocumentLink

Date de publication: Oct 13, 2022
Description

Terminologie

ContentDocument : Représente un document qui a été chargé dans une bibliothèque dans Salesforce CRM Content ou Salesforce Files.

ContentVersion : Représente une version spécifique d’un document dans Salesforce CRM Content ou Salesforce Files. Un ContentDocument peut avoir plusieurs ContentVersion.

ContentDocumentLink :
Représente le lien entre un document Salesforce CRM Content ou un fichier Salesforce et l’endroit où il est partagé. Un fichier peut être partagé avec d’autres utilisateurs, groupes, enregistrements et bibliothèques Salesforce CRM Content.
 

Création d’un lien de document et accès au contenu

Deux types d’accès au contenu sont possibles :
  1. Fonction qui accède à son contenu
  2. Fonction qui accède au contenu d’un autre utilisateur
Lorsqu’une fonction crée un contenu, l’utilisateur de l’intégration Cloud est propriétaire du contenu et par conséquent, les fonctions peuvent y accéder. Il s’agit du scénario le plus simple et le scénario le plus courant est quand le contenu existe déjà et doit être accessible à une fonction.
 

Fonction qui accède à son contenu

Une fonction peut créer un contenu et l’insérer à l’aide du point de terminaison de l’API REST dans :
services/data/vXX.X/sobjects/ContentVersion

Ceci rend automatiquement l’utilisateur de l’intégration Cloud propriétaire du contenu et autorise la fonction (ainsi que d’autres utilisateurs) à accéder à ce contenu. Les liens de document sont insérés automatiquement donc aucune étape supplémentaire n’est nécessaire.

Fonction qui accède au contenu d’un autre utilisateur

Nous devons créer un enregistrement dans ContentDocumentLink qui lie le contenu avec l’utilisateur avec lequel il est partagé. Dans ce cas, l’utilisateur est l’utilisateur de l’intégration Cloud. Cela peut se faire via Apex une fois que le contenu est créé ou via DataLoader une fois que le contenu est chargé.

Voici un exemple de code Apex utilisé pour créer un contenu (enregistrement ContentVersion) et le lier à ContentDocumentLink (enregistrement ContentDocumentLink).
 
//Create Document
//Note: This example creates the content in Apex
//We could also load content via Data Loader.
ContentVersion cv = new ContentVersion();
cv.Title = 'Test Document';
cv.PathOnClient = 'TestDocument.pdf';
cv.VersionData = Blob.valueOf('Test Content');
cv.IsMajorVersion = true;
Insert cv;
 
//Get Content Documents
Id conDocId = [SELECT ContentDocumentId FROM ContentVersion WHERE Id =:cv.Id].ContentDocumentId;
 
//Create ContentDocumentLink 
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = conDocId;
//Label would contain the user id of the cloud integration user (obtained separately)
cdl.LinkedEntityId = Label.Platform_User_Id;
//V - Viewer permission. C - Collaborator permission. I - Inferred permission
cdl.ShareType = 'V';
Insert cdl;

Ici, ContentDocumentId est obtenu de ContentVersion (la version du document créé précédemment - non présentée ici)

LinkedEntityId se réfère à l’ID de l’utilisateur de l’intégration Cloud. Il doit être obtenu au préalable et transmis à ce code, ou être accessible à partir de ce code comme variable globale (ou via le cache de la plate-forme).

Une fois que nous avons créé une entrée dans ContentDocumentLink (comme précédemment), une fonction peut accéder au contenu normalement via le SDK.

Obtention de l’ID de l’utilisateur de l’intégration Cloud
Étant donné que l’utilisateur de l’intégration Cloud n’est pas exposé dans Salesforce comme les autres utilisateurs, l’ID de cet utilisateur peut être obtenu de l’une des manières suivantes :

1. Nous pouvons interroger l’objet Utilisateur et trouver le nom d’utilisateur pour CloudIntegrationUser.Le nom de l’utilisateur de l’intégration Cloud est cloud@ + ID de l’organisation à 18 caractères en minuscules. Voir la requête SOQL ci-dessous 
SELECT Id, UserName from User WHERE username like 'cloud@00d%'

2. Par une insertion d’un enregistrement par la fonction. L’ID de l’utilisateur qui a inséré cet enregistrement sera celui de l’utilisateur de l’intégration Cloud.

Une fois l’ID obtenu, il peut être stocké pour être utilisé par le code Apex indiqué précédemment.
Le code ci-dessous contient une fonction qui accède à un document de contenu spécifique après l’établissement du partage comme indiqué plus haut.
// Purposefully selecting another file NOT owned by the platform integration user
// (Hardcoded platform integration user Id - to be replaced with a more dynamic ID 
// merge in the query)
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;
}

// File Id for download
logger.info("contId: " + JSON.parse(JSON.stringify(contId)));

// Print
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);    
}

Remarque 1

Le code tente d’accéder au contenu créé par un utilisateur autre que l’utilisateur de l’intégration Cloud. Si le contenu a été partagé de façon correcte dans ContentDocumentLink (comme indiqué précédemment), cette fonction peut accéder au contenu.

Remarque 2

Si le code de fonction doit accéder au contenu créé par l’utilisateur de l’intégration Cloud, il n’est pas nécessaire de le partager via ContentDocumentLink (car il a été créé automatiquement). L’accès au contenu ne présente aucune difficulté dans ce cas.

Création d’un lien de document automatisée

Il est possible d’automatiser la création des enregistrements de liens de document lorsqu’un contenu est créé. L’exemple ci-dessous explique comment procéder.

Exemple de code déclencheur

Le code ci-dessous est le déclencheur qui crée un enregistrement ContentDocumentLink lorsqu’un enregistrement ContentVersion est créé (exige le Platform_User_Id de l’exemple précédent qui est nécessaire pour la création du lien de document).
 
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);
    }
}
 

Considérations et risques

  • Une fois qu’un lien de document de contenu est partagé, il est accessible à toutes les fonctions. Pour empêcher l’accès au document dans le futur, le partage doit être explicitement annulé dans ContentDocumentLink. Cette approche donne accès au document à la totalité des fonctions ou à aucune car toutes les fonctions sont exécutées comme utilisateur d’intégration Cloud
  • L’ID de l’utilisateur de l’intégration Cloud doit être obtenu manuellement et injecté dans le déclencheur Apex. Pour cela, l’ID doit être stocké dans un paramètre, objet ou étiquette personnalisé. Ou il peut être stocké et accessible du cache de la plate-forme. De plus, l’ID de l’utilisateur peut changer après une migration d’organisation et exiger la recréation des partages avec le nouvel ID.
  • Les documents doivent être partagés individuellement en créant un partage d’enregistrement pour chaque document. Cela peut entraîner des problèmes d’évolutivité lorsque nous gérons un grand nombre de documents.
Numéro d’article de la base de connaissances

000393095

 
Chargement
Salesforce Help | Article