Loading

Accesso all'oggetto Contenuto da parte delle funzioni utilizzando la condivisione programmatica in ContentDocumentLink

Data pubblicazione: Oct 13, 2022
Descrizione

Terminologia

Documento contenuto: rappresenta un documento che è stato caricato in una libreria in Salesforce CRM Content o Salesforce Files.

Versione contenuto: rappresenta una versione specifica di un documento in Salesforce CRM Content o Salesforce Files. Un documento contenuto può avere più versioni di contenuto.

Link al documento contenuto:
Rappresenta il collegamento tra un documento di Salesforce CRM Content o Salesforce Files e indica dove è condiviso. Un file può essere condiviso con altri utenti, gruppi, record e librerie di Salesforce CRM Content.
 

Creazione del collegamento al documento e accesso al contenuto

Sono possibili due tipi di accesso al contenuto:
  1. Funzione che accede al proprio contenuto
  2. Funzione che accede al contenuto di un altro utente
Quando una funzione crea un nuovo contenuto, l'utente integrazione Cloud sarà proprietario del contenuto, in modo che le funzioni possano accedervi. Questo è lo scenario più semplice, mentre lo scenario più comune è quello in cui il contenuto esiste già e deve essere accessibile da una funzione.
 

Funzione che accede al proprio contenuto

Una funzione può creare un contenuto e inserirlo utilizzando l'endpoint API REST in:
services/data/vXX.X/sobjects/ContentVersion

Ciò renderà automaticamente l'utente integrazione Cloud proprietario del contenuto e consentirà alla funzione (e agli altri utenti) di accedervi. I link ai documenti vengono inseriti automaticamente, quindi non sono necessari passaggi aggiuntivi.

Funzione che accede al contenuto di un altro utente

Occorre creare un record in ContentDocumentLink che colleghi il contenuto con l'utente con cui viene condiviso. In questo caso, sarà l'utente integrazione Cloud. Si può eseguire questa operazione tramite Apex, dopo la creazione del contenuto, oppure tramite DataLoader, dopo il caricamento del contenuto.

Di seguito è riportato un esempio di codice Apex che viene utilizzato per creare contenuti (ossia il record ContentVersion) e collegarlo a ContentDocumentLink (ossia il record ContentDocumentLink).
 
//Creare il documento
//Nota: in questo esempio, il contenuto viene creato in Apex
//In alternativa, è possibile caricare il contenuto tramite 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;
 
//Ottenere i documenti contenuto
Id conDocId = [SELECT ContentDocumentId FROM ContentVersion WHERE Id =:cv.Id].ContentDocumentId;
 
//Creare ContentDocumentLink 
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = conDocId;
//L'etichetta contiene l'ID utente dell'utente integrazione Cloud (ottenuta separatamente)
cdl.LinkedEntityId = Label.Platform_User_Id;
//V - Autorizzazione Visualizzatore. C - Autorizzazione Collaboratore. I - Autorizzazione implicita
cdl.ShareType = 'V';
Insert cdl;

In questo caso ContentDocumentId si ottiene da ContentVersion (la versione del documento che è stata creata in precedenza, non mostrata qui)

LinkedEntityId si riferisce all'ID dell'utente integrazione Cloud. L'ID deve essere ottenuto in anticipo e passato in questo codice, o essere accessibile da questo codice come variabile globale (o tramite la cache della piattaforma).

Una volta creata una voce in ContentDocumentLink (come sopra), una funzione sarà in grado di accedere al contenuto normalmente tramite l'SDK.

Come ottenere l'ID dell'utente integrazione Cloud
Poiché l'utente integrazione cloud non è visualizzato in Salesforce come gli altri utenti, per ottenere l'ID di questo utente si può procedere in uno dei seguenti modi:

1. È possibile interrogare l'oggetto Utente e scoprire il nome utente per CloudIntegrationUser.Il nome dell'utente integrazione Cloud è cloud@ + orgId di 18 caratteri in minuscolo. Vedere la query SOQL seguente 
SELECT Id, UserName from User WHERE username like 'cloud@00d%'

2. Tramite l'inserimento di un record da parte della funzione. L'ID dell'utente che ha inserito questo record sarà quello dell'utente integrazione Cloud.

Una volta ottenuto l'ID, lo si può memorizzare per il successivo utilizzo da parte del codice Apex di cui sopra.
Il seguente codice mostra una funzione che accede a un documento contenuto specifico dopo che è stata stabilita la condivisione, come mostrato sopra.
// Selezione intenzionale di un altro file NON di proprietà dell'utente integrazione piattaforma
// (Id dell'utente integrazione piattaforma hardcoded, da sostituire con un ID più dinamico 
// unire nella 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;
}

// ID file per il download
logger.info("contId: " + JSON.parse(JSON.stringify(contId)));

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

Nota 1

Il codice tenta intenzionalmente di accedere al contenuto creato da un utente diverso dall'utente integrazione Cloud. Se il contenuto è stato condiviso con successo in ContentDocumentLink (come mostrato in precedenza), questa funzione riuscirà ad accedere al contenuto.

Nota 2

Se il codice funzione dovesse accedere al contenuto creato dall'utente integrazione Cloud, non sarebbe necessario condividerlo tramite ContentDocumentLink (perché sarebbe stato creato automaticamente). In questo caso, accedere al contenuto sarebbe semplice.

Creazione automatica del link al documento

È possibile automatizzare la creazione dei record dei link ai documenti ogni volta che viene creato un nuovo contenuto. Il seguente esempio mostra come procedere.

Esempio di codice trigger

Il seguente codice è il trigger che crea un record ContentDocumentLink quando viene creato un record ContentVersion (richiede Platform_User_Id dell'esempio precedente, necessario per la creazione del link al documento).
 
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);
    }
}
 

Considerazioni e rischi

  • Una volta che un collegamento a un documento di contenuto è condiviso, è possibile accedervi da qualsiasi funzione. Per impedire l'accesso al documento in futuro, la condivisione deve essere esplicitamente annullata da ContentDocumentLink. Questo approccio consente l'accesso al documento a tutte le funzioni o a nessuna, perché tutte le funzioni vengono eseguite come utente integrazione Cloud
  • L'ID utente dell'utente integrazione Cloud deve essere ottenuto manualmente e iniettato nel trigger Apex. Pertanto, è necessario memorizzare l'ID in un'impostazione, un oggetto o un'etichetta personalizzati. Oppure, è possibile memorizzarlo e accedervi dalla cache della piattaforma. Inoltre, l'ID utente potrebbe cambiare dopo una migrazione dell'organizzazione; in questo caso, sarà necessario ripetere le condivisioni con il nuovo ID.
  • I documenti devono essere condivisi individualmente, creando una condivisione del record per ogni documento. Ciò potrebbe creare problemi di scalabilità, in caso si debba gestire un gran numero di documenti.
Numero articolo Knowledge

000393095

 
Caricamento
Salesforce Help | Article